little_ghost 0.7.0 → 0.9.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 (270) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +34 -6
  3. data/docs/guides/assemblies.md +21 -9
  4. data/docs/guides/code_mode.md +2 -2
  5. data/docs/guides/getting_started.md +27 -2
  6. data/docs/guides/integrations.md +20 -161
  7. data/docs/guides/mcp.md +288 -0
  8. data/docs/guides/models_and_providers.md +21 -54
  9. data/docs/guides/production.md +14 -5
  10. data/docs/guides/prompt_views.md +234 -27
  11. data/docs/guides/providers.md +275 -0
  12. data/docs/guides/sandboxing.md +42 -7
  13. data/docs/guides/skills.md +1 -3
  14. data/docs/guides/tools.md +2 -0
  15. data/exe/little_ghost +12 -0
  16. data/lib/little_ghost/agent/context_management.rb +2 -13
  17. data/lib/little_ghost/agent/delegation.rb +7 -4
  18. data/lib/little_ghost/agent/skills.rb +8 -6
  19. data/lib/little_ghost/agent/tool_loop.rb +4 -4
  20. data/lib/little_ghost/agent.rb +230 -70
  21. data/lib/little_ghost/agent_builder.rb +16 -4
  22. data/lib/little_ghost/artifacts/workspace_store.rb +16 -14
  23. data/lib/little_ghost/assembly.rb +48 -7
  24. data/lib/little_ghost/assembly_builder.rb +3 -3
  25. data/lib/little_ghost/cli.rb +429 -0
  26. data/lib/little_ghost/code_mode/broker.rb +11 -3
  27. data/lib/little_ghost/code_mode/javascript/client.rb +58 -11
  28. data/lib/little_ghost/code_mode/javascript/host.rb +37 -13
  29. data/lib/little_ghost/code_mode/javascript/session.rb +21 -9
  30. data/lib/little_ghost/code_mode/javascript_engine.rb +21 -42
  31. data/lib/little_ghost/code_mode/ruby/host.rb +8 -4
  32. data/lib/little_ghost/code_mode/ruby/session.rb +41 -14
  33. data/lib/little_ghost/code_mode/ruby_engine.rb +6 -36
  34. data/lib/little_ghost/code_mode/runtime.rb +57 -24
  35. data/lib/little_ghost/console.rb +17 -0
  36. data/lib/little_ghost/errors.rb +20 -2
  37. data/lib/little_ghost/framework_prompts.rb +376 -0
  38. data/lib/little_ghost/generators/application_generator.rb +179 -0
  39. data/lib/little_ghost/generators/templates/application/Gemfile.tt +3 -0
  40. data/lib/little_ghost/generators/templates/application/README.md.tt +29 -0
  41. data/lib/little_ghost/generators/templates/application/app/agents/application_agent.rb.tt +5 -0
  42. data/lib/little_ghost/generators/templates/application/app/prompts/application/system_prompt.erb.tt +1 -0
  43. data/lib/little_ghost/generators/templates/application/bin/application.tt +10 -0
  44. data/lib/little_ghost/generators/templates/application/config/little_ghost.rb.tt +5 -0
  45. data/lib/little_ghost/generators/templates/application/gitignore.tt +2 -0
  46. data/lib/little_ghost/generators/templates/application/keep.tt +0 -0
  47. data/lib/little_ghost/graph.rb +24 -5
  48. data/lib/little_ghost/mcp/client.rb +307 -610
  49. data/lib/little_ghost/mcp/toolset.rb +133 -95
  50. data/lib/little_ghost/mcp.rb +21 -3
  51. data/lib/little_ghost/model_operations.rb +103 -36
  52. data/lib/little_ghost/model_resolver.rb +2 -0
  53. data/lib/little_ghost/models/catalog/models_dev_source.rb +4 -1
  54. data/lib/little_ghost/prompt_resolver.rb +61 -27
  55. data/lib/little_ghost/prompts/little_ghost/agent/interjections/instructions.erb +12 -0
  56. data/lib/little_ghost/prompts/little_ghost/agent/system/default.erb +10 -0
  57. data/lib/little_ghost/prompts/little_ghost/artifacts/batch/feedback/batch_too_large.erb +10 -0
  58. data/lib/little_ghost/prompts/little_ghost/artifacts/batch/feedback/batch_too_many.erb +10 -0
  59. data/lib/little_ghost/prompts/little_ghost/artifacts/batch/feedback/item_too_large.erb +10 -0
  60. data/lib/little_ghost/prompts/little_ghost/artifacts/errors/preparation_failed.erb +10 -0
  61. data/lib/little_ghost/prompts/little_ghost/artifacts/errors/resolver_invalid.erb +10 -0
  62. data/lib/little_ghost/prompts/little_ghost/artifacts/errors/value_unstorable.erb +10 -0
  63. data/lib/little_ghost/prompts/little_ghost/artifacts/presentation/format/reference.erb +13 -0
  64. data/lib/little_ghost/prompts/little_ghost/artifacts/presentation/format/references.erb +12 -0
  65. data/lib/little_ghost/prompts/little_ghost/artifacts/presentation/format/workspace_references.erb +12 -0
  66. data/lib/little_ghost/prompts/little_ghost/artifacts/presentation/notices/full_result.erb +14 -0
  67. data/lib/little_ghost/prompts/little_ghost/artifacts/presentation/notices/storage_failed.erb +13 -0
  68. data/lib/little_ghost/prompts/little_ghost/artifacts/storage/errors/destination_unsafe.erb +10 -0
  69. data/lib/little_ghost/prompts/little_ghost/artifacts/storage/errors/secure_unavailable.erb +10 -0
  70. data/lib/little_ghost/prompts/little_ghost/artifacts/storage/errors/workspace_changed.erb +10 -0
  71. data/lib/little_ghost/prompts/little_ghost/artifacts/storage/errors/workspace_unavailable.erb +10 -0
  72. data/lib/little_ghost/prompts/little_ghost/artifacts/storage/errors/workspace_unsafe.erb +10 -0
  73. data/lib/little_ghost/prompts/little_ghost/artifacts/storage/feedback/count_limit.erb +10 -0
  74. data/lib/little_ghost/prompts/little_ghost/artifacts/storage/feedback/destination_exists.erb +10 -0
  75. data/lib/little_ghost/prompts/little_ghost/artifacts/storage/feedback/too_large.erb +10 -0
  76. data/lib/little_ghost/prompts/little_ghost/artifacts/storage/feedback/total_limit.erb +10 -0
  77. data/lib/little_ghost/prompts/little_ghost/assembly/feedback/transition_only.erb +10 -0
  78. data/lib/little_ghost/prompts/little_ghost/assembly/tools/fallback/description.erb +10 -0
  79. data/lib/little_ghost/prompts/little_ghost/code_mode/artifacts/format/references.erb +12 -0
  80. data/lib/little_ghost/prompts/little_ghost/code_mode/errors/brokered_close.erb +10 -0
  81. data/lib/little_ghost/prompts/little_ghost/code_mode/errors/cleanup_failed.erb +10 -0
  82. data/lib/little_ghost/prompts/little_ghost/code_mode/errors/execution_failed.erb +11 -0
  83. data/lib/little_ghost/prompts/little_ghost/code_mode/feedback/arguments_object.erb +10 -0
  84. data/lib/little_ghost/prompts/little_ghost/code_mode/feedback/closed.erb +10 -0
  85. data/lib/little_ghost/prompts/little_ghost/code_mode/feedback/control_active.erb +10 -0
  86. data/lib/little_ghost/prompts/little_ghost/code_mode/feedback/limit_exceeded.erb +10 -0
  87. data/lib/little_ghost/prompts/little_ghost/code_mode/feedback/not_active.erb +10 -0
  88. data/lib/little_ghost/prompts/little_ghost/code_mode/feedback/program_active.erb +10 -0
  89. data/lib/little_ghost/prompts/little_ghost/code_mode/feedback/program_timed_out.erb +10 -0
  90. data/lib/little_ghost/prompts/little_ghost/code_mode/feedback/unavailable_tool.erb +10 -0
  91. data/lib/little_ghost/prompts/little_ghost/code_mode/feedback/unknown_program.erb +10 -0
  92. data/lib/little_ghost/prompts/little_ghost/code_mode/javascript/errors/active_programs_limit.erb +10 -0
  93. data/lib/little_ghost/prompts/little_ghost/code_mode/javascript/errors/cleanup_failed.erb +10 -0
  94. data/lib/little_ghost/prompts/little_ghost/code_mode/javascript/errors/execution_limit.erb +10 -0
  95. data/lib/little_ghost/prompts/little_ghost/code_mode/javascript/errors/invalid_request.erb +10 -0
  96. data/lib/little_ghost/prompts/little_ghost/code_mode/javascript/errors/memory_limit.erb +10 -0
  97. data/lib/little_ghost/prompts/little_ghost/code_mode/javascript/errors/pending_calls_limit.erb +10 -0
  98. data/lib/little_ghost/prompts/little_ghost/code_mode/javascript/errors/source_size_limit.erb +10 -0
  99. data/lib/little_ghost/prompts/little_ghost/code_mode/javascript/errors/tools_array.erb +10 -0
  100. data/lib/little_ghost/prompts/little_ghost/code_mode/javascript/instructions.erb +35 -0
  101. data/lib/little_ghost/prompts/little_ghost/code_mode/ruby/feedback/parallel_callables.erb +10 -0
  102. data/lib/little_ghost/prompts/little_ghost/code_mode/ruby/instructions.erb +40 -0
  103. data/lib/little_ghost/prompts/little_ghost/code_mode/tools/exec/description.erb +10 -0
  104. data/lib/little_ghost/prompts/little_ghost/code_mode/tools/stop/description.erb +10 -0
  105. data/lib/little_ghost/prompts/little_ghost/code_mode/tools/stop/inputs/max_output_tokens/description.erb +10 -0
  106. data/lib/little_ghost/prompts/little_ghost/code_mode/tools/wait/description.erb +10 -0
  107. data/lib/little_ghost/prompts/little_ghost/code_mode/tools/wait/inputs/max_output_tokens/description.erb +10 -0
  108. data/lib/little_ghost/prompts/little_ghost/context_management/summary/request.erb +10 -0
  109. data/lib/little_ghost/prompts/little_ghost/context_management/summary/system_instruction.erb +16 -0
  110. data/lib/little_ghost/prompts/little_ghost/graph/context/format/failed_input.erb +11 -0
  111. data/lib/little_ghost/prompts/little_ghost/graph/context/format/previous_input.erb +13 -0
  112. data/lib/little_ghost/prompts/little_ghost/graph/context/headings/original_task.erb +10 -0
  113. data/lib/little_ghost/prompts/little_ghost/graph/context/headings/previous_inputs.erb +10 -0
  114. data/lib/little_ghost/prompts/little_ghost/mcp/errors/request_failed.erb +10 -0
  115. data/lib/little_ghost/prompts/little_ghost/mcp/errors/transformation_unserializable.erb +10 -0
  116. data/lib/little_ghost/prompts/little_ghost/mcp/tools/fallback/description.erb +10 -0
  117. data/lib/little_ghost/prompts/little_ghost/output/truncation/marker.erb +11 -0
  118. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/errors/mount_changed.erb +10 -0
  119. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/errors/secure_traversal_unavailable.erb +10 -0
  120. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/errors/workspace_root_changed.erb +10 -0
  121. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/directory_listing_limit.erb +10 -0
  122. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/entry_required.erb +10 -0
  123. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/file_read_limit.erb +10 -0
  124. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/invalid_utf8.erb +10 -0
  125. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/mount_escape.erb +10 -0
  126. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/mount_missing.erb +10 -0
  127. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/multiply_linked.erb +10 -0
  128. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/not_directory.erb +10 -0
  129. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/not_file.erb +10 -0
  130. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/null_byte.erb +10 -0
  131. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/outside_scope.erb +10 -0
  132. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/parent_escape.erb +10 -0
  133. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/path_missing.erb +10 -0
  134. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/path_traverses_symlink.erb +10 -0
  135. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/read_only.erb +10 -0
  136. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/replace_empty.erb +10 -0
  137. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/symlink_path.erb +10 -0
  138. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/text_multiple.erb +10 -0
  139. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/text_not_found.erb +10 -0
  140. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/write_limit.erb +10 -0
  141. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/write_parent_missing.erb +10 -0
  142. data/lib/little_ghost/prompts/little_ghost/sandbox/filesystem/feedback/write_target_symlink.erb +10 -0
  143. data/lib/little_ghost/prompts/little_ghost/sandbox/policy/feedback/feature_denied.erb +10 -0
  144. data/lib/little_ghost/prompts/little_ghost/sandbox/process/errors/program_supervisor_failed.erb +10 -0
  145. data/lib/little_ghost/prompts/little_ghost/sandbox/process/feedback/command_timed_out.erb +10 -0
  146. data/lib/little_ghost/prompts/little_ghost/sandbox/process/feedback/executable_required.erb +10 -0
  147. data/lib/little_ghost/prompts/little_ghost/sandbox/process/feedback/program_memory_exceeded.erb +10 -0
  148. data/lib/little_ghost/prompts/little_ghost/sandbox/process/feedback/program_output_exceeded.erb +10 -0
  149. data/lib/little_ghost/prompts/little_ghost/sandbox/process/feedback/program_timed_out.erb +10 -0
  150. data/lib/little_ghost/prompts/little_ghost/skills/discovery/instructions.erb +18 -0
  151. data/lib/little_ghost/prompts/little_ghost/skills/feedback/unknown.erb +11 -0
  152. data/lib/little_ghost/prompts/little_ghost/skills/resources/notices/truncated.erb +10 -0
  153. data/lib/little_ghost/prompts/little_ghost/skills/tools/activate/content.erb +28 -0
  154. data/lib/little_ghost/prompts/little_ghost/skills/tools/activate/description.erb +10 -0
  155. data/lib/little_ghost/prompts/little_ghost/skills/tools/activate/inputs/name/description.erb +10 -0
  156. data/lib/little_ghost/prompts/little_ghost/structured_output/persistence/format/redaction.erb +12 -0
  157. data/lib/little_ghost/prompts/little_ghost/structured_output/repair/feedback/invalid_result.erb +11 -0
  158. data/lib/little_ghost/prompts/little_ghost/structured_output/repair/feedback/schema_errors.erb +11 -0
  159. data/lib/little_ghost/prompts/little_ghost/structured_output/repair/request.erb +14 -0
  160. data/lib/little_ghost/prompts/little_ghost/structured_output/tools/result/description.erb +11 -0
  161. data/lib/little_ghost/prompts/little_ghost/structured_output/validation/feedback/invalid_json.erb +11 -0
  162. data/lib/little_ghost/prompts/little_ghost/structured_output/validation/feedback/missing_tool.erb +11 -0
  163. data/lib/little_ghost/prompts/little_ghost/structured_output/validation/feedback/multiple_tools.erb +11 -0
  164. data/lib/little_ghost/prompts/little_ghost/structured_output/validation/feedback/too_complex.erb +11 -0
  165. data/lib/little_ghost/prompts/little_ghost/structured_output/validation/feedback/too_deep.erb +11 -0
  166. data/lib/little_ghost/prompts/little_ghost/structured_output/validation/feedback/too_large.erb +11 -0
  167. data/lib/little_ghost/prompts/little_ghost/structured_output/validation/feedback/tool_not_exclusive.erb +11 -0
  168. data/lib/little_ghost/prompts/little_ghost/subagents/errors/create_failed.erb +10 -0
  169. data/lib/little_ghost/prompts/little_ghost/subagents/errors/previous_turn_failed.erb +10 -0
  170. data/lib/little_ghost/prompts/little_ghost/subagents/errors/restore_failed.erb +10 -0
  171. data/lib/little_ghost/prompts/little_ghost/subagents/errors/turn_failed.erb +10 -0
  172. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/duplicate_ids.erb +10 -0
  173. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/duplicate_path.erb +10 -0
  174. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/identity_capacity.erb +10 -0
  175. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/inactive.erb +10 -0
  176. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/interjection_chars_limit.erb +10 -0
  177. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/interjection_limit.erb +10 -0
  178. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/interjection_unsupported.erb +10 -0
  179. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/invalid_cursor.erb +10 -0
  180. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/invalid_mode.erb +10 -0
  181. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/list_limit.erb +10 -0
  182. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/message_limit.erb +10 -0
  183. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/message_type.erb +10 -0
  184. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/not_running.erb +10 -0
  185. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/queue_capacity.erb +10 -0
  186. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/task_name_invalid.erb +10 -0
  187. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/task_name_limit.erb +10 -0
  188. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/terminal_identity.erb +11 -0
  189. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/turn_capacity.erb +10 -0
  190. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/unknown_id.erb +10 -0
  191. data/lib/little_ghost/prompts/little_ghost/subagents/feedback/unknown_kind.erb +10 -0
  192. data/lib/little_ghost/prompts/little_ghost/subagents/notices/turn_cancelled.erb +10 -0
  193. data/lib/little_ghost/prompts/little_ghost/subagents/tools/interject/description.erb +10 -0
  194. data/lib/little_ghost/prompts/little_ghost/subagents/tools/interject/inputs/active_id/description.erb +10 -0
  195. data/lib/little_ghost/prompts/little_ghost/subagents/tools/interject/inputs/message/description.erb +10 -0
  196. data/lib/little_ghost/prompts/little_ghost/subagents/tools/list/description.erb +10 -0
  197. data/lib/little_ghost/prompts/little_ghost/subagents/tools/send/description.erb +10 -0
  198. data/lib/little_ghost/prompts/little_ghost/subagents/tools/send/inputs/id/description.erb +10 -0
  199. data/lib/little_ghost/prompts/little_ghost/subagents/tools/send/inputs/message/description.erb +10 -0
  200. data/lib/little_ghost/prompts/little_ghost/subagents/tools/send/inputs/send_mode/description.erb +10 -0
  201. data/lib/little_ghost/prompts/little_ghost/subagents/tools/spawn/description.erb +10 -0
  202. data/lib/little_ghost/prompts/little_ghost/subagents/tools/spawn/inputs/kind/description.erb +11 -0
  203. data/lib/little_ghost/prompts/little_ghost/subagents/tools/spawn/inputs/spawn_mode/description.erb +10 -0
  204. data/lib/little_ghost/prompts/little_ghost/subagents/tools/spawn/inputs/task/description.erb +10 -0
  205. data/lib/little_ghost/prompts/little_ghost/subagents/tools/spawn/inputs/task_name/description.erb +10 -0
  206. data/lib/little_ghost/prompts/little_ghost/subagents/tools/wait/description.erb +10 -0
  207. data/lib/little_ghost/prompts/little_ghost/subagents/tools/wait/inputs/ids/description.erb +10 -0
  208. data/lib/little_ghost/prompts/little_ghost/swarm/handoff/notice.erb +10 -0
  209. data/lib/little_ghost/prompts/little_ghost/swarm/handoff/request.erb +16 -0
  210. data/lib/little_ghost/prompts/little_ghost/swarm/tools/handoff/description.erb +10 -0
  211. data/lib/little_ghost/prompts/little_ghost/tools/built_in/list_files/description.erb +10 -0
  212. data/lib/little_ghost/prompts/little_ghost/tools/built_in/read_file/description.erb +10 -0
  213. data/lib/little_ghost/prompts/little_ghost/tools/built_in/replace_in_file/description.erb +10 -0
  214. data/lib/little_ghost/prompts/little_ghost/tools/built_in/shell/description.erb +10 -0
  215. data/lib/little_ghost/prompts/little_ghost/tools/built_in/write_file/description.erb +10 -0
  216. data/lib/little_ghost/prompts/little_ghost/tools/built_in/write_todos/description.erb +10 -0
  217. data/lib/little_ghost/prompts/little_ghost/tools/built_in/write_todos/feedback/single_progress.erb +10 -0
  218. data/lib/little_ghost/prompts/little_ghost/tools/built_in/write_todos/feedback/unique_ids.erb +10 -0
  219. data/lib/little_ghost/prompts/little_ghost/tools/errors/unexpected_failure.erb +10 -0
  220. data/lib/little_ghost/prompts/little_ghost/tools/errors/unserializable_result.erb +10 -0
  221. data/lib/little_ghost/prompts/little_ghost/tools/feedback/invalid_input.erb +10 -0
  222. data/lib/little_ghost/prompts/little_ghost/tools/feedback/unknown.erb +10 -0
  223. data/lib/little_ghost/prompts/little_ghost/tools/loop/notices/final_warning.erb +10 -0
  224. data/lib/little_ghost/prompts/little_ghost/tools/loop/notices/termination.erb +10 -0
  225. data/lib/little_ghost/prompts/little_ghost/tools/loop/notices/warning.erb +10 -0
  226. data/lib/little_ghost/prompts/little_ghost/tools/validation/schema/additional_property.erb +10 -0
  227. data/lib/little_ghost/prompts/little_ghost/tools/validation/schema/enum.erb +11 -0
  228. data/lib/little_ghost/prompts/little_ghost/tools/validation/schema/invalid_format.erb +10 -0
  229. data/lib/little_ghost/prompts/little_ghost/tools/validation/schema/invalid_pattern.erb +10 -0
  230. data/lib/little_ghost/prompts/little_ghost/tools/validation/schema/max_items.erb +11 -0
  231. data/lib/little_ghost/prompts/little_ghost/tools/validation/schema/max_length.erb +11 -0
  232. data/lib/little_ghost/prompts/little_ghost/tools/validation/schema/maximum.erb +11 -0
  233. data/lib/little_ghost/prompts/little_ghost/tools/validation/schema/min_items.erb +11 -0
  234. data/lib/little_ghost/prompts/little_ghost/tools/validation/schema/min_length.erb +11 -0
  235. data/lib/little_ghost/prompts/little_ghost/tools/validation/schema/minimum.erb +11 -0
  236. data/lib/little_ghost/prompts/little_ghost/tools/validation/schema/required.erb +10 -0
  237. data/lib/little_ghost/prompts/little_ghost/tools/validation/schema/type.erb +11 -0
  238. data/lib/little_ghost/prompts/little_ghost/workspace/feedback/path_changed.erb +10 -0
  239. data/lib/little_ghost/provider_registry.rb +1 -0
  240. data/lib/little_ghost/providers/lm_studio/catalog_source.rb +201 -0
  241. data/lib/little_ghost/providers/lm_studio.rb +52 -0
  242. data/lib/little_ghost/providers/openai.rb +3 -75
  243. data/lib/little_ghost/providers/openai_compatible.rb +78 -1
  244. data/lib/little_ghost/runtime/hooks/artifacts.rb +58 -22
  245. data/lib/little_ghost/runtime.rb +8 -3
  246. data/lib/little_ghost/sandbox/environment_policy.rb +29 -4
  247. data/lib/little_ghost/sandbox/filesystem.rb +51 -33
  248. data/lib/little_ghost/sandbox/policy.rb +28 -6
  249. data/lib/little_ghost/sandbox/process_runner.rb +6 -2
  250. data/lib/little_ghost/sandbox/process_session.rb +8 -4
  251. data/lib/little_ghost/sandbox/scope.rb +4 -1
  252. data/lib/little_ghost/sandboxes/seatbelt.rb +3 -1
  253. data/lib/little_ghost/sandboxes/unrestricted.rb +17 -9
  254. data/lib/little_ghost/skills/catalog.rb +41 -36
  255. data/lib/little_ghost/structured_output.rb +6 -6
  256. data/lib/little_ghost/subagents/control_tool.rb +58 -0
  257. data/lib/little_ghost/subagents/manager.rb +99 -74
  258. data/lib/little_ghost/support/output_truncation.rb +28 -4
  259. data/lib/little_ghost/swarm.rb +20 -7
  260. data/lib/little_ghost/tool.rb +47 -20
  261. data/lib/little_ghost/tool_registry.rb +2 -2
  262. data/lib/little_ghost/tools/filesystem.rb +12 -4
  263. data/lib/little_ghost/tools/shell.rb +5 -1
  264. data/lib/little_ghost/tools/write_todos.rb +9 -9
  265. data/lib/little_ghost/version.rb +1 -1
  266. data/lib/little_ghost/workflow.rb +199 -27
  267. data/lib/little_ghost/workspace.rb +2 -2
  268. data/lib/little_ghost.rb +6 -2
  269. metadata +222 -7
  270. data/lib/little_ghost/mcp/types.rb +0 -216
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d214ff7dd49c056712968000f9ddc127bc132dd4b97b8f0c89bb3adb2f52f3b0
4
- data.tar.gz: de2f85339390969db2ae0863bf9056ab386b07e2bf05cc976f23899ae2b318d2
3
+ metadata.gz: 271908b0fc40900504fb25cd57d2cbcc8d987ac1ab32a0db58353562793446fc
4
+ data.tar.gz: 507e5d747e8b341dd60b1edce8811e0dc5b2d41f98cb970e801284b2a326a49f
5
5
  SHA512:
