shadok-ai 0.1.149 → 0.1.151

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/public/index.html +39 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shadok-ai",
3
- "version": "0.1.149",
3
+ "version": "0.1.151",
4
4
  "main": "dist/session.js",
5
5
  "scripts": {
6
6
  "test": "node --import tsx --test test/*.ts .claude/skills/shadok-ai-agents/test/*.test.mjs",
package/public/index.html CHANGED
@@ -2883,6 +2883,45 @@
2883
2883
  await loadVault(); renderSecrets();
2884
2884
  $("secretKey").focus();
2885
2885
  });
2886
+ // Parse un bloc collé façon .env → [{name, value}]. Gère `export KEY=VALUE`,
2887
+ // les guillemets simples/doubles englobants, les commentaires (#) et les
2888
+ // lignes vides. Une ligne sans nom d'env valide avant `=` est ignorée — donc
2889
+ // un collage sans aucune paire valide (ex. un simple nom) laisse le collage
2890
+ // normal remplir le champ NAME.
2891
+ function parseEnvSecrets(text) {
2892
+ const out = [];
2893
+ for (const raw of String(text).split(/\r?\n/)) {
2894
+ let line = raw.trim();
2895
+ if (!line || line.startsWith("#")) continue;
2896
+ if (line.startsWith("export ")) line = line.slice(7).trim();
2897
+ const eq = line.indexOf("=");
2898
+ if (eq <= 0) continue;
2899
+ const name = line.slice(0, eq).trim();
2900
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) continue;
2901
+ let value = line.slice(eq + 1).trim();
2902
+ const q = value[0];
2903
+ if (value.length >= 2 && (q === '"' || q === "'") && value[value.length - 1] === q) {
2904
+ value = value.slice(1, -1);
2905
+ }
2906
+ out.push({ name, value });
2907
+ }
2908
+ return out;
2909
+ }
2910
+ // Coller une liste .env dans le champ NAME ajoute tous les secrets d'un coup.
2911
+ $("secretKey").addEventListener("paste", async (e) => {
2912
+ const text = (e.clipboardData || window.clipboardData).getData("text");
2913
+ const pairs = parseEnvSecrets(text);
2914
+ if (!pairs.length) return; // rien de parsable → collage normal (remplit NAME)
2915
+ e.preventDefault();
2916
+ // Séquentiel : chaque PUT fait un read-modify-write de secrets.json côté
2917
+ // serveur ; les awaits évitent une course sur le fichier.
2918
+ for (const { name, value } of pairs) {
2919
+ await fetch("/secrets", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name, value }) });
2920
+ }
2921
+ $("secretKey").value = ""; $("secretVal").value = "";
2922
+ await loadVault(); renderSecrets();
2923
+ $("secretKey").focus();
2924
+ });
2886
2925
  // ── Profiles panel (global agent roles/guardrails/secret refs) ──────────
2887
2926
  let profileCache = []; // profiles from the server
2888
2927
  let editSecretRefs = []; // secret NAMES the profile being edited injects