insika 0.9.0 → 1.0.1

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 (257) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +237 -2
  3. data/README.md +5 -3
  4. data/bin/insika +3 -0
  5. data/bin/insika-router +0 -1
  6. data/docs/AGENTS.md +90 -7
  7. data/docs/ARCHITECTURE.md +12 -7
  8. data/docs/ARTIFACTS.md +33 -3
  9. data/docs/BENCHMARK.md +50 -7
  10. data/docs/CONTEXT.md +63 -0
  11. data/docs/CROSS-HARNESS-BENCH.md +157 -0
  12. data/docs/DEPLOY.md +57 -11
  13. data/docs/EMBEDDING.md +10 -0
  14. data/docs/EVALS.md +33 -4
  15. data/docs/FACTS.md +8 -6
  16. data/docs/HARVEST.md +8 -3
  17. data/docs/KNOWLEDGE.md +7 -0
  18. data/docs/MEDIA.md +6 -2
  19. data/docs/OBSERVABILITY.md +143 -22
  20. data/docs/PERFORMANCE.md +110 -0
  21. data/docs/PLUGINS.md +4 -4
  22. data/docs/POLICY.md +22 -13
  23. data/docs/RELEASING.md +5 -0
  24. data/docs/ROUTER.md +7 -0
  25. data/docs/RUBYLLM_2_MIGRATION.md +307 -0
  26. data/docs/SECURITY.md +7 -0
  27. data/docs/SHARED-CONVERSATIONS.md +40 -0
  28. data/docs/SKILLS.md +5 -3
  29. data/docs/STUDIO.md +122 -0
  30. data/docs/TOOLS.md +111 -9
  31. data/docs/operate.md +3 -0
  32. data/lib/insika/agent_defaults.rb +140 -0
  33. data/lib/insika/agent_file_store.rb +12 -0
  34. data/lib/insika/agent_profile.rb +78 -8
  35. data/lib/insika/artifact_signing.rb +11 -0
  36. data/lib/insika/chat_builder.rb +79 -25
  37. data/lib/insika/checkpoint.rb +6 -1
  38. data/lib/insika/checkpoint_store.rb +59 -7
  39. data/lib/insika/commands/agent_payload.rb +3 -3
  40. data/lib/insika/commands/delete_kit.rb +26 -0
  41. data/lib/insika/commands/gate_harvest.rb +3 -0
  42. data/lib/insika/commands/review_guardrail_flag.rb +38 -0
  43. data/lib/insika/commands/run_harvest.rb +17 -1
  44. data/lib/insika/commands/seed_session.rb +11 -1
  45. data/lib/insika/commands/send_message.rb +9 -3
  46. data/lib/insika/commands/update_settings.rb +23 -1
  47. data/lib/insika/commands/write_kit.rb +27 -0
  48. data/lib/insika/compaction.rb +33 -7
  49. data/lib/insika/config_store.rb +87 -7
  50. data/lib/insika/context/priority.rb +3 -0
  51. data/lib/insika/context/provider.rb +2 -2
  52. data/lib/insika/context/providers/knowledge.rb +25 -2
  53. data/lib/insika/context/providers/memory.rb +53 -4
  54. data/lib/insika/context/providers/pending_confirmation.rb +52 -0
  55. data/lib/insika/context/providers/prompt.rb +17 -4
  56. data/lib/insika/context/providers/session.rb +39 -3
  57. data/lib/insika/context/reranker.rb +75 -0
  58. data/lib/insika/distill.rb +22 -13
  59. data/lib/insika/doctor.rb +34 -4
  60. data/lib/insika/dsl/runtime.rb +36 -4
  61. data/lib/insika/dsl/server_boot.rb +4 -12
  62. data/lib/insika/dsl.rb +13 -5
  63. data/lib/insika/edge_limiter.rb +23 -15
  64. data/lib/insika/egress_guard.rb +11 -3
  65. data/lib/insika/env_schema.rb +33 -73
  66. data/lib/insika/evals/assertions.rb +171 -16
  67. data/lib/insika/evals/golden.rb +141 -4
  68. data/lib/insika/evals/judge.rb +19 -10
  69. data/lib/insika/evals/moderator_compare.rb +47 -0
  70. data/lib/insika/evals/report.rb +61 -9
  71. data/lib/insika/evals/runner.rb +44 -4
  72. data/lib/insika/evals/simulator.rb +10 -1
  73. data/lib/insika/evals/transport.rb +200 -0
  74. data/lib/insika/event_stream.rb +63 -7
  75. data/lib/insika/evidence.rb +29 -8
  76. data/lib/insika/executor.rb +668 -141
  77. data/lib/insika/harvest.rb +26 -14
  78. data/lib/insika/harvest_engine.rb +1 -0
  79. data/lib/insika/harvest_store.rb +12 -0
  80. data/lib/insika/http_client.rb +87 -4
  81. data/lib/insika/kits.rb +54 -0
  82. data/lib/insika/knowledge.rb +34 -20
  83. data/lib/insika/llm_configurator.rb +46 -4
  84. data/lib/insika/llm_provider_store.rb +1 -3
  85. data/lib/insika/llm_trace_store.rb +54 -0
  86. data/lib/insika/mcp_client.rb +27 -63
  87. data/lib/insika/mcp_live_tool.rb +55 -9
  88. data/lib/insika/mcp_store.rb +32 -1
  89. data/lib/insika/mcp_tool_registry.rb +69 -26
  90. data/lib/insika/media.rb +38 -25
  91. data/lib/insika/memory_store.rb +4 -3
  92. data/lib/insika/memory_trim.rb +60 -0
  93. data/lib/insika/middleware.rb +12 -3
  94. data/lib/insika/model_metrics_store.rb +285 -0
  95. data/lib/insika/model_registry.rb +110 -0
  96. data/lib/insika/model_resolver.rb +1 -1
  97. data/lib/insika/model_selection.rb +14 -21
  98. data/lib/insika/model_visible.rb +17 -6
  99. data/lib/insika/onboarding.rb +1 -0
  100. data/lib/insika/outcome_store.rb +1 -1
  101. data/lib/insika/overlay_tool_registry.rb +25 -2
  102. data/lib/insika/pack_importer.rb +54 -9
  103. data/lib/insika/packaging.rb +14 -5
  104. data/lib/insika/pending_action_store.rb +45 -18
  105. data/lib/insika/plugin/loader.rb +4 -2
  106. data/lib/insika/profile_source.rb +4 -0
  107. data/lib/insika/provider_error_classifier.rb +18 -3
  108. data/lib/insika/queue_policy.rb +7 -2
  109. data/lib/insika/refinement/proposer.rb +42 -17
  110. data/lib/insika/reliability.rb +12 -3
  111. data/lib/insika/router/app.rb +14 -5
  112. data/lib/insika/router/session_key.rb +35 -5
  113. data/lib/insika/safety/config.rb +20 -3
  114. data/lib/insika/safety/corpus.rb +10 -3
  115. data/lib/insika/safety/factory.rb +39 -1
  116. data/lib/insika/safety/input_guardrail.rb +21 -1
  117. data/lib/insika/safety/judge_moderator.rb +70 -0
  118. data/lib/insika/safety/output_validator.rb +29 -5
  119. data/lib/insika/safety/prompt_echo.rb +89 -0
  120. data/lib/insika/schema_guard.rb +53 -76
  121. data/lib/insika/server/app.rb +17 -8
  122. data/lib/insika/server/responses.rb +19 -1
  123. data/lib/insika/session_actor.rb +58 -28
  124. data/lib/insika/session_store.rb +159 -10
  125. data/lib/insika/settings_store.rb +47 -1
  126. data/lib/insika/shared_conversations.rb +305 -0
  127. data/lib/insika/skill_catalog.rb +28 -2
  128. data/lib/insika/skill_store.rb +6 -0
  129. data/lib/insika/soak/runner.rb +1 -1
  130. data/lib/insika/steer_injector.rb +7 -48
  131. data/lib/insika/store.rb +29 -1
  132. data/lib/insika/stores/json_value.rb +37 -0
  133. data/lib/insika/stores/memory.rb +22 -35
  134. data/lib/insika/stores/postgres.rb +295 -0
  135. data/lib/insika/stores/sqlite.rb +257 -43
  136. data/lib/insika/stores/turn_counter.rb +25 -0
  137. data/lib/insika/studio/app.rb +1453 -161
  138. data/lib/insika/studio/assets/dist/application.css +1 -1
  139. data/lib/insika/studio/assets/dist/application.js +25 -25
  140. data/lib/insika/studio/assets/dist/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
  141. data/lib/insika/studio/assets/dist/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
  142. data/lib/insika/studio/assets/dist/fonts/ibm-plex-mono-latin-600-normal.woff2 +0 -0
  143. data/lib/insika/studio/assets/dist/fonts/ibm-plex-sans-latin-wght-normal.woff2 +0 -0
  144. data/lib/insika/studio/forms.rb +171 -9
  145. data/lib/insika/studio/nav_icons.rb +3 -0
  146. data/lib/insika/studio/views/_agent_config_retrieval.erb +73 -0
  147. data/lib/insika/studio/views/_agent_picker.erb +15 -0
  148. data/lib/insika/studio/views/_agent_tab_config.erb +78 -242
  149. data/lib/insika/studio/views/_agent_tab_history.erb +56 -1
  150. data/lib/insika/studio/views/_agent_tab_performance.erb +34 -0
  151. data/lib/insika/studio/views/_agent_tab_prompts.erb +7 -9
  152. data/lib/insika/studio/views/_agent_tab_skills.erb +16 -7
  153. data/lib/insika/studio/views/_agent_tab_tools.erb +90 -0
  154. data/lib/insika/studio/views/_agents_master.erb +8 -12
  155. data/lib/insika/studio/views/_cfg_alerts.erb +4 -0
  156. data/lib/insika/studio/views/_cfg_budget.erb +20 -0
  157. data/lib/insika/studio/views/_cfg_distill.erb +26 -0
  158. data/lib/insika/studio/views/_cfg_followup.erb +30 -0
  159. data/lib/insika/studio/views/_cfg_grounding.erb +21 -0
  160. data/lib/insika/studio/views/_cfg_guardrails.erb +47 -0
  161. data/lib/insika/studio/views/_cfg_harvest.erb +35 -0
  162. data/lib/insika/studio/views/_cfg_reliability.erb +32 -0
  163. data/lib/insika/studio/views/_chats_master.erb +66 -0
  164. data/lib/insika/studio/views/_customers_master.erb +37 -0
  165. data/lib/insika/studio/views/_empty.erb +15 -0
  166. data/lib/insika/studio/views/_facts_master.erb +42 -0
  167. data/lib/insika/studio/views/_harvest_candidate_detail.erb +14 -0
  168. data/lib/insika/studio/views/_identity.erb +16 -0
  169. data/lib/insika/studio/views/_kpi.erb +17 -0
  170. data/lib/insika/studio/views/_message.erb +40 -2
  171. data/lib/insika/studio/views/_model_chart.erb +82 -0
  172. data/lib/insika/studio/views/_refinement_master.erb +38 -0
  173. data/lib/insika/studio/views/{tool_edit.erb → _tool_edit.erb} +32 -9
  174. data/lib/insika/studio/views/_tool_users.erb +17 -0
  175. data/lib/insika/studio/views/_why.erb +53 -0
  176. data/lib/insika/studio/views/agent_detail.erb +17 -10
  177. data/lib/insika/studio/views/agents.erb +28 -16
  178. data/lib/insika/studio/views/approvals.erb +16 -11
  179. data/lib/insika/studio/views/artifact.erb +20 -7
  180. data/lib/insika/studio/views/artifacts.erb +19 -14
  181. data/lib/insika/studio/views/chats.erb +22 -29
  182. data/lib/insika/studio/views/customer.erb +88 -43
  183. data/lib/insika/studio/views/customers.erb +16 -26
  184. data/lib/insika/studio/views/evals.erb +49 -31
  185. data/lib/insika/studio/views/fact_detail.erb +114 -0
  186. data/lib/insika/studio/views/facts.erb +15 -116
  187. data/lib/insika/studio/views/followups.erb +63 -52
  188. data/lib/insika/studio/views/funnel.erb +104 -43
  189. data/lib/insika/studio/views/harvest.erb +85 -59
  190. data/lib/insika/studio/views/home.erb +138 -23
  191. data/lib/insika/studio/views/inbox.erb +36 -0
  192. data/lib/insika/studio/views/kits.erb +176 -0
  193. data/lib/insika/studio/views/knowledge.erb +92 -80
  194. data/lib/insika/studio/views/layout.erb +42 -11
  195. data/lib/insika/studio/views/live.erb +45 -0
  196. data/lib/insika/studio/views/mcp.erb +43 -13
  197. data/lib/insika/studio/views/models.erb +187 -0
  198. data/lib/insika/studio/views/parity.erb +38 -32
  199. data/lib/insika/studio/views/playground.erb +13 -9
  200. data/lib/insika/studio/views/refinement.erb +15 -224
  201. data/lib/insika/studio/views/refinement_detail.erb +243 -0
  202. data/lib/insika/studio/views/session.erb +152 -117
  203. data/lib/insika/studio/views/settings.erb +86 -22
  204. data/lib/insika/studio/views/skills.erb +53 -19
  205. data/lib/insika/studio/views/system_files.erb +7 -7
  206. data/lib/insika/studio/views/task.erb +45 -15
  207. data/lib/insika/studio/views/tasks.erb +35 -18
  208. data/lib/insika/studio/views/tools.erb +62 -73
  209. data/lib/insika/task_actor.rb +4 -1
  210. data/lib/insika/task_store.rb +67 -1
  211. data/lib/insika/telemetry/pricing.rb +16 -14
  212. data/lib/insika/telemetry/recorder.rb +103 -9
  213. data/lib/insika/telemetry/ruby_llm_instrumenter.rb +110 -0
  214. data/lib/insika/telemetry.rb +12 -2
  215. data/lib/insika/templates/daily-digest/README.md +13 -0
  216. data/lib/insika/templates/daily-digest/agent.rb +22 -11
  217. data/lib/insika/testing/store_contract.rb +65 -0
  218. data/lib/insika/text_tool_call.rb +66 -0
  219. data/lib/insika/tick.rb +7 -1
  220. data/lib/insika/token_store.rb +5 -0
  221. data/lib/insika/tool_batch.rb +1 -1
  222. data/lib/insika/tool_catalog.rb +12 -2
  223. data/lib/insika/tool_definition.rb +10 -4
  224. data/lib/insika/tool_envelope.rb +165 -28
  225. data/lib/insika/tool_manifest.rb +1 -0
  226. data/lib/insika/tool_store.rb +3 -0
  227. data/lib/insika/tool_trace_store.rb +15 -8
  228. data/lib/insika/tool_usage_report.rb +2 -2
  229. data/lib/insika/tools/a2a_remote.rb +1 -1
  230. data/lib/insika/tools/agent_enum.rb +1 -1
  231. data/lib/insika/tools/confirm_pending.rb +112 -0
  232. data/lib/insika/tools/data_defined_tool.rb +23 -15
  233. data/lib/insika/tools/generate_image.rb +2 -2
  234. data/lib/insika/tools/load_knowledge.rb +7 -3
  235. data/lib/insika/tools/load_skill.rb +3 -3
  236. data/lib/insika/tools/present.rb +1 -8
  237. data/lib/insika/tools/remember.rb +7 -2
  238. data/lib/insika/tools/run_persona_eval.rb +3 -5
  239. data/lib/insika/tools/save_artifact.rb +16 -6
  240. data/lib/insika/tools/schedule_followup.rb +3 -3
  241. data/lib/insika/tools/stuck_signal.rb +3 -3
  242. data/lib/insika/tools/subagent.rb +5 -5
  243. data/lib/insika/tools/subagents.rb +3 -3
  244. data/lib/insika/tools/tool_search.rb +7 -5
  245. data/lib/insika/tools/tts.rb +2 -2
  246. data/lib/insika/tools/update_briefing.rb +4 -4
  247. data/lib/insika/turn_output.rb +2 -2
  248. data/lib/insika/turn_state.rb +18 -0
  249. data/lib/insika/turn_timing.rb +51 -14
  250. data/lib/insika/version.rb +1 -1
  251. data/lib/insika/wiring/graph.rb +81 -16
  252. data/lib/insika/workflow.rb +25 -64
  253. data/lib/insika.rb +19 -3
  254. metadata +69 -13
  255. data/lib/insika/commands/import_mcp_tools.rb +0 -48
  256. data/lib/insika/mcp_http_client.rb +0 -67
  257. data/lib/insika/mcp_tool_ingestor.rb +0 -165
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: insika
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guilherme Lages Santos
@@ -24,33 +24,33 @@ dependencies:
24
24
  - !ruby/object:Gem::Version
