anima-core 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/.reek.yml +61 -0
  4. data/README.md +202 -116
  5. data/anima-core.gemspec +4 -1
  6. data/app/channels/session_channel.rb +44 -10
  7. data/app/decorators/agent_message_decorator.rb +6 -0
  8. data/app/decorators/event_decorator.rb +41 -7
  9. data/app/decorators/tool_call_decorator.rb +66 -5
  10. data/app/decorators/tool_decorator.rb +57 -0
  11. data/app/decorators/tool_response_decorator.rb +35 -5
  12. data/app/decorators/user_message_decorator.rb +6 -0
  13. data/app/decorators/web_get_tool_decorator.rb +102 -0
  14. data/app/jobs/agent_request_job.rb +95 -20
  15. data/app/jobs/mneme_job.rb +51 -0
  16. data/app/jobs/passive_recall_job.rb +29 -0
  17. data/app/models/concerns/event/broadcasting.rb +18 -0
  18. data/app/models/event.rb +10 -0
  19. data/app/models/goal.rb +27 -0
  20. data/app/models/goal_pinned_event.rb +11 -0
  21. data/app/models/pinned_event.rb +41 -0
  22. data/app/models/session.rb +335 -6
  23. data/app/models/snapshot.rb +76 -0
  24. data/config/initializers/event_subscribers.rb +14 -3
  25. data/config/initializers/fts5_schema_dump.rb +21 -0
  26. data/db/migrate/20260316094817_add_interrupt_requested_to_sessions.rb +5 -0
  27. data/db/migrate/20260321080000_create_mneme_schema.rb +32 -0
  28. data/db/migrate/20260321120000_create_pinned_events.rb +27 -0
  29. data/db/migrate/20260321140000_create_events_fts_index.rb +77 -0
  30. data/db/migrate/20260321140100_add_recalled_event_ids_to_sessions.rb +10 -0
  31. data/lib/agent_loop.rb +67 -18
  32. data/lib/analytical_brain/runner.rb +159 -84
  33. data/lib/analytical_brain/tools/assign_nickname.rb +76 -0
  34. data/lib/analytical_brain/tools/finish_goal.rb +6 -1
  35. data/lib/anima/cli.rb +34 -1
  36. data/lib/anima/config_migrator.rb +205 -0
  37. data/lib/anima/installer.rb +13 -130
  38. data/lib/anima/settings.rb +42 -1
  39. data/lib/anima/version.rb +1 -1
  40. data/lib/events/bounce_back.rb +37 -0
  41. data/lib/events/subscribers/agent_dispatcher.rb +29 -0
  42. data/lib/events/subscribers/persister.rb +17 -0
  43. data/lib/events/subscribers/subagent_message_router.rb +102 -0
  44. data/lib/events/subscribers/transient_broadcaster.rb +36 -0
  45. data/lib/llm/client.rb +99 -14
  46. data/lib/mneme/compressed_viewport.rb +200 -0
  47. data/lib/mneme/l2_runner.rb +138 -0
  48. data/lib/mneme/passive_recall.rb +69 -0
  49. data/lib/mneme/runner.rb +254 -0
  50. data/lib/mneme/search.rb +150 -0
  51. data/lib/mneme/tools/attach_events_to_goals.rb +107 -0
  52. data/lib/mneme/tools/everything_ok.rb +24 -0
  53. data/lib/mneme/tools/save_snapshot.rb +68 -0
  54. data/lib/mneme.rb +29 -0
  55. data/lib/providers/anthropic.rb +57 -13
  56. data/lib/shell_session.rb +188 -59
  57. data/lib/tasks/fts5.rake +6 -0
  58. data/lib/tools/remember.rb +179 -0
  59. data/lib/tools/spawn_specialist.rb +21 -9
  60. data/lib/tools/spawn_subagent.rb +22 -11
  61. data/lib/tools/subagent_prompts.rb +20 -3
  62. data/lib/tools/think.rb +57 -0
  63. data/lib/tools/web_get.rb +15 -6
  64. data/lib/tui/app.rb +230 -127
  65. data/lib/tui/cable_client.rb +8 -0
  66. data/lib/tui/decorators/base_decorator.rb +165 -0
  67. data/lib/tui/decorators/bash_decorator.rb +20 -0
  68. data/lib/tui/decorators/edit_decorator.rb +19 -0
  69. data/lib/tui/decorators/read_decorator.rb +24 -0
  70. data/lib/tui/decorators/think_decorator.rb +36 -0
  71. data/lib/tui/decorators/web_get_decorator.rb +19 -0
  72. data/lib/tui/decorators/write_decorator.rb +19 -0
  73. data/lib/tui/flash.rb +139 -0
  74. data/lib/tui/formatting.rb +28 -0
  75. data/lib/tui/height_map.rb +93 -0
  76. data/lib/tui/message_store.rb +25 -1
  77. data/lib/tui/performance_logger.rb +90 -0
  78. data/lib/tui/screens/chat.rb +374 -109
  79. data/templates/config.toml +156 -0
  80. metadata +87 -4
  81. data/CHANGELOG.md +0 -79
  82. data/Gemfile +0 -17
  83. data/lib/tools/return_result.rb +0 -81
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+
5
+ module TUI
6
+ # Frame-level performance logger for TUI render profiling.
7
+ #
8
+ # When enabled via `--debug`, logs timing data for each render phase
9
+ # to `log/tui_performance.log`. Each frame produces one log line with
10
+ # phase durations in milliseconds, enabling bottleneck identification.
11
+ #
12
+ # Uses monotonic clock to avoid wall-clock jitter.
13
+ #
14
+ # @example
15
+ # logger = PerformanceLogger.new(enabled: true)
16
+ # logger.start_frame
17
+ # logger.measure(:build_lines) { build_message_lines(tui) }
18
+ # logger.measure(:line_count) { widget.line_count(width) }
19
+ # logger.end_frame
20
+ class PerformanceLogger
21
+ LOG_PATH = "log/tui_performance.log"
22
+
23
+ # @param enabled [Boolean] whether to actually log (no-op when false)
24
+ def initialize(enabled: false)
25
+ @enabled = enabled
26
+ @phases = {}
27
+ @frame_start = nil
28
+ @frame_count = 0
29
+ @logger = nil
30
+
31
+ return unless @enabled
32
+
33
+ @logger = Logger.new(LOG_PATH, 1, 5 * 1024 * 1024) # 5MB rotation
34
+ @logger.formatter = proc { |_sev, time, _prog, msg| "#{time.strftime("%H:%M:%S.%L")} #{msg}\n" }
35
+ @logger.info("TUI Performance Logger started — pid=#{Process.pid}")
36
+ end
37
+
38
+ # @return [Boolean] true when logging is active
39
+ def enabled?
40
+ @enabled
41
+ end
42
+
43
+ # Marks the beginning of a render frame.
44
+ def start_frame
45
+ return unless @enabled
46
+
47
+ @frame_start = monotonic_now
48
+ @phases = {}
49
+ end
50
+
51
+ # Measures a named phase within the current frame.
52
+ # Returns the block's result so it can be used inline.
53
+ #
54
+ # @param name [Symbol] phase name (e.g. :build_lines, :line_count)
55
+ # @yield the code to measure
56
+ # @return [Object] the block's return value
57
+ def measure(name)
58
+ return yield unless @enabled
59
+
60
+ start = monotonic_now
61
+ result = yield
62
+ @phases[name] = ((monotonic_now - start) * 1000).round(2)
63
+ result
64
+ end
65
+
66
+ # Logs the completed frame with all phase timings.
67
+ def end_frame
68
+ return unless @enabled
69
+
70
+ total = ((monotonic_now - @frame_start) * 1000).round(2)
71
+ @frame_count += 1
72
+
73
+ parts = @phases.map { |name, ms| "#{name}=#{ms}ms" }
74
+ @logger.info("frame=#{@frame_count} total=#{total}ms #{parts.join(" ")}")
75
+ end
76
+
77
+ # Logs a one-off informational message (e.g. cache hit/miss).
78
+ #
79
+ # @param message [String]
80
+ def info(message)
81
+ @logger&.info(message)
82
+ end
83
+
84
+ private
85
+
86
+ def monotonic_now
87
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
88
+ end
89
+ end
90
+ end