insika 0.0.1 → 0.1.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.
Files changed (260) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +295 -0
  3. data/LICENSE +21 -0
  4. data/README.md +136 -2
  5. data/bin/insika +351 -0
  6. data/docs/AGENTS.md +494 -0
  7. data/docs/ARCHITECTURE.md +333 -0
  8. data/docs/BENCHMARK.md +114 -0
  9. data/docs/CHANNELS.md +453 -0
  10. data/docs/CONTEXT.md +100 -0
  11. data/docs/DEPLOY.md +334 -0
  12. data/docs/EMBEDDING.md +194 -0
  13. data/docs/EVALS.md +273 -0
  14. data/docs/LOADTEST.md +231 -0
  15. data/docs/OBSERVABILITY.md +365 -0
  16. data/docs/PLUGINS.md +211 -0
  17. data/docs/REFINEMENT.md +477 -0
  18. data/docs/RELEASING.md +70 -0
  19. data/docs/RUNNING-LOCAL.md +153 -0
  20. data/docs/SANDBOX.md +114 -0
  21. data/docs/SECURITY.md +362 -0
  22. data/docs/SKILLS.md +98 -0
  23. data/docs/TOOLS.md +302 -0
  24. data/docs/WHY.md +137 -0
  25. data/docs/WORKFLOWS.md +225 -0
  26. data/docs/build.md +14 -0
  27. data/docs/index.md +68 -0
  28. data/docs/onboarding/start.md +126 -0
  29. data/docs/operate.md +12 -0
  30. data/docs/ship.md +10 -0
  31. data/docs/understand.md +10 -0
  32. data/lib/insika/agent_file_store.rb +125 -0
  33. data/lib/insika/agent_profile.rb +188 -0
  34. data/lib/insika/allowlist.rb +28 -0
  35. data/lib/insika/baseline_store.rb +74 -0
  36. data/lib/insika/capability/resolved_tool.rb +34 -0
  37. data/lib/insika/capability_registry.rb +112 -0
  38. data/lib/insika/channel_delivery.rb +150 -0
  39. data/lib/insika/channel_registry.rb +30 -0
  40. data/lib/insika/channels/relay.rb +178 -0
  41. data/lib/insika/channels/web/widget.js +283 -0
  42. data/lib/insika/channels/web.rb +211 -0
  43. data/lib/insika/chat_builder.rb +254 -0
  44. data/lib/insika/checkpoint.rb +13 -0
  45. data/lib/insika/checkpoint_store.rb +153 -0
  46. data/lib/insika/coercion.rb +50 -0
  47. data/lib/insika/command.rb +32 -0
  48. data/lib/insika/command_bus.rb +39 -0
  49. data/lib/insika/commands/agent_payload.rb +41 -0
  50. data/lib/insika/commands/approve_action.rb +46 -0
  51. data/lib/insika/commands/cancel_task.rb +33 -0
  52. data/lib/insika/commands/create_agent.rb +54 -0
  53. data/lib/insika/commands/create_session.rb +67 -0
  54. data/lib/insika/commands/delete_agent.rb +33 -0
  55. data/lib/insika/commands/delete_agent_file.rb +50 -0
  56. data/lib/insika/commands/delete_data_tool.rb +33 -0
  57. data/lib/insika/commands/delete_llm_provider.rb +36 -0
  58. data/lib/insika/commands/delete_mcp.rb +30 -0
  59. data/lib/insika/commands/delete_system_file.rb +29 -0
  60. data/lib/insika/commands/gate_refinement.rb +245 -0
  61. data/lib/insika/commands/import_mcp_tools.rb +48 -0
  62. data/lib/insika/commands/import_tools.rb +81 -0
  63. data/lib/insika/commands/memory_add_note.rb +32 -0
  64. data/lib/insika/commands/memory_forget_fact.rb +32 -0
  65. data/lib/insika/commands/memory_put_fact.rb +35 -0
  66. data/lib/insika/commands/pause_task.rb +29 -0
  67. data/lib/insika/commands/resolve_refinement.rb +126 -0
  68. data/lib/insika/commands/restore_agent_file.rb +36 -0
  69. data/lib/insika/commands/restore_data_tool.rb +34 -0
  70. data/lib/insika/commands/restore_system_file.rb +31 -0
  71. data/lib/insika/commands/resume_task.rb +85 -0
  72. data/lib/insika/commands/run_refinement.rb +133 -0
  73. data/lib/insika/commands/send_message.rb +150 -0
  74. data/lib/insika/commands/set_agent_tools.rb +39 -0
  75. data/lib/insika/commands/set_skill_agents.rb +71 -0
  76. data/lib/insika/commands/trigger_workflow.rb +80 -0
  77. data/lib/insika/commands/update_agent.rb +49 -0
  78. data/lib/insika/commands/update_settings.rb +33 -0
  79. data/lib/insika/commands/upsert_llm_provider.rb +34 -0
  80. data/lib/insika/commands/upsert_mcp.rb +32 -0
  81. data/lib/insika/commands/write_agent_file.rb +57 -0
  82. data/lib/insika/commands/write_data_tool.rb +43 -0
  83. data/lib/insika/commands/write_golden.rb +58 -0
  84. data/lib/insika/commands/write_skill.rb +50 -0
  85. data/lib/insika/commands/write_system_file.rb +31 -0
  86. data/lib/insika/config_store.rb +85 -0
  87. data/lib/insika/context/builder.rb +166 -0
  88. data/lib/insika/context/catalog_provider.rb +23 -0
  89. data/lib/insika/context/fragment.rb +19 -0
  90. data/lib/insika/context/priority.rb +29 -0
  91. data/lib/insika/context/provider.rb +19 -0
  92. data/lib/insika/context/providers/memory.rb +60 -0
  93. data/lib/insika/context/providers/prompt.rb +105 -0
  94. data/lib/insika/context/providers/request.rb +32 -0
  95. data/lib/insika/context/providers/session.rb +108 -0
  96. data/lib/insika/context/providers/skill.rb +20 -0
  97. data/lib/insika/context/providers/tool_search.rb +20 -0
  98. data/lib/insika/delegation_store.rb +153 -0
  99. data/lib/insika/doctor.rb +294 -0
  100. data/lib/insika/dsl/definition.rb +55 -0
  101. data/lib/insika/dsl/runtime.rb +379 -0
  102. data/lib/insika/dsl/server_boot.rb +97 -0
  103. data/lib/insika/dsl/system.rb +93 -0
  104. data/lib/insika/dsl/workflow_adapter.rb +59 -0
  105. data/lib/insika/dsl.rb +307 -0
  106. data/lib/insika/edge_limiter.rb +130 -0
  107. data/lib/insika/egress_guard.rb +75 -0
  108. data/lib/insika/env_schema.rb +246 -0
  109. data/lib/insika/errors.rb +145 -0
  110. data/lib/insika/evals/assertions.rb +247 -0
  111. data/lib/insika/evals/baseline.rb +69 -0
  112. data/lib/insika/evals/golden.rb +172 -0
  113. data/lib/insika/evals/judge.rb +225 -0
  114. data/lib/insika/evals/pairwise.rb +178 -0
  115. data/lib/insika/evals/report.rb +115 -0
  116. data/lib/insika/evals/runner.rb +141 -0
  117. data/lib/insika/evals/transport.rb +178 -0
  118. data/lib/insika/event.rb +18 -0
  119. data/lib/insika/event_stream.rb +114 -0
  120. data/lib/insika/executor.rb +1680 -0
  121. data/lib/insika/frontmatter.rb +42 -0
  122. data/lib/insika/golden_store.rb +145 -0
  123. data/lib/insika/hooks.rb +48 -0
  124. data/lib/insika/http_client.rb +63 -0
  125. data/lib/insika/inbound_log.rb +84 -0
  126. data/lib/insika/llm_configurator.rb +99 -0
  127. data/lib/insika/llm_provider_store.rb +83 -0
  128. data/lib/insika/mcp_http_client.rb +67 -0
  129. data/lib/insika/mcp_store.rb +115 -0
  130. data/lib/insika/mcp_tool_ingestor.rb +143 -0
  131. data/lib/insika/memory_store.rb +93 -0
  132. data/lib/insika/message_origin.rb +76 -0
  133. data/lib/insika/middleware.rb +36 -0
  134. data/lib/insika/model_policy.rb +52 -0
  135. data/lib/insika/model_resolver.rb +176 -0
  136. data/lib/insika/model_selection.rb +114 -0
  137. data/lib/insika/onboarding.rb +208 -0
  138. data/lib/insika/outbox_store.rb +166 -0
  139. data/lib/insika/overlay_tool_registry.rb +103 -0
  140. data/lib/insika/pack.rb +102 -0
  141. data/lib/insika/pack_importer.rb +121 -0
  142. data/lib/insika/pending_action_store.rb +120 -0
  143. data/lib/insika/plugin/loader.rb +356 -0
  144. data/lib/insika/plugin.rb +35 -0
  145. data/lib/insika/policy/engine.rb +83 -0
  146. data/lib/insika/policy/policy.rb +120 -0
  147. data/lib/insika/policy_registry.rb +23 -0
  148. data/lib/insika/profile_source.rb +137 -0
  149. data/lib/insika/prompt_catalog.rb +61 -0
  150. data/lib/insika/queue_policy.rb +167 -0
  151. data/lib/insika/recovery.rb +127 -0
  152. data/lib/insika/refinement/candidate.rb +159 -0
  153. data/lib/insika/refinement/evidence_collector.rb +371 -0
  154. data/lib/insika/refinement/gate.rb +234 -0
  155. data/lib/insika/refinement/panel.rb +222 -0
  156. data/lib/insika/refinement/proposer.rb +262 -0
  157. data/lib/insika/refinement_store.rb +295 -0
  158. data/lib/insika/registry.rb +59 -0
  159. data/lib/insika/safety/config.rb +109 -0
  160. data/lib/insika/safety/detectors.rb +176 -0
  161. data/lib/insika/safety/factory.rb +102 -0
  162. data/lib/insika/safety/input_guardrail.rb +87 -0
  163. data/lib/insika/safety/moderator.rb +86 -0
  164. data/lib/insika/safety/output_filter.rb +79 -0
  165. data/lib/insika/safety/output_validator.rb +101 -0
  166. data/lib/insika/safety/safe_responses.rb +47 -0
  167. data/lib/insika/sandbox/boundary.rb +93 -0
  168. data/lib/insika/sandbox/docker.rb +74 -0
  169. data/lib/insika/sandbox/local.rb +33 -0
  170. data/lib/insika/sandbox/runner.rb +80 -0
  171. data/lib/insika/sandbox.rb +85 -0
  172. data/lib/insika/schema_guard.rb +147 -0
  173. data/lib/insika/secret_masking.rb +34 -0
  174. data/lib/insika/server/a2a/agent_card.rb +27 -0
  175. data/lib/insika/server/a2a/app.rb +112 -0
  176. data/lib/insika/server/a2a/client.rb +101 -0
  177. data/lib/insika/server/a2a/errors.rb +32 -0
  178. data/lib/insika/server/a2a/http.rb +42 -0
  179. data/lib/insika/server/a2a/message.rb +27 -0
  180. data/lib/insika/server/a2a/protocol.rb +45 -0
  181. data/lib/insika/server/a2a/remotes.rb +25 -0
  182. data/lib/insika/server/a2a/task_projection.rb +40 -0
  183. data/lib/insika/server/admin_auth.rb +29 -0
  184. data/lib/insika/server/app.rb +850 -0
  185. data/lib/insika/server/boot.rb +119 -0
  186. data/lib/insika/server/rack_app.rb +110 -0
  187. data/lib/insika/server/responses.rb +155 -0
  188. data/lib/insika/server/sse_body.rb +96 -0
  189. data/lib/insika/session_actor.rb +162 -0
  190. data/lib/insika/session_store.rb +143 -0
  191. data/lib/insika/settings_store.rb +154 -0
  192. data/lib/insika/shutdown.rb +125 -0
  193. data/lib/insika/skill_catalog.rb +113 -0
  194. data/lib/insika/skill_store.rb +79 -0
  195. data/lib/insika/steer_injector.rb +110 -0
  196. data/lib/insika/store.rb +52 -0
  197. data/lib/insika/stores/memory.rb +123 -0
  198. data/lib/insika/stores/sqlite.rb +183 -0
  199. data/lib/insika/studio/app.rb +1571 -0
  200. data/lib/insika/studio/assets/dist/application.css +1 -0
  201. data/lib/insika/studio/assets/dist/application.js +69 -0
  202. data/lib/insika/studio/forms.rb +340 -0
  203. data/lib/insika/studio/nav_icons.rb +31 -0
  204. data/lib/insika/studio/views/_message.erb +44 -0
  205. data/lib/insika/studio/views/agent_detail.erb +285 -0
  206. data/lib/insika/studio/views/agents.erb +63 -0
  207. data/lib/insika/studio/views/approvals.erb +41 -0
  208. data/lib/insika/studio/views/chats.erb +34 -0
  209. data/lib/insika/studio/views/evals.erb +83 -0
  210. data/lib/insika/studio/views/home.erb +72 -0
  211. data/lib/insika/studio/views/layout.erb +94 -0
  212. data/lib/insika/studio/views/login.erb +17 -0
  213. data/lib/insika/studio/views/mcp.erb +91 -0
  214. data/lib/insika/studio/views/not_found.erb +5 -0
  215. data/lib/insika/studio/views/playground.erb +47 -0
  216. data/lib/insika/studio/views/refinement.erb +234 -0
  217. data/lib/insika/studio/views/session.erb +62 -0
  218. data/lib/insika/studio/views/settings.erb +173 -0
  219. data/lib/insika/studio/views/skills.erb +86 -0
  220. data/lib/insika/studio/views/system_files.erb +65 -0
  221. data/lib/insika/studio/views/task.erb +105 -0
  222. data/lib/insika/studio/views/tasks.erb +33 -0
  223. data/lib/insika/studio/views/tool_edit.erb +107 -0
  224. data/lib/insika/studio/views/tools.erb +89 -0
  225. data/lib/insika/subagent_graph.rb +96 -0
  226. data/lib/insika/system_file_store.rb +96 -0
  227. data/lib/insika/task_actor.rb +128 -0
  228. data/lib/insika/task_store.rb +250 -0
  229. data/lib/insika/telemetry/pricing.rb +104 -0
  230. data/lib/insika/telemetry/recorder.rb +228 -0
  231. data/lib/insika/telemetry.rb +127 -0
  232. data/lib/insika/testing/store_contract.rb +270 -0
  233. data/lib/insika/token_estimator.rb +16 -0
  234. data/lib/insika/tool_assembly.rb +140 -0
  235. data/lib/insika/tool_catalog.rb +89 -0
  236. data/lib/insika/tool_definition.rb +518 -0
  237. data/lib/insika/tool_envelope.rb +140 -0
  238. data/lib/insika/tool_manifest.rb +218 -0
  239. data/lib/insika/tool_registry.rb +21 -0
  240. data/lib/insika/tool_store.rb +135 -0
  241. data/lib/insika/tool_trace_store.rb +92 -0
  242. data/lib/insika/tools/a2a_remote.rb +48 -0
  243. data/lib/insika/tools/agent_enum.rb +68 -0
  244. data/lib/insika/tools/concurrency.rb +54 -0
  245. data/lib/insika/tools/data_defined_tool.rb +220 -0
  246. data/lib/insika/tools/load_skill.rb +41 -0
  247. data/lib/insika/tools/remember.rb +53 -0
  248. data/lib/insika/tools/subagent.rb +75 -0
  249. data/lib/insika/tools/subagents.rb +77 -0
  250. data/lib/insika/tools/tool_search.rb +94 -0
  251. data/lib/insika/turn_output.rb +139 -0
  252. data/lib/insika/turn_state.rb +158 -0
  253. data/lib/insika/turn_timing.rb +56 -0
  254. data/lib/insika/usage_ledger.rb +47 -0
  255. data/lib/insika/version.rb +3 -1
  256. data/lib/insika/wiring/graph.rb +198 -0
  257. data/lib/insika/workflow.rb +185 -0
  258. data/lib/insika/workflow_registry.rb +33 -0
  259. data/lib/insika.rb +203 -4
  260. metadata +395 -8
