samagotchi 0.94.0 → 0.96.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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -1
  3. data/README.md +7 -7
  4. data/bin/chi +6 -2
  5. data/docs/architecture.md +4 -5
  6. data/docs/cli.md +11 -3
  7. data/docs/configuration.md +49 -86
  8. data/docs/hooks.md +1 -1
  9. data/docs/internals/context-telemetry.md +1 -1
  10. data/docs/internals/engine.md +7 -4
  11. data/docs/plugins.md +4 -3
  12. data/docs/sessions.md +8 -2
  13. data/docs/testing.md +6 -9
  14. data/lib/samagotchi/bootstrap/config_writer.rb +1 -5
  15. data/lib/samagotchi/bundle_command/try/sandbox.rb +8 -2
  16. data/lib/samagotchi/bundles/system/config_modification_protocol.md +6 -7
  17. data/lib/samagotchi/bundles/system/manifest.yml +3 -3
  18. data/lib/samagotchi/bundles/system/self_map.md +1 -1
  19. data/lib/samagotchi/children_status.rb +1 -1
  20. data/lib/samagotchi/client.rb +59 -196
  21. data/lib/samagotchi/config.rb +74 -15
  22. data/lib/samagotchi/engine.rb +7 -7
  23. data/lib/samagotchi/host_config.rb +20 -27
  24. data/lib/samagotchi/host_registry.rb +8 -8
  25. data/lib/samagotchi/kernel_loop.rb +46 -8
  26. data/lib/samagotchi/model_profile.rb +2 -3
  27. data/lib/samagotchi/plugin/sessions.rb +4 -3
  28. data/lib/samagotchi/self_report.rb +0 -2
  29. data/lib/samagotchi/send_command.rb +1 -1
  30. data/lib/samagotchi/session.rb +13 -1
  31. data/lib/samagotchi/session_commands.rb +13 -0
  32. data/lib/samagotchi/session_continue.rb +8 -8
  33. data/lib/samagotchi/session_delete_command.rb +1 -1
  34. data/lib/samagotchi/session_manager.rb +13 -7
  35. data/lib/samagotchi/sessions_command.rb +8 -6
  36. data/lib/samagotchi/system_prompt.rb +7 -21
  37. data/lib/samagotchi/terminal_ui/thinking_line.rb +2 -4
  38. data/lib/samagotchi/thinking.rb +35 -2
  39. data/lib/samagotchi/thinking_notices.rb +11 -4
  40. data/lib/samagotchi/title_command.rb +61 -0
  41. data/lib/samagotchi/version.rb +1 -1
  42. data/lib/samagotchi/vision_support.rb +0 -3
  43. data/lib/samagotchi/web/app.rb +4 -4
  44. data/lib/samagotchi/web/public/app.js +12 -0
  45. data/lib/samagotchi/web/public/chains.js +21 -8
  46. data/lib/samagotchi/web/public/format.js +4 -3
  47. data/lib/samagotchi/web/public/index.html +7 -0
  48. data/lib/samagotchi/web/public/info_bar_model.js +2 -0
  49. data/lib/samagotchi/web/public/session_rename.js +86 -0
  50. data/lib/samagotchi/web/public/session_state.js +4 -2
  51. data/lib/samagotchi/web/session_summary.rb +3 -0
  52. data/lib/samagotchi/worker.rb +5 -2
  53. metadata +3 -1
