shadok-ai 0.12.5 → 0.12.6
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 +51 -2
package/package.json
CHANGED
package/public/index.html
CHANGED
|
@@ -2259,7 +2259,12 @@
|
|
|
2259
2259
|
// every upload settles. `updateSendDisabled` re-derives the button state.
|
|
2260
2260
|
let pendingUploads = 0;
|
|
2261
2261
|
function updateSendDisabled() {
|
|
2262
|
-
|
|
2262
|
+
// Sending is also allowed while a turn is RUNNING (`busy`): the message then
|
|
2263
|
+
// interrupts the turn and is sent the moment it settles, mirroring Telegram
|
|
2264
|
+
// (see preemptTurn). A pending dialog still blocks — you answer it, you don't
|
|
2265
|
+
// free-type over it — and so does an in-flight upload.
|
|
2266
|
+
const canType = active && (active.status === "ready" || active.status === "busy");
|
|
2267
|
+
sendBtn.disabled = !canType || !!active.pendingChoices || pendingUploads > 0;
|
|
2263
2268
|
}
|
|
2264
2269
|
const machine = $("machine"), screenEl = $("screen");
|
|
2265
2270
|
|
|
@@ -5194,6 +5199,16 @@
|
|
|
5194
5199
|
persistChannels();
|
|
5195
5200
|
}
|
|
5196
5201
|
stopTurnTimer(t);
|
|
5202
|
+
// A message was typed during this turn (a takeover): the turn has just
|
|
5203
|
+
// settled, so send it now. Mirrors the Telegram bridge's preempt.
|
|
5204
|
+
if (t.preempting) {
|
|
5205
|
+
const queued = t.preempting;
|
|
5206
|
+
t.preempting = null;
|
|
5207
|
+
clearTimeout(t.preemptTimer);
|
|
5208
|
+
setTabState(t, "ready", "ready");
|
|
5209
|
+
submitPrompt(t, queued);
|
|
5210
|
+
break;
|
|
5211
|
+
}
|
|
5197
5212
|
// "unread" only when the turn produced visible text. An empty turn (e.g.
|
|
5198
5213
|
// a cron concluding NOTHING TO SHOW) asks for no reading at all, neither
|
|
5199
5214
|
// on the tab nor on the favicon.
|
|
@@ -5406,6 +5421,36 @@
|
|
|
5406
5421
|
if (!$("setupOverlay").hidden) refreshLiveList();
|
|
5407
5422
|
}, 5000);
|
|
5408
5423
|
|
|
5424
|
+
// If the interrupt never lands (a wedged agent whose turn won't settle), don't
|
|
5425
|
+
// lose the message: put it back in the box and say so, rather than loop.
|
|
5426
|
+
const PREEMPT_TIMEOUT_MS = 8000;
|
|
5427
|
+
/**
|
|
5428
|
+
* Send a message WHILE a turn is running: interrupt the turn (Escape, exactly
|
|
5429
|
+
* the on-screen ⎋ button), stash the text, and submit it from the `turn-done`
|
|
5430
|
+
* that follows. This mirrors the Telegram bridge, which does the same on a
|
|
5431
|
+
* `busy` refusal — the web used to just disable Send instead.
|
|
5432
|
+
*
|
|
5433
|
+
* Nothing is rendered optimistically: the queued message appears as an
|
|
5434
|
+
* ordinary prompt once the interrupted turn has settled, so the transcript
|
|
5435
|
+
* stays in order (interrupted output, then your message, then its answer).
|
|
5436
|
+
*/
|
|
5437
|
+
function preemptTurn(t, text) {
|
|
5438
|
+
// Socket down: leave the text in the box, like submitPrompt's own guard.
|
|
5439
|
+
if (!sendTo(t, { type: "key", key: "escape" })) return;
|
|
5440
|
+
t.preempting = text;
|
|
5441
|
+
t.transcriptEl._stickBottom = true;
|
|
5442
|
+
if (t === active) { promptInput.value = ""; promptInput.style.height = "auto"; }
|
|
5443
|
+
dropDraft(t);
|
|
5444
|
+
setTabState(t, "busy", "interrupting…");
|
|
5445
|
+
clearTimeout(t.preemptTimer);
|
|
5446
|
+
t.preemptTimer = setTimeout(() => {
|
|
5447
|
+
if (t.preempting !== text) return; // already sent, or replaced by a newer one
|
|
5448
|
+
t.preempting = null;
|
|
5449
|
+
if (t === active && !promptInput.value) { promptInput.value = text; active.draft = text; }
|
|
5450
|
+
addTurn(t, "system", "", "Couldn't interrupt the running turn — your message is back in the box. Try again, or use ⎋.");
|
|
5451
|
+
}, PREEMPT_TIMEOUT_MS);
|
|
5452
|
+
}
|
|
5453
|
+
|
|
5409
5454
|
function submitPrompt(t, text, force) {
|
|
5410
5455
|
// Send BEFORE touching the UI. Everything below is optimistic — it shows the
|
|
5411
5456
|
// turn, marks the tab busy, clears the composer and drops the draft — so on
|
|
@@ -5505,7 +5550,11 @@
|
|
|
5505
5550
|
e.preventDefault();
|
|
5506
5551
|
const t = active;
|
|
5507
5552
|
const text = promptInput.value.trim();
|
|
5508
|
-
if (!text || t
|
|
5553
|
+
if (!text || !t || t.pendingChoices || pendingUploads > 0 || !t.ws) return;
|
|
5554
|
+
// Sending during a running turn is a takeover: interrupt it, then send the
|
|
5555
|
+
// message once the turn settles. Same behaviour as Telegram.
|
|
5556
|
+
if (t.status === "busy") return preemptTurn(t, text);
|
|
5557
|
+
if (t.status !== "ready") return;
|
|
5509
5558
|
// Checked here so nothing is optimistically rendered before the server
|
|
5510
5559
|
// refuses. The server re-checks anyway — it is the authority.
|
|
5511
5560
|
if (paceBlocked) return renderPaceConfirm(t, text, paceReason);
|