samagotchi 0.145.0 → 0.146.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 +33 -1
- data/docs/cli.md +1 -1
- data/docs/guardrails.md +7 -2
- data/docs/internals/bridge.md +3 -1
- data/docs/internals/engine.md +1 -1
- data/docs/internals/web-frontend.md +3 -2
- data/docs/memory.md +45 -0
- data/docs/sessions.md +1 -1
- data/lib/samagotchi/bundles/system/manifest.yml +1 -1
- data/lib/samagotchi/child_reports.rb +13 -6
- data/lib/samagotchi/guardrails/approval.rb +17 -4
- data/lib/samagotchi/guardrails/parent_approvals.rb +5 -1
- data/lib/samagotchi/guardrails/verdict.rb +5 -3
- data/lib/samagotchi/memory_command.rb +135 -7
- data/lib/samagotchi/memory_paths.rb +9 -0
- data/lib/samagotchi/memory_usage.rb +368 -0
- data/lib/samagotchi/relay.rb +2 -2
- data/lib/samagotchi/tool_activity.rb +3 -3
- data/lib/samagotchi/tool_output_cut.rb +12 -1
- data/lib/samagotchi/toolkit_suggest.rb +7 -4
- data/lib/samagotchi/tools/delegate.rb +88 -13
- data/lib/samagotchi/tools/memory.rb +12 -2
- data/lib/samagotchi/version.rb +1 -1
- data/lib/samagotchi/web/app.rb +1 -1
- data/lib/samagotchi/web/public/app.js +6 -2
- data/lib/samagotchi/web/public/participant_annotate.js +2 -1
- data/lib/samagotchi/web/public/question_cards.js +33 -9
- data/lib/samagotchi/web/public/revise_stack.js +6 -5
- data/lib/samagotchi/web/public/verify_preset.js +5 -1
- data/lib/samagotchi/web/public/worker_features.js +14 -0
- data/lib/samagotchi/working_set.rb +3 -2
- metadata +3 -1
|
@@ -433,6 +433,8 @@ const questionCards = createQuestionCards({
|
|
|
433
433
|
renderMarkdown,
|
|
434
434
|
linkRefs: linkRefsIn,
|
|
435
435
|
pairRefs: pairRefsIn,
|
|
436
|
+
// The bar's chip reads questionCards.pendingQuestion() (sessionWaits).
|
|
437
|
+
onPending: () => store.touch("infoBar"),
|
|
436
438
|
});
|
|
437
439
|
// The history's bubbles (bubbles.js): output, end lines, every client's
|
|
438
440
|
// prompts, the recap, warnings and notices, command and note bubbles.
|
|
@@ -1508,9 +1510,11 @@ async function restartWorker() {
|
|
|
1508
1510
|
|
|
1509
1511
|
// The session bar (info_bar_model.js sessionBar): its buttons, and the
|
|
1510
1512
|
// info line rendered by info_bar.js.
|
|
1511
|
-
// The open session waits on the user: its
|
|
1513
|
+
// The open session waits on the user: its card is up, or its summary says so
|
|
1514
|
+
// (not for a question answered here: the summary is a refresh behind).
|
|
1512
1515
|
function sessionWaits() {
|
|
1513
|
-
|
|
1516
|
+
const summary = waitingOn(store.sessions.find((s) => s.id === store.selected));
|
|
1517
|
+
return !!((summary && !questionCards.isResolved(summary.id)) || questionCards.pendingQuestion());
|
|
1514
1518
|
}
|
|
1515
1519
|
function updateInfoBar() {
|
|
1516
1520
|
annotateBar?.refresh();
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
// blank the page.
|
|
19
19
|
|
|
20
20
|
import { quoteBlock } from "./annotations.js";
|
|
21
|
+
import { isParticipantAuthor } from "./participant_model.js";
|
|
21
22
|
|
|
22
23
|
// Where a node on the participant page came from: { kind, root, … } where
|
|
23
24
|
// root is the element a selection is clipped to, or null.
|
|
@@ -69,7 +70,7 @@ export function participantQuote(text, source) {
|
|
|
69
70
|
// participant route's: mine, author, author_name, automatic).
|
|
70
71
|
export function messageAuthorData(message) {
|
|
71
72
|
if (message?.mine) return { by: "me" };
|
|
72
|
-
if (message?.author) return { by: "participant", name: message.author_name || "" };
|
|
73
|
+
if (isParticipantAuthor(message?.author)) return { by: "participant", name: message.author_name || "" };
|
|
73
74
|
if (message?.automatic) return { by: "automatic" };
|
|
74
75
|
return { by: "owner" };
|
|
75
76
|
}
|
|
@@ -41,13 +41,18 @@ import { plainText } from "./plain_line.js";
|
|
|
41
41
|
// own text; markdown_place.js pairRefsIn)
|
|
42
42
|
// @param api {sendAnswer, dismissQuestion, sendCommand} (data.js)
|
|
43
43
|
// @param doc the page's document
|
|
44
|
+
// @param onPending (pending|null) called whenever the open question changes:
|
|
45
|
+
// the page touches the redraws that read pendingQuestion() (the session
|
|
46
|
+
// bar's waiting chip, docs/internals/web-frontend.md write -> redraw)
|
|
44
47
|
// @return {renderQuestion(pq, {said}), resolveQuestion(id, opts), removeQuestion(),
|
|
45
48
|
// questionCard() (the live card or null), pendingQuestion() (or null),
|
|
49
|
+
// isResolved(id) (this page already saw that question answered),
|
|
46
50
|
// renderContinue(offer), resolveContinue(data), forgetContinue()}
|
|
47
51
|
export function createQuestionCards({
|
|
48
52
|
sessionId, clientId, place, isNearBottom, scrollToEnd, removeHintIfEmpty, askingText = () => "",
|
|
49
53
|
renderMarkdown = () => Promise.resolve(null), linkRefs = () => {}, pairRefs = () => {},
|
|
50
54
|
api = { sendAnswer, dismissQuestion, sendCommand }, doc = globalThis.document,
|
|
55
|
+
onPending = () => {},
|
|
51
56
|
}) {
|
|
52
57
|
// Live ask_user_question card, keyed by pending question id. Re-rendered from
|
|
53
58
|
// pending_question on session select so a reload mid-question restores it.
|
|
@@ -57,6 +62,16 @@ export function createQuestionCards({
|
|
|
57
62
|
let continueEl = null;
|
|
58
63
|
// card → the reply that asked it, drawn under the summary once resolved.
|
|
59
64
|
const saidOf = new WeakMap();
|
|
65
|
+
// The question last answered here: a session summary fetched earlier still
|
|
66
|
+
// names it as pending until the next refresh (isResolved).
|
|
67
|
+
let resolvedId = null;
|
|
68
|
+
|
|
69
|
+
// The one way the open question changes: +onPending+ is the page's hook for
|
|
70
|
+
// the redraws that read it (the session bar's waiting chip).
|
|
71
|
+
function setPending(next) {
|
|
72
|
+
pending = next;
|
|
73
|
+
onPending(pending);
|
|
74
|
+
}
|
|
60
75
|
|
|
61
76
|
// +said+: the asking reply when the caller knows it (a reloaded card: its
|
|
62
77
|
// step's text, "" for none); else the running turn's (askingText).
|
|
@@ -65,8 +80,8 @@ export function createQuestionCards({
|
|
|
65
80
|
if (action === "same") return;
|
|
66
81
|
// A resolved card stays where it was; only a pending one is replaced.
|
|
67
82
|
if (action === "keep") questionEl = null;
|
|
68
|
-
else
|
|
69
|
-
|
|
83
|
+
else replaceQuestionCard();
|
|
84
|
+
setPending(pq);
|
|
70
85
|
removeHintIfEmpty();
|
|
71
86
|
|
|
72
87
|
const approval = approvalView(pq);
|
|
@@ -424,7 +439,7 @@ export function createQuestionCards({
|
|
|
424
439
|
// The parent relayed the open question, or no longer does (question_relay).
|
|
425
440
|
function markRelayed(id, relayedTo) {
|
|
426
441
|
if (!questionEl || !pending || String(pending.id) !== String(id)) return;
|
|
427
|
-
|
|
442
|
+
setPending({ ...pending, relayed_to: relayedTo || null });
|
|
428
443
|
questionEl.querySelector(".question-relayed")?.replaceWith(renderRelayedTo(pending));
|
|
429
444
|
}
|
|
430
445
|
|
|
@@ -491,7 +506,8 @@ export function createQuestionCards({
|
|
|
491
506
|
if (!questionEl.dataset.toggled) questionEl.open = false;
|
|
492
507
|
// After the collapse: a card left open by hand renders at once.
|
|
493
508
|
if (full) renderSaidOnOpen(questionEl, full, asked, refs);
|
|
494
|
-
|
|
509
|
+
resolvedId = pending.id;
|
|
510
|
+
setPending(null);
|
|
495
511
|
}
|
|
496
512
|
|
|
497
513
|
// The body's copy as markdown, from the card's first open on (a reload
|
|
@@ -546,11 +562,18 @@ export function createQuestionCards({
|
|
|
546
562
|
}
|
|
547
563
|
|
|
548
564
|
function removeQuestionCard() {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
565
|
+
replaceQuestionCard();
|
|
566
|
+
setPending(null);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// The live card taken off the history because a new one takes its place:
|
|
570
|
+
// the question itself changes in the same step, so the hook is not touched
|
|
571
|
+
// for the in-between null.
|
|
572
|
+
function replaceQuestionCard() {
|
|
573
|
+
if (!questionEl) return;
|
|
574
|
+
|
|
575
|
+
questionEl.remove();
|
|
576
|
+
questionEl = null;
|
|
554
577
|
}
|
|
555
578
|
|
|
556
579
|
// ── continue card ──────────────────────────────────────────────────────────
|
|
@@ -653,6 +676,7 @@ export function createQuestionCards({
|
|
|
653
676
|
removeQuestion: removeQuestionCard,
|
|
654
677
|
questionCard: () => questionEl,
|
|
655
678
|
pendingQuestion: () => pending,
|
|
679
|
+
isResolved: (id) => resolvedId !== null && String(resolvedId) === String(id),
|
|
656
680
|
renderContinue: renderContinueCard,
|
|
657
681
|
resolveContinue: resolveContinueCard,
|
|
658
682
|
// The running turn's DOM was reset: a later offer draws a new card.
|
|
@@ -30,6 +30,7 @@ import { bubbleCopyText } from "./copy.js";
|
|
|
30
30
|
import { foldLabel, keepRowInView, lineCount, readFolded, writeFold } from "./answer_fold.js";
|
|
31
31
|
import { clip } from "./format.js";
|
|
32
32
|
import { NOTE_BOUNDARY } from "./turn_range.js";
|
|
33
|
+
import { workerPredates } from "./worker_features.js";
|
|
33
34
|
import { SWAPPED_CLASS, VIEW_CLASS, stepVersion, switcherTemplate, viewOf } from "./revise_switch.js";
|
|
34
35
|
|
|
35
36
|
// The classes and attributes this module puts on the history.
|
|
@@ -113,12 +114,12 @@ export function versionChipText(count, at = count - 1) {
|
|
|
113
114
|
// the worker predates Revise turns).
|
|
114
115
|
export const REVISE_UNAVAILABLE = "restart this session to use Revise";
|
|
115
116
|
|
|
116
|
-
// The feature gate (app.js featureGates): a live worker without the
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
//
|
|
117
|
+
// The feature gate (app.js featureGates): a live worker without the "revise"
|
|
118
|
+
// feature predates Revise turns (chi web would answer 409 revise_unavailable).
|
|
119
|
+
// A worker that isn't up isn't asked: the send wakes a new one, which has it
|
|
120
|
+
// (worker_features.js's rule, the same as Verify's gate).
|
|
120
121
|
export function reviseWorkerUnavailable(workerFeatures, bridgeUp) {
|
|
121
|
-
return
|
|
122
|
+
return workerPredates(workerFeatures, bridgeUp, "revise");
|
|
122
123
|
}
|
|
123
124
|
export function reviseChipText(label, { unavailable = false } = {}) {
|
|
124
125
|
if (unavailable) return `Revise: ${REVISE_UNAVAILABLE}`;
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
// module of its own: static JS is cached at unversioned URLs, and a new
|
|
7
7
|
// export on an old module would blank the page.
|
|
8
8
|
|
|
9
|
+
import { workerPredates } from "./worker_features.js";
|
|
10
|
+
|
|
9
11
|
export const VERIFY_PRESET = Object.freeze({
|
|
10
12
|
label: "Verify",
|
|
11
13
|
text: "Verify this claim against the code. If this session's context doesn't settle it, say so. "
|
|
@@ -14,8 +16,10 @@ export const VERIFY_PRESET = Object.freeze({
|
|
|
14
16
|
|
|
15
17
|
export const VERIFY_UNAVAILABLE = "restart this session to use Verify";
|
|
16
18
|
|
|
19
|
+
// The Verify gate (app.js featureGates): a live worker without "verify"
|
|
20
|
+
// predates Verify turns (worker_features.js's rule).
|
|
17
21
|
export function verifyWorkerUnavailable(workerFeatures, bridgeUp) {
|
|
18
|
-
return
|
|
22
|
+
return workerPredates(workerFeatures, bridgeUp, "verify");
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
// +presets+ (annotate_presets.js parsePresets) with Verify after them.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// One rule for the worker-side feature gates: a worker that is up and whose
|
|
2
|
+
// features lack +feature+ predates it (chi web would answer 409
|
|
3
|
+
// <feature>_unavailable), so the page says so instead of offering the action.
|
|
4
|
+
// A worker that isn't up isn't asked: the send wakes a new one that has it.
|
|
5
|
+
// Used by Verify's gate (verify_preset.js) and Revise's (revise_stack.js).
|
|
6
|
+
//
|
|
7
|
+
// A new module: the page's modules are cached at unversioned URLs, and a new
|
|
8
|
+
// export of an old one (docs/internals/web-frontend.md) leaves a cached copy
|
|
9
|
+
// without it.
|
|
10
|
+
|
|
11
|
+
// @return [bool] true only for a live worker without the feature.
|
|
12
|
+
export function workerPredates(workerFeatures, bridgeUp, feature) {
|
|
13
|
+
return bridgeUp === true && Array.isArray(workerFeatures) && !workerFeatures.includes(feature);
|
|
14
|
+
}
|
|
@@ -235,7 +235,8 @@ module Samagotchi
|
|
|
235
235
|
def shared_with(touch, key) = touch.share > 1 ? found_names(touch.run) - [key] : []
|
|
236
236
|
|
|
237
237
|
# A memory_read's names (Tools::MemoryRead.parse_names: none for the
|
|
238
|
-
# index listing), less the ones its output says weren't found.
|
|
238
|
+
# index listing), less the ones its output says weren't found. Public:
|
|
239
|
+
# `chi memory usage` counts reads the same way (MemoryUsage).
|
|
239
240
|
def found_names(run)
|
|
240
241
|
names = Tools::MemoryRead.parse_names(run.call[:content].to_s)
|
|
241
242
|
last = run.text.split(ToolResponse::SEPARATOR).last.to_s
|
|
@@ -308,6 +309,6 @@ module Samagotchi
|
|
|
308
309
|
|
|
309
310
|
def field(hash, key) = hash.key?(key) ? hash[key] : hash[key.to_s]
|
|
310
311
|
|
|
311
|
-
private_class_method :all_touches, :touches, :failed?, :
|
|
312
|
+
private_class_method :all_touches, :touches, :failed?, :shared_with, :item, :still_sent?, :dropped?, :with_id, :changed?, :stamp_of, :field
|
|
312
313
|
end
|
|
313
314
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: samagotchi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.146.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dmitry Dedov
|
|
@@ -487,6 +487,7 @@ files:
|
|
|
487
487
|
- lib/samagotchi/memory_command.rb
|
|
488
488
|
- lib/samagotchi/memory_orphans.rb
|
|
489
489
|
- lib/samagotchi/memory_paths.rb
|
|
490
|
+
- lib/samagotchi/memory_usage.rb
|
|
490
491
|
- lib/samagotchi/message_parts.rb
|
|
491
492
|
- lib/samagotchi/message_time.rb
|
|
492
493
|
- lib/samagotchi/model_binding.rb
|
|
@@ -958,6 +959,7 @@ files:
|
|
|
958
959
|
- lib/samagotchi/web/public/verify_card.css
|
|
959
960
|
- lib/samagotchi/web/public/verify_preset.js
|
|
960
961
|
- lib/samagotchi/web/public/verify_target.js
|
|
962
|
+
- lib/samagotchi/web/public/worker_features.js
|
|
961
963
|
- lib/samagotchi/web/public/working_set.js
|
|
962
964
|
- lib/samagotchi/web/public/working_set_rail.js
|
|
963
965
|
- lib/samagotchi/web/public/working_set_view.js
|