samagotchi 0.150.0 → 0.152.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.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +50 -1
  3. data/docs/architecture.md +2 -2
  4. data/docs/bundle-authoring.md +5 -5
  5. data/docs/cli.md +32 -7
  6. data/docs/configuration.md +1 -1
  7. data/docs/guardrails.md +4 -0
  8. data/docs/internals/block-renderers.md +98 -0
  9. data/docs/internals/bridge.md +53 -17
  10. data/docs/internals/bundles.md +49 -14
  11. data/docs/internals/objectives.md +6 -4
  12. data/docs/internals/web-frontend.md +2 -2
  13. data/docs/memory.md +7 -2
  14. data/docs/plugins.md +91 -14
  15. data/docs/releasing.md +7 -2
  16. data/docs/sessions.md +1 -1
  17. data/lib/samagotchi/block_renderers.rb +116 -0
  18. data/lib/samagotchi/bridge/card_places.rb +93 -0
  19. data/lib/samagotchi/bridge/card_store.rb +219 -122
  20. data/lib/samagotchi/bridge.rb +12 -4
  21. data/lib/samagotchi/bundle_command/check.rb +43 -3
  22. data/lib/samagotchi/bundle_command/installed_check.rb +6 -2
  23. data/lib/samagotchi/bundle_command/try/sandbox.rb +11 -3
  24. data/lib/samagotchi/bundle_command/try/trace.rb +1 -1
  25. data/lib/samagotchi/bundle_command.rb +88 -10
  26. data/lib/samagotchi/bundle_needs.rb +4 -6
  27. data/lib/samagotchi/bundle_settings_check.rb +14 -13
  28. data/lib/samagotchi/bundles/agents-md/manifest.yml +2 -2
  29. data/lib/samagotchi/bundles/btw/manifest.yml +2 -2
  30. data/lib/samagotchi/bundles/loop-guard/manifest.yml +2 -2
  31. data/lib/samagotchi/bundles/mcp/manifest.yml +2 -2
  32. data/lib/samagotchi/bundles/skills/manifest.yml +2 -2
  33. data/lib/samagotchi/bundles/slow-commands/manifest.yml +2 -2
  34. data/lib/samagotchi/bundles/system/manifest.yml +2 -2
  35. data/lib/samagotchi/bundles/system/memory_guide.md +3 -3
  36. data/lib/samagotchi/child_env.rb +15 -0
  37. data/lib/samagotchi/context_providers.rb +42 -10
  38. data/lib/samagotchi/engine.rb +47 -6
  39. data/lib/samagotchi/extension_load.rb +4 -3
  40. data/lib/samagotchi/guardrail_wiring.rb +28 -19
  41. data/lib/samagotchi/guardrails/approval.rb +2 -2
  42. data/lib/samagotchi/guardrails/rules.rb +1 -0
  43. data/lib/samagotchi/guardrails/verdict.rb +20 -0
  44. data/lib/samagotchi/hooks/bundle_loader.rb +5 -7
  45. data/lib/samagotchi/memory_bundle/asset_installer.rb +18 -9
  46. data/lib/samagotchi/memory_bundle/builder.rb +39 -31
  47. data/lib/samagotchi/memory_bundle/bundle_hook.rb +3 -2
  48. data/lib/samagotchi/memory_bundle/file_digest.rb +31 -0
  49. data/lib/samagotchi/memory_bundle/file_standing.rb +2 -2
  50. data/lib/samagotchi/memory_bundle/installed_bundle.rb +55 -43
  51. data/lib/samagotchi/memory_bundle/installed_copy.rb +38 -14
  52. data/lib/samagotchi/memory_bundle/installed_manifest.rb +224 -0
  53. data/lib/samagotchi/memory_bundle/installer.rb +91 -16
  54. data/lib/samagotchi/memory_bundle/manifest.rb +166 -5
  55. data/lib/samagotchi/memory_bundle/manifest_standing.rb +171 -0
  56. data/lib/samagotchi/memory_bundle/merger.rb +7 -8
  57. data/lib/samagotchi/memory_bundle/profile.rb +3 -2
  58. data/lib/samagotchi/memory_bundle/provenance.rb +220 -19
  59. data/lib/samagotchi/memory_bundle/shas.rb +4 -3
  60. data/lib/samagotchi/memory_bundle/shipped_update.rb +52 -24
  61. data/lib/samagotchi/memory_bundle/status.rb +11 -10
  62. data/lib/samagotchi/memory_bundle/system_bundle.rb +13 -2
  63. data/lib/samagotchi/plugin/loader.rb +1 -1
  64. data/lib/samagotchi/session_chain.rb +2 -7
  65. data/lib/samagotchi/session_commands.rb +15 -9
  66. data/lib/samagotchi/session_config.rb +5 -4
  67. data/lib/samagotchi/session_manager.rb +10 -7
  68. data/lib/samagotchi/steer.rb +17 -0
  69. data/lib/samagotchi/system_one/record.rb +10 -2
  70. data/lib/samagotchi/terminal_ui.rb +4 -4
  71. data/lib/samagotchi/tools/delegate.rb +20 -2
  72. data/lib/samagotchi/turn_checkpoint.rb +11 -5
  73. data/lib/samagotchi/turn_flow.rb +2 -3
  74. data/lib/samagotchi/update_command.rb +13 -2
  75. data/lib/samagotchi/version.rb +1 -1
  76. data/lib/samagotchi/web/app.rb +24 -13
  77. data/lib/samagotchi/web/block_renderer_routes.rb +32 -0
  78. data/lib/samagotchi/web/markdown_renderer.rb +39 -6
  79. data/lib/samagotchi/web/message_display.rb +3 -3
  80. data/lib/samagotchi/web/participant_view.rb +1 -1
  81. data/lib/samagotchi/web/public/app.js +2 -0
  82. data/lib/samagotchi/web/public/block_frame.js +202 -0
  83. data/lib/samagotchi/web/public/block_host.js +502 -0
  84. data/lib/samagotchi/web/public/block_renderers.css +20 -0
  85. data/lib/samagotchi/web/public/block_source.js +37 -0
  86. data/lib/samagotchi/web/public/bubbles.js +9 -5
  87. data/lib/samagotchi/web/public/card.js +17 -10
  88. data/lib/samagotchi/web/public/cards_place.js +2 -2
  89. data/lib/samagotchi/web/public/claim_link.js +4 -2
  90. data/lib/samagotchi/web/public/history_reveal.js +4 -1
  91. data/lib/samagotchi/web/public/index.html +2 -0
  92. data/lib/samagotchi/web/public/markdown_place.js +2 -3
  93. data/lib/samagotchi/web/public/text_roots.js +6 -0
  94. data/lib/samagotchi/web/public/turn_html.js +4 -1
  95. data/lib/samagotchi/web/session_access_routes.rb +2 -1
  96. data/lib/samagotchi/web/session_hub.rb +6 -0
  97. data/lib/samagotchi/web/session_show.rb +1 -1
  98. data/lib/samagotchi/worker.rb +4 -2
  99. metadata +13 -1