25
25
  version: '2.0'
26
26
  - !ruby/object:Gem::Dependency
27
- name: ruby_llm
27
+ name: json_schemer
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
- - - ">="
30
+ - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: '1.15'
32
+ version: '2.5'
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - ">="
37
+ - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '1.15'
39
+ version: '2.5'
40
40
  - !ruby/object:Gem::Dependency
41
- name: ruby_llm-mcp
41
+ name: ruby_llm
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '1.0'
46
+ version: '2.1'
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '1.0'
53
+ version: '2.1'
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: falcon
56
56
  requirement: !ruby/object:Gem::Requirement
@@ -173,6 +173,7 @@ files:
173
173
  - docs/BENCHMARK.md
174
174
  - docs/CHANNELS.md
175
175
  - docs/CONTEXT.md
176
+ - docs/CROSS-HARNESS-BENCH.md
176
177
  - docs/DEMO.md
177
178
  - docs/DEPLOY.md
178
179
  - docs/EMBEDDING.md
@@ -184,17 +185,21 @@ files:
184
185
  - docs/MEDIA.md
185
186
  - docs/OBSERVABILITY.md
186
187
  - docs/OUTCOMES.md
188
+ - docs/PERFORMANCE.md
187
189
  - docs/PLUGINS.md
188
190
  - docs/POLICY.md
