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.
Files changed (252) hide show
  1. package/README.md +372 -10
  2. package/connectors/README.md +20 -0
  3. package/connectors/asana-mcp/README.md +24 -0
  4. package/connectors/asana-mcp/dist/index.js +427 -0
  5. package/connectors/asana-mcp/package.json +15 -0
  6. package/connectors/asana-mcp/src/index.ts +553 -0
  7. package/connectors/asana-mcp/tsconfig.json +13 -0
  8. package/connectors/hubspot-mcp/README.md +35 -0
  9. package/connectors/hubspot-mcp/dist/index.js +454 -0
  10. package/connectors/hubspot-mcp/package.json +15 -0
  11. package/connectors/hubspot-mcp/src/index.ts +562 -0
  12. package/connectors/hubspot-mcp/tsconfig.json +13 -0
  13. package/connectors/jira-mcp/README.md +49 -0
  14. package/connectors/jira-mcp/dist/index.js +588 -0
  15. package/connectors/jira-mcp/package.json +15 -0
  16. package/connectors/jira-mcp/src/index.ts +711 -0
  17. package/connectors/jira-mcp/tsconfig.json +13 -0
  18. package/connectors/linear-mcp/README.md +22 -0
  19. package/connectors/linear-mcp/dist/index.js +402 -0
  20. package/connectors/linear-mcp/package.json +15 -0
  21. package/connectors/linear-mcp/src/index.ts +522 -0
  22. package/connectors/linear-mcp/tsconfig.json +13 -0
  23. package/connectors/okta-mcp/README.md +24 -0
  24. package/connectors/okta-mcp/dist/index.js +411 -0
  25. package/connectors/okta-mcp/package.json +15 -0
  26. package/connectors/okta-mcp/src/index.ts +520 -0
  27. package/connectors/okta-mcp/tsconfig.json +13 -0
  28. package/connectors/salesforce-mcp/README.md +47 -0
  29. package/connectors/salesforce-mcp/dist/index.js +584 -0
  30. package/connectors/salesforce-mcp/package.json +15 -0
  31. package/connectors/salesforce-mcp/src/index.ts +722 -0
  32. package/connectors/salesforce-mcp/tsconfig.json +13 -0
  33. package/connectors/servicenow-mcp/README.md +26 -0
  34. package/connectors/servicenow-mcp/dist/index.js +400 -0
  35. package/connectors/servicenow-mcp/package.json +15 -0
  36. package/connectors/servicenow-mcp/src/index.ts +500 -0
  37. package/connectors/servicenow-mcp/tsconfig.json +13 -0
  38. package/connectors/templates/mcp-connector/README.md +31 -0
  39. package/connectors/templates/mcp-connector/package.json +15 -0
  40. package/connectors/templates/mcp-connector/src/index.ts +330 -0
  41. package/connectors/templates/mcp-connector/tsconfig.json +13 -0
  42. package/connectors/zendesk-mcp/README.md +40 -0
  43. package/connectors/zendesk-mcp/dist/index.js +431 -0
  44. package/connectors/zendesk-mcp/package.json +15 -0
  45. package/connectors/zendesk-mcp/src/index.ts +543 -0
  46. package/connectors/zendesk-mcp/tsconfig.json +13 -0
  47. package/dist/electron/electron/agent/custom-skill-loader.js +31 -1
  48. package/dist/electron/electron/agent/daemon.js +189 -13
  49. package/dist/electron/electron/agent/executor.js +895 -78
  50. package/dist/electron/electron/agent/llm/anthropic-compatible-provider.js +177 -0
  51. package/dist/electron/electron/agent/llm/azure-openai-provider.js +328 -0
  52. package/dist/electron/electron/agent/llm/bedrock-provider.js +49 -9
  53. package/dist/electron/electron/agent/llm/github-copilot-provider.js +97 -0
  54. package/dist/electron/electron/agent/llm/groq-provider.js +33 -0
  55. package/dist/electron/electron/agent/llm/index.js +13 -1
  56. package/dist/electron/electron/agent/llm/kimi-provider.js +33 -0
  57. package/dist/electron/electron/agent/llm/openai-compatible-provider.js +116 -0
  58. package/dist/electron/electron/agent/llm/openai-compatible.js +111 -0
  59. package/dist/electron/electron/agent/llm/openai-oauth.js +2 -1
  60. package/dist/electron/electron/agent/llm/openrouter-provider.js +1 -1
  61. package/dist/electron/electron/agent/llm/provider-factory.js +350 -4
  62. package/dist/electron/electron/agent/llm/types.js +66 -1
  63. package/dist/electron/electron/agent/llm/xai-provider.js +33 -0
  64. package/dist/electron/electron/agent/search/provider-factory.js +38 -2
  65. package/dist/electron/electron/agent/tools/box-tools.js +231 -0
  66. package/dist/electron/electron/agent/tools/builtin-settings.js +28 -0
  67. package/dist/electron/electron/agent/tools/dropbox-tools.js +237 -0
  68. package/dist/electron/electron/agent/tools/file-tools.js +66 -3
  69. package/dist/electron/electron/agent/tools/google-drive-tools.js +227 -0
  70. package/dist/electron/electron/agent/tools/grep-tools.js +90 -10
  71. package/dist/electron/electron/agent/tools/image-tools.js +11 -1
  72. package/dist/electron/electron/agent/tools/notion-tools.js +312 -0
  73. package/dist/electron/electron/agent/tools/onedrive-tools.js +217 -0
  74. package/dist/electron/electron/agent/tools/registry.js +548 -10
  75. package/dist/electron/electron/agent/tools/search-tools.js +28 -10
  76. package/dist/electron/electron/agent/tools/sharepoint-tools.js +243 -0
  77. package/dist/electron/electron/agent/tools/shell-tools.js +12 -3
  78. package/dist/electron/electron/agent/tools/x-tools.js +1 -1
  79. package/dist/electron/electron/agents/agent-dispatch.js +63 -0
  80. package/dist/electron/electron/database/repositories.js +19 -5
  81. package/dist/electron/electron/database/schema.js +8 -0
  82. package/dist/electron/electron/gateway/channels/whatsapp.js +55 -0
  83. package/dist/electron/electron/gateway/index.js +75 -1
  84. package/dist/electron/electron/gateway/router.js +209 -154
  85. package/dist/electron/electron/ipc/canvas-handlers.js +5 -0
  86. package/dist/electron/electron/ipc/handlers.js +763 -267
  87. package/dist/electron/electron/main.js +63 -0
  88. package/dist/electron/electron/mcp/oauth/connector-oauth.js +333 -0
  89. package/dist/electron/electron/mcp/registry/MCPRegistryManager.js +503 -154
  90. package/dist/electron/electron/memory/MemoryService.js +2 -1
  91. package/dist/electron/electron/preload.js +78 -1
  92. package/dist/electron/electron/settings/appearance-manager.js +18 -1
  93. package/dist/electron/electron/settings/box-manager.js +54 -0
  94. package/dist/electron/electron/settings/dropbox-manager.js +54 -0
  95. package/dist/electron/electron/settings/google-drive-manager.js +54 -0
  96. package/dist/electron/electron/settings/notion-manager.js +56 -0
  97. package/dist/electron/electron/settings/onedrive-manager.js +54 -0
  98. package/dist/electron/electron/settings/sharepoint-manager.js +54 -0
  99. package/dist/electron/electron/utils/box-api.js +153 -0
  100. package/dist/electron/electron/utils/dropbox-api.js +144 -0
  101. package/dist/electron/electron/utils/env-migration.js +19 -0
  102. package/dist/electron/electron/utils/google-drive-api.js +152 -0
  103. package/dist/electron/electron/utils/notion-api.js +103 -0
  104. package/dist/electron/electron/utils/onedrive-api.js +113 -0
  105. package/dist/electron/electron/utils/sharepoint-api.js +109 -0
  106. package/dist/electron/electron/utils/validation.js +98 -3
  107. package/dist/electron/electron/utils/x-cli.js +1 -1
  108. package/dist/electron/shared/channelMessages.js +284 -3
  109. package/dist/electron/shared/llm-provider-catalog.js +198 -0
  110. package/dist/electron/shared/types.js +90 -1
  111. package/package.json +14 -3
  112. package/resources/skills/nano-banana-pro.json +4 -4
  113. package/resources/skills/openai-image-gen.json +3 -3
  114. package/resources/skills/scripts/gen.py +163 -0
  115. package/resources/skills/scripts/generate_image.py +91 -0
  116. package/src/electron/agent/custom-skill-loader.ts +34 -1
  117. package/src/electron/agent/daemon.ts +210 -14
  118. package/src/electron/agent/executor.ts +1124 -85
  119. package/src/electron/agent/llm/anthropic-compatible-provider.ts +214 -0
  120. package/src/electron/agent/llm/azure-openai-provider.ts +388 -0
  121. package/src/electron/agent/llm/bedrock-provider.ts +62 -9
  122. package/src/electron/agent/llm/github-copilot-provider.ts +117 -0
  123. package/src/electron/agent/llm/groq-provider.ts +39 -0
  124. package/src/electron/agent/llm/index.ts +6 -0
  125. package/src/electron/agent/llm/kimi-provider.ts +39 -0
  126. package/src/electron/agent/llm/openai-compatible-provider.ts +153 -0
  127. package/src/electron/agent/llm/openai-compatible.ts +133 -0
  128. package/src/electron/agent/llm/openai-oauth.ts +2 -1
  129. package/src/electron/agent/llm/openrouter-provider.ts +2 -1
  130. package/src/electron/agent/llm/provider-factory.ts +459 -6
  131. package/src/electron/agent/llm/types.ts +95 -1
  132. package/src/electron/agent/llm/xai-provider.ts +39 -0
  133. package/src/electron/agent/search/provider-factory.ts +43 -2
  134. package/src/electron/agent/tools/box-tools.ts +239 -0
  135. package/src/electron/agent/tools/builtin-settings.ts +36 -0
  136. package/src/electron/agent/tools/dropbox-tools.ts +237 -0
  137. package/src/electron/agent/tools/file-tools.ts +66 -3
  138. package/src/electron/agent/tools/gmail-tools.ts +240 -0
  139. package/src/electron/agent/tools/google-calendar-tools.ts +258 -0
  140. package/src/electron/agent/tools/google-drive-tools.ts +228 -0
  141. package/src/electron/agent/tools/grep-tools.ts +97 -12
  142. package/src/electron/agent/tools/image-tools.ts +11 -1
  143. package/src/electron/agent/tools/notion-tools.ts +330 -0
  144. package/src/electron/agent/tools/onedrive-tools.ts +217 -0
  145. package/src/electron/agent/tools/registry.ts +794 -10
  146. package/src/electron/agent/tools/search-tools.ts +29 -11
  147. package/src/electron/agent/tools/sharepoint-tools.ts +247 -0
  148. package/src/electron/agent/tools/shell-tools.ts +11 -3
  149. package/src/electron/agent/tools/x-tools.ts +1 -1
  150. package/src/electron/agents/agent-dispatch.ts +79 -0
  151. package/src/electron/database/SecureSettingsRepository.ts +7 -1
  152. package/src/electron/database/repositories.ts +58 -6
  153. package/src/electron/database/schema.ts +8 -0
  154. package/src/electron/gateway/channels/discord.ts +4 -0
  155. package/src/electron/gateway/channels/google-chat.ts +3 -0
  156. package/src/electron/gateway/channels/line.ts +3 -0
  157. package/src/electron/gateway/channels/matrix-client.ts +15 -0
  158. package/src/electron/gateway/channels/matrix.ts +31 -0
  159. package/src/electron/gateway/channels/mattermost.ts +3 -0
  160. package/src/electron/gateway/channels/signal.ts +3 -0
  161. package/src/electron/gateway/channels/slack.ts +9 -4
  162. package/src/electron/gateway/channels/teams.ts +4 -0
  163. package/src/electron/gateway/channels/telegram.ts +2 -0
  164. package/src/electron/gateway/channels/twitch.ts +2 -0
  165. package/src/electron/gateway/channels/types.ts +8 -0
  166. package/src/electron/gateway/channels/whatsapp.ts +66 -0
  167. package/src/electron/gateway/index.ts +95 -2
  168. package/src/electron/gateway/router.ts +231 -161
  169. package/src/electron/gateway/security.ts +21 -9
  170. package/src/electron/ipc/canvas-handlers.ts +10 -0
  171. package/src/electron/ipc/handlers.ts +848 -292
  172. package/src/electron/main.ts +35 -0
  173. package/src/electron/mcp/oauth/connector-oauth.ts +448 -0
  174. package/src/electron/mcp/registry/MCPRegistryManager.ts +343 -12
  175. package/src/electron/memory/MemoryService.ts +7 -1
  176. package/src/electron/preload.ts +200 -5
  177. package/src/electron/settings/appearance-manager.ts +20 -2
  178. package/src/electron/settings/box-manager.ts +58 -0
  179. package/src/electron/settings/dropbox-manager.ts +58 -0
  180. package/src/electron/settings/google-workspace-manager.ts +59 -0
  181. package/src/electron/settings/notion-manager.ts +60 -0
  182. package/src/electron/settings/onedrive-manager.ts +58 -0
  183. package/src/electron/settings/sharepoint-manager.ts +58 -0
  184. package/src/electron/utils/box-api.ts +184 -0
  185. package/src/electron/utils/dropbox-api.ts +171 -0
  186. package/src/electron/utils/env-migration.ts +22 -0
  187. package/src/electron/utils/gmail-api.ts +121 -0
  188. package/src/electron/utils/google-calendar-api.ts +115 -0
  189. package/src/electron/utils/google-workspace-api.ts +228 -0
  190. package/src/electron/utils/google-workspace-auth.ts +109 -0
  191. package/src/electron/utils/google-workspace-oauth.ts +232 -0
  192. package/src/electron/utils/notion-api.ts +126 -0
  193. package/src/electron/utils/onedrive-api.ts +137 -0
  194. package/src/electron/utils/sharepoint-api.ts +132 -0
  195. package/src/electron/utils/validation.ts +128 -1
  196. package/src/electron/utils/x-cli.ts +1 -1
  197. package/src/renderer/App.tsx +119 -8
  198. package/src/renderer/components/ActivityFeedItem.tsx +34 -17
  199. package/src/renderer/components/AgentWorkingStatePanel.tsx +7 -5
  200. package/src/renderer/components/AppearanceSettings.tsx +37 -2
  201. package/src/renderer/components/BlueBubblesSettings.tsx +18 -7
  202. package/src/renderer/components/BoxSettings.tsx +203 -0
  203. package/src/renderer/components/BrowserView.tsx +101 -0
  204. package/src/renderer/components/BuiltinToolsSettings.tsx +105 -0
  205. package/src/renderer/components/CanvasPreview.tsx +68 -1
  206. package/src/renderer/components/ConnectorEnvModal.tsx +116 -0
  207. package/src/renderer/components/ConnectorSetupModal.tsx +566 -0
  208. package/src/renderer/components/ConnectorsSettings.tsx +397 -0
  209. package/src/renderer/components/ControlPlaneSettings.tsx +2 -0
  210. package/src/renderer/components/DiscordSettings.tsx +18 -7
  211. package/src/renderer/components/DropboxSettings.tsx +202 -0
  212. package/src/renderer/components/EmailSettings.tsx +18 -7
  213. package/src/renderer/components/FileViewer.tsx +21 -13
  214. package/src/renderer/components/GoogleChatSettings.tsx +17 -7
  215. package/src/renderer/components/GoogleWorkspaceSettings.tsx +332 -0
  216. package/src/renderer/components/ImessageSettings.tsx +22 -11
  217. package/src/renderer/components/LineIcons.tsx +376 -0
  218. package/src/renderer/components/LineSettings.tsx +18 -7
  219. package/src/renderer/components/MCPSettings.tsx +56 -0
  220. package/src/renderer/components/MainContent.tsx +740 -76
  221. package/src/renderer/components/MatrixSettings.tsx +18 -7
  222. package/src/renderer/components/MattermostSettings.tsx +18 -7
  223. package/src/renderer/components/NodesSettings.tsx +58 -99
  224. package/src/renderer/components/NotificationPanel.tsx +25 -11
  225. package/src/renderer/components/NotionSettings.tsx +231 -0
  226. package/src/renderer/components/Onboarding/Onboarding.tsx +13 -1
  227. package/src/renderer/components/OnboardingModal.tsx +70 -1
  228. package/src/renderer/components/OneDriveSettings.tsx +212 -0
  229. package/src/renderer/components/RightPanel.tsx +141 -28
  230. package/src/renderer/components/ScheduledTasksSettings.tsx +10 -62
  231. package/src/renderer/components/SearchSettings.tsx +118 -114
  232. package/src/renderer/components/Settings.tsx +1425 -651
  233. package/src/renderer/components/SharePointSettings.tsx +224 -0
  234. package/src/renderer/components/Sidebar.tsx +94 -19
  235. package/src/renderer/components/SignalSettings.tsx +18 -7
  236. package/src/renderer/components/SkillHubBrowser.tsx +144 -185
  237. package/src/renderer/components/SlackSettings.tsx +18 -7
  238. package/src/renderer/components/TaskQuickActions.tsx +11 -6
  239. package/src/renderer/components/TaskTimeline.tsx +58 -26
  240. package/src/renderer/components/TeamsSettings.tsx +18 -7
  241. package/src/renderer/components/TelegramSettings.tsx +18 -7
  242. package/src/renderer/components/ThemeIcon.tsx +16 -0
  243. package/src/renderer/components/TwitchSettings.tsx +18 -7
  244. package/src/renderer/components/VoiceSettings.tsx +30 -74
  245. package/src/renderer/components/WhatsAppSettings.tsx +48 -37
  246. package/src/renderer/components/WorkingStateHistory.tsx +7 -5
  247. package/src/renderer/components/WorkspaceSelector.tsx +42 -13
  248. package/src/renderer/hooks/useOnboardingFlow.ts +21 -0
  249. package/src/renderer/styles/index.css +2333 -209
  250. package/src/shared/channelMessages.ts +367 -4
  251. package/src/shared/llm-provider-catalog.ts +217 -0
  252. package/src/shared/types.ts +251 -2
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.BoxTools = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const box_manager_1 = require("../../settings/box-manager");
40
+ const box_api_1 = require("../../utils/box-api");
41
+ const DEFAULT_FOLDER_ID = '0';
42
+ class BoxTools {
43
+ constructor(workspace, daemon, taskId) {
44
+ this.workspace = workspace;
45
+ this.daemon = daemon;
46
+ this.taskId = taskId;
47
+ }
48
+ setWorkspace(workspace) {
49
+ this.workspace = workspace;
50
+ }
51
+ static isEnabled() {
52
+ return box_manager_1.BoxSettingsManager.loadSettings().enabled;
53
+ }
54
+ async requireApproval(summary, details) {
55
+ const approved = await this.daemon.requestApproval(this.taskId, 'external_service', summary, details);
56
+ if (!approved) {
57
+ throw new Error('User denied Box action');
58
+ }
59
+ }
60
+ resolveFilePath(inputPath) {
61
+ if (!this.workspace.permissions.read) {
62
+ throw new Error('Read permission not granted for uploads');
63
+ }
64
+ const workspaceRoot = path.resolve(this.workspace.path);
65
+ const allowedPaths = this.workspace.permissions.allowedPaths || [];
66
+ const canReadOutside = this.workspace.isTemp || this.workspace.permissions.unrestrictedFileAccess;
67
+ const isPathAllowed = (absolutePath) => {
68
+ if (allowedPaths.length === 0)
69
+ return false;
70
+ const normalizedPath = path.normalize(absolutePath);
71
+ return allowedPaths.some((allowed) => {
72
+ const normalizedAllowed = path.normalize(allowed);
73
+ return normalizedPath === normalizedAllowed || normalizedPath.startsWith(normalizedAllowed + path.sep);
74
+ });
75
+ };
76
+ const candidate = path.isAbsolute(inputPath)
77
+ ? path.normalize(inputPath)
78
+ : path.resolve(workspaceRoot, inputPath);
79
+ const relative = path.relative(workspaceRoot, candidate);
80
+ const isInsideWorkspace = !(relative.startsWith('..') || path.isAbsolute(relative));
81
+ if (!isInsideWorkspace && !canReadOutside && !isPathAllowed(candidate)) {
82
+ throw new Error('File path must be inside the workspace or in Allowed Paths');
83
+ }
84
+ if (!fs.existsSync(candidate)) {
85
+ throw new Error(`File not found: ${inputPath}`);
86
+ }
87
+ const stats = fs.statSync(candidate);
88
+ if (!stats.isFile()) {
89
+ throw new Error(`Path is not a file: ${inputPath}`);
90
+ }
91
+ return candidate;
92
+ }
93
+ async executeAction(input) {
94
+ const settings = box_manager_1.BoxSettingsManager.loadSettings();
95
+ if (!settings.enabled) {
96
+ throw new Error('Box integration is disabled. Enable it in Settings > Integrations > Box.');
97
+ }
98
+ const action = input.action;
99
+ if (!action) {
100
+ throw new Error('Missing required "action" parameter');
101
+ }
102
+ let result;
103
+ switch (action) {
104
+ case 'get_current_user': {
105
+ result = await (0, box_api_1.boxRequest)(settings, { method: 'GET', path: '/users/me' });
106
+ break;
107
+ }
108
+ case 'search': {
109
+ if (!input.query)
110
+ throw new Error('Missing query for search');
111
+ result = await (0, box_api_1.boxRequest)(settings, {
112
+ method: 'GET',
113
+ path: '/search',
114
+ query: {
115
+ query: input.query,
116
+ limit: input.limit,
117
+ offset: input.offset,
118
+ fields: input.fields,
119
+ type: input.type,
120
+ ancestor_folder_ids: input.ancestor_folder_ids,
121
+ file_extensions: input.file_extensions,
122
+ content_types: input.content_types,
123
+ scope: input.scope,
124
+ },
125
+ });
126
+ break;
127
+ }
128
+ case 'get_file': {
129
+ if (!input.file_id)
130
+ throw new Error('Missing file_id for get_file');
131
+ result = await (0, box_api_1.boxRequest)(settings, {
132
+ method: 'GET',
133
+ path: `/files/${input.file_id}`,
134
+ query: input.fields ? { fields: input.fields } : undefined,
135
+ });
136
+ break;
137
+ }
138
+ case 'get_folder': {
139
+ if (!input.folder_id)
140
+ throw new Error('Missing folder_id for get_folder');
141
+ result = await (0, box_api_1.boxRequest)(settings, {
142
+ method: 'GET',
143
+ path: `/folders/${input.folder_id}`,
144
+ query: input.fields ? { fields: input.fields } : undefined,
145
+ });
146
+ break;
147
+ }
148
+ case 'list_folder_items': {
149
+ const folderId = input.folder_id || DEFAULT_FOLDER_ID;
150
+ result = await (0, box_api_1.boxRequest)(settings, {
151
+ method: 'GET',
152
+ path: `/folders/${folderId}/items`,
153
+ query: {
154
+ limit: input.limit,
155
+ offset: input.offset,
156
+ fields: input.fields,
157
+ },
158
+ });
159
+ break;
160
+ }
161
+ case 'create_folder': {
162
+ if (!input.name)
163
+ throw new Error('Missing name for create_folder');
164
+ const parentId = input.parent_id || DEFAULT_FOLDER_ID;
165
+ await this.requireApproval('Create a Box folder', {
166
+ action: 'create_folder',
167
+ parent_id: parentId,
168
+ name: input.name,
169
+ });
170
+ result = await (0, box_api_1.boxRequest)(settings, {
171
+ method: 'POST',
172
+ path: '/folders',
173
+ body: {
174
+ name: input.name,
175
+ parent: { id: parentId },
176
+ },
177
+ });
178
+ break;
179
+ }
180
+ case 'delete_file': {
181
+ if (!input.file_id)
182
+ throw new Error('Missing file_id for delete_file');
183
+ await this.requireApproval('Delete a Box file', { action: 'delete_file', file_id: input.file_id });
184
+ result = await (0, box_api_1.boxRequest)(settings, { method: 'DELETE', path: `/files/${input.file_id}` });
185
+ break;
186
+ }
187
+ case 'delete_folder': {
188
+ if (!input.folder_id)
189
+ throw new Error('Missing folder_id for delete_folder');
190
+ await this.requireApproval('Delete a Box folder', { action: 'delete_folder', folder_id: input.folder_id });
191
+ result = await (0, box_api_1.boxRequest)(settings, { method: 'DELETE', path: `/folders/${input.folder_id}` });
192
+ break;
193
+ }
194
+ case 'upload_file': {
195
+ if (!input.file_path)
196
+ throw new Error('Missing file_path for upload_file');
197
+ const parentId = input.parent_id || DEFAULT_FOLDER_ID;
198
+ const resolved = this.resolveFilePath(input.file_path);
199
+ const data = fs.readFileSync(resolved);
200
+ const fileName = input.name || path.basename(resolved);
201
+ await this.requireApproval(`Upload file to Box: ${fileName}`, {
202
+ action: 'upload_file',
203
+ parent_id: parentId,
204
+ file: fileName,
205
+ });
206
+ result = await (0, box_api_1.boxUploadFile)(settings, {
207
+ fileName,
208
+ parentId,
209
+ data,
210
+ });
211
+ break;
212
+ }
213
+ default:
214
+ throw new Error(`Unsupported action: ${action}`);
215
+ }
216
+ this.daemon.logEvent(this.taskId, 'tool_result', {
217
+ tool: 'box_action',
218
+ action,
219
+ status: result?.status,
220
+ hasData: result?.data ? true : false,
221
+ });
222
+ return {
223
+ success: true,
224
+ action,
225
+ status: result?.status,
226
+ data: result?.data,
227
+ raw: result?.raw,
228
+ };
229
+ }
230
+ }
231
+ exports.BoxTools = BoxTools;
@@ -95,6 +95,8 @@ const DEFAULT_SETTINGS = {
95
95
  },
