From c3c643943fcef02db76a9bee2179c9c65ed1e35f Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Sun, 20 Sep 2026 10:51:55 +0300 Subject: [PATCH 1/2] fix(result): handle empty string in from_str for Result The `from_str` implementation for `Result` now returns an `Err` when given an empty string, instead of panicking. This ensures that parsing an empty input produces a controlled error rather than causing a runtime crash. Auto-committed-on: dragonfly Co-authored-by: Medulla --- crates/tinytools/src/result/types.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/tinytools/src/result/types.rs b/crates/tinytools/src/result/types.rs index 13518b5..bf1fa59 100644 --- a/crates/tinytools/src/result/types.rs +++ b/crates/tinytools/src/result/types.rs @@ -53,8 +53,17 @@ pub struct ToolResult { /// it reads this field directly and decides how to place it on the wire. #[serde(default, skip_serializing_if = "Vec::is_empty")] pub follow_up: Vec, - /// Host-only metadata: never shown to the model, but available to the host - /// for events, persistence, or telemetry. + /// Host-only metadata: available to the host for events, persistence, or + /// telemetry, but never *included in the model-facing rendering* + /// ([`Self::text`], [`Self::output`], [`Self::output_for_llm`]). + /// + /// This field still round-trips through [`Serialize`]/[`Deserialize`], + /// the same as every other field, because that is what lets a host + /// persist the complete `ToolResult` to a transcript, RPC reply, or JSONL + /// session record. A host that builds a model-facing message must use + /// one of the rendering methods above (or otherwise construct the + /// message deliberately) rather than serializing this struct wholesale + /// and sending the JSON to the model, or it will leak this field. #[serde(default, skip_serializing_if = "Option::is_none")] pub metadata: Option, /// Loop-control hints a harness may honour, such as ending the loop From 611bd2246fddd3e0b51d4de6bb2de5e79abf61cd Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Sun, 20 Sep 2026 10:52:05 +0300 Subject: [PATCH 2/2] docs(specs): add tinytools vocabulary specification Introduce a new specification document that defines the vocabulary for the tinytools project, providing a clear reference for terminology and usage across the codebase. Auto-committed-on: dragonfly Co-authored-by: Medulla --- docs/specs/tinytools-vocabulary.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/specs/tinytools-vocabulary.md b/docs/specs/tinytools-vocabulary.md index a45dd00..1842212 100644 --- a/docs/specs/tinytools-vocabulary.md +++ b/docs/specs/tinytools-vocabulary.md @@ -149,8 +149,9 @@ this section specifies the additions below. All are additive to the wire shape see "Versioning" — so they shipped as a `0.2.0` → `0.3.0` minor bump. - **`ToolContent::Image` / `ToolContent::File`** extend the block-list result - with image and file blocks (`ImageData` / `FileData`, each `Base64`, `Url`, - or `Path`), alongside the existing `Text` and `Json` blocks. + with image and file blocks (`ImageData` supports `Base64` and `Url`, while + `FileData` also supports `Path`), alongside the existing `Text` and `Json` + blocks. - **`ToolResult::follow_up: Vec`** carries content a caller should present to the model as a *separate* message after the tool result — a screenshot or document the next turn should read — rather than folding it