189
191
  - docs/REFINEMENT.md
190
192
  - docs/RELEASING.md
191
193
  - docs/ROUTER.md
194
+ - docs/RUBYLLM_2_MIGRATION.md
192
195
  - docs/RUNNING-LOCAL.md
193
196
  - docs/SANDBOX.md
194
197
  - docs/SCHEDULING.md
195
198
  - docs/SECURITY.md
199
+ - docs/SHARED-CONVERSATIONS.md
196
200
  - docs/SKILLS.md
197
201
  - docs/SOAK.md
202
+ - docs/STUDIO.md
198
203
  - docs/TEMPLATES.md
199
204
  - docs/TOOLS.md
200
205
  - docs/WHY.md
@@ -221,6 +226,7 @@ files:
221
226
  - docs/ship.md
222
227
  - docs/start-here.md
223
228
  - lib/insika.rb
229
+ - lib/insika/agent_defaults.rb
224
230
  - lib/insika/agent_file_store.rb
225
231
  - lib/insika/agent_profile.rb
226
232
  - lib/insika/alert_dispatcher.rb
@@ -258,6 +264,7 @@ files:
258
264
  - lib/insika/commands/delete_artifact.rb
259
265
  - lib/insika/commands/delete_concept.rb
260
266
  - lib/insika/commands/delete_data_tool.rb