96
96
  },
97
97
  toolOverrides: {},
98
+ toolTimeouts: {},
99
+ toolAutoApprove: {},
98
100
  version: '1.0.0',
99
101
  };
100
102
  /**
@@ -107,6 +109,12 @@ const TOOL_CATEGORIES = {
107
109
  edit_file: 'code',
108
110
  // Web fetch tools (high priority)
109
111
  web_fetch: 'webfetch',
112
+ notion_action: 'webfetch',
113
+ box_action: 'webfetch',
114
+ onedrive_action: 'webfetch',
115
+ google_drive_action: 'webfetch',
116
+ dropbox_action: 'webfetch',
117
+ sharepoint_action: 'webfetch',
110
118
  // Browser tools
111
119
  browser_navigate: 'browser',
112
120
  browser_screenshot: 'browser',
@@ -276,6 +284,8 @@ class BuiltinToolsSettingsManager {
276
284
  ...settings.categories,
277
285
  },
278
286
  toolOverrides: settings.toolOverrides || {},
287
+ toolTimeouts: settings.toolTimeouts || {},
288
+ toolAutoApprove: settings.toolAutoApprove || {},
279
289
  version: settings.version || defaults.version,
280
290
  };
281
291
  }
@@ -318,6 +328,24 @@ class BuiltinToolsSettingsManager {
318
328
  static getToolCategory(toolName) {
319
329
  return TOOL_CATEGORIES[toolName] || null;
320
330
  }
331
+ /**
332
+ * Get per-tool timeout override (ms), if configured
333
+ */
334
+ static getToolTimeoutMs(toolName) {
335
+ const settings = this.loadSettings();
336
+ const timeout = settings.toolTimeouts?.[toolName];
337
+ if (typeof timeout !== 'number' || !Number.isFinite(timeout) || timeout <= 0) {
338
+ return null;
339
+ }
340
+ return Math.round(timeout);
341
+ }
342
+ /**
343
+ * Check if a tool should be auto-approved
344
+ */
345
+ static getToolAutoApprove(toolName) {
346
+ const settings = this.loadSettings();
347
+ return Boolean(settings.toolAutoApprove?.[toolName]);
348
+ }
321
349
  /**
322
350
  * Get all tool categories with their tools
323
351
  */
