anima-core 1.3.0 → 1.5.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 (175) hide show
  1. checksums.yaml +4 -4
  2. data/.reek.yml +23 -26
  3. data/README.md +118 -104
  4. data/agents/thoughts-analyzer.md +12 -7
  5. data/anima-core.gemspec +1 -0
  6. data/app/channels/session_channel.rb +38 -58
  7. data/app/decorators/agent_message_decorator.rb +7 -2
  8. data/app/decorators/message_decorator.rb +31 -100
  9. data/app/decorators/pending_from_melete_decorator.rb +36 -0
  10. data/app/decorators/pending_from_melete_goal_decorator.rb +13 -0
  11. data/app/decorators/pending_from_melete_skill_decorator.rb +19 -0
  12. data/app/decorators/pending_from_melete_workflow_decorator.rb +13 -0
  13. data/app/decorators/pending_from_mneme_decorator.rb +44 -0
  14. data/app/decorators/pending_message_decorator.rb +94 -0
  15. data/app/decorators/pending_subagent_decorator.rb +46 -0
  16. data/app/decorators/pending_tool_response_decorator.rb +51 -0
  17. data/app/decorators/pending_user_message_decorator.rb +22 -0
  18. data/app/decorators/system_message_decorator.rb +5 -0
  19. data/app/decorators/tool_call_decorator.rb +16 -5
  20. data/app/decorators/tool_response_decorator.rb +2 -2
  21. data/app/decorators/user_message_decorator.rb +7 -2
  22. data/app/jobs/count_tokens_job.rb +23 -0
  23. data/app/jobs/drain_job.rb +169 -0
  24. data/app/jobs/melete_enrichment_job/goal_change_listener.rb +52 -0
  25. data/app/jobs/melete_enrichment_job.rb +48 -0
  26. data/app/jobs/mneme_enrichment_job.rb +46 -0
  27. data/app/jobs/tool_execution_job.rb +87 -0
  28. data/app/models/concerns/token_estimation.rb +54 -0
  29. data/app/models/goal.rb +23 -11
  30. data/app/models/message.rb +46 -48
  31. data/app/models/pending_message.rb +407 -12
  32. data/app/models/pinned_message.rb +8 -3
  33. data/app/models/session.rb +660 -566
  34. data/app/models/snapshot.rb +11 -21
  35. data/bin/inspect-cassette +157 -0
  36. data/bin/release +212 -0
  37. data/bin/with-llms +20 -0
  38. data/config/application.rb +1 -0
  39. data/config/database.yml +1 -0
  40. data/config/initializers/event_subscribers.rb +71 -4
  41. data/config/initializers/inflections.rb +3 -1
  42. data/db/cable_structure.sql +9 -0
  43. data/db/migrate/20260330120000_add_source_to_pending_messages.rb +8 -0
  44. data/db/migrate/20260401180000_add_api_metrics_to_messages.rb +7 -0
  45. data/db/migrate/20260401210935_remove_recalled_message_ids_from_sessions.rb +5 -0
  46. data/db/migrate/20260403080031_add_initial_cwd_to_sessions.rb +5 -0
  47. data/db/migrate/20260407170803_remove_viewport_message_ids_from_sessions.rb +5 -0
  48. data/db/migrate/20260407180400_remove_mneme_snapshot_pointer_columns_from_sessions.rb +6 -0
  49. data/db/migrate/20260411120553_add_token_count_to_pinned_messages.rb +5 -0
  50. data/db/migrate/20260411172926_remove_active_skills_and_workflow_from_sessions.rb +6 -0
  51. data/db/migrate/20260412110625_replace_processing_with_aasm_state.rb +6 -0
  52. data/db/migrate/20260418150323_add_kind_and_message_type_to_pending_messages.rb +6 -0
  53. data/db/migrate/20260419120000_add_drain_fields_to_pending_messages.rb +7 -0
  54. data/db/migrate/20260419130000_drop_pending_messages_kind_default.rb +5 -0
  55. data/db/migrate/20260419140000_add_drain_indexes_to_pending_messages.rb +8 -0
  56. data/db/migrate/20260420100000_add_hud_visibility_to_sessions.rb +15 -0
  57. data/db/queue_structure.sql +61 -0
  58. data/db/structure.sql +133 -0
  59. data/lib/agents/registry.rb +1 -1
  60. data/lib/anima/cli.rb +41 -13
  61. data/lib/anima/installer.rb +13 -0
  62. data/lib/anima/settings.rb +16 -36
  63. data/lib/anima/version.rb +1 -1
  64. data/lib/events/authentication_required.rb +24 -0
  65. data/lib/events/bounce_back.rb +4 -4
  66. data/lib/events/eviction_completed.rb +28 -0
  67. data/lib/events/goal_created.rb +28 -0
  68. data/lib/events/goal_updated.rb +32 -0
  69. data/lib/events/llm_responded.rb +35 -0
  70. data/lib/events/message_created.rb +27 -0
  71. data/lib/events/message_updated.rb +25 -0
  72. data/lib/events/session_state_changed.rb +30 -0
  73. data/lib/events/skill_activated.rb +28 -0
  74. data/lib/events/start_melete.rb +36 -0
  75. data/lib/events/start_mneme.rb +33 -0
  76. data/lib/events/start_processing.rb +32 -0
  77. data/lib/events/subagent_evicted.rb +31 -0
  78. data/lib/events/subscribers/active_state_broadcaster.rb +27 -0
  79. data/lib/events/subscribers/authentication_broadcaster.rb +34 -0
  80. data/lib/events/subscribers/drain_kickoff.rb +20 -0
  81. data/lib/events/subscribers/eviction_broadcaster.rb +26 -0
  82. data/lib/events/subscribers/llm_response_handler.rb +111 -0
  83. data/lib/events/subscribers/melete_kickoff.rb +24 -0
  84. data/lib/events/subscribers/message_broadcaster.rb +34 -0
  85. data/lib/events/subscribers/mneme_kickoff.rb +24 -0
  86. data/lib/events/subscribers/mneme_scheduler.rb +21 -0
  87. data/lib/events/subscribers/persister.rb +8 -9
  88. data/lib/events/subscribers/session_state_broadcaster.rb +33 -0
  89. data/lib/events/subscribers/subagent_message_router.rb +28 -34
  90. data/lib/events/subscribers/subagent_visibility_broadcaster.rb +33 -0
  91. data/lib/events/subscribers/tool_response_creator.rb +33 -0
  92. data/lib/events/subscribers/transient_broadcaster.rb +1 -1
  93. data/lib/events/tool_executed.rb +34 -0
  94. data/lib/events/workflow_activated.rb +27 -0
  95. data/lib/llm/client.rb +46 -199
  96. data/lib/mcp/client_manager.rb +41 -46
  97. data/lib/mcp/stdio_transport.rb +9 -5
  98. data/lib/{analytical_brain → melete}/runner.rb +73 -68
  99. data/lib/{analytical_brain → melete}/tools/activate_skill.rb +3 -3
  100. data/lib/{analytical_brain → melete}/tools/assign_nickname.rb +3 -3
  101. data/lib/{analytical_brain → melete}/tools/everything_is_ready.rb +2 -2
  102. data/lib/{analytical_brain → melete}/tools/finish_goal.rb +6 -3
  103. data/lib/melete/tools/goal_messaging.rb +29 -0
  104. data/lib/{analytical_brain → melete}/tools/read_workflow.rb +4 -4
  105. data/lib/{analytical_brain → melete}/tools/rename_session.rb +3 -3
  106. data/lib/{analytical_brain → melete}/tools/set_goal.rb +6 -2
  107. data/lib/{analytical_brain → melete}/tools/update_goal.rb +9 -5
  108. data/lib/{analytical_brain.rb → melete.rb} +6 -3
  109. data/lib/mneme/base_runner.rb +121 -0
  110. data/lib/mneme/l2_runner.rb +14 -20
  111. data/lib/mneme/recall_runner.rb +132 -0
  112. data/lib/mneme/runner.rb +123 -165
  113. data/lib/mneme/search.rb +104 -62
  114. data/lib/mneme/tools/nothing_to_surface.rb +25 -0
  115. data/lib/mneme/tools/save_snapshot.rb +2 -10
  116. data/lib/mneme/tools/surface_memory.rb +89 -0
  117. data/lib/mneme.rb +11 -5
  118. data/lib/providers/anthropic.rb +112 -7
  119. data/lib/shell_session.rb +290 -432
  120. data/lib/skills/definition.rb +2 -2
  121. data/lib/skills/registry.rb +1 -1
  122. data/lib/tools/base.rb +16 -1
  123. data/lib/tools/bash.rb +25 -55
  124. data/lib/tools/edit.rb +2 -0
  125. data/lib/tools/mark_goal_completed.rb +4 -5
  126. data/lib/tools/read.rb +2 -0
  127. data/lib/tools/registry.rb +85 -4
  128. data/lib/tools/response_truncator.rb +1 -1
  129. data/lib/tools/{recall.rb → search_messages.rb} +19 -21
  130. data/lib/tools/spawn_specialist.rb +22 -14
  131. data/lib/tools/spawn_subagent.rb +30 -20
  132. data/lib/tools/subagent_prompts.rb +17 -19
  133. data/lib/tools/think.rb +1 -1
  134. data/lib/tools/{remember.rb → view_messages.rb} +10 -10
  135. data/lib/tools/write.rb +2 -0
  136. data/lib/tui/app.rb +393 -149
  137. data/lib/tui/braille_spinner.rb +7 -7
  138. data/lib/tui/cable_client.rb +9 -16
  139. data/lib/tui/decorators/base_decorator.rb +47 -6
  140. data/lib/tui/decorators/bash_decorator.rb +1 -1
  141. data/lib/tui/decorators/edit_decorator.rb +4 -2
  142. data/lib/tui/decorators/read_decorator.rb +4 -2
  143. data/lib/tui/decorators/think_decorator.rb +2 -2
  144. data/lib/tui/decorators/web_get_decorator.rb +1 -1
  145. data/lib/tui/decorators/write_decorator.rb +4 -2
  146. data/lib/tui/flash.rb +19 -14
  147. data/lib/tui/formatting.rb +20 -9
  148. data/lib/tui/input_buffer.rb +6 -6
  149. data/lib/tui/message_store.rb +165 -28
  150. data/lib/tui/performance_logger.rb +2 -3
  151. data/lib/tui/screens/chat.rb +149 -79
  152. data/lib/tui/settings.rb +93 -0
  153. data/lib/workflows/definition.rb +3 -3
  154. data/lib/workflows/registry.rb +1 -1
  155. data/skills/github.md +38 -0
  156. data/templates/config.toml +16 -32
  157. data/templates/tui.toml +209 -0
  158. data/workflows/review_pr.md +18 -14
  159. metadata +98 -29
  160. data/app/jobs/agent_request_job.rb +0 -199
  161. data/app/jobs/analytical_brain_job.rb +0 -33
  162. data/app/jobs/count_message_tokens_job.rb +0 -39
  163. data/app/jobs/passive_recall_job.rb +0 -29
  164. data/app/models/concerns/message/broadcasting.rb +0 -85
  165. data/config/initializers/fts5_schema_dump.rb +0 -21
  166. data/lib/agent_loop.rb +0 -186
  167. data/lib/analytical_brain/tools/deactivate_skill.rb +0 -39
  168. data/lib/analytical_brain/tools/deactivate_workflow.rb +0 -34
  169. data/lib/environment_probe.rb +0 -232
  170. data/lib/events/agent_message.rb +0 -11
  171. data/lib/events/subscribers/message_collector.rb +0 -64
  172. data/lib/events/tool_call.rb +0 -31
  173. data/lib/events/tool_response.rb +0 -33
  174. data/lib/mneme/compressed_viewport.rb +0 -200
  175. data/lib/mneme/passive_recall.rb +0 -69