267
+ - lib/insika/commands/delete_kit.rb
261
268
  - lib/insika/commands/delete_llm_provider.rb
262
269
  - lib/insika/commands/delete_mcp.rb
263
270
  - lib/insika/commands/delete_skill.rb
@@ -268,7 +275,6 @@ files:
268
275
  - lib/insika/commands/freeze_funnel_baseline.rb
269
276
  - lib/insika/commands/gate_harvest.rb
270
277
  - lib/insika/commands/gate_refinement.rb
271
- - lib/insika/commands/import_mcp_tools.rb
272
278
  - lib/insika/commands/import_tools.rb
273
279
  - lib/insika/commands/issue_tenant_token.rb
274
280
  - lib/insika/commands/judge_shadow_pairs.rb
@@ -288,6 +294,7 @@ files:
288
294
  - lib/insika/commands/restore_data_tool.rb
289
295
  - lib/insika/commands/restore_system_file.rb
290
296
  - lib/insika/commands/resume_task.rb
297
+ - lib/insika/commands/review_guardrail_flag.rb
291
298
  - lib/insika/commands/revoke_contact.rb
292
299
  - lib/insika/commands/revoke_token.rb
293
300
  - lib/insika/commands/rollback_harvest.rb
@@ -310,6 +317,7 @@ files:
310
317
  - lib/insika/commands/write_concept.rb
311
318
  - lib/insika/commands/write_data_tool.rb
312
319
  - lib/insika/commands/write_golden.rb
320
+ - lib/insika/commands/write_kit.rb
313
321
  - lib/insika/commands/write_skill.rb
314
322
  - lib/insika/commands/write_system_file.rb
315
323
  - lib/insika/compaction.rb
@@ -324,12 +332,14 @@ files:
324
332
  - lib/insika/context/providers/fence_notice.rb
325
333
  - lib/insika/context/providers/knowledge.rb
326
334
  - lib/insika/context/providers/memory.rb
335
+ - lib/insika/context/providers/pending_confirmation.rb
327
336
  - lib/insika/context/providers/prompt.rb
328
337
  - lib/insika/context/providers/request.rb
329
338
  - lib/insika/context/providers/session.rb
330
339
  - lib/insika/context/providers/skill.rb
331
340
  - lib/insika/context/providers/skill_trigger.rb
332
341
  - lib/insika/context/providers/tool_search.rb
342
+ - lib/insika/context/reranker.rb
333
343
  - lib/insika/context_trace_store.rb
334
344
  - lib/insika/cron.rb
335
345
  - lib/insika/delegation_store.rb
@@ -353,6 +363,7 @@ files:
353
363
  - lib/insika/evals/baseline.rb
354
364
  - lib/insika/evals/golden.rb
355
365
  - lib/insika/evals/judge.rb
366
+ - lib/insika/evals/moderator_compare.rb
356
367
  - lib/insika/evals/pairwise.rb
357
368
  - lib/insika/evals/persona.rb
358
369
  - lib/insika/evals/report.rb
@@ -384,24 +395,27 @@ files:
384
395
  - lib/insika/hooks.rb
385
396
  - lib/insika/http_client.rb
386
397
  - lib/insika/inbound_log.rb
398
+ - lib/insika/kits.rb
387
399
  - lib/insika/knowledge.rb
388
400
  - lib/insika/knowledge_store.rb
389
401
  - lib/insika/llm_configurator.rb
