anima-core 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +34 -0
- data/README.md +20 -32
- data/anima-core.gemspec +1 -0
- data/app/channels/session_channel.rb +220 -26
- data/app/decorators/agent_message_decorator.rb +24 -0
- data/app/decorators/application_decorator.rb +6 -0
- data/app/decorators/event_decorator.rb +173 -0
- data/app/decorators/system_message_decorator.rb +21 -0
- data/app/decorators/tool_call_decorator.rb +48 -0
- data/app/decorators/tool_response_decorator.rb +37 -0
- data/app/decorators/user_message_decorator.rb +35 -0
- data/app/jobs/agent_request_job.rb +31 -2
- data/app/jobs/count_event_tokens_job.rb +14 -3
- data/app/models/concerns/event/broadcasting.rb +63 -0
- data/app/models/event.rb +36 -0
- data/app/models/session.rb +46 -14
- data/config/application.rb +1 -0
- data/config/initializers/event_subscribers.rb +0 -1
- data/config/routes.rb +0 -6
- data/db/cable_schema.rb +14 -2
- data/db/migrate/20260312170000_add_view_mode_to_sessions.rb +7 -0
- data/db/migrate/20260313010000_add_status_to_events.rb +8 -0
- data/db/migrate/20260313020000_add_processing_to_sessions.rb +7 -0
- data/lib/agent_loop.rb +5 -2
- data/lib/anima/cli.rb +1 -40
- data/lib/anima/version.rb +1 -1
- data/lib/events/subscribers/persister.rb +1 -0
- data/lib/events/user_message.rb +17 -0
- data/lib/providers/anthropic.rb +3 -13
- data/lib/tools/edit.rb +227 -0
- data/lib/tools/read.rb +152 -0
- data/lib/tools/write.rb +86 -0
- data/lib/tui/app.rb +831 -55
- data/lib/tui/cable_client.rb +79 -31
- data/lib/tui/input_buffer.rb +181 -0
- data/lib/tui/message_store.rb +162 -14
- data/lib/tui/screens/chat.rb +504 -75
- metadata +30 -5
- data/app/controllers/api/sessions_controller.rb +0 -25
- data/lib/events/subscribers/action_cable_bridge.rb +0 -35
- data/lib/tui/screens/anthropic.rb +0 -25
- data/lib/tui/screens/settings.rb +0 -52
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: anima-core
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yevhenii Hurin
|
|
@@ -9,6 +9,20 @@ bindir: exe
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: draper
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '4.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '4.0'
|
|
12
26
|
- !ruby/object:Gem::Dependency
|
|
13
27
|
name: foreman
|
|
14
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -155,12 +169,19 @@ files:
|
|
|
155
169
|
- app/channels/application_cable/channel.rb
|
|
156
170
|
- app/channels/application_cable/connection.rb
|
|
157
171
|
- app/channels/session_channel.rb
|
|
158
|
-
- app/controllers/api/sessions_controller.rb
|
|
159
172
|
- app/controllers/application_controller.rb
|
|
173
|
+
- app/decorators/agent_message_decorator.rb
|
|
174
|
+
- app/decorators/application_decorator.rb
|
|
175
|
+
- app/decorators/event_decorator.rb
|
|
176
|
+
- app/decorators/system_message_decorator.rb
|
|
177
|
+
- app/decorators/tool_call_decorator.rb
|
|
178
|
+
- app/decorators/tool_response_decorator.rb
|
|
179
|
+
- app/decorators/user_message_decorator.rb
|
|
160
180
|
- app/jobs/agent_request_job.rb
|
|
161
181
|
- app/jobs/application_job.rb
|
|
162
182
|
- app/jobs/count_event_tokens_job.rb
|
|
163
183
|
- app/models/application_record.rb
|
|
184
|
+
- app/models/concerns/event/broadcasting.rb
|
|
164
185
|
- app/models/event.rb
|
|
165
186
|
- app/models/session.rb
|
|
166
187
|
- bin/jobs
|
|
@@ -189,6 +210,9 @@ files:
|
|
|
189
210
|
- db/migrate/20260308140000_remove_position_from_events.rb
|
|
190
211
|
- db/migrate/20260308150000_add_token_count_to_events.rb
|
|
191
212
|
- db/migrate/20260308160000_add_tool_use_id_to_events.rb
|
|
213
|
+
- db/migrate/20260312170000_add_view_mode_to_sessions.rb
|
|
214
|
+
- db/migrate/20260313010000_add_status_to_events.rb
|
|
215
|
+
- db/migrate/20260313020000_add_processing_to_sessions.rb
|
|
192
216
|
- db/queue_schema.rb
|
|
193
217
|
- db/seeds.rb
|
|
194
218
|
- exe/anima
|
|
@@ -201,7 +225,6 @@ files:
|
|
|
201
225
|
- lib/events/base.rb
|
|
202
226
|
- lib/events/bus.rb
|
|
203
227
|
- lib/events/subscriber.rb
|
|
204
|
-
- lib/events/subscribers/action_cable_bridge.rb
|
|
205
228
|
- lib/events/subscribers/message_collector.rb
|
|
206
229
|
- lib/events/subscribers/persister.rb
|
|
207
230
|
- lib/events/system_message.rb
|
|
@@ -213,14 +236,16 @@ files:
|
|
|
213
236
|
- lib/shell_session.rb
|
|
214
237
|
- lib/tools/base.rb
|
|
215
238
|
- lib/tools/bash.rb
|
|
239
|
+
- lib/tools/edit.rb
|
|
240
|
+
- lib/tools/read.rb
|
|
216
241
|
- lib/tools/registry.rb
|
|
217
242
|
- lib/tools/web_get.rb
|
|
243
|
+
- lib/tools/write.rb
|
|
218
244
|
- lib/tui/app.rb
|
|
219
245
|
- lib/tui/cable_client.rb
|
|
246
|
+
- lib/tui/input_buffer.rb
|
|
220
247
|
- lib/tui/message_store.rb
|
|
221
|
-
- lib/tui/screens/anthropic.rb
|
|
222
248
|
- lib/tui/screens/chat.rb
|
|
223
|
-
- lib/tui/screens/settings.rb
|
|
224
249
|
homepage: https://github.com/hoblin/anima
|
|
225
250
|
licenses:
|
|
226
251
|
- MIT
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Api
|
|
4
|
-
# REST endpoint for session management. The TUI client uses this to
|
|
5
|
-
# obtain a session ID before subscribing to the WebSocket channel.
|
|
6
|
-
class SessionsController < ApplicationController
|
|
7
|
-
# Returns the most recent session or creates one if none exist.
|
|
8
|
-
#
|
|
9
|
-
# GET /api/sessions/current
|
|
10
|
-
# @return [JSON] { id: Integer }
|
|
11
|
-
def current
|
|
12
|
-
session = Session.last || Session.create!
|
|
13
|
-
render json: {id: session.id}
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# Creates a new conversation session.
|
|
17
|
-
#
|
|
18
|
-
# POST /api/sessions
|
|
19
|
-
# @return [JSON] { id: Integer }
|
|
20
|
-
def create
|
|
21
|
-
session = Session.create!
|
|
22
|
-
render json: {id: session.id}, status: :created
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Events
|
|
4
|
-
module Subscribers
|
|
5
|
-
# Forwards EventBus events to Action Cable, bridging internal pub/sub
|
|
6
|
-
# to external WebSocket clients. Each event is broadcast to the
|
|
7
|
-
# session-specific stream (e.g. "session_42"), matching the stream
|
|
8
|
-
# name used by {SessionChannel}.
|
|
9
|
-
#
|
|
10
|
-
# Only events with a valid session_id are broadcast — events without
|
|
11
|
-
# one have no destination channel and are silently skipped.
|
|
12
|
-
#
|
|
13
|
-
# @example
|
|
14
|
-
# Events::Bus.subscribe(Events::Subscribers::ActionCableBridge.instance)
|
|
15
|
-
# # Now all events with session_id flow to "session_<id>" streams
|
|
16
|
-
class ActionCableBridge
|
|
17
|
-
include Events::Subscriber
|
|
18
|
-
include Singleton
|
|
19
|
-
|
|
20
|
-
# Receives a Rails.event notification hash and broadcasts the payload
|
|
21
|
-
# to the session's Action Cable stream.
|
|
22
|
-
#
|
|
23
|
-
# @param event [Hash] with :payload containing event data including :session_id
|
|
24
|
-
def emit(event)
|
|
25
|
-
payload = event[:payload]
|
|
26
|
-
return unless payload.is_a?(Hash)
|
|
27
|
-
|
|
28
|
-
session_id = payload[:session_id]
|
|
29
|
-
return if session_id.nil?
|
|
30
|
-
|
|
31
|
-
ActionCable.server.broadcast("session_#{session_id}", payload)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module TUI
|
|
4
|
-
module Screens
|
|
5
|
-
class Anthropic
|
|
6
|
-
def render(frame, area, tui)
|
|
7
|
-
widget = tui.paragraph(
|
|
8
|
-
text: "Anthropic account connection will be configured here.",
|
|
9
|
-
alignment: :center,
|
|
10
|
-
wrap: true,
|
|
11
|
-
block: tui.block(
|
|
12
|
-
title: "Anthropic Connection",
|
|
13
|
-
titles: [
|
|
14
|
-
{content: "Esc back", position: :bottom, alignment: :center}
|
|
15
|
-
],
|
|
16
|
-
borders: [:all],
|
|
17
|
-
border_type: :rounded,
|
|
18
|
-
border_style: {fg: "magenta"}
|
|
19
|
-
)
|
|
20
|
-
)
|
|
21
|
-
frame.render_widget(widget, area)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
data/lib/tui/screens/settings.rb
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module TUI
|
|
4
|
-
module Screens
|
|
5
|
-
class Settings
|
|
6
|
-
MENU_ITEMS = [
|
|
7
|
-
"General",
|
|
8
|
-
"Appearance",
|
|
9
|
-
"Keybindings"
|
|
10
|
-
].freeze
|
|
11
|
-
|
|
12
|
-
def initialize
|
|
13
|
-
# Initialized on first render — requires tui context from RatatuiRuby.run block
|
|
14
|
-
@list_state = nil
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def render(frame, area, tui)
|
|
18
|
-
@list_state ||= tui.list_state(0)
|
|
19
|
-
|
|
20
|
-
list = tui.list(
|
|
21
|
-
items: MENU_ITEMS,
|
|
22
|
-
highlight_style: {fg: "yellow", bold: true},
|
|
23
|
-
highlight_symbol: "> ",
|
|
24
|
-
block: tui.block(
|
|
25
|
-
title: "Settings",
|
|
26
|
-
titles: [
|
|
27
|
-
{content: "↑/↓ navigate • Esc back", position: :bottom, alignment: :center}
|
|
28
|
-
],
|
|
29
|
-
borders: [:all],
|
|
30
|
-
border_type: :rounded,
|
|
31
|
-
border_style: {fg: "green"}
|
|
32
|
-
)
|
|
33
|
-
)
|
|
34
|
-
frame.render_stateful_widget(list, area, @list_state)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def handle_event(event)
|
|
38
|
-
return false unless @list_state
|
|
39
|
-
|
|
40
|
-
if event.down? || event.j?
|
|
41
|
-
@list_state.select_next
|
|
42
|
-
true
|
|
43
|
-
elsif event.up? || event.k?
|
|
44
|
-
@list_state.select_previous
|
|
45
|
-
true
|
|
46
|
-
else
|
|
47
|
-
false
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|