samagotchi 0.168.0 → 0.169.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +38 -1
- data/docs/architecture.md +1 -1
- data/docs/configuration.md +1 -1
- data/docs/guardrails.md +2 -2
- data/docs/hooks.md +2 -2
- data/docs/internals/block-renderers.md +1 -1
- data/docs/internals/bridge.md +16 -4
- data/docs/internals/inline-widgets.md +1 -1
- data/docs/internals/objectives.md +2 -1
- data/docs/internals/remote-sessions.md +1 -1
- data/docs/internals/web-frontend.md +62 -22
- data/docs/plugins.md +1 -1
- data/docs/releasing.md +10 -6
- data/docs/testing.md +12 -0
- data/lib/samagotchi/bridge.rb +12 -2
- data/lib/samagotchi/bundles/system/manifest.yml +1 -1
- data/lib/samagotchi/client_id.rb +3 -0
- data/lib/samagotchi/command_intake.rb +7 -7
- data/lib/samagotchi/compat.rb +14 -5
- data/lib/samagotchi/engine/objectives.rb +10 -1
- data/lib/samagotchi/guardrails/approvals.rb +8 -3
- data/lib/samagotchi/session_continue.rb +8 -11
- data/lib/samagotchi/session_manager/removal.rb +3 -3
- data/lib/samagotchi/session_stores.rb +79 -0
- data/lib/samagotchi/turn_stages/objectives.rb +6 -8
- data/lib/samagotchi/version.rb +1 -1
- data/lib/samagotchi/web/public/app.js +3 -1
- data/lib/samagotchi/web/public/block_watch.js +1 -1
- data/lib/samagotchi/web/public/cards_place.js +5 -1
- data/lib/samagotchi/web/public/index.html +58 -39
- data/lib/samagotchi/web/public/markdown_place.js +1 -1
- data/lib/samagotchi/web/public/question_cards.js +20 -6
- data/lib/samagotchi/web/public/stage_asking.js +283 -0
- data/lib/samagotchi/web/public/stage_frame.js +7 -11
- data/lib/samagotchi/web/public/stage_model.js +37 -11
- data/lib/samagotchi/web/public/stage_opened.js +28 -18
- data/lib/samagotchi/web/public/stage_slots.js +13 -89
- data/lib/samagotchi/web/public/stage_view.js +202 -160
- data/lib/samagotchi/web/public/stage_waiting.js +180 -0
- data/lib/samagotchi/web/public/stream_handlers.js +1 -1
- data/lib/samagotchi/web/public/turn_model.js +1 -1
- data/lib/samagotchi/web/session_show.rb +14 -4
- data/lib/samagotchi/worker.rb +3 -4
- metadata +4 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// The stage view's live slots (stage_view.js): the headline, the
|
|
2
|
-
//
|
|
1
|
+
// The stage view's live slots (stage_view.js): the headline, the "now"
|
|
2
|
+
// row, the trail and the chip's ticks, each drawn from
|
|
3
3
|
// liveSlots (stage_model.js) and patched only when what it shows changes
|
|
4
4
|
// (+shown+), so an unchanged slot keeps its nodes: a selection in it
|
|
5
5
|
// survives, and its animations never restart (the ticks' blink; the
|
|
@@ -15,29 +15,13 @@ export function node(tag, cls, parent = null) {
|
|
|
15
15
|
return el;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
// +headline+, +
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
// (Promise<string|null>; null keeps the raw text: markdown off, a failed
|
|
24
|
-
// read); +linkRefs(el, refs)+: the page's ref pass on the slot (a
|
|
25
|
-
// plugin's +refs+ paired first, then the path:line ones).
|
|
26
|
-
export function createStageSlots({
|
|
27
|
-
headline, asking, now, trail, ticks, taskStop = null, gens, onChange,
|
|
28
|
-
renderMarkdown = () => Promise.resolve(null), linkRefs = () => {},
|
|
29
|
-
}) {
|
|
18
|
+
// +headline+, +now+, +trail+, +ticks+: the slots' elements. +taskStop+:
|
|
19
|
+
// the page's stopper (task_stop.js), for the stop-task button on a running
|
|
20
|
+
// task_wait; +gens()+ the running turn's gens (the button's command, read
|
|
21
|
+
// at its click); +onChange+ redraws (the stage's scheduleRefresh).
|
|
22
|
+
export function createStageSlots({ headline, now, trail, ticks, taskStop = null, gens, onChange }) {
|
|
30
23
|
// What each slot shows, so an unchanged slot is left alone.
|
|
31
|
-
const shown = { headline: null, now: null, trail: null
|
|
32
|
-
// The refs the asking text is paired with (its pending question's).
|
|
33
|
-
let askingRefs = null;
|
|
34
|
-
// The last asking text sent to render and its answer (in flight or
|
|
35
|
-
// done, HTML only): the same question drawn again (after a reset, a
|
|
36
|
-
// blank between) asks no second time.
|
|
37
|
-
let rendering = { text: null, html: null };
|
|
38
|
-
// The asking text shows in its final form (its markdown swapped in, or
|
|
39
|
-
// a null render left the raw text): askingSettled.
|
|
40
|
-
let askingFinal = false;
|
|
24
|
+
const shown = { headline: null, now: null, trail: null };
|
|
41
25
|
|
|
42
26
|
function drawHeadline({ text, thinking }) {
|
|
43
27
|
const key = `${thinking ? "t" : "n"}|${text}`;
|
|
@@ -55,61 +39,6 @@ export function createStageSlots({
|
|
|
55
39
|
headline.classList.add("fresh");
|
|
56
40
|
}
|
|
57
41
|
|
|
58
|
-
// Patched only when the text changes (a late chunk to the closed gen
|
|
59
|
-
// rewrites the same text): a selection in it survives. A new text reads
|
|
60
|
-
// from its top: drawn raw at once, then swapped for its markdown when
|
|
61
|
-
// that comes back while the slot still shows the same text (the text is
|
|
62
|
-
// final: it shows only once the call that asks runs). +refs+: a plugin's
|
|
63
|
-
// refs on it (the pending question's), paired on both draws; new refs on
|
|
64
|
-
// the same text (a second question in the step) are paired in place.
|
|
65
|
-
function drawAsking(text, refs = null) {
|
|
66
|
-
asking.hidden = !text;
|
|
67
|
-
const refsKey = text && Array.isArray(refs) && refs.length ? JSON.stringify(refs) : "";
|
|
68
|
-
if (shown.asking === text) {
|
|
69
|
-
if (shown.askingRefs === refsKey) return;
|
|
70
|
-
shown.askingRefs = refsKey;
|
|
71
|
-
askingRefs = refsKey ? refs : null;
|
|
72
|
-
linkRefs(asking, askingRefs);
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
shown.asking = text;
|
|
76
|
-
shown.askingRefs = refsKey;
|
|
77
|
-
askingRefs = refsKey ? refs : null;
|
|
78
|
-
asking.classList.remove("markdown", "md-compact");
|
|
79
|
-
asking.textContent = text;
|
|
80
|
-
asking.scrollTop = 0;
|
|
81
|
-
askingFinal = false;
|
|
82
|
-
if (!text) return;
|
|
83
|
-
linkRefs(asking, askingRefs);
|
|
84
|
-
if (rendering.text !== text) {
|
|
85
|
-
let html;
|
|
86
|
-
try { html = Promise.resolve(renderMarkdown(text)).catch(() => null); } catch (_) { html = Promise.resolve(null); }
|
|
87
|
-
rendering = { text, html };
|
|
88
|
-
}
|
|
89
|
-
const pending = rendering;
|
|
90
|
-
pending.html.then((html) => {
|
|
91
|
-
// A null isn't kept: the next draw of this text asks again.
|
|
92
|
-
if (!html && rendering === pending) rendering = { text: null, html: null };
|
|
93
|
-
if (shown.asking !== text || askingFinal) return;
|
|
94
|
-
// The raw text is final (markdown off, a failed read).
|
|
95
|
-
if (!html) {
|
|
96
|
-
askingFinal = true;
|
|
97
|
-
onChange?.();
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
// Swapped once: a blank-then-same draw while in flight waits twice.
|
|
101
|
-
if (asking.classList.contains("markdown")) return;
|
|
102
|
-
// Sanitised on the server (POST /api/render), as an answer's HTML is.
|
|
103
|
-
asking.innerHTML = html;
|
|
104
|
-
asking.classList.add("markdown", "md-compact");
|
|
105
|
-
asking.scrollTop = 0;
|
|
106
|
-
linkRefs(asking, askingRefs);
|
|
107
|
-
askingFinal = true;
|
|
108
|
-
// Its height changed: the stage refits.
|
|
109
|
-
onChange?.();
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
|
|
113
42
|
function drawNow(tool, quiet) {
|
|
114
43
|
// A task_wait's stop button, as the row's (task_stop.js): in the key
|
|
115
44
|
// with its in-flight state, so a redraw keeps a clicked one disabled.
|
|
@@ -177,17 +106,12 @@ export function createStageSlots({
|
|
|
177
106
|
while (ticks.children.length > list.length) ticks.lastChild.remove();
|
|
178
107
|
}
|
|
179
108
|
|
|
180
|
-
// A new turn (or none): the slots empty, the
|
|
181
|
-
//
|
|
109
|
+
// A new turn (or none): the slots empty, the next draw of each slot a
|
|
110
|
+
// fresh one.
|
|
182
111
|
function reset() {
|
|
183
|
-
for (const slot of [headline,
|
|
184
|
-
|
|
185
|
-
asking.classList.remove("markdown", "md-compact");
|
|
186
|
-
shown.headline = shown.now = shown.trail = shown.asking = null;
|
|
187
|
-
shown.askingRefs = "";
|
|
188
|
-
askingRefs = null;
|
|
189
|
-
askingFinal = false;
|
|
112
|
+
for (const slot of [headline, now, trail, ticks]) slot.replaceChildren();
|
|
113
|
+
shown.headline = shown.now = shown.trail = null;
|
|
190
114
|
}
|
|
191
115
|
|
|
192
|
-
return { drawHeadline,
|
|
116
|
+
return { drawHeadline, drawNow, drawTrail, drawTicks, reset };
|
|
193
117
|
}
|