390
402
  - lib/insika/llm_provider_store.rb
403
+ - lib/insika/llm_trace_store.rb
391
404
  - lib/insika/loop_detector.rb
392
405
  - lib/insika/mcp_client.rb
393
- - lib/insika/mcp_http_client.rb
394
406
  - lib/insika/mcp_json.rb
395
407
  - lib/insika/mcp_live_tool.rb
396
408
  - lib/insika/mcp_store.rb
397
- - lib/insika/mcp_tool_ingestor.rb
398
409
  - lib/insika/mcp_tool_registry.rb
399
410
  - lib/insika/media.rb
400
411
  - lib/insika/memory_audit_store.rb
401
412
  - lib/insika/memory_store.rb
413
+ - lib/insika/memory_trim.rb
402
414
  - lib/insika/message_origin.rb
403
415
  - lib/insika/middleware.rb
416
+ - lib/insika/model_metrics_store.rb
404
417
  - lib/insika/model_policy.rb
418
+ - lib/insika/model_registry.rb
405
419
  - lib/insika/model_resolver.rb
406
420
  - lib/insika/model_selection.rb
407
421
  - lib/insika/model_visible.rb
@@ -451,9 +465,11 @@ files:
451
465
  - lib/insika/safety/grounding_enforcer.rb
452
466
  - lib/insika/safety/grounding_validator.rb
453
467
  - lib/insika/safety/input_guardrail.rb
468
+ - lib/insika/safety/judge_moderator.rb
454
469
  - lib/insika/safety/moderator.rb
455
470
  - lib/insika/safety/output_filter.rb
456
471
  - lib/insika/safety/output_validator.rb
472
+ - lib/insika/safety/prompt_echo.rb
457
473
  - lib/insika/safety/safe_responses.rb
458
474
  - lib/insika/sandbox.rb
459
475
  - lib/insika/sandbox/boundary.rb
@@ -484,6 +500,7 @@ files:
484
500
  - lib/insika/session_store.rb
485
501
  - lib/insika/settings_store.rb
486
502
  - lib/insika/shadow_pair_store.rb
503
+ - lib/insika/shared_conversations.rb
487
504
  - lib/insika/shutdown.rb
488
505
  - lib/insika/skill_catalog.rb
489
506
  - lib/insika/skill_store.rb
@@ -493,24 +510,55 @@ files:
493
510
  - lib/insika/spoken_transcript.rb
494
511
  - lib/insika/steer_injector.rb
495
512
  - lib/insika/store.rb
513
+ - lib/insika/stores/json_value.rb
496
514
  - lib/insika/stores/memory.rb
515
+ - lib/insika/stores/postgres.rb
497
516
  - lib/insika/stores/sqlite.rb
517
+ - lib/insika/stores/turn_counter.rb
498
518
  - lib/insika/studio/app.rb
499
519
  - lib/insika/studio/assets/dist/application.css
500
520
  - lib/insika/studio/assets/dist/application.js
501
521
  - lib/insika/studio/assets/dist/favicon.svg
522
+ - lib/insika/studio/assets/dist/fonts/ibm-plex-mono-latin-400-normal.woff2
523
+ - lib/insika/studio/assets/dist/fonts/ibm-plex-mono-latin-500-normal.woff2
524
+ - lib/insika/studio/assets/dist/fonts/ibm-plex-mono-latin-600-normal.woff2
525
+ - lib/insika/studio/assets/dist/fonts/ibm-plex-sans-latin-wght-normal.woff2
502
526
  - lib/insika/studio/forms.rb
503
527
  - lib/insika/studio/nav_icons.rb
528
+ - lib/insika/studio/views/_agent_config_retrieval.erb
529
+ - lib/insika/studio/views/_agent_picker.erb
504
530
  - lib/insika/studio/views/_agent_tab_cache.erb
505
531
  - lib/insika/studio/views/_agent_tab_config.erb
506
532
  - lib/insika/studio/views/_agent_tab_history.erb
507
533
  - lib/insika/studio/views/_agent_tab_loops.erb
508
534
  - lib/insika/studio/views/_agent_tab_memory.erb
509
535
  - lib/insika/studio/views/_agent_tab_outcomes.erb
536
+ - lib/insika/studio/views/_agent_tab_performance.erb
510
537
  - lib/insika/studio/views/_agent_tab_prompts.erb
511
538
  - lib/insika/studio/views/_agent_tab_skills.erb
539
+ - lib/insika/studio/views/_agent_tab_tools.erb
512
540
  - lib/insika/studio/views/_agents_master.erb
541
+ - lib/insika/studio/views/_cfg_alerts.erb
542
+ - lib/insika/studio/views/_cfg_budget.erb
543
+ - lib/insika/studio/views/_cfg_distill.erb
544
+ - lib/insika/studio/views/_cfg_followup.erb
545
+ - lib/insika/studio/views/_cfg_grounding.erb
546
+ - lib/insika/studio/views/_cfg_guardrails.erb
547
+ - lib/insika/studio/views/_cfg_harvest.erb
548
+ - lib/insika/studio/views/_cfg_reliability.erb
549
+ - lib/insika/studio/views/_chats_master.erb
550
+ - lib/insika/studio/views/_customers_master.erb
551
+ - lib/insika/studio/views/_empty.erb
552
+ - lib/insika/studio/views/_facts_master.erb
553
+ - lib/insika/studio/views/_harvest_candidate_detail.erb
554
+ - lib/insika/studio/views/_identity.erb
555
+ - lib/insika/studio/views/_kpi.erb
513
556
  - lib/insika/studio/views/_message.erb
557
+ - lib/insika/studio/views/_model_chart.erb
558
+ - lib/insika/studio/views/_refinement_master.erb
559
+ - lib/insika/studio/views/_tool_edit.erb
560
+ - lib/insika/studio/views/_tool_users.erb
561
+ - lib/insika/studio/views/_why.erb
514
562
  - lib/insika/studio/views/agent_detail.erb
