cowork-os 0.3.21 → 0.3.25
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 +372 -10
- package/connectors/README.md +20 -0
- package/connectors/asana-mcp/README.md +24 -0
- package/connectors/asana-mcp/dist/index.js +427 -0
- package/connectors/asana-mcp/package.json +15 -0
- package/connectors/asana-mcp/src/index.ts +553 -0
- package/connectors/asana-mcp/tsconfig.json +13 -0
- package/connectors/hubspot-mcp/README.md +35 -0
- package/connectors/hubspot-mcp/dist/index.js +454 -0
- package/connectors/hubspot-mcp/package.json +15 -0
- package/connectors/hubspot-mcp/src/index.ts +562 -0
- package/connectors/hubspot-mcp/tsconfig.json +13 -0
- package/connectors/jira-mcp/README.md +49 -0
- package/connectors/jira-mcp/dist/index.js +588 -0
- package/connectors/jira-mcp/package.json +15 -0
- package/connectors/jira-mcp/src/index.ts +711 -0
- package/connectors/jira-mcp/tsconfig.json +13 -0
- package/connectors/linear-mcp/README.md +22 -0
- package/connectors/linear-mcp/dist/index.js +402 -0
- package/connectors/linear-mcp/package.json +15 -0
- package/connectors/linear-mcp/src/index.ts +522 -0
- package/connectors/linear-mcp/tsconfig.json +13 -0
- package/connectors/okta-mcp/README.md +24 -0
- package/connectors/okta-mcp/dist/index.js +411 -0
- package/connectors/okta-mcp/package.json +15 -0
- package/connectors/okta-mcp/src/index.ts +520 -0
- package/connectors/okta-mcp/tsconfig.json +13 -0
- package/connectors/salesforce-mcp/README.md +47 -0
- package/connectors/salesforce-mcp/dist/index.js +584 -0
- package/connectors/salesforce-mcp/package.json +15 -0
- package/connectors/salesforce-mcp/src/index.ts +722 -0
- package/connectors/salesforce-mcp/tsconfig.json +13 -0
- package/connectors/servicenow-mcp/README.md +26 -0
- package/connectors/servicenow-mcp/dist/index.js +400 -0
- package/connectors/servicenow-mcp/package.json +15 -0
- package/connectors/servicenow-mcp/src/index.ts +500 -0
- package/connectors/servicenow-mcp/tsconfig.json +13 -0
- package/connectors/templates/mcp-connector/README.md +31 -0
- package/connectors/templates/mcp-connector/package.json +15 -0
- package/connectors/templates/mcp-connector/src/index.ts +330 -0
- package/connectors/templates/mcp-connector/tsconfig.json +13 -0
- package/connectors/zendesk-mcp/README.md +40 -0
- package/connectors/zendesk-mcp/dist/index.js +431 -0
- package/connectors/zendesk-mcp/package.json +15 -0
- package/connectors/zendesk-mcp/src/index.ts +543 -0
- package/connectors/zendesk-mcp/tsconfig.json +13 -0
- package/dist/electron/electron/agent/custom-skill-loader.js +31 -1
- package/dist/electron/electron/agent/daemon.js +189 -13
- package/dist/electron/electron/agent/executor.js +895 -78
- package/dist/electron/electron/agent/llm/anthropic-compatible-provider.js +177 -0
- package/dist/electron/electron/agent/llm/azure-openai-provider.js +328 -0
- package/dist/electron/electron/agent/llm/bedrock-provider.js +49 -9
- package/dist/electron/electron/agent/llm/github-copilot-provider.js +97 -0
- package/dist/electron/electron/agent/llm/groq-provider.js +33 -0
- package/dist/electron/electron/agent/llm/index.js +13 -1
- package/dist/electron/electron/agent/llm/kimi-provider.js +33 -0
- package/dist/electron/electron/agent/llm/openai-compatible-provider.js +116 -0
- package/dist/electron/electron/agent/llm/openai-compatible.js +111 -0
- package/dist/electron/electron/agent/llm/openai-oauth.js +2 -1
- package/dist/electron/electron/agent/llm/openrouter-provider.js +1 -1
- package/dist/electron/electron/agent/llm/provider-factory.js +350 -4
- package/dist/electron/electron/agent/llm/types.js +66 -1
- package/dist/electron/electron/agent/llm/xai-provider.js +33 -0
- package/dist/electron/electron/agent/search/provider-factory.js +38 -2
- package/dist/electron/electron/agent/tools/box-tools.js +231 -0
- package/dist/electron/electron/agent/tools/builtin-settings.js +28 -0
- package/dist/electron/electron/agent/tools/dropbox-tools.js +237 -0
- package/dist/electron/electron/agent/tools/file-tools.js +66 -3
- package/dist/electron/electron/agent/tools/google-drive-tools.js +227 -0
- package/dist/electron/electron/agent/tools/grep-tools.js +90 -10
- package/dist/electron/electron/agent/tools/image-tools.js +11 -1
- package/dist/electron/electron/agent/tools/notion-tools.js +312 -0
- package/dist/electron/electron/agent/tools/onedrive-tools.js +217 -0
- package/dist/electron/electron/agent/tools/registry.js +548 -10
- package/dist/electron/electron/agent/tools/search-tools.js +28 -10
- package/dist/electron/electron/agent/tools/sharepoint-tools.js +243 -0
- package/dist/electron/electron/agent/tools/shell-tools.js +12 -3
- package/dist/electron/electron/agent/tools/x-tools.js +1 -1
- package/dist/electron/electron/agents/agent-dispatch.js +63 -0
- package/dist/electron/electron/database/repositories.js +19 -5
- package/dist/electron/electron/database/schema.js +8 -0
- package/dist/electron/electron/gateway/channels/whatsapp.js +55 -0
- package/dist/electron/electron/gateway/index.js +75 -1
- package/dist/electron/electron/gateway/router.js +209 -154
- package/dist/electron/electron/ipc/canvas-handlers.js +5 -0
- package/dist/electron/electron/ipc/handlers.js +763 -267
- package/dist/electron/electron/main.js +63 -0
- package/dist/electron/electron/mcp/oauth/connector-oauth.js +333 -0
- package/dist/electron/electron/mcp/registry/MCPRegistryManager.js +503 -154
- package/dist/electron/electron/memory/MemoryService.js +2 -1
- package/dist/electron/electron/preload.js +78 -1
- package/dist/electron/electron/settings/appearance-manager.js +18 -1
- package/dist/electron/electron/settings/box-manager.js +54 -0
- package/dist/electron/electron/settings/dropbox-manager.js +54 -0
- package/dist/electron/electron/settings/google-drive-manager.js +54 -0
- package/dist/electron/electron/settings/notion-manager.js +56 -0
- package/dist/electron/electron/settings/onedrive-manager.js +54 -0
- package/dist/electron/electron/settings/sharepoint-manager.js +54 -0
- package/dist/electron/electron/utils/box-api.js +153 -0
- package/dist/electron/electron/utils/dropbox-api.js +144 -0
- package/dist/electron/electron/utils/env-migration.js +19 -0
- package/dist/electron/electron/utils/google-drive-api.js +152 -0
- package/dist/electron/electron/utils/notion-api.js +103 -0
- package/dist/electron/electron/utils/onedrive-api.js +113 -0
- package/dist/electron/electron/utils/sharepoint-api.js +109 -0
- package/dist/electron/electron/utils/validation.js +98 -3
- package/dist/electron/electron/utils/x-cli.js +1 -1
- package/dist/electron/shared/channelMessages.js +284 -3
- package/dist/electron/shared/llm-provider-catalog.js +198 -0
- package/dist/electron/shared/types.js +90 -1
- package/package.json +14 -3
- package/resources/skills/nano-banana-pro.json +4 -4
- package/resources/skills/openai-image-gen.json +3 -3
- package/resources/skills/scripts/gen.py +163 -0
- package/resources/skills/scripts/generate_image.py +91 -0
- package/src/electron/agent/custom-skill-loader.ts +34 -1
- package/src/electron/agent/daemon.ts +210 -14
- package/src/electron/agent/executor.ts +1124 -85
- package/src/electron/agent/llm/anthropic-compatible-provider.ts +214 -0
- package/src/electron/agent/llm/azure-openai-provider.ts +388 -0
- package/src/electron/agent/llm/bedrock-provider.ts +62 -9
- package/src/electron/agent/llm/github-copilot-provider.ts +117 -0
- package/src/electron/agent/llm/groq-provider.ts +39 -0
- package/src/electron/agent/llm/index.ts +6 -0
- package/src/electron/agent/llm/kimi-provider.ts +39 -0
- package/src/electron/agent/llm/openai-compatible-provider.ts +153 -0
- package/src/electron/agent/llm/openai-compatible.ts +133 -0
- package/src/electron/agent/llm/openai-oauth.ts +2 -1
- package/src/electron/agent/llm/openrouter-provider.ts +2 -1
- package/src/electron/agent/llm/provider-factory.ts +459 -6
- package/src/electron/agent/llm/types.ts +95 -1
- package/src/electron/agent/llm/xai-provider.ts +39 -0
- package/src/electron/agent/search/provider-factory.ts +43 -2
- package/src/electron/agent/tools/box-tools.ts +239 -0
- package/src/electron/agent/tools/builtin-settings.ts +36 -0
- package/src/electron/agent/tools/dropbox-tools.ts +237 -0
- package/src/electron/agent/tools/file-tools.ts +66 -3
- package/src/electron/agent/tools/gmail-tools.ts +240 -0
- package/src/electron/agent/tools/google-calendar-tools.ts +258 -0
- package/src/electron/agent/tools/google-drive-tools.ts +228 -0
- package/src/electron/agent/tools/grep-tools.ts +97 -12
- package/src/electron/agent/tools/image-tools.ts +11 -1
- package/src/electron/agent/tools/notion-tools.ts +330 -0
- package/src/electron/agent/tools/onedrive-tools.ts +217 -0
- package/src/electron/agent/tools/registry.ts +794 -10
- package/src/electron/agent/tools/search-tools.ts +29 -11
- package/src/electron/agent/tools/sharepoint-tools.ts +247 -0
- package/src/electron/agent/tools/shell-tools.ts +11 -3
- package/src/electron/agent/tools/x-tools.ts +1 -1
- package/src/electron/agents/agent-dispatch.ts +79 -0
- package/src/electron/database/SecureSettingsRepository.ts +7 -1
- package/src/electron/database/repositories.ts +58 -6
- package/src/electron/database/schema.ts +8 -0
- package/src/electron/gateway/channels/discord.ts +4 -0
- package/src/electron/gateway/channels/google-chat.ts +3 -0
- package/src/electron/gateway/channels/line.ts +3 -0
- package/src/electron/gateway/channels/matrix-client.ts +15 -0
- package/src/electron/gateway/channels/matrix.ts +31 -0
- package/src/electron/gateway/channels/mattermost.ts +3 -0
- package/src/electron/gateway/channels/signal.ts +3 -0
- package/src/electron/gateway/channels/slack.ts +9 -4
- package/src/electron/gateway/channels/teams.ts +4 -0
- package/src/electron/gateway/channels/telegram.ts +2 -0
- package/src/electron/gateway/channels/twitch.ts +2 -0
- package/src/electron/gateway/channels/types.ts +8 -0
- package/src/electron/gateway/channels/whatsapp.ts +66 -0
- package/src/electron/gateway/index.ts +95 -2
- package/src/electron/gateway/router.ts +231 -161
- package/src/electron/gateway/security.ts +21 -9
- package/src/electron/ipc/canvas-handlers.ts +10 -0
- package/src/electron/ipc/handlers.ts +848 -292
- package/src/electron/main.ts +35 -0
- package/src/electron/mcp/oauth/connector-oauth.ts +448 -0
- package/src/electron/mcp/registry/MCPRegistryManager.ts +343 -12
- package/src/electron/memory/MemoryService.ts +7 -1
- package/src/electron/preload.ts +200 -5
- package/src/electron/settings/appearance-manager.ts +20 -2
- package/src/electron/settings/box-manager.ts +58 -0
- package/src/electron/settings/dropbox-manager.ts +58 -0
- package/src/electron/settings/google-workspace-manager.ts +59 -0
- package/src/electron/settings/notion-manager.ts +60 -0
- package/src/electron/settings/onedrive-manager.ts +58 -0
- package/src/electron/settings/sharepoint-manager.ts +58 -0
- package/src/electron/utils/box-api.ts +184 -0
- package/src/electron/utils/dropbox-api.ts +171 -0
- package/src/electron/utils/env-migration.ts +22 -0
- package/src/electron/utils/gmail-api.ts +121 -0
- package/src/electron/utils/google-calendar-api.ts +115 -0
- package/src/electron/utils/google-workspace-api.ts +228 -0
- package/src/electron/utils/google-workspace-auth.ts +109 -0
- package/src/electron/utils/google-workspace-oauth.ts +232 -0
- package/src/electron/utils/notion-api.ts +126 -0
- package/src/electron/utils/onedrive-api.ts +137 -0
- package/src/electron/utils/sharepoint-api.ts +132 -0
- package/src/electron/utils/validation.ts +128 -1
- package/src/electron/utils/x-cli.ts +1 -1
- package/src/renderer/App.tsx +119 -8
- package/src/renderer/components/ActivityFeedItem.tsx +34 -17
- package/src/renderer/components/AgentWorkingStatePanel.tsx +7 -5
- package/src/renderer/components/AppearanceSettings.tsx +37 -2
- package/src/renderer/components/BlueBubblesSettings.tsx +18 -7
- package/src/renderer/components/BoxSettings.tsx +203 -0
- package/src/renderer/components/BrowserView.tsx +101 -0
- package/src/renderer/components/BuiltinToolsSettings.tsx +105 -0
- package/src/renderer/components/CanvasPreview.tsx +68 -1
- package/src/renderer/components/ConnectorEnvModal.tsx +116 -0
- package/src/renderer/components/ConnectorSetupModal.tsx +566 -0
- package/src/renderer/components/ConnectorsSettings.tsx +397 -0
- package/src/renderer/components/ControlPlaneSettings.tsx +2 -0
- package/src/renderer/components/DiscordSettings.tsx +18 -7
- package/src/renderer/components/DropboxSettings.tsx +202 -0
- package/src/renderer/components/EmailSettings.tsx +18 -7
- package/src/renderer/components/FileViewer.tsx +21 -13
- package/src/renderer/components/GoogleChatSettings.tsx +17 -7
- package/src/renderer/components/GoogleWorkspaceSettings.tsx +332 -0
- package/src/renderer/components/ImessageSettings.tsx +22 -11
- package/src/renderer/components/LineIcons.tsx +376 -0
- package/src/renderer/components/LineSettings.tsx +18 -7
- package/src/renderer/components/MCPSettings.tsx +56 -0
- package/src/renderer/components/MainContent.tsx +740 -76
- package/src/renderer/components/MatrixSettings.tsx +18 -7
- package/src/renderer/components/MattermostSettings.tsx +18 -7
- package/src/renderer/components/NodesSettings.tsx +58 -99
- package/src/renderer/components/NotificationPanel.tsx +25 -11
- package/src/renderer/components/NotionSettings.tsx +231 -0
- package/src/renderer/components/Onboarding/Onboarding.tsx +13 -1
- package/src/renderer/components/OnboardingModal.tsx +70 -1
- package/src/renderer/components/OneDriveSettings.tsx +212 -0
- package/src/renderer/components/RightPanel.tsx +141 -28
- package/src/renderer/components/ScheduledTasksSettings.tsx +10 -62
- package/src/renderer/components/SearchSettings.tsx +118 -114
- package/src/renderer/components/Settings.tsx +1425 -651
- package/src/renderer/components/SharePointSettings.tsx +224 -0
- package/src/renderer/components/Sidebar.tsx +94 -19
- package/src/renderer/components/SignalSettings.tsx +18 -7
- package/src/renderer/components/SkillHubBrowser.tsx +144 -185
- package/src/renderer/components/SlackSettings.tsx +18 -7
- package/src/renderer/components/TaskQuickActions.tsx +11 -6
- package/src/renderer/components/TaskTimeline.tsx +58 -26
- package/src/renderer/components/TeamsSettings.tsx +18 -7
- package/src/renderer/components/TelegramSettings.tsx +18 -7
- package/src/renderer/components/ThemeIcon.tsx +16 -0
- package/src/renderer/components/TwitchSettings.tsx +18 -7
- package/src/renderer/components/VoiceSettings.tsx +30 -74
- package/src/renderer/components/WhatsAppSettings.tsx +48 -37
- package/src/renderer/components/WorkingStateHistory.tsx +7 -5
- package/src/renderer/components/WorkspaceSelector.tsx +42 -13
- package/src/renderer/hooks/useOnboardingFlow.ts +21 -0
- package/src/renderer/styles/index.css +2333 -209
- package/src/shared/channelMessages.ts +367 -4
- package/src/shared/llm-provider-catalog.ts +217 -0
- package/src/shared/types.ts +251 -2
|
@@ -221,24 +221,9 @@ function formatDuration(ms: number): string {
|
|
|
221
221
|
// Styles
|
|
222
222
|
const styles = {
|
|
223
223
|
container: {
|
|
224
|
-
padding:
|
|
225
|
-
maxWidth: '
|
|
226
|
-
|
|
227
|
-
header: {
|
|
228
|
-
marginBottom: '24px',
|
|
229
|
-
} as React.CSSProperties,
|
|
230
|
-
title: {
|
|
231
|
-
fontSize: '24px',
|
|
232
|
-
fontWeight: 600,
|
|
233
|
-
color: 'var(--color-text-primary)',
|
|
234
|
-
marginBottom: '8px',
|
|
235
|
-
display: 'flex',
|
|
236
|
-
alignItems: 'center',
|
|
237
|
-
gap: '12px',
|
|
238
|
-
} as React.CSSProperties,
|
|
239
|
-
subtitle: {
|
|
240
|
-
fontSize: '14px',
|
|
241
|
-
color: 'var(--color-text-muted)',
|
|
224
|
+
padding: 0,
|
|
225
|
+
maxWidth: '100%',
|
|
226
|
+
width: '100%',
|
|
242
227
|
} as React.CSSProperties,
|
|
243
228
|
statsGrid: {
|
|
244
229
|
display: 'grid',
|
|
@@ -266,21 +251,6 @@ const styles = {
|
|
|
266
251
|
fontWeight: 600,
|
|
267
252
|
color: 'var(--color-text-primary)',
|
|
268
253
|
} as React.CSSProperties,
|
|
269
|
-
addButton: {
|
|
270
|
-
display: 'inline-flex',
|
|
271
|
-
alignItems: 'center',
|
|
272
|
-
gap: '8px',
|
|
273
|
-
padding: '12px 20px',
|
|
274
|
-
backgroundColor: 'var(--color-accent)',
|
|
275
|
-
color: '#000',
|
|
276
|
-
border: 'none',
|
|
277
|
-
borderRadius: 'var(--radius-md)',
|
|
278
|
-
fontSize: '14px',
|
|
279
|
-
fontWeight: 600,
|
|
280
|
-
cursor: 'pointer',
|
|
281
|
-
transition: 'all 0.2s ease',
|
|
282
|
-
marginBottom: '24px',
|
|
283
|
-
} as React.CSSProperties,
|
|
284
254
|
jobCard: {
|
|
285
255
|
backgroundColor: 'var(--color-bg-glass)',
|
|
286
256
|
border: '1px solid var(--color-border-subtle)',
|
|
@@ -517,19 +487,7 @@ export function ScheduledTasksSettings() {
|
|
|
517
487
|
};
|
|
518
488
|
|
|
519
489
|
if (loading) {
|
|
520
|
-
return
|
|
521
|
-
<div style={styles.container}>
|
|
522
|
-
<div style={styles.header}>
|
|
523
|
-
<div style={styles.title}>
|
|
524
|
-
{Icons.clock}
|
|
525
|
-
<span>Scheduled Tasks</span>
|
|
526
|
-
</div>
|
|
527
|
-
</div>
|
|
528
|
-
<div style={{ padding: '40px', textAlign: 'center', color: 'var(--color-text-muted)' }}>
|
|
529
|
-
Loading...
|
|
530
|
-
</div>
|
|
531
|
-
</div>
|
|
532
|
-
);
|
|
490
|
+
return <div className="settings-loading">Loading scheduled tasks...</div>;
|
|
533
491
|
}
|
|
534
492
|
|
|
535
493
|
const lastRunJob = jobs.reduce<CronJob | null>((latest, job) => {
|
|
@@ -540,15 +498,13 @@ export function ScheduledTasksSettings() {
|
|
|
540
498
|
|
|
541
499
|
return (
|
|
542
500
|
<div style={styles.container}>
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
{Icons.clock}
|
|
547
|
-
<span>Scheduled Tasks</span>
|
|
501
|
+
<div className="settings-section">
|
|
502
|
+
<div className="settings-section-header">
|
|
503
|
+
<h3>Scheduled Tasks</h3>
|
|
548
504
|
</div>
|
|
549
|
-
<
|
|
505
|
+
<p className="settings-description">
|
|
550
506
|
Automate tasks to run on a schedule. Results appear in your workspace.
|
|
551
|
-
</
|
|
507
|
+
</p>
|
|
552
508
|
</div>
|
|
553
509
|
|
|
554
510
|
{/* Error Banner */}
|
|
@@ -599,19 +555,11 @@ export function ScheduledTasksSettings() {
|
|
|
599
555
|
|
|
600
556
|
{/* Add Button */}
|
|
601
557
|
<button
|
|
602
|
-
|
|
558
|
+
className="button-primary button-with-icon scheduled-tasks-add"
|
|
603
559
|
onClick={() => {
|
|
604
560
|
setEditingJob(null);
|
|
605
561
|
setShowCreateModal(true);
|
|
606
562
|
}}
|
|
607
|
-
onMouseOver={(e) => {
|
|
608
|
-
e.currentTarget.style.backgroundColor = 'var(--color-accent-hover)';
|
|
609
|
-
e.currentTarget.style.transform = 'translateY(-1px)';
|
|
610
|
-
}}
|
|
611
|
-
onMouseOut={(e) => {
|
|
612
|
-
e.currentTarget.style.backgroundColor = 'var(--color-accent)';
|
|
613
|
-
e.currentTarget.style.transform = 'translateY(0)';
|
|
614
|
-
}}
|
|
615
563
|
>
|
|
616
564
|
{Icons.plus}
|
|
617
565
|
<span>New Scheduled Task</span>
|
|
@@ -23,8 +23,8 @@ export function SearchSettings({ onStatusChange }: SearchSettingsProps) {
|
|
|
23
23
|
const [googleApiKey, setGoogleApiKey] = useState('');
|
|
24
24
|
const [googleSearchEngineId, setGoogleSearchEngineId] = useState('');
|
|
25
25
|
|
|
26
|
-
// Track which
|
|
27
|
-
const [
|
|
26
|
+
// Track which provider is active in the tab view
|
|
27
|
+
const [activeProvider, setActiveProvider] = useState<SearchProviderType | null>(null);
|
|
28
28
|
|
|
29
29
|
useEffect(() => {
|
|
30
30
|
loadConfig();
|
|
@@ -37,6 +37,12 @@ export function SearchSettings({ onStatusChange }: SearchSettingsProps) {
|
|
|
37
37
|
setConfigStatus(status);
|
|
38
38
|
setPrimaryProvider(status.primaryProvider);
|
|
39
39
|
setFallbackProvider(status.fallbackProvider);
|
|
40
|
+
setActiveProvider((prev) => {
|
|
41
|
+
if (prev && status.providers.some((provider) => provider.type === prev)) {
|
|
42
|
+
return prev;
|
|
43
|
+
}
|
|
44
|
+
return status.primaryProvider ?? status.providers[0]?.type ?? null;
|
|
45
|
+
});
|
|
40
46
|
onStatusChange?.(status.isConfigured);
|
|
41
47
|
} catch (error) {
|
|
42
48
|
console.error('Failed to load search config:', error);
|
|
@@ -89,6 +95,7 @@ export function SearchSettings({ onStatusChange }: SearchSettingsProps) {
|
|
|
89
95
|
|
|
90
96
|
const configuredProviders = configStatus?.providers.filter(p => p.configured) || [];
|
|
91
97
|
const hasMultipleProviders = configuredProviders.length > 1;
|
|
98
|
+
const activeProviderConfig = configStatus?.providers.find(p => p.type === activeProvider) || null;
|
|
92
99
|
|
|
93
100
|
if (loading) {
|
|
94
101
|
return <div className="settings-loading">Loading search settings...</div>;
|
|
@@ -102,129 +109,126 @@ export function SearchSettings({ onStatusChange }: SearchSettingsProps) {
|
|
|
102
109
|
Add API keys to enable web search. You can configure multiple providers and set a primary and fallback.
|
|
103
110
|
</p>
|
|
104
111
|
|
|
105
|
-
<div className="provider-
|
|
112
|
+
<div className="llm-provider-tabs">
|
|
106
113
|
{configStatus?.providers.map(provider => (
|
|
107
|
-
<
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
<span className="provider-expand-icon">
|
|
121
|
-
{expandedProvider === provider.type ? '▼' : '▶'}
|
|
122
|
-
</span>
|
|
123
|
-
</div>
|
|
114
|
+
<button
|
|
115
|
+
key={provider.type}
|
|
116
|
+
className={`llm-provider-tab ${activeProvider === provider.type ? 'active' : ''}`}
|
|
117
|
+
onClick={() => {
|
|
118
|
+
setActiveProvider(provider.type);
|
|
119
|
+
setTestResult(null);
|
|
120
|
+
}}
|
|
121
|
+
>
|
|
122
|
+
<span className="llm-provider-tab-label">{provider.name}</span>
|
|
123
|
+
{provider.configured && <span className="llm-provider-tab-status" />}
|
|
124
|
+
</button>
|
|
125
|
+
))}
|
|
126
|
+
</div>
|
|
124
127
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
{activeProviderConfig ? (
|
|
129
|
+
<div className="settings-card provider-config-panel">
|
|
130
|
+
<div className="provider-config-form">
|
|
131
|
+
<p className="provider-description">{activeProviderConfig.description}</p>
|
|
132
|
+
<p className="provider-types">
|
|
133
|
+
Supports: {activeProviderConfig.supportedTypes.join(', ')}
|
|
134
|
+
</p>
|
|
131
135
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
136
|
+
{activeProviderConfig.type === 'tavily' && (
|
|
137
|
+
<div className="settings-field">
|
|
138
|
+
<label>Tavily API Key</label>
|
|
139
|
+
<input
|
|
140
|
+
type="password"
|
|
141
|
+
className="settings-input"
|
|
142
|
+
placeholder={activeProviderConfig.configured ? '••••••••••••••••' : 'tvly-...'}
|
|
143
|
+
value={tavilyApiKey}
|
|
144
|
+
onChange={(e) => setTavilyApiKey(e.target.value)}
|
|
145
|
+
/>
|
|
146
|
+
<p className="settings-hint">
|
|
147
|
+
Get your API key from <a href="https://tavily.com/" target="_blank" rel="noopener noreferrer">tavily.com</a>
|
|
148
|
+
</p>
|
|
149
|
+
</div>
|
|
150
|
+
)}
|
|
147
151
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
152
|
+
{activeProviderConfig.type === 'brave' && (
|
|
153
|
+
<div className="settings-field">
|
|
154
|
+
<label>Brave Search API Key</label>
|
|
155
|
+
<input
|
|
156
|
+
type="password"
|
|
157
|
+
className="settings-input"
|
|
158
|
+
placeholder={activeProviderConfig.configured ? '••••••••••••••••' : 'BSA...'}
|
|
159
|
+
value={braveApiKey}
|
|
160
|
+
onChange={(e) => setBraveApiKey(e.target.value)}
|
|
161
|
+
/>
|
|
162
|
+
<p className="settings-hint">
|
|
163
|
+
Get your API key from <a href="https://brave.com/search/api/" target="_blank" rel="noopener noreferrer">brave.com/search/api</a>
|
|
164
|
+
</p>
|
|
165
|
+
</div>
|
|
166
|
+
)}
|
|
163
167
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
168
|
+
{activeProviderConfig.type === 'serpapi' && (
|
|
169
|
+
<div className="settings-field">
|
|
170
|
+
<label>SerpAPI Key</label>
|
|
171
|
+
<input
|
|
172
|
+
type="password"
|
|
173
|
+
className="settings-input"
|
|
174
|
+
placeholder={activeProviderConfig.configured ? '••••••••••••••••' : 'Enter API key'}
|
|
175
|
+
value={serpapiApiKey}
|
|
176
|
+
onChange={(e) => setSerpapiApiKey(e.target.value)}
|
|
177
|
+
/>
|
|
178
|
+
<p className="settings-hint">
|
|
179
|
+
Get your API key from <a href="https://serpapi.com/" target="_blank" rel="noopener noreferrer">serpapi.com</a>
|
|
180
|
+
</p>
|
|
181
|
+
</div>
|
|
182
|
+
)}
|
|
179
183
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
184
|
+
{activeProviderConfig.type === 'google' && (
|
|
185
|
+
<>
|
|
186
|
+
<div className="settings-field">
|
|
187
|
+
<label>Google API Key</label>
|
|
188
|
+
<input
|
|
189
|
+
type="password"
|
|
190
|
+
className="settings-input"
|
|
191
|
+
placeholder={activeProviderConfig.configured ? '••••••••••••••••' : 'AIza...'}
|
|
192
|
+
value={googleApiKey}
|
|
193
|
+
onChange={(e) => setGoogleApiKey(e.target.value)}
|
|
194
|
+
/>
|
|
195
|
+
</div>
|
|
196
|
+
<div className="settings-field">
|
|
197
|
+
<label>Search Engine ID</label>
|
|
198
|
+
<input
|
|
199
|
+
type="text"
|
|
200
|
+
className="settings-input"
|
|
201
|
+
placeholder="Enter Search Engine ID"
|
|
202
|
+
value={googleSearchEngineId}
|
|
203
|
+
onChange={(e) => setGoogleSearchEngineId(e.target.value)}
|
|
204
|
+
/>
|
|
205
|
+
<p className="settings-hint">
|
|
206
|
+
Get your credentials from <a href="https://developers.google.com/custom-search/v1/introduction" target="_blank" rel="noopener noreferrer">Google Custom Search</a>
|
|
207
|
+
</p>
|
|
208
|
+
</div>
|
|
209
|
+
</>
|
|
210
|
+
)}
|
|
207
211
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
212
|
+
{activeProviderConfig.configured && (
|
|
213
|
+
<button
|
|
214
|
+
className="button-small button-secondary"
|
|
215
|
+
onClick={() => handleTestProvider(activeProviderConfig.type)}
|
|
216
|
+
disabled={testingProvider === activeProviderConfig.type}
|
|
217
|
+
>
|
|
218
|
+
{testingProvider === activeProviderConfig.type ? 'Testing...' : 'Test Connection'}
|
|
219
|
+
</button>
|
|
220
|
+
)}
|
|
217
221
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
</div>
|
|
222
|
-
)}
|
|
222
|
+
{testResult?.provider === activeProviderConfig.type && (
|
|
223
|
+
<div className={`test-result-inline ${testResult.success ? 'success' : 'error'}`}>
|
|
224
|
+
{testResult.success ? '✓ Connection successful' : `✗ ${testResult.error}`}
|
|
223
225
|
</div>
|
|
224
226
|
)}
|
|
225
227
|
</div>
|
|
226
|
-
|
|
227
|
-
|
|
228
|
+
</div>
|
|
229
|
+
) : (
|
|
230
|
+
<div className="settings-empty">Select a provider to configure.</div>
|
|
231
|
+
)}
|
|
228
232
|
</div>
|
|
229
233
|
|
|
230
234
|
{configuredProviders.length > 0 && (
|