@@ -0,0 +1,237 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.DropboxTools = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const dropbox_manager_1 = require("../../settings/dropbox-manager");
40
+ const dropbox_api_1 = require("../../utils/dropbox-api");
41
+ class DropboxTools {
42
+ constructor(workspace, daemon, taskId) {
43
+ this.workspace = workspace;
44
+ this.daemon = daemon;
45
+ this.taskId = taskId;
46
+ }
47
+ setWorkspace(workspace) {
48
+ this.workspace = workspace;
49
+ }
50
+ static isEnabled() {
51
+ return dropbox_manager_1.DropboxSettingsManager.loadSettings().enabled;
52
+ }
53
+ async requireApproval(summary, details) {
54
+ const approved = await this.daemon.requestApproval(this.taskId, 'external_service', summary, details);
55
+ if (!approved) {
56
+ throw new Error('User denied Dropbox action');
57
+ }
58
+ }
59
+ resolveFilePath(inputPath) {
60
+ if (!this.workspace.permissions.read) {
61
+ throw new Error('Read permission not granted for uploads');
62
+ }
63
+ const workspaceRoot = path.resolve(this.workspace.path);
64
+ const allowedPaths = this.workspace.permissions.allowedPaths || [];
65
+ const canReadOutside = this.workspace.isTemp || this.workspace.permissions.unrestrictedFileAccess;
66
+ const isPathAllowed = (absolutePath) => {
67
+ if (allowedPaths.length === 0)
68
+ return false;
69
+ const normalizedPath = path.normalize(absolutePath);
70
+ return allowedPaths.some((allowed) => {
71
+ const normalizedAllowed = path.normalize(allowed);
72
+ return normalizedPath === normalizedAllowed || normalizedPath.startsWith(normalizedAllowed + path.sep);
73
+ });
74
+ };
75
+ const candidate = path.isAbsolute(inputPath)
76
+ ? path.normalize(inputPath)
77
+ : path.resolve(workspaceRoot, inputPath);
78
+ const relative = path.relative(workspaceRoot, candidate);
79
+ const isInsideWorkspace = !(relative.startsWith('..') || path.isAbsolute(relative));
80
+ if (!isInsideWorkspace && !canReadOutside && !isPathAllowed(candidate)) {
81
+ throw new Error('File path must be inside the workspace or in Allowed Paths');
82
+ }
83
+ if (!fs.existsSync(candidate)) {
84
+ throw new Error(`File not found: ${inputPath}`);
85
+ }
86
+ const stats = fs.statSync(candidate);
87
+ if (!stats.isFile()) {
88
+ throw new Error(`Path is not a file: ${inputPath}`);
89
+ }
90
+ return candidate;
91
+ }
92
+ normalizeDropboxPath(pathValue) {
93
+ const trimmed = pathValue.trim();
94
+ if (!trimmed)
95
+ return '';
96
+ return trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
97
+ }
98
+ async executeAction(input) {
99
+ const settings = dropbox_manager_1.DropboxSettingsManager.loadSettings();
100
+ if (!settings.enabled) {
101
+ throw new Error('Dropbox integration is disabled. Enable it in Settings > Integrations > Dropbox.');
102
+ }
103
+ const action = input.action;
104
+ if (!action) {
105
+ throw new Error('Missing required "action" parameter');
106
+ }
107
+ let result;
108
+ switch (action) {
109
+ case 'get_current_user': {
110
+ result = await (0, dropbox_api_1.dropboxRequest)(settings, { method: 'POST', path: '/users/get_current_account' });
111
+ break;
112
+ }
113
+ case 'list_folder': {
114
+ const pathValue = input.path ? this.normalizeDropboxPath(input.path) : '';
115
+ result = await (0, dropbox_api_1.dropboxRequest)(settings, {
116
+ method: 'POST',
117
+ path: '/files/list_folder',
118
+ body: {
119
+ path: pathValue,
120
+ recursive: false,
121
+ include_deleted: false,
122
+ include_has_explicit_shared_members: false,
123
+ include_mounted_folders: true,
124
+ limit: input.limit,
125
+ },
126
+ });
127
+ break;
128
+ }
129
+ case 'list_folder_continue': {
130
+ if (!input.cursor)
131
+ throw new Error('Missing cursor for list_folder_continue');
132
+ result = await (0, dropbox_api_1.dropboxRequest)(settings, {
133
+ method: 'POST',
134
+ path: '/files/list_folder/continue',
135
+ body: { cursor: input.cursor },
136
+ });
137
+ break;
138
+ }
139
+ case 'search': {
140
+ if (!input.query)
141
+ throw new Error('Missing query for search');
142
+ result = await (0, dropbox_api_1.dropboxRequest)(settings, {
143
+ method: 'POST',
144
+ path: '/files/search_v2',
145
+ body: {
146
+ query: input.query,
147
+ options: {
148
+ path: input.path ? this.normalizeDropboxPath(input.path) : undefined,
149
+ max_results: input.limit,
150
+ },
151
+ },
152
+ });
153
+ break;
154
+ }
155
+ case 'get_metadata': {
156
+ if (!input.path)
157
+ throw new Error('Missing path for get_metadata');
158
+ result = await (0, dropbox_api_1.dropboxRequest)(settings, {
159
+ method: 'POST',
160
+ path: '/files/get_metadata',
161
+ body: {
162
+ path: this.normalizeDropboxPath(input.path),
163
+ include_media_info: false,
164
+ include_deleted: false,
165
+ include_has_explicit_shared_members: false,
166
+ },
167
+ });
168
+ break;
169
+ }
170
+ case 'create_folder': {
171
+ if (!input.path)
172
+ throw new Error('Missing path for create_folder');
173
+ const folderPath = this.normalizeDropboxPath(input.path);
174
+ await this.requireApproval('Create a Dropbox folder', {
175
+ action: 'create_folder',
176
+ path: folderPath,
177
+ });
178
+ result = await (0, dropbox_api_1.dropboxRequest)(settings, {
179
+ method: 'POST',
180
+ path: '/files/create_folder_v2',
181
+ body: {
182
+ path: folderPath,
183
+ autorename: true,
184
+ },
185
+ });
186
+ break;
187
+ }
188
+ case 'delete_item': {
189
+ if (!input.path)
190
+ throw new Error('Missing path for delete_item');
191
+ const deletePath = this.normalizeDropboxPath(input.path);
192
+ await this.requireApproval('Delete a Dropbox item', {
193
+ action: 'delete_item',
194
+ path: deletePath,
195
+ });
196
+ result = await (0, dropbox_api_1.dropboxRequest)(settings, {
197
+ method: 'POST',
198
+ path: '/files/delete_v2',
199
+ body: { path: deletePath },
200
+ });
201
+ break;
202
+ }
203
+ case 'upload_file': {
204
+ if (!input.file_path)
205
+ throw new Error('Missing file_path for upload_file');
206
+ const resolved = this.resolveFilePath(input.file_path);
207
+ const data = fs.readFileSync(resolved);
208
+ const fileName = input.name || path.basename(resolved);
209
+ const targetPath = input.path
210
+ ? this.normalizeDropboxPath(input.path)
211
+ : this.normalizeDropboxPath(`${input.parent_path || ''}/${fileName}`);
212
+ await this.requireApproval(`Upload file to Dropbox: ${fileName}`, {
213
+ action: 'upload_file',
214
+ path: targetPath,
215
+ });
216
+ result = await (0, dropbox_api_1.dropboxContentUpload)(settings, { path: targetPath, data });
217
+ break;
218
+ }
219
+ default:
220
+ throw new Error(`Unsupported action: ${action}`);
221
+ }
222
+ this.daemon.logEvent(this.taskId, 'tool_result', {
223
+ tool: 'dropbox_action',
224
+ action,
225
+ status: result?.status,
226
+ hasData: result?.data ? true : false,
227
+ });
228
+ return {
229
+ success: true,
230
+ action,
231
+ status: result?.status,
232
+ data: result?.data,
233
+ raw: result?.raw,
234
+ };
235
+ }
236
+ }
237
+ exports.DropboxTools = DropboxTools;
@@ -168,10 +168,29 @@ class FileTools {
168
168
  throw new Error('Invalid path: path must be a non-empty string');
169
169
  }