@@ -6,39 +6,37 @@ module Tools
6
6
  module SubagentPrompts
7
7
  # Prepended to every sub-agent's stored prompt after nickname assignment.
8
8
  # Establishes identity before any other instruction.
9
- IDENTITY_TEMPLATE = "You are @%s, a sub-agent of the primary agent."
9
+ IDENTITY_TEMPLATE = "You are %s, a sub-agent of the primary agent."
10
10
 
11
11
  COMMUNICATION_INSTRUCTION = "Your messages reach the parent automatically. " \
12
12
  "Ask if you need clarification — the parent can reply."
13
13
 
14
- # Framing message inserted as the sub-agent's first user message.
15
- # This is the "brake" between inherited parent context and the sub-agent's
16
- # own task — without it, the model continues the parent's trajectory.
17
- FORK_FRAMING_MESSAGE = "You were spawned to help with a single task. " \
18
- "The messages above are the parent agent's context — background for your work, " \
19
- "but the parent's goals are not yours. " \
20
- "Your sole task is described in your Goal."
21
-
22
14
  private
23
15
 
24
- # Creates the sub-agent's Goal from the task description and inserts
25
- # the framing message as the first user message.
16
+ # Creates the sub-agent's Goal from the task description, inserts the
17
+ # task as the first user message, and pins it to the Goal so it survives
18
+ # viewport eviction for as long as the Goal is active.
26
19
  #
