anima-core 1.4.0 → 1.5.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.
- checksums.yaml +4 -4
- data/.reek.yml +18 -20
- data/README.md +61 -95
- data/agents/thoughts-analyzer.md +12 -7
- data/anima-core.gemspec +1 -0
- data/app/channels/session_channel.rb +38 -58
- data/app/decorators/agent_message_decorator.rb +7 -2
- data/app/decorators/message_decorator.rb +31 -100
- data/app/decorators/pending_from_melete_decorator.rb +36 -0
- data/app/decorators/pending_from_melete_goal_decorator.rb +13 -0
- data/app/decorators/pending_from_melete_skill_decorator.rb +19 -0
- data/app/decorators/pending_from_melete_workflow_decorator.rb +13 -0
- data/app/decorators/pending_from_mneme_decorator.rb +44 -0
- data/app/decorators/pending_message_decorator.rb +94 -0
- data/app/decorators/pending_subagent_decorator.rb +46 -0
- data/app/decorators/pending_tool_response_decorator.rb +51 -0
- data/app/decorators/pending_user_message_decorator.rb +22 -0
- data/app/decorators/system_message_decorator.rb +5 -0
- data/app/decorators/tool_call_decorator.rb +13 -2
- data/app/decorators/tool_response_decorator.rb +2 -2
- data/app/decorators/user_message_decorator.rb +7 -2
- data/app/jobs/count_tokens_job.rb +23 -0
- data/app/jobs/drain_job.rb +169 -0
- data/app/jobs/melete_enrichment_job/goal_change_listener.rb +52 -0
- data/app/jobs/melete_enrichment_job.rb +48 -0
- data/app/jobs/mneme_enrichment_job.rb +46 -0
- data/app/jobs/tool_execution_job.rb +87 -0
- data/app/models/concerns/token_estimation.rb +54 -0
- data/app/models/goal.rb +21 -10
- data/app/models/message.rb +47 -36
- data/app/models/pending_message.rb +276 -29
- data/app/models/pinned_message.rb +8 -3
- data/app/models/session.rb +474 -432
- data/app/models/snapshot.rb +11 -21
- data/bin/inspect-cassette +17 -4
- data/config/application.rb +1 -0
- data/config/initializers/event_subscribers.rb +71 -4
- data/config/initializers/inflections.rb +3 -1
- data/db/cable_structure.sql +3 -3
- data/db/migrate/20260407170803_remove_viewport_message_ids_from_sessions.rb +5 -0
- data/db/migrate/20260407180400_remove_mneme_snapshot_pointer_columns_from_sessions.rb +6 -0
- data/db/migrate/20260411120553_add_token_count_to_pinned_messages.rb +5 -0
- data/db/migrate/20260411172926_remove_active_skills_and_workflow_from_sessions.rb +6 -0
- data/db/migrate/20260412110625_replace_processing_with_aasm_state.rb +6 -0
- data/db/migrate/20260418150323_add_kind_and_message_type_to_pending_messages.rb +6 -0
- data/db/migrate/20260419120000_add_drain_fields_to_pending_messages.rb +7 -0
- data/db/migrate/20260419130000_drop_pending_messages_kind_default.rb +5 -0
- data/db/migrate/20260419140000_add_drain_indexes_to_pending_messages.rb +8 -0
- data/db/migrate/20260420100000_add_hud_visibility_to_sessions.rb +15 -0
- data/db/queue_structure.sql +13 -13
- data/db/structure.sql +44 -31
- data/lib/agents/registry.rb +1 -1
- data/lib/anima/settings.rb +7 -33
- data/lib/anima/version.rb +1 -1
- data/lib/aoide/phantom_call_filter.rb +49 -0
- data/lib/{analytical_brain.rb → aoide.rb} +6 -3
- data/lib/events/authentication_required.rb +24 -0
- data/lib/events/bounce_back.rb +4 -4
- data/lib/events/eviction_completed.rb +28 -0
- data/lib/events/goal_created.rb +28 -0
- data/lib/events/goal_updated.rb +32 -0
- data/lib/events/llm_responded.rb +35 -0
- data/lib/events/message_created.rb +27 -0
- data/lib/events/message_updated.rb +25 -0
- data/lib/events/session_state_changed.rb +30 -0
- data/lib/events/skill_activated.rb +28 -0
- data/lib/events/start_melete.rb +36 -0
- data/lib/events/start_mneme.rb +33 -0
- data/lib/events/start_processing.rb +32 -0
- data/lib/events/subagent_evicted.rb +31 -0
- data/lib/events/subscribers/active_state_broadcaster.rb +27 -0
- data/lib/events/subscribers/authentication_broadcaster.rb +34 -0
- data/lib/events/subscribers/drain_kickoff.rb +20 -0
- data/lib/events/subscribers/eviction_broadcaster.rb +26 -0
- data/lib/events/subscribers/llm_response_handler.rb +145 -0
- data/lib/events/subscribers/melete_kickoff.rb +24 -0
- data/lib/events/subscribers/message_broadcaster.rb +34 -0
- data/lib/events/subscribers/mneme_kickoff.rb +24 -0
- data/lib/events/subscribers/mneme_scheduler.rb +21 -0
- data/lib/events/subscribers/persister.rb +6 -8
- data/lib/events/subscribers/session_state_broadcaster.rb +33 -0
- data/lib/events/subscribers/subagent_message_router.rb +26 -29
- data/lib/events/subscribers/subagent_visibility_broadcaster.rb +33 -0
- data/lib/events/subscribers/tool_response_creator.rb +33 -0
- data/lib/events/subscribers/transient_broadcaster.rb +1 -1
- data/lib/events/tool_executed.rb +34 -0
- data/lib/events/workflow_activated.rb +27 -0
- data/lib/llm/client.rb +41 -201
- data/lib/mcp/client_manager.rb +41 -46
- data/lib/mcp/stdio_transport.rb +9 -5
- data/lib/{analytical_brain → melete}/runner.rb +63 -68
- data/lib/{analytical_brain → melete}/tools/activate_skill.rb +1 -1
- data/lib/{analytical_brain → melete}/tools/assign_nickname.rb +2 -2
- data/lib/{analytical_brain → melete}/tools/everything_is_ready.rb +2 -2
- data/lib/{analytical_brain → melete}/tools/finish_goal.rb +3 -3
- data/lib/{analytical_brain → melete}/tools/goal_messaging.rb +4 -3
- data/lib/{analytical_brain → melete}/tools/read_workflow.rb +2 -2
- data/lib/{analytical_brain → melete}/tools/rename_session.rb +3 -3
- data/lib/{analytical_brain → melete}/tools/set_goal.rb +1 -1
- data/lib/{analytical_brain → melete}/tools/update_goal.rb +4 -4
- data/lib/melete.rb +26 -0
- data/lib/mneme/base_runner.rb +121 -0
- data/lib/mneme/l2_runner.rb +14 -20
- data/lib/mneme/recall_runner.rb +132 -0
- data/lib/mneme/runner.rb +118 -171
- data/lib/mneme/search.rb +104 -62
- data/lib/mneme/tools/nothing_to_surface.rb +25 -0
- data/lib/mneme/tools/save_snapshot.rb +2 -10
- data/lib/mneme/tools/surface_memory.rb +89 -0
- data/lib/mneme.rb +11 -5
- data/lib/shell_session.rb +303 -612
- data/lib/skills/definition.rb +2 -2
- data/lib/skills/registry.rb +1 -1
- data/lib/tools/base.rb +16 -0
- data/lib/tools/bash.rb +25 -57
- data/lib/tools/edit.rb +2 -0
- data/lib/tools/read.rb +2 -0
- data/lib/tools/registry.rb +79 -3
- data/lib/tools/{recall.rb → search_messages.rb} +19 -21
- data/lib/tools/spawn_specialist.rb +20 -10
- data/lib/tools/spawn_subagent.rb +24 -14
- data/lib/tools/subagent_prompts.rb +15 -4
- data/lib/tools/think.rb +1 -1
- data/lib/tools/{remember.rb → view_messages.rb} +10 -10
- data/lib/tools/write.rb +2 -0
- data/lib/tui/app.rb +5 -4
- data/lib/tui/braille_spinner.rb +7 -7
- data/lib/tui/decorators/base_decorator.rb +24 -3
- data/lib/tui/message_store.rb +93 -44
- data/lib/tui/screens/chat.rb +94 -20
- data/lib/tui/settings.rb +9 -2
- data/lib/workflows/definition.rb +3 -3
- data/lib/workflows/registry.rb +1 -1
- data/skills/github.md +38 -0
- data/templates/config.toml +4 -23
- data/workflows/review_pr.md +18 -14
- metadata +88 -28
- data/app/jobs/agent_request_job.rb +0 -199
- data/app/jobs/analytical_brain_job.rb +0 -33
- data/app/jobs/count_message_tokens_job.rb +0 -39
- data/app/jobs/passive_recall_job.rb +0 -24
- data/app/models/concerns/message/broadcasting.rb +0 -86
- data/lib/agent_loop.rb +0 -215
- data/lib/analytical_brain/tools/deactivate_skill.rb +0 -40
- data/lib/analytical_brain/tools/deactivate_workflow.rb +0 -35
- data/lib/events/agent_message.rb +0 -25
- data/lib/events/subscribers/message_collector.rb +0 -64
- data/lib/events/tool_call.rb +0 -31
- data/lib/events/tool_response.rb +0 -33
- data/lib/mneme/compressed_viewport.rb +0 -204
- data/lib/mneme/passive_recall.rb +0 -138
data/app/models/snapshot.rb
CHANGED
|
@@ -18,8 +18,12 @@
|
|
|
18
18
|
# @!attribute level
|
|
19
19
|
# @return [Integer] compression level (1 = from raw messages, 2 = from L1 snapshots)
|
|
20
20
|
# @!attribute token_count
|
|
21
|
-
# @return [Integer]
|
|
21
|
+
# @return [Integer] token count of the summary text. Seeded with a
|
|
22
|
+
# local estimate on create and later refined by {CountTokensJob}
|
|
23
|
+
# using the real Anthropic tokenizer.
|
|
22
24
|
class Snapshot < ApplicationRecord
|
|
25
|
+
include TokenEstimation
|
|
26
|
+
|
|
23
27
|
belongs_to :session
|
|
24
28
|
|
|
25
29
|
# 32KB — generous upper bound (~8K tokens). The LLM tool description advises
|
|
@@ -30,12 +34,17 @@ class Snapshot < ApplicationRecord
|
|
|
30
34
|
validates :from_message_id, presence: true
|
|
31
35
|
validates :to_message_id, presence: true
|
|
32
36
|
validates :level, presence: true, numericality: {greater_than: 0}
|
|
33
|
-
validates :token_count, numericality: {greater_than_or_equal_to: 0}
|
|
37
|
+
validates :token_count, numericality: {greater_than_or_equal_to: 0}
|
|
34
38
|
validate :from_message_id_not_after_to_message_id
|
|
35
39
|
|
|
36
40
|
scope :for_level, ->(level) { where(level: level) }
|
|
37
41
|
scope :chronological, -> { order(:from_message_id) }
|
|
38
42
|
|
|
43
|
+
# @return [String] summary text used for token estimation and remote counting
|
|
44
|
+
def tokenization_text
|
|
45
|
+
text.to_s
|
|
46
|
+
end
|
|
47
|
+
|
|
39
48
|
# L1 snapshots whose message range is NOT fully contained within any L2 snapshot.
|
|
40
49
|
# Used to determine which L1 snapshots are still "live" in the viewport.
|
|
41
50
|
scope :not_covered_by_l2, -> {
|
|
@@ -48,29 +57,10 @@ class Snapshot < ApplicationRecord
|
|
|
48
57
|
)
|
|
49
58
|
}
|
|
50
59
|
|
|
51
|
-
# Snapshots whose source messages have fully evicted from the sliding window.
|
|
52
|
-
# A snapshot is visible when its entire message range precedes the first
|
|
53
|
-
# message currently in the viewport.
|
|
54
|
-
#
|
|
55
|
-
# @param first_message_id [Integer] the first message ID in the sliding window
|
|
56
|
-
scope :source_messages_evicted, ->(first_message_id) {
|
|
57
|
-
where("to_message_id < ?", first_message_id)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
# @return [Integer] token cost, using cached count or heuristic estimate
|
|
61
|
-
def token_cost
|
|
62
|
-
token_count.positive? ? token_count : estimate_tokens
|
|
63
|
-
end
|
|
64
|
-
|
|
65
60
|
private
|
|
66
61
|
|
|
67
62
|
def from_message_id_not_after_to_message_id
|
|
68
63
|
return unless from_message_id && to_message_id
|
|
69
64
|
errors.add(:from_message_id, "must be <= to_message_id") if from_message_id > to_message_id
|
|
70
65
|
end
|
|
71
|
-
|
|
72
|
-
# @return [Integer] estimated token count (at least 1)
|
|
73
|
-
def estimate_tokens
|
|
74
|
-
[(text.bytesize / Message::BYTES_PER_TOKEN.to_f).ceil, 1].max
|
|
75
|
-
end
|
|
76
66
|
end
|
data/bin/inspect-cassette
CHANGED
|
@@ -106,6 +106,8 @@ puts " (#{omitted} non-LLM HTTP requests omitted)" if omitted > 0
|
|
|
106
106
|
puts
|
|
107
107
|
|
|
108
108
|
seen_messages = 0
|
|
109
|
+
previous_first = nil
|
|
110
|
+
|
|
109
111
|
llm_interactions.each_with_index do |interaction, round|
|
|
110
112
|
request_body = JSON.parse(interaction["request"]["body"]["string"])
|
|
111
113
|
messages = request_body["messages"] || []
|
|
@@ -114,17 +116,28 @@ llm_interactions.each_with_index do |interaction, round|
|
|
|
114
116
|
status = interaction["response"]["status"]["code"]
|
|
115
117
|
model = response_body["model"] || request_body["model"]
|
|
116
118
|
|
|
119
|
+
# Detect a new conversation: cassettes can interleave multiple phantom
|
|
120
|
+
# sessions (Mneme, Melete, Aoide's drain) that each keep their own
|
|
121
|
+
# independent message history. When a new round's first message differs
|
|
122
|
+
# from the prior round's, or the round has fewer messages than we've
|
|
123
|
+
# already shown, we've crossed into a new conversation — rewind the
|
|
124
|
+
# dedup counter so we render from the top again.
|
|
125
|
+
first = messages.first
|
|
126
|
+
if round > 0 && (previous_first != first || messages.size < seen_messages)
|
|
127
|
+
puts "─── new conversation ───"
|
|
128
|
+
puts
|
|
129
|
+
seen_messages = 0
|
|
130
|
+
end
|
|
131
|
+
previous_first = first
|
|
132
|
+
|
|
117
133
|
puts "── Round #{round + 1} (#{status} #{model}) ──"
|
|
118
134
|
puts
|
|
119
135
|
|
|
120
|
-
|
|
121
|
-
new_messages = messages[seen_messages..]
|
|
122
|
-
new_messages.each do |msg|
|
|
136
|
+
messages[seen_messages..].to_a.each do |msg|
|
|
123
137
|
puts format_message(msg)
|
|
124
138
|
puts
|
|
125
139
|
end
|
|
126
140
|
|
|
127
|
-
# Print the assistant response from this round
|
|
128
141
|
if response_body["content"]
|
|
129
142
|
assistant_msg = {"role" => "assistant", "content" => response_body["content"]}
|
|
130
143
|
puts format_message(assistant_msg)
|
data/config/application.rb
CHANGED
|
@@ -3,17 +3,84 @@
|
|
|
3
3
|
# Registers global EventBus subscribers at boot time.
|
|
4
4
|
# Subscribers registered here receive all events regardless of which
|
|
5
5
|
# process emitted them (brain server, background job, etc.).
|
|
6
|
+
#
|
|
7
|
+
# Three event layers:
|
|
8
|
+
# 1. Domain events (anima.agent_message, anima.system_message,
|
|
9
|
+
# anima.goal.created, anima.goal.updated, etc.) — raw intent
|
|
10
|
+
# 2. Lifecycle events (anima.message.created) — emitted after persistence
|
|
11
|
+
# 3. Drain pipeline events (anima.session.start_melete, start_mneme,
|
|
12
|
+
# start_processing, llm_responded, tool_executed) — the event-driven
|
|
13
|
+
# agent loop that promotes PendingMessages into the conversation,
|
|
14
|
+
# calls the LLM, and dispatches tool execution (epic #427). Pipeline
|
|
15
|
+
# order: Melete first; Mneme conditional on a goal change during the
|
|
16
|
+
# Melete run; Processing always closes the chain.
|
|
17
|
+
#
|
|
18
|
+
# Persister bridges layer 1 → 2 by creating Message records whose
|
|
19
|
+
# after_create_commit emits MessageCreated events.
|
|
20
|
+
MESSAGE_LIFECYCLE_FILTER = ->(event) { event[:name].start_with?("anima.message.") }
|
|
21
|
+
MESSAGE_CREATED_FILTER = ->(event) { event[:name] == "anima.message.created" }
|
|
22
|
+
EVICTION_FILTER = ->(event) { event[:name] == "anima.eviction.completed" }
|
|
23
|
+
SUBAGENT_EVICTED_FILTER = ->(event) { event[:name] == "anima.subagent.evicted" }
|
|
24
|
+
ACTIVE_STATE_TRIGGER_FILTER = ->(event) {
|
|
25
|
+
%w[anima.skill.activated anima.workflow.activated anima.eviction.completed].include?(event[:name])
|
|
26
|
+
}
|
|
27
|
+
SESSION_STATE_FILTER = ->(event) { event[:name] == "anima.session.state_changed" }
|
|
28
|
+
AUTHENTICATION_REQUIRED_FILTER = ->(event) { event[:name] == "anima.authentication_required" }
|
|
29
|
+
START_MNEME_FILTER = ->(event) { event[:name] == "anima.session.start_mneme" }
|
|
30
|
+
START_MELETE_FILTER = ->(event) { event[:name] == "anima.session.start_melete" }
|
|
31
|
+
START_PROCESSING_FILTER = ->(event) { event[:name] == "anima.session.start_processing" }
|
|
32
|
+
LLM_RESPONDED_FILTER = ->(event) { event[:name] == "anima.session.llm_responded" }
|
|
33
|
+
TOOL_EXECUTED_FILTER = ->(event) { event[:name] == "anima.session.tool_executed" }
|
|
34
|
+
|
|
6
35
|
Rails.application.config.after_initialize do
|
|
36
|
+
# SessionStateBroadcaster also runs in tests — job/channel specs assert
|
|
37
|
+
# ActionCable broadcasts, which now flow through this subscriber.
|
|
38
|
+
Events::Bus.subscribe(Events::Subscribers::SessionStateBroadcaster.new, &SESSION_STATE_FILTER)
|
|
39
|
+
|
|
40
|
+
# AuthenticationBroadcaster turns provider auth failures into a
|
|
41
|
+
# conversation-visible system_message plus a client-side action frame.
|
|
42
|
+
Events::Bus.subscribe(Events::Subscribers::AuthenticationBroadcaster.new, &AUTHENTICATION_REQUIRED_FILTER)
|
|
43
|
+
|
|
44
|
+
# Drain pipeline — registered in all environments so job/channel specs
|
|
45
|
+
# can drive the full event-driven loop end-to-end.
|
|
46
|
+
Events::Bus.subscribe(Events::Subscribers::MnemeKickoff.new, &START_MNEME_FILTER)
|
|
47
|
+
Events::Bus.subscribe(Events::Subscribers::MeleteKickoff.new, &START_MELETE_FILTER)
|
|
48
|
+
Events::Bus.subscribe(Events::Subscribers::DrainKickoff.new, &START_PROCESSING_FILTER)
|
|
49
|
+
Events::Bus.subscribe(Events::Subscribers::LLMResponseHandler.new, &LLM_RESPONDED_FILTER)
|
|
50
|
+
Events::Bus.subscribe(Events::Subscribers::ToolResponseCreator.new, &TOOL_EXECUTED_FILTER)
|
|
51
|
+
|
|
7
52
|
unless Rails.env.test?
|
|
53
|
+
# --- Domain event subscribers (layer 1) ---
|
|
54
|
+
|
|
8
55
|
# Global persister handles events from all sessions (brain server, background jobs).
|
|
9
|
-
# Skips
|
|
10
|
-
# (SessionChannel#speak for idle sessions, AgentLoop#process for direct usage).
|
|
56
|
+
# Skips user messages — those are promoted from PendingMessage by {DrainJob}.
|
|
11
57
|
Events::Bus.subscribe(Events::Subscribers::Persister.new)
|
|
12
58
|
|
|
13
59
|
# Bridges transient events (e.g. BounceBack) to ActionCable for client delivery.
|
|
14
60
|
Events::Bus.subscribe(Events::Subscribers::TransientBroadcaster.new)
|
|
15
61
|
|
|
16
|
-
#
|
|
17
|
-
|
|
62
|
+
# --- Lifecycle event subscribers (layer 2) ---
|
|
63
|
+
|
|
64
|
+
# Broadcasts message creates and updates to connected WebSocket clients.
|
|
65
|
+
Events::Bus.subscribe(Events::Subscribers::MessageBroadcaster.new, &MESSAGE_LIFECYCLE_FILTER)
|
|
66
|
+
|
|
67
|
+
# Routes agent_message Messages between parent and sub-agent sessions
|
|
68
|
+
# via @mentions. Hangs off the Message persistence lifecycle, so every
|
|
69
|
+
# persisted agent_message is a routing opportunity.
|
|
70
|
+
Events::Bus.subscribe(Events::Subscribers::SubagentMessageRouter.new, &MESSAGE_CREATED_FILTER)
|
|
71
|
+
|
|
72
|
+
# Checks whether Mneme should run after each persisted message.
|
|
73
|
+
Events::Bus.subscribe(Events::Subscribers::MnemeScheduler.new, &MESSAGE_CREATED_FILTER)
|
|
74
|
+
|
|
75
|
+
# Broadcasts eviction cutoff to clients after Mneme advances the boundary.
|
|
76
|
+
Events::Bus.subscribe(Events::Subscribers::EvictionBroadcaster.new, &EVICTION_FILTER)
|
|
77
|
+
|
|
78
|
+
# Broadcasts sub-agent HUD removal when eviction takes the last trace
|
|
79
|
+
# of a sub-agent past the Mneme boundary.
|
|
80
|
+
Events::Bus.subscribe(Events::Subscribers::SubagentVisibilityBroadcaster.new, &SUBAGENT_EVICTED_FILTER)
|
|
81
|
+
|
|
82
|
+
# Rebroadcasts active skills/workflow on every event that can change
|
|
83
|
+
# the set: skill activation, workflow activation, or eviction.
|
|
84
|
+
Events::Bus.subscribe(Events::Subscribers::ActiveStateBroadcaster.new, &ACTIVE_STATE_TRIGGER_FILTER)
|
|
18
85
|
end
|
|
19
86
|
end
|
data/db/cable_structure.sql
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
CREATE TABLE
|
|
1
|
+
CREATE TABLE "solid_cable_messages" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "channel" blob(1024) NOT NULL, "channel_hash" integer(8) NOT NULL, "created_at" datetime(6) NOT NULL, "payload" blob(536870912) NOT NULL);
|
|
2
2
|
CREATE INDEX "index_solid_cable_messages_on_channel" ON "solid_cable_messages" ("channel");
|
|
3
3
|
CREATE INDEX "index_solid_cable_messages_on_channel_hash" ON "solid_cable_messages" ("channel_hash");
|
|
4
4
|
CREATE INDEX "index_solid_cable_messages_on_created_at" ON "solid_cable_messages" ("created_at");
|
|
5
|
-
CREATE TABLE
|
|
6
|
-
CREATE TABLE
|
|
5
|
+
CREATE TABLE "schema_migrations" ("version" varchar NOT NULL PRIMARY KEY);
|
|
6
|
+
CREATE TABLE "ar_internal_metadata" ("key" varchar NOT NULL PRIMARY KEY, "value" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
|
|
7
7
|
INSERT INTO "schema_migrations" (version) VALUES
|
|
8
8
|
('1');
|
|
9
9
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
class AddDrainFieldsToPendingMessages < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
add_column :pending_messages, :tool_use_id, :string
|
|
4
|
+
add_column :pending_messages, :success, :boolean
|
|
5
|
+
add_column :pending_messages, :bounce_back, :boolean, default: false, null: false
|
|
6
|
+
end
|
|
7
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
class AddDrainIndexesToPendingMessages < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
add_index :pending_messages, [:session_id, :message_type, :created_at],
|
|
4
|
+
name: "index_pending_messages_on_drain_ordering"
|
|
5
|
+
add_index :pending_messages, [:session_id, :tool_use_id],
|
|
6
|
+
name: "index_pending_messages_on_session_and_tool_use"
|
|
7
|
+
end
|
|
8
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Sub-agent sessions track presence in the parent's HUD panel through the
|
|
4
|
+
# +hud_visible+ boolean. Mneme flips it to +false+ when viewport eviction
|
|
5
|
+
# removes every trace of the sub-agent (spawn pair + response pairs). The
|
|
6
|
+
# +spawn_tool_use_id+ column lets the trace query find the spawn pair
|
|
7
|
+
# directly instead of string-matching the +spawn_subagent+ tool_input.
|
|
8
|
+
class AddHudVisibilityToSessions < ActiveRecord::Migration[8.1]
|
|
9
|
+
def change
|
|
10
|
+
add_column :sessions, :hud_visible, :boolean, default: true, null: false
|
|
11
|
+
add_column :sessions, :spawn_tool_use_id, :string
|
|
12
|
+
|
|
13
|
+
add_index :sessions, [:parent_session_id, :hud_visible]
|
|
14
|
+
end
|
|
15
|
+
end
|
data/db/queue_structure.sql
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
CREATE TABLE
|
|
1
|
+
CREATE TABLE "solid_queue_jobs" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "active_job_id" varchar, "arguments" text, "class_name" varchar NOT NULL, "concurrency_key" varchar, "created_at" datetime(6) NOT NULL, "finished_at" datetime(6), "priority" integer DEFAULT 0 NOT NULL, "queue_name" varchar NOT NULL, "scheduled_at" datetime(6), "updated_at" datetime(6) NOT NULL);
|
|
2
2
|
CREATE INDEX "index_solid_queue_jobs_on_active_job_id" ON "solid_queue_jobs" ("active_job_id");
|
|
3
3
|
CREATE INDEX "index_solid_queue_jobs_on_class_name" ON "solid_queue_jobs" ("class_name");
|
|
4
4
|
CREATE INDEX "index_solid_queue_jobs_on_finished_at" ON "solid_queue_jobs" ("finished_at");
|
|
5
5
|
CREATE INDEX "index_solid_queue_jobs_for_filtering" ON "solid_queue_jobs" ("queue_name", "finished_at");
|
|
6
6
|
CREATE INDEX "index_solid_queue_jobs_for_alerting" ON "solid_queue_jobs" ("scheduled_at", "finished_at");
|
|
7
|
-
CREATE TABLE
|
|
7
|
+
CREATE TABLE "solid_queue_pauses" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime(6) NOT NULL, "queue_name" varchar NOT NULL);
|
|
8
8
|
CREATE UNIQUE INDEX "index_solid_queue_pauses_on_queue_name" ON "solid_queue_pauses" ("queue_name");
|
|
9
|
-
CREATE TABLE
|
|
9
|
+
CREATE TABLE "solid_queue_processes" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime(6) NOT NULL, "hostname" varchar, "kind" varchar NOT NULL, "last_heartbeat_at" datetime(6) NOT NULL, "metadata" text, "name" varchar NOT NULL, "pid" integer NOT NULL, "supervisor_id" bigint);
|
|
10
10
|
CREATE INDEX "index_solid_queue_processes_on_last_heartbeat_at" ON "solid_queue_processes" ("last_heartbeat_at");
|
|
11
11
|
CREATE UNIQUE INDEX "index_solid_queue_processes_on_name_and_supervisor_id" ON "solid_queue_processes" ("name", "supervisor_id");
|
|
12
12
|
CREATE INDEX "index_solid_queue_processes_on_supervisor_id" ON "solid_queue_processes" ("supervisor_id");
|
|
13
|
-
CREATE TABLE
|
|
13
|
+
CREATE TABLE "solid_queue_recurring_tasks" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "arguments" text, "class_name" varchar, "command" varchar(2048), "created_at" datetime(6) NOT NULL, "description" text, "key" varchar NOT NULL, "priority" integer DEFAULT 0, "queue_name" varchar, "schedule" varchar NOT NULL, "static" boolean DEFAULT TRUE NOT NULL, "updated_at" datetime(6) NOT NULL);
|
|
14
14
|
CREATE UNIQUE INDEX "index_solid_queue_recurring_tasks_on_key" ON "solid_queue_recurring_tasks" ("key");
|
|
15
15
|
CREATE INDEX "index_solid_queue_recurring_tasks_on_static" ON "solid_queue_recurring_tasks" ("static");
|
|
16
|
-
CREATE TABLE
|
|
16
|
+
CREATE TABLE "solid_queue_semaphores" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime(6) NOT NULL, "expires_at" datetime(6) NOT NULL, "key" varchar NOT NULL, "updated_at" datetime(6) NOT NULL, "value" integer DEFAULT 1 NOT NULL);
|
|
17
17
|
CREATE INDEX "index_solid_queue_semaphores_on_expires_at" ON "solid_queue_semaphores" ("expires_at");
|
|
18
18
|
CREATE INDEX "index_solid_queue_semaphores_on_key_and_value" ON "solid_queue_semaphores" ("key", "value");
|
|
19
19
|
CREATE UNIQUE INDEX "index_solid_queue_semaphores_on_key" ON "solid_queue_semaphores" ("key");
|
|
20
|
-
CREATE TABLE
|
|
20
|
+
CREATE TABLE "solid_queue_blocked_executions" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "concurrency_key" varchar NOT NULL, "created_at" datetime(6) NOT NULL, "expires_at" datetime(6) NOT NULL, "job_id" bigint NOT NULL, "priority" integer DEFAULT 0 NOT NULL, "queue_name" varchar NOT NULL, CONSTRAINT "fk_rails_4cd34e2228"
|
|
21
21
|
FOREIGN KEY ("job_id")
|
|
22
22
|
REFERENCES "solid_queue_jobs" ("id")
|
|
23
23
|
ON DELETE CASCADE);
|
|
24
24
|
CREATE INDEX "index_solid_queue_blocked_executions_for_release" ON "solid_queue_blocked_executions" ("concurrency_key", "priority", "job_id");
|
|
25
25
|
CREATE INDEX "index_solid_queue_blocked_executions_for_maintenance" ON "solid_queue_blocked_executions" ("expires_at", "concurrency_key");
|
|
26
26
|
CREATE UNIQUE INDEX "index_solid_queue_blocked_executions_on_job_id" ON "solid_queue_blocked_executions" ("job_id");
|
|
27
|
-
CREATE TABLE
|
|
27
|
+
CREATE TABLE "solid_queue_claimed_executions" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime(6) NOT NULL, "job_id" bigint NOT NULL, "process_id" bigint, CONSTRAINT "fk_rails_9cfe4d4944"
|
|
28
28
|
FOREIGN KEY ("job_id")
|
|
29
29
|
REFERENCES "solid_queue_jobs" ("id")
|
|
30
30
|
ON DELETE CASCADE);
|
|
31
31
|
CREATE UNIQUE INDEX "index_solid_queue_claimed_executions_on_job_id" ON "solid_queue_claimed_executions" ("job_id");
|
|
32
32
|
CREATE INDEX "index_solid_queue_claimed_executions_on_process_id_and_job_id" ON "solid_queue_claimed_executions" ("process_id", "job_id");
|
|
33
|
-
CREATE TABLE
|
|
33
|
+
CREATE TABLE "solid_queue_failed_executions" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime(6) NOT NULL, "error" text, "job_id" bigint NOT NULL, CONSTRAINT "fk_rails_39bbc7a631"
|
|
34
34
|
FOREIGN KEY ("job_id")
|
|
35
35
|
REFERENCES "solid_queue_jobs" ("id")
|
|
36
36
|
ON DELETE CASCADE);
|
|
37
37
|
CREATE UNIQUE INDEX "index_solid_queue_failed_executions_on_job_id" ON "solid_queue_failed_executions" ("job_id");
|
|
38
|
-
CREATE TABLE
|
|
38
|
+
CREATE TABLE "solid_queue_ready_executions" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime(6) NOT NULL, "job_id" bigint NOT NULL, "priority" integer DEFAULT 0 NOT NULL, "queue_name" varchar NOT NULL, CONSTRAINT "fk_rails_81fcbd66af"
|
|
39
39
|
FOREIGN KEY ("job_id")
|
|
40
40
|
REFERENCES "solid_queue_jobs" ("id")
|
|
41
41
|
ON DELETE CASCADE);
|
|
42
42
|
CREATE UNIQUE INDEX "index_solid_queue_ready_executions_on_job_id" ON "solid_queue_ready_executions" ("job_id");
|
|
43
43
|
CREATE INDEX "index_solid_queue_poll_all" ON "solid_queue_ready_executions" ("priority", "job_id");
|
|
44
44
|
CREATE INDEX "index_solid_queue_poll_by_queue" ON "solid_queue_ready_executions" ("queue_name", "priority", "job_id");
|
|
45
|
-
CREATE TABLE
|
|
45
|
+
CREATE TABLE "solid_queue_recurring_executions" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime(6) NOT NULL, "job_id" bigint NOT NULL, "run_at" datetime(6) NOT NULL, "task_key" varchar NOT NULL, CONSTRAINT "fk_rails_318a5533ed"
|
|
46
46
|
FOREIGN KEY ("job_id")
|
|
47
47
|
REFERENCES "solid_queue_jobs" ("id")
|
|
48
48
|
ON DELETE CASCADE);
|
|
49
49
|
CREATE UNIQUE INDEX "index_solid_queue_recurring_executions_on_job_id" ON "solid_queue_recurring_executions" ("job_id");
|
|
50
50
|
CREATE UNIQUE INDEX "index_solid_queue_recurring_executions_on_task_key_and_run_at" ON "solid_queue_recurring_executions" ("task_key", "run_at");
|
|
51
|
-
CREATE TABLE
|
|
51
|
+
CREATE TABLE "solid_queue_scheduled_executions" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime(6) NOT NULL, "job_id" bigint NOT NULL, "priority" integer DEFAULT 0 NOT NULL, "queue_name" varchar NOT NULL, "scheduled_at" datetime(6) NOT NULL, CONSTRAINT "fk_rails_c4316f352d"
|
|
52
52
|
FOREIGN KEY ("job_id")
|
|
53
53
|
REFERENCES "solid_queue_jobs" ("id")
|
|
54
54
|
ON DELETE CASCADE);
|
|
55
55
|
CREATE UNIQUE INDEX "index_solid_queue_scheduled_executions_on_job_id" ON "solid_queue_scheduled_executions" ("job_id");
|
|
56
56
|
CREATE INDEX "index_solid_queue_dispatch_all" ON "solid_queue_scheduled_executions" ("scheduled_at", "priority", "job_id");
|
|
57
|
-
CREATE TABLE
|
|
58
|
-
CREATE TABLE
|
|
57
|
+
CREATE TABLE "schema_migrations" ("version" varchar NOT NULL PRIMARY KEY);
|
|
58
|
+
CREATE TABLE "ar_internal_metadata" ("key" varchar NOT NULL PRIMARY KEY, "value" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
|
|
59
59
|
INSERT INTO "schema_migrations" (version) VALUES
|
|
60
60
|
('1');
|
|
61
61
|
|
data/db/structure.sql
CHANGED
|
@@ -1,46 +1,48 @@
|
|
|
1
|
-
CREATE TABLE
|
|
2
|
-
CREATE
|
|
3
|
-
CREATE TABLE
|
|
4
|
-
FOREIGN KEY ("session_id")
|
|
5
|
-
REFERENCES "sessions" ("id")
|
|
6
|
-
, CONSTRAINT "fk_rails_feeb9df31e"
|
|
1
|
+
CREATE TABLE "secrets" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime(6) NOT NULL, "key" varchar NOT NULL, "namespace" varchar NOT NULL, "updated_at" datetime(6) NOT NULL, "value" text NOT NULL);
|
|
2
|
+
CREATE UNIQUE INDEX "index_secrets_on_namespace_and_key" ON "secrets" ("namespace", "key");
|
|
3
|
+
CREATE TABLE "goals" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "completed_at" datetime(6), "created_at" datetime(6) NOT NULL, "description" text NOT NULL, "evicted_at" datetime(6), "parent_goal_id" integer, "session_id" integer NOT NULL, "status" varchar DEFAULT 'active' NOT NULL, "updated_at" datetime(6) NOT NULL, CONSTRAINT "fk_rails_feeb9df31e"
|
|
7
4
|
FOREIGN KEY ("parent_goal_id")
|
|
8
5
|
REFERENCES "goals" ("id")
|
|
6
|
+
, CONSTRAINT "fk_rails_874b7534ae"
|
|
7
|
+
FOREIGN KEY ("session_id")
|
|
8
|
+
REFERENCES "sessions" ("id")
|
|
9
9
|
);
|
|
10
|
-
CREATE INDEX "index_goals_on_session_id" ON "goals" ("session_id");
|
|
11
10
|
CREATE INDEX "index_goals_on_parent_goal_id" ON "goals" ("parent_goal_id");
|
|
12
11
|
CREATE INDEX "index_goals_on_session_id_and_status" ON "goals" ("session_id", "status");
|
|
13
|
-
CREATE
|
|
12
|
+
CREATE INDEX "index_goals_on_session_id" ON "goals" ("session_id");
|
|
13
|
+
CREATE TABLE "schema_migrations" ("version" varchar NOT NULL PRIMARY KEY);
|
|
14
|
+
CREATE TABLE "ar_internal_metadata" ("key" varchar NOT NULL PRIMARY KEY, "value" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
|
|
15
|
+
CREATE TABLE "messages" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "api_metrics" json, "created_at" datetime(6) NOT NULL, "message_type" varchar NOT NULL, "payload" json DEFAULT '{}' NOT NULL, "session_id" integer NOT NULL, "status" varchar, "timestamp" integer(8) NOT NULL, "token_count" integer DEFAULT 0 NOT NULL, "tool_use_id" varchar, "updated_at" datetime(6) NOT NULL, CONSTRAINT "fk_rails_1ee2a92df0"
|
|
14
16
|
FOREIGN KEY ("session_id")
|
|
15
17
|
REFERENCES "sessions" ("id")
|
|
16
18
|
);
|
|
17
19
|
CREATE INDEX "index_messages_on_session_id_and_status" ON "messages" ("session_id", "status");
|
|
18
|
-
CREATE INDEX "index_messages_on_tool_use_id" ON "messages" ("tool_use_id");
|
|
19
20
|
CREATE INDEX "index_messages_on_session_id" ON "messages" ("session_id");
|
|
21
|
+
CREATE INDEX "index_messages_on_tool_use_id" ON "messages" ("tool_use_id");
|
|
20
22
|
CREATE INDEX "index_messages_on_message_type" ON "messages" ("message_type");
|
|
21
23
|
CREATE INDEX "index_messages_on_session_id_and_message_type" ON "messages" ("session_id", "message_type");
|
|
22
|
-
CREATE TABLE
|
|
24
|
+
CREATE TABLE "pinned_messages" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime(6) NOT NULL, "display_text" text NOT NULL, "message_id" integer NOT NULL, "updated_at" datetime(6) NOT NULL, "token_count" integer DEFAULT 0 NOT NULL, CONSTRAINT "fk_rails_4a5f237c43"
|
|
23
25
|
FOREIGN KEY ("message_id")
|
|
24
26
|
REFERENCES "messages" ("id")
|
|
25
27
|
);
|
|
26
28
|
CREATE UNIQUE INDEX "index_pinned_messages_on_message_id" ON "pinned_messages" ("message_id");
|
|
27
|
-
CREATE TABLE
|
|
28
|
-
FOREIGN KEY ("pinned_message_id")
|
|
29
|
-
REFERENCES "pinned_messages" ("id")
|
|
30
|
-
, CONSTRAINT "fk_rails_689fd4bf8a"
|
|
29
|
+
CREATE TABLE "goal_pinned_messages" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime(6) NOT NULL, "goal_id" integer NOT NULL, "pinned_message_id" integer NOT NULL, "updated_at" datetime(6) NOT NULL, CONSTRAINT "fk_rails_689fd4bf8a"
|
|
31
30
|
FOREIGN KEY ("goal_id")
|
|
32
31
|
REFERENCES "goals" ("id")
|
|
32
|
+
, CONSTRAINT "fk_rails_fb51bfeebe"
|
|
33
|
+
FOREIGN KEY ("pinned_message_id")
|
|
34
|
+
REFERENCES "pinned_messages" ("id")
|
|
33
35
|
);
|
|
34
36
|
CREATE INDEX "index_goal_pinned_messages_on_goal_id" ON "goal_pinned_messages" ("goal_id");
|
|
35
|
-
CREATE INDEX "index_goal_pinned_messages_on_pinned_message_id" ON "goal_pinned_messages" ("pinned_message_id");
|
|
36
37
|
CREATE UNIQUE INDEX "index_goal_pinned_messages_on_goal_id_and_pinned_message_id" ON "goal_pinned_messages" ("goal_id", "pinned_message_id");
|
|
37
|
-
CREATE
|
|
38
|
+
CREATE INDEX "index_goal_pinned_messages_on_pinned_message_id" ON "goal_pinned_messages" ("pinned_message_id");
|
|
39
|
+
CREATE TABLE "snapshots" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime(6) NOT NULL, "from_message_id" integer NOT NULL, "level" integer DEFAULT 1 NOT NULL, "session_id" integer NOT NULL, "text" text NOT NULL, "to_message_id" integer NOT NULL, "token_count" integer DEFAULT 0 NOT NULL, "updated_at" datetime(6) NOT NULL, CONSTRAINT "fk_rails_eb2ad51db9"
|
|
38
40
|
FOREIGN KEY ("session_id")
|
|
39
41
|
REFERENCES "sessions" ("id")
|
|
40
42
|
);
|
|
41
|
-
CREATE INDEX "index_snapshots_on_session_id" ON "snapshots" ("session_id");
|
|
42
|
-
CREATE INDEX "index_snapshots_on_session_id_and_level" ON "snapshots" ("session_id", "level");
|
|
43
43
|
CREATE INDEX "index_snapshots_on_session_and_event_range" ON "snapshots" ("session_id", "from_message_id", "to_message_id");
|
|
44
|
+
CREATE INDEX "index_snapshots_on_session_id_and_level" ON "snapshots" ("session_id", "level");
|
|
45
|
+
CREATE INDEX "index_snapshots_on_session_id" ON "snapshots" ("session_id");
|
|
44
46
|
CREATE VIRTUAL TABLE messages_fts USING fts5(
|
|
45
47
|
searchable_text,
|
|
46
48
|
content='',
|
|
@@ -48,10 +50,10 @@ CREATE VIRTUAL TABLE messages_fts USING fts5(
|
|
|
48
50
|
tokenize='porter unicode61'
|
|
49
51
|
)
|
|
50
52
|
/* messages_fts(searchable_text) */;
|
|
51
|
-
CREATE TABLE
|
|
52
|
-
CREATE TABLE
|
|
53
|
-
CREATE TABLE
|
|
54
|
-
CREATE TABLE
|
|
53
|
+
CREATE TABLE 'messages_fts_data'(id INTEGER PRIMARY KEY, block BLOB);
|
|
54
|
+
CREATE TABLE 'messages_fts_idx'(segid, term, pgno, PRIMARY KEY(segid, term)) WITHOUT ROWID;
|
|
55
|
+
CREATE TABLE 'messages_fts_docsize'(id INTEGER PRIMARY KEY, sz BLOB, origin INTEGER);
|
|
56
|
+
CREATE TABLE 'messages_fts_config'(k PRIMARY KEY, v) WITHOUT ROWID;
|
|
55
57
|
CREATE TRIGGER messages_fts_insert AFTER INSERT ON messages
|
|
56
58
|
WHEN NEW.message_type IN ('user_message', 'agent_message', 'system_message')
|
|
57
59
|
OR (NEW.message_type = 'tool_call' AND json_extract(NEW.payload, '$.tool_name') = 'think')
|
|
@@ -73,20 +75,31 @@ WHEN OLD.message_type IN ('user_message', 'agent_message', 'system_message')
|
|
|
73
75
|
BEGIN
|
|
74
76
|
DELETE FROM messages_fts WHERE rowid = OLD.id;
|
|
75
77
|
END;
|
|
76
|
-
CREATE TABLE
|
|
77
|
-
CREATE UNIQUE INDEX "index_secrets_on_namespace_and_key" ON "secrets" ("namespace", "key");
|
|
78
|
-
CREATE INDEX "index_goals_on_evicted_at" ON "goals" ("evicted_at");
|
|
79
|
-
CREATE TABLE IF NOT EXISTS "pending_messages" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "session_id" integer NOT NULL, "content" text NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "source_type" varchar DEFAULT 'user' NOT NULL, "source_name" varchar, CONSTRAINT "fk_rails_007242365b"
|
|
80
|
-
FOREIGN KEY ("session_id")
|
|
81
|
-
REFERENCES "sessions" ("id")
|
|
82
|
-
);
|
|
83
|
-
CREATE INDEX "index_pending_messages_on_session_id" ON "pending_messages" ("session_id");
|
|
84
|
-
CREATE TABLE IF NOT EXISTS "sessions" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "view_mode" varchar DEFAULT 'basic' NOT NULL, "processing" boolean DEFAULT FALSE NOT NULL, "parent_session_id" integer, "prompt" text, "granted_tools" text, "name" varchar, "viewport_message_ids" json DEFAULT '[]' NOT NULL, "active_skills" json DEFAULT '[]' NOT NULL, "active_workflow" varchar, "interrupt_requested" boolean DEFAULT FALSE NOT NULL, "mneme_boundary_message_id" integer, "mneme_snapshot_first_message_id" integer, "mneme_snapshot_last_message_id" integer, "initial_cwd" varchar, CONSTRAINT "fk_rails_045409ac27"
|
|
78
|
+
CREATE TABLE "sessions" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime(6) NOT NULL, "granted_tools" text, "interrupt_requested" boolean DEFAULT FALSE NOT NULL, "mneme_boundary_message_id" integer, "name" varchar, "parent_session_id" integer, "prompt" text, "recalled_message_ids" json DEFAULT '[]' NOT NULL, "updated_at" datetime(6) NOT NULL, "view_mode" varchar DEFAULT 'basic' NOT NULL, "initial_cwd" varchar, "aasm_state" varchar DEFAULT 'idle' NOT NULL, "hud_visible" boolean DEFAULT TRUE NOT NULL, "spawn_tool_use_id" varchar, CONSTRAINT "fk_rails_045409ac27"
|
|
85
79
|
FOREIGN KEY ("parent_session_id")
|
|
86
80
|
REFERENCES "sessions" ("id")
|
|
87
81
|
);
|
|
82
|
+
CREATE UNIQUE INDEX "index_sessions_on_parent_and_name_unique" ON "sessions" ("parent_session_id", "name") WHERE name IS NOT NULL;
|
|
88
83
|
CREATE INDEX "index_sessions_on_parent_session_id" ON "sessions" ("parent_session_id");
|
|
84
|
+
CREATE TABLE "pending_messages" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "content" text NOT NULL, "created_at" datetime(6) NOT NULL, "session_id" integer NOT NULL, "source_name" varchar, "source_type" varchar DEFAULT 'user' NOT NULL, "updated_at" datetime(6) NOT NULL, "kind" varchar NOT NULL, "message_type" varchar, "tool_use_id" varchar, "success" boolean, "bounce_back" boolean DEFAULT FALSE NOT NULL, CONSTRAINT "fk_rails_007242365b"
|
|
85
|
+
FOREIGN KEY ("session_id")
|
|
86
|
+
REFERENCES "sessions" ("id")
|
|
87
|
+
);
|
|
88
|
+
CREATE INDEX "index_pending_messages_on_session_id" ON "pending_messages" ("session_id");
|
|
89
|
+
CREATE INDEX "index_pending_messages_on_drain_ordering" ON "pending_messages" ("session_id", "message_type", "created_at");
|
|
90
|
+
CREATE INDEX "index_pending_messages_on_session_and_tool_use" ON "pending_messages" ("session_id", "tool_use_id");
|
|
91
|
+
CREATE INDEX "index_sessions_on_parent_session_id_and_hud_visible" ON "sessions" ("parent_session_id", "hud_visible");
|
|
89
92
|
INSERT INTO "schema_migrations" (version) VALUES
|
|
93
|
+
('20260420100000'),
|
|
94
|
+
('20260419140000'),
|
|
95
|
+
('20260419130000'),
|
|
96
|
+
('20260419120000'),
|
|
97
|
+
('20260418150323'),
|
|
98
|
+
('20260412110625'),
|
|
99
|
+
('20260411172926'),
|
|
100
|
+
('20260411120553'),
|
|
101
|
+
('20260407180400'),
|
|
102
|
+
('20260407170803'),
|
|
90
103
|
('20260403080031'),
|
|
91
104
|
('20260401210935'),
|
|
92
105
|
('20260401180000'),
|
data/lib/agents/registry.rb
CHANGED
|
@@ -97,7 +97,7 @@ module Agents
|
|
|
97
97
|
def validate_tools!(agent_name, tools)
|
|
98
98
|
return if tools.empty?
|
|
99
99
|
|
|
100
|
-
unknown = tools -
|
|
100
|
+
unknown = tools - Tools::Registry::STANDARD_TOOLS_BY_NAME.keys
|
|
101
101
|
return if unknown.empty?
|
|
102
102
|
|
|
103
103
|
raise InvalidDefinitionError, "Unknown tools in '#{agent_name}': #{unknown.join(", ")}"
|