@@ -0,0 +1,185 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Insika
4
+ # Workflow surface (item 22 / COMPETITIVE-ANALYSIS §4.4). A workflow is a Ruby
5
+ # callable orchestrating RubyLLM Agents/Workflows FROM WITHIN (RubyLLM First);
6
+ # its durable RUN is a Task (checkpointed, recoverable — stronger than Flue's
7
+ # at-most-once run record). This module adds the EXPOSED surface the consumer
8
+ # asked for, matching the honest Flue scope (not Temporal):
9
+ # · runId — the run id (== task id; the Task IS the run record).
10
+ # · event stream — :workflow_started / :workflow_completed on the task stream.
11
+ # · I/O by schema — optional input_schema / output_schema validated at the edges.
12
+ #
13
+ # A schema is any dry-schema-compatible validator: `#call(value)` returning a
14
+ # result that responds to `#success?` and `#errors` (dry-schema's own contract).
15
+ # As a batteries-included default, a plain JSON Schema Hash (the interlingua the
16
+ # ToolDefinition already speaks) is accepted and validated by the zero-dependency
17
+ # Schema below — "config over convention": bring dry-schema for richer contracts,
18
+ # or hand a JSON Schema for the common case.
19
+ module Workflow
20
+ # Bundles a registered workflow's callable factory with its metadata (schemas +
21
+ # description). Built lazily by WorkflowRegistry#definition — it does NOT resolve
22
+ # the factory (the Executor resolves inside the fiber; the contract forbids
23
+ # instantiating outside it). Schema validation touches only the schemas.
24
+ Definition = Data.define(:name, :description, :input_schema, :output_schema, :factory) do
25
+ # Raises WorkflowSchemaError (< ValidationError) when the input does not
26
+ # conform. No-op without an input_schema (parity). Called synchronously by
27
+ # TriggerWorkflow -> a bad input is a 422 with no run created.
28
+ def validate_input!(input) = enforce!(input_schema, input, :input)
29
+
30
+ # Raises WorkflowSchemaError when the RETURN does not conform. No-op without an
31
+ # output_schema. Called inside the fiber after the workflow returns -> a bad
32
+ # output fails the run at the :workflow_schema stage.
33
+ def validate_output!(output) = enforce!(output_schema, output, :output)
34
+
35
+ # Resolves the factory (INSIDE the fiber) and invokes the orchestrator with the
36
+ # canonical signature `#call(input, context:, tools:)`.
37
+ def call(input, context:, tools:)
38
+ factory.call.call(input, context: context, tools: tools)
39
+ end
40
+
41
+ # Discovery view (GET /v1/workflows): name + description + the I/O contract.
42
+ # A JSON-Schema-backed schema exposes its schema Hash; a duck-typed validator
43
+ # (dry-schema etc.) is opaque to introspection -> "opaque".
44
+ def catalog_entry
45
+ {
46
+ "name" => name,
47
+ "description" => description,
48
+ "input_schema" => schema_view(input_schema),
49
+ "output_schema" => schema_view(output_schema)
50
+ }
51
+ end
52
+
53
+ private
54
+
55
+ def enforce!(schema, value, phase)
56
+ return if schema.nil?
57
+
58
+ result = schema.call(value)
59
+ return if result.success?
60
+
61
+ raise Insika::WorkflowSchemaError.new(
62
+ "workflow '#{name}' #{phase}", phase: phase, errors: normalize_errors(result.errors)
63
+ )
64
+ end
65
+
66
+ # dry-schema returns a MessageSet (responds to #to_h); the built-in Schema
67
+ # already returns a Hash.
68
+ def normalize_errors(errors) = errors.respond_to?(:to_h) ? errors.to_h : errors
69
+
70
+ def schema_view(schema)
71
+ return nil if schema.nil?
72
+
73
+ schema.respond_to?(:json_schema) ? schema.json_schema : "opaque"
74
+ end
75
+ end
76
+
77
+ # Zero-dependency instance validator for a plain JSON Schema Hash, speaking the
78
+ # same safe subset (object/array/string/number/integer/boolean + enum) the
79
+ # ToolDefinition validates its parameters against. It implements the SAME
80
+ # `#call(value) -> result{#success?, #errors}` contract as dry-schema, so the
81
+ # Definition treats both uniformly. Not a full JSON Schema engine (no
82
+ # composition/$ref — the subset the insika supports everywhere); permissive on
83
+ # unknown keys (JSON Schema's additionalProperties default).
84
+ class Schema
85
+ # dry-schema-compatible result. `errors` is { "field.path" => ["message", …] }.
86
+ Result = Data.define(:errors) do
87
+ def success? = errors.empty?
88
+ end
89
+
90
+ # nil -> nil; a callable (dry-schema / proc) -> as-is; a JSON Schema Hash ->
91
+ # wrapped. Idempotent for an existing Schema (it is callable).
92
+ def self.coerce(schema)
93
+ return nil if schema.nil?
94
+ return schema if schema.respond_to?(:call)
95
+
96
+ new(schema)
97
+ end
98
+
99
+ attr_reader :json_schema
100
+
101
+ def initialize(json_schema)
102
+ unless json_schema.is_a?(Hash)
103
+ raise Insika::ValidationError, "workflow schema must be a JSON Schema object or a #call-able validator"
104
+ end
105
+
106
+ @json_schema = Insika::Coercion.deep_stringify(json_schema)
107
+ end
108
+
109
+ def call(value)
110
+ Result.new(errors: collect(@json_schema, value, "").freeze)
111
+ end
112
+
113
+ private
114
+
115
+ # -> { path => [messages] }. Empty = valid.
116
+ def collect(schema, value, path)
117
+ type = schema["type"].to_s
118
+ return { key(path) => ["must be #{type}, got #{ruby_type(value)}"] } unless type.empty? || matches?(type, value)
119
+
120
+ errors = {}
121
+ case type
122
+ when "object" then check_object(schema, value, path, errors)
123
+ when "array" then check_array(schema, value, path, errors)
124
+ end
125
+ check_enum(schema, value, path, errors)
126
+ errors
127
+ end
128
+
129
+ def check_object(schema, value, path, errors)
130
+ props = schema["properties"] || {}
131
+ Array(schema["required"]).each do |name|
132
+ errors[key(join(path, name))] = ["is required"] unless value.key?(name.to_s) || value.key?(name.to_sym)
133
+ end
134
+ props.each do |name, subschema|
135
+ next unless value.key?(name.to_s) || value.key?(name.to_sym)
136
+
137
+ sub = value[name.to_s] || value[name.to_sym]
138
+ errors.merge!(collect(subschema || {}, sub, join(path, name)))
139
+ end
140
+ end
141
+
142
+ def check_array(schema, value, path, errors)
143
+ items = schema["items"]
144
+ return if items.nil?
145
+
146
+ value.each_with_index { |el, i| errors.merge!(collect(items, el, "#{join(path, i)}")) }
147
+ end
148
+
149
+ def check_enum(schema, value, path, errors)
150
+ return unless schema.key?("enum")
151
+
152
+ allowed = Array(schema["enum"])
153
+ errors[key(path)] = ["must be one of #{allowed.inspect}"] unless allowed.include?(value)
154
+ end
155
+
156
+ def matches?(type, value)
157
+ case type
158
+ when "object" then value.is_a?(Hash)
159
+ when "array" then value.is_a?(Array)
160
+ when "string" then value.is_a?(String)
161
+ when "integer" then value.is_a?(Integer) && !value.is_a?(TrueClass) && !value.is_a?(FalseClass)
162
+ when "number" then value.is_a?(Numeric) && !value.is_a?(TrueClass) && !value.is_a?(FalseClass)
163
+ when "boolean" then value == true || value == false
164
+ else true # unknown type in the schema -> do not block (permissive)
165
+ end
166
+ end
167
+
168
+ def ruby_type(value)
169
+ case value
170
+ when Hash then "object"
171
+ when Array then "array"
172
+ when String then "string"
173
+ when Integer then "integer"
174
+ when Numeric then "number"
175
+ when true, false then "boolean"
176
+ when nil then "null"
177
+ else value.class.name.downcase
178
+ end
179
+ end
180
+
181
+ def join(path, segment) = path.empty? ? segment.to_s : "#{path}.#{segment}"
182
+ def key(path) = path.empty? ? "(root)" : path
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Insika
4
+ # Workflow registry. A workflow is a Ruby callable with the signature
5
+ # `#call(input, context:, tools:)` that orchestrates RubyLLM Agents/Workflows FROM
6
+ # WITHIN (RubyLLM First): `context:` is the ContextPackage, `tools:` are
7
+ # instances already filtered by the Resolution. Execution = one logical turn;
8
+ # checkpoint at the end. Nothing is validated at registration (the callable may come
9
+ # via a factory block). Consumed by the TriggerWorkflow handler.
10
+ #
11
+ # Item 22 / §4.4 — the EXPOSED surface: a registration may carry `input_schema:` /
12
+ # `output_schema:` (a JSON Schema Hash or any dry-schema-compatible validator) and a
13
+ # `description:` in its metadata. `definition` bundles them with the factory into a
14
+ # Workflow::Definition (schemas resolved, factory left lazy); `catalog` is the
15
+ # discovery view (GET /v1/workflows).
16
+ class WorkflowRegistry < Registry
17
+ # -> Workflow::Definition (does NOT resolve the factory — the Executor resolves
18
+ # inside the fiber). Raises NotFoundError for an unregistered name.
19
+ def definition(name)
20
+ e = entry(name)
21
+ Insika::Workflow::Definition.new(
22
+ name: e.name,
23
+ description: e.metadata[:description],
24
+ input_schema: Insika::Workflow::Schema.coerce(e.metadata[:input_schema]),
25
+ output_schema: Insika::Workflow::Schema.coerce(e.metadata[:output_schema]),
26
+ factory: e.factory
27
+ )
28
+ end
29
+
30
+ # Discovery: [{ "name", "description", "input_schema", "output_schema" }, …].
31
+ def catalog = entries.map { |e| definition(e.name).catalog_entry }
32
+ end
33
+ end
data/lib/insika.rb CHANGED
@@ -1,7 +1,206 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "insika/version"
4
-
5
- # Insika — name reserved. Project under active development.
6
- module Insika
7
- end
4
+ require_relative "insika/errors"
5
+ require_relative "insika/coercion"
6
+ require_relative "insika/message_origin"
7
+ require_relative "insika/env_schema"
8
+ require_relative "insika/allowlist"
9
+ require_relative "insika/event"
10
+ require_relative "insika/agent_profile"
11
+ require_relative "insika/subagent_graph"
12
+ require_relative "insika/model_policy"
13
+ require_relative "insika/model_selection"
14
+ require_relative "insika/model_resolver"
15
+ require_relative "insika/tool_definition"
16
+ require_relative "insika/tool_manifest"
17
+ require_relative "insika/frontmatter"
18
+ require_relative "insika/token_estimator"
19
+ require_relative "insika/checkpoint"
20
+ require_relative "insika/command"
21
+ require_relative "insika/hooks"
22
+ require_relative "insika/middleware"
23
+ # Production edge (item 33 / §12 G7): windowed counters + the rate-limit/cost
24
+ # Middleware. Both inert until configured (nil/0 = off).
25
+ require_relative "insika/usage_ledger"
26
+ require_relative "insika/edge_limiter"
27
+ # Content safety / guardrails (RFC-0009). detectors.rb is self-contained (the eval
28
+ # requires it directly, D4); the rest hang off Middleware/hooks seams. No ruby_llm
29
+ # at load-time — Factory requires the gem lazily, like the Executor's create_chat.
30
+ require_relative "insika/safety/detectors"
31
+ require_relative "insika/safety/safe_responses"
32
+ require_relative "insika/safety/config"
33
+ require_relative "insika/safety/moderator"
34
+ require_relative "insika/safety/output_filter"
35
+ require_relative "insika/safety/input_guardrail"
36
+ require_relative "insika/safety/output_validator"
37
+ require_relative "insika/safety/factory"
38
+ require_relative "insika/context/fragment"
39
+ require_relative "insika/context/priority"
40
+ require_relative "insika/context/provider"
41
+ require_relative "insika/context/catalog_provider"
42
+ require_relative "insika/context/builder"
43
+ require_relative "insika/context/providers/request"
44
+ require_relative "insika/context/providers/prompt"
45
+ require_relative "insika/context/providers/skill"
46
+ require_relative "insika/context/providers/tool_search"
47
+ require_relative "insika/context/providers/memory"
48
+ require_relative "insika/context/providers/session"
49
+ require_relative "insika/policy/policy"
50
+ require_relative "insika/policy/engine"
51
+ require_relative "insika/registry"
52
+ require_relative "insika/tool_registry"
53
+ require_relative "insika/workflow"
54
+ require_relative "insika/workflow_registry"
55
+ require_relative "insika/policy_registry"
56
+ require_relative "insika/capability_registry"
57
+ require_relative "insika/prompt_catalog"
58
+ require_relative "insika/plugin"
59
+ require_relative "insika/plugin/loader"
60
+ require_relative "insika/store"
61
+ require_relative "insika/stores/memory"
62
+ require_relative "insika/stores/sqlite"
63
+ require_relative "insika/session_store"
64
+ require_relative "insika/task_store"
65
+ require_relative "insika/checkpoint_store"
66
+ require_relative "insika/pending_action_store"
67
+ require_relative "insika/delegation_store"
68
+ # Channels (RFC-0011): the outbound record + the inbound retry window. Both are
69
+ # plain stores; the channel objects themselves come after the HTTP client.
70
+ require_relative "insika/outbox_store"
71
+ require_relative "insika/inbound_log"
72
+ require_relative "insika/memory_store"
73
+ require_relative "insika/config_store"
74
+ require_relative "insika/profile_source"
75
+ require_relative "insika/agent_file_store"
76
+ require_relative "insika/skill_store"
77
+ require_relative "insika/secret_masking"
78
+ require_relative "insika/tool_store"
79
+ require_relative "insika/tool_trace_store"
80
+ # Refinement (RFC-0013 phase A): the run record + the evidence half of the loop.
81
+ # Reads sessions/tasks/traces above; requires Safety::Detectors (loaded earlier) for
82
+ # the PII redaction of the snippets it puts in a report.
83
+ require_relative "insika/refinement_store"
84
+ require_relative "insika/refinement/evidence_collector"
85
+ # The candidate format is pure data + validation, so it loads with the collector;
86
+ # the GATE needs the evals module and the stores, so it waits for them below.
87
+ require_relative "insika/refinement/candidate"
88
+ # The proposer only needs the candidate format and an injected `ask` — the provider
89
+ # gem is required lazily, inside the factory, so requiring Insika still loads nothing.
90
+ require_relative "insika/refinement/proposer"
91
+ require_relative "insika/egress_guard"
92
+ require_relative "insika/schema_guard"
93
+ require_relative "insika/sandbox"
94
+ require_relative "insika/http_client"
95
+ # Channels (RFC-0011 §4/§6): the registry, the bundled relay adapter and the
96
+ # out-of-band dispatcher. After http_client and egress_guard — the relay POSTs
97
+ # through both — and after registry.rb, which ChannelRegistry extends.
98
+ require_relative "insika/channel_registry"
99
+ require_relative "insika/channels/relay"
100
+ require_relative "insika/channels/web"
101
+ require_relative "insika/channel_delivery"
102
+ require_relative "insika/overlay_tool_registry"
103
+ require_relative "insika/settings_store"
104
+ require_relative "insika/llm_provider_store"
105
+ require_relative "insika/llm_configurator"
106
+ # LLM-first onboarding surface (item 20 / §5.6): serves start.md + models.json + the
107
+ # public docs. Reads the settings/provider stores above at call-time (order is free).
108
+ require_relative "insika/onboarding"
109
+ # Evals (RFC-0008) — the quality harness, moved under lib/ so the engine can call it
110
+ # (the RFC-0013 refinement gate scores a candidate agent with the SAME judge the CLI
111
+ # uses; a second copy would be the worst outcome). It stays a CLIENT of the engine:
112
+ # HttpTransport talks to a running deployment, nothing here reads a store. Pure Ruby +
113
+ # stdlib; the judge's provider call is injected, so no ruby_llm at load time.
114
+ require_relative "insika/evals/golden"
115
+ require_relative "insika/evals/assertions"
116
+ require_relative "insika/evals/judge"
117
+ require_relative "insika/evals/pairwise"
118
+ require_relative "insika/evals/runner"
119
+ require_relative "insika/evals/report"
120
+ require_relative "insika/evals/baseline"
121
+ require_relative "insika/evals/transport"
122
+ # Authored eval cases (RFC-0013 §3.7): the corpus becomes editable without a
123
+ # checkout. Requires the loader above (it is the one validator).
124
+ require_relative "insika/golden_store"
125
+ require_relative "insika/baseline_store"
126
+ # RFC-0013 §3.5: scores a candidate by REPLAYING it. After evals (the runner and
127
+ # the baseline comparison) and after the stores it clones an agent through.
128
+ require_relative "insika/refinement/gate"
129
+ # RFC-0013 §3.9 (phase D): the proposer PANEL and the run's token budget. Needs the
130
+ # candidate format and the gate's Report shape, so it loads after both.
131
+ require_relative "insika/refinement/panel"
132
+ require_relative "insika/mcp_store"
133
+ require_relative "insika/mcp_http_client"
134
+ require_relative "insika/mcp_tool_ingestor"
135
+ require_relative "insika/system_file_store"
136
+ require_relative "insika/recovery"
137
+ require_relative "insika/command_bus"
138
+ require_relative "insika/commands/create_session"
139
+ require_relative "insika/commands/cancel_task"
140
+ require_relative "insika/commands/pause_task"
141
+ require_relative "insika/commands/approve_action"
142
+ require_relative "insika/commands/send_message"
143
+ require_relative "insika/commands/resume_task"
144
+ require_relative "insika/commands/trigger_workflow"
145
+ require_relative "insika/commands/agent_payload"
146
+ require_relative "insika/commands/create_agent"
147
+ require_relative "insika/commands/update_agent"
148
+ require_relative "insika/commands/delete_agent"
149
+ require_relative "insika/commands/set_agent_tools"
150
+ require_relative "insika/commands/write_agent_file"
151
+ require_relative "insika/commands/delete_agent_file"
152
+ require_relative "insika/commands/restore_agent_file"
153
+ require_relative "insika/commands/write_skill"
154
+ require_relative "insika/commands/set_skill_agents"
155
+ require_relative "insika/commands/memory_put_fact"
156
+ require_relative "insika/commands/memory_forget_fact"
157
+ require_relative "insika/commands/memory_add_note"
158
+ require_relative "insika/commands/run_refinement"
159
+ require_relative "insika/commands/gate_refinement"
160
+ require_relative "insika/commands/resolve_refinement"
161
+ require_relative "insika/commands/write_golden"
162
+ require_relative "insika/commands/update_settings"
163
+ require_relative "insika/commands/upsert_llm_provider"
164
+ require_relative "insika/commands/delete_llm_provider"
165
+ require_relative "insika/commands/upsert_mcp"
166
+ require_relative "insika/commands/delete_mcp"
167
+ require_relative "insika/commands/write_system_file"
168
+ require_relative "insika/commands/delete_system_file"
169
+ require_relative "insika/commands/restore_system_file"
170
+ require_relative "insika/commands/write_data_tool"
171
+ require_relative "insika/commands/delete_data_tool"
172
+ require_relative "insika/commands/restore_data_tool"
173
+ require_relative "insika/commands/import_tools"
174
+ require_relative "insika/commands/import_mcp_tools"
175
+ require_relative "insika/event_stream"
176
+ require_relative "insika/task_actor"
177
+ require_relative "insika/queue_policy"
178
+ require_relative "insika/session_actor"
179
+ require_relative "insika/skill_catalog"
180
+ require_relative "insika/tool_catalog"
181
+ require_relative "insika/steer_injector"
182
+ require_relative "insika/turn_output"
183
+ require_relative "insika/turn_state"
184
+ require_relative "insika/turn_timing"
185
+ require_relative "insika/capability/resolved_tool"
186
+ require_relative "insika/tool_envelope"
187
+ require_relative "insika/tool_assembly"
188
+ require_relative "insika/chat_builder"
189
+ require_relative "insika/executor"
190
+ require_relative "insika/shutdown"
191
+ require_relative "insika/pack"
192
+ require_relative "insika/pack_importer"
193
+ require_relative "insika/telemetry"
194
+ # Strict config + diagnosis (item 23 / §8.1). Doctor reads the config stores above;
195
+ # EnvSchema (required at the top) is its env layer.
196
+ require_relative "insika/doctor"
197
+ # Shared composition core for both roots (config/wiring.rb + config/deployment.rb).
198
+ # Only references the classes above at call-time, so require order is unconstrained.
199
+ require_relative "insika/wiring/graph"
200
+ # Public Ruby DSL (item 36): Insika.agent { … }. The Builder is gem-free (it only
201
+ # generates a Pack); the runtime (chat/serve) is required lazily by Definition, so
202
+ # `require "insika"` stays free of ruby_llm and the HTTP server.
203
+ require_relative "insika/dsl"
204
+ # Do NOT require "insika/tools/load_skill" here: it does `require "ruby_llm"` at
205
+ # the top (inherits from RubyLLM::Tool) and would pull the gem in at load-time. The
206
+ # Executor loads it lazily inside create_chat (D9).