shadok-ai 0.2.43 → 0.2.44
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/package.json +1 -1
- package/public/index.html +29 -4
- package/public/profile-card.js +29 -0
package/package.json
CHANGED
package/public/index.html
CHANGED
|
@@ -1550,13 +1550,21 @@
|
|
|
1550
1550
|
qui rend inoffensif le HTML qu'un agent pourrait écrire dans le transcript. -->
|
|
1551
1551
|
<script type="module" nonce="__CSP_NONCE__">
|
|
1552
1552
|
import { extractLiveText } from "/live-text.js";
|
|
1553
|
-
import {
|
|
1553
|
+
import {
|
|
1554
|
+
profileBlurb,
|
|
1555
|
+
profileBadges,
|
|
1556
|
+
defaultAgentName,
|
|
1557
|
+
hasReadonlyPreset,
|
|
1558
|
+
applyReadonlyPreset,
|
|
1559
|
+
} from "/profile-card.js";
|
|
1554
1560
|
import { notifyState, BLINK_MS } from "/notify.js";
|
|
1555
1561
|
import { dialPos, dialColor, arcSegments, dialTitle, SWEEP_DEG } from "/gauge-dial.js";
|
|
1556
1562
|
window.extractLiveText = extractLiveText;
|
|
1557
1563
|
window.profileBlurb = profileBlurb;
|
|
1558
1564
|
window.profileBadges = profileBadges;
|
|
1559
1565
|
window.defaultAgentName = defaultAgentName;
|
|
1566
|
+
window.hasReadonlyPreset = hasReadonlyPreset;
|
|
1567
|
+
window.applyReadonlyPreset = applyReadonlyPreset;
|
|
1560
1568
|
window.notifyState = notifyState;
|
|
1561
1569
|
window.BLINK_MS = BLINK_MS;
|
|
1562
1570
|
window.dialPos = dialPos;
|
|
@@ -4665,14 +4673,14 @@
|
|
|
4665
4673
|
$("profRole").value = p.systemPrompt || "";
|
|
4666
4674
|
$("profDeny").value = (p.deny || []).join("\n");
|
|
4667
4675
|
$("profModel").value = p.model || "";
|
|
4668
|
-
|
|
4676
|
+
syncReadonlyBox(); // la case suit le deny réel, elle n'est plus figée à false
|
|
4669
4677
|
editSecretRefs = [...(p.secrets || [])];
|
|
4670
4678
|
renderProfSecrets();
|
|
4671
4679
|
}
|
|
4672
4680
|
function clearProfileForm() {
|
|
4673
4681
|
$("profEditTitle").textContent = "New profile";
|
|
4674
4682
|
$("profName").value = ""; $("profRole").value = ""; $("profDeny").value = ""; $("profModel").value = "";
|
|
4675
|
-
$("profReadonly").checked = false; editSecretRefs = [];
|
|
4683
|
+
$("profReadonly").checked = false; editSecretRefs = []; // zone deny vidée juste au-dessus
|
|
4676
4684
|
renderProfSecrets();
|
|
4677
4685
|
}
|
|
4678
4686
|
// The profile's secrets are checkboxes over the vault: pick which named
|
|
@@ -4694,7 +4702,24 @@
|
|
|
4694
4702
|
}
|
|
4695
4703
|
}
|
|
4696
4704
|
const READONLY_DENY = ["Bash(git commit:*)","Bash(git push:*)","Bash(git add:*)","Bash(git reset:*)","Bash(git rebase:*)","Bash(git merge:*)","Bash(git checkout:*)"];
|
|
4697
|
-
|
|
4705
|
+
/** Les motifs saisis, un par ligne, sans les vides. */
|
|
4706
|
+
function denyLines() {
|
|
4707
|
+
return $("profDeny").value.split("\n").map((x) => x.trim()).filter(Boolean);
|
|
4708
|
+
}
|
|
4709
|
+
/** La case reflète la zone de texte, qui reste la source de vérité. */
|
|
4710
|
+
function syncReadonlyBox() {
|
|
4711
|
+
$("profReadonly").checked = window.hasReadonlyPreset
|
|
4712
|
+
? window.hasReadonlyPreset(denyLines(), READONLY_DENY)
|
|
4713
|
+
: false;
|
|
4714
|
+
}
|
|
4715
|
+
// Interrupteur à DOUBLE SENS. L'ancien ne réagissait qu'au cochage et écrasait
|
|
4716
|
+
// toute la zone : décocher ne faisait rien, et un motif perso disparaissait.
|
|
4717
|
+
$("profReadonly").addEventListener("change", (e) => {
|
|
4718
|
+
$("profDeny").value = window.applyReadonlyPreset(denyLines(), e.target.checked, READONLY_DENY).join("\n");
|
|
4719
|
+
});
|
|
4720
|
+
// Éditer les motifs à la main doit remettre la case d'accord avec eux, sinon
|
|
4721
|
+
// elle se remet à mentir dès la première ligne tapée.
|
|
4722
|
+
$("profDeny").addEventListener("input", syncReadonlyBox);
|
|
4698
4723
|
$("profSave").addEventListener("click", async () => {
|
|
4699
4724
|
const name = $("profName").value.trim(); if (!name) return alert("Name required.");
|
|
4700
4725
|
const body = {
|
package/public/profile-card.js
CHANGED
|
@@ -78,3 +78,32 @@ export function defaultAgentName(profileName, cwd) {
|
|
|
78
78
|
const base = dir.split(/[/\\]/).pop() || "";
|
|
79
79
|
return base || "agent";
|
|
80
80
|
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* La case « read-only » du formulaire de profil reflète-t-elle un profil
|
|
84
|
+
* réellement read-only ? Vrai seulement si TOUT le preset est présent : un
|
|
85
|
+
* preset à moitié appliqué ne doit pas se donner des airs d'être en place.
|
|
86
|
+
*
|
|
87
|
+
* Volontairement plus strict que le badge de la carte, qui répond à une autre
|
|
88
|
+
* question — « ce profil a-t-il des garde-fous ? » — et s'allume dès qu'il
|
|
89
|
+
* existe un `deny`, fût-il personnalisé.
|
|
90
|
+
*/
|
|
91
|
+
export function hasReadonlyPreset(deny, preset) {
|
|
92
|
+
const have = new Set(deny || []);
|
|
93
|
+
return (preset || []).length > 0 && preset.every((p) => have.has(p));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Coche/décoche le preset SANS toucher aux motifs personnalisés : décocher
|
|
98
|
+
* retire les motifs du preset et laisse le reste, cocher ajoute ceux qui
|
|
99
|
+
* manquent en fin de liste. La zone de texte reste la source de vérité — elle
|
|
100
|
+
* n'est jamais écrasée en bloc, ce que faisait l'ancien gestionnaire.
|
|
101
|
+
*/
|
|
102
|
+
export function applyReadonlyPreset(deny, on, preset) {
|
|
103
|
+
const list = [...(deny || [])];
|
|
104
|
+
const p = preset || [];
|
|
105
|
+
if (!on) return list.filter((x) => !p.includes(x));
|
|
106
|
+
const have = new Set(list);
|
|
107
|
+
for (const x of p) if (!have.has(x)) list.push(x);
|
|
108
|
+
return list;
|
|
109
|
+
}
|