Module: Insika::Coercion
- Included in:
- CheckpointStore, DelegationStore, LLMProviderStore, McpStore, PendingActionStore, Refinement::EvidenceCollector, RefinementStore, SessionStore, StoredProfileSource, TaskStore
- Defined in:
- lib/insika/coercion.rb
Overview
Shared coercions at the input/persistence boundary. They used to live copied in each store/handler; a single home keeps them from drifting.
Constant Summary collapse
- TRUTHY =
The operator-facing truthy: what a form checkbox ("1"), a JSON round-trip ("true") or the DSL (true) produce for an opt-in. One list, one reading — AgentProfile#stream_public?, SkillCatalog#blanket? and the Studio all consult it, so a value that opts in on one surface cannot opt out on another.
[true, "true", "1", "yes", "on"].freeze
Class Method Summary collapse
-
.blank?(value) ⇒ Boolean
nil or blank (incl. whitespace-only) -> true.
-
.deep_stringify(obj) ⇒ Object
Normalizes keys and Symbols to String recursively (the stores' JSON model has no Symbol).
-
.presence(str) ⇒ Object
Present string or nil: nil and blank (incl. whitespace-only) become nil; everything else becomes a stripped String.
-
.present?(value) ⇒ Boolean
Inverse of blank? — a usable, non-empty value.
- .truthy?(value) ⇒ Boolean
-
.utf8(str) ⇒ Object
Bytes that come from outside the engine (sockets, pipes, subprocesses) arrive tagged BINARY, or as UTF-8 carrying invalid sequences.
Class Method Details
.blank?(value) ⇒ Boolean
nil or blank (incl. whitespace-only) -> true.
17 |
# File 'lib/insika/coercion.rb', line 17 def blank?(value) = value.nil? || value.to_s.strip.empty? |
.deep_stringify(obj) ⇒ Object
Normalizes keys and Symbols to String recursively (the stores' JSON model has no Symbol). Hash -> keys and values; Array -> elements.
45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/insika/coercion.rb', line 45 def deep_stringify(obj) case obj when Hash obj.each_with_object({}) { |(k, v), acc| acc[k.to_s] = deep_stringify(v) } when Array obj.map { |v| deep_stringify(v) } when Symbol obj.to_s else obj end end |
.presence(str) ⇒ Object
Present string or nil: nil and blank (incl. whitespace-only) become nil; everything else becomes a stripped String.
11 12 13 14 |
# File 'lib/insika/coercion.rb', line 11 def presence(str) s = str.to_s.strip s.empty? ? nil : s end |
.present?(value) ⇒ Boolean
Inverse of blank? — a usable, non-empty value.
20 |
# File 'lib/insika/coercion.rb', line 20 def present?(value) = !blank?(value) |
.truthy?(value) ⇒ Boolean
28 |
# File 'lib/insika/coercion.rb', line 28 def truthy?(value) = TRUTHY.include?(value) |
.utf8(str) ⇒ Object
Bytes that come from outside the engine (sockets, pipes, subprocesses)
arrive tagged BINARY, or as UTF-8 carrying invalid sequences. Both break
JSON.generate the moment the text has an accent or an emoji — today a
warning ("UTF-8 string passed as BINARY"), an exception from json 3.0 — and
that text ends up in a transcript, an event and an SSE frame. Reinterprets
the bytes as UTF-8 (the wire encoding of every source we read) and scrubs
what is not valid, so what crosses the boundary is always serializable.
37 38 39 40 41 |
# File 'lib/insika/coercion.rb', line 37 def utf8(str) s = str.to_s s = s.dup.force_encoding(Encoding::UTF_8) unless s.encoding == Encoding::UTF_8 s.valid_encoding? ? s : s.scrub end |