Class: Insika::DSL::Runtime

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

Overview

The live graph behind a Definition: it assembles the SAME authoring graph a concrete deployment does (Insika::Wiring::Graph + the runtime-authoring command surface), configures RubyLLM, and imports the definition's pack via the standard PackImporter. From there the agent is indistinguishable from one provisioned by any other pack — chat and serve just drive the normal path.

Built lazily by Definition#runtime, so require "insika" never pays for ruby_llm or the HTTP server.

Constant Summary collapse

TERMINAL =
%i[task_completed task_failed task_cancelled].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(definition, backend: nil) ⇒ Runtime

definition is a Definition (one agent) or a System (N agents). Both answer #pack/#id; a System also answers #packs. Duck-typed on purpose: the runtime does not care how many agents it hosts, only that each one arrives as an ordinary Pack.

backend: the store this graph owns. nil = the historic path, INSIKA_DB or memory — ENV is a default, never a requirement (the embed contract). An injected backend wins and is never widened back to the environment.



33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/insika/dsl/runtime.rb', line 33

def initialize(definition, backend: nil)
  @definition = definition
  @injected_backend = backend
  @packs = (definition.respond_to?(:packs) ? Array(definition.packs) : [definition.pack]).freeze
  @pack = @packs.first
  # the graph's OWN RubyLLM config, built before the graph so
  # every collaborator that talks to a provider is handed it at wiring time
  # rather than reading a process-wide singleton at call time.
  @llm = build_llm_context
  @graph = build_graph
  seed_default_model
  import_packs
end

Instance Attribute Details

#graphObject (readonly)

graph: the assembled Wiring::Graph::Result; pack: the PRIMARY imported Pack; packs: every imported Pack (one per agent — a System has N, a Definition has one). All read by the server boot and the specs.



22
23
24
# File 'lib/insika/dsl/runtime.rb', line 22

def graph
  @graph
end

#llmObject (readonly)

The graph's RubyLLM context — an isolated config dup that answers #chat. nil only under the test stub, where the fallback is the RubyLLM constant itself. Read by the specs and by anything a host wires alongside this graph.



51
52
53
# File 'lib/insika/dsl/runtime.rb', line 51

def llm
  @llm
end

#packObject (readonly)

graph: the assembled Wiring::Graph::Result; pack: the PRIMARY imported Pack; packs: every imported Pack (one per agent — a System has N, a Definition has one). All read by the server boot and the specs.



22
23
24
# File 'lib/insika/dsl/runtime.rb', line 22

def pack
  @pack
end

#packsObject (readonly)

graph: the assembled Wiring::Graph::Result; pack: the PRIMARY imported Pack; packs: every imported Pack (one per agent — a System has N, a Definition has one). All read by the server boot and the specs.



22
23
24
# File 'lib/insika/dsl/runtime.rb', line 22

def packs
  @packs
end

Instance Method Details

#chat(message, session_id: nil, timeout: nil, agent: nil) ⇒ Object

One turn, in-process → the assistant's text. session_id nil = stateless one-shot; a value threads multi-turn memory (created on first use). agent: targets one agent of a system (default: the primary).



64
65
66
67
68
69
70
71
# File 'lib/insika/dsl/runtime.rb', line 64

def chat(message, session_id: nil, timeout: nil, agent: nil)
  command = Insika::Command.build(
    :send_message,
    { agent: (agent || @definition.id).to_s, message: message, session_id: session_id },
    transport: :cli
  )
  run_command(command, session_id: session_id, timeout: timeout)[:text]
end

#component(name) ⇒ Object

A named collaborator (settings_store, tool_store, …) the server boot reads.



92
# File 'lib/insika/dsl/runtime.rb', line 92

def component(name) = @components.fetch(name)

#profile(agent_id = nil) ⇒ Object

An imported profile, read back from the store (config-over-code round-trip). Defaults to the primary agent.



55
56
57
58
59
# File 'lib/insika/dsl/runtime.rb', line 55

def profile(agent_id = nil)
  id = (agent_id || @definition.id).to_s
  @graph.profiles.fetch(id) ||
    (raise Insika::Error, "agent '#{id}' was not imported")
end

#run_workflow(name, input:, agent:, timeout: nil) ⇒ Object

Triggers a declared workflow and returns its OUTPUT (the typed value the workflow returned), not the turn text. A schema violation on the input raises here, synchronously, with no run created — same contract as POST /v1/workflows/:name.



77
78
79
80
81
82
83
# File 'lib/insika/dsl/runtime.rb', line 77

def run_workflow(name, input:, agent:, timeout: nil)
  command = Insika::Command.build(
    :trigger_workflow, { workflow: name, agent: agent, input: input }, transport: :cli
  )
  outcome = run_command(command, session_id: nil, timeout: timeout)
  outcome.key?(:output) ? outcome[:output] : outcome[:text]
end

#serve(port:, host:, token:, **_opts) ⇒ Object

Boot the control UI (/studio) + drop-in API (/v1). Blocks on the reactor.



86
87
88
89
# File 'lib/insika/dsl/runtime.rb', line 86

def serve(port:, host:, token:, **_opts)
  require_relative "server_boot"
  ServerBoot.new(self, port: port, host: host, token: token).run
end