Class: Insika::DSL::Builder

Inherits:
Object
  • Object
show all
Defined in:
lib/insika/dsl.rb

Overview

Collects the declarations and emits a Insika::Pack. Declarations map 1:1 to the pack manifest (AgentProfile.build attrs) + the pack's files/skills/tools — so what you write is exactly the data the engine stores.

Instance Method Summary collapse

Constructor Details

#initialize(id) ⇒ Builder

Returns a new instance of Builder.



110
111
112
113
114
115
116
117
118
119
120
# File 'lib/insika/dsl.rb', line 110

def initialize(id)
  @id = id.to_s
  @config = {}
  @files = {}
  @skills = {}
  @tools = []
  # Auto-enable the allowlist policies: harmless when the allowlist is nil=all,
  # correct once you restrict tools/skills. Visible in #to_pack — no hidden magic.
  @config[:policies] = %i[tool_allowlist skill_allowlist]
  @runtime = {} # non-pack knobs (llm provider/key/base) consumed by the runtime
end

Instance Method Details

#api_base(value) ⇒ Object



237
# File 'lib/insika/dsl.rb', line 237

def api_base(value) = @runtime[:api_base] = value.to_s

#api_key(value) ⇒ Object

--- runtime (LLM provider) config — NOT part of the pack ------------ Configures RubyLLM at chat/serve time. Defaults: provider = the agent's provider; key = ENV.



236
# File 'lib/insika/dsl.rb', line 236

def api_key(value) = @runtime[:api_key] = value.to_s

#build(&block) ⇒ Object



122
123
124
125
# File 'lib/insika/dsl.rb', line 122

def build(&block)
  instance_eval(&block) if block
  Definition.new(pack: to_pack, runtime: @runtime)
end

#data_tool(defn) ⇒ Object

A DATA-DEFINED (declarative HTTP) tool — pure config-over-code. defn is a ToolDefinition hash (name/description/parameters/binding…). Its name is auto-added to the allowlist so the agent can call its own tool (NF2).



157
158
159
160
161
162
163
# File 'lib/insika/dsl.rb', line 157

def data_tool(defn)
  h = defn.transform_keys(&:to_s)
  @tools << h
  name = h["name"].to_s
  (@config[:tools_allow] ||= []) << name unless name.empty? || Array(@config[:tools_allow]).include?(name)
  h
end

#declares(*names) ⇒ Object

Facts about THIS deployment that are not tools (RFC-0014 §3.5), so an eval case can declare what it needs and be skipped where it is absent instead of failing for the wrong reason. declares "promotions", "human_handoff"



208
209
210
# File 'lib/insika/dsl.rb', line 208

def declares(*names)
  (@config[:capabilities_declared] ||= []).concat(names.flatten.map(&:to_s))
end

#deny_tools(*names) ⇒ Object



150
151
152
# File 'lib/insika/dsl.rb', line 150

def deny_tools(*names)
  @config[:tools_deny] = names.flatten.map(&:to_s)
end

#edge_stream(hash) ⇒ Object

Which internal channels may cross to the CUSTOMER. Both off by default: the answer is the answer, and the provider's reasoning (thinking) or the model narrating its tool loop (intermediate) is for the Studio and the trace. Each opted-in channel gets its OWN frame type at /v1/responses — never the answer's — so a consumer that only reads the answer is unaffected either way. edge_stream thinking: true, intermediate: false



218
# File 'lib/insika/dsl.rb', line 218

def edge_stream(hash) = (@config[:edge_stream] ||= {}).merge!(hash.transform_keys(&:to_s))

#guardrails(hash) ⇒ Object

Content-safety guardrails (RFC-0009) — opt-in and configurable per agent. Pure config-over-code: the hash is stored on the profile and consumed by Safety::Config.from_profile. Merges, so repeated calls accumulate. guardrails input: true, output: true, strictness: "medium", moderator: "deepseek/deepseek-chat", responses: { "injection" => "I can't help with that." }



194
# File 'lib/insika/dsl.rb', line 194

def guardrails(hash) = (@config[:guardrails] ||= {}).merge!(hash.transform_keys(&:to_s))

#instructions(text) ⇒ Object Also known as: prompt



136
# File 'lib/insika/dsl.rb', line 136

def instructions(text) = @config[:base_prompt] = text.to_s

#limit(key, value) ⇒ Object

Per-agent limits (timeouts/budgets). limit :turn_timeout, 120 or limits(...).



227
# File 'lib/insika/dsl.rb', line 227

def limit(key, value) = (@config[:limits] ||= {})[key.to_sym] = value