515
563
  - lib/insika/studio/views/agents.erb
516
564
  - lib/insika/studio/views/approvals.erb
@@ -520,26 +568,31 @@ files:
520
568
  - lib/insika/studio/views/customer.erb
521
569
  - lib/insika/studio/views/customers.erb
522
570
  - lib/insika/studio/views/evals.erb
571
+ - lib/insika/studio/views/fact_detail.erb
523
572
  - lib/insika/studio/views/facts.erb
524
573
  - lib/insika/studio/views/followups.erb
525
574
  - lib/insika/studio/views/funnel.erb
526
575
  - lib/insika/studio/views/harvest.erb
527
576
  - lib/insika/studio/views/home.erb
577
+ - lib/insika/studio/views/inbox.erb
578
+ - lib/insika/studio/views/kits.erb
528
579
  - lib/insika/studio/views/knowledge.erb
529
580
  - lib/insika/studio/views/layout.erb
581
+ - lib/insika/studio/views/live.erb
530
582
  - lib/insika/studio/views/login.erb
531
583
  - lib/insika/studio/views/mcp.erb
584
+ - lib/insika/studio/views/models.erb
532
585
  - lib/insika/studio/views/not_found.erb
533
586
  - lib/insika/studio/views/parity.erb
534
587
  - lib/insika/studio/views/playground.erb
535
588
  - lib/insika/studio/views/refinement.erb
589
+ - lib/insika/studio/views/refinement_detail.erb
536
590
  - lib/insika/studio/views/session.erb
537
591
  - lib/insika/studio/views/settings.erb
538
592
  - lib/insika/studio/views/skills.erb
539
593
  - lib/insika/studio/views/system_files.erb
540
594
  - lib/insika/studio/views/task.erb
541
595
  - lib/insika/studio/views/tasks.erb
542
- - lib/insika/studio/views/tool_edit.erb
543
596
  - lib/insika/studio/views/tools.erb
544
597
  - lib/insika/subagent_graph.rb
545
598
  - lib/insika/system_file_store.rb
@@ -548,6 +601,7 @@ files:
548
601
  - lib/insika/telemetry.rb
549
602
  - lib/insika/telemetry/pricing.rb
550
603
  - lib/insika/telemetry/recorder.rb
604
+ - lib/insika/telemetry/ruby_llm_instrumenter.rb
551
605
  - lib/insika/templates.rb
552
606
  - lib/insika/templates/browser-agent/README.md
553
607
  - lib/insika/templates/browser-agent/agent.rb
@@ -562,6 +616,7 @@ files:
562
616
  - lib/insika/templates/travel-planner/README.md
563
617
  - lib/insika/templates/travel-planner/agent.rb
564
618
  - lib/insika/testing/store_contract.rb
619
+ - lib/insika/text_tool_call.rb
565
620
  - lib/insika/tick.rb
566
621
  - lib/insika/timezone.rb
567
622
  - lib/insika/token_estimator.rb
@@ -580,6 +635,7 @@ files:
580
635
  - lib/insika/tools/a2a_remote.rb
581
636
  - lib/insika/tools/agent_enum.rb
582
637
  - lib/insika/tools/concurrency.rb
638
+ - lib/insika/tools/confirm_pending.rb
583
639
  - lib/insika/tools/data_defined_tool.rb
584
640
  - lib/insika/tools/generate_image.rb
