@ericsanchezok/synergy-util 2.4.5 → 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 -277
- package/dist/capability.js +54 -474
- 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 +1 -1
- 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",
|
|
@@ -220,17 +237,30 @@ export const SYNERGY_CAPABILITY_DETAILS = {
|
|
|
220
237
|
title: "Use browser clipboard",
|
|
221
238
|
description: "Can read from or write to browser clipboard state.",
|
|
222
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
|
+
},
|
|
223
253
|
browser_download: {
|
|
224
254
|
category: "browser",
|
|
225
255
|
severity: "medium",
|
|
226
256
|
title: "Download browser files",
|
|
227
257
|
description: "Can download files through the browser workspace.",
|
|
228
258
|
},
|
|
229
|
-
|
|
259
|
+
browser_emulation: {
|
|
230
260
|
category: "browser",
|
|
231
261
|
severity: "low",
|
|
232
|
-
title: "
|
|
233
|
-
description: "Can change
|
|
262
|
+
title: "Emulate a browser environment",
|
|
263
|
+
description: "Can change browser viewport, device, locale, media, CPU, and network emulation.",
|
|
234
264
|
},
|
|
235
265
|
identity_act: {
|
|
236
266
|
category: "identity",
|
|
@@ -273,8 +303,10 @@ export const SYNERGY_PROFILE_CAPABILITIES = [
|
|
|
273
303
|
"file_write",
|
|
274
304
|
"shell_read",
|
|
275
305
|
"shell",
|
|
276
|
-
"
|
|
306
|
+
"shell_branch_mutation",
|
|
307
|
+
"shell_remote_execute",
|
|
277
308
|
"shell_remote_publish",
|
|
309
|
+
"shell_remote_write",
|
|
278
310
|
"shell_destructive",
|
|
279
311
|
"shell_hardline",
|
|
280
312
|
"file_external_read",
|
|
@@ -306,8 +338,10 @@ export const SYNERGY_PROFILE_CAPABILITIES = [
|
|
|
306
338
|
"browser_eval_readonly",
|
|
307
339
|
"browser_eval_trusted",
|
|
308
340
|
"browser_clipboard",
|
|
341
|
+
"browser_upload",
|
|
342
|
+
"browser_coordinate",
|
|
309
343
|
"browser_download",
|
|
310
|
-
"
|
|
344
|
+
"browser_emulation",
|
|
311
345
|
];
|
|
312
346
|
export const SYNERGY_PERMISSION_CAPABILITY = {
|
|
313
347
|
read: "file_read",
|
|
@@ -332,6 +366,7 @@ export const SYNERGY_PERMISSION_CAPABILITY = {
|
|
|
332
366
|
network_request: "network_request",
|
|
333
367
|
scan_document: "file_read",
|
|
334
368
|
look_at: "file_read",
|
|
369
|
+
view_image: "file_read",
|
|
335
370
|
attach: "file_read",
|
|
336
371
|
ast_grep: "file_read",
|
|
337
372
|
lsp: "file_read",
|
|
@@ -370,7 +405,7 @@ export const SYNERGY_PERMISSION_CAPABILITY = {
|
|
|
370
405
|
email_read: "communication_email",
|
|
371
406
|
email_send: "communication_email",
|
|
372
407
|
communication_email: "communication_email",
|
|
373
|
-
session_send: "
|
|
408
|
+
session_send: "identity_act",
|
|
374
409
|
channel_outbound: "channel_outbound",
|
|
375
410
|
identity_act: "identity_act",
|
|
376
411
|
platform_control: "platform_control",
|
|
@@ -381,375 +416,8 @@ export function permissionCapability(permission) {
|
|
|
381
416
|
export function capabilityNonBypassable(capability) {
|
|
382
417
|
return SYNERGY_CAPABILITY_DETAILS[capability]?.nonBypassable === true;
|
|
383
418
|
}
|
|
384
|
-
export function capabilityRisk(capability
|
|
385
|
-
|
|
386
|
-
return (manifest.permissions?.network?.connectDomains ?? []).length > 0 ? "medium" : "high";
|
|
387
|
-
}
|
|
388
|
-
const details = SYNERGY_CAPABILITY_DETAILS[capability];
|
|
389
|
-
if (details)
|
|
390
|
-
return details.severity;
|
|
391
|
-
return "high";
|
|
392
|
-
}
|
|
393
|
-
function maxRisk(current, next) {
|
|
394
|
-
if (current === "high" || next === "high")
|
|
395
|
-
return "high";
|
|
396
|
-
if (current === "medium" || next === "medium")
|
|
397
|
-
return "medium";
|
|
398
|
-
return "low";
|
|
399
|
-
}
|
|
400
|
-
function sortKeys(value) {
|
|
401
|
-
if (Array.isArray(value))
|
|
402
|
-
return value.map(sortKeys);
|
|
403
|
-
if (value !== null && typeof value === "object") {
|
|
404
|
-
const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
|
|
405
|
-
const result = {};
|
|
406
|
-
for (const [key, item] of entries) {
|
|
407
|
-
result[key] = sortKeys(item);
|
|
408
|
-
}
|
|
409
|
-
return result;
|
|
410
|
-
}
|
|
411
|
-
return value;
|
|
412
|
-
}
|
|
413
|
-
function buildCapabilitySet(permissions, toolOverrides) {
|
|
414
|
-
const caps = new Set();
|
|
415
|
-
const pt = permissions?.tools;
|
|
416
|
-
const pd = permissions?.data;
|
|
417
|
-
const tc = toolOverrides;
|
|
418
|
-
const fs = tc?.filesystem ?? pt?.filesystem ?? "none";
|
|
419
|
-
if (fs === "read")
|
|
420
|
-
caps.add("file_read");
|
|
421
|
-
if (fs === "write") {
|
|
422
|
-
caps.add("file_read");
|
|
423
|
-
caps.add("file_write");
|
|
424
|
-
}
|
|
425
|
-
if (tc?.shell ?? pt?.shell ?? false)
|
|
426
|
-
caps.add("shell");
|
|
427
|
-
if (tc?.network ?? pt?.network ?? false)
|
|
428
|
-
caps.add("network_request");
|
|
429
|
-
if (pt?.mcp === "invoke")
|
|
430
|
-
caps.add("mcp_invoke");
|
|
431
|
-
if (pt?.mcp === "spawn") {
|
|
432
|
-
caps.add("mcp_invoke");
|
|
433
|
-
caps.add("mcp_spawn");
|
|
434
|
-
}
|
|
435
|
-
if (pt?.task)
|
|
436
|
-
caps.add("task");
|
|
437
|
-
const sess = tc?.session ?? pd?.session ?? "none";
|
|
438
|
-
if (sess === "read")
|
|
439
|
-
caps.add("session_data");
|
|
440
|
-
const ws = tc?.workspace ?? pd?.workspace ?? "none";
|
|
441
|
-
if (ws === "read")
|
|
442
|
-
caps.add("workspace_data");
|
|
443
|
-
const cfg = tc?.config ?? pd?.config ?? "none";
|
|
444
|
-
if (cfg === "global") {
|
|
445
|
-
caps.add("config:read");
|
|
446
|
-
caps.add("config:write");
|
|
447
|
-
}
|
|
448
|
-
if (cfg === "plugin")
|
|
449
|
-
caps.add("config:read");
|
|
450
|
-
if (pd?.secrets === "own")
|
|
451
|
-
caps.add("secrets");
|
|
452
|
-
const hooks = permissions?.hooks;
|
|
453
|
-
if (hooks?.promptTransform)
|
|
454
|
-
caps.add("prompt_transform");
|
|
455
|
-
if (hooks?.compactionTransform)
|
|
456
|
-
caps.add("compaction_transform");
|
|
457
|
-
if (hooks?.config)
|
|
458
|
-
caps.add("config_hook");
|
|
459
|
-
if (hooks?.toolExecute && hooks.toolExecute !== "none")
|
|
460
|
-
caps.add("tool_execution_hook");
|
|
461
|
-
if (hooks?.permissionAsk && hooks.permissionAsk !== "none")
|
|
462
|
-
caps.add("permission_hook");
|
|
463
|
-
if (hooks?.events === "all" || (hooks?.events === "selected" && (hooks.eventNames?.length ?? 0) > 0)) {
|
|
464
|
-
caps.add("event_hook");
|
|
465
|
-
}
|
|
466
|
-
return [...caps].sort();
|
|
467
|
-
}
|
|
468
|
-
export function baseCapabilities(manifest) {
|
|
469
|
-
return buildCapabilitySet(manifest.permissions);
|
|
470
|
-
}
|
|
471
|
-
export function toolCapabilities(manifest, tool) {
|
|
472
|
-
return buildCapabilitySet(manifest.permissions, tool.capabilities);
|
|
473
|
-
}
|
|
474
|
-
export function publicToolCapabilities(manifest) {
|
|
475
|
-
const caps = new Set();
|
|
476
|
-
for (const tool of manifest.contributes?.tools ?? []) {
|
|
477
|
-
if (tool.exposure?.mode === "internal")
|
|
478
|
-
continue;
|
|
479
|
-
for (const capability of toolCapabilities(manifest, tool))
|
|
480
|
-
caps.add(capability);
|
|
481
|
-
}
|
|
482
|
-
return [...caps].sort();
|
|
483
|
-
}
|
|
484
|
-
export function computeRisk(capabilities, manifest) {
|
|
485
|
-
if (capabilities.length === 0)
|
|
486
|
-
return "low";
|
|
487
|
-
let risk = "low";
|
|
488
|
-
for (const cap of capabilities) {
|
|
489
|
-
risk = maxRisk(risk, capabilityRisk(cap, manifest));
|
|
490
|
-
}
|
|
491
|
-
return risk;
|
|
492
|
-
}
|
|
493
|
-
export function capabilitiesForRiskScope(manifest, scope) {
|
|
494
|
-
return scope === "agent" ? publicToolCapabilities(manifest) : baseCapabilities(manifest);
|
|
495
|
-
}
|
|
496
|
-
export function pluginRisk(manifest, input) {
|
|
497
|
-
return computeRisk(capabilitiesForRiskScope(manifest, input.scope), manifest);
|
|
498
|
-
}
|
|
499
|
-
export function toolRisk(manifest, tool) {
|
|
500
|
-
return computeRisk(toolCapabilities(manifest, tool), manifest);
|
|
501
|
-
}
|
|
502
|
-
function networkPermissionItem(manifest) {
|
|
503
|
-
const domains = manifest.permissions?.network?.connectDomains ?? [];
|
|
504
|
-
const severity = capabilityRisk("network_request", manifest);
|
|
505
|
-
return {
|
|
506
|
-
key: "network_request",
|
|
507
|
-
category: "network",
|
|
508
|
-
severity,
|
|
509
|
-
title: "Access network",
|
|
510
|
-
description: domains.length > 0
|
|
511
|
-
? `Can make network requests to: ${domains.join(", ")}.`
|
|
512
|
-
: "Can make outbound network requests to any domain.",
|
|
513
|
-
technical: domains.length > 0 ? `domains: ${domains.join(", ")}` : undefined,
|
|
514
|
-
};
|
|
515
|
-
}
|
|
516
|
-
function contributionPermissionItems(manifest) {
|
|
517
|
-
const ui = manifest.contributes?.ui;
|
|
518
|
-
const perms = manifest.permissions?.ui;
|
|
519
|
-
const items = [];
|
|
520
|
-
if (ui?.toolRenderers || perms?.toolRenderers) {
|
|
521
|
-
items.push({
|
|
522
|
-
key: "ui.toolRenderers",
|
|
523
|
-
category: "ui",
|
|
524
|
-
severity: "low",
|
|
525
|
-
title: "Custom tool renderers",
|
|
526
|
-
description: "Overrides how tool outputs appear in the chat UI.",
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
if (ui?.partRenderers || perms?.partRenderers) {
|
|
530
|
-
items.push({
|
|
531
|
-
key: "ui.partRenderers",
|
|
532
|
-
category: "ui",
|
|
533
|
-
severity: "low",
|
|
534
|
-
title: "Custom part renderers",
|
|
535
|
-
description: "Overrides how message parts appear in the chat UI.",
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
if (ui?.workbenchPanels || perms?.workbenchPanels) {
|
|
539
|
-
items.push({
|
|
540
|
-
key: "ui.workbenchPanels",
|
|
541
|
-
category: "ui",
|
|
542
|
-
severity: "low",
|
|
543
|
-
title: "Workbench panels",
|
|
544
|
-
description: "Adds custom panels to the side workspace or BottomSpace.",
|
|
545
|
-
});
|
|
546
|
-
}
|
|
547
|
-
if (ui?.appPanels || perms?.appPanels) {
|
|
548
|
-
items.push({
|
|
549
|
-
key: "ui.appPanels",
|
|
550
|
-
category: "ui",
|
|
551
|
-
severity: "low",
|
|
552
|
-
title: "App panels",
|
|
553
|
-
description: "Adds top-level sidebar panels to the app.",
|
|
554
|
-
});
|
|
555
|
-
}
|
|
556
|
-
if (ui?.settings || perms?.settings) {
|
|
557
|
-
items.push({
|
|
558
|
-
key: "ui.settings",
|
|
559
|
-
category: "ui",
|
|
560
|
-
severity: "low",
|
|
561
|
-
title: "Settings page",
|
|
562
|
-
description: "Adds a custom settings page or form.",
|
|
563
|
-
});
|
|
564
|
-
}
|
|
565
|
-
if (ui?.themes || perms?.themes) {
|
|
566
|
-
items.push({
|
|
567
|
-
key: "ui.themes",
|
|
568
|
-
category: "ui",
|
|
569
|
-
severity: "low",
|
|
570
|
-
title: "Custom themes",
|
|
571
|
-
description: "Adds custom color themes to the UI.",
|
|
572
|
-
});
|
|
573
|
-
}
|
|
574
|
-
if (ui?.icons || perms?.icons) {
|
|
575
|
-
items.push({
|
|
576
|
-
key: "ui.icons",
|
|
577
|
-
category: "ui",
|
|
578
|
-
severity: "low",
|
|
579
|
-
title: "Custom icons",
|
|
580
|
-
description: "Adds custom icon sets to the UI.",
|
|
581
|
-
});
|
|
582
|
-
}
|
|
583
|
-
if (ui?.messageSlots || perms?.messageSlots) {
|
|
584
|
-
items.push({
|
|
585
|
-
key: "ui.messageSlots",
|
|
586
|
-
category: "ui",
|
|
587
|
-
severity: "low",
|
|
588
|
-
title: "Message slots",
|
|
589
|
-
description: "Adds custom components around reasoning and tool timeline sections.",
|
|
590
|
-
});
|
|
591
|
-
}
|
|
592
|
-
if (ui?.appRoutes || perms?.appRoutes) {
|
|
593
|
-
items.push({
|
|
594
|
-
key: "ui.appRoutes",
|
|
595
|
-
category: "ui",
|
|
596
|
-
severity: "low",
|
|
597
|
-
title: "App routes",
|
|
598
|
-
description: "Adds custom plugin pages to the app.",
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
if (ui?.commands || perms?.commands) {
|
|
602
|
-
items.push({
|
|
603
|
-
key: "ui.commands",
|
|
604
|
-
category: "ui",
|
|
605
|
-
severity: "low",
|
|
606
|
-
title: "Custom commands",
|
|
607
|
-
description: "Adds custom UI commands to the command palette.",
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
|
-
return items;
|
|
611
|
-
}
|
|
612
|
-
function dataPermissionItems(manifest) {
|
|
613
|
-
const data = manifest.permissions?.data;
|
|
614
|
-
const items = [];
|
|
615
|
-
if (data?.session === "read") {
|
|
616
|
-
items.push({
|
|
617
|
-
key: "data.session",
|
|
618
|
-
category: "data",
|
|
619
|
-
severity: "medium",
|
|
620
|
-
title: "Read session data",
|
|
621
|
-
description: "Can access session history and metadata across all sessions.",
|
|
622
|
-
});
|
|
623
|
-
}
|
|
624
|
-
else if (data?.session === "metadata") {
|
|
625
|
-
items.push({
|
|
626
|
-
key: "data.session",
|
|
627
|
-
category: "data",
|
|
628
|
-
severity: "low",
|
|
629
|
-
title: "Read session metadata",
|
|
630
|
-
description: "Can access session metadata but not message content.",
|
|
631
|
-
});
|
|
632
|
-
}
|
|
633
|
-
if (data?.workspace === "read") {
|
|
634
|
-
items.push({
|
|
635
|
-
key: "data.workspace",
|
|
636
|
-
category: "data",
|
|
637
|
-
severity: "low",
|
|
638
|
-
title: "Read workspace metadata",
|
|
639
|
-
description: "Can access workspace metadata and directory information.",
|
|
640
|
-
});
|
|
641
|
-
}
|
|
642
|
-
if (data?.secrets === "own") {
|
|
643
|
-
items.push({
|
|
644
|
-
key: "data.secrets",
|
|
645
|
-
category: "data",
|
|
646
|
-
severity: "high",
|
|
647
|
-
title: "Own credential store",
|
|
648
|
-
description: "Can read and write its own stored credentials.",
|
|
649
|
-
});
|
|
650
|
-
}
|
|
651
|
-
return items;
|
|
652
|
-
}
|
|
653
|
-
function hookPermissionItems(manifest) {
|
|
654
|
-
const hooks = manifest.permissions?.hooks;
|
|
655
|
-
const items = [];
|
|
656
|
-
if (hooks?.promptTransform) {
|
|
657
|
-
items.push({
|
|
658
|
-
key: "hooks.promptTransform",
|
|
659
|
-
category: "hooks",
|
|
660
|
-
severity: "high",
|
|
661
|
-
title: "Transform prompts",
|
|
662
|
-
description: "Can modify the system prompt and message context sent to the LLM.",
|
|
663
|
-
});
|
|
664
|
-
}
|
|
665
|
-
if (hooks?.config) {
|
|
666
|
-
items.push({
|
|
667
|
-
key: "hooks.config",
|
|
668
|
-
category: "hooks",
|
|
669
|
-
severity: "medium",
|
|
670
|
-
title: "Observe runtime config",
|
|
671
|
-
description: "Can observe redacted runtime configuration snapshots when Synergy starts or reloads config.",
|
|
672
|
-
});
|
|
673
|
-
}
|
|
674
|
-
if (hooks?.toolExecute === "all") {
|
|
675
|
-
items.push({
|
|
676
|
-
key: "hooks.toolExecute",
|
|
677
|
-
category: "hooks",
|
|
678
|
-
severity: "medium",
|
|
679
|
-
title: "Intercept all tool execution",
|
|
680
|
-
description: "Can rewrite arguments and outputs for all tool calls, including from other plugins.",
|
|
681
|
-
});
|
|
682
|
-
}
|
|
683
|
-
else if (hooks?.toolExecute === "declared") {
|
|
684
|
-
items.push({
|
|
685
|
-
key: "hooks.toolExecute",
|
|
686
|
-
category: "hooks",
|
|
687
|
-
severity: "low",
|
|
688
|
-
title: "Intercept declared tool execution",
|
|
689
|
-
description: "Can rewrite arguments and outputs for tools declared in its manifest.",
|
|
690
|
-
});
|
|
691
|
-
}
|
|
692
|
-
else if (hooks?.toolExecute === "own") {
|
|
693
|
-
items.push({
|
|
694
|
-
key: "hooks.toolExecute",
|
|
695
|
-
category: "hooks",
|
|
696
|
-
severity: "low",
|
|
697
|
-
title: "Intercept own tool execution",
|
|
698
|
-
description: "Can rewrite arguments and outputs for its own tool calls.",
|
|
699
|
-
});
|
|
700
|
-
}
|
|
701
|
-
if (hooks?.permissionAsk === "all") {
|
|
702
|
-
items.push({
|
|
703
|
-
key: "hooks.permissionAsk",
|
|
704
|
-
category: "hooks",
|
|
705
|
-
severity: "high",
|
|
706
|
-
title: "Override all permission decisions",
|
|
707
|
-
description: "Can allow or deny any permission request, including from other plugins.",
|
|
708
|
-
});
|
|
709
|
-
}
|
|
710
|
-
else if (hooks?.permissionAsk === "own") {
|
|
711
|
-
items.push({
|
|
712
|
-
key: "hooks.permissionAsk",
|
|
713
|
-
category: "hooks",
|
|
714
|
-
severity: "medium",
|
|
715
|
-
title: "Override own permission decisions",
|
|
716
|
-
description: "Can allow or deny its own permission requests.",
|
|
717
|
-
});
|
|
718
|
-
}
|
|
719
|
-
return items;
|
|
720
|
-
}
|
|
721
|
-
export function permissionItems(manifest, capabilities) {
|
|
722
|
-
const items = [];
|
|
723
|
-
const seen = new Set();
|
|
724
|
-
const add = (item) => {
|
|
725
|
-
if (seen.has(item.key))
|
|
726
|
-
return;
|
|
727
|
-
seen.add(item.key);
|
|
728
|
-
items.push(item);
|
|
729
|
-
};
|
|
730
|
-
for (const capability of capabilities) {
|
|
731
|
-
if (capability === "network_request") {
|
|
732
|
-
add(networkPermissionItem(manifest));
|
|
733
|
-
continue;
|
|
734
|
-
}
|
|
735
|
-
const details = SYNERGY_CAPABILITY_DETAILS[capability];
|
|
736
|
-
if (details)
|
|
737
|
-
add({ key: capability, ...details });
|
|
738
|
-
}
|
|
739
|
-
for (const item of contributionPermissionItems(manifest))
|
|
740
|
-
add(item);
|
|
741
|
-
for (const item of dataPermissionItems(manifest))
|
|
742
|
-
add(item);
|
|
743
|
-
for (const item of hookPermissionItems(manifest))
|
|
744
|
-
add(item);
|
|
745
|
-
return items;
|
|
746
|
-
}
|
|
747
|
-
export function registryPermissionSummary(manifest, capabilities) {
|
|
748
|
-
return permissionItems(manifest, capabilities).map((item) => ({
|
|
749
|
-
key: item.key,
|
|
750
|
-
description: item.description,
|
|
751
|
-
risk: item.severity,
|
|
752
|
-
}));
|
|
419
|
+
export function capabilityRisk(capability) {
|
|
420
|
+
return SYNERGY_CAPABILITY_DETAILS[capability]?.severity ?? "high";
|
|
753
421
|
}
|
|
754
422
|
export function permissionCategoryForKey(key) {
|
|
755
423
|
const details = SYNERGY_CAPABILITY_DETAILS[key];
|
|
@@ -769,91 +437,3 @@ export function permissionCategoryForKey(key) {
|
|
|
769
437
|
return "browser";
|
|
770
438
|
return "tools";
|
|
771
439
|
}
|
|
772
|
-
export function permissionsHashPayload(manifest, capabilities) {
|
|
773
|
-
return {
|
|
774
|
-
capabilities: [...capabilities].sort(),
|
|
775
|
-
permissions: manifest.permissions ?? {},
|
|
776
|
-
contributes: permissionsRelevantContributes(manifest),
|
|
777
|
-
lifecycle: manifest.lifecycle ?? {},
|
|
778
|
-
};
|
|
779
|
-
}
|
|
780
|
-
function permissionsRelevantContributes(manifest) {
|
|
781
|
-
const contributes = manifest.contributes;
|
|
782
|
-
if (!contributes)
|
|
783
|
-
return undefined;
|
|
784
|
-
return {
|
|
785
|
-
...(contributes.permissions ? { permissions: contributes.permissions } : {}),
|
|
786
|
-
...(contributes.tools
|
|
787
|
-
? {
|
|
788
|
-
tools: contributes.tools.map((tool) => ({
|
|
789
|
-
id: tool.id,
|
|
790
|
-
name: tool.name,
|
|
791
|
-
exposure: tool.exposure,
|
|
792
|
-
capabilities: tool.capabilities,
|
|
793
|
-
})),
|
|
794
|
-
}
|
|
795
|
-
: {}),
|
|
796
|
-
...(contributes.agents
|
|
797
|
-
? {
|
|
798
|
-
agents: contributes.agents.map((agent) => ({
|
|
799
|
-
name: agent.name,
|
|
800
|
-
mode: agent.mode,
|
|
801
|
-
hidden: agent.hidden,
|
|
802
|
-
model: agent.model,
|
|
803
|
-
modelRole: agent.modelRole,
|
|
804
|
-
permission: agent.permission,
|
|
805
|
-
})),
|
|
806
|
-
}
|
|
807
|
-
: {}),
|
|
808
|
-
...(contributes.mcp ? { mcp: contributes.mcp } : {}),
|
|
809
|
-
...(contributes.ui
|
|
810
|
-
? {
|
|
811
|
-
ui: {
|
|
812
|
-
toolRenderers: Boolean(contributes.ui.toolRenderers?.length),
|
|
813
|
-
partRenderers: Boolean(contributes.ui.partRenderers?.length),
|
|
814
|
-
workbenchPanels: Boolean(contributes.ui.workbenchPanels?.length),
|
|
815
|
-
appPanels: Boolean(contributes.ui.appPanels?.length),
|
|
816
|
-
settings: Boolean(contributes.ui.settings?.length),
|
|
817
|
-
messageSlots: Boolean(contributes.ui.messageSlots?.length),
|
|
818
|
-
themes: Boolean(contributes.ui.themes?.length),
|
|
819
|
-
icons: Boolean(contributes.ui.icons?.length),
|
|
820
|
-
appRoutes: Boolean(contributes.ui.appRoutes?.length),
|
|
821
|
-
commands: Boolean(contributes.ui.commands?.length),
|
|
822
|
-
},
|
|
823
|
-
}
|
|
824
|
-
: {}),
|
|
825
|
-
};
|
|
826
|
-
}
|
|
827
|
-
export function manifestHashPayload(manifest) {
|
|
828
|
-
return manifest;
|
|
829
|
-
}
|
|
830
|
-
export function stablePluginJson(value) {
|
|
831
|
-
return JSON.stringify(sortKeys(value));
|
|
832
|
-
}
|
|
833
|
-
export const SYNERGY_BRIDGE_METHOD_POLICY = {
|
|
834
|
-
"config.get": { type: "capability", capability: "config:read" },
|
|
835
|
-
"config.set": { type: "capability", capability: "config:write" },
|
|
836
|
-
"config.replace": { type: "capability", capability: "config:write" },
|
|
837
|
-
"secret.get": { type: "capability", capability: "secrets" },
|
|
838
|
-
"secret.set": { type: "capability", capability: "secrets" },
|
|
839
|
-
"secret.delete": { type: "capability", capability: "secrets" },
|
|
840
|
-
"cache.get": { type: "unprivileged" },
|
|
841
|
-
"cache.set": { type: "unprivileged" },
|
|
842
|
-
"cache.delete": { type: "unprivileged" },
|
|
843
|
-
"file.read": { type: "capability", capability: "file_read" },
|
|
844
|
-
"file.write": { type: "capability", capability: "file_write" },
|
|
845
|
-
"network.fetch": { type: "capability", capability: "network_request" },
|
|
846
|
-
"shell.run": { type: "capability", capability: "shell" },
|
|
847
|
-
"session.getMetadata": { type: "capability", capability: "session_data" },
|
|
848
|
-
"workspace.getMetadata": { type: "capability", capability: "workspace_data" },
|
|
849
|
-
"task.run": { type: "capability", capability: "task" },
|
|
850
|
-
"tool.invoke": { type: "unprivileged" },
|
|
851
|
-
"permission.request": { type: "unprivileged" },
|
|
852
|
-
};
|
|
853
|
-
export function bridgeMethodPolicy(method) {
|
|
854
|
-
return SYNERGY_BRIDGE_METHOD_POLICY[method] ?? { type: "unknown" };
|
|
855
|
-
}
|
|
856
|
-
export function bridgeCapability(method) {
|
|
857
|
-
const policy = bridgeMethodPolicy(method);
|
|
858
|
-
return policy.type === "capability" ? policy.capability : undefined;
|
|
859
|
-
}
|