@@ -325,12 +325,14 @@ export function showClaim(container, claim, { roots: rootSelector, opts = {}, do
325
325
  const hit = findClaim(texts.map((t) => t.text), claim, opts);
326
326
  if (!hit && !turn) return null;
327
327
  const el = hit ? roots[hit.at] : turn.anchor;
328
+ const start = hit && pointAt(texts[hit.at], hit.start);
329
+ const end = hit && pointAt(texts[hit.at], hit.end, true);
328
330
  revealInHistory(el);
331
+ // The text can be somewhere its root isn't: a drawn block's hidden source.
332
+ if (start) revealInHistory(start.node.parentElement);
329
333
  el.classList.add(HIT_CLASS);
330
334
  el.scrollIntoView?.({ block: "center" });
331
335
  if (hit) {
332
- const start = pointAt(texts[hit.at], hit.start);
333
- const end = pointAt(texts[hit.at], hit.end, true);
334
336
  const highlights = win?.CSS?.highlights;
335
337
  if (start && end && highlights && typeof win.Highlight === "function") {
336
338
  const range = doc.createRange();
@@ -2,7 +2,8 @@
2
2
  // hides +el+ unfolds: a closed <details> around it (a turn's steps block, a
3
3
  // step, a diff), an answer or a delegate report folded (answer_fold.js: its row follows
4
4
  // the bubble's class; the jump's unfold isn't saved), a superseded version
5
- // of a Revise stack (revise_stack.js: its stub opens, not saved). Every
5
+ // of a Revise stack (revise_stack.js: its stub opens, not saved), a drawn
6
+ // block's source (block_source.js). Every
6
7
  // jump goes through it (claim_link.js showClaim, refs.js showRow and so the
7
8
  // working set's step tags, verdict_card.js "View check"), so a new way to
8
9
  // hide history is opened in one place.
@@ -11,6 +12,7 @@
11
12
  // own: static JS is cached at unversioned URLs, and a new export on an old
12
13
  // module would blank the page.
13
14
 
15
+ import { revealBlockSource } from "./block_source.js";
14
16
  import { openStubOver } from "./revise_stack.js";
15
17
 
16
18
  // Opens each closed <details> that holds +el+ (not +el+ itself: a fold the
@@ -19,6 +21,7 @@ import { openStubOver } from "./revise_stack.js";
19
21
  export function revealInHistory(el) {
20
22
  if (!el) return null;
21
23
  openStubOver(el);
24
+ revealBlockSource(el);
22
25
  el.closest?.(".bubble.folded")?.classList.remove("folded");
23
26
  for (let details = el.parentElement?.closest("details"); details; details = details.parentElement?.closest("details")) {
24
27
  details.open = true;
@@ -15,6 +15,7 @@
15
15
  <link rel="stylesheet" href="/assets/composer.css">
16
16
  <link rel="stylesheet" href="/assets/forms.css">
17
17
  <link rel="stylesheet" href="/assets/objectives.css">
18
+ <link rel="stylesheet" href="/assets/block_renderers.css">
18
19
  <style>
19
20
  /* Icon masks shared by the phone info bar and the all view's cards (the stroke only shapes the mask; the icon takes currentColor); the image icon is composer.css's. */
20
21
  :root{--icon-archive:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='2.75' width='12' height='3.5' rx='1'/%3E%3Cpath d='M3.25 6.25v6a1 1 0 0 0 1 1h7.5a1 1 0 0 0 1-1v-6M6.5 9h3'/%3E%3C/svg%3E");--icon-unarchive:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='2.75' width='12' height='3.5' rx='1'/%3E%3Cpath d='M3.25 6.25v6a1 1 0 0 0 1 1h7.5a1 1 0 0 0 1-1v-6M8 11.5V8.25M6.5 9.75 8 8.25l1.5 1.5'/%3E%3C/svg%3E")}
@@ -609,6 +610,7 @@ button.system-one-wrong,.system-one-wrong.marked{flex:none;padding:1px 6px;borde
609
610
  .card-head{display:flex;align-items:baseline;gap:8px;margin-bottom:4px}
610
611
  .card-title{font-size:14px;font-weight:600;color:var(--text-bright)}
611
612
  .card-source{font-size:11px;color:var(--text-faint);font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
613
+ .card-label{font-size:11px;color:var(--text-faint)}
612
614
  .card-body{font-size:13.5px;color:var(--text-2);white-space:normal;line-height:1.5}
613
615
  .card-body p{margin:0 0 6px}.card-body p:last-child{margin-bottom:0}
614
616
  .card-body ul,.card-body ol{margin:0 0 6px 20px}
@@ -4,9 +4,8 @@
4
4
  // page's state comes in as getters (capabilities, roots, currentDir), read
5
5
  // at each call.
6
6
 
7
- // The texts whose refs linkTextRefs links: the answers and the closed
8
- // steps' texts.
9
- const TEXTS = ".bubble.output, .gen:not(.live) > .gen-text";
7
+ import { TEXTS } from "./text_roots.js";
8
+
10
9
  // The closed steps' texts still shown raw: a live turn's (a reload's come
11
10
  // rendered, turn_block.js textTemplate).
12
11
  const RAW_STEPS = ".gen:not(.live) > .gen-text:not(.markdown)";
@@ -0,0 +1,6 @@
1
+ // The texts the page treats as text it wrote out of a model's words: the
2
+ // answers and the closed steps' texts. Cards, question replies, the asking
3
+ // slot and delegate reports aren't among them. markdown_place.js links refs on
4
+ // these; block_host.js draws in these. A module of its own: static JS is cached
5
+ // at unversioned URLs, and a new export on an old module would blank the page.
6
+ export const TEXTS = ".bubble.output, .gen:not(.live) > .gen-text";
@@ -284,7 +284,10 @@ export function answerBubbleTemplate(message, { cls = "", at = null, turnId = nu
284
284
  export function noteBubbleTemplate(note) {
285
285
  if (note?.objectives) return objectivesEntryTemplate(note, timeTitle(note.at));
286
286
  const from = note?.label ? `note from ${note.label}` : "note";
287
- return html`<div class="bubble note" title=${timeTitle(note?.at)}><div class="note-line">${from}</div><div class="note-text">${note?.content ?? ""}</div></div>`;
287
+ // A wake turn's note opens that turn (TURN_PROMPT, bubbles.js); a class, not
288
+ // data-turn-id, which marks a claim's anchor (claim_link.js).
289
+ const cls = note?.turn_start ? "bubble note turn-start" : "bubble note";
290
+ return html`<div class=${cls} title=${timeTitle(note?.at)}><div class="note-line">${from}</div><div class="note-text">${note?.content ?? ""}</div></div>`;
288
291
  }
289
292
 
290
293
  // A plugin's steer (a nudge put into the running turn): one line that
@@ -14,6 +14,7 @@ require_relative "../client_id"
14
14
  require_relative "../children_status"
15
15
  require_relative "../session_metrics"
16
16
  require_relative "../version"
17
+ require_relative "session_hub"
17
18
 
18
19
  module Samagotchi
19
20
  module Web
@@ -274,7 +275,7 @@ module Samagotchi
274
275
  model_name: session_access.show(id).model_name,
275
276
  default_model: ModelProfile.default_model_name,
276
277
  parent_strategy: strategy_json(session_access.parent_strategy(id)),
277
- **(@hub&.chi_state || { version: VERSION, installed: nil, available: nil, update_blocked: nil, auto: "off", restart: "idle", auto_offers: nil }) })
278
+ **(@hub&.chi_state || SessionHub::HUBLESS_STATE) })
278
279
  rescue SessionManager::OwnedByTUI => e
279
280
  owned_by_tui(e)
280
281
  rescue SessionAccess::Refused => e
@@ -32,6 +32,12 @@ module Samagotchi
32
32
  # step under it, so no stale upsert can follow a fresh snapshot.
33
33
  class SessionHub
34
34
  SCAN_INTERVAL = 1.0
35
+ # What an info route says about updates when there is no hub at all:
36
+ # this chi's version, and nothing known of the rest. The one place this
37
+ # is written (Web::App#handle_info and the remote info route).
38
+ HUBLESS_STATE = { version: Samagotchi::VERSION, installed: nil, available: nil, update_blocked: nil,
39
+ auto: "off", restart: "idle", auto_offers: nil }.freeze
40
+
35
41
  # The flock leaves no file trace when its holder dies, so owners are
36
42
  # probed: every tick for the sessions the projection believes owned
37
43
  # (a handful; OwnerLock.owner is open + LOCK_SH|LOCK_NB + close), and
@@ -80,7 +80,7 @@ module Samagotchi
80
80
  plugin_warning: turn_snapshot && turn_snapshot["plugin_warning"],
81
81
  # Plugins' slow setup still running (chi.init): the page's init row.
82
82
  init_tasks: snapshot_list(turn_snapshot, "init_tasks"),
83
- cards: cards_for_display(live_or_saved(turn_snapshot, "cards") { saved_cards(id) }, cwd: session.working_directory),
83
+ cards: cards_for_display(live_or_saved(turn_snapshot, "cards") { saved_cards(id, messages: raw_messages) }, cwd: session.working_directory),
84
84
  # The composer's / autocomplete; the built-ins until a worker
85
85
  # names its plugins' too.
86
86
  commands: turn_snapshot&.fetch("commands", nil) || SessionCommands.builtin_registry.listing,
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "fileutils"
4
+ require "securerandom"
4
5
 
5
6
  require_relative "client_id"
6
7
  require_relative "config"
@@ -1263,14 +1264,15 @@ module Samagotchi
1263
1264
  # a fresh worker's first), so the list is this turn's from the start.
1264
1265
  @merged_this_turn = []
1265
1266
  origin = fresh_origin(turn_args[:origin])
1266
- turn_args = turn_args.merge(origin: origin)
1267
+ # Settled here: the checkpoint's prompt carries it from the start.
1268
+ turn_args = turn_args.merge(origin: origin, id: turn_args[:id] || SecureRandom.uuid)
1267
1269
  verdicts_before = @session.verdicts.size
1268
1270
  @reporting_turn = reports_to_parent?(origin)
1269
1271
  # A participant's review turn merges no input (#pending_input_drain).
1270
1272
  @participant_turn = origin.participant?
1271
1273
  restores = @turn_flow.restores
1272
1274
  begin
1273
- @checkpoint.begin_turn(prompt: prompt, enqueued_id: origin.enqueued_id, author: turn_author_fields(origin))
1275
+ @checkpoint.begin_turn(prompt: prompt, turn_id: turn_args[:id], enqueued_id: origin.enqueued_id, author: turn_author_fields(origin))
1274
1276
  @session.status = Session::STATUS_RUNNING
1275
1277
  # A continue that moved this session to the chain's new link wrote
1276
1278
  # the new parent beside it (Session::PARENT_FILE): this turn's
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.150.0
4
+ version: 0.152.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Dedov
@@ -155,6 +155,7 @@ files:
155
155
  - docs/internals/anthropic.md
156
156
  - docs/internals/attached-context.md
157
157
  - docs/internals/background-tasks.md
158
+ - docs/internals/block-renderers.md
158
159
  - docs/internals/bridge.md
159
160
  - docs/internals/bundles.md
160
161
  - docs/internals/context-telemetry.md
@@ -186,12 +187,14 @@ files:
186
187
  - lib/samagotchi/answer_tail.rb
187
188
  - lib/samagotchi/archive_store.rb
188
189
  - lib/samagotchi/atomic_file.rb
190
+ - lib/samagotchi/block_renderers.rb
189
191
  - lib/samagotchi/bootstrap/bundles.rb
190
192
  - lib/samagotchi/bootstrap/config_writer.rb
191
193
  - lib/samagotchi/bootstrap/probe.rb
192
194
  - lib/samagotchi/bootstrap_command.rb
193
195
  - lib/samagotchi/bridge.rb
194
196
  - lib/samagotchi/bridge/bounded_queue.rb
197
+ - lib/samagotchi/bridge/card_places.rb
195
198
  - lib/samagotchi/bridge/card_store.rb
196
199
  - lib/samagotchi/bridge/client_event.rb
197
200
  - lib/samagotchi/bridge/event_id.rb
@@ -469,15 +472,18 @@ files:
469
472
  - lib/samagotchi/memory_bundle/builder.rb
470
473
  - lib/samagotchi/memory_bundle/bundle_hook.rb
471
474
  - lib/samagotchi/memory_bundle/entry_size.rb
475
+ - lib/samagotchi/memory_bundle/file_digest.rb
472
476
  - lib/samagotchi/memory_bundle/file_standing.rb
473
477
  - lib/samagotchi/memory_bundle/index_size.rb
474
478
  - lib/samagotchi/memory_bundle/index_sync.rb
475
479
  - lib/samagotchi/memory_bundle/index_updater.rb
476
480
  - lib/samagotchi/memory_bundle/installed_bundle.rb
477
481
  - lib/samagotchi/memory_bundle/installed_copy.rb
482
+ - lib/samagotchi/memory_bundle/installed_manifest.rb
478
483
  - lib/samagotchi/memory_bundle/installer.rb
479
484
  - lib/samagotchi/memory_bundle/listing.rb
480
485
  - lib/samagotchi/memory_bundle/manifest.rb
486
+ - lib/samagotchi/memory_bundle/manifest_standing.rb
481
487
  - lib/samagotchi/memory_bundle/memory_files.rb
482
488
  - lib/samagotchi/memory_bundle/merger.rb
483
489
  - lib/samagotchi/memory_bundle/placeholder.rb
@@ -799,6 +805,7 @@ files:
799
805
  - lib/samagotchi/web/app.rb
800
806
  - lib/samagotchi/web/auto_update.rb
801
807
  - lib/samagotchi/web/auto_update_record.rb
808
+ - lib/samagotchi/web/block_renderer_routes.rb
802
809
  - lib/samagotchi/web/capabilities.rb
803
810
  - lib/samagotchi/web/editor.rb
804
811
  - lib/samagotchi/web/grants.rb
@@ -828,7 +835,11 @@ files:
828
835
  - lib/samagotchi/web/public/app.js
829
836
  - lib/samagotchi/web/public/apple-touch-icon.png
830
837
  - lib/samagotchi/web/public/auth_lost.js
838
+ - lib/samagotchi/web/public/block_frame.js
839
+ - lib/samagotchi/web/public/block_host.js
831
840
  - lib/samagotchi/web/public/block_open.js
841
+ - lib/samagotchi/web/public/block_renderers.css
842
+ - lib/samagotchi/web/public/block_source.js
832
843
  - lib/samagotchi/web/public/bubbles.js
833
844
  - lib/samagotchi/web/public/card.js
834
845
  - lib/samagotchi/web/public/cards_place.js
@@ -953,6 +964,7 @@ files:
953
964
  - lib/samagotchi/web/public/system_one_wrong.js
954
965
  - lib/samagotchi/web/public/tally.js
955
966
  - lib/samagotchi/web/public/task_stop.js
967
+ - lib/samagotchi/web/public/text_roots.js
956
968
  - lib/samagotchi/web/public/thinking_chip.js
957
969
  - lib/samagotchi/web/public/thinking_ticker.js
958
970
  - lib/samagotchi/web/public/time_gaps.js