@@ -0,0 +1,86 @@
1
+ // The info bar's ✎ (Rename this session): a small input in its place,
2
+ // prefilled with the session's title ("" for none). Enter sends
3
+ // `/title TEXT` (blank: `/title --clear`) through the chips' command path
4
+ // (composer.js run: the reply shows as a command bubble, a refusal in the
5
+ // failed bubble, the composer untouched); leaving the field saves the same
6
+ // way (a phone's keyboard dismissed keeps what was typed). Esc, or opening
7
+ // another session, closes it unsent. The cards follow from the saved file
8
+ // (the hub's scan), as for any title.
9
+ import { normalize } from "./format.js";
10
+
11
+ // As long as a title may be (TitleCommand::LIMIT).
12
+ const TITLE_CHARS = 80;
13
+
14
+ // The line the input's +text+ sends.
15
+ export function titleLine(text) {
16
+ const title = normalize(text);
17
+ return title ? `/title ${title}` : "/title --clear";
18
+ }
19
+
20
+ // @param button the ✎ button (it hides while the input shows)
21
+ // @param session () => the open session's id, or null
22
+ // @param titleOf (id) => that session's title, or null
23
+ // @param run (line) => composer.js run's promise
24
+ export function createRename({ button, session, titleOf, run }) {
25
+ let input = null;
26
+ let openFor = null;
27
+
28
+ function close() {
29
+ if (!input) return;
30
+ const el = input;
31
+ input = null;
32
+ openFor = null;
33
+ el.remove();
34
+ button.hidden = false;
35
+ }
36
+
37
+ // Enter's and blur's: once (closing it blurs it again), and only to the
38
+ // session it was opened for.
39
+ function submit() {
40
+ if (!input) return null;
41
+ const id = openFor;
42
+ const before = normalize(input.dataset.before);
43
+ const text = input.value;
44
+ close();
45
+ if (!id || session() !== id || normalize(text) === before) return null;
46
+ return run(titleLine(text));
47
+ }
48
+
49
+ function open() {
50
+ const id = session();
51
+ if (input || !id) return;
52
+ const el = document.createElement("input");
53
+ el.type = "text";
54
+ el.className = "rename-input";
55
+ el.maxLength = TITLE_CHARS;
56
+ el.placeholder = "Session title";
57
+ el.setAttribute("aria-label", "Session title (Enter saves, empty clears, Esc cancels)");
58
+ el.value = titleOf(id) || "";
59
+ el.dataset.before = el.value;
60
+ el.addEventListener("keydown", (e) => {
61
+ if (e.key === "Enter") {
62
+ e.preventDefault();
63
+ submit();
64
+ } else if (e.key === "Escape") {
65
+ e.preventDefault();
66
+ close();
67
+ }
68
+ });
69
+ el.addEventListener("blur", () => submit());
70
+ input = el;
71
+ openFor = id;
72
+ button.hidden = true;
73
+ button.after(el);
74
+ el.focus();
75
+ el.select();
76
+ }
77
+
78
+ // The info bar redrew for +id+ (app.js updateInfoBar): an input opened
79
+ // for another session closes.
80
+ function follow(id) {
81
+ if (input && openFor !== id) close();
82
+ }
83
+
84
+ button.addEventListener("click", () => open());
85
+ return { open, close, follow, isOpen: () => !!input };
86
+ }
@@ -118,10 +118,12 @@ export function sessionStateFrom(data) {
118
118
  return state;
119
119
  }
120
120
 
121
- // The info bar's title: the first user message when the payload has
122
- // messages, else the card's preview, else the first prompt of its history.
121
+ // The info bar's title: the session's own title (/title), else the first
122
+ // user message when the payload has messages, else the card's preview, else
123
+ // the first prompt of its history.
123
124
  function sessionFirstPreview(data) {
124
125
  const s = data.session;
126
+ if (s.title) return firstPreview(s.title);
125
127
  let preview = s.first_preview || previewForCard(s);
126
128
  if (data.messages && data.messages.length) {
127
129
  const first = data.messages.find((m) => m.role === "user");
@@ -67,6 +67,9 @@ module Samagotchi
67
67
  # chain), else nil: the lists draw chains from it.
68
68
  continues: session.continues,
69
69
  first_preview: first_preview_for(session),
70
+ # The session's own name (/title), else nil: the pages show it in
71
+ # place of the first message.
72
+ title: session.title,
70
73
  owner: owner&.kind,
71
74
  # The saved recap's first sentence, for the session card.
72
75
  recap: RecapStore.preview(session_dir),
@@ -933,8 +933,11 @@ module Samagotchi
933
933
  # finishes) comes after its command_queued. The cards it shows go out at
934
934
  # once (btw's "thinking…" card), after its command_queued, which the
935
935
  # UIs draw its line at (Engine#running_anytime). Its handler reads
936
- # copies (ctx.messages) and shows things through ctx only; nothing is
937
- # saved.
936
+ # copies (ctx.messages) and shows things through ctx only. One saves:
937
+ # /title, a field no turn writes, through Session#save, which takes the
938
+ # session's lock and writes a running turn's checkpoint (as
939
+ # WorkerSignals' save off the turn thread does), so the turn's own saves
940
+ # keep it.
938
941
  def start_anytime_command(command)
939
942
  @engine.spawn_anytime do
940
943
  result = command_result(command) { @engine.running_anytime { @commands.run(command.line, confirm: confirm?(command)) } }
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.94.0
4
+ version: 0.96.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Dedov
@@ -582,6 +582,7 @@ files:
582
582
  - lib/samagotchi/thinking_tails.rb
583
583
  - lib/samagotchi/thinking_ticker.rb
584
584
  - lib/samagotchi/thought_stream_splitter.rb
585
+ - lib/samagotchi/title_command.rb
585
586
  - lib/samagotchi/token_usage.rb
586
587
  - lib/samagotchi/tool_activity.rb
587
588
  - lib/samagotchi/tool_call_parser.rb
@@ -717,6 +718,7 @@ files:
717
718
  - lib/samagotchi/web/public/send_turn.js
718
719
  - lib/samagotchi/web/public/sentences.js
719
720
  - lib/samagotchi/web/public/session_actions.js
721
+ - lib/samagotchi/web/public/session_rename.js
720
722
  - lib/samagotchi/web/public/session_state.js
721
723
  - lib/samagotchi/web/public/session_title.js
722
724
  - lib/samagotchi/web/public/sessions_list.js