cowork-os 0.3.21 → 0.3.23

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 (170) hide show
  1. package/README.md +293 -6
  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/daemon.js +25 -0
  48. package/dist/electron/electron/agent/executor.js +181 -26
  49. package/dist/electron/electron/agent/llm/anthropic-compatible-provider.js +177 -0
  50. package/dist/electron/electron/agent/llm/github-copilot-provider.js +97 -0
  51. package/dist/electron/electron/agent/llm/groq-provider.js +33 -0
  52. package/dist/electron/electron/agent/llm/index.js +11 -1
  53. package/dist/electron/electron/agent/llm/kimi-provider.js +33 -0
  54. package/dist/electron/electron/agent/llm/openai-compatible-provider.js +116 -0
  55. package/dist/electron/electron/agent/llm/openai-compatible.js +111 -0
  56. package/dist/electron/electron/agent/llm/openai-oauth.js +2 -1
  57. package/dist/electron/electron/agent/llm/openrouter-provider.js +1 -1
  58. package/dist/electron/electron/agent/llm/provider-factory.js +318 -4
  59. package/dist/electron/electron/agent/llm/types.js +66 -1
  60. package/dist/electron/electron/agent/llm/xai-provider.js +33 -0
  61. package/dist/electron/electron/agent/tools/box-tools.js +231 -0
  62. package/dist/electron/electron/agent/tools/builtin-settings.js +28 -0
  63. package/dist/electron/electron/agent/tools/dropbox-tools.js +237 -0
  64. package/dist/electron/electron/agent/tools/google-drive-tools.js +227 -0
  65. package/dist/electron/electron/agent/tools/notion-tools.js +312 -0
  66. package/dist/electron/electron/agent/tools/onedrive-tools.js +217 -0
  67. package/dist/electron/electron/agent/tools/registry.js +541 -0
  68. package/dist/electron/electron/agent/tools/sharepoint-tools.js +243 -0
  69. package/dist/electron/electron/agent/tools/shell-tools.js +12 -3
  70. package/dist/electron/electron/agent/tools/x-tools.js +1 -1
  71. package/dist/electron/electron/gateway/index.js +1 -0
  72. package/dist/electron/electron/gateway/router.js +123 -143
  73. package/dist/electron/electron/ipc/canvas-handlers.js +5 -0
  74. package/dist/electron/electron/ipc/handlers.js +627 -158
  75. package/dist/electron/electron/main.js +63 -0
  76. package/dist/electron/electron/mcp/oauth/connector-oauth.js +333 -0
  77. package/dist/electron/electron/mcp/registry/MCPRegistryManager.js +503 -154
  78. package/dist/electron/electron/memory/MemoryService.js +1 -1
  79. package/dist/electron/electron/preload.js +74 -1
  80. package/dist/electron/electron/settings/box-manager.js +54 -0
  81. package/dist/electron/electron/settings/dropbox-manager.js +54 -0
  82. package/dist/electron/electron/settings/google-drive-manager.js +54 -0
  83. package/dist/electron/electron/settings/notion-manager.js +56 -0
  84. package/dist/electron/electron/settings/onedrive-manager.js +54 -0
  85. package/dist/electron/electron/settings/sharepoint-manager.js +54 -0
  86. package/dist/electron/electron/utils/box-api.js +153 -0
  87. package/dist/electron/electron/utils/dropbox-api.js +144 -0
  88. package/dist/electron/electron/utils/env-migration.js +19 -0
  89. package/dist/electron/electron/utils/google-drive-api.js +152 -0
  90. package/dist/electron/electron/utils/notion-api.js +103 -0
  91. package/dist/electron/electron/utils/onedrive-api.js +113 -0
  92. package/dist/electron/electron/utils/sharepoint-api.js +109 -0
  93. package/dist/electron/electron/utils/validation.js +82 -3
  94. package/dist/electron/electron/utils/x-cli.js +1 -1
  95. package/dist/electron/shared/channelMessages.js +284 -3
  96. package/dist/electron/shared/llm-provider-catalog.js +198 -0
  97. package/dist/electron/shared/types.js +88 -1
  98. package/package.json +12 -2
  99. package/src/electron/agent/executor.ts +205 -28
  100. package/src/electron/agent/llm/anthropic-compatible-provider.ts +214 -0
  101. package/src/electron/agent/llm/github-copilot-provider.ts +117 -0
  102. package/src/electron/agent/llm/groq-provider.ts +39 -0
  103. package/src/electron/agent/llm/index.ts +5 -0
  104. package/src/electron/agent/llm/kimi-provider.ts +39 -0
  105. package/src/electron/agent/llm/openai-compatible-provider.ts +153 -0
  106. package/src/electron/agent/llm/openai-compatible.ts +133 -0
  107. package/src/electron/agent/llm/openai-oauth.ts +2 -1
  108. package/src/electron/agent/llm/openrouter-provider.ts +2 -1
  109. package/src/electron/agent/llm/provider-factory.ts +414 -6
  110. package/src/electron/agent/llm/types.ts +90 -1
  111. package/src/electron/agent/llm/xai-provider.ts +39 -0
  112. package/src/electron/agent/tools/box-tools.ts +239 -0
  113. package/src/electron/agent/tools/builtin-settings.ts +34 -0
  114. package/src/electron/agent/tools/dropbox-tools.ts +237 -0
  115. package/src/electron/agent/tools/google-drive-tools.ts +228 -0
  116. package/src/electron/agent/tools/notion-tools.ts +330 -0
  117. package/src/electron/agent/tools/onedrive-tools.ts +217 -0
  118. package/src/electron/agent/tools/registry.ts +565 -0
  119. package/src/electron/agent/tools/sharepoint-tools.ts +247 -0
  120. package/src/electron/agent/tools/shell-tools.ts +11 -3
  121. package/src/electron/agent/tools/x-tools.ts +1 -1
  122. package/src/electron/database/SecureSettingsRepository.ts +7 -1
  123. package/src/electron/gateway/index.ts +1 -0
  124. package/src/electron/gateway/router.ts +134 -149
  125. package/src/electron/ipc/canvas-handlers.ts +10 -0
  126. package/src/electron/ipc/handlers.ts +673 -153
  127. package/src/electron/main.ts +35 -0
  128. package/src/electron/mcp/oauth/connector-oauth.ts +448 -0
  129. package/src/electron/mcp/registry/MCPRegistryManager.ts +343 -12
  130. package/src/electron/memory/MemoryService.ts +5 -1
  131. package/src/electron/preload.ts +167 -4
  132. package/src/electron/settings/box-manager.ts +58 -0
  133. package/src/electron/settings/dropbox-manager.ts +58 -0
  134. package/src/electron/settings/google-drive-manager.ts +58 -0
  135. package/src/electron/settings/notion-manager.ts +60 -0
  136. package/src/electron/settings/onedrive-manager.ts +58 -0
  137. package/src/electron/settings/sharepoint-manager.ts +58 -0
  138. package/src/electron/utils/box-api.ts +184 -0
  139. package/src/electron/utils/dropbox-api.ts +171 -0
  140. package/src/electron/utils/env-migration.ts +22 -0
  141. package/src/electron/utils/google-drive-api.ts +183 -0
  142. package/src/electron/utils/notion-api.ts +126 -0
  143. package/src/electron/utils/onedrive-api.ts +137 -0
  144. package/src/electron/utils/sharepoint-api.ts +132 -0
  145. package/src/electron/utils/validation.ts +102 -1
  146. package/src/electron/utils/x-cli.ts +1 -1
  147. package/src/renderer/App.tsx +20 -2
  148. package/src/renderer/components/BoxSettings.tsx +203 -0
  149. package/src/renderer/components/BrowserView.tsx +101 -0
  150. package/src/renderer/components/BuiltinToolsSettings.tsx +105 -0
  151. package/src/renderer/components/CanvasPreview.tsx +68 -1
  152. package/src/renderer/components/ConnectorEnvModal.tsx +116 -0
  153. package/src/renderer/components/ConnectorSetupModal.tsx +566 -0
  154. package/src/renderer/components/ConnectorsSettings.tsx +397 -0
  155. package/src/renderer/components/DropboxSettings.tsx +202 -0
  156. package/src/renderer/components/GoogleDriveSettings.tsx +201 -0
  157. package/src/renderer/components/MCPSettings.tsx +56 -0
  158. package/src/renderer/components/MainContent.tsx +270 -34
  159. package/src/renderer/components/NotionSettings.tsx +231 -0
  160. package/src/renderer/components/Onboarding/Onboarding.tsx +13 -1
  161. package/src/renderer/components/OnboardingModal.tsx +70 -1
  162. package/src/renderer/components/OneDriveSettings.tsx +212 -0
  163. package/src/renderer/components/Settings.tsx +611 -8
  164. package/src/renderer/components/SharePointSettings.tsx +224 -0
  165. package/src/renderer/components/Sidebar.tsx +25 -9
  166. package/src/renderer/hooks/useOnboardingFlow.ts +21 -0
  167. package/src/renderer/styles/index.css +438 -25
  168. package/src/shared/channelMessages.ts +367 -4
  169. package/src/shared/llm-provider-catalog.ts +217 -0
  170. package/src/shared/types.ts +226 -1
