shadok-ai 0.2.18 → 0.2.19

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/README.md CHANGED
@@ -124,6 +124,27 @@ the same-origin policy, so without that check any page you happen to visit could
124
124
  drive your agents. Behind a reverse proxy that rewrites `Host`, list the public
125
125
  origin in `SHADOK_ORIGINS`.
126
126
 
127
+ ### Behind TLS (nginx, Caddy…)
128
+
129
+ Serving the cockpit over HTTPS works, with one requirement: **the proxy must
130
+ forward the WebSocket upgrade**. Everything live — the channel list included —
131
+ travels over `/ws`, and the page itself is static HTML, so a proxy that drops
132
+ `Upgrade`/`Connection` produces a cockpit that loads perfectly and then never
133
+ connects. In nginx:
134
+
135
+ ```nginx
136
+ location / {
137
+ proxy_pass http://127.0.0.1:3789;
138
+ proxy_http_version 1.1;
139
+ proxy_set_header Upgrade $http_upgrade;
140
+ proxy_set_header Connection "upgrade";
141
+ proxy_set_header Host $host;
142
+ }
143
+ ```
144
+
145
+ The client picks `wss://` on its own when the page is HTTPS, so there is nothing
146
+ to configure on that side.
147
+
127
148
  ### SSH identity in Docker
128
149
 
129
150
  When shadok-ai runs **in a container** it gives itself an SSH key on first boot
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shadok-ai",
3
- "version": "0.2.18",
3
+ "version": "0.2.19",
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
@@ -3158,7 +3158,12 @@
3158
3158
  * of stranding the tab on "link lost". */
3159
3159
  function openLink(t) {
3160
3160
  setTabState(t, "connecting", t.reconnectAttempts ? "reconnecting…" : "connecting…");
3161
- const ws = new WebSocket(`ws://${location.host}/ws`);
3161
+ // The scheme MUST follow the page's. On an HTTPS page — the cockpit behind an
3162
+ // nginx/TLS reverse proxy — a `ws://` socket is blocked as mixed content, and
3163
+ // the failure is invisible: the page is static HTML so it paints normally,
3164
+ // while every channel stays stuck "connecting…" forever. Never hardcode `ws://`.
3165
+ const scheme = location.protocol === "https:" ? "wss:" : "ws:";
3166
+ const ws = new WebSocket(`${scheme}//${location.host}/ws`);
3162
3167
  t.ws = ws;
3163
3168
  ws.addEventListener("open", () => {
3164
3169
  t.reconnectAttempts = 0;