#limits(hash) ⇒ Object



228
# File 'lib/insika/dsl.rb', line 228

def limits(hash) = (@config[:limits] ||= {}).merge!(hash.transform_keys(&:to_sym))

#max_tokens(value) ⇒ Object



224
# File 'lib/insika/dsl.rb', line 224

def max_tokens(value) = param(:max_tokens, value)

#memory(on = true) ⇒ Object

--- knobs -----------------------------------------------------------



186
# File 'lib/insika/dsl.rb', line 186

def memory(on = true) = @config[:memory] = on

#metadata(hash) ⇒ Object



231
# File 'lib/insika/dsl.rb', line 231

def (hash) = (@config[:metadata] ||= {}).merge!(hash.transform_keys(&:to_s))

#model(name) ⇒ Object

--- identity & model ------------------------------------------------



128
# File 'lib/insika/dsl.rb', line 128

def model(name) = @config[:model] = name.to_s

#param(key, value) ⇒ Object

LLM generation params (v2, §10). param :temperature, 0.2 or params(...).



221
# File 'lib/insika/dsl.rb', line 221

def param(key, value) = (@config[:params] ||= {})[key.to_sym] = value

#params(hash) ⇒ Object



222
# File 'lib/insika/dsl.rb', line 222

def params(hash) = (@config[:params] ||= {}).merge!(hash.transform_keys(&:to_sym))

#policies(*names) ⇒ Object



230
# File 'lib/insika/dsl.rb', line 230

def policies(*names) = @config[:policies] = names.flatten.map(&:to_sym)

#prompt_file(name, content) ⇒ Object

An extra prompt FILE (identity fragment). Name = the file name (e.g. "SOUL.md").



140
141
142
# File 'lib/insika/dsl.rb', line 140

def prompt_file(name, content)
  @files[name.to_s] = content.to_s
end

#provider(name) ⇒ Object

Provider for both the profile AND the RubyLLM configuration at run time.



131
132
133
134
# File 'lib/insika/dsl.rb', line 131

def provider(name)
  @config[:provider] = name.to_s
  @runtime[:provider] ||= name.to_s
end

#refine(hash) ⇒ Object

Refinement (RFC-0013) — how the agent's own instruction files may be improved from real traffic. Same config-over-code shape as guardrails; omitting it entirely leaves the agent report-only (phase A writes nothing). refine mode: "propose", window: { last_sessions: 200 }, files: %w, proposers: ["deepseek/deepseek-chat", "gpt-5-mini"], budget: { tokens: 200_000 }



202
# File 'lib/insika/dsl.rb', line 202

def refine(hash) = (@config[:refinement] ||= {}).merge!(hash.transform_keys(&:to_s))

#skill(name, content = nil, description: nil, instructions: nil) ⇒ Object

--- skills ---------------------------------------------------------- skill "escalate", "" — or — skill "escalate", description: "…", instructions: "…" The name is auto-added to the agent's skill allowlist.



169
170
171
172
173
174
# File 'lib/insika/dsl.rb', line 169

def skill(name, content = nil, description: nil, instructions: nil)
  n = name.to_s
  @skills[n] = normalize_skill(n, content, description, instructions)
  (@config[:skills] ||= []) << n unless @config.fetch(:skills, []).include?(n)
  n
end

#subagents(*ids) ⇒ Object

--- delegation ------------------------------------------------------ subagents "security", "performance" → the child agents this one MAY spawn (RFC-0010). CAPACITY field: opt-in, never inherited, and the ids must be agents of the same system (Insika.system { … }) or already in the store. Present ⇒ the engine wires spawn_subagent/spawn_subagents.



181
182
183
# File 'lib/insika/dsl.rb', line 181

def subagents(*ids)
  @config[:subagents] = ids.flatten.map(&:to_s)
end

#temperature(value) ⇒ Object



223
# File 'lib/insika/dsl.rb', line 223

def temperature(value) = param(:temperature, value)

#to_packObject

The generated portable artifact — the heart of "generates the data".



240
241
242
243
244
245
# File 'lib/insika/dsl.rb', line 240

def to_pack
  Insika::Pack.from_h(
    config: @config.merge(id: @id),
    files: @files, skills: @skills, tools: @tools
  )
end

#tools(*names) ⇒ Object

--- tools ----------------------------------------------------------- tools "a", "b" → allowlist [names]. Not called → nil = all (parity).



146
147
148
# File 'lib/insika/dsl.rb', line 146

def tools(*names)
  @config[:tools_allow] = names.flatten.map(&:to_s)
end