@@ -0,0 +1,227 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.GoogleDriveTools = void 0;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const mime_types_1 = __importDefault(require("mime-types"));
43
+ const google_drive_manager_1 = require("../../settings/google-drive-manager");
44
+ const google_drive_api_1 = require("../../utils/google-drive-api");
45
+ const DEFAULT_LIST_FIELDS = 'nextPageToken, files(id,name,mimeType,modifiedTime,parents,webViewLink,size)';
46
+ const DEFAULT_FILE_FIELDS = 'id,name,mimeType,modifiedTime,parents,webViewLink,size';
47
+ class GoogleDriveTools {
48
+ constructor(workspace, daemon, taskId) {
49
+ this.workspace = workspace;
50
+ this.daemon = daemon;
51
+ this.taskId = taskId;
52
+ }
53
+ setWorkspace(workspace) {
54
+ this.workspace = workspace;
55
+ }
56
+ static isEnabled() {
57
+ return google_drive_manager_1.GoogleDriveSettingsManager.loadSettings().enabled;
58
+ }
59
+ async requireApproval(summary, details) {
60
+ const approved = await this.daemon.requestApproval(this.taskId, 'external_service', summary, details);
61
+ if (!approved) {
62
+ throw new Error('User denied Google Drive action');
63
+ }
64
+ }
65
+ resolveFilePath(inputPath) {
66
+ if (!this.workspace.permissions.read) {
67
+ throw new Error('Read permission not granted for uploads');
68
+ }
69
+ const workspaceRoot = path.resolve(this.workspace.path);
70
+ const allowedPaths = this.workspace.permissions.allowedPaths || [];
71
+ const canReadOutside = this.workspace.isTemp || this.workspace.permissions.unrestrictedFileAccess;
72
+ const isPathAllowed = (absolutePath) => {
73
+ if (allowedPaths.length === 0)
74
+ return false;
75
+ const normalizedPath = path.normalize(absolutePath);
76
+ return allowedPaths.some((allowed) => {
77
+ const normalizedAllowed = path.normalize(allowed);
78
+ return normalizedPath === normalizedAllowed || normalizedPath.startsWith(normalizedAllowed + path.sep);
79
+ });
80
+ };
81
+ const candidate = path.isAbsolute(inputPath)
82
+ ? path.normalize(inputPath)
83
+ : path.resolve(workspaceRoot, inputPath);
84
+ const relative = path.relative(workspaceRoot, candidate);
85
+ const isInsideWorkspace = !(relative.startsWith('..') || path.isAbsolute(relative));
86
+ if (!isInsideWorkspace && !canReadOutside && !isPathAllowed(candidate)) {
87
+ throw new Error('File path must be inside the workspace or in Allowed Paths');
88
+ }
89
+ if (!fs.existsSync(candidate)) {
90
+ throw new Error(`File not found: ${inputPath}`);
91
+ }
92
+ const stats = fs.statSync(candidate);
93
+ if (!stats.isFile()) {
94
+ throw new Error(`Path is not a file: ${inputPath}`);
95
+ }
96
+ return candidate;
97
+ }
98
+ async executeAction(input) {
99
+ const settings = google_drive_manager_1.GoogleDriveSettingsManager.loadSettings();
100
+ if (!settings.enabled) {
101
+ throw new Error('Google Drive integration is disabled. Enable it in Settings > Integrations > Google Drive.');
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, google_drive_api_1.googleDriveRequest)(settings, {
111
+ method: 'GET',
112
+ path: '/about',
113
+ query: { fields: 'user' },
114
+ });
115
+ break;
116
+ }
117
+ case 'list_files': {
118
+ const query = input.query || 'trashed = false';
119
+ result = await (0, google_drive_api_1.googleDriveRequest)(settings, {
120
+ method: 'GET',
121
+ path: '/files',
122
+ query: {
123
+ q: query,
124
+ pageSize: input.page_size,
125
+ pageToken: input.page_token,
126
+ fields: input.fields || DEFAULT_LIST_FIELDS,
127
+ },
128
+ });
129
+ break;
130
+ }
131
+ case 'get_file': {
132
+ if (!input.file_id)
133
+ throw new Error('Missing file_id for get_file');
134
+ result = await (0, google_drive_api_1.googleDriveRequest)(settings, {
135
+ method: 'GET',
136
+ path: `/files/${input.file_id}`,
137
+ query: {
138
+ fields: input.fields || DEFAULT_FILE_FIELDS,
139
+ },
140
+ });
141
+ break;
142
+ }
143
+ case 'create_folder': {
144
+ if (!input.name)
145
+ throw new Error('Missing name for create_folder');
146
+ await this.requireApproval('Create a Google Drive folder', {
147
+ action: 'create_folder',
148
+ parent_id: input.parent_id || 'root',
149
+ name: input.name,
150
+ });
151
+ result = await (0, google_drive_api_1.googleDriveRequest)(settings, {
152
+ method: 'POST',
153
+ path: '/files',
154
+ query: { fields: DEFAULT_FILE_FIELDS },
155
+ body: {
156
+ name: input.name,
157
+ mimeType: 'application/vnd.google-apps.folder',
158
+ parents: input.parent_id ? [input.parent_id] : undefined,
159
+ },
160
+ });
161
+ break;
162
+ }
163
+ case 'upload_file': {
164
+ if (!input.file_path)
165
+ throw new Error('Missing file_path for upload_file');
166
+ const resolved = this.resolveFilePath(input.file_path);
167
+ const data = fs.readFileSync(resolved);
168
+ const fileName = input.name || path.basename(resolved);
169
+ const contentType = (mime_types_1.default.lookup(fileName) || 'application/octet-stream');
170
+ await this.requireApproval(`Upload file to Google Drive: ${fileName}`, {
171
+ action: 'upload_file',
172
+ parent_id: input.parent_id || 'root',
173
+ file: fileName,
174
+ });
175
+ const created = await (0, google_drive_api_1.googleDriveRequest)(settings, {
176
+ method: 'POST',
177
+ path: '/files',
178
+ query: { fields: DEFAULT_FILE_FIELDS },
179
+ body: {
180
+ name: fileName,
181
+ parents: input.parent_id ? [input.parent_id] : undefined,
182
+ },
183
+ });
184
+ const fileId = created.data?.id;
185
+ if (!fileId) {
186
+ throw new Error('Failed to create Google Drive file record');
187
+ }
188
+ const uploaded = await (0, google_drive_api_1.googleDriveUpload)(settings, fileId, data, contentType);
189
+ result = {
190
+ status: uploaded.status,
191
+ data: uploaded.data || created.data,
192
+ raw: uploaded.raw,
193
+ };
194
+ break;
195
+ }
196
+ case 'delete_file': {
197
+ if (!input.file_id)
198
+ throw new Error('Missing file_id for delete_file');
199
+ await this.requireApproval('Delete a Google Drive file', {
200
+ action: 'delete_file',
201
+ file_id: input.file_id,
202
+ });
203
+ result = await (0, google_drive_api_1.googleDriveRequest)(settings, {
204
+ method: 'DELETE',
205
+ path: `/files/${input.file_id}`,
206
+ });
207
+ break;
208
+ }
209
+ default:
210
+ throw new Error(`Unsupported action: ${action}`);
211
+ }
212
+ this.daemon.logEvent(this.taskId, 'tool_result', {
213
+ tool: 'google_drive_action',
214
+ action,
215
+ status: result?.status,
216
+ hasData: result?.data ? true : false,
217
+ });
218
+ return {
219
+ success: true,
220
+ action,
221
+ status: result?.status,
222
+ data: result?.data,
223
+ raw: result?.raw,
224
+ };
225
+ }
226
+ }
227
+ exports.GoogleDriveTools = GoogleDriveTools;
@@ -0,0 +1,312 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NotionTools = void 0;
4
+ const notion_manager_1 = require("../../settings/notion-manager");
5
+ const notion_api_1 = require("../../utils/notion-api");
6
+ class NotionTools {
7
+ constructor(workspace, daemon, taskId) {
8
+ this.workspace = workspace;
9
+ this.daemon = daemon;
10
+ this.taskId = taskId;
11
+ }
12
+ setWorkspace(workspace) {
13
+ this.workspace = workspace;
14
+ }
15
+ static isEnabled() {
16
+ return notion_manager_1.NotionSettingsManager.loadSettings().enabled;
17
+ }
18
+ async requireApproval(summary, details) {
19
+ const approved = await this.daemon.requestApproval(this.taskId, 'external_service', summary, details);
20
+ if (!approved) {
21
+ throw new Error('User denied Notion action');
22
+ }
23
+ }
24
+ buildPagination(input) {
25
+ const body = {};
26
+ if (input.start_cursor)
27
+ body.start_cursor = input.start_cursor;
28
+ if (typeof input.page_size === 'number')
29
+ body.page_size = input.page_size;
30
+ return body;
31
+ }
32
+ buildTitle(title) {
33
+ if (!title)
34
+ return undefined;
35
+ const trimmed = title.trim();
36
+ if (!trimmed)
37
+ return undefined;
38
+ return [{ text: { content: trimmed } }];
39
+ }
40
+ buildParent(input) {
41
+ if (input.database_id) {
42
+ return { database_id: input.database_id };
43
+ }
44
+ if (input.parent_page_id) {
45
+ return { page_id: input.parent_page_id };
46
+ }
47
+ throw new Error('Missing parent identifier (database_id or parent_page_id)');
48
+ }
49
+ async executeAction(input) {
50
+ const settings = notion_manager_1.NotionSettingsManager.loadSettings();
51
+ if (!settings.enabled) {
52
+ throw new Error('Notion integration is disabled. Enable it in Settings > Integrations > Notion.');
53
+ }
54
+ const action = input.action;
55
+ if (!action) {
56
+ throw new Error('Missing required "action" parameter');
57
+ }
58
+ let result;
59
+ switch (action) {
60
+ case 'search': {
61
+ const body = input.payload ? { ...input.payload } : {};
62
+ if (!input.payload) {
63
+ if (input.query)
64
+ body.query = input.query;
65
+ if (input.filter)
66
+ body.filter = input.filter;
67
+ if (input.sort)
68
+ body.sort = input.sort;
69
+ else if (input.sorts)
70
+ body.sort = input.sorts;
71
+ Object.assign(body, this.buildPagination(input));
72
+ }
73
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'POST', path: '/search', body });
74
+ break;
75
+ }
76
+ case 'list_users': {
77
+ const params = new URLSearchParams();
78
+ if (input.start_cursor)
79
+ params.set('start_cursor', input.start_cursor);
80
+ if (typeof input.page_size === 'number')
81
+ params.set('page_size', String(input.page_size));
82
+ const suffix = params.toString() ? `?${params.toString()}` : '';
83
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'GET', path: `/users${suffix}` });
84
+ break;
85
+ }
86
+ case 'get_user': {
87
+ if (!input.user_id)
88
+ throw new Error('Missing user_id for get_user');
89
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'GET', path: `/users/${input.user_id}` });
90
+ break;
91
+ }
92
+ case 'get_page': {
93
+ if (!input.page_id)
94
+ throw new Error('Missing page_id for get_page');
95
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'GET', path: `/pages/${input.page_id}` });
96
+ break;
97
+ }
98
+ case 'get_page_property': {
99
+ if (!input.page_id)
100
+ throw new Error('Missing page_id for get_page_property');
101
+ if (!input.property_id)
102
+ throw new Error('Missing property_id for get_page_property');
103
+ const params = new URLSearchParams();
104
+ if (input.start_cursor)
105
+ params.set('start_cursor', input.start_cursor);
106
+ if (typeof input.page_size === 'number')
107
+ params.set('page_size', String(input.page_size));
108
+ const suffix = params.toString() ? `?${params.toString()}` : '';
109
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'GET', path: `/pages/${input.page_id}/properties/${input.property_id}${suffix}` });
110
+ break;
111
+ }
112
+ case 'get_database': {
113
+ if (!input.database_id)
114
+ throw new Error('Missing database_id for get_database');
115
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'GET', path: `/databases/${input.database_id}` });
116
+ break;
117
+ }
118
+ case 'get_block': {
119
+ if (!input.block_id)
120
+ throw new Error('Missing block_id for get_block');
121
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'GET', path: `/blocks/${input.block_id}` });
122
+ break;
123
+ }
124
+ case 'get_block_children': {
125
+ if (!input.block_id)
126
+ throw new Error('Missing block_id for get_block_children');
127
+ const params = new URLSearchParams();
128
+ if (input.start_cursor)
129
+ params.set('start_cursor', input.start_cursor);
130
+ if (typeof input.page_size === 'number')
131
+ params.set('page_size', String(input.page_size));
132
+ const suffix = params.toString() ? `?${params.toString()}` : '';
133
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'GET', path: `/blocks/${input.block_id}/children${suffix}` });
134
+ break;
135
+ }
136
+ case 'update_block': {
137
+ if (!input.block_id)
138
+ throw new Error('Missing block_id for update_block');
139
+ const body = input.payload ? { ...input.payload } : {};
140
+ if (!input.payload) {
141
+ if (typeof input.archived === 'boolean')
142
+ body.archived = input.archived;
143
+ if (input.block_type && input.block) {
144
+ body[input.block_type] = input.block;
145
+ }
146
+ if (Object.keys(body).length === 0) {
147
+ throw new Error('Missing update payload (archived or block content)');
148
+ }
149
+ }
150
+ await this.requireApproval('Update a Notion block', {
151
+ action: 'update_block',
152
+ block_id: input.block_id,
153
+ });
154
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'PATCH', path: `/blocks/${input.block_id}`, body });
155
+ break;
156
+ }
157
+ case 'delete_block': {
158
+ if (!input.block_id)
159
+ throw new Error('Missing block_id for delete_block');
160
+ await this.requireApproval('Delete a Notion block', {
161
+ action: 'delete_block',
162
+ block_id: input.block_id,
163
+ });
164
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'DELETE', path: `/blocks/${input.block_id}` });
165
+ break;
166
+ }
167
+ case 'get_data_source': {
168
+ if (!input.data_source_id)
169
+ throw new Error('Missing data_source_id for get_data_source');
170
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'GET', path: `/data_sources/${input.data_source_id}` });
171
+ break;
172
+ }
173
+ case 'query_data_source': {
174
+ if (!input.data_source_id)
175
+ throw new Error('Missing data_source_id for query_data_source');
176
+ const body = input.payload ? { ...input.payload } : {};
177
+ if (!input.payload) {
178
+ if (input.filter)
179
+ body.filter = input.filter;
180
+ if (input.sorts)
181
+ body.sorts = input.sorts;
182
+ Object.assign(body, this.buildPagination(input));
183
+ }
184
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'POST', path: `/data_sources/${input.data_source_id}/query`, body });
185
+ break;
186
+ }
187
+ case 'create_page': {
188
+ const body = input.payload ? { ...input.payload } : {};
189
+ if (!input.payload) {
190
+ body.parent = this.buildParent(input);
191
+ if (!input.properties)
192
+ throw new Error('Missing properties for create_page');
193
+ body.properties = input.properties;
194
+ if (input.children)
195
+ body.children = input.children;
196
+ if (input.icon)
197
+ body.icon = input.icon;
198
+ if (input.cover)
199
+ body.cover = input.cover;
200
+ }
201
+ await this.requireApproval('Create a Notion page', {
202
+ action: 'create_page',
203
+ parent: body.parent,
204
+ });
205
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'POST', path: '/pages', body });
206
+ break;
207
+ }
208
+ case 'update_page': {
209
+ if (!input.page_id)
210
+ throw new Error('Missing page_id for update_page');
211
+ const body = input.payload ? { ...input.payload } : {};
212
+ if (!input.payload) {
213
+ if (input.properties)
214
+ body.properties = input.properties;
215
+ if (typeof input.archived === 'boolean')
216
+ body.archived = input.archived;
217
+ if (input.icon)
218
+ body.icon = input.icon;
219
+ if (input.cover)
220
+ body.cover = input.cover;
221
+ if (Object.keys(body).length === 0) {
222
+ throw new Error('Missing update payload (properties, archived, icon, or cover)');
223
+ }
224
+ }
225
+ await this.requireApproval('Update a Notion page', {
226
+ action: 'update_page',
227
+ page_id: input.page_id,
228
+ });
229
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'PATCH', path: `/pages/${input.page_id}`, body });
230
+ break;
231
+ }
232
+ case 'append_blocks': {
233
+ if (!input.block_id)
234
+ throw new Error('Missing block_id for append_blocks');
235
+ const body = input.payload ? { ...input.payload } : {};
236
+ if (!input.payload) {
237
+ if (!input.children || input.children.length === 0) {
238
+ throw new Error('Missing children for append_blocks');
239
+ }
240
+ body.children = input.children;
241
+ }
242
+ await this.requireApproval('Append blocks in Notion', {
243
+ action: 'append_blocks',
244
+ block_id: input.block_id,
245
+ count: Array.isArray(body.children) ? body.children.length : undefined,
246
+ });
247
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'PATCH', path: `/blocks/${input.block_id}/children`, body });
248
+ break;
249
+ }
250
+ case 'create_data_source': {
251
+ const body = input.payload ? { ...input.payload } : {};
252
+ if (!input.payload) {
253
+ if (!input.parent_page_id)
254
+ throw new Error('Missing parent_page_id for create_data_source');
255
+ if (!input.properties)
256
+ throw new Error('Missing properties for create_data_source');
257
+ const title = this.buildTitle(input.title);
258
+ if (!title)
259
+ throw new Error('Missing title for create_data_source');
260
+ body.parent = { page_id: input.parent_page_id };
261
+ body.title = title;
262
+ body.properties = input.properties;
263
+ if (typeof input.is_inline === 'boolean')
264
+ body.is_inline = input.is_inline;
265
+ }
266
+ await this.requireApproval('Create a Notion data source', {
267
+ action: 'create_data_source',
268
+ parent: body.parent,
269
+ });
270
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'POST', path: '/data_sources', body });
271
+ break;
272
+ }
273
+ case 'update_data_source': {
274
+ if (!input.data_source_id)
275
+ throw new Error('Missing data_source_id for update_data_source');
276
+ const body = input.payload ? { ...input.payload } : {};
277
+ if (!input.payload) {
278
+ if (input.properties)
279
+ body.properties = input.properties;
280
+ const title = this.buildTitle(input.title);
281
+ if (title)
282
+ body.title = title;
283
+ if (Object.keys(body).length === 0) {
284
+ throw new Error('Missing update payload (properties or title)');
285
+ }
286
+ }
287
+ await this.requireApproval('Update a Notion data source', {
288
+ action: 'update_data_source',
289
+ data_source_id: input.data_source_id,
290
+ });
291
+ result = await (0, notion_api_1.notionRequest)(settings, { method: 'PATCH', path: `/data_sources/${input.data_source_id}`, body });
292
+ break;
293
+ }
294
+ default:
295
+ throw new Error(`Unsupported action: ${action}`);
296
+ }
297
+ this.daemon.logEvent(this.taskId, 'tool_result', {
298
+ tool: 'notion_action',
299
+ action,
300
+ status: result?.status,
301
+ hasData: !!result?.data,
302
+ });
303
+ return {
304
+ success: true,
305
+ action,
306
+ status: result?.status,
307
+ data: result?.data,
308
+ raw: result?.raw,
309
+ };
310
+ }
311
+ }
312
+ exports.NotionTools = NotionTools;