170
170
  this.checkPermission('read');
171
- const fullPath = this.resolvePath(relativePath, 'read');
172
- const ext = path.extname(fullPath).toLowerCase();
171
+ let fullPath = this.resolvePath(relativePath, 'read');
172
+ let ext = path.extname(fullPath).toLowerCase();
173
173
  try {
174
- const stats = await fs.stat(fullPath);
174
+ let stats;
175
+ try {
176
+ stats = await fs.stat(fullPath);
177
+ }
178
+ catch (error) {
179
+ if (this.isNotFoundError(error) && !path.isAbsolute(relativePath)) {
180
+ const fallbackPath = await this.resolveCaseInsensitivePath(relativePath);
181
+ if (fallbackPath && fallbackPath !== fullPath) {
182
+ fullPath = fallbackPath;
183
+ ext = path.extname(fullPath).toLowerCase();
184
+ stats = await fs.stat(fullPath);
185
+ }
186
+ else {
187
+ throw error;
188
+ }
189
+ }
190
+ else {
191
+ throw error;
192
+ }
193
+ }
175
194
  // Handle DOCX files
176
195
  if (ext === '.docx') {
177
196
  return await this.readDocxFile(fullPath, stats.size);
@@ -209,6 +228,50 @@ class FileTools {
209
228
  throw new Error(`Failed to read file: ${error.message}`);
210
229
  }
211
230
  }
231
+ isNotFoundError(error) {
232
+ const code = error?.code;
233
+ if (code === 'ENOENT' || code === 'ENOTDIR')
234
+ return true;
235
+ const message = String(error?.message || '');
236
+ return /no such file/i.test(message) || /not found/i.test(message);
237
+ }
238
+ /**
239
+ * Try resolving a path case-insensitively within the workspace.
240
+ * Only applies to workspace-relative paths without traversal.
241
+ */
242
+ async resolveCaseInsensitivePath(relativePath) {
243
+ const normalized = path.normalize(relativePath);
244
+ if (path.isAbsolute(normalized))
245
+ return null;
246
+ const parts = normalized.split(path.sep).filter(Boolean);
247
+ if (parts.some(part => part === '..'))
248
+ return null;
249
+ let current = this.workspace.path;
250
+ for (let i = 0; i < parts.length; i++) {
251
+ const segment = parts[i];
252
+ const lower = segment.toLowerCase();
253
+ let entries;
254
+ try {
255
+ entries = await fs.readdir(current, { withFileTypes: true });
256
+ }
257
+ catch {
258
+ return null;
259
+ }
260
+ if (entries.length > MAX_DIR_ENTRIES * 5) {
261
+ return null;
262
+ }
263
+ const match = entries.find(entry => entry.name.toLowerCase() === lower);
264
+ if (!match)
265
+ return null;
266
+ const nextPath = path.join(current, match.name);
267
+ const isLast = i === parts.length - 1;
268
+ if (!isLast && !match.isDirectory()) {
269
+ return null;
270
+ }
271
+ current = nextPath;
272
+ }
273
+ return current;
274
+ }
212
275
  /**
213
276
  * Read DOCX file and extract text content
214
277
  */