27
20
  # @param child [Session] the newly created child session
28
- # @param task [String] the task description to pin as the sole Goal
21
+ # @param task [String] the task description
29
22
  # @return [void]
30
- def pin_goal_and_frame(child, task)
31
- child.goals.create!(description: task)
32
- child.create_user_message(FORK_FRAMING_MESSAGE)
23
+ def create_goal_with_pinned_task(child, task)
24
+ goal = child.goals.create!(description: task)
25
+ message = child.create_user_message(task)
26
+ pin = PinnedMessage.create!(
27
+ message: message,
28
+ display_text: task.truncate(PinnedMessage::MAX_DISPLAY_TEXT_LENGTH)
29
+ )
30
+ GoalPinnedMessage.create!(goal: goal, pinned_message: pin)
33
31
  end
34
32
 
35
- # Runs the analytical brain synchronously to assign a nickname,
33
+ # Runs Melete synchronously to assign a nickname,
36
34
  # then prepends identity context to the stored prompt.
37
35
  # Falls back to a sequential "agent-N" name on any failure.
38
36
  # Identity injection runs in +ensure+ so it applies to both
39
- # brain-assigned and fallback nicknames.
40
- def assign_nickname_via_brain(child)
41
- AnalyticalBrain::Runner.new(child).call
37
+ # Melete-assigned and fallback nicknames.
38
+ def assign_nickname_via_melete(child)
39
+ Melete::Runner.new(child).call
42
40
  child.reload
