shadok-ai 0.8.17 → 0.8.18

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 +69 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shadok-ai",
3
- "version": "0.8.17",
3
+ "version": "0.8.18",
4
4
  "main": "dist/session.js",
5
5
  "scripts": {
6
6
  "test": "node --import tsx --test test/*.ts context/*/test/*.test.mjs",
package/public/index.html CHANGED
@@ -679,6 +679,12 @@
679
679
  .prof-drift { margin-left: 8px; font-size: 11px; color: var(--amber); }
680
680
  /* À qui ce secret est injecté. Discret : c'est une information de contexte,
681
681
  pas une alerte — contrairement à sec-orphan juste en dessous. */
682
+ /* Le pont ESM n'a jamais chargé : le dire plutôt que d'afficher un écran
683
+ amputé sans explication. */
684
+ .bridge-dead {
685
+ position: fixed; left: 50%; transform: translateX(-50%); bottom: 12px; z-index: 200;
686
+ background: #e2564a; color: #fff; padding: 8px 14px; border-radius: 8px; font-size: 13px;
687
+ }
682
688
  .sec-users { margin-left: 8px; font-size: 11px; color: var(--text-dim); }
683
689
  .sec-orphan { margin-left: 8px; font-size: 11px; color: var(--amber); font-family: var(--sans, inherit); }
684
690
  /* Profile picker for a running agent (the tab's context menu). */
@@ -1985,8 +1991,71 @@
1985
1991
  window.arcSegments = arcSegments;
1986
1992
  window.dialTitle = dialTitle;
1987
1993
  window.SWEEP_DEG = SWEEP_DEG;
1994
+ // Les bouchons du script classique sont maintenant remplacés par les vraies
1995
+ // fonctions : tout ce qui a pu être peint entre-temps est incomplet.
1996
+ window.dispatchEvent(new Event("shadok-bridge-ready"));
1988
1997
  </script>
1989
1998
  <script nonce="__CSP_NONCE__">
1999
+ // ── Bouchons du pont ESM (invariant 10) ─────────────────────────────────
2000
+ // Le bloc module ci-dessus est DIFFÉRÉ : il s'exécute après le parsing,
2001
+ // alors que ce script-ci tourne PENDANT et câble déjà les boutons.
2002
+ // Un clic dans cet intervalle appelait un window.<fn> inexistant — c'est
2003
+ // ainsi que `profileBadges` a levé sur un clic Secrets, à cinq lignes d'un
2004
+ // appel voisin correctement gardé. Garder chaque site d'appel était un
2005
+ // combat perdu : le suivant oubliait. Un bouchon neutre par nom, remplacé à
2006
+ // l'arrivée du module, rend tous les sites sûrs par construction.
2007
+ // test/esm-bridge.test.ts verrouille la correspondance nom ↔ bouchon.
2008
+ const BRIDGE_STUBS = {
2009
+ profileBlurb: () => "",
2010
+ profileBadges: () => [],
2011
+ defaultAgentName: (_p, cwd) => String(cwd ?? "").split("/").filter(Boolean).pop() || "agent",
2012
+ hasReadonlyPreset: () => false,
2013
+ applyReadonlyPreset: (deny) => deny,
2014
+ isManagedProfile: () => false,
2015
+ profileSaveBody: (form) => ({ ...form }),
2016
+ secretUsers: () => [],
2017
+ extractLiveText: () => "",
2018
+ livePreviewDecision: () => null,
2019
+ echoAuthor: () => "",
2020
+ notifyState: () => ({ color: null, badge: "", blink: false }),
2021
+ dialPos: () => 0,
2022
+ dialColor: () => "",
2023
+ arcSegments: () => [],
2024
+ dialTitle: () => "",
2025
+ bubblePlacement: () => null,
2026
+ unionRect: () => null,
2027
+ visibleSteps: (steps) => steps ?? [],
2028
+ };
2029
+ for (const [name, stub] of Object.entries(BRIDGE_STUBS)) {
2030
+ if (typeof window[name] !== "function") { stub.__stub = true; window[name] = stub; }
2031
+ }
2032
+ // Un bouchon empêche le plantage, il ne remplace pas la fonction : si le
2033
+ // module n'arrive JAMAIS (un des six fichiers en échec, une coupure), l'écran
2034
+ // resterait silencieusement amputé — pas de badges, pas d'aperçu en direct,
2035
+ // pas de notifications. Une dégradation muette est pire que l'erreur qu'elle
2036
+ // masque : on le dit.
2037
+ window.addEventListener("load", () => setTimeout(() => {
2038
+ const dead = Object.keys(BRIDGE_STUBS).filter((n) => window[n] && window[n].__stub);
2039
+ if (!dead.length) return;
2040
+ console.error("shadok-ai: le pont ESM n'a pas chargé — " + dead.join(", "));
2041
+ const bar = document.createElement("div");
2042
+ bar.className = "bridge-dead";
2043
+ bar.textContent = "⚠ This page did not load fully — some panels will look empty. Reload it.";
2044
+ document.body.appendChild(bar);
2045
+ }, 3000));
2046
+ // Un écran peint pendant que les bouchons étaient en place est incomplet
2047
+ // (une carte sans badges, une jauge à plat). Le module signale son arrivée :
2048
+ // on repeint ce qui est à l'écran, plutôt que de laisser un rendu dégradé.
2049
+ window.addEventListener("shadok-bridge-ready", () => {
2050
+ try {
2051
+ if (typeof renderProfileGrid === "function" && $("profileGrid")) renderProfileGrid(false);
2052
+ if (typeof renderProfilesList === "function" && !$("profilesOverlay").hidden) renderProfilesList();
2053
+ if (typeof renderSecrets === "function" && !$("secretsOverlay").hidden) renderSecrets();
2054
+ } catch {
2055
+ /* une repeinte ratée ne doit pas casser le chargement */
2056
+ }
2057
+ });
2058
+
1990
2059
  const $ = (id) => document.getElementById(id);
1991
2060
  const tabbar = $("tabbar"), newTabBtn = $("newTab"), newGroupBtn = $("newGroup");
1992
2061
  const ungroupedEl = $("ungrouped"), groupsEl = $("groups");