@miller-tech/uap 1.145.0 → 1.146.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/.tsbuildinfo +1 -1
- package/dist/dashboard/server.d.ts.map +1 -1
- package/dist/dashboard/server.js +189 -0
- package/dist/dashboard/server.js.map +1 -1
- package/dist/memory/embeddings.d.ts.map +1 -1
- package/dist/memory/embeddings.js +4 -2
- package/dist/memory/embeddings.js.map +1 -1
- package/dist/policies/policy-memory.d.ts +29 -0
- package/dist/policies/policy-memory.d.ts.map +1 -1
- package/dist/policies/policy-memory.js +81 -0
- package/dist/policies/policy-memory.js.map +1 -1
- package/dist/policies/policy-order.d.ts +51 -0
- package/dist/policies/policy-order.d.ts.map +1 -0
- package/dist/policies/policy-order.js +124 -0
- package/dist/policies/policy-order.js.map +1 -0
- package/package.json +1 -1
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
- package/tools/agents/scripts/anthropic_proxy.py +127 -2
- package/tools/agents/tests/test_vision_passthrough.py +126 -0
- package/web/dash/styles.css +31 -0
- package/web/dash/tab-policies.js +229 -8
- package/web/dashboard.html +3 -0
package/web/dash/tab-policies.js
CHANGED
|
@@ -1,12 +1,233 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* tab-policies.js —
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* tab-policies.js — Policy management panel.
|
|
3
|
+
*
|
|
4
|
+
* Lists every policy ordered by firing priority (fires-earliest first) and lets
|
|
5
|
+
* the operator: view each policy's description + full prompt, toggle it, change
|
|
6
|
+
* level/stage, duplicate it, drag-and-drop to reorder (manual), ask for an
|
|
7
|
+
* intelligent order (heuristic + AI refine), dedupe, and import/export the whole
|
|
8
|
+
* set. All DOM is built with UAP.el (no innerHTML), mutations go through UAP.api
|
|
9
|
+
* (token-guarded); GET reads use fetch on UAP.API_URL.
|
|
5
10
|
*/
|
|
11
|
+
(function () {
|
|
12
|
+
'use strict';
|
|
13
|
+
if (typeof UAP === 'undefined' || !UAP.registerTab) return;
|
|
14
|
+
var el = UAP.el, api = UAP.api, toast = UAP.toast;
|
|
6
15
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
16
|
+
function get(path) {
|
|
17
|
+
return fetch(UAP.API_URL + path).then(function (r) {
|
|
18
|
+
if (!r.ok) throw new Error('HTTP ' + r.status);
|
|
19
|
+
return r.json();
|
|
20
|
+
});
|
|
11
21
|
}
|
|
12
|
-
|
|
22
|
+
|
|
23
|
+
var LEVELS = ['REQUIRED', 'RECOMMENDED', 'OPTIONAL'];
|
|
24
|
+
var STAGES = ['pre-exec', 'always', 'post-exec', 'review'];
|
|
25
|
+
|
|
26
|
+
function badge(text, cls) { return el('span', { class: 'pol-badge ' + (cls || ''), text: text }); }
|
|
27
|
+
|
|
28
|
+
function reloadInto(listEl) {
|
|
29
|
+
UAP.clear(listEl);
|
|
30
|
+
listEl.appendChild(el('div', { class: 'muted', text: 'Loading policies…' }));
|
|
31
|
+
return get('/api/policies').then(function (d) {
|
|
32
|
+
renderList(listEl, (d && d.policies) || []);
|
|
33
|
+
}).catch(function (e) {
|
|
34
|
+
UAP.clear(listEl);
|
|
35
|
+
listEl.appendChild(el('div', { class: 'empty', text: 'Failed to load policies: ' + e.message }));
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Drag-and-drop reorder: track the dragged row, reorder DOM on hover, then
|
|
40
|
+
// persist the new id order via /api/policies/reorder on drop.
|
|
41
|
+
function attachDnD(row, listEl) {
|
|
42
|
+
row.setAttribute('draggable', 'true');
|
|
43
|
+
row.addEventListener('dragstart', function (e) {
|
|
44
|
+
row.classList.add('dragging');
|
|
45
|
+
e.dataTransfer.effectAllowed = 'move';
|
|
46
|
+
try { e.dataTransfer.setData('text/plain', row.dataset.id); } catch (_) {}
|
|
47
|
+
});
|
|
48
|
+
row.addEventListener('dragend', function () {
|
|
49
|
+
row.classList.remove('dragging');
|
|
50
|
+
persistOrder(listEl);
|
|
51
|
+
});
|
|
52
|
+
row.addEventListener('dragover', function (e) {
|
|
53
|
+
e.preventDefault();
|
|
54
|
+
var dragging = listEl.querySelector('.pol-row.dragging');
|
|
55
|
+
if (!dragging || dragging === row) return;
|
|
56
|
+
var rect = row.getBoundingClientRect();
|
|
57
|
+
var after = (e.clientY - rect.top) > rect.height / 2;
|
|
58
|
+
listEl.insertBefore(dragging, after ? row.nextSibling : row);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function persistOrder(listEl) {
|
|
63
|
+
var ids = [];
|
|
64
|
+
listEl.querySelectorAll('.pol-row').forEach(function (r) { ids.push(r.dataset.id); });
|
|
65
|
+
api('/api/policies/reorder', { order: ids })
|
|
66
|
+
.then(function () { toast('Order saved', 'ok'); })
|
|
67
|
+
.catch(function () {});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function policyRow(p, listEl) {
|
|
71
|
+
var row = el('div', { class: 'pol-row' + (p.isActive ? '' : ' off') });
|
|
72
|
+
row.dataset.id = p.id;
|
|
73
|
+
var handle = el('span', { class: 'pol-handle', title: 'Drag to reorder' }, '⠿');
|
|
74
|
+
var main = el('div', { class: 'pol-main' },
|
|
75
|
+
el('div', { class: 'pol-name', text: p.name }),
|
|
76
|
+
el('div', { class: 'pol-desc', text: p.description || '(no description)' }),
|
|
77
|
+
el('div', { class: 'pol-badges' },
|
|
78
|
+
badge(p.level, 'lvl-' + String(p.level || '').toLowerCase()),
|
|
79
|
+
badge(p.stage, 'stage'),
|
|
80
|
+
badge(p.category, 'cat'),
|
|
81
|
+
badge('prio ' + p.priority, 'prio')
|
|
82
|
+
)
|
|
83
|
+
);
|
|
84
|
+
var actions = el('div', { class: 'pol-actions' },
|
|
85
|
+
el('button', { class: 'btn btn-sm', title: 'View description + prompt', onclick: function () { openDetail(p.id); } }, 'View'),
|
|
86
|
+
el('button', { class: 'btn btn-sm', title: 'Duplicate', onclick: function () { duplicate(p.id, listEl); } }, 'Duplicate'),
|
|
87
|
+
el('button', {
|
|
88
|
+
class: 'btn btn-sm ' + (p.isActive ? 'btn-on' : 'btn-off'),
|
|
89
|
+
title: p.isActive ? 'Enabled — click to disable' : 'Disabled — click to enable',
|
|
90
|
+
onclick: function () { toggle(p.id, listEl); }
|
|
91
|
+
}, p.isActive ? 'On' : 'Off')
|
|
92
|
+
);
|
|
93
|
+
row.appendChild(handle);
|
|
94
|
+
row.appendChild(main);
|
|
95
|
+
row.appendChild(actions);
|
|
96
|
+
attachDnD(row, listEl);
|
|
97
|
+
return row;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function renderList(listEl, policies) {
|
|
101
|
+
UAP.clear(listEl);
|
|
102
|
+
if (!policies.length) {
|
|
103
|
+
listEl.appendChild(el('div', { class: 'empty', text: 'No policies installed. Import a bundle or run setup.' }));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
policies.forEach(function (p) { listEl.appendChild(policyRow(p, listEl)); });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function toggle(id, listEl) {
|
|
110
|
+
api('/api/policy/' + id + '/toggle').then(function () { reloadInto(listEl); }).catch(function () {});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function duplicate(id, listEl) {
|
|
114
|
+
api('/api/policy/' + id + '/duplicate').then(function () {
|
|
115
|
+
toast('Policy duplicated', 'ok');
|
|
116
|
+
reloadInto(listEl);
|
|
117
|
+
}).catch(function () {});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function openDetail(id) {
|
|
121
|
+
get('/api/policy/' + id).then(function (p) {
|
|
122
|
+
var body = el('div', { class: 'pol-detail' },
|
|
123
|
+
el('div', { class: 'pol-badges' },
|
|
124
|
+
badge(p.level, 'lvl-' + String(p.level || '').toLowerCase()),
|
|
125
|
+
badge(p.stage, 'stage'),
|
|
126
|
+
badge(p.category, 'cat'),
|
|
127
|
+
badge('prio ' + p.priority, 'prio'),
|
|
128
|
+
badge(p.isActive ? 'enabled' : 'disabled', p.isActive ? 'on' : 'off')
|
|
129
|
+
),
|
|
130
|
+
el('label', { class: 'field' }, 'Level',
|
|
131
|
+
selectFor(LEVELS, p.level, function (v) { api('/api/policy/' + id + '/level', { level: v }).then(function () { toast('Level updated', 'ok'); }); })),
|
|
132
|
+
el('label', { class: 'field' }, 'Stage',
|
|
133
|
+
selectFor(STAGES, p.stage, function (v) { api('/api/policy/' + id + '/stage', { stage: v }).then(function () { toast('Stage updated', 'ok'); }); })),
|
|
134
|
+
el('div', { class: 'pol-section-label', text: 'Description' }),
|
|
135
|
+
el('div', { class: 'pol-desc-full', text: p.description || '(none)' }),
|
|
136
|
+
el('div', { class: 'pol-section-label', text: 'Prompt (rawMarkdown)' }),
|
|
137
|
+
el('pre', { class: 'pol-prompt', text: p.rawMarkdown || '' })
|
|
138
|
+
);
|
|
139
|
+
UAP.drawer(p.name, body);
|
|
140
|
+
}).catch(function (e) { toast('Failed to load policy: ' + e.message, 'err'); });
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function selectFor(options, current, onChange) {
|
|
144
|
+
var sel = el('select', { class: 'pol-select' });
|
|
145
|
+
options.forEach(function (o) {
|
|
146
|
+
var opt = el('option', { value: o, text: o });
|
|
147
|
+
if (o === current) opt.selected = true;
|
|
148
|
+
sel.appendChild(opt);
|
|
149
|
+
});
|
|
150
|
+
sel.addEventListener('change', function () { onChange(sel.value); });
|
|
151
|
+
return sel;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function suggestOrder(listEl) {
|
|
155
|
+
toast('Computing intelligent order…', 'ok');
|
|
156
|
+
api('/api/policies/suggest-order', { ai: true }).then(function (res) {
|
|
157
|
+
var order = res.order || [];
|
|
158
|
+
var list = el('ol', { class: 'pol-suggest-list' });
|
|
159
|
+
order.forEach(function (o) { list.appendChild(el('li', { text: o.name })); });
|
|
160
|
+
var body = el('div', { class: 'pol-suggest' },
|
|
161
|
+
el('div', { class: 'pol-badges' }, badge(res.source === 'ai' ? 'AI refined' : 'heuristic', res.source === 'ai' ? 'on' : 'cat')),
|
|
162
|
+
el('div', { class: 'pol-section-label', text: 'Rationale' }),
|
|
163
|
+
el('div', { class: 'pol-desc-full', text: res.rationale || '' }),
|
|
164
|
+
el('div', { class: 'pol-section-label', text: 'Proposed firing order (first fires earliest)' }),
|
|
165
|
+
list,
|
|
166
|
+
el('div', { class: 'modal-actions' },
|
|
167
|
+
el('button', { class: 'btn btn-primary', onclick: function () {
|
|
168
|
+
api('/api/policies/reorder', { order: order.map(function (o) { return o.id; }) }).then(function () {
|
|
169
|
+
toast('Applied intelligent order', 'ok');
|
|
170
|
+
UAP.closeDrawer();
|
|
171
|
+
reloadInto(listEl);
|
|
172
|
+
});
|
|
173
|
+
} }, 'Apply this order'))
|
|
174
|
+
);
|
|
175
|
+
UAP.drawer('Intelligent policy order', body);
|
|
176
|
+
}).catch(function (e) { toast('Suggest failed: ' + e.message, 'err'); });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function dedupe(listEl) {
|
|
180
|
+
api('/api/policies/dedupe').then(function (res) {
|
|
181
|
+
toast(res.removed ? ('Removed ' + res.removed + ' duplicate(s)') : 'No duplicates found', 'ok');
|
|
182
|
+
reloadInto(listEl);
|
|
183
|
+
}).catch(function () {});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function exportPolicies() {
|
|
187
|
+
// GET download — navigate to the export endpoint (Content-Disposition attachment).
|
|
188
|
+
var a = el('a', { href: UAP.API_URL + '/api/policies/export', download: 'uap-policies.json' });
|
|
189
|
+
document.body.appendChild(a);
|
|
190
|
+
a.click();
|
|
191
|
+
document.body.removeChild(a);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function importPolicies(listEl) {
|
|
195
|
+
var input = el('input', { type: 'file', accept: '.json,application/json', style: 'display:none' });
|
|
196
|
+
input.addEventListener('change', function () {
|
|
197
|
+
var file = input.files && input.files[0];
|
|
198
|
+
if (!file) return;
|
|
199
|
+
var reader = new FileReader();
|
|
200
|
+
reader.onload = function () {
|
|
201
|
+
var bundle;
|
|
202
|
+
try { bundle = JSON.parse(String(reader.result)); }
|
|
203
|
+
catch (e) { toast('Invalid JSON bundle', 'err'); return; }
|
|
204
|
+
api('/api/policies/import', bundle).then(function (res) {
|
|
205
|
+
toast('Imported ' + (res.imported || 0) + ' policies', 'ok');
|
|
206
|
+
reloadInto(listEl);
|
|
207
|
+
}).catch(function () {});
|
|
208
|
+
};
|
|
209
|
+
reader.readAsText(file);
|
|
210
|
+
});
|
|
211
|
+
document.body.appendChild(input);
|
|
212
|
+
input.click();
|
|
213
|
+
document.body.removeChild(input);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function render(root) {
|
|
217
|
+
UAP.clear(root);
|
|
218
|
+
var listEl = el('div', { class: 'pol-list' });
|
|
219
|
+
var toolbar = el('div', { class: 'pol-toolbar' },
|
|
220
|
+
el('button', { class: 'btn btn-primary', onclick: function () { suggestOrder(listEl); } }, '✨ AI suggest order'),
|
|
221
|
+
el('button', { class: 'btn', onclick: function () { dedupe(listEl); } }, 'Dedupe'),
|
|
222
|
+
el('button', { class: 'btn', onclick: function () { importPolicies(listEl); } }, 'Import'),
|
|
223
|
+
el('button', { class: 'btn', onclick: function () { exportPolicies(); } }, 'Export'),
|
|
224
|
+
el('button', { class: 'btn', onclick: function () { reloadInto(listEl); } }, 'Refresh')
|
|
225
|
+
);
|
|
226
|
+
root.appendChild(el('div', { class: 'pol-hint', text: 'Drag rows to reorder (earlier = fires first). Order minimizes wasted turns: cheap, high-block gates fire first.' }));
|
|
227
|
+
root.appendChild(toolbar);
|
|
228
|
+
root.appendChild(listEl);
|
|
229
|
+
reloadInto(listEl);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
UAP.registerTab('policies', { label: 'Policies', render: render });
|
|
233
|
+
})();
|
package/web/dashboard.html
CHANGED
|
@@ -47,5 +47,8 @@
|
|
|
47
47
|
<script src="/dash/charts.js"></script>
|
|
48
48
|
<script src="/dash/core.js"></script>
|
|
49
49
|
<script src="/dash/tabs.js"></script>
|
|
50
|
+
<!-- Loaded AFTER tabs.js so its registerTab('policies') overrides the inline
|
|
51
|
+
stub with the full policy-management panel (view/duplicate/reorder/AI-order/import/export). -->
|
|
52
|
+
<script src="/dash/tab-policies.js"></script>
|
|
50
53
|
</body>
|
|
51
54
|
</html>
|