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
|
@@ -118,6 +118,7 @@ class MessageRouter {
|
|
|
118
118
|
agentName: settings.agentName || 'CoWork',
|
|
119
119
|
userName: settings.relationship?.userName,
|
|
120
120
|
personality: settings.activePersonality || 'professional',
|
|
121
|
+
persona: settings.activePersona,
|
|
121
122
|
emojiUsage: settings.responseStyle?.emojiUsage || 'minimal',
|
|
122
123
|
quirks: settings.quirks || types_2.DEFAULT_QUIRKS,
|
|
123
124
|
};
|
|
@@ -128,6 +129,28 @@ class MessageRouter {
|
|
|
128
129
|
}
|
|
129
130
|
return channelMessages_1.DEFAULT_CHANNEL_CONTEXT;
|
|
130
131
|
}
|
|
132
|
+
normalizeSimpleChannelMessage(text, context) {
|
|
133
|
+
if (!text)
|
|
134
|
+
return text;
|
|
135
|
+
let normalized = text;
|
|
136
|
+
const signOff = context.quirks?.signOff?.trim();
|
|
137
|
+
if (signOff) {
|
|
138
|
+
const escaped = signOff.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
139
|
+
const signOffRegex = new RegExp(`(?:\\s|\\n)*${escaped}\\s*$`, 'i');
|
|
140
|
+
const withoutSignOff = normalized.replace(signOffRegex, '').trimEnd();
|
|
141
|
+
if (withoutSignOff.length > 0) {
|
|
142
|
+
normalized = withoutSignOff;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
normalized = normalized.replace(/[ \t]+$/g, '');
|
|
146
|
+
if (normalized.endsWith(':')) {
|
|
147
|
+
normalized = normalized.slice(0, -1).trimEnd();
|
|
148
|
+
}
|
|
149
|
+
return normalized;
|
|
150
|
+
}
|
|
151
|
+
getUiCopy(key, replacements) {
|
|
152
|
+
return (0, channelMessages_1.getChannelUiCopy)(key, this.getMessageContext(), replacements);
|
|
153
|
+
}
|
|
131
154
|
/**
|
|
132
155
|
* Get or create the temp workspace for sessions without a workspace
|
|
133
156
|
*/
|
|
@@ -507,10 +530,10 @@ class MessageRouter {
|
|
|
507
530
|
// Not a pairing code or pairing not required - send appropriate message
|
|
508
531
|
let responseText;
|
|
509
532
|
if (securityResult.pairingRequired) {
|
|
510
|
-
responseText = this.
|
|
533
|
+
responseText = this.getUiCopy('pairingRequired');
|
|
511
534
|
}
|
|
512
535
|
else {
|
|
513
|
-
responseText = this.
|
|
536
|
+
responseText = this.getUiCopy('unauthorized');
|
|
514
537
|
}
|
|
515
538
|
try {
|
|
516
539
|
await adapter.sendMessage({
|
|
@@ -549,9 +572,19 @@ class MessageRouter {
|
|
|
549
572
|
if (!isNaN(num) && num > 0 && num <= workspaces.length) {
|
|
550
573
|
const workspace = workspaces[num - 1];
|
|
551
574
|
this.sessionManager.setSessionWorkspace(sessionId, workspace.id);
|
|
575
|
+
if (workspace.id !== types_1.TEMP_WORKSPACE_ID) {
|
|
576
|
+
try {
|
|
577
|
+
this.workspaceRepo.updateLastUsedAt(workspace.id);
|
|
578
|
+
}
|
|
579
|
+
catch (error) {
|
|
580
|
+
console.warn('Failed to update workspace last used time:', error);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
const selectedText = this.getUiCopy('workspaceSelected', { workspaceName: workspace.name });
|
|
584
|
+
const exampleText = this.getUiCopy('workspaceSelectedExample');
|
|
552
585
|
await adapter.sendMessage({
|
|
553
586
|
chatId: message.chatId,
|
|
554
|
-
text:
|
|
587
|
+
text: `${selectedText}\n\n${exampleText}`,
|
|
555
588
|
parseMode: 'markdown',
|
|
556
589
|
});
|
|
557
590
|
return;
|
|
@@ -561,9 +594,19 @@ class MessageRouter {
|
|
|
561
594
|
ws.name.toLowerCase().startsWith(text.toLowerCase()));
|
|
562
595
|
if (matchedWorkspace) {
|
|
563
596
|
this.sessionManager.setSessionWorkspace(sessionId, matchedWorkspace.id);
|
|
597
|
+
if (matchedWorkspace.id !== types_1.TEMP_WORKSPACE_ID) {
|
|
598
|
+
try {
|
|
599
|
+
this.workspaceRepo.updateLastUsedAt(matchedWorkspace.id);
|
|
600
|
+
}
|
|
601
|
+
catch (error) {
|
|
602
|
+
console.warn('Failed to update workspace last used time:', error);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
const selectedText = this.getUiCopy('workspaceSelected', { workspaceName: matchedWorkspace.name });
|
|
606
|
+
const exampleText = this.getUiCopy('workspaceSelectedExample');
|
|
564
607
|
await adapter.sendMessage({
|
|
565
608
|
chatId: message.chatId,
|
|
566
|
-
text:
|
|
609
|
+
text: `${selectedText}\n\n${exampleText}`,
|
|
567
610
|
parseMode: 'markdown',
|
|
568
611
|
});
|
|
569
612
|
return;
|
|
@@ -626,7 +669,7 @@ class MessageRouter {
|
|
|
626
669
|
if (args.length === 0) {
|
|
627
670
|
await adapter.sendMessage({
|
|
628
671
|
chatId: message.chatId,
|
|
629
|
-
text: '
|
|
672
|
+
text: this.getUiCopy('pairingPrompt'),
|
|
630
673
|
parseMode: 'markdown',
|
|
631
674
|
});
|
|
632
675
|
}
|
|
@@ -681,7 +724,7 @@ class MessageRouter {
|
|
|
681
724
|
default:
|
|
682
725
|
await adapter.sendMessage({
|
|
683
726
|
chatId: message.chatId,
|
|
684
|
-
text:
|
|
727
|
+
text: this.getUiCopy('unknownCommand', { command }),
|
|
685
728
|
replyTo: message.messageId,
|
|
686
729
|
});
|
|
687
730
|
}
|
|
@@ -691,21 +734,24 @@ class MessageRouter {
|
|
|
691
734
|
*/
|
|
692
735
|
async handleStatusCommand(adapter, message, sessionId) {
|
|
693
736
|
const session = this.sessionRepo.findById(sessionId);
|
|
694
|
-
let statusText = '
|
|
737
|
+
let statusText = `✅ ${this.getUiCopy('statusHeader')}\n\n`;
|
|
695
738
|
if (session?.workspaceId) {
|
|
696
739
|
const workspace = this.workspaceRepo.findById(session.workspaceId);
|
|
697
740
|
if (workspace) {
|
|
698
|
-
statusText +=
|
|
699
|
-
|
|
741
|
+
statusText += this.getUiCopy('workspaceCurrent', {
|
|
742
|
+
workspaceName: workspace.name,
|
|
743
|
+
workspacePath: workspace.path,
|
|
744
|
+
});
|
|
745
|
+
statusText += '\n';
|
|
700
746
|
}
|
|
701
747
|
}
|
|
702
748
|
else {
|
|
703
|
-
statusText +=
|
|
749
|
+
statusText += this.getUiCopy('statusNoWorkspace');
|
|
704
750
|
}
|
|
705
751
|
if (session?.taskId) {
|
|
706
752
|
const task = this.taskRepo.findById(session.taskId);
|
|
707
753
|
if (task) {
|
|
708
|
-
statusText += `\n
|
|
754
|
+
statusText += `\n${this.getUiCopy('statusActiveTask', { taskTitle: task.title, status: task.status })}`;
|
|
709
755
|
}
|
|
710
756
|
}
|
|
711
757
|
await adapter.sendMessage({
|
|
@@ -721,20 +767,19 @@ class MessageRouter {
|
|
|
721
767
|
if (workspaces.length === 0) {
|
|
722
768
|
await adapter.sendMessage({
|
|
723
769
|
chatId: message.chatId,
|
|
724
|
-
text: '
|
|
770
|
+
text: this.getUiCopy('workspacesNone'),
|
|
725
771
|
parseMode: 'markdown',
|
|
726
772
|
});
|
|
727
773
|
return;
|
|
728
774
|
}
|
|
729
775
|
// WhatsApp and iMessage don't support inline keyboards - use text-based selection
|
|
730
776
|
if (adapter.type === 'whatsapp' || adapter.type === 'imessage') {
|
|
731
|
-
let text = '
|
|
777
|
+
let text = `${this.getUiCopy('workspacesHeader')}\n\n`;
|
|
732
778
|
workspaces.forEach((ws, index) => {
|
|
733
779
|
text += `${index + 1}. *${ws.name}*\n \`${ws.path}\`\n\n`;
|
|
734
780
|
});
|
|
735
781
|
text += '━━━━━━━━━━━━━━━\n';
|
|
736
|
-
text += '
|
|
737
|
-
text += 'Example: `1` or `myproject`';
|
|
782
|
+
text += this.getUiCopy('workspacesFooter');
|
|
738
783
|
await adapter.sendMessage({
|
|
739
784
|
chatId: message.chatId,
|
|
740
785
|
text,
|
|
@@ -751,7 +796,7 @@ class MessageRouter {
|
|
|
751
796
|
callbackData: `workspace:${ws.id}`,
|
|
752
797
|
}]);
|
|
753
798
|
}
|
|
754
|
-
let text = '
|
|
799
|
+
let text = `${this.getUiCopy('workspacesHeader')}\n\n${this.getUiCopy('workspacesSelectPrompt')}`;
|
|
755
800
|
await adapter.sendMessage({
|
|
756
801
|
chatId: message.chatId,
|
|
757
802
|
text,
|
|
@@ -780,7 +825,10 @@ class MessageRouter {
|
|
|
780
825
|
const displayName = isTempWorkspace ? 'Temporary Workspace (work in a folder for persistence)' : workspace.name;
|
|
781
826
|
await adapter.sendMessage({
|
|
782
827
|
chatId: message.chatId,
|
|
783
|
-
text:
|
|
828
|
+
text: this.getUiCopy('workspaceCurrent', {
|
|
829
|
+
workspaceName: displayName,
|
|
830
|
+
workspacePath: workspace.path,
|
|
831
|
+
}),
|
|
784
832
|
parseMode: 'markdown',
|
|
785
833
|
});
|
|
786
834
|
return;
|
|
@@ -788,7 +836,7 @@ class MessageRouter {
|
|
|
788
836
|
}
|
|
789
837
|
await adapter.sendMessage({
|
|
790
838
|
chatId: message.chatId,
|
|
791
|
-
text:
|
|
839
|
+
text: this.getUiCopy('workspaceNoneSelected'),
|
|
792
840
|
parseMode: 'markdown',
|
|
793
841
|
});
|
|
794
842
|
return;
|
|
@@ -808,15 +856,26 @@ class MessageRouter {
|
|
|
808
856
|
if (!workspace) {
|
|
809
857
|
await adapter.sendMessage({
|
|
810
858
|
chatId: message.chatId,
|
|
811
|
-
text:
|
|
859
|
+
text: this.getUiCopy('workspaceNotFound', { selector }),
|
|
812
860
|
});
|
|
813
861
|
return;
|
|
814
862
|
}
|
|
815
863
|
// Update session workspace
|
|
816
864
|
this.sessionManager.setSessionWorkspace(sessionId, workspace.id);
|
|
865
|
+
if (workspace.id !== types_1.TEMP_WORKSPACE_ID) {
|
|
866
|
+
try {
|
|
867
|
+
this.workspaceRepo.updateLastUsedAt(workspace.id);
|
|
868
|
+
}
|
|
869
|
+
catch (error) {
|
|
870
|
+
console.warn('Failed to update workspace last used time:', error);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
817
873
|
await adapter.sendMessage({
|
|
818
874
|
chatId: message.chatId,
|
|
819
|
-
text:
|
|
875
|
+
text: this.getUiCopy('workspaceSet', {
|
|
876
|
+
workspaceName: workspace.name,
|
|
877
|
+
workspacePath: workspace.path,
|
|
878
|
+
}),
|
|
820
879
|
parseMode: 'markdown',
|
|
821
880
|
});
|
|
822
881
|
}
|
|
@@ -827,7 +886,7 @@ class MessageRouter {
|
|
|
827
886
|
if (args.length === 0) {
|
|
828
887
|
await adapter.sendMessage({
|
|
829
888
|
chatId: message.chatId,
|
|
830
|
-
text: '
|
|
889
|
+
text: this.getUiCopy('workspaceAddUsage'),
|
|
831
890
|
parseMode: 'markdown',
|
|
832
891
|
});
|
|
833
892
|
return;
|
|
@@ -847,7 +906,7 @@ class MessageRouter {
|
|
|
847
906
|
if (!stats.isDirectory()) {
|
|
848
907
|
await adapter.sendMessage({
|
|
849
908
|
chatId: message.chatId,
|
|
850
|
-
text:
|
|
909
|
+
text: this.getUiCopy('workspacePathNotDir', { workspacePath }),
|
|
851
910
|
parseMode: 'markdown',
|
|
852
911
|
});
|
|
853
912
|
return;
|
|
@@ -856,7 +915,7 @@ class MessageRouter {
|
|
|
856
915
|
catch {
|
|
857
916
|
await adapter.sendMessage({
|
|
858
917
|
chatId: message.chatId,
|
|
859
|
-
text:
|
|
918
|
+
text: this.getUiCopy('workspacePathNotFound', { workspacePath }),
|
|
860
919
|
parseMode: 'markdown',
|
|
861
920
|
});
|
|
862
921
|
return;
|
|
@@ -869,7 +928,10 @@ class MessageRouter {
|
|
|
869
928
|
this.sessionManager.setSessionWorkspace(sessionId, existing.id);
|
|
870
929
|
await adapter.sendMessage({
|
|
871
930
|
chatId: message.chatId,
|
|
872
|
-
text:
|
|
931
|
+
text: this.getUiCopy('workspaceAlreadyExists', {
|
|
932
|
+
workspaceName: existing.name,
|
|
933
|
+
workspacePath: existing.path,
|
|
934
|
+
}),
|
|
873
935
|
parseMode: 'markdown',
|
|
874
936
|
});
|
|
875
937
|
return;
|
|
@@ -897,7 +959,10 @@ class MessageRouter {
|
|
|
897
959
|
}
|
|
898
960
|
await adapter.sendMessage({
|
|
899
961
|
chatId: message.chatId,
|
|
900
|
-
text:
|
|
962
|
+
text: this.getUiCopy('workspaceAdded', {
|
|
963
|
+
workspaceName: workspace.name,
|
|
964
|
+
workspacePath: workspace.path,
|
|
965
|
+
}),
|
|
901
966
|
parseMode: 'markdown',
|
|
902
967
|
});
|
|
903
968
|
}
|
|
@@ -917,6 +982,7 @@ class MessageRouter {
|
|
|
917
982
|
'anthropic': 'Claude',
|
|
918
983
|
'bedrock': 'Claude',
|
|
919
984
|
'openai': 'OpenAI',
|
|
985
|
+
'azure': 'Azure OpenAI',
|
|
920
986
|
'gemini': 'Gemini',
|
|
921
987
|
'openrouter': 'OpenRouter',
|
|
922
988
|
'ollama': 'Ollama',
|
|
@@ -946,6 +1012,18 @@ class MessageRouter {
|
|
|
946
1012
|
}
|
|
947
1013
|
break;
|
|
948
1014
|
}
|
|
1015
|
+
case 'azure': {
|
|
1016
|
+
const deployments = (settings.azure?.deployments || []).filter(Boolean);
|
|
1017
|
+
currentModel = settings.azure?.deployment || deployments[0] || 'deployment-name';
|
|
1018
|
+
models = deployments.map((deployment) => ({
|
|
1019
|
+
key: deployment,
|
|
1020
|
+
displayName: deployment,
|
|
1021
|
+
}));
|
|
1022
|
+
if (currentModel && !models.some(m => m.key === currentModel)) {
|
|
1023
|
+
models.unshift({ key: currentModel, displayName: currentModel });
|
|
1024
|
+
}
|
|
1025
|
+
break;
|
|
1026
|
+
}
|
|
949
1027
|
case 'gemini': {
|
|
950
1028
|
currentModel = settings.gemini?.model || 'gemini-2.0-flash';
|
|
951
1029
|
const cachedGemini = provider_factory_1.LLMProviderFactory.getCachedModels('gemini');
|
|
@@ -1207,6 +1285,12 @@ class MessageRouter {
|
|
|
1207
1285
|
model: result.model.key,
|
|
1208
1286
|
};
|
|
1209
1287
|
break;
|
|
1288
|
+
case 'azure':
|
|
1289
|
+
newSettings.azure = {
|
|
1290
|
+
...settings.azure,
|
|
1291
|
+
deployment: result.model.key,
|
|
1292
|
+
};
|
|
1293
|
+
break;
|
|
1210
1294
|
case 'gemini':
|
|
1211
1295
|
newSettings.gemini = {
|
|
1212
1296
|
...settings.gemini,
|
|
@@ -1255,10 +1339,11 @@ class MessageRouter {
|
|
|
1255
1339
|
text += '*Available Providers:*\n';
|
|
1256
1340
|
text += '1. anthropic - Anthropic API (direct)\n';
|
|
1257
1341
|
text += '2. openai - OpenAI/ChatGPT\n';
|
|
1258
|
-
text += '3.
|
|
1259
|
-
text += '4.
|
|
1260
|
-
text += '5.
|
|
1261
|
-
text += '6.
|
|
1342
|
+
text += '3. azure - Azure OpenAI\n';
|
|
1343
|
+
text += '4. gemini - Google Gemini\n';
|
|
1344
|
+
text += '5. openrouter - OpenRouter\n';
|
|
1345
|
+
text += '6. bedrock - AWS Bedrock\n';
|
|
1346
|
+
text += '7. ollama - Ollama (local)\n\n';
|
|
1262
1347
|
text += '💡 Use `/provider <name>` to switch\n';
|
|
1263
1348
|
text += 'Example: `/provider bedrock` or `/provider 2`';
|
|
1264
1349
|
await adapter.sendMessage({
|
|
@@ -1277,16 +1362,19 @@ class MessageRouter {
|
|
|
1277
1362
|
'2': 'openai',
|
|
1278
1363
|
'openai': 'openai',
|
|
1279
1364
|
'chatgpt': 'openai',
|
|
1280
|
-
'3': '
|
|
1365
|
+
'3': 'azure',
|
|
1366
|
+
'azure': 'azure',
|
|
1367
|
+
'azure-openai': 'azure',
|
|
1368
|
+
'4': 'gemini',
|
|
1281
1369
|
'gemini': 'gemini',
|
|
1282
1370
|
'google': 'gemini',
|
|
1283
|
-
'
|
|
1371
|
+
'5': 'openrouter',
|
|
1284
1372
|
'openrouter': 'openrouter',
|
|
1285
1373
|
'or': 'openrouter',
|
|
1286
|
-
'
|
|
1374
|
+
'6': 'bedrock',
|
|
1287
1375
|
'bedrock': 'bedrock',
|
|
1288
1376
|
'aws': 'bedrock',
|
|
1289
|
-
'
|
|
1377
|
+
'7': 'ollama',
|
|
1290
1378
|
'ollama': 'ollama',
|
|
1291
1379
|
'local': 'ollama',
|
|
1292
1380
|
};
|
|
@@ -1294,7 +1382,7 @@ class MessageRouter {
|
|
|
1294
1382
|
if (!targetProvider) {
|
|
1295
1383
|
await adapter.sendMessage({
|
|
1296
1384
|
chatId: message.chatId,
|
|
1297
|
-
text: `❌ Unknown provider: "${args[0]}"\n\n*Available providers:*\n1. anthropic\n2. openai\n3.
|
|
1385
|
+
text: `❌ Unknown provider: "${args[0]}"\n\n*Available providers:*\n1. anthropic\n2. openai\n3. azure\n4. gemini\n5. openrouter\n6. bedrock\n7. ollama\n\nUse \`/provider <name>\` or \`/provider <number>\``,
|
|
1298
1386
|
parseMode: 'markdown',
|
|
1299
1387
|
});
|
|
1300
1388
|
return;
|
|
@@ -1337,7 +1425,7 @@ class MessageRouter {
|
|
|
1337
1425
|
if (!workspace) {
|
|
1338
1426
|
await adapter.sendMessage({
|
|
1339
1427
|
chatId: message.chatId,
|
|
1340
|
-
text:
|
|
1428
|
+
text: this.getUiCopy('workspaceNotFoundForShell'),
|
|
1341
1429
|
});
|
|
1342
1430
|
return;
|
|
1343
1431
|
}
|
|
@@ -1362,7 +1450,7 @@ class MessageRouter {
|
|
|
1362
1450
|
else {
|
|
1363
1451
|
await adapter.sendMessage({
|
|
1364
1452
|
chatId: message.chatId,
|
|
1365
|
-
text:
|
|
1453
|
+
text: this.getUiCopy('shellInvalidOption'),
|
|
1366
1454
|
parseMode: 'markdown',
|
|
1367
1455
|
});
|
|
1368
1456
|
return;
|
|
@@ -1470,7 +1558,7 @@ class MessageRouter {
|
|
|
1470
1558
|
if (result.success) {
|
|
1471
1559
|
await adapter.sendMessage({
|
|
1472
1560
|
chatId: message.chatId,
|
|
1473
|
-
text:
|
|
1561
|
+
text: this.getUiCopy('pairingSuccess'),
|
|
1474
1562
|
replyTo: message.messageId,
|
|
1475
1563
|
});
|
|
1476
1564
|
this.emitEvent({
|
|
@@ -1483,7 +1571,9 @@ class MessageRouter {
|
|
|
1483
1571
|
else {
|
|
1484
1572
|
await adapter.sendMessage({
|
|
1485
1573
|
chatId: message.chatId,
|
|
1486
|
-
text:
|
|
1574
|
+
text: this.getUiCopy('pairingFailed', {
|
|
1575
|
+
error: result.error || 'Invalid pairing code. Please try again.',
|
|
1576
|
+
}),
|
|
1487
1577
|
replyTo: message.messageId,
|
|
1488
1578
|
});
|
|
1489
1579
|
}
|
|
@@ -1512,8 +1602,8 @@ class MessageRouter {
|
|
|
1512
1602
|
if (this.agentDaemon) {
|
|
1513
1603
|
try {
|
|
1514
1604
|
const statusMsg = isActive
|
|
1515
|
-
? '💬
|
|
1516
|
-
: '💬
|
|
1605
|
+
? '💬 Got it — adding that to the current task...'
|
|
1606
|
+
: '💬 Picking up where we left off...';
|
|
1517
1607
|
await adapter.sendMessage({
|
|
1518
1608
|
chatId: message.chatId,
|
|
1519
1609
|
text: statusMsg,
|
|
@@ -1531,7 +1621,7 @@ class MessageRouter {
|
|
|
1531
1621
|
console.error('Error sending follow-up message:', error);
|
|
1532
1622
|
await adapter.sendMessage({
|
|
1533
1623
|
chatId: message.chatId,
|
|
1534
|
-
text:
|
|
1624
|
+
text: this.getUiCopy('taskContinueFailed'),
|
|
1535
1625
|
});
|
|
1536
1626
|
}
|
|
1537
1627
|
}
|
|
@@ -1545,7 +1635,7 @@ class MessageRouter {
|
|
|
1545
1635
|
if (!this.agentDaemon) {
|
|
1546
1636
|
await adapter.sendMessage({
|
|
1547
1637
|
chatId: message.chatId,
|
|
1548
|
-
text:
|
|
1638
|
+
text: this.getUiCopy('agentUnavailable'),
|
|
1549
1639
|
replyTo: message.messageId,
|
|
1550
1640
|
});
|
|
1551
1641
|
return;
|
|
@@ -1555,7 +1645,7 @@ class MessageRouter {
|
|
|
1555
1645
|
if (!workspace) {
|
|
1556
1646
|
await adapter.sendMessage({
|
|
1557
1647
|
chatId: message.chatId,
|
|
1558
|
-
text:
|
|
1648
|
+
text: this.getUiCopy('workspaceMissingForTask'),
|
|
1559
1649
|
replyTo: message.messageId,
|
|
1560
1650
|
});
|
|
1561
1651
|
return;
|
|
@@ -1585,8 +1675,8 @@ class MessageRouter {
|
|
|
1585
1675
|
}
|
|
1586
1676
|
// Send acknowledgment - concise for WhatsApp and iMessage
|
|
1587
1677
|
const ackMessage = (adapter.type === 'whatsapp' || adapter.type === 'imessage')
|
|
1588
|
-
?
|
|
1589
|
-
:
|
|
1678
|
+
? this.getUiCopy('taskStartAckSimple')
|
|
1679
|
+
: this.getUiCopy('taskStartAck', { taskTitle });
|
|
1590
1680
|
await adapter.sendMessage({
|
|
1591
1681
|
chatId: message.chatId,
|
|
1592
1682
|
text: ackMessage,
|
|
@@ -1616,7 +1706,9 @@ class MessageRouter {
|
|
|
1616
1706
|
console.error('Error starting task:', error);
|
|
1617
1707
|
await adapter.sendMessage({
|
|
1618
1708
|
chatId: message.chatId,
|
|
1619
|
-
text:
|
|
1709
|
+
text: this.getUiCopy('taskStartFailed', {
|
|
1710
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
1711
|
+
}),
|
|
1620
1712
|
});
|
|
1621
1713
|
// Cleanup
|
|
1622
1714
|
this.pendingTaskResponses.delete(task.id);
|
|
@@ -1634,6 +1726,9 @@ class MessageRouter {
|
|
|
1634
1726
|
return;
|
|
1635
1727
|
}
|
|
1636
1728
|
try {
|
|
1729
|
+
if (pending.adapter.type === 'whatsapp') {
|
|
1730
|
+
text = this.normalizeSimpleChannelMessage(text, this.getMessageContext());
|
|
1731
|
+
}
|
|
1637
1732
|
// Use draft streaming for Telegram when streaming content
|
|
1638
1733
|
if (isStreaming && pending.adapter instanceof telegram_1.TelegramAdapter) {
|
|
1639
1734
|
await pending.adapter.updateDraftStream(pending.chatId, text);
|
|
@@ -1685,6 +1780,9 @@ class MessageRouter {
|
|
|
1685
1780
|
const isSimpleMessaging = pending.adapter.type === 'whatsapp' || pending.adapter.type === 'imessage';
|
|
1686
1781
|
const msgCtx = this.getMessageContext();
|
|
1687
1782
|
const message = (0, channelMessages_1.getCompletionMessage)(msgCtx, result, !isSimpleMessaging);
|
|
1783
|
+
const normalizedMessage = pending.adapter.type === 'whatsapp'
|
|
1784
|
+
? this.normalizeSimpleChannelMessage(message, msgCtx)
|
|
1785
|
+
: message;
|
|
1688
1786
|
// Finalize draft stream if using Telegram
|
|
1689
1787
|
if (pending.adapter instanceof telegram_1.TelegramAdapter) {
|
|
1690
1788
|
// Finalize the streaming draft with final message
|
|
@@ -1697,7 +1795,7 @@ class MessageRouter {
|
|
|
1697
1795
|
else {
|
|
1698
1796
|
// Split long messages (Telegram has 4096 char limit, WhatsApp/iMessage ~65k but keep it reasonable)
|
|
1699
1797
|
const maxLen = isSimpleMessaging ? 4000 : 4000;
|
|
1700
|
-
const chunks = this.splitMessage(
|
|
1798
|
+
const chunks = this.splitMessage(normalizedMessage, maxLen);
|
|
1701
1799
|
for (const chunk of chunks) {
|
|
1702
1800
|
await pending.adapter.sendMessage({
|
|
1703
1801
|
chatId: pending.chatId,
|
|
@@ -1813,7 +1911,7 @@ class MessageRouter {
|
|
|
1813
1911
|
sessionId: pending.sessionId,
|
|
1814
1912
|
});
|
|
1815
1913
|
// Format approval message
|
|
1816
|
-
let message = `🔐
|
|
1914
|
+
let message = `🔐 *${this.getUiCopy('approvalRequiredTitle')}*\n\n`;
|
|
1817
1915
|
message += `**${approval.description}**\n\n`;
|
|
1818
1916
|
if (approval.type === 'run_command' && approval.details?.command) {
|
|
1819
1917
|
message += `\`\`\`\n${approval.details.command}\n\`\`\`\n\n`;
|
|
@@ -1840,8 +1938,8 @@ class MessageRouter {
|
|
|
1840
1938
|
// Create inline keyboard with Approve/Deny buttons for Telegram/Discord
|
|
1841
1939
|
const keyboard = [
|
|
1842
1940
|
[
|
|
1843
|
-
{ text: '
|
|
1844
|
-
{ text: '
|
|
1941
|
+
{ text: this.getUiCopy('approvalButtonApprove'), callbackData: 'approve:' + approval.id },
|
|
1942
|
+
{ text: this.getUiCopy('approvalButtonDeny'), callbackData: 'deny:' + approval.id },
|
|
1845
1943
|
],
|
|
1846
1944
|
];
|
|
1847
1945
|
try {
|
|
@@ -1867,7 +1965,7 @@ class MessageRouter {
|
|
|
1867
1965
|
if (!approvalEntry) {
|
|
1868
1966
|
await adapter.sendMessage({
|
|
1869
1967
|
chatId: message.chatId,
|
|
1870
|
-
text:
|
|
1968
|
+
text: this.getUiCopy('approvalNone'),
|
|
1871
1969
|
});
|
|
1872
1970
|
return;
|
|
1873
1971
|
}
|
|
@@ -1877,14 +1975,14 @@ class MessageRouter {
|
|
|
1877
1975
|
await this.agentDaemon?.respondToApproval(approvalId, true);
|
|
1878
1976
|
await adapter.sendMessage({
|
|
1879
1977
|
chatId: message.chatId,
|
|
1880
|
-
text: '
|
|
1978
|
+
text: this.getUiCopy('approvalApproved'),
|
|
1881
1979
|
});
|
|
1882
1980
|
}
|
|
1883
1981
|
catch (error) {
|
|
1884
1982
|
console.error('Error responding to approval:', error);
|
|
1885
1983
|
await adapter.sendMessage({
|
|
1886
1984
|
chatId: message.chatId,
|
|
1887
|
-
text:
|
|
1985
|
+
text: this.getUiCopy('approvalFailed'),
|
|
1888
1986
|
});
|
|
1889
1987
|
}
|
|
1890
1988
|
}
|
|
@@ -1898,7 +1996,7 @@ class MessageRouter {
|
|
|
1898
1996
|
if (!approvalEntry) {
|
|
1899
1997
|
await adapter.sendMessage({
|
|
1900
1998
|
chatId: message.chatId,
|
|
1901
|
-
text:
|
|
1999
|
+
text: this.getUiCopy('approvalNone'),
|
|
1902
2000
|
});
|
|
1903
2001
|
return;
|
|
1904
2002
|
}
|
|
@@ -1908,14 +2006,14 @@ class MessageRouter {
|
|
|
1908
2006
|
await this.agentDaemon?.respondToApproval(approvalId, false);
|
|
1909
2007
|
await adapter.sendMessage({
|
|
1910
2008
|
chatId: message.chatId,
|
|
1911
|
-
text:
|
|
2009
|
+
text: this.getUiCopy('approvalDenied'),
|
|
1912
2010
|
});
|
|
1913
2011
|
}
|
|
1914
2012
|
catch (error) {
|
|
1915
2013
|
console.error('Error responding to denial:', error);
|
|
1916
2014
|
await adapter.sendMessage({
|
|
1917
2015
|
chatId: message.chatId,
|
|
1918
|
-
text:
|
|
2016
|
+
text: this.getUiCopy('approvalFailed'),
|
|
1919
2017
|
});
|
|
1920
2018
|
}
|
|
1921
2019
|
}
|
|
@@ -1926,7 +2024,7 @@ class MessageRouter {
|
|
|
1926
2024
|
if (!this.agentDaemon) {
|
|
1927
2025
|
await adapter.sendMessage({
|
|
1928
2026
|
chatId: message.chatId,
|
|
1929
|
-
text:
|
|
2027
|
+
text: this.getUiCopy('agentUnavailable'),
|
|
1930
2028
|
});
|
|
1931
2029
|
return;
|
|
1932
2030
|
}
|
|
@@ -1936,7 +2034,10 @@ class MessageRouter {
|
|
|
1936
2034
|
const result = await this.agentDaemon.clearStuckTasks();
|
|
1937
2035
|
await adapter.sendMessage({
|
|
1938
2036
|
chatId: message.chatId,
|
|
1939
|
-
text:
|
|
2037
|
+
text: this.getUiCopy('queueCleared', {
|
|
2038
|
+
running: result.clearedRunning,
|
|
2039
|
+
queued: result.clearedQueued,
|
|
2040
|
+
}),
|
|
1940
2041
|
});
|
|
1941
2042
|
}
|
|
1942
2043
|
else {
|
|
@@ -1955,7 +2056,7 @@ ${status.queuedCount > 0 ? `Queued task IDs: ${status.queuedTaskIds.join(', ')}`
|
|
|
1955
2056
|
• \`/queue clear\` - Clear stuck tasks`;
|
|
1956
2057
|
await adapter.sendMessage({
|
|
1957
2058
|
chatId: message.chatId,
|
|
1958
|
-
text: statusText,
|
|
2059
|
+
text: this.getUiCopy('queueStatus', { statusText }),
|
|
1959
2060
|
parseMode: 'markdown',
|
|
1960
2061
|
});
|
|
1961
2062
|
}
|
|
@@ -2006,13 +2107,13 @@ ${status.queuedCount > 0 ? `Queued task IDs: ${status.queuedTaskIds.join(', ')}`
|
|
|
2006
2107
|
this.sessionRepo.update(sessionId, { state: 'idle', taskId: undefined });
|
|
2007
2108
|
await adapter.sendMessage({
|
|
2008
2109
|
chatId: message.chatId,
|
|
2009
|
-
text: '
|
|
2110
|
+
text: this.getUiCopy('cancelled'),
|
|
2010
2111
|
});
|
|
2011
2112
|
}
|
|
2012
2113
|
else {
|
|
2013
2114
|
await adapter.sendMessage({
|
|
2014
2115
|
chatId: message.chatId,
|
|
2015
|
-
text:
|
|
2116
|
+
text: this.getUiCopy('cancelNoActive'),
|
|
2016
2117
|
});
|
|
2017
2118
|
}
|
|
2018
2119
|
}
|
|
@@ -2028,7 +2129,7 @@ ${status.queuedCount > 0 ? `Queued task IDs: ${status.queuedTaskIds.join(', ')}`
|
|
|
2028
2129
|
}
|
|
2029
2130
|
await adapter.sendMessage({
|
|
2030
2131
|
chatId: message.chatId,
|
|
2031
|
-
text:
|
|
2132
|
+
text: this.getUiCopy('newTaskReady'),
|
|
2032
2133
|
});
|
|
2033
2134
|
}
|
|
2034
2135
|
/**
|
|
@@ -2038,7 +2139,7 @@ ${status.queuedCount > 0 ? `Queued task IDs: ${status.queuedTaskIds.join(', ')}`
|
|
|
2038
2139
|
if (args.length === 0) {
|
|
2039
2140
|
await adapter.sendMessage({
|
|
2040
2141
|
chatId: message.chatId,
|
|
2041
|
-
text: '
|
|
2142
|
+
text: this.getUiCopy('workspaceRemoveUsage'),
|
|
2042
2143
|
parseMode: 'markdown',
|
|
2043
2144
|
});
|
|
2044
2145
|
return;
|
|
@@ -2049,7 +2150,7 @@ ${status.queuedCount > 0 ? `Queued task IDs: ${status.queuedTaskIds.join(', ')}`
|
|
|
2049
2150
|
if (!workspace) {
|
|
2050
2151
|
await adapter.sendMessage({
|
|
2051
2152
|
chatId: message.chatId,
|
|
2052
|
-
text:
|
|
2153
|
+
text: this.getUiCopy('workspaceNotFound', { selector: workspaceName }),
|
|
2053
2154
|
});
|
|
2054
2155
|
return;
|
|
2055
2156
|
}
|
|
@@ -2063,7 +2164,7 @@ ${status.queuedCount > 0 ? `Queued task IDs: ${status.queuedTaskIds.join(', ')}`
|
|
|
2063
2164
|
this.workspaceRepo.delete(workspace.id);
|
|
2064
2165
|
await adapter.sendMessage({
|
|
2065
2166
|
chatId: message.chatId,
|
|
2066
|
-
text:
|
|
2167
|
+
text: this.getUiCopy('workspaceRemoved', { workspaceName: workspace.name }),
|
|
2067
2168
|
});
|
|
2068
2169
|
}
|
|
2069
2170
|
/**
|
|
@@ -2085,14 +2186,14 @@ ${status.queuedCount > 0 ? `Queued task IDs: ${status.queuedTaskIds.join(', ')}`
|
|
|
2085
2186
|
if (!lastFailedTask) {
|
|
2086
2187
|
await adapter.sendMessage({
|
|
2087
2188
|
chatId: message.chatId,
|
|
2088
|
-
text:
|
|
2189
|
+
text: this.getUiCopy('retryNone'),
|
|
2089
2190
|
});
|
|
2090
2191
|
return;
|
|
2091
2192
|
}
|
|
2092
2193
|
// Re-submit the task by sending the original prompt as a new message
|
|
2093
2194
|
await adapter.sendMessage({
|
|
2094
2195
|
chatId: message.chatId,
|
|
2095
|
-
text:
|
|
2196
|
+
text: this.getUiCopy('retrying', { taskTitle: lastFailedTask.title }),
|
|
2096
2197
|
});
|
|
2097
2198
|
// Create a synthetic message with the original prompt
|
|
2098
2199
|
const retryMessage = {
|
|
@@ -2120,7 +2221,7 @@ ${status.queuedCount > 0 ? `Queued task IDs: ${status.queuedTaskIds.join(', ')}`
|
|
|
2120
2221
|
if (recentTasks.length === 0) {
|
|
2121
2222
|
await adapter.sendMessage({
|
|
2122
2223
|
chatId: message.chatId,
|
|
2123
|
-
text:
|
|
2224
|
+
text: this.getUiCopy('historyNone'),
|
|
2124
2225
|
});
|
|
2125
2226
|
return;
|
|
2126
2227
|
}
|
|
@@ -2141,7 +2242,7 @@ ${status.queuedCount > 0 ? `Queued task IDs: ${status.queuedTaskIds.join(', ')}`
|
|
|
2141
2242
|
.join('\n\n');
|
|
2142
2243
|
await adapter.sendMessage({
|
|
2143
2244
|
chatId: message.chatId,
|
|
2144
|
-
text:
|
|
2245
|
+
text: this.getUiCopy('historyHeader', { history: historyText }),
|
|
2145
2246
|
parseMode: 'markdown',
|
|
2146
2247
|
});
|
|
2147
2248
|
}
|
|
@@ -2156,7 +2257,7 @@ ${status.queuedCount > 0 ? `Queued task IDs: ${status.queuedTaskIds.join(', ')}`
|
|
|
2156
2257
|
if (skills.length === 0) {
|
|
2157
2258
|
await adapter.sendMessage({
|
|
2158
2259
|
chatId: message.chatId,
|
|
2159
|
-
text: '
|
|
2260
|
+
text: this.getUiCopy('skillsNone'),
|
|
2160
2261
|
parseMode: 'markdown',
|
|
2161
2262
|
});
|
|
2162
2263
|
return;
|
|
@@ -2190,7 +2291,7 @@ ${status.queuedCount > 0 ? `Queued task IDs: ${status.queuedTaskIds.join(', ')}`
|
|
|
2190
2291
|
catch (error) {
|
|
2191
2292
|
await adapter.sendMessage({
|
|
2192
2293
|
chatId: message.chatId,
|
|
2193
|
-
text:
|
|
2294
|
+
text: this.getUiCopy('skillsLoadFailed'),
|
|
2194
2295
|
});
|
|
2195
2296
|
}
|
|
2196
2297
|
}
|
|
@@ -2201,7 +2302,7 @@ ${status.queuedCount > 0 ? `Queued task IDs: ${status.queuedTaskIds.join(', ')}`
|
|
|
2201
2302
|
if (args.length === 0) {
|
|
2202
2303
|
await adapter.sendMessage({
|
|
2203
2304
|
chatId: message.chatId,
|
|
2204
|
-
text:
|
|
2305
|
+
text: this.getUiCopy('skillSpecify'),
|
|
2205
2306
|
parseMode: 'markdown',
|
|
2206
2307
|
});
|
|
2207
2308
|
return;
|
|
@@ -2214,7 +2315,7 @@ ${status.queuedCount > 0 ? `Queued task IDs: ${status.queuedTaskIds.join(', ')}`
|
|
|
2214
2315
|
if (!skill) {
|
|
2215
2316
|
await adapter.sendMessage({
|
|
2216
2317
|
chatId: message.chatId,
|
|
2217
|
-
text:
|
|
2318
|
+
text: this.getUiCopy('skillNotFound', { skillId }),
|
|
2218
2319
|
});
|
|
2219
2320
|
return;
|
|
2220
2321
|
}
|
|
@@ -2224,14 +2325,18 @@ ${status.queuedCount > 0 ? `Queued task IDs: ${status.queuedTaskIds.join(', ')}`
|
|
|
2224
2325
|
const statusText = newState ? '✅ enabled' : '❌ disabled';
|
|
2225
2326
|
await adapter.sendMessage({
|
|
2226
2327
|
chatId: message.chatId,
|
|
2227
|
-
text:
|
|
2328
|
+
text: this.getUiCopy('skillToggle', {
|
|
2329
|
+
emoji: skill.icon || '⚡',
|
|
2330
|
+
skillName: skill.name,
|
|
2331
|
+
statusText,
|
|
2332
|
+
}),
|
|
2228
2333
|
parseMode: 'markdown',
|
|
2229
2334
|
});
|
|
2230
2335
|
}
|
|
2231
2336
|
catch (error) {
|
|
2232
2337
|
await adapter.sendMessage({
|
|
2233
2338
|
chatId: message.chatId,
|
|
2234
|
-
text:
|
|
2339
|
+
text: this.getUiCopy('skillsLoadFailed'),
|
|
2235
2340
|
});
|
|
2236
2341
|
}
|
|
2237
2342
|
}
|
|
@@ -2254,7 +2359,7 @@ ${status.queuedCount > 0 ? `Queued task IDs: ${status.queuedTaskIds.join(', ')}`
|
|
|
2254
2359
|
const row1 = [];
|
|
2255
2360
|
const row2 = [];
|
|
2256
2361
|
// Get configured providers for the keyboard
|
|
2257
|
-
const providerOrder = ['anthropic', 'openai', 'gemini', 'bedrock', 'openrouter', 'ollama'];
|
|
2362
|
+
const providerOrder = ['anthropic', 'openai', 'azure', 'gemini', 'bedrock', 'openrouter', 'ollama'];
|
|
2258
2363
|
for (let i = 0; i < providerOrder.length; i++) {
|
|
2259
2364
|
const provider = providerOrder[i];
|
|
2260
2365
|
const emoji = providerEmoji[provider] || '⚡';
|
|
@@ -2345,7 +2450,7 @@ ${status.queuedCount > 0 ? `Queued task IDs: ${status.queuedTaskIds.join(', ')}`
|
|
|
2345
2450
|
const statusText = newDebug ? '✅ enabled' : '❌ disabled';
|
|
2346
2451
|
await adapter.sendMessage({
|
|
2347
2452
|
chatId: message.chatId,
|
|
2348
|
-
text:
|
|
2453
|
+
text: this.getUiCopy('debugStatus', { statusText }),
|
|
2349
2454
|
});
|
|
2350
2455
|
}
|
|
2351
2456
|
/**
|
|
@@ -2383,14 +2488,14 @@ Node.js: \`${nodeVersion}\`
|
|
|
2383
2488
|
const workspace = this.workspaceRepo.findById(session.workspaceId);
|
|
2384
2489
|
await adapter.sendMessage({
|
|
2385
2490
|
chatId: message.chatId,
|
|
2386
|
-
text:
|
|
2491
|
+
text: this.getUiCopy('welcomeBack', { workspaceName: workspace?.name || 'Unknown' }),
|
|
2387
2492
|
parseMode: 'markdown',
|
|
2388
2493
|
});
|
|
2389
2494
|
}
|
|
2390
2495
|
else if (workspaces.length === 0) {
|
|
2391
2496
|
await adapter.sendMessage({
|
|
2392
2497
|
chatId: message.chatId,
|
|
2393
|
-
text:
|
|
2498
|
+
text: this.getUiCopy('welcomeNoWorkspace'),
|
|
2394
2499
|
parseMode: 'markdown',
|
|
2395
2500
|
});
|
|
2396
2501
|
}
|
|
@@ -2400,17 +2505,16 @@ Node.js: \`${nodeVersion}\`
|
|
|
2400
2505
|
this.sessionManager.setSessionWorkspace(sessionId, workspace.id);
|
|
2401
2506
|
await adapter.sendMessage({
|
|
2402
2507
|
chatId: message.chatId,
|
|
2403
|
-
text:
|
|
2508
|
+
text: this.getUiCopy('welcomeSingleWorkspace', { workspaceName: workspace.name }),
|
|
2404
2509
|
parseMode: 'markdown',
|
|
2405
2510
|
});
|
|
2406
2511
|
}
|
|
2407
2512
|
else {
|
|
2408
2513
|
// Multiple workspaces - show selection
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
});
|
|
2413
|
-
text += `\nReply with a number (e.g., \`1\`)`;
|
|
2514
|
+
const workspaceList = workspaces
|
|
2515
|
+
.map((ws, index) => `${index + 1}. *${ws.name}*`)
|
|
2516
|
+
.join('\n');
|
|
2517
|
+
const text = this.getUiCopy('welcomeSelectWorkspace', { workspaceList });
|
|
2414
2518
|
await adapter.sendMessage({
|
|
2415
2519
|
chatId: message.chatId,
|
|
2416
2520
|
text,
|
|
@@ -2422,7 +2526,7 @@ Node.js: \`${nodeVersion}\`
|
|
|
2422
2526
|
// Standard welcome for Telegram/Discord
|
|
2423
2527
|
await adapter.sendMessage({
|
|
2424
2528
|
chatId: message.chatId,
|
|
2425
|
-
text: this.
|
|
2529
|
+
text: this.getUiCopy('welcomeStandard'),
|
|
2426
2530
|
});
|
|
2427
2531
|
// Show workspaces if none selected
|
|
2428
2532
|
if (!session?.workspaceId && workspaces.length > 0) {
|
|
@@ -2435,70 +2539,10 @@ Node.js: \`${nodeVersion}\`
|
|
|
2435
2539
|
getHelpText(channelType) {
|
|
2436
2540
|
// Compact help for WhatsApp (mobile-friendly)
|
|
2437
2541
|
if (channelType === 'whatsapp') {
|
|
2438
|
-
return
|
|
2439
|
-
|
|
2440
|
-
*Basics*
|
|
2441
|
-
/workspaces - Select workspace
|
|
2442
|
-
/status - Current status
|
|
2443
|
-
/newtask - Fresh start
|
|
2444
|
-
|
|
2445
|
-
*Tasks*
|
|
2446
|
-
/cancel - Stop task
|
|
2447
|
-
/approve or /yes - Approve action
|
|
2448
|
-
/deny or /no - Reject action
|
|
2449
|
-
|
|
2450
|
-
*Settings*
|
|
2451
|
-
/shell on|off - Shell access
|
|
2452
|
-
/models - Change AI model
|
|
2453
|
-
|
|
2454
|
-
━━━━━━━━━━━━━━━
|
|
2455
|
-
💡 Just send your task directly!
|
|
2456
|
-
Example: "Add a login form"`;
|
|
2542
|
+
return this.getUiCopy('helpCompact');
|
|
2457
2543
|
}
|
|
2458
2544
|
// Full help for other channels
|
|
2459
|
-
return
|
|
2460
|
-
|
|
2461
|
-
*Core*
|
|
2462
|
-
/start - Start the bot
|
|
2463
|
-
/help - Show this help message
|
|
2464
|
-
/status - Check bot status and workspace
|
|
2465
|
-
/version - Show version information
|
|
2466
|
-
|
|
2467
|
-
*Workspaces*
|
|
2468
|
-
/workspaces - List available workspaces
|
|
2469
|
-
/workspace <name> - Select a workspace
|
|
2470
|
-
/addworkspace <path> - Add a new workspace
|
|
2471
|
-
/removeworkspace <name> - Remove a workspace
|
|
2472
|
-
|
|
2473
|
-
*Tasks*
|
|
2474
|
-
/newtask - Start a fresh task/conversation
|
|
2475
|
-
/cancel - Cancel current task
|
|
2476
|
-
/retry - Retry the last failed task
|
|
2477
|
-
/history - Show recent task history
|
|
2478
|
-
/approve - Approve pending action (or /yes, /y)
|
|
2479
|
-
/deny - Reject pending action (or /no, /n)
|
|
2480
|
-
/queue - View/clear task queue
|
|
2481
|
-
|
|
2482
|
-
*Models*
|
|
2483
|
-
/providers - List available AI providers
|
|
2484
|
-
/provider <name> - Show or change provider
|
|
2485
|
-
/models - List available AI models
|
|
2486
|
-
/model <name> - Show or change model
|
|
2487
|
-
|
|
2488
|
-
*Skills*
|
|
2489
|
-
/skills - List available skills
|
|
2490
|
-
/skill <name> - Toggle a skill on/off
|
|
2491
|
-
|
|
2492
|
-
*Settings*
|
|
2493
|
-
/settings - View current settings
|
|
2494
|
-
/shell - Enable/disable shell commands
|
|
2495
|
-
/debug - Toggle debug mode
|
|
2496
|
-
|
|
2497
|
-
💬 *Quick Start*
|
|
2498
|
-
1. \`/workspaces\` → \`/workspace <name>\`
|
|
2499
|
-
2. \`/shell on\` (if needed)
|
|
2500
|
-
3. Send your task message
|
|
2501
|
-
4. \`/newtask\` to start fresh`;
|
|
2545
|
+
return this.getUiCopy('helpFull');
|
|
2502
2546
|
}
|
|
2503
2547
|
/**
|
|
2504
2548
|
* Handle callback query from inline keyboard button press
|
|
@@ -2561,7 +2605,7 @@ Example: "Add a login form"`;
|
|
|
2561
2605
|
if (!workspace) {
|
|
2562
2606
|
await adapter.sendMessage({
|
|
2563
2607
|
chatId: query.chatId,
|
|
2564
|
-
text:
|
|
2608
|
+
text: this.getUiCopy('workspaceNotFoundShort'),
|
|
2565
2609
|
});
|
|
2566
2610
|
return;
|
|
2567
2611
|
}
|
|
@@ -2569,12 +2613,18 @@ Example: "Add a login form"`;
|
|
|
2569
2613
|
this.sessionManager.setSessionWorkspace(sessionId, workspace.id);
|
|
2570
2614
|
// Update the original message with the selection
|
|
2571
2615
|
if (adapter.editMessageWithKeyboard) {
|
|
2572
|
-
await adapter.editMessageWithKeyboard(query.chatId, query.messageId,
|
|
2616
|
+
await adapter.editMessageWithKeyboard(query.chatId, query.messageId, this.getUiCopy('workspaceSet', {
|
|
2617
|
+
workspaceName: workspace.name,
|
|
2618
|
+
workspacePath: workspace.path,
|
|
2619
|
+
}));
|
|
2573
2620
|
}
|
|
2574
2621
|
else {
|
|
2575
2622
|
await adapter.sendMessage({
|
|
2576
2623
|
chatId: query.chatId,
|
|
2577
|
-
text:
|
|
2624
|
+
text: this.getUiCopy('workspaceSet', {
|
|
2625
|
+
workspaceName: workspace.name,
|
|
2626
|
+
workspacePath: workspace.path,
|
|
2627
|
+
}),
|
|
2578
2628
|
parseMode: 'markdown',
|
|
2579
2629
|
});
|
|
2580
2630
|
}
|
|
@@ -2619,6 +2669,9 @@ Example: "Add a login form"`;
|
|
|
2619
2669
|
case 'openai':
|
|
2620
2670
|
newSettings.openai = { ...settings.openai, model: modelKey };
|
|
2621
2671
|
break;
|
|
2672
|
+
case 'azure':
|
|
2673
|
+
newSettings.azure = { ...settings.azure, deployment: modelKey };
|
|
2674
|
+
break;
|
|
2622
2675
|
case 'gemini':
|
|
2623
2676
|
newSettings.gemini = { ...settings.gemini, model: modelKey };
|
|
2624
2677
|
break;
|
|
@@ -2656,7 +2709,7 @@ Example: "Add a login form"`;
|
|
|
2656
2709
|
.find(([, data]) => data.sessionId === sessionId);
|
|
2657
2710
|
if (!approvalEntry) {
|
|
2658
2711
|
if (adapter.editMessageWithKeyboard) {
|
|
2659
|
-
await adapter.editMessageWithKeyboard(query.chatId, query.messageId,
|
|
2712
|
+
await adapter.editMessageWithKeyboard(query.chatId, query.messageId, this.getUiCopy('approvalNone'));
|
|
2660
2713
|
}
|
|
2661
2714
|
return;
|
|
2662
2715
|
}
|
|
@@ -2664,7 +2717,9 @@ Example: "Add a login form"`;
|
|
|
2664
2717
|
this.pendingApprovals.delete(approvalId);
|
|
2665
2718
|
try {
|
|
2666
2719
|
await this.agentDaemon?.respondToApproval(approvalId, approved);
|
|
2667
|
-
const statusText = approved
|
|
2720
|
+
const statusText = approved
|
|
2721
|
+
? this.getUiCopy('approvalApproved')
|
|
2722
|
+
: this.getUiCopy('approvalDenied');
|
|
2668
2723
|
if (adapter.editMessageWithKeyboard) {
|
|
2669
2724
|
await adapter.editMessageWithKeyboard(query.chatId, query.messageId, statusText);
|
|
2670
2725
|
}
|
|
@@ -2679,7 +2734,7 @@ Example: "Add a login form"`;
|
|
|
2679
2734
|
console.error('Error responding to approval:', error);
|
|
2680
2735
|
await adapter.sendMessage({
|
|
2681
2736
|
chatId: query.chatId,
|
|
2682
|
-
text:
|
|
2737
|
+
text: this.getUiCopy('responseFailed'),
|
|
2683
2738
|
});
|
|
2684
2739
|
}
|
|
2685
2740
|
}
|