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
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
import { TaskEvent, DEFAULT_QUIRKS } from '../../shared/types';
|
|
2
|
+
import { ThemeIcon } from './ThemeIcon';
|
|
3
|
+
import {
|
|
4
|
+
AlertTriangleIcon,
|
|
5
|
+
BanIcon,
|
|
6
|
+
CheckIcon,
|
|
7
|
+
ClipboardIcon,
|
|
8
|
+
DotIcon,
|
|
9
|
+
FileIcon,
|
|
10
|
+
PackageIcon,
|
|
11
|
+
PauseIcon,
|
|
12
|
+
PlayIcon,
|
|
13
|
+
ShieldIcon,
|
|
14
|
+
SlidersIcon,
|
|
15
|
+
StopIcon,
|
|
16
|
+
TargetIcon,
|
|
17
|
+
TrashIcon,
|
|
18
|
+
XIcon,
|
|
19
|
+
ZapIcon,
|
|
20
|
+
} from './LineIcons';
|
|
2
21
|
import type { AgentContext } from '../hooks/useAgentContext';
|
|
3
22
|
import { getUiCopy, type UiCopyKey } from '../utils/agentMessages';
|
|
4
23
|
|
|
@@ -39,57 +58,57 @@ export function TaskTimeline({ events, agentContext }: TaskTimelineProps) {
|
|
|
39
58
|
const getEventIcon = (type: TaskEvent['type']) => {
|
|
40
59
|
switch (type) {
|
|
41
60
|
case 'task_created':
|
|
42
|
-
return
|
|
61
|
+
return <ThemeIcon emoji="🎯" icon={<TargetIcon size={16} />} />;
|
|
43
62
|
case 'plan_created':
|
|
44
|
-
return
|
|
63
|
+
return <ThemeIcon emoji="📋" icon={<ClipboardIcon size={16} />} />;
|
|
45
64
|
case 'step_started':
|
|
46
|
-
return
|
|
65
|
+
return <ThemeIcon emoji="▶️" icon={<PlayIcon size={16} />} />;
|
|
47
66
|
case 'step_completed':
|
|
48
|
-
return
|
|
67
|
+
return <ThemeIcon emoji="✅" icon={<CheckIcon size={16} />} />;
|
|
49
68
|
case 'tool_call':
|
|
50
|
-
return
|
|
69
|
+
return <ThemeIcon emoji="🔧" icon={<SlidersIcon size={16} />} />;
|
|
51
70
|
case 'tool_result':
|
|
52
|
-
return
|
|
71
|
+
return <ThemeIcon emoji="📦" icon={<PackageIcon size={16} />} />;
|
|
53
72
|
case 'file_created':
|
|
54
73
|
case 'file_modified':
|
|
55
|
-
return
|
|
74
|
+
return <ThemeIcon emoji="📄" icon={<FileIcon size={16} />} />;
|
|
56
75
|
case 'file_deleted':
|
|
57
|
-
return
|
|
76
|
+
return <ThemeIcon emoji="🗑️" icon={<TrashIcon size={16} />} />;
|
|
58
77
|
case 'error':
|
|
59
|
-
return
|
|
78
|
+
return <ThemeIcon emoji="❌" icon={<XIcon size={16} />} />;
|
|
60
79
|
case 'task_cancelled':
|
|
61
|
-
return
|
|
80
|
+
return <ThemeIcon emoji="🛑" icon={<StopIcon size={16} />} />;
|
|
62
81
|
case 'approval_requested':
|
|
63
|
-
return
|
|
82
|
+
return <ThemeIcon emoji="⚠️" icon={<AlertTriangleIcon size={16} />} />;
|
|
64
83
|
case 'approval_granted':
|
|
65
|
-
return
|
|
84
|
+
return <ThemeIcon emoji="✅" icon={<CheckIcon size={16} />} />;
|
|
66
85
|
case 'approval_denied':
|
|
67
|
-
return
|
|
86
|
+
return <ThemeIcon emoji="⛔" icon={<BanIcon size={16} />} />;
|
|
68
87
|
case 'task_paused':
|
|
69
|
-
return
|
|
88
|
+
return <ThemeIcon emoji="⏸️" icon={<PauseIcon size={16} />} />;
|
|
70
89
|
case 'task_resumed':
|
|
71
|
-
return
|
|
90
|
+
return <ThemeIcon emoji="▶️" icon={<PlayIcon size={16} />} />;
|
|
72
91
|
case 'executing':
|
|
73
|
-
return
|
|
92
|
+
return <ThemeIcon emoji="⚡" icon={<ZapIcon size={16} />} />;
|
|
74
93
|
case 'task_completed':
|
|
75
|
-
return
|
|
94
|
+
return <ThemeIcon emoji="✅" icon={<CheckIcon size={16} />} />;
|
|
76
95
|
case 'follow_up_completed':
|
|
77
|
-
return
|
|
96
|
+
return <ThemeIcon emoji="✅" icon={<CheckIcon size={16} />} />;
|
|
78
97
|
default:
|
|
79
|
-
return
|
|
98
|
+
return <ThemeIcon emoji="•" icon={<DotIcon size={8} />} />;
|
|
80
99
|
}
|
|
81
100
|
};
|
|
82
101
|
|
|
83
102
|
const getEventTitle = (event: TaskEvent) => {
|
|
84
103
|
switch (event.type) {
|
|
85
104
|
case 'task_created':
|
|
86
|
-
return isCompanion ? "Session started - I'm here." : '
|
|
105
|
+
return isCompanion ? "Session started - I'm here." : 'Session started';
|
|
87
106
|
case 'plan_created':
|
|
88
107
|
return isCompanion ? "Here's the path I'm taking" : "Here's our approach";
|
|
89
108
|
case 'step_started':
|
|
90
109
|
return `Working on: ${event.payload.step?.description || 'Getting started'}`;
|
|
91
110
|
case 'step_completed':
|
|
92
|
-
return
|
|
111
|
+
return event.payload.step?.description || event.payload.message || 'Done';
|
|
93
112
|
case 'tool_call':
|
|
94
113
|
return `Using: ${event.payload.tool}`;
|
|
95
114
|
case 'tool_result':
|
|
@@ -119,9 +138,9 @@ export function TaskTimeline({ events, agentContext }: TaskTimelineProps) {
|
|
|
119
138
|
case 'executing':
|
|
120
139
|
return event.payload.message || 'Working on it';
|
|
121
140
|
case 'task_completed':
|
|
122
|
-
return isCompanion ? 'All done.' : '
|
|
141
|
+
return isCompanion ? 'All done.' : 'All done!';
|
|
123
142
|
case 'follow_up_completed':
|
|
124
|
-
return '
|
|
143
|
+
return 'All done!';
|
|
125
144
|
case 'log':
|
|
126
145
|
return event.payload.message;
|
|
127
146
|
default:
|
|
@@ -156,12 +175,23 @@ export function TaskTimeline({ events, agentContext }: TaskTimelineProps) {
|
|
|
156
175
|
<pre>{JSON.stringify(event.payload.result, null, 2)}</pre>
|
|
157
176
|
</div>
|
|
158
177
|
);
|
|
159
|
-
case 'error':
|
|
178
|
+
case 'error': {
|
|
179
|
+
const errorMessage = event.payload.error || event.payload.message;
|
|
180
|
+
const actionHint = event.payload.actionHint;
|
|
160
181
|
return (
|
|
161
182
|
<div className="event-details error">
|
|
162
|
-
{
|
|
183
|
+
<div>{errorMessage}</div>
|
|
184
|
+
{actionHint?.type === 'open_settings' && (
|
|
185
|
+
<button
|
|
186
|
+
className="button-primary button-small"
|
|
187
|
+
onClick={() => window.dispatchEvent(new CustomEvent('open-settings'))}
|
|
188
|
+
>
|
|
189
|
+
{actionHint.label || 'Open Settings'}
|
|
190
|
+
</button>
|
|
191
|
+
)}
|
|
163
192
|
</div>
|
|
164
193
|
);
|
|
194
|
+
}
|
|
165
195
|
case 'task_cancelled':
|
|
166
196
|
return (
|
|
167
197
|
<div className="event-details cancelled">
|
|
@@ -200,7 +230,9 @@ export function TaskTimeline({ events, agentContext }: TaskTimelineProps) {
|
|
|
200
230
|
{/* Show summary of blocked events if any - collapsed for cleaner UI */}
|
|
201
231
|
{blockedEvents.length > 0 && (
|
|
202
232
|
<div className="timeline-event timeline-event-muted">
|
|
203
|
-
<div className="event-icon"
|
|
233
|
+
<div className="event-icon">
|
|
234
|
+
<ThemeIcon emoji="🛡️" icon={<ShieldIcon size={16} />} />
|
|
235
|
+
</div>
|
|
204
236
|
<div className="event-content">
|
|
205
237
|
<div className="event-header">
|
|
206
238
|
<div className="event-title">
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react';
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
2
2
|
import { ChannelData, ChannelUserData, SecurityMode, ContextType, ContextPolicy } from '../../shared/types';
|
|
3
3
|
import { PairingCodeDisplay } from './PairingCodeDisplay';
|
|
4
4
|
import { ContextPolicySettings } from './ContextPolicySettings';
|
|
@@ -32,11 +32,7 @@ export function TeamsSettings({ onStatusChange }: TeamsSettingsProps) {
|
|
|
32
32
|
const [contextPolicies, setContextPolicies] = useState<Record<ContextType, ContextPolicy>>({} as Record<ContextType, ContextPolicy>);
|
|
33
33
|
const [savingPolicy, setSavingPolicy] = useState(false);
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
loadChannel();
|
|
37
|
-
}, []);
|
|
38
|
-
|
|
39
|
-
const loadChannel = async () => {
|
|
35
|
+
const loadChannel = useCallback(async () => {
|
|
40
36
|
try {
|
|
41
37
|
setLoading(true);
|
|
42
38
|
const channels = await window.electronAPI.getGatewayChannels();
|
|
@@ -65,7 +61,22 @@ export function TeamsSettings({ onStatusChange }: TeamsSettingsProps) {
|
|
|
65
61
|
} finally {
|
|
66
62
|
setLoading(false);
|
|
67
63
|
}
|
|
68
|
-
};
|
|
64
|
+
}, [onStatusChange]);
|
|
65
|
+
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
loadChannel();
|
|
68
|
+
}, [loadChannel]);
|
|
69
|
+
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
const unsubscribe = window.electronAPI?.onGatewayUsersUpdated?.((data) => {
|
|
72
|
+
if (data?.channelType !== 'teams') return;
|
|
73
|
+
if (channel && data?.channelId && data.channelId !== channel.id) return;
|
|
74
|
+
loadChannel();
|
|
75
|
+
});
|
|
76
|
+
return () => {
|
|
77
|
+
if (unsubscribe) unsubscribe();
|
|
78
|
+
};
|
|
79
|
+
}, [channel?.id, loadChannel]);
|
|
69
80
|
|
|
70
81
|
const handleAddChannel = async () => {
|
|
71
82
|
if (!appId.trim() || !appPassword.trim()) return;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react';
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
2
2
|
import { ChannelData, ChannelUserData, SecurityMode, ContextType, ContextPolicy } from '../../shared/types';
|
|
3
3
|
import { PairingCodeDisplay } from './PairingCodeDisplay';
|
|
4
4
|
import { ContextPolicySettings } from './ContextPolicySettings';
|
|
@@ -29,11 +29,7 @@ export function TelegramSettings({ onStatusChange }: TelegramSettingsProps) {
|
|
|
29
29
|
const [contextPolicies, setContextPolicies] = useState<Record<ContextType, ContextPolicy>>({} as Record<ContextType, ContextPolicy>);
|
|
30
30
|
const [savingPolicy, setSavingPolicy] = useState(false);
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
loadChannel();
|
|
34
|
-
}, []);
|
|
35
|
-
|
|
36
|
-
const loadChannel = async () => {
|
|
32
|
+
const loadChannel = useCallback(async () => {
|
|
37
33
|
try {
|
|
38
34
|
setLoading(true);
|
|
39
35
|
const channels = await window.electronAPI.getGatewayChannels();
|
|
@@ -62,7 +58,22 @@ export function TelegramSettings({ onStatusChange }: TelegramSettingsProps) {
|
|
|
62
58
|
} finally {
|
|
63
59
|
setLoading(false);
|
|
64
60
|
}
|
|
65
|
-
};
|
|
61
|
+
}, [onStatusChange]);
|
|
62
|
+
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
loadChannel();
|
|
65
|
+
}, [loadChannel]);
|
|
66
|
+
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
const unsubscribe = window.electronAPI?.onGatewayUsersUpdated?.((data) => {
|
|
69
|
+
if (data?.channelType !== 'telegram') return;
|
|
70
|
+
if (channel && data?.channelId && data.channelId !== channel.id) return;
|
|
71
|
+
loadChannel();
|
|
72
|
+
});
|
|
73
|
+
return () => {
|
|
74
|
+
if (unsubscribe) unsubscribe();
|
|
75
|
+
};
|
|
76
|
+
}, [channel?.id, loadChannel]);
|
|
66
77
|
|
|
67
78
|
const handleAddChannel = async () => {
|
|
68
79
|
if (!botToken.trim()) return;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface ThemeIconProps {
|
|
4
|
+
emoji: string;
|
|
5
|
+
icon: React.ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function ThemeIcon({ emoji, icon, className }: ThemeIconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<span className={className} aria-hidden="true">
|
|
12
|
+
<span className="terminal-only">{emoji}</span>
|
|
13
|
+
<span className="modern-only">{icon}</span>
|
|
14
|
+
</span>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react';
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
2
2
|
import { ChannelData, ChannelUserData, SecurityMode, ContextType, ContextPolicy } from '../../shared/types';
|
|
3
3
|
import { PairingCodeDisplay } from './PairingCodeDisplay';
|
|
4
4
|
import { ContextPolicySettings } from './ContextPolicySettings';
|
|
@@ -32,11 +32,7 @@ export function TwitchSettings({ onStatusChange }: TwitchSettingsProps) {
|
|
|
32
32
|
const [contextPolicies, setContextPolicies] = useState<Record<ContextType, ContextPolicy>>({} as Record<ContextType, ContextPolicy>);
|
|
33
33
|
const [savingPolicy, setSavingPolicy] = useState(false);
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
loadChannel();
|
|
37
|
-
}, []);
|
|
38
|
-
|
|
39
|
-
const loadChannel = async () => {
|
|
35
|
+
const loadChannel = useCallback(async () => {
|
|
40
36
|
try {
|
|
41
37
|
setLoading(true);
|
|
42
38
|
const channels = await window.electronAPI.getGatewayChannels();
|
|
@@ -74,7 +70,22 @@ export function TwitchSettings({ onStatusChange }: TwitchSettingsProps) {
|
|
|
74
70
|
} finally {
|
|
75
71
|
setLoading(false);
|
|
76
72
|
}
|
|
77
|
-
};
|
|
73
|
+
}, [onStatusChange]);
|
|
74
|
+
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
loadChannel();
|
|
77
|
+
}, [loadChannel]);
|
|
78
|
+
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
const unsubscribe = window.electronAPI?.onGatewayUsersUpdated?.((data) => {
|
|
81
|
+
if (data?.channelType !== 'twitch') return;
|
|
82
|
+
if (channel && data?.channelId && data.channelId !== channel.id) return;
|
|
83
|
+
loadChannel();
|
|
84
|
+
});
|
|
85
|
+
return () => {
|
|
86
|
+
if (unsubscribe) unsubscribe();
|
|
87
|
+
};
|
|
88
|
+
}, [channel?.id, loadChannel]);
|
|
78
89
|
|
|
79
90
|
const handleAddChannel = async () => {
|
|
80
91
|
if (!username.trim() || !oauthToken.trim() || !twitchChannels.trim()) {
|
|
@@ -391,63 +391,38 @@ export function VoiceSettings({ onStateChange }: VoiceSettingsProps) {
|
|
|
391
391
|
<div className="settings-section">
|
|
392
392
|
<h4>Text-to-Speech Provider</h4>
|
|
393
393
|
<p className="settings-description">Choose the voice synthesis provider.</p>
|
|
394
|
-
<div className="provider-
|
|
394
|
+
<div className="llm-provider-tabs">
|
|
395
395
|
<button
|
|
396
|
-
className={`provider-
|
|
396
|
+
className={`llm-provider-tab ${settings.ttsProvider === 'elevenlabs' ? 'active' : ''}`}
|
|
397
397
|
onClick={() => handleTTSProviderChange('elevenlabs')}
|
|
398
398
|
disabled={saving}
|
|
399
399
|
>
|
|
400
|
-
<
|
|
401
|
-
|
|
402
|
-
{settings.elevenLabsApiKey && (
|
|
403
|
-
<svg className="provider-configured-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
|
|
404
|
-
<path d="M20 6L9 17l-5-5" />
|
|
405
|
-
</svg>
|
|
406
|
-
)}
|
|
407
|
-
</div>
|
|
408
|
-
<span className="provider-badge">Premium</span>
|
|
400
|
+
<span className="llm-provider-tab-label">ElevenLabs</span>
|
|
401
|
+
{settings.elevenLabsApiKey && <span className="llm-provider-tab-status" />}
|
|
409
402
|
</button>
|
|
410
403
|
<button
|
|
411
|
-
className={`provider-
|
|
404
|
+
className={`llm-provider-tab ${settings.ttsProvider === 'openai' ? 'active' : ''}`}
|
|
412
405
|
onClick={() => handleTTSProviderChange('openai')}
|
|
413
406
|
disabled={saving}
|
|
414
407
|
>
|
|
415
|
-
<
|
|
416
|
-
|
|
417
|
-
{settings.openaiApiKey && (
|
|
418
|
-
<svg className="provider-configured-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
|
|
419
|
-
<path d="M20 6L9 17l-5-5" />
|
|
420
|
-
</svg>
|
|
421
|
-
)}
|
|
422
|
-
</div>
|
|
408
|
+
<span className="llm-provider-tab-label">OpenAI</span>
|
|
409
|
+
{settings.openaiApiKey && <span className="llm-provider-tab-status" />}
|
|
423
410
|
</button>
|
|
424
411
|
<button
|
|
425
|
-
className={`provider-
|
|
412
|
+
className={`llm-provider-tab ${settings.ttsProvider === 'azure' ? 'active' : ''}`}
|
|
426
413
|
onClick={() => handleTTSProviderChange('azure')}
|
|
427
414
|
disabled={saving}
|
|
428
415
|
>
|
|
429
|
-
<
|
|
430
|
-
|
|
431
|
-
{settings.azureApiKey && settings.azureEndpoint && (
|
|
432
|
-
<svg className="provider-configured-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
|
|
433
|
-
<path d="M20 6L9 17l-5-5" />
|
|
434
|
-
</svg>
|
|
435
|
-
)}
|
|
436
|
-
</div>
|
|
437
|
-
<span className="provider-badge">Enterprise</span>
|
|
416
|
+
<span className="llm-provider-tab-label">Azure OpenAI</span>
|
|
417
|
+
{settings.azureApiKey && settings.azureEndpoint && <span className="llm-provider-tab-status" />}
|
|
438
418
|
</button>
|
|
439
419
|
<button
|
|
440
|
-
className={`provider-
|
|
420
|
+
className={`llm-provider-tab ${settings.ttsProvider === 'local' ? 'active' : ''}`}
|
|
441
421
|
onClick={() => handleTTSProviderChange('local')}
|
|
442
422
|
disabled={saving}
|
|
443
423
|
>
|
|
444
|
-
<
|
|
445
|
-
|
|
446
|
-
<svg className="provider-configured-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
|
|
447
|
-
<path d="M20 6L9 17l-5-5" />
|
|
448
|
-
</svg>
|
|
449
|
-
</div>
|
|
450
|
-
<span className="provider-badge">Free</span>
|
|
424
|
+
<span className="llm-provider-tab-label">System</span>
|
|
425
|
+
<span className="llm-provider-tab-status" />
|
|
451
426
|
</button>
|
|
452
427
|
</div>
|
|
453
428
|
</div>
|
|
@@ -698,49 +673,30 @@ export function VoiceSettings({ onStateChange }: VoiceSettingsProps) {
|
|
|
698
673
|
<div className="settings-section">
|
|
699
674
|
<h4>Speech-to-Text Provider</h4>
|
|
700
675
|
<p className="settings-description">Choose the speech recognition provider.</p>
|
|
701
|
-
<div className="provider-
|
|
676
|
+
<div className="llm-provider-tabs">
|
|
702
677
|
<button
|
|
703
|
-
className={`provider-
|
|
678
|
+
className={`llm-provider-tab ${settings.sttProvider === 'openai' ? 'active' : ''}`}
|
|
704
679
|
onClick={() => handleSTTProviderChange('openai')}
|
|
705
680
|
disabled={saving}
|
|
706
681
|
>
|
|
707
|
-
<
|
|
708
|
-
|
|
709
|
-
{settings.openaiApiKey && (
|
|
710
|
-
<svg className="provider-configured-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
|
|
711
|
-
<path d="M20 6L9 17l-5-5" />
|
|
712
|
-
</svg>
|
|
713
|
-
)}
|
|
714
|
-
</div>
|
|
715
|
-
<span className="provider-badge">Recommended</span>
|
|
682
|
+
<span className="llm-provider-tab-label">OpenAI Whisper</span>
|
|
683
|
+
{settings.openaiApiKey && <span className="llm-provider-tab-status" />}
|
|
716
684
|
</button>
|
|
717
685
|
<button
|
|
718
|
-
className={`provider-
|
|
686
|
+
className={`llm-provider-tab ${settings.sttProvider === 'azure' ? 'active' : ''}`}
|
|
719
687
|
onClick={() => handleSTTProviderChange('azure')}
|
|
720
688
|
disabled={saving}
|
|
721
689
|
>
|
|
722
|
-
<
|
|
723
|
-
|
|
724
|
-
{settings.azureApiKey && settings.azureEndpoint && (
|
|
725
|
-
<svg className="provider-configured-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
|
|
726
|
-
<path d="M20 6L9 17l-5-5" />
|
|
727
|
-
</svg>
|
|
728
|
-
)}
|
|
729
|
-
</div>
|
|
730
|
-
<span className="provider-badge">Enterprise</span>
|
|
690
|
+
<span className="llm-provider-tab-label">Azure Whisper</span>
|
|
691
|
+
{settings.azureApiKey && settings.azureEndpoint && <span className="llm-provider-tab-status" />}
|
|
731
692
|
</button>
|
|
732
693
|
<button
|
|
733
|
-
className={`provider-
|
|
694
|
+
className={`llm-provider-tab ${settings.sttProvider === 'local' ? 'active' : ''}`}
|
|
734
695
|
onClick={() => handleSTTProviderChange('local')}
|
|
735
696
|
disabled={saving}
|
|
736
697
|
>
|
|
737
|
-
<
|
|
738
|
-
|
|
739
|
-
<svg className="provider-configured-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
|
|
740
|
-
<path d="M20 6L9 17l-5-5" />
|
|
741
|
-
</svg>
|
|
742
|
-
</div>
|
|
743
|
-
<span className="provider-badge">Free</span>
|
|
698
|
+
<span className="llm-provider-tab-label">System</span>
|
|
699
|
+
<span className="llm-provider-tab-status" />
|
|
744
700
|
</button>
|
|
745
701
|
</div>
|
|
746
702
|
</div>
|
|
@@ -748,27 +704,27 @@ export function VoiceSettings({ onStateChange }: VoiceSettingsProps) {
|
|
|
748
704
|
{/* Voice Input Mode */}
|
|
749
705
|
<div className="settings-section">
|
|
750
706
|
<h4>Voice Input Mode</h4>
|
|
751
|
-
<div className="provider-
|
|
707
|
+
<div className="llm-provider-tabs">
|
|
752
708
|
<button
|
|
753
|
-
className={`provider-
|
|
709
|
+
className={`llm-provider-tab ${settings.inputMode === 'push_to_talk' ? 'active' : ''}`}
|
|
754
710
|
onClick={() => handleInputModeChange('push_to_talk')}
|
|
755
711
|
disabled={saving}
|
|
756
712
|
>
|
|
757
|
-
<span className="provider-
|
|
713
|
+
<span className="llm-provider-tab-label">Push to Talk</span>
|
|
758
714
|
</button>
|
|
759
715
|
<button
|
|
760
|
-
className={`provider-
|
|
716
|
+
className={`llm-provider-tab ${settings.inputMode === 'voice_activity' ? 'active' : ''}`}
|
|
761
717
|
onClick={() => handleInputModeChange('voice_activity')}
|
|
762
718
|
disabled={saving}
|
|
763
719
|
>
|
|
764
|
-
<span className="provider-
|
|
720
|
+
<span className="llm-provider-tab-label">Voice Activity</span>
|
|
765
721
|
</button>
|
|
766
722
|
<button
|
|
767
|
-
className={`provider-
|
|
723
|
+
className={`llm-provider-tab ${settings.inputMode === 'disabled' ? 'active' : ''}`}
|
|
768
724
|
onClick={() => handleInputModeChange('disabled')}
|
|
769
725
|
disabled={saving}
|
|
770
726
|
>
|
|
771
|
-
<span className="provider-
|
|
727
|
+
<span className="llm-provider-tab-label">Disabled</span>
|
|
772
728
|
</button>
|
|
773
729
|
</div>
|
|
774
730
|
<p className="settings-hint">
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react';
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
2
2
|
import { ChannelData, ChannelUserData, SecurityMode } from '../../shared/types';
|
|
3
3
|
import QRCode from 'qrcode';
|
|
4
4
|
|
|
@@ -29,6 +29,41 @@ export function WhatsAppSettings({ onStatusChange }: WhatsAppSettingsProps) {
|
|
|
29
29
|
// Pairing code state
|
|
30
30
|
const [pairingCode, setPairingCode] = useState<string | null>(null);
|
|
31
31
|
|
|
32
|
+
const loadChannel = useCallback(async () => {
|
|
33
|
+
try {
|
|
34
|
+
setLoading(true);
|
|
35
|
+
const channels = await window.electronAPI.getGatewayChannels();
|
|
36
|
+
const whatsappChannel = channels.find((c: ChannelData) => c.type === 'whatsapp');
|
|
37
|
+
|
|
38
|
+
if (whatsappChannel) {
|
|
39
|
+
setChannel(whatsappChannel);
|
|
40
|
+
setChannelName(whatsappChannel.name);
|
|
41
|
+
setSecurityMode(whatsappChannel.securityMode);
|
|
42
|
+
onStatusChange?.(whatsappChannel.status === 'connected');
|
|
43
|
+
|
|
44
|
+
// Load self-chat mode settings from config
|
|
45
|
+
if (whatsappChannel.config) {
|
|
46
|
+
setSelfChatMode(whatsappChannel.config.selfChatMode ?? true);
|
|
47
|
+
setResponsePrefix(whatsappChannel.config.responsePrefix ?? '🤖');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Load users for this channel
|
|
51
|
+
const channelUsers = await window.electronAPI.getGatewayUsers(whatsappChannel.id);
|
|
52
|
+
setUsers(channelUsers);
|
|
53
|
+
|
|
54
|
+
// Check for QR code
|
|
55
|
+
const info = await window.electronAPI.getWhatsAppInfo?.();
|
|
56
|
+
if (info?.qrCode) {
|
|
57
|
+
setQrCode(info.qrCode);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.error('Failed to load WhatsApp channel:', error);
|
|
62
|
+
} finally {
|
|
63
|
+
setLoading(false);
|
|
64
|
+
}
|
|
65
|
+
}, [onStatusChange]);
|
|
66
|
+
|
|
32
67
|
useEffect(() => {
|
|
33
68
|
loadChannel();
|
|
34
69
|
|
|
@@ -50,7 +85,18 @@ export function WhatsAppSettings({ onStatusChange }: WhatsAppSettingsProps) {
|
|
|
50
85
|
return () => {
|
|
51
86
|
// Cleanup listeners if needed
|
|
52
87
|
};
|
|
53
|
-
}, []);
|
|
88
|
+
}, [loadChannel]);
|
|
89
|
+
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
const unsubscribe = window.electronAPI?.onGatewayUsersUpdated?.((data) => {
|
|
92
|
+
if (data?.channelType !== 'whatsapp') return;
|
|
93
|
+
if (channel && data?.channelId && data.channelId !== channel.id) return;
|
|
94
|
+
loadChannel();
|
|
95
|
+
});
|
|
96
|
+
return () => {
|
|
97
|
+
if (unsubscribe) unsubscribe();
|
|
98
|
+
};
|
|
99
|
+
}, [channel?.id, loadChannel]);
|
|
54
100
|
|
|
55
101
|
// Render QR code when it changes
|
|
56
102
|
useEffect(() => {
|
|
@@ -75,41 +121,6 @@ export function WhatsAppSettings({ onStatusChange }: WhatsAppSettingsProps) {
|
|
|
75
121
|
}
|
|
76
122
|
};
|
|
77
123
|
|
|
78
|
-
const loadChannel = async () => {
|
|
79
|
-
try {
|
|
80
|
-
setLoading(true);
|
|
81
|
-
const channels = await window.electronAPI.getGatewayChannels();
|
|
82
|
-
const whatsappChannel = channels.find((c: ChannelData) => c.type === 'whatsapp');
|
|
83
|
-
|
|
84
|
-
if (whatsappChannel) {
|
|
85
|
-
setChannel(whatsappChannel);
|
|
86
|
-
setChannelName(whatsappChannel.name);
|
|
87
|
-
setSecurityMode(whatsappChannel.securityMode);
|
|
88
|
-
onStatusChange?.(whatsappChannel.status === 'connected');
|
|
89
|
-
|
|
90
|
-
// Load self-chat mode settings from config
|
|
91
|
-
if (whatsappChannel.config) {
|
|
92
|
-
setSelfChatMode(whatsappChannel.config.selfChatMode ?? true);
|
|
93
|
-
setResponsePrefix(whatsappChannel.config.responsePrefix ?? '🤖');
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Load users for this channel
|
|
97
|
-
const channelUsers = await window.electronAPI.getGatewayUsers(whatsappChannel.id);
|
|
98
|
-
setUsers(channelUsers);
|
|
99
|
-
|
|
100
|
-
// Check for QR code
|
|
101
|
-
const info = await window.electronAPI.getWhatsAppInfo?.();
|
|
102
|
-
if (info?.qrCode) {
|
|
103
|
-
setQrCode(info.qrCode);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
} catch (error) {
|
|
107
|
-
console.error('Failed to load WhatsApp channel:', error);
|
|
108
|
-
} finally {
|
|
109
|
-
setLoading(false);
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
|
|
113
124
|
const handleAddChannel = async () => {
|
|
114
125
|
try {
|
|
115
126
|
setSaving(true);
|
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
WorkingStateType,
|
|
5
5
|
} from '../../electron/preload';
|
|
6
6
|
import { useAgentContext } from '../hooks/useAgentContext';
|
|
7
|
+
import { ThemeIcon } from './ThemeIcon';
|
|
8
|
+
import { ChartIcon, ClipboardIcon, EditIcon, TargetIcon } from './LineIcons';
|
|
7
9
|
|
|
8
10
|
interface WorkingStateHistoryProps {
|
|
9
11
|
agentRoleId: string;
|
|
@@ -12,11 +14,11 @@ interface WorkingStateHistoryProps {
|
|
|
12
14
|
onClose: () => void;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
const STATE_TYPE_LABELS: Record<WorkingStateType, { label: string; icon:
|
|
16
|
-
context: { label: 'Context', icon:
|
|
17
|
-
progress: { label: 'Progress', icon:
|
|
18
|
-
notes: { label: 'Notes', icon:
|
|
19
|
-
plan: { label: 'Plan', icon:
|
|
17
|
+
const STATE_TYPE_LABELS: Record<WorkingStateType, { label: string; icon: React.ReactNode }> = {
|
|
18
|
+
context: { label: 'Context', icon: <ThemeIcon emoji="📋" icon={<ClipboardIcon size={14} />} /> },
|
|
19
|
+
progress: { label: 'Progress', icon: <ThemeIcon emoji="📊" icon={<ChartIcon size={14} />} /> },
|
|
20
|
+
notes: { label: 'Notes', icon: <ThemeIcon emoji="📝" icon={<EditIcon size={14} />} /> },
|
|
21
|
+
plan: { label: 'Plan', icon: <ThemeIcon emoji="🎯" icon={<TargetIcon size={14} />} /> },
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
function formatDate(timestamp: number): string {
|