samagotchi 0.24.0 → 0.25.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 +54 -1
- data/docs/architecture.md +16 -9
- data/docs/cli.md +4 -3
- data/docs/configuration.md +21 -13
- data/docs/hooks.md +1 -1
- data/docs/internals/background-tasks.md +1 -0
- data/docs/internals/prompt-caching.md +94 -0
- data/docs/plugins.md +16 -2
- data/docs/testing.md +12 -0
- data/lib/samagotchi/bundles/loop-guard/manifest.yml +2 -2
- data/lib/samagotchi/bundles/loop-guard/plugin.rb +43 -7
- data/lib/samagotchi/bundles/system/manifest.yml +1 -1
- data/lib/samagotchi/command_steps.rb +233 -0
- data/lib/samagotchi/config.rb +5 -2
- data/lib/samagotchi/empty_answer_retry.rb +2 -2
- data/lib/samagotchi/engine.rb +23 -4
- data/lib/samagotchi/guardrails/shell_lex.rb +49 -5
- data/lib/samagotchi/idle_client.rb +14 -2
- data/lib/samagotchi/kernel_loop.rb +21 -3
- data/lib/samagotchi/llm/chat_loop.rb +17 -3
- data/lib/samagotchi/llm/errors.rb +26 -1
- data/lib/samagotchi/llm/openai_chat.rb +5 -4
- data/lib/samagotchi/llm/prompt_cache.rb +34 -9
- data/lib/samagotchi/llm/usage.rb +18 -3
- data/lib/samagotchi/log_subscriber.rb +2 -1
- data/lib/samagotchi/plugin/api.rb +3 -2
- data/lib/samagotchi/session_metrics.rb +38 -4
- data/lib/samagotchi/system_prompt.rb +30 -9
- data/lib/samagotchi/terminal_ui/attached_loop.rb +5 -2
- data/lib/samagotchi/terminal_ui/attached_view.rb +6 -2
- data/lib/samagotchi/terminal_ui/event_renderer.rb +14 -2
- data/lib/samagotchi/terminal_ui/formatting.rb +31 -9
- data/lib/samagotchi/thinking_tails.rb +103 -0
- data/lib/samagotchi/token_usage.rb +18 -6
- data/lib/samagotchi/tool_activity.rb +37 -3
- data/lib/samagotchi/tool_declarations.rb +14 -0
- data/lib/samagotchi/tool_view.rb +40 -4
- data/lib/samagotchi/tools/builtins.rb +4 -1
- data/lib/samagotchi/tools/execute.rb +2 -1
- data/lib/samagotchi/tools/registry.rb +11 -4
- data/lib/samagotchi/tools/shell.rb +32 -0
- data/lib/samagotchi/tools/task_runtime.rb +3 -3
- data/lib/samagotchi/turn_tally.rb +17 -6
- data/lib/samagotchi/version.rb +1 -1
- data/lib/samagotchi/web/public/command_view.js +71 -3
- data/lib/samagotchi/web/public/format.js +11 -1
- data/lib/samagotchi/web/public/index.html +25 -0
- data/lib/samagotchi/web/public/stage_model.js +5 -1
- data/lib/samagotchi/web/public/stage_view.js +1 -1
- data/lib/samagotchi/web/public/turn_view.js +3 -3
- metadata +5 -1
|
@@ -141,6 +141,31 @@ main{flex:1;display:flex;flex-direction:column;gap:16px;padding:16px;overflow:au
|
|
|
141
141
|
.activity-command-cwd{margin-bottom:2px}
|
|
142
142
|
.activity-command-cwd>span{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--text-muted)}
|
|
143
143
|
.activity-command-cut{margin-top:2px}
|
|
144
|
+
.activity-command-desc{font-size:12px;line-height:1.4;color:var(--text-2);margin-bottom:3px;overflow-wrap:anywhere}
|
|
145
|
+
/* The command as its steps (CommandSteps): the op that links each to the one before, labels as small headings, limits and heredocs as chips; "raw" swaps in the command as written (CSS only). */
|
|
146
|
+
.activity-command.has-steps{background:var(--bg-inset);border:1px solid var(--border);border-radius:6px;padding:4px 8px 5px}
|
|
147
|
+
.activity-command-head{display:flex;align-items:center;gap:8px;min-height:20px;padding-right:30px}
|
|
148
|
+
.has-steps .activity-command-cwd{flex:1 1 auto;min-width:0;margin:0;overflow-wrap:anywhere}
|
|
149
|
+
.activity-command-cwd>.activity-command-sep{font-family:inherit;color:var(--text-faint)}
|
|
150
|
+
.activity-command-raw{flex:none;display:inline-flex;align-items:center;height:18px;padding:0 7px;border:1px solid var(--border-strong);border-radius:9px;font-size:11px;color:var(--text-muted);cursor:pointer;user-select:none;-webkit-user-select:none}
|
|
151
|
+
.activity-command-raw:hover{color:var(--text-2)}
|
|
152
|
+
.activity-command-raw input{position:absolute;opacity:0;width:0;height:0;margin:0}
|
|
153
|
+
.activity-command-raw:has(input:focus-visible){outline:2px solid var(--accent);outline-offset:1px}
|
|
154
|
+
.activity-command-raw:has(input:checked){color:var(--accent);border-color:var(--accent-border);background:var(--accent-tint)}
|
|
155
|
+
.activity-steps{list-style:none;margin:2px 0 0;padding:0;max-height:220px;overflow:auto;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.5;color:var(--text-2)}
|
|
156
|
+
.activity-step{display:flex;align-items:baseline;gap:6px;min-width:0}
|
|
157
|
+
.step-body{flex:1 1 auto;min-width:0;display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 6px}
|
|
158
|
+
.step-body>code{min-width:0;font:inherit;white-space:pre-wrap;overflow-wrap:anywhere}
|
|
159
|
+
.step-op{flex:none;width:2.4em;text-align:right;font-family:ui-sans-serif,system-ui,sans-serif;font-size:11px;color:var(--text-faint)}
|
|
160
|
+
.step-op.else{color:var(--warn-text)}
|
|
161
|
+
.step-label{margin:5px 0 0 calc(2.4em + 6px);font-family:ui-sans-serif,system-ui,sans-serif;font-size:11px;font-weight:600;color:var(--text-muted)}
|
|
162
|
+
.step-label:first-child{margin-top:1px}
|
|
163
|
+
.step-chip{flex:none;align-self:center;padding:0 6px;border:1px solid var(--border-strong);border-radius:8px;font-family:ui-sans-serif,system-ui,sans-serif;font-size:10.5px;line-height:15px;color:var(--text-muted);white-space:nowrap}
|
|
164
|
+
.step-chip.heredoc{border-style:dashed}
|
|
165
|
+
.step-plumbing{color:var(--text-faint)}
|
|
166
|
+
.activity-command.has-steps>pre{display:none;max-height:220px;margin-top:2px;padding:0 4px;background:none;border:0}
|
|
167
|
+
.has-steps:has(.activity-command-raw input:checked)>pre{display:block}
|
|
168
|
+
.has-steps:has(.activity-command-raw input:checked)>.activity-steps{display:none}
|
|
144
169
|
@media(max-width:600px){
|
|
145
170
|
.activity-params{flex:1 1 0}
|
|
146
171
|
.activity-output{margin-left:0}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// covers the rules; stage_view.js draws them.
|
|
5
5
|
import { toolName } from "./activity.js";
|
|
6
6
|
import { splitSentences } from "./sentences.js";
|
|
7
|
+
import { steerSender } from "./format.js";
|
|
7
8
|
import { hookNoticeLabel } from "./turn_events.js";
|
|
8
9
|
|
|
9
10
|
const READ_LIKE = new Set(["read", "memory_read", "web_fetch", "task_get", "task_list", "list_sessions"]);
|
|
@@ -174,7 +175,10 @@ export function handOffOrder({ prompt = null, block = null, extras = [], answer
|
|
|
174
175
|
// chi's own asking-again row (a notice with a line and no hook) does not:
|
|
175
176
|
// the status line tells that already. null: nothing flashes.
|
|
176
177
|
export function flashOf(what, data = {}) {
|
|
177
|
-
if (what === "steer")
|
|
178
|
+
if (what === "steer") {
|
|
179
|
+
const sender = steerSender(data.source);
|
|
180
|
+
return { kind: "steer", text: sender ? `${sender} nudged the model` : "nudged the model" };
|
|
181
|
+
}
|
|
178
182
|
if (what !== "notice" || !data.hook) return null;
|
|
179
183
|
return { kind: data.level === "warn" ? "warn" : "info", text: data.line || `${hookNoticeLabel(data.hook)}: ${data.text || ""}` };
|
|
180
184
|
}
|
|
@@ -234,7 +234,7 @@ export function createStageView({ historyEl, appendToHistory, isNearBottom: hist
|
|
|
234
234
|
name.textContent = tool.name;
|
|
235
235
|
const title = node("span", "ts-title", now);
|
|
236
236
|
title.textContent = tool.title;
|
|
237
|
-
// The full command when the call has one (the title is its first
|
|
237
|
+
// The full command when the call has one (the title is its first step +N).
|
|
238
238
|
title.title = tool.command || tool.title;
|
|
239
239
|
} else {
|
|
240
240
|
const word = node("span", "ts-title quiet", now);
|
|
@@ -54,8 +54,8 @@ function fillActivityRow(el, row, sessionId) {
|
|
|
54
54
|
const outEl = el.querySelector(".activity-output");
|
|
55
55
|
// The call's full command, above its output (running too).
|
|
56
56
|
if (row.view?.command && !el.querySelector(".activity-command")) {
|
|
57
|
-
if (outEl) outEl.insertAdjacentHTML("beforebegin", commandBlockHtml(row.view));
|
|
58
|
-
else el.insertAdjacentHTML("beforeend", commandBlockHtml(row.view));
|
|
57
|
+
if (outEl) outEl.insertAdjacentHTML("beforebegin", commandBlockHtml(row.view, row.title));
|
|
58
|
+
else el.insertAdjacentHTML("beforeend", commandBlockHtml(row.view, row.title));
|
|
59
59
|
}
|
|
60
60
|
if (outEl) {
|
|
61
61
|
if (row.status === "running") {
|
|
@@ -691,7 +691,7 @@ function reloadRowHtml(r, thumbs) {
|
|
|
691
691
|
: "";
|
|
692
692
|
return `<div class="activity-row" data-key="${escapeHtml(r.key)}"><span class="activity-status ${activityStatusClass(r.status)}">${activityStatusLabel(r.status)}</span>` +
|
|
693
693
|
`<span class="activity-tool">${escapeHtml(toolName(r))}</span>${params}${duration ? `<span class="activity-duration">${escapeHtml(duration)}</span>` : ""}` +
|
|
694
|
-
`${commandBlockHtml(r.view)}${output}` +
|
|
694
|
+
`${commandBlockHtml(r.view, r.title)}${output}` +
|
|
695
695
|
`${r.images?.length ? thumbs(r.images) : ""}${r.diff ? activityDiffHtml(r.diff) : ""}</div>`;
|
|
696
696
|
}
|
|
697
697
|
|
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.25.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dmitry Dedov
|
|
@@ -131,6 +131,7 @@ files:
|
|
|
131
131
|
- docs/internals/background-tasks.md
|
|
132
132
|
- docs/internals/context-telemetry.md
|
|
133
133
|
- docs/internals/gemma4-contract.md
|
|
134
|
+
- docs/internals/prompt-caching.md
|
|
134
135
|
- docs/internals/tool-guardrails.md
|
|
135
136
|
- docs/memory.md
|
|
136
137
|
- docs/plugins.md
|
|
@@ -196,6 +197,7 @@ files:
|
|
|
196
197
|
- lib/samagotchi/cli/flags.rb
|
|
197
198
|
- lib/samagotchi/cli/parent_wait.rb
|
|
198
199
|
- lib/samagotchi/client.rb
|
|
200
|
+
- lib/samagotchi/command_steps.rb
|
|
199
201
|
- lib/samagotchi/commands/registry.rb
|
|
200
202
|
- lib/samagotchi/config.rb
|
|
201
203
|
- lib/samagotchi/config_text_edit.rb
|
|
@@ -373,6 +375,7 @@ files:
|
|
|
373
375
|
- lib/samagotchi/terminal_ui/version_lines.rb
|
|
374
376
|
- lib/samagotchi/text_diff.rb
|
|
375
377
|
- lib/samagotchi/thinking.rb
|
|
378
|
+
- lib/samagotchi/thinking_tails.rb
|
|
376
379
|
- lib/samagotchi/thinking_ticker.rb
|
|
377
380
|
- lib/samagotchi/thought_stream_splitter.rb
|
|
378
381
|
- lib/samagotchi/token_usage.rb
|
|
@@ -402,6 +405,7 @@ files:
|
|
|
402
405
|
- lib/samagotchi/tools/register_reminder.rb
|
|
403
406
|
- lib/samagotchi/tools/registry.rb
|
|
404
407
|
- lib/samagotchi/tools/send_note.rb
|
|
408
|
+
- lib/samagotchi/tools/shell.rb
|
|
405
409
|
- lib/samagotchi/tools/task_create.rb
|
|
406
410
|
- lib/samagotchi/tools/task_get.rb
|
|
407
411
|
- lib/samagotchi/tools/task_list.rb
|