@ericsanchezok/synergy-util 2.4.4 → 3.0.0
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/dist/capability.d.ts +4 -275
- package/dist/capability.js +61 -463
- package/dist/plugin-policy.d.ts +26 -56
- package/dist/plugin-policy.js +33 -202
- package/dist/uuid.d.ts +10 -0
- package/dist/uuid.js +30 -0
- package/package.json +3 -3
- package/dist/browser-protocol.d.ts +0 -97
- package/dist/browser-protocol.js +0 -51
package/dist/capability.js
CHANGED
|
@@ -12,14 +12,6 @@ export const SYNERGY_CAPABILITY_CATEGORIES = [
|
|
|
12
12
|
"communication",
|
|
13
13
|
"platform",
|
|
14
14
|
];
|
|
15
|
-
export function publicToolNames(manifest) {
|
|
16
|
-
return (manifest.contributes?.tools ?? [])
|
|
17
|
-
.filter((tool) => tool.exposure?.mode !== "internal")
|
|
18
|
-
.map((tool) => tool.name);
|
|
19
|
-
}
|
|
20
|
-
export function hasPublicTools(manifest) {
|
|
21
|
-
return publicToolNames(manifest).length > 0;
|
|
22
|
-
}
|
|
23
15
|
export const SYNERGY_CAPABILITY_DETAILS = {
|
|
24
16
|
shell_read: {
|
|
25
17
|
category: "runtime",
|
|
@@ -33,17 +25,30 @@ export const SYNERGY_CAPABILITY_DETAILS = {
|
|
|
33
25
|
title: "Run shell commands",
|
|
34
26
|
description: "Can execute non-destructive shell commands in the current workspace.",
|
|
35
27
|
},
|
|
28
|
+
shell_branch_mutation: {
|
|
29
|
+
category: "runtime",
|
|
30
|
+
severity: "medium",
|
|
31
|
+
title: "Change active branch in workspace",
|
|
32
|
+
description: "Can run git checkout / git switch to change the active branch, which is safe in worktrees but can corrupt concurrent sessions on the main checkout.",
|
|
33
|
+
},
|
|
36
34
|
shell_remote_write: {
|
|
37
35
|
category: "runtime",
|
|
38
36
|
severity: "medium",
|
|
39
37
|
title: "Run remote-write shell commands",
|
|
40
38
|
description: "Can modify existing remote state outside ordinary branch/PR publication workflows.",
|
|
41
39
|
},
|
|
40
|
+
shell_remote_execute: {
|
|
41
|
+
category: "runtime",
|
|
42
|
+
severity: "high",
|
|
43
|
+
title: "Execute commands on remote host",
|
|
44
|
+
description: "Can run bash/process commands on a remote Synergy Link host.",
|
|
45
|
+
nonBypassable: true,
|
|
46
|
+
},
|
|
42
47
|
shell_remote_publish: {
|
|
43
48
|
category: "runtime",
|
|
44
49
|
severity: "medium",
|
|
45
50
|
title: "Publish development changes",
|
|
46
|
-
description: "Can push explicit non-protected branches
|
|
51
|
+
description: "Can push explicit non-protected branches, create pull requests, comment on PRs/issues, and create issues without destructive remote updates.",
|
|
47
52
|
},
|
|
48
53
|
shell_destructive: {
|
|
49
54
|
category: "runtime",
|
|
@@ -143,9 +148,21 @@ export const SYNERGY_CAPABILITY_DETAILS = {
|
|
|
143
148
|
},
|
|
144
149
|
task: {
|
|
145
150
|
category: "tools",
|
|
146
|
-
severity: "
|
|
151
|
+
severity: "low",
|
|
147
152
|
title: "Delegate tasks to subagents",
|
|
148
|
-
description: "
|
|
153
|
+
description: "Runtime control-profile permission to launch an approved Synergy subagent.",
|
|
154
|
+
},
|
|
155
|
+
"blueprint.delegate": {
|
|
156
|
+
category: "runtime",
|
|
157
|
+
severity: "high",
|
|
158
|
+
title: "Delegate Blueprint runs",
|
|
159
|
+
description: "Can create and control BlueprintLoop executions in an existing Session.",
|
|
160
|
+
},
|
|
161
|
+
"lightloop.delegate": {
|
|
162
|
+
category: "runtime",
|
|
163
|
+
severity: "high",
|
|
164
|
+
title: "Enable Light Loop",
|
|
165
|
+
description: "Can enable the Light Loop workflow in an existing Session.",
|
|
149
166
|
},
|
|
150
167
|
prompt_transform: {
|
|
151
168
|
category: "hooks",
|
|
@@ -177,6 +194,12 @@ export const SYNERGY_CAPABILITY_DETAILS = {
|
|
|
177
194
|
title: "Subscribe to Synergy events",
|
|
178
195
|
description: "Can receive approved Synergy runtime events.",
|
|
179
196
|
},
|
|
197
|
+
config_hook: {
|
|
198
|
+
category: "hooks",
|
|
199
|
+
severity: "medium",
|
|
200
|
+
title: "Observe runtime config",
|
|
201
|
+
description: "Can receive redacted runtime configuration snapshots when Synergy starts or reloads config.",
|
|
202
|
+
},
|
|
180
203
|
session_state: {
|
|
181
204
|
category: "session",
|
|
182
205
|
severity: "low",
|
|
@@ -214,17 +237,30 @@ export const SYNERGY_CAPABILITY_DETAILS = {
|
|
|
214
237
|
title: "Use browser clipboard",
|
|
215
238
|
description: "Can read from or write to browser clipboard state.",
|
|
216
239
|
},
|
|
240
|
+
browser_upload: {
|
|
241
|
+
category: "browser",
|
|
242
|
+
severity: "high",
|
|
243
|
+
title: "Upload files to browser",
|
|
244
|
+
description: "Can transfer approved workspace file content into the current browser page.",
|
|
245
|
+
nonBypassable: true,
|
|
246
|
+
},
|
|
247
|
+
browser_coordinate: {
|
|
248
|
+
category: "browser",
|
|
249
|
+
severity: "medium",
|
|
250
|
+
title: "Use browser coordinates",
|
|
251
|
+
description: "Can interact with a browser page using visual coordinates instead of semantic locators.",
|
|
252
|
+
},
|
|
217
253
|
browser_download: {
|
|
218
254
|
category: "browser",
|
|
219
255
|
severity: "medium",
|
|
220
256
|
title: "Download browser files",
|
|
221
257
|
description: "Can download files through the browser workspace.",
|
|
222
258
|
},
|
|
223
|
-
|
|
259
|
+
browser_emulation: {
|
|
224
260
|
category: "browser",
|
|
225
261
|
severity: "low",
|
|
226
|
-
title: "
|
|
227
|
-
description: "Can change
|
|
262
|
+
title: "Emulate a browser environment",
|
|
263
|
+
description: "Can change browser viewport, device, locale, media, CPU, and network emulation.",
|
|
228
264
|
},
|
|
229
265
|
identity_act: {
|
|
230
266
|
category: "identity",
|
|
@@ -267,8 +303,10 @@ export const SYNERGY_PROFILE_CAPABILITIES = [
|
|
|
267
303
|
"file_write",
|
|
268
304
|
"shell_read",
|
|
269
305
|
"shell",
|
|
270
|
-
"
|
|
306
|
+
"shell_branch_mutation",
|
|
307
|
+
"shell_remote_execute",
|
|
271
308
|
"shell_remote_publish",
|
|
309
|
+
"shell_remote_write",
|
|
272
310
|
"shell_destructive",
|
|
273
311
|
"shell_hardline",
|
|
274
312
|
"file_external_read",
|
|
@@ -288,6 +326,7 @@ export const SYNERGY_PROFILE_CAPABILITIES = [
|
|
|
288
326
|
"tool_execution_hook",
|
|
289
327
|
"permission_hook",
|
|
290
328
|
"event_hook",
|
|
329
|
+
"config_hook",
|
|
291
330
|
"identity_act",
|
|
292
331
|
"communication_email",
|
|
293
332
|
"channel_outbound",
|
|
@@ -299,8 +338,10 @@ export const SYNERGY_PROFILE_CAPABILITIES = [
|
|
|
299
338
|
"browser_eval_readonly",
|
|
300
339
|
"browser_eval_trusted",
|
|
301
340
|
"browser_clipboard",
|
|
341
|
+
"browser_upload",
|
|
342
|
+
"browser_coordinate",
|
|
302
343
|
"browser_download",
|
|
303
|
-
"
|
|
344
|
+
"browser_emulation",
|
|
304
345
|
];
|
|
305
346
|
export const SYNERGY_PERMISSION_CAPABILITY = {
|
|
306
347
|
read: "file_read",
|
|
@@ -325,6 +366,7 @@ export const SYNERGY_PERMISSION_CAPABILITY = {
|
|
|
325
366
|
network_request: "network_request",
|
|
326
367
|
scan_document: "file_read",
|
|
327
368
|
look_at: "file_read",
|
|
369
|
+
view_image: "file_read",
|
|
328
370
|
attach: "file_read",
|
|
329
371
|
ast_grep: "file_read",
|
|
330
372
|
lsp: "file_read",
|
|
@@ -363,7 +405,7 @@ export const SYNERGY_PERMISSION_CAPABILITY = {
|
|
|
363
405
|
email_read: "communication_email",
|
|
364
406
|
email_send: "communication_email",
|
|
365
407
|
communication_email: "communication_email",
|
|
366
|
-
session_send: "
|
|
408
|
+
session_send: "identity_act",
|
|
367
409
|
channel_outbound: "channel_outbound",
|
|
368
410
|
identity_act: "identity_act",
|
|
369
411
|
platform_control: "platform_control",
|
|
@@ -374,364 +416,8 @@ export function permissionCapability(permission) {
|
|
|
374
416
|
export function capabilityNonBypassable(capability) {
|
|
375
417
|
return SYNERGY_CAPABILITY_DETAILS[capability]?.nonBypassable === true;
|
|
376
418
|
}
|
|
377
|
-
export function capabilityRisk(capability
|
|
378
|
-
|
|
379
|
-
return (manifest.permissions?.network?.connectDomains ?? []).length > 0 ? "medium" : "high";
|
|
380
|
-
}
|
|
381
|
-
const details = SYNERGY_CAPABILITY_DETAILS[capability];
|
|
382
|
-
if (details)
|
|
383
|
-
return details.severity;
|
|
384
|
-
return "high";
|
|
385
|
-
}
|
|
386
|
-
function maxRisk(current, next) {
|
|
387
|
-
if (current === "high" || next === "high")
|
|
388
|
-
return "high";
|
|
389
|
-
if (current === "medium" || next === "medium")
|
|
390
|
-
return "medium";
|
|
391
|
-
return "low";
|
|
392
|
-
}
|
|
393
|
-
function sortKeys(value) {
|
|
394
|
-
if (Array.isArray(value))
|
|
395
|
-
return value.map(sortKeys);
|
|
396
|
-
if (value !== null && typeof value === "object") {
|
|
397
|
-
const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
|
|
398
|
-
const result = {};
|
|
399
|
-
for (const [key, item] of entries) {
|
|
400
|
-
result[key] = sortKeys(item);
|
|
401
|
-
}
|
|
402
|
-
return result;
|
|
403
|
-
}
|
|
404
|
-
return value;
|
|
405
|
-
}
|
|
406
|
-
function buildCapabilitySet(permissions, toolOverrides) {
|
|
407
|
-
const caps = new Set();
|
|
408
|
-
const pt = permissions?.tools;
|
|
409
|
-
const pd = permissions?.data;
|
|
410
|
-
const tc = toolOverrides;
|
|
411
|
-
const fs = tc?.filesystem ?? pt?.filesystem ?? "none";
|
|
412
|
-
if (fs === "read")
|
|
413
|
-
caps.add("file_read");
|
|
414
|
-
if (fs === "write") {
|
|
415
|
-
caps.add("file_read");
|
|
416
|
-
caps.add("file_write");
|
|
417
|
-
}
|
|
418
|
-
if (tc?.shell ?? pt?.shell ?? false)
|
|
419
|
-
caps.add("shell");
|
|
420
|
-
if (tc?.network ?? pt?.network ?? false)
|
|
421
|
-
caps.add("network_request");
|
|
422
|
-
if (pt?.mcp === "invoke")
|
|
423
|
-
caps.add("mcp_invoke");
|
|
424
|
-
if (pt?.mcp === "spawn") {
|
|
425
|
-
caps.add("mcp_invoke");
|
|
426
|
-
caps.add("mcp_spawn");
|
|
427
|
-
}
|
|
428
|
-
if (pt?.task)
|
|
429
|
-
caps.add("task");
|
|
430
|
-
const sess = tc?.session ?? pd?.session ?? "none";
|
|
431
|
-
if (sess === "read")
|
|
432
|
-
caps.add("session_data");
|
|
433
|
-
const ws = tc?.workspace ?? pd?.workspace ?? "none";
|
|
434
|
-
if (ws === "read")
|
|
435
|
-
caps.add("workspace_data");
|
|
436
|
-
const cfg = tc?.config ?? pd?.config ?? "none";
|
|
437
|
-
if (cfg === "global") {
|
|
438
|
-
caps.add("config:read");
|
|
439
|
-
caps.add("config:write");
|
|
440
|
-
}
|
|
441
|
-
if (cfg === "plugin")
|
|
442
|
-
caps.add("config:read");
|
|
443
|
-
if (pd?.secrets === "own")
|
|
444
|
-
caps.add("secrets");
|
|
445
|
-
const hooks = permissions?.hooks;
|
|
446
|
-
if (hooks?.promptTransform)
|
|
447
|
-
caps.add("prompt_transform");
|
|
448
|
-
if (hooks?.compactionTransform)
|
|
449
|
-
caps.add("compaction_transform");
|
|
450
|
-
if (hooks?.toolExecute && hooks.toolExecute !== "none")
|
|
451
|
-
caps.add("tool_execution_hook");
|
|
452
|
-
if (hooks?.permissionAsk && hooks.permissionAsk !== "none")
|
|
453
|
-
caps.add("permission_hook");
|
|
454
|
-
if (hooks?.events === "all" || (hooks?.events === "selected" && (hooks.eventNames?.length ?? 0) > 0)) {
|
|
455
|
-
caps.add("event_hook");
|
|
456
|
-
}
|
|
457
|
-
return [...caps].sort();
|
|
458
|
-
}
|
|
459
|
-
export function baseCapabilities(manifest) {
|
|
460
|
-
return buildCapabilitySet(manifest.permissions);
|
|
461
|
-
}
|
|
462
|
-
export function toolCapabilities(manifest, tool) {
|
|
463
|
-
return buildCapabilitySet(manifest.permissions, tool.capabilities);
|
|
464
|
-
}
|
|
465
|
-
export function publicToolCapabilities(manifest) {
|
|
466
|
-
const caps = new Set();
|
|
467
|
-
for (const tool of manifest.contributes?.tools ?? []) {
|
|
468
|
-
if (tool.exposure?.mode === "internal")
|
|
469
|
-
continue;
|
|
470
|
-
for (const capability of toolCapabilities(manifest, tool))
|
|
471
|
-
caps.add(capability);
|
|
472
|
-
}
|
|
473
|
-
return [...caps].sort();
|
|
474
|
-
}
|
|
475
|
-
export function computeRisk(capabilities, manifest) {
|
|
476
|
-
if (capabilities.length === 0)
|
|
477
|
-
return "low";
|
|
478
|
-
let risk = "low";
|
|
479
|
-
for (const cap of capabilities) {
|
|
480
|
-
risk = maxRisk(risk, capabilityRisk(cap, manifest));
|
|
481
|
-
}
|
|
482
|
-
return risk;
|
|
483
|
-
}
|
|
484
|
-
export function capabilitiesForRiskScope(manifest, scope) {
|
|
485
|
-
return scope === "agent" ? publicToolCapabilities(manifest) : baseCapabilities(manifest);
|
|
486
|
-
}
|
|
487
|
-
export function pluginRisk(manifest, input) {
|
|
488
|
-
return computeRisk(capabilitiesForRiskScope(manifest, input.scope), manifest);
|
|
489
|
-
}
|
|
490
|
-
export function toolRisk(manifest, tool) {
|
|
491
|
-
return computeRisk(toolCapabilities(manifest, tool), manifest);
|
|
492
|
-
}
|
|
493
|
-
function networkPermissionItem(manifest) {
|
|
494
|
-
const domains = manifest.permissions?.network?.connectDomains ?? [];
|
|
495
|
-
const severity = capabilityRisk("network_request", manifest);
|
|
496
|
-
return {
|
|
497
|
-
key: "network_request",
|
|
498
|
-
category: "network",
|
|
499
|
-
severity,
|
|
500
|
-
title: "Access network",
|
|
501
|
-
description: domains.length > 0
|
|
502
|
-
? `Can make network requests to: ${domains.join(", ")}.`
|
|
503
|
-
: "Can make outbound network requests to any domain.",
|
|
504
|
-
technical: domains.length > 0 ? `domains: ${domains.join(", ")}` : undefined,
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
function contributionPermissionItems(manifest) {
|
|
508
|
-
const ui = manifest.contributes?.ui;
|
|
509
|
-
const perms = manifest.permissions?.ui;
|
|
510
|
-
const items = [];
|
|
511
|
-
if (ui?.toolRenderers || perms?.toolRenderers) {
|
|
512
|
-
items.push({
|
|
513
|
-
key: "ui.toolRenderers",
|
|
514
|
-
category: "ui",
|
|
515
|
-
severity: "low",
|
|
516
|
-
title: "Custom tool renderers",
|
|
517
|
-
description: "Overrides how tool outputs appear in the chat UI.",
|
|
518
|
-
});
|
|
519
|
-
}
|
|
520
|
-
if (ui?.partRenderers || perms?.partRenderers) {
|
|
521
|
-
items.push({
|
|
522
|
-
key: "ui.partRenderers",
|
|
523
|
-
category: "ui",
|
|
524
|
-
severity: "low",
|
|
525
|
-
title: "Custom part renderers",
|
|
526
|
-
description: "Overrides how message parts appear in the chat UI.",
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
if (ui?.workbenchPanels || perms?.workbenchPanels) {
|
|
530
|
-
items.push({
|
|
531
|
-
key: "ui.workbenchPanels",
|
|
532
|
-
category: "ui",
|
|
533
|
-
severity: "low",
|
|
534
|
-
title: "Workbench panels",
|
|
535
|
-
description: "Adds custom panels to the side workspace or BottomSpace.",
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
if (ui?.appPanels || perms?.appPanels) {
|
|
539
|
-
items.push({
|
|
540
|
-
key: "ui.appPanels",
|
|
541
|
-
category: "ui",
|
|
542
|
-
severity: "low",
|
|
543
|
-
title: "App panels",
|
|
544
|
-
description: "Adds top-level sidebar panels to the app.",
|
|
545
|
-
});
|
|
546
|
-
}
|
|
547
|
-
if (ui?.settings || perms?.settings) {
|
|
548
|
-
items.push({
|
|
549
|
-
key: "ui.settings",
|
|
550
|
-
category: "ui",
|
|
551
|
-
severity: "low",
|
|
552
|
-
title: "Settings page",
|
|
553
|
-
description: "Adds a custom settings page or form.",
|
|
554
|
-
});
|
|
555
|
-
}
|
|
556
|
-
if (ui?.themes || perms?.themes) {
|
|
557
|
-
items.push({
|
|
558
|
-
key: "ui.themes",
|
|
559
|
-
category: "ui",
|
|
560
|
-
severity: "low",
|
|
561
|
-
title: "Custom themes",
|
|
562
|
-
description: "Adds custom color themes to the UI.",
|
|
563
|
-
});
|
|
564
|
-
}
|
|
565
|
-
if (ui?.icons || perms?.icons) {
|
|
566
|
-
items.push({
|
|
567
|
-
key: "ui.icons",
|
|
568
|
-
category: "ui",
|
|
569
|
-
severity: "low",
|
|
570
|
-
title: "Custom icons",
|
|
571
|
-
description: "Adds custom icon sets to the UI.",
|
|
572
|
-
});
|
|
573
|
-
}
|
|
574
|
-
if (ui?.messageSlots || perms?.messageSlots) {
|
|
575
|
-
items.push({
|
|
576
|
-
key: "ui.messageSlots",
|
|
577
|
-
category: "ui",
|
|
578
|
-
severity: "low",
|
|
579
|
-
title: "Message slots",
|
|
580
|
-
description: "Adds custom components around reasoning and tool timeline sections.",
|
|
581
|
-
});
|
|
582
|
-
}
|
|
583
|
-
if (ui?.appRoutes || perms?.appRoutes) {
|
|
584
|
-
items.push({
|
|
585
|
-
key: "ui.appRoutes",
|
|
586
|
-
category: "ui",
|
|
587
|
-
severity: "low",
|
|
588
|
-
title: "App routes",
|
|
589
|
-
description: "Adds custom plugin pages to the app.",
|
|
590
|
-
});
|
|
591
|
-
}
|
|
592
|
-
if (ui?.commands || perms?.commands) {
|
|
593
|
-
items.push({
|
|
594
|
-
key: "ui.commands",
|
|
595
|
-
category: "ui",
|
|
596
|
-
severity: "low",
|
|
597
|
-
title: "Custom commands",
|
|
598
|
-
description: "Adds custom UI commands to the command palette.",
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
return items;
|
|
602
|
-
}
|
|
603
|
-
function dataPermissionItems(manifest) {
|
|
604
|
-
const data = manifest.permissions?.data;
|
|
605
|
-
const items = [];
|
|
606
|
-
if (data?.session === "read") {
|
|
607
|
-
items.push({
|
|
608
|
-
key: "data.session",
|
|
609
|
-
category: "data",
|
|
610
|
-
severity: "medium",
|
|
611
|
-
title: "Read session data",
|
|
612
|
-
description: "Can access session history and metadata across all sessions.",
|
|
613
|
-
});
|
|
614
|
-
}
|
|
615
|
-
else if (data?.session === "metadata") {
|
|
616
|
-
items.push({
|
|
617
|
-
key: "data.session",
|
|
618
|
-
category: "data",
|
|
619
|
-
severity: "low",
|
|
620
|
-
title: "Read session metadata",
|
|
621
|
-
description: "Can access session metadata but not message content.",
|
|
622
|
-
});
|
|
623
|
-
}
|
|
624
|
-
if (data?.workspace === "read") {
|
|
625
|
-
items.push({
|
|
626
|
-
key: "data.workspace",
|
|
627
|
-
category: "data",
|
|
628
|
-
severity: "low",
|
|
629
|
-
title: "Read workspace metadata",
|
|
630
|
-
description: "Can access workspace metadata and directory information.",
|
|
631
|
-
});
|
|
632
|
-
}
|
|
633
|
-
if (data?.secrets === "own") {
|
|
634
|
-
items.push({
|
|
635
|
-
key: "data.secrets",
|
|
636
|
-
category: "data",
|
|
637
|
-
severity: "high",
|
|
638
|
-
title: "Own credential store",
|
|
639
|
-
description: "Can read and write its own stored credentials.",
|
|
640
|
-
});
|
|
641
|
-
}
|
|
642
|
-
return items;
|
|
643
|
-
}
|
|
644
|
-
function hookPermissionItems(manifest) {
|
|
645
|
-
const hooks = manifest.permissions?.hooks;
|
|
646
|
-
const items = [];
|
|
647
|
-
if (hooks?.promptTransform) {
|
|
648
|
-
items.push({
|
|
649
|
-
key: "hooks.promptTransform",
|
|
650
|
-
category: "hooks",
|
|
651
|
-
severity: "high",
|
|
652
|
-
title: "Transform prompts",
|
|
653
|
-
description: "Can modify the system prompt and message context sent to the LLM.",
|
|
654
|
-
});
|
|
655
|
-
}
|
|
656
|
-
if (hooks?.toolExecute === "all") {
|
|
657
|
-
items.push({
|
|
658
|
-
key: "hooks.toolExecute",
|
|
659
|
-
category: "hooks",
|
|
660
|
-
severity: "medium",
|
|
661
|
-
title: "Intercept all tool execution",
|
|
662
|
-
description: "Can rewrite arguments and outputs for all tool calls, including from other plugins.",
|
|
663
|
-
});
|
|
664
|
-
}
|
|
665
|
-
else if (hooks?.toolExecute === "declared") {
|
|
666
|
-
items.push({
|
|
667
|
-
key: "hooks.toolExecute",
|
|
668
|
-
category: "hooks",
|
|
669
|
-
severity: "low",
|
|
670
|
-
title: "Intercept declared tool execution",
|
|
671
|
-
description: "Can rewrite arguments and outputs for tools declared in its manifest.",
|
|
672
|
-
});
|
|
673
|
-
}
|
|
674
|
-
else if (hooks?.toolExecute === "own") {
|
|
675
|
-
items.push({
|
|
676
|
-
key: "hooks.toolExecute",
|
|
677
|
-
category: "hooks",
|
|
678
|
-
severity: "low",
|
|
679
|
-
title: "Intercept own tool execution",
|
|
680
|
-
description: "Can rewrite arguments and outputs for its own tool calls.",
|
|
681
|
-
});
|
|
682
|
-
}
|
|
683
|
-
if (hooks?.permissionAsk === "all") {
|
|
684
|
-
items.push({
|
|
685
|
-
key: "hooks.permissionAsk",
|
|
686
|
-
category: "hooks",
|
|
687
|
-
severity: "high",
|
|
688
|
-
title: "Override all permission decisions",
|
|
689
|
-
description: "Can allow or deny any permission request, including from other plugins.",
|
|
690
|
-
});
|
|
691
|
-
}
|
|
692
|
-
else if (hooks?.permissionAsk === "own") {
|
|
693
|
-
items.push({
|
|
694
|
-
key: "hooks.permissionAsk",
|
|
695
|
-
category: "hooks",
|
|
696
|
-
severity: "medium",
|
|
697
|
-
title: "Override own permission decisions",
|
|
698
|
-
description: "Can allow or deny its own permission requests.",
|
|
699
|
-
});
|
|
700
|
-
}
|
|
701
|
-
return items;
|
|
702
|
-
}
|
|
703
|
-
export function permissionItems(manifest, capabilities) {
|
|
704
|
-
const items = [];
|
|
705
|
-
const seen = new Set();
|
|
706
|
-
const add = (item) => {
|
|
707
|
-
if (seen.has(item.key))
|
|
708
|
-
return;
|
|
709
|
-
seen.add(item.key);
|
|
710
|
-
items.push(item);
|
|
711
|
-
};
|
|
712
|
-
for (const capability of capabilities) {
|
|
713
|
-
if (capability === "network_request") {
|
|
714
|
-
add(networkPermissionItem(manifest));
|
|
715
|
-
continue;
|
|
716
|
-
}
|
|
717
|
-
const details = SYNERGY_CAPABILITY_DETAILS[capability];
|
|
718
|
-
if (details)
|
|
719
|
-
add({ key: capability, ...details });
|
|
720
|
-
}
|
|
721
|
-
for (const item of contributionPermissionItems(manifest))
|
|
722
|
-
add(item);
|
|
723
|
-
for (const item of dataPermissionItems(manifest))
|
|
724
|
-
add(item);
|
|
725
|
-
for (const item of hookPermissionItems(manifest))
|
|
726
|
-
add(item);
|
|
727
|
-
return items;
|
|
728
|
-
}
|
|
729
|
-
export function registryPermissionSummary(manifest, capabilities) {
|
|
730
|
-
return permissionItems(manifest, capabilities).map((item) => ({
|
|
731
|
-
key: item.key,
|
|
732
|
-
description: item.description,
|
|
733
|
-
risk: item.severity,
|
|
734
|
-
}));
|
|
419
|
+
export function capabilityRisk(capability) {
|
|
420
|
+
return SYNERGY_CAPABILITY_DETAILS[capability]?.severity ?? "high";
|
|
735
421
|
}
|
|
736
422
|
export function permissionCategoryForKey(key) {
|
|
737
423
|
const details = SYNERGY_CAPABILITY_DETAILS[key];
|
|
@@ -751,91 +437,3 @@ export function permissionCategoryForKey(key) {
|
|
|
751
437
|
return "browser";
|
|
752
438
|
return "tools";
|
|
753
439
|
}
|
|
754
|
-
export function permissionsHashPayload(manifest, capabilities) {
|
|
755
|
-
return {
|
|
756
|
-
capabilities: [...capabilities].sort(),
|
|
757
|
-
permissions: manifest.permissions ?? {},
|
|
758
|
-
contributes: permissionsRelevantContributes(manifest),
|
|
759
|
-
lifecycle: manifest.lifecycle ?? {},
|
|
760
|
-
};
|
|
761
|
-
}
|
|
762
|
-
function permissionsRelevantContributes(manifest) {
|
|
763
|
-
const contributes = manifest.contributes;
|
|
764
|
-
if (!contributes)
|
|
765
|
-
return undefined;
|
|
766
|
-
return {
|
|
767
|
-
...(contributes.permissions ? { permissions: contributes.permissions } : {}),
|
|
768
|
-
...(contributes.tools
|
|
769
|
-
? {
|
|
770
|
-
tools: contributes.tools.map((tool) => ({
|
|
771
|
-
id: tool.id,
|
|
772
|
-
name: tool.name,
|
|
773
|
-
exposure: tool.exposure,
|
|
774
|
-
capabilities: tool.capabilities,
|
|
775
|
-
})),
|
|
776
|
-
}
|
|
777
|
-
: {}),
|
|
778
|
-
...(contributes.agents
|
|
779
|
-
? {
|
|
780
|
-
agents: contributes.agents.map((agent) => ({
|
|
781
|
-
name: agent.name,
|
|
782
|
-
mode: agent.mode,
|
|
783
|
-
hidden: agent.hidden,
|
|
784
|
-
model: agent.model,
|
|
785
|
-
modelRole: agent.modelRole,
|
|
786
|
-
permission: agent.permission,
|
|
787
|
-
})),
|
|
788
|
-
}
|
|
789
|
-
: {}),
|
|
790
|
-
...(contributes.mcp ? { mcp: contributes.mcp } : {}),
|
|
791
|
-
...(contributes.ui
|
|
792
|
-
? {
|
|
793
|
-
ui: {
|
|
794
|
-
toolRenderers: Boolean(contributes.ui.toolRenderers?.length),
|
|
795
|
-
partRenderers: Boolean(contributes.ui.partRenderers?.length),
|
|
796
|
-
workbenchPanels: Boolean(contributes.ui.workbenchPanels?.length),
|
|
797
|
-
appPanels: Boolean(contributes.ui.appPanels?.length),
|
|
798
|
-
settings: Boolean(contributes.ui.settings?.length),
|
|
799
|
-
messageSlots: Boolean(contributes.ui.messageSlots?.length),
|
|
800
|
-
themes: Boolean(contributes.ui.themes?.length),
|
|
801
|
-
icons: Boolean(contributes.ui.icons?.length),
|
|
802
|
-
appRoutes: Boolean(contributes.ui.appRoutes?.length),
|
|
803
|
-
commands: Boolean(contributes.ui.commands?.length),
|
|
804
|
-
},
|
|
805
|
-
}
|
|
806
|
-
: {}),
|
|
807
|
-
};
|
|
808
|
-
}
|
|
809
|
-
export function manifestHashPayload(manifest) {
|
|
810
|
-
return manifest;
|
|
811
|
-
}
|
|
812
|
-
export function stablePluginJson(value) {
|
|
813
|
-
return JSON.stringify(sortKeys(value));
|
|
814
|
-
}
|
|
815
|
-
export const SYNERGY_BRIDGE_METHOD_POLICY = {
|
|
816
|
-
"config.get": { type: "capability", capability: "config:read" },
|
|
817
|
-
"config.set": { type: "capability", capability: "config:write" },
|
|
818
|
-
"config.replace": { type: "capability", capability: "config:write" },
|
|
819
|
-
"secret.get": { type: "capability", capability: "secrets" },
|
|
820
|
-
"secret.set": { type: "capability", capability: "secrets" },
|
|
821
|
-
"secret.delete": { type: "capability", capability: "secrets" },
|
|
822
|
-
"cache.get": { type: "unprivileged" },
|
|
823
|
-
"cache.set": { type: "unprivileged" },
|
|
824
|
-
"cache.delete": { type: "unprivileged" },
|
|
825
|
-
"file.read": { type: "capability", capability: "file_read" },
|
|
826
|
-
"file.write": { type: "capability", capability: "file_write" },
|
|
827
|
-
"network.fetch": { type: "capability", capability: "network_request" },
|
|
828
|
-
"shell.run": { type: "capability", capability: "shell" },
|
|
829
|
-
"session.getMetadata": { type: "capability", capability: "session_data" },
|
|
830
|
-
"workspace.getMetadata": { type: "capability", capability: "workspace_data" },
|
|
831
|
-
"task.run": { type: "capability", capability: "task" },
|
|
832
|
-
"tool.invoke": { type: "unprivileged" },
|
|
833
|
-
"permission.request": { type: "unprivileged" },
|
|
834
|
-
};
|
|
835
|
-
export function bridgeMethodPolicy(method) {
|
|
836
|
-
return SYNERGY_BRIDGE_METHOD_POLICY[method] ?? { type: "unknown" };
|
|
837
|
-
}
|
|
838
|
-
export function bridgeCapability(method) {
|
|
839
|
-
const policy = bridgeMethodPolicy(method);
|
|
840
|
-
return policy.type === "capability" ? policy.capability : undefined;
|
|
841
|
-
}
|