585
641
  - lib/insika/tools/load_knowledge.rb
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "time"
4
-
5
- module Insika
6
- module Commands
7
- # Control command: LIVE MCP ingestion. Receives the NAME of
8
- # an MCP instance, delegates to McpToolIngestor (discovers via an injectable client
9
- # -> builds the manifest -> reuses :import_tools: batch upsert + hot reload)
10
- # and returns the per-tool report in the shape of :import_tools, plus
11
- # `instance:`. Idempotent (re-ingesting reconciles). A per-tool failure is isolated
12
- # in `errors[]` (R4); an absent/disabled/url-less instance raises.
13
- # -> { instance, version, created: [names], updated: [names], errors: [{tool,error}] }
14
- class ImportMcpTools
15
- def initialize(ingestor:, event_stream:)
16
- @ingestor = ingestor
17
- @event_stream = event_stream
18
- end
19
-
20
- def call(command)
21
- p = symbolize(command.payload)
22
- name = Insika::Coercion.presence(p[:name]) ||
23
- (raise Insika::ValidationError, "import_mcp_tools: 'name' (MCP instance) is required")
24
-
25
- report = @ingestor.ingest(name)
26
- emit(report)
27
- report
28
- end
29
-
30
- private
31
-
32
- # Emits only COUNTS + the instance name (never headers/env/secrets): 0 leakage.
33
- def emit(report)
34
- @event_stream.emit(Insika::Event.new(
35
- type: :mcp_tools_imported,
36
- data: { instance: report[:instance],
37
- created: report[:created].size, updated: report[:updated].size,
38
- errors: report[:errors].size },
39
- meta: { at: Time.now.utc.iso8601 }
40
- ))
41
- end
42
-
43
- def symbolize(payload)
44
- (payload || {}).each_with_object({}) { |(k, v), acc| acc[k.to_sym] = v }
45
- end
46
- end
47
- end
48
- end
@@ -1,67 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "json"
4
-
5
- module Insika
6
- # MINIMAL MCP client over HTTP JSON-RPC. Discovers the tools
7
- # of an MCP instance with HTTP transport by making a JSON-RPC 2.0 `tools/list`
8
- # POST to the instance endpoint, behind the EgressGuard (SSRF — the url comes
9
- # from editable config). It is the DEFAULT client injected into the
10
- # McpToolIngestor; tests pass a Fake (duck-typed) in its place.
11
- #
12
- # Contract (MCP client duck-type): `#list_tools -> [{name, description,
13
- # inputSchema}]` — the same MCP envelope that the ToolManifest adapter normalizes.
14
- #
15
- # SCOPE (bounded): only the minimal handshake of ONE stateless `tools/list`
16
- # POST. Does NOT implement the full MCP session lifecycle (initialize/protocol
17
- # negotiation/session-id/notifications) nor the stdio transport — that is the
18
- # "real MCP transport", later work (out-of-scope, see spec). It serves
19
- # simple HTTP MCP servers (direct JSON-RPC) and proves the ingestion seam.
20
- class McpHttpClient
21
- JSONRPC_VERSION = "2.0"
22
-
23
- def initialize(url:, http: Insika::HttpClient.new, egress: Insika::EgressGuard,
24
- egress_options: {}, headers: {}, timeout: nil)
25
- @url = url.to_s
26
- @http = http
27
- @egress = egress
28
- @egress_options = egress_options
29
- @headers = { "Content-Type" => "application/json", "Accept" => "application/json" }.merge(headers || {})
30
- @timeout = timeout
31
- end
32
-
33
- # -> [ { "name", "description", "inputSchema" } ]. Raises Insika::Error on
34
- # blocked egress, HTTP != 2xx, invalid JSON or a JSON-RPC error.
35
- def list_tools
36
- reason = @egress.violation(@url, **@egress_options)
37
- raise Insika::Error, "MCP target blocked: #{reason}" if reason
38
-
39
- result = @http.request(method: "POST", url: @url, headers: @headers,
40
- body: request_body("tools/list", {}), timeout: @timeout)
41
- Array(rpc_result(result).fetch("tools", []))
42
- end
43
-
44
- private
45
-
46
- def request_body(method, params)
47
- JSON.generate(jsonrpc: JSONRPC_VERSION, id: 1, method: method, params: params)
48
- end
49
-
50
- # Validates the JSON-RPC envelope and returns `result` (Hash). HTTP/parse/error -> Error.
51
- def rpc_result(result)
52
- status = result[:status].to_i
53
- raise Insika::Error, "MCP HTTP #{status}: #{result[:body].to_s[0, 200]}" if status >= 400
54
-
55
- parsed = begin
56
- JSON.parse(result[:body].to_s)
57
- rescue JSON::ParserError => e
58
- raise Insika::Error, "MCP response is not JSON: #{e.message}"
59
- end
60
- if (err = parsed["error"])
61
- raise Insika::Error, "MCP JSON-RPC error: #{err["message"] || err.inspect}"
62
- end
63
-
64
- parsed["result"] || {}
65
- end
66
- end
67
- end
@@ -1,165 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "json"
4
-
5
- module Insika
6
- # LIVE MCP ingestion (/ spec): discovers the tools of an
7
- # MCP instance at RUNTIME (no hand-written manifest) and ingests them as
8
- # data-tools. Given an McpStore instance + an INJECTABLE MCP client
9
- # (duck-typed: `#list_tools -> [{name, description, inputSchema}]`), it builds a
10
- # ToolManifest and REUSES the ingestion path (the:import_tools Command:
11
- # batch upsert into the ToolStore + hot reload + per-tool report + partial-
12
- # failure isolation R4). The ToolManifest MCP adapter (`inputSchema`) is reused
13
- # — no schema parsing here.
14
- #
15
- # GENERIC: nothing here mentions a consumer/gateway. The MCP instance is DATA in the store.
16
- #
17
- # BINDING STRATEGY (this stage's choice, bounded):
18
- # Each discovered tool becomes an HTTP data-tool that makes a JSON-RPC 2.0
19
- # `tools/call` POST to the instance endpoint (url). The tool name is resolved
20
- # at INGESTION (literal in the body); the model's arguments come in as `{{param}}`
21
- # per TOP-level property of the inputSchema (with quoting by type — strings
22
- # quoted, others raw, via the DataDefinedTool :body encode). This way the tool
23
- # runs through the SAME HTTP path as the other data-tools (egress guard, secret
24
- # headers, hot reload) — no new execution code.
25
- #
26
- # Each tool gets `group: "mcp:<instance>"` so the per-group gating
27
- # (tools_allow_groups) works for free.
28
- #
29
- # DEFERRED / OUT-OF-SCOPE (documented — spec):
30
- # - Real MCP transport: only instances with a `url` (http transport) are ingestible;
31
- # stdio has no HTTP endpoint -> raises a clear error (later work).
32
- # - MCP session lifecycle (initialize/negotiation/session-id/notifications) and the
33
- # UNWRAP of the `tools/call` response (`{content:[{type,text}]}`) — the binding
34
- # makes a stateless POST and returns the raw body (extract body_raw). A server
35
- # that requires the handshake before answering `tools/list`/`tools/call` is not
36
- # reachable yet — that IS the real transport, not this minimal client.
37
- # - Tools whose name/top-level property is outside the ToolDefinition NAME_RE
38
- # (uppercase/hyphens) are ISOLATED into `errors[]` by the import (R4).
39
- #
40
- # CREDENTIAL INJECTION: the instance `env` (Hash) is sent verbatim as HTTP
41
- # headers, on BOTH the discovery request (`tools/list`, this file) and every
42
- # ingested tool's `tools/call` binding (`build_manifest`'s `defaults.headers`)
43
- # — literal header-name -> value, the same convention as a data-tool's own
44
- # `secret_headers` (the operator types the full value, "Bearer xxx" included;
45
- # no magic prefixing). An instance with no `env` sends the bare
46
- # `Content-Type` header only, byte-for-byte what shipped before this.
47
- class McpToolIngestor
48
- def initialize(mcp_store:, import_tools:, client_factory: nil)
49
- @mcp_store = mcp_store
50
- @import_tools = import_tools
51
- # Per-instance client factory (default: minimal JSON-RPC HTTP client).
52
- # Injectable for tests (Fake) and to swap for a real transport later.
53
- @client_factory = client_factory || method(:default_client)
54
- end
55
-
56
- # Discovers + ingests the tools of instance `name`. `client` is injectable
57
- # (Fake in tests); absent -> the factory builds one from the record. -> the
58
- # import_tools report + `instance:` ({ instance:, version:, created:, updated:, errors: }).
59
- def ingest(name, client: nil)
60
- manifest = manifest_for(name, client: client)
61
- report = @import_tools.call(Insika::Command.build(:import_tools, manifest, transport: :internal))
62
- report.merge(instance: name.to_s)
63
- end
64
-
65
- # Discovers the tools and builds the manifest Hash (without ingesting) — isolable for testing.
66
- def manifest_for(name, client: nil)
67
- record = @mcp_store.get_raw(name.to_s)
68
- raise Insika::NotFoundError, "MCP instance '#{name}' not found" if record.nil?
69
- raise Insika::ValidationError, "MCP instance '#{name}' is disabled" unless record["enabled"]
70
-
71
- url = presence(record["url"])
72
- if url.nil?
73
- raise Insika::ValidationError,
74
- "MCP instance '#{name}' has no url: live ingestion requires HTTP transport " \
75
- "(stdio is later work)"
76
- end
77
-
78
- tools = Array((client || @client_factory.call(record)).list_tools)
79
- build_manifest(name.to_s, url, tools, env_headers(record))
80
- end
81
-
82
- private
83
-
84
- # `headers` (an http/sse instance's credentials — `env` reads
85
- # as `headers` for these transports via McpStore's migration-on-read, see
86
- # McpStore#migrate_legacy_headers) -> literal HTTP headers (header-NAME ->
87
- # value; the value carries its own scheme, e.g. "Bearer xxx" — no magic
88
- # prefixing). NOT `secret_headers`: ToolManifest's own rule for a secret
89
- # header requires a `{{secret.*}}` reference, which is the opposite of what
90
- # a literal credential is — so an MCP instance's headers are NOT masked in
91
- # a tool's edit page in /studio/tools, unlike a hand-authored data-tool's
92
- # Authorization header. Acceptable for now (Studio is already
93
- # operator-gated); a real fix routes this through the deployment's own
94
- # {{secret.*}}/{{env.*}} resolution instead — later work.
95
- def env_headers(record)
96
- (record["headers"] || {}).each_with_object({}) { |(k, v), acc| acc[k.to_s] = v.to_s }
97
- end
98
-
99
- def build_manifest(name, url, tools, headers)
100
- {
101
- "version" => 1,
102
- "defaults" => {
103
- "method" => "POST",
104
- "headers" => { "Content-Type" => "application/json" }.merge(headers),
105
- "response" => { "extract" => "body_raw" },
106
- "group" => "mcp:#{name}"
107
- },
108
- "tools" => tools.map { |raw| tool_entry(name, url, stringify(raw)) }
109
- }
110
- end
111
-
112
- # Raw MCP entry -> manifest entry (MCP `inputSchema` envelope + JSON-RPC
113
- # binding). ToolManifest normalizes the `inputSchema` (MCP adapter) and
114
- # inherits the defaults; `group` falls through from the defaults.
115
- def tool_entry(name, url, raw)
116
- tool_name = raw["name"]
117
- input_schema = raw["inputSchema"] || {}
118
- {
119
- "name" => tool_name,
120
- "description" => presence(raw["description"]) || "Tool '#{tool_name}' from MCP server '#{name}'.",
121
- "inputSchema" => input_schema,
122
- "url" => url,
123
- "side_effect" => true, # a tools/call is a side effect (checkpoint/skip-on-resume)
124
- "body" => jsonrpc_call_body(tool_name, input_schema)
125
- }
126
- end
127
-
128
- # JSON-RPC 2.0 `tools/call` body. `name` literal (resolved at ingestion);
129
- # `arguments` per TOP-level property of the inputSchema, with `{{param}}` that
130
- # the DataDefinedTool interpolates at TURN time.
131
- def jsonrpc_call_body(tool_name, input_schema)
132
- %({"jsonrpc":"2.0","id":1,"method":"tools/call",) +
133
- %("params":{"name":#{JSON.generate(tool_name)},"arguments":#{arguments_fragment(input_schema)}}})
134
- end
135
-
136
- # -> "{...}" JSON with one placeholder per top-level property. Strings are
137
- # quoted (the DataDefinedTool :body encode returns the escaped content WITHOUT
138
- # quotes); other types raw (the encode returns value.to_json).
139
- def arguments_fragment(input_schema)
140
- props = (input_schema["properties"] || input_schema[:properties] || {})
141
- return "{}" if props.nil? || props.empty?
142
-
143
- pairs = props.map do |key, spec|
144
- type = stringify(spec)["type"].to_s
145
- placeholder = type == "string" ? %("{{#{key}}}") : "{{#{key}}}"
146
- %(#{JSON.generate(key.to_s)}:#{placeholder})
147
- end
148
- "{#{pairs.join(',')}}"
149
- end
150
-
151
- def default_client(record)
152
- Insika::McpHttpClient.new(url: record["url"], headers: env_headers(record))
153
- end
154
-
155
- def presence(str) = Insika::Coercion.presence(str)
156
-
157
- def stringify(obj)
158
- case obj
159
- when Hash then obj.each_with_object({}) { |(k, v), acc| acc[k.to_s] = stringify(v) }
160
- when Array then obj.map { |v| stringify(v) }
161
- else obj
162
- end
163
- end
164
- end
165
- end