@duke-dsh-plugins/dsh-agent-approval 1.3.0 → 1.3.2
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/client.js +76 -0
- package/cordis.patch.yml +1 -1
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -56,6 +56,17 @@ window.__ModuleLoader__.load({
|
|
|
56
56
|
hover/active colors without changing the shell's 16px icon rhythm. */
|
|
57
57
|
[data-dsh-agent-approval-settings-nav]>svg:first-child{display:none}
|
|
58
58
|
[data-dsh-agent-approval-settings-nav]::before{content:'';flex:none;width:16px;height:16px;background:currentColor;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z'/%3E%3Cpath d='m9 12 2 2 4-4'/%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z'/%3E%3Cpath d='m9 12 2 2 4-4'/%3E%3C/svg%3E") center/contain no-repeat}
|
|
59
|
+
|
|
60
|
+
/* /permission menu + composer permission trigger: both pick icons from the
|
|
61
|
+
permissionGlyphs map compiled into the official dsh-client-ui-conversation
|
|
62
|
+
bundle ("host-configured names outside the design set get none") — there is
|
|
63
|
+
no public registration seam, so an external preset row renders with no icon
|
|
64
|
+
element at all. registerPermissionGlyphIcon marks the Agent 审批 menu row
|
|
65
|
+
([role=menu] button[role=menuitem]) and the composer trigger button; CSS
|
|
66
|
+
draws the same shield + AI-star glyph patch-glyph.mjs used, as a
|
|
67
|
+
currentColor mask so hover/selected/disabled colors all follow the shell. */
|
|
68
|
+
[data-dsh-agent-approval-perm-item]::before,
|
|
69
|
+
[data-dsh-agent-approval-perm-trigger]::before{content:'';flex:none;width:16px;height:16px;background:currentColor;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M8.20554 0.899994L14.7901 3.36857V7.01026C14.7901 12 11.0466 14.2103 8.20554 15.3C5.36446 14.2103 1.62012 12 1.62012 7.01026V3.36857L8.20554 0.899994Z' stroke='black' stroke-width='1.31831' stroke-linejoin='round'/%3E%3Cpath d='M8 3.2L9.1 5.9L11.8 7L9.1 8.1L8 10.8L6.9 8.1L4.2 7L6.9 5.9Z' fill='black'/%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M8.20554 0.899994L14.7901 3.36857V7.01026C14.7901 12 11.0466 14.2103 8.20554 15.3C5.36446 14.2103 1.62012 12 1.62012 7.01026V3.36857L8.20554 0.899994Z' stroke='black' stroke-width='1.31831' stroke-linejoin='round'/%3E%3Cpath d='M8 3.2L9.1 5.9L11.8 7L9.1 8.1L8 10.8L6.9 8.1L4.2 7L6.9 5.9Z' fill='black'/%3E%3C/svg%3E") center/contain no-repeat}
|
|
59
70
|
`;
|
|
60
71
|
|
|
61
72
|
// ---- Settings nav icon --------------------------------------------------
|
|
@@ -94,6 +105,66 @@ window.__ModuleLoader__.load({
|
|
|
94
105
|
};
|
|
95
106
|
}
|
|
96
107
|
|
|
108
|
+
// ---- /permission menu + composer trigger icon ----------------------------
|
|
109
|
+
// The permission surfaces (menu rows and the composer trigger button) pick
|
|
110
|
+
// icons from the permissionGlyphs map compiled into the official
|
|
111
|
+
// dsh-client-ui-conversation bundle — external presets get no icon element
|
|
112
|
+
// at all (see PermissionSelect: `icon === void 0 ? {} : { icon }`). Mark
|
|
113
|
+
// the two surfaces whose label is this preset's display name so the CSS
|
|
114
|
+
// above can paint the glyph; the disposer clears both markers.
|
|
115
|
+
const PERM_ITEM_MARKER = "data-dsh-agent-approval-perm-item";
|
|
116
|
+
const PERM_TRIGGER_MARKER = "data-dsh-agent-approval-perm-trigger";
|
|
117
|
+
|
|
118
|
+
function registerPermissionGlyphIcon(label) {
|
|
119
|
+
let disposed = false;
|
|
120
|
+
const sync = function () {
|
|
121
|
+
if (disposed) return;
|
|
122
|
+
const currentLabel = String(label).trim();
|
|
123
|
+
if (currentLabel.length === 0) return;
|
|
124
|
+
// 1) /permission menu rows: Menu renders [itemIcon?][itemLabel][check?]
|
|
125
|
+
// inside button[role=menuitem]; an icon-less row starts at the label.
|
|
126
|
+
const items = document.querySelectorAll('[role="menu"] button[role="menuitem"]');
|
|
127
|
+
for (let i = 0; i < items.length; i++) {
|
|
128
|
+
const button = items[i];
|
|
129
|
+
const text = button.textContent ? button.textContent.trim() : "";
|
|
130
|
+
if (text === currentLabel) button.setAttribute(PERM_ITEM_MARKER, "");
|
|
131
|
+
else button.removeAttribute(PERM_ITEM_MARKER);
|
|
132
|
+
}
|
|
133
|
+
// 2) Composer trigger button: [triggerIcon?][triggerLabel][chevron svg];
|
|
134
|
+
// with no glyph the icon span is absent, leaving label + chevron.
|
|
135
|
+
// Skip menu rows (handled above) and the settings dialog (its nav
|
|
136
|
+
// row carries the same label but is owned by the settings-nav icon).
|
|
137
|
+
const buttons = document.querySelectorAll("button");
|
|
138
|
+
for (let i = 0; i < buttons.length; i++) {
|
|
139
|
+
const button = buttons[i];
|
|
140
|
+
if (button.getAttribute("role") === "menuitem") continue;
|
|
141
|
+
if (button.closest('[role="dialog"]') !== null) continue;
|
|
142
|
+
if (button.hasAttribute(SETTINGS_NAV_MARKER)) continue;
|
|
143
|
+
const spans = button.querySelectorAll(":scope > span");
|
|
144
|
+
let labelText = "";
|
|
145
|
+
for (let j = 0; j < spans.length; j++) {
|
|
146
|
+
const s = spans[j].textContent ? spans[j].textContent.trim() : "";
|
|
147
|
+
if (s.length > 0) { labelText = s; break; }
|
|
148
|
+
}
|
|
149
|
+
const matches = labelText === currentLabel && button.querySelector("svg") !== null;
|
|
150
|
+
if (matches) button.setAttribute(PERM_TRIGGER_MARKER, "");
|
|
151
|
+
else button.removeAttribute(PERM_TRIGGER_MARKER);
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
sync();
|
|
155
|
+
const observer = new MutationObserver(sync);
|
|
156
|
+
observer.observe(document.body, { childList: true, subtree: true, characterData: true });
|
|
157
|
+
return function () {
|
|
158
|
+
disposed = true;
|
|
159
|
+
observer.disconnect();
|
|
160
|
+
const names = [PERM_ITEM_MARKER, PERM_TRIGGER_MARKER];
|
|
161
|
+
for (let n = 0; n < names.length; n++) {
|
|
162
|
+
const marked = document.querySelectorAll("[" + names[n] + "]");
|
|
163
|
+
for (let i = 0; i < marked.length; i++) marked[i].removeAttribute(names[n]);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
97
168
|
// ---- Client Remote contribution -------------------------------------------
|
|
98
169
|
// The browser-side `remote.agentApproval` service only exists after this
|
|
99
170
|
// module mounts its namespace via ctx.remote.$mount(): dsh-api-remotes'
|
|
@@ -190,6 +261,11 @@ window.__ModuleLoader__.load({
|
|
|
190
261
|
// fallback gear (no icon field exists in settings.section yet).
|
|
191
262
|
ctx.effect(() => registerSettingsNavIcon(SETTINGS_LABEL));
|
|
192
263
|
|
|
264
|
+
// Mark the /permission menu row and the composer trigger button so the
|
|
265
|
+
// CSS above paints the preset glyph (external presets get no icon from
|
|
266
|
+
// the official permissionGlyphs map; no public registration seam).
|
|
267
|
+
ctx.effect(() => registerPermissionGlyphIcon(SETTINGS_LABEL));
|
|
268
|
+
|
|
193
269
|
// ctx.get() reads the service without the property-accessor inject guard.
|
|
194
270
|
const remote = ctx.get("remote.agentApproval");
|
|
195
271
|
|
package/cordis.patch.yml
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# registers the Agent 审批 preset in the permission menu.
|
|
3
3
|
- insert:
|
|
4
4
|
- id: agent-approval
|
|
5
|
-
name: 'dsh-agent-approval'
|
|
5
|
+
name: '@duke-dsh-plugins/dsh-agent-approval'
|
|
6
6
|
|
|
7
7
|
# --- dsh-agent-approval: register the Agent 审批 preset in the permission menu ---
|
|
8
8
|
# Restates the full presets table because a patch REPLACES the `permission`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@duke-dsh-plugins/dsh-agent-approval",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "Agent-decided approvals for DeepSeek Harness: a workspace-write base permission mode where an independent approval subagent judges every sandbox escalation (risky operations are rejected), with a configurable approval model and an audit log in Settings.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|