43
41
  rescue => error
44
42
  Rails.logger.warn("Sub-agent nickname assignment failed: #{error.message}")
data/lib/tools/think.rb CHANGED
@@ -5,7 +5,7 @@ module Tools
5
5
  # pause between tool calls where the agent can organize thoughts, plan
6
6
  # next steps, or make decisions without interrupting the user.
7
7
  #
8
- # Think events bridge the gap between the analytical brain (subconscious
8
+ # Think events bridge the gap between Melete (subconscious
9
9
  # background processing) and speech (user-facing messages). Without this
10
10
  # tool, reasoning leaks into tool arguments as comments.
11
11
  #
@@ -1,21 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tools
4
- # Fractal-resolution zoom into message history. Returns a window centered
5
- # on a target message with full detail at the center and compressed context
6
- # at the edges — sharp fovea, blurry periphery.
4
+ # Fractal-resolution window into long-term memory. Given a message_id,
5
+ # returns the surrounding conversation with full detail at the center
6
+ # and compressed snapshots at the edges — sharp fovea, blurry periphery.
7
7
  #
8
8
  # Output structure:
9
9
  # [Previous snapshots — compressed context before]
10
10
  # [Messages N-M — full detail, tool_responses compressed to checkmarks]
11
11
  # [Following snapshots — compressed context after]
12
12
  #
13
- # The agent discovers target messages via FTS5 search results embedded in
14
- # viewport recall snippets. This tool drills down into the full context.
13
+ # Aoide discovers target message IDs via {SearchMessages} and drills
14
+ # down here to recover the full context around any moment.
15
15
  #
16
16
  # @example
17
- # remember(message_id: 42)
18
- class Remember < Base
17
+ # view_messages(message_id: 42)
18
+ class ViewMessages < Base
19
19
  # Messages around the target to include at full resolution.
20
20
  # ±10 messages provides sharp foveal detail while keeping output readable.
21
21
  CONTEXT_WINDOW = 20
@@ -26,9 +26,9 @@ module Tools
26
26
  "system_message" => "System"
27
27
  }.freeze
28
28
 
29
- def self.tool_name = "remember"
29
+ def self.tool_name = "view_messages"
30
30
 
31
- def self.description = "Recall the full conversation around a past message."
31
+ def self.description = "View the full conversation around a message in long-term memory. Pass a message_id — typically one returned by search_messages — to see the surrounding exchange with compressed snapshots at the edges."
32
32
 
33
33
  def self.input_schema
34
34
  {
@@ -112,7 +112,7 @@ module Tools
112
112
  # @return [Array<Message>] chronologically ordered
113
113
  def fetch_center_messages(target, target_session)
114
114
  half = CONTEXT_WINDOW / 2
115
- scope = target_session.messages.context_messages
115
+ scope = target_session.messages
116
116
  target_id = target.id
117
117
 
118
118
  before = scope.where("id <= ?", target_id).reorder(id: :desc).limit(half + 1).to_a.reverse
data/lib/tools/write.rb CHANGED
@@ -19,6 +19,8 @@ module Tools
19
19
 
20
20
  def self.description = "Write file."
21
21
 
22
+ def self.prompt_snippet = "Create or overwrite a whole file."
23
+
22
24
  def self.input_schema
23
25
  {
24
26
  type: "object",