6
- metadata.gz: 48004e9b2b4c826877601f31681129f5f0434f544aa979941d2d09840ca677ccbf86e0334cdd9de60081601e039326d445a033064940049dbd3f5e27243f47ac
7
- data.tar.gz: 88fc87d32cb553b047273e249685f410ff8721e32275a3f3800e00cd79a674fb43188b0ef34d2b0a2ca04c4502a18503a6da791d2634ec92f4bc539d665ad36a
6
+ metadata.gz: 830edf81e2d4892e7b72def07ba1d1be85843c8abf5cbb25d744ad520e8586fe9de2ae1cb32084ce832bb1eb866f4fa083af95b93e59df2b3e2c47f4e5c7aea9
7
+ data.tar.gz: a8dba3d880bdc6adc4271daac984f9ab6384d34520a5be2071e66d1d746f4979952c13e7743364e2de2f2c2aa721057e12e54ca29c83a382b6506e49889ee43e
data/README.md CHANGED
@@ -20,7 +20,9 @@ run.response
20
20
  # One possible response: Hi! How can I help today?
21
21
  ```
22
22
 
23
- That small definition is already a complete agent. LittleGhost makes the model call, tracks usage, supports streaming, and closes the resources it creates for the request. Add a tool when the agent needs something from your application. Bring in more agents when the work grows.
23
+ That definition is a complete Agent. LittleGhost makes the model call, tracks
24
+ usage, supports streaming, and closes request resources. Add a Tool for
25
+ application capabilities or an Assembly as the work grows.
24
26
 
25
27
  Model requests may send system instructions, caller input, conversation history,
26
28
  Tool results, and attachments to the selected provider. Model wording can vary
@@ -40,9 +42,33 @@ $ bundle install
40
42
  $ export OPENROUTER_API_KEY="..."
41
43
  ```
