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.
- package/README.md +293 -6
- 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/daemon.js +25 -0
- package/dist/electron/electron/agent/executor.js +181 -26
- package/dist/electron/electron/agent/llm/anthropic-compatible-provider.js +177 -0
- 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 +11 -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 +318 -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/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/google-drive-tools.js +227 -0
- 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 +541 -0
- 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/gateway/index.js +1 -0
- package/dist/electron/electron/gateway/router.js +123 -143
- package/dist/electron/electron/ipc/canvas-handlers.js +5 -0
- package/dist/electron/electron/ipc/handlers.js +627 -158
- 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 +1 -1
- package/dist/electron/electron/preload.js +74 -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 +82 -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 +88 -1
- package/package.json +12 -2
- package/src/electron/agent/executor.ts +205 -28
- package/src/electron/agent/llm/anthropic-compatible-provider.ts +214 -0
- 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 +5 -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 +414 -6
- package/src/electron/agent/llm/types.ts +90 -1
- package/src/electron/agent/llm/xai-provider.ts +39 -0
- package/src/electron/agent/tools/box-tools.ts +239 -0
- package/src/electron/agent/tools/builtin-settings.ts +34 -0
- package/src/electron/agent/tools/dropbox-tools.ts +237 -0
- package/src/electron/agent/tools/google-drive-tools.ts +228 -0
- 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 +565 -0
- 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/database/SecureSettingsRepository.ts +7 -1
- package/src/electron/gateway/index.ts +1 -0
- package/src/electron/gateway/router.ts +134 -149
- package/src/electron/ipc/canvas-handlers.ts +10 -0
- package/src/electron/ipc/handlers.ts +673 -153
- 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 +5 -1
- package/src/electron/preload.ts +167 -4
- package/src/electron/settings/box-manager.ts +58 -0
- package/src/electron/settings/dropbox-manager.ts +58 -0
- package/src/electron/settings/google-drive-manager.ts +58 -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/google-drive-api.ts +183 -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 +102 -1
- package/src/electron/utils/x-cli.ts +1 -1
- package/src/renderer/App.tsx +20 -2
- 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/DropboxSettings.tsx +202 -0
- package/src/renderer/components/GoogleDriveSettings.tsx +201 -0
- package/src/renderer/components/MCPSettings.tsx +56 -0
- package/src/renderer/components/MainContent.tsx +270 -34
- 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/Settings.tsx +611 -8
- package/src/renderer/components/SharePointSettings.tsx +224 -0
- package/src/renderer/components/Sidebar.tsx +25 -9
- package/src/renderer/hooks/useOnboardingFlow.ts +21 -0
- package/src/renderer/styles/index.css +438 -25
- package/src/shared/channelMessages.ts +367 -4
- package/src/shared/llm-provider-catalog.ts +217 -0
- package/src/shared/types.ts +226 -1
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { Workspace } from '../../../shared/types';
|
|
4
|
+
import { AgentDaemon } from '../daemon';
|
|
5
|
+
import { SharePointSettingsManager } from '../../settings/sharepoint-manager';
|
|
6
|
+
import { sharepointRequest } from '../../utils/sharepoint-api';
|
|
7
|
+
|
|
8
|
+
type SharePointAction =
|
|
9
|
+
| 'get_current_user'
|
|
10
|
+
| 'search_sites'
|
|
11
|
+
| 'get_site'
|
|
12
|
+
| 'list_site_drives'
|
|
13
|
+
| 'list_drive_items'
|
|
14
|
+
| 'get_item'
|
|
15
|
+
| 'create_folder'
|
|
16
|
+
| 'upload_file'
|
|
17
|
+
| 'delete_item';
|
|
18
|
+
|
|
19
|
+
interface SharePointActionInput {
|
|
20
|
+
action: SharePointAction;
|
|
21
|
+
site_id?: string;
|
|
22
|
+
drive_id?: string;
|
|
23
|
+
item_id?: string;
|
|
24
|
+
query?: string;
|
|
25
|
+
parent_id?: string;
|
|
26
|
+
name?: string;
|
|
27
|
+
conflict_behavior?: 'rename' | 'fail' | 'replace';
|
|
28
|
+
file_path?: string;
|
|
29
|
+
remote_path?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class SharePointTools {
|
|
33
|
+
constructor(
|
|
34
|
+
private workspace: Workspace,
|
|
35
|
+
private daemon: AgentDaemon,
|
|
36
|
+
private taskId: string
|
|
37
|
+
) {}
|
|
38
|
+
|
|
39
|
+
setWorkspace(workspace: Workspace): void {
|
|
40
|
+
this.workspace = workspace;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static isEnabled(): boolean {
|
|
44
|
+
return SharePointSettingsManager.loadSettings().enabled;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private async requireApproval(summary: string, details: Record<string, unknown>): Promise<void> {
|
|
48
|
+
const approved = await this.daemon.requestApproval(
|
|
49
|
+
this.taskId,
|
|
50
|
+
'external_service',
|
|
51
|
+
summary,
|
|
52
|
+
details
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
if (!approved) {
|
|
56
|
+
throw new Error('User denied SharePoint action');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private resolveFilePath(inputPath: string): string {
|
|
61
|
+
if (!this.workspace.permissions.read) {
|
|
62
|
+
throw new Error('Read permission not granted for uploads');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const workspaceRoot = path.resolve(this.workspace.path);
|
|
66
|
+
const allowedPaths = this.workspace.permissions.allowedPaths || [];
|
|
67
|
+
const canReadOutside = this.workspace.isTemp || this.workspace.permissions.unrestrictedFileAccess;
|
|
68
|
+
|
|
69
|
+
const isPathAllowed = (absolutePath: string): boolean => {
|
|
70
|
+
if (allowedPaths.length === 0) return false;
|
|
71
|
+
const normalizedPath = path.normalize(absolutePath);
|
|
72
|
+
return allowedPaths.some((allowed) => {
|
|
73
|
+
const normalizedAllowed = path.normalize(allowed);
|
|
74
|
+
return normalizedPath === normalizedAllowed || normalizedPath.startsWith(normalizedAllowed + path.sep);
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const candidate = path.isAbsolute(inputPath)
|
|
79
|
+
? path.normalize(inputPath)
|
|
80
|
+
: path.resolve(workspaceRoot, inputPath);
|
|
81
|
+
|
|
82
|
+
const relative = path.relative(workspaceRoot, candidate);
|
|
83
|
+
const isInsideWorkspace = !(relative.startsWith('..') || path.isAbsolute(relative));
|
|
84
|
+
if (!isInsideWorkspace && !canReadOutside && !isPathAllowed(candidate)) {
|
|
85
|
+
throw new Error('File path must be inside the workspace or in Allowed Paths');
|
|
86
|
+
}
|
|
87
|
+
if (!fs.existsSync(candidate)) {
|
|
88
|
+
throw new Error(`File not found: ${inputPath}`);
|
|
89
|
+
}
|
|
90
|
+
const stats = fs.statSync(candidate);
|
|
91
|
+
if (!stats.isFile()) {
|
|
92
|
+
throw new Error(`Path is not a file: ${inputPath}`);
|
|
93
|
+
}
|
|
94
|
+
return candidate;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private getSiteId(inputSiteId?: string): string {
|
|
98
|
+
const settings = SharePointSettingsManager.loadSettings();
|
|
99
|
+
const siteId = inputSiteId || settings.siteId;
|
|
100
|
+
if (!siteId) {
|
|
101
|
+
throw new Error('Missing site_id. Provide it in settings or the tool input.');
|
|
102
|
+
}
|
|
103
|
+
return siteId;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private getDriveId(inputDriveId?: string): string {
|
|
107
|
+
const settings = SharePointSettingsManager.loadSettings();
|
|
108
|
+
const driveId = inputDriveId || settings.driveId;
|
|
109
|
+
if (!driveId) {
|
|
110
|
+
throw new Error('Missing drive_id. Provide it in settings or the tool input.');
|
|
111
|
+
}
|
|
112
|
+
return driveId;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async executeAction(input: SharePointActionInput): Promise<any> {
|
|
116
|
+
const settings = SharePointSettingsManager.loadSettings();
|
|
117
|
+
if (!settings.enabled) {
|
|
118
|
+
throw new Error('SharePoint integration is disabled. Enable it in Settings > Integrations > SharePoint.');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const action = input.action;
|
|
122
|
+
if (!action) {
|
|
123
|
+
throw new Error('Missing required "action" parameter');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
let result;
|
|
127
|
+
|
|
128
|
+
switch (action) {
|
|
129
|
+
case 'get_current_user': {
|
|
130
|
+
result = await sharepointRequest(settings, { method: 'GET', path: '/me' });
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case 'search_sites': {
|
|
134
|
+
if (!input.query) throw new Error('Missing query for search_sites');
|
|
135
|
+
result = await sharepointRequest(settings, {
|
|
136
|
+
method: 'GET',
|
|
137
|
+
path: '/sites',
|
|
138
|
+
query: { search: input.query },
|
|
139
|
+
});
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
case 'get_site': {
|
|
143
|
+
const siteId = this.getSiteId(input.site_id);
|
|
144
|
+
result = await sharepointRequest(settings, { method: 'GET', path: `/sites/${siteId}` });
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
case 'list_site_drives': {
|
|
148
|
+
const siteId = this.getSiteId(input.site_id);
|
|
149
|
+
result = await sharepointRequest(settings, { method: 'GET', path: `/sites/${siteId}/drives` });
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
case 'list_drive_items': {
|
|
153
|
+
const driveId = this.getDriveId(input.drive_id);
|
|
154
|
+
const pathSuffix = input.item_id ? `/items/${input.item_id}/children` : '/root/children';
|
|
155
|
+
result = await sharepointRequest(settings, { method: 'GET', path: `/drives/${driveId}${pathSuffix}` });
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
case 'get_item': {
|
|
159
|
+
if (!input.item_id) throw new Error('Missing item_id for get_item');
|
|
160
|
+
const driveId = this.getDriveId(input.drive_id);
|
|
161
|
+
result = await sharepointRequest(settings, { method: 'GET', path: `/drives/${driveId}/items/${input.item_id}` });
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
case 'create_folder': {
|
|
165
|
+
if (!input.name) throw new Error('Missing name for create_folder');
|
|
166
|
+
const driveId = this.getDriveId(input.drive_id);
|
|
167
|
+
const parentPath = input.parent_id
|
|
168
|
+
? `/items/${input.parent_id}/children`
|
|
169
|
+
: '/root/children';
|
|
170
|
+
await this.requireApproval('Create a SharePoint folder', {
|
|
171
|
+
action: 'create_folder',
|
|
172
|
+
parent_id: input.parent_id || 'root',
|
|
173
|
+
name: input.name,
|
|
174
|
+
});
|
|
175
|
+
result = await sharepointRequest(settings, {
|
|
176
|
+
method: 'POST',
|
|
177
|
+
path: `/drives/${driveId}${parentPath}`,
|
|
178
|
+
body: {
|
|
179
|
+
name: input.name,
|
|
180
|
+
folder: {},
|
|
181
|
+
'@microsoft.graph.conflictBehavior': input.conflict_behavior || 'rename',
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
case 'upload_file': {
|
|
187
|
+
if (!input.file_path) throw new Error('Missing file_path for upload_file');
|
|
188
|
+
const driveId = this.getDriveId(input.drive_id);
|
|
189
|
+
const resolved = this.resolveFilePath(input.file_path);
|
|
190
|
+
const data = fs.readFileSync(resolved);
|
|
191
|
+
const fileName = input.name || path.basename(resolved);
|
|
192
|
+
let uploadPath: string;
|
|
193
|
+
if (input.remote_path) {
|
|
194
|
+
const cleaned = input.remote_path.replace(/^\/+/, '');
|
|
195
|
+
const encoded = cleaned
|
|
196
|
+
.split('/')
|
|
197
|
+
.map(segment => encodeURIComponent(segment))
|
|
198
|
+
.join('/');
|
|
199
|
+
uploadPath = `/drives/${driveId}/root:/${encoded}:/content`;
|
|
200
|
+
} else if (input.parent_id) {
|
|
201
|
+
uploadPath = `/drives/${driveId}/items/${input.parent_id}:/${encodeURIComponent(fileName)}:/content`;
|
|
202
|
+
} else {
|
|
203
|
+
uploadPath = `/drives/${driveId}/root:/${encodeURIComponent(fileName)}:/content`;
|
|
204
|
+
}
|
|
205
|
+
await this.requireApproval(`Upload file to SharePoint: ${fileName}`, {
|
|
206
|
+
action: 'upload_file',
|
|
207
|
+
destination: input.remote_path || input.parent_id || 'root',
|
|
208
|
+
file: fileName,
|
|
209
|
+
});
|
|
210
|
+
result = await sharepointRequest(settings, {
|
|
211
|
+
method: 'PUT',
|
|
212
|
+
path: uploadPath,
|
|
213
|
+
body: data,
|
|
214
|
+
headers: { 'Content-Type': 'application/octet-stream' },
|
|
215
|
+
});
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
case 'delete_item': {
|
|
219
|
+
if (!input.item_id) throw new Error('Missing item_id for delete_item');
|
|
220
|
+
const driveId = this.getDriveId(input.drive_id);
|
|
221
|
+
await this.requireApproval('Delete a SharePoint item', {
|
|
222
|
+
action: 'delete_item',
|
|
223
|
+
item_id: input.item_id,
|
|
224
|
+
});
|
|
225
|
+
result = await sharepointRequest(settings, { method: 'DELETE', path: `/drives/${driveId}/items/${input.item_id}` });
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
default:
|
|
229
|
+
throw new Error(`Unsupported action: ${action}`);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
this.daemon.logEvent(this.taskId, 'tool_result', {
|
|
233
|
+
tool: 'sharepoint_action',
|
|
234
|
+
action,
|
|
235
|
+
status: result?.status,
|
|
236
|
+
hasData: result?.data ? true : false,
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
success: true,
|
|
241
|
+
action,
|
|
242
|
+
status: result?.status,
|
|
243
|
+
data: result?.data,
|
|
244
|
+
raw: result?.raw,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
}
|
|
@@ -2,6 +2,7 @@ import { spawn, ChildProcess, execSync } from 'child_process';
|
|
|
2
2
|
import { Workspace, CommandTerminationReason } from '../../../shared/types';
|
|
3
3
|
import { AgentDaemon } from '../daemon';
|
|
4
4
|
import { GuardrailManager } from '../../guardrails/guardrail-manager';
|
|
5
|
+
import { BuiltinToolsSettingsManager } from './builtin-settings';
|
|
5
6
|
|
|
6
7
|
// Limits to prevent runaway commands
|
|
7
8
|
const MAX_TIMEOUT = 5 * 60 * 1000; // 5 minutes max
|
|
@@ -345,9 +346,9 @@ export class ShellTools {
|
|
|
345
346
|
}
|
|
346
347
|
|
|
347
348
|
/**
|
|
348
|
-
* Execute a shell command (requires user approval)
|
|
349
|
+
* Execute a shell command (requires user approval unless auto-approve is enabled)
|
|
349
350
|
* Note: We don't check workspace.permissions.shell here because
|
|
350
|
-
* shell commands
|
|
351
|
+
* shell commands are gated by approval flow (or auto-approve/trust settings)
|
|
351
352
|
*/
|
|
352
353
|
async runCommand(
|
|
353
354
|
command: string,
|
|
@@ -376,9 +377,16 @@ export class ShellTools {
|
|
|
376
377
|
|
|
377
378
|
// Check if command is trusted (auto-approve without user confirmation)
|
|
378
379
|
const trustCheck = GuardrailManager.isCommandTrusted(command);
|
|
380
|
+
const autoApproveEnabled = BuiltinToolsSettingsManager.getToolAutoApprove('run_command');
|
|
379
381
|
let approved = false;
|
|
380
382
|
|
|
381
|
-
if (
|
|
383
|
+
if (autoApproveEnabled && this.isAutoApprovalSafe(command)) {
|
|
384
|
+
approved = true;
|
|
385
|
+
this.daemon.logEvent(this.taskId, 'log', {
|
|
386
|
+
message: 'Auto-approved command (user setting enabled)',
|
|
387
|
+
command,
|
|
388
|
+
});
|
|
389
|
+
} else if (trustCheck.trusted) {
|
|
382
390
|
// Auto-approve trusted commands
|
|
383
391
|
approved = true;
|
|
384
392
|
this.daemon.logEvent(this.taskId, 'log', {
|
|
@@ -119,7 +119,7 @@ export class XTools {
|
|
|
119
119
|
async executeAction(input: XActionInput): Promise<any> {
|
|
120
120
|
const settings = XSettingsManager.loadSettings();
|
|
121
121
|
if (!settings.enabled) {
|
|
122
|
-
throw new Error('X integration is disabled. Enable it in Settings >
|
|
122
|
+
throw new Error('X integration is disabled. Enable it in Settings > X (Twitter).');
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
const action = input.action;
|
|
@@ -116,6 +116,7 @@ export class ChannelGateway {
|
|
|
116
116
|
agentName: settings.agentName || 'CoWork',
|
|
117
117
|
userName: settings.relationship?.userName,
|
|
118
118
|
personality: settings.activePersonality || 'professional',
|
|
119
|
+
persona: settings.activePersona,
|
|
119
120
|
emojiUsage: settings.responseStyle?.emojiUsage || 'minimal',
|
|
120
121
|
quirks: settings.quirks || DEFAULT_QUIRKS,
|
|
121
122
|
};
|