42
44
 
43
- OpenRouter keeps the first setup to one credential. It is not required: LittleGhost also includes adapters for OpenAI-compatible APIs, Anthropic, Gemini, Vertex AI, and Bedrock. [Running in Production](docs/guides/production.md) shows how to configure providers and give model choices application-facing names.
45
+ The introductory guides use OpenRouter so you can start with one key. Prefer
46
+ another hosted provider or a local Ollama or LM Studio server? See [Provider
47
+ Support](docs/guides/providers.md).
44
48
 
45
- LittleGhost runs inside your Ruby process. Use it from a controller, job, CLI, or service. If you want a conventional layout, start with `app/agents`, `app/assemblies`, `app/prompts`, and `app/tools`.
49
+ LittleGhost runs inside your Ruby process. Use it from a controller, job, CLI,
50
+ or service.
51
+
52
+ ## Generate a small application
53
+
54
+ Generate a conventional standalone application:
55
+
56
+ ```sh
57
+ $ gem install little_ghost
58
+ $ little_ghost new MyApp
59
+ $ cd my_app
60
+ $ export OPENROUTER_API_KEY="..."
61
+ $ bin/little_ghost console
62
+ ```
63
+
64
+ The generator installs the bundle. `bin/little_ghost console` runs that
65
+ bundle's LittleGhost version and loads the application before starting IRB.
66
+
67
+ The source checkout also includes a complete
68
+ [single-file Agent](https://github.com/littleghostai/little_ghost/tree/main/examples/basic_agent)
69
+ and
70
+ [coding harness](https://github.com/littleghostai/little_ghost/tree/main/examples/coding_harness),
71
+ both configured for local Ollama.
46
72
 
47
73
  ## Give an agent real capabilities
48
74
 
@@ -120,15 +146,17 @@ upgrading, because interfaces may change between releases.
120
146
 
121
147
  - [Getting Started](docs/guides/getting_started.md) takes you from installation to a tool-backed, streaming agent.
122
148
  - [Core Concepts](docs/guides/core_concepts.md) builds the mental model from Agent to Assembly.
123
- - [Models and Providers](docs/guides/models_and_providers.md) gives shared model choices application-facing names.
124
- - [Prompts as Views](docs/guides/prompt_views.md) gives growing instructions, shared pieces, and application values a natural home.
149
+ - [Models and Providers](docs/guides/models_and_providers.md) explains targets, shared roles, and per-request model selection.
150
+ - [Provider Support](docs/guides/providers.md) has copyable setup for hosted APIs and local model servers.
151
+ - [Prompts as Views](docs/guides/prompt_views.md) explains Agent instructions and shared partials, including how to customize LittleGhost's bundled framework prompts.
125
152
  - [Tools](docs/guides/tools.md) explains how models call focused Ruby operations.
153
+ - [MCP](docs/guides/mcp.md) connects agents to operations published through the Model Context Protocol.
126
154
  - [Structured Results and Content](docs/guides/structured_outputs_and_content.md) covers checked result shapes, images, and documents.
127
155
  - [Compose Agents](docs/guides/assemblies.md) walks through workflows, swarms, graphs, nesting, and builders.
128
156
  - [Skills](docs/guides/skills.md) organizes reusable instructions and supporting resources.
129
157
  - [Workspaces and Sandboxes](docs/guides/sandboxing.md) gives files and child processes a deliberate place to run.
130
158
  - [Code Mode](docs/guides/code_mode.md) lets a model compose Tools in sandboxed Ruby or optional JavaScript.
131
- - [Integrations](docs/guides/integrations.md) connects MCP, AG-UI, and OpenTelemetry.
159
+ - [Integrations](docs/guides/integrations.md) connects Run streams to AG-UI and OpenTelemetry.
132
160
  - [Running in Production](docs/guides/production.md) covers configuration, saved conversations, supervision, and observability.
133
161
  - [API reference](rdoc-ref:LittleGhost) provides exact method signatures and ownership rules.
134
162
 
@@ -15,7 +15,7 @@ run = entrypoint.ask(question)
15
15
 
16
16
  ## Use a Workflow for explicit application logic
17
17
 
18
- A Workflow's `perform` method is ordinary Ruby. Inside it, `invoke` prepares a child call. Read `.output` when you need an intermediate answer. Return the final `invoke` call untouched so its response can stream to the caller.
18
+ A Workflow's `perform` method is ordinary Ruby. Inside it, `invoke` prepares a child call. Read `.output` when you need an intermediate answer. Return the final `invoke` call untouched so its response can stream to the caller, or return a value that Ruby computes from the intermediate answers.
19
19
 
20
20
  ```ruby
21
21
  class ResponseWorkflow < LittleGhost::Workflow
@@ -41,25 +41,37 @@ Every participant passed to `invoke` can be an Agent or another Assembly. By def
41
41
 
42
42
  Each child Agent keeps its own [prompt view](prompt_views.md). The Workflow supplies request-specific input; it does not replace that Agent's reusable system instructions.
43
43
 
44
- The last child is special because its events become the Workflow's public stream. Return that `invoke` without consuming it:
44
+ The last child is special when its events should become the Workflow's public stream. Return that `invoke` without consuming it:
45
45
 
46
46
  ```ruby
47
- # Wrong: this returns a String after consuming the final invocation.
48
47
  def perform
49
- invoke(CustomerSupportAgent).output
48
+ invoke CustomerSupportAgent
50
49
  end
50
+ ```
51
51
 
52
- # Right: this returns the lazy invocation itself.
53
- def perform
54
- invoke CustomerSupportAgent
52
+ When Ruby should compute the caller-visible result, consume every child and return the computed value:
53
+
54
+ ```ruby
55
+ class EvidenceWorkflow < LittleGhost::Workflow
56
+ private
57
+
58
+ def perform
59
+ findings = parallel(
60
+ invoke(LedgerResearchAgent),
61
+ invoke(PolicyResearchAgent),
62
+ max_concurrency: 2
63
+ )
64
+
65
+ {"findings" => findings}
66
+ end
55
67
  end
56
68
  ```
57
69
 
58
- The first version produces a failed top-level Run whose error is `ProtocolError`. Use `.output` only when Ruby needs an intermediate answer before choosing the next step.
70
+ A returned String becomes the Workflow's textual response. Arrays, mappings, numbers, and booleans become a structured result available through `RunResult#output`, including when the Workflow is exposed with `assembly_as_tool`. Direct structured results must be JSON-compatible and stay within LittleGhost's structured-result size, depth, and complexity limits. Return an explicit value: `nil` remains a `ProtocolError`, which catches forgotten returns.
59
71
 
60
72
  ### Choose a branch in Ruby
61
73
 
62
- Each branch should end with its final unconsumed invocation:
74
+ Each branch should end with its final unconsumed invocation or a directly computed value:
63
75
 
64
76
  ```ruby
65
77
  class RoutedResponseWorkflow < LittleGhost::Workflow
@@ -274,5 +274,5 @@ engine, but the generated program then has the same host access as the parent.
274
274
 
275
275
  See `LittleGhost::CodeMode::Engine`, `LittleGhost::CodeMode::Session`, and
276
276
  `LittleGhost::CodeMode::ProgramResult` for the extension contract. Continue
277
- with [Integrations](integrations.md) to connect Runs to MCP tools, AG-UI, and
278
- OpenTelemetry.
277
+ with [MCP](mcp.md) to add operations from a remote server, or
278
+ [Integrations](integrations.md) to connect Runs to AG-UI and OpenTelemetry.
@@ -17,7 +17,8 @@ $ export OPENROUTER_API_KEY="..."
17
17
 
18
18
  Use your application's secret manager outside a local shell, and never commit provider credentials.
19
19
 
20
- This guide uses OpenRouter because one credential is enough to begin. LittleGhost can use other provider connections too; you will configure those in [Running in Production](production.md).
20
+ This guide uses OpenRouter to keep setup to one key. Prefer another hosted
21
+ provider or a local model server? Start with [Provider Support](providers.md).
21
22
 
22
23
  ## See your first answer
23
24
 
@@ -196,11 +197,35 @@ app/
196
197
  │ └── response_workflow.rb
197
198
  ├── prompts/
198
199
  │ └── customer_support/
199
- │ └── system.erb
200
+ │ └── system_prompt.erb
200
201
  └── tools/
201
202
  └── help_center_lookup_tool.rb
202
203
  ```
203
204
 
205
+ To generate this layout for a standalone application, install the gem and run
206
+ `little_ghost new`:
207
+
208
+ ```sh
209
+ $ gem install little_ghost
210
+ $ little_ghost new MyApp
211
+ $ cd my_app
212
+ $ export OPENROUTER_API_KEY="..."
213
+ $ bin/little_ghost console
214
+ ```
215
+
216
+ The generator creates `my_app` with one Agent, a prompt view, configuration,
217
+ the conventional application directories, an installed bundle, and a local
218
+ LittleGhost command. `bin/little_ghost console` uses the generated
219
+ application's bundle, loads its configuration and classes, and then starts
220
+ IRB.
221
+
222
+ The source repository also contains a complete
223
+ [single-file Agent](https://github.com/littleghostai/little_ghost/tree/main/examples/basic_agent)
224
+ and a
225
+ [coding harness](https://github.com/littleghostai/little_ghost/tree/main/examples/coding_harness)
226
+ that demonstrates Agents, prompt views, Tools, a Graph, a Workspace, and a
227
+ native Sandbox.
228
+
204
229
  You now have the smallest useful LittleGhost application: one Agent, one Tool, and one familiar Ruby call.
205
230
 
206
231
  When the feature grows, the calling style stays the same. An **assembly** lets one or more agents work as a unit while keeping `.ask` and `.stream_ask`. Read [Core Concepts](core_concepts.md) next and grow this Agent into a larger system.
@@ -1,149 +1,8 @@
1
- # Connect MCP, AG-UI, and OpenTelemetry
1
+ # Connect Runs to interfaces and tracing
2
2
 
3
- LittleGhost can load Tools from an MCP server, translate a Run stream for an
4
- interactive interface, and publish traces. Each integration uses the same
5
- Agents and Runs you already have.
6
-
7
- ## Load Tools from an MCP server
8
-
9
- An MCP Toolset connects to one server and turns its published operations into
10
- LittleGhost Tool classes. Add the Toolset through the same Agent `tools`
11
- declaration used for local Tools:
12
-
13
- ```ruby
14
- require "little_ghost/mcp"
15
-
16
- class HelpCenterTools < LittleGhost::MCP::Toolset
17
- connection url: "https://mcp.example/rpc", timeout: 20
18
- end
19
-
20
- class CustomerSupportAgent < LittleGhost::Agent
21
- system_prompt "Use help-center tools for published guidance."
22
- tools HelpCenterTools
23
- end
24
-
25
- run = CustomerSupportAgent.ask("How long do refunds take?")
26
- run.response
27
- ```
28
-
29
- `connection` requires `url` and also accepts `headers`, `timeout`, `signer`,
30
- `allow_insecure_http`, and `max_response_bytes`. Pass a block when credentials
31
- depend on the current Agent run:
32
-
33
- ```ruby
34
- connection do |binding|
35
- token = McpAccessTokens.for_actor(binding.run.invocation.actor_id)
36
- {
37
- url: "https://mcp.example/rpc",
38
- headers: {"Authorization" => "Bearer #{token}"},
39
- timeout: 20
40
- }
41
- end
42
- ```
43
-
44
- The block's `binding` gives it access to the current Run. LittleGhost evaluates
45
- the block before opening the MCP session, so each Agent run can use credentials
46
- for its authenticated caller.
47
-
48
- By default, the Agent receives every operation published by the server. Their
49
- normalized server names, such as `search` and `fetch`, become Tool names.
50
-
51
- Use `map_tool` when the Agent should receive only part of the server catalog or
52
- when a generated Tool needs a different name or configuration:
53
-
54
- ```ruby
55
- class CuratedHelpCenterTools < LittleGhost::MCP::Toolset
56
- connection url: "https://mcp.example/rpc", timeout: 20
57
-
58
- map_tool do |tool_class, definition:, binding:|
59
- next unless %w[search fetch].include?(definition.source_name)
60
-
61
- tool_class.tool_name "help_center_#{definition.source_name}"
62
- tool_class
63
- end
64
- end
65
- ```
66
-
67
- `definition` describes the operation published by the server, and `binding`
68
- identifies the current Agent run. Return the class after configuring it, or
69
- return `nil` to omit the operation. Renaming a generated Tool does not change
70
- the original `Definition#source_name` sent back to the server.
71
-
72
- The Agent can call the generated Tools like local Tools. LittleGhost uses one
73
- local client and transport for the Toolset during the Agent run. The built-in
74
- HTTP transport does not send an MCP session-termination request. Configure
75
- server-side expiry, or arrange explicit remote cleanup when the server requires
76
- it.
77
-
78
- Most MCP results need no mapping. LittleGhost returns `structuredContent` as a
79
- Ruby Hash when present, otherwise it returns the server's text. Server images
80
- become Artifacts.
81
-
82
- Use `map_result` when one operation needs application-specific conversion. This
83
- example turns the server's download identifier into a deferred Artifact:
84
-
85
- ```ruby
86
- map_result do |result, call:, binding:|
87
- next result unless call.definition.source_name == "export"
88
-
89
- LittleGhost::Tool::Result.new(
90
- value: result.structured_content,
91
- artifacts: [
92
- LittleGhost::Artifact.deferred(
93
- reference: result.metadata.fetch("download_id"),
94
- media_type: "application/octet-stream"
95
- )
96
- ]
97
- )
98
- end
99
- ```
100
-
101
- `map_result` receives the complete `MCP::Result`, the `MCP::Call` that produced
102
- it, and the current binding. Return any Ruby value or `Tool::Result`. Returning
103
- the supplied result unchanged keeps the default conversion described above.
104
- MCP images and local Tool artifacts use the same storage and presentation
105
- rules when `Configuration#artifacts` is enabled. Images and documents are sent
106
- as model content; their stored references are fallback information rather than
107
- a second representation. LittleGhost also checks results against
108
- server-advertised JSON Schema Draft 2020-12 output schemas.
109
-
110
- An optional server can fail discovery without preventing Agent construction:
111
-
112
- ```ruby
113
- class HelpCenterTools < LittleGhost::MCP::Toolset
114
- connection { |binding| McpConnections.help_center(binding) }
115
- optional true
116
- on_error do |error, binding:|
117
- McpAvailability.report(error, run_id: binding.run.invocation.run_id)
118
- end
119
- end
120
- ```
121
-
122
- `optional true` converts expected provider and protocol discovery failures
123
- into an empty Tool set. `on_error` observes only those caught failures.
124
- Cancellation, deadlines, configuration errors, and application callback
125
- failures still propagate.
126
-
127
- LittleGhost limits the number and total size of discovered operations, the
128
- complexity of their schemas, and the size and number of returned images.
129
- `HTTPTransport` also limits each HTTP response and requires HTTPS unless local
130
- HTTP is explicitly enabled.
131
-
132
- > **Safety note:** An MCP server supplies descriptions and results that the model
133
- > can see. Structural validation does not make that content trustworthy or
134
- > authorize an operation it suggests. Expose only the operations the Agent
135
- > needs, use narrowly scoped credentials, and have the server authorize every
136
- > sensitive call. If a result becomes a deferred Artifact, its resolver must
137
- > verify that the referenced file belongs to the authenticated caller, fetch
138
- > only from an intended service, and limit the response size before returning
139
- > bytes to LittleGhost.
140
-
141
- LittleGhost implements its documented client behavior for the [MCP 2025-06-18
142
- specification](https://modelcontextprotocol.io/specification/2025-06-18).
143
-
144
- Use `LittleGhost::MCP::HTTPTransport` and `LittleGhost::MCP::Client` directly
145
- when you need a custom transport. They produce the same generated Tool classes
146
- and accept the same mapping callbacks as Toolset.
3
+ Use AG-UI to stream Run events to an interactive client. Use OpenTelemetry to
4
+ publish traces to the backend your application already uses. Neither changes
5
+ the Agent that produced the Run.
147
6
 
148
7
  ## Send a Run stream through AG-UI
149
8
 
@@ -168,13 +27,13 @@ events = LittleGhost::AGUI::Adapter.new.stream(
168
27
  events.each { |event| websocket.write(JSON.generate(event)) }
169
28
  ```
170
29
 
171
- The adapter translates text, reasoning, Tool activity, usage, retries, trace
172
- context, subagent activity, and terminal outcomes. It is stateless between
173
- calls. Your application still owns the connection, backpressure, disconnect
174
- behavior, and any request state its callbacks need.
30
+ The adapter translates the full Run, including model output, Tool activity,
31
+ retries, subagent activity, and the final outcome. It does not keep state between
32
+ calls. Your application owns the connection, backpressure, disconnect behavior,
33
+ and any request state its callbacks need.
175
34
 
176
- LittleGhost also emits namespaced custom events. Consumers should preserve or
177
- deliberately ignore event types they don't recognize. See the [AG-UI event
35
+ LittleGhost may emit event types beyond the core AG-UI set. Decide whether the
36
+ client preserves or ignores types it does not recognize. See the [AG-UI event
178
37
  documentation](https://docs.ag-ui.com/concepts/events) when implementing the
179
38
  client.
180
39
 
@@ -183,8 +42,8 @@ client.
183
42
  > see the complete Run, then filter fields before sending or storing events.
184
43
 
185
44
  Calling `each` drives the source stream on the caller's fiber or thread. When a
186
- client disconnects, stop enumerating and apply the cancellation behavior your
187
- application needs. Closing the socket can't undo Tool work that already ran.
45
+ client disconnects, stop enumerating and decide whether the application should
46
+ cancel the Run. Closing the socket cannot undo Tool work that already ran.
188
47
 
189
48
  ## Trace Runs with OpenTelemetry
190
49
 
@@ -197,9 +56,9 @@ LittleGhost.configure do |config|
197
56
  end
198
57
  ```
199
58
 
200
- LittleGhost depends on `opentelemetry-api`, leaving the SDK, processor, and
201
- exporter up to the application. It emits spans and events for Runs, Agents,
202
- model calls, Tools, assemblies, sessions, usage, and failures. Active operations
59
+ LittleGhost includes the `opentelemetry-api` integration. Your application
60
+ chooses the SDK, processor, and exporter. The subscriber emits spans and events
61
+ for Runs, model calls, Tools, assemblies, sessions, usage, and failures, and it
203
62
  can propagate W3C `traceparent` and `tracestate` fields.
204
63
 
205
64
  Prompts, messages, responses, Tool arguments, and exception content are omitted
@@ -209,9 +68,9 @@ Avoid putting raw user, order, session, or request IDs in span attributes.
209
68
 
210
69
  Attribute names follow the evolving [OpenTelemetry GenAI semantic
211
70
  conventions](https://opentelemetry.io/docs/specs/semconv/gen-ai/) where they
212
- apply. Flush or shut down `LittleGhost::Instrumentation` during application
213
- shutdown when your backend buffers data.
71
+ apply. If the tracing backend buffers data, flush or shut down
72
+ `LittleGhost::Instrumentation` before the application exits.
214
73
 
215
- See [Running in Production](production.md) for startup, shutdown, and observability,
216
- [Tools](tools.md) for local and remote Tool behavior, and [Workspaces and
217
- Sandboxes](sandboxing.md) for child processes and files.
74
+ See [Running in Production](production.md) for startup, shutdown, and
75
+ observability, [MCP](mcp.md) for operations published by remote servers,
76
+ and [Workspaces and Sandboxes](sandboxing.md) for child processes and files.