swarm_sdk 2.7.13 → 3.0.0.alpha1
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/lib/swarm_sdk/ruby_llm_patches/chat_callbacks_patch.rb +43 -22
- data/lib/swarm_sdk/ruby_llm_patches/init.rb +6 -0
- data/lib/swarm_sdk/ruby_llm_patches/mcp_ssl_patch.rb +144 -0
- data/lib/swarm_sdk/ruby_llm_patches/tool_concurrency_patch.rb +3 -4
- data/lib/swarm_sdk/v3/agent.rb +1165 -0
- data/lib/swarm_sdk/v3/agent_builder.rb +533 -0
- data/lib/swarm_sdk/v3/agent_definition.rb +330 -0
- data/lib/swarm_sdk/v3/configuration.rb +490 -0
- data/lib/swarm_sdk/v3/debug_log.rb +86 -0
- data/lib/swarm_sdk/v3/event_stream.rb +130 -0
- data/lib/swarm_sdk/v3/hooks/context.rb +112 -0
- data/lib/swarm_sdk/v3/hooks/result.rb +115 -0
- data/lib/swarm_sdk/v3/hooks/runner.rb +128 -0
- data/lib/swarm_sdk/v3/mcp/connector.rb +183 -0
- data/lib/swarm_sdk/v3/mcp/mcp_error.rb +15 -0
- data/lib/swarm_sdk/v3/mcp/server_definition.rb +125 -0
- data/lib/swarm_sdk/v3/mcp/ssl_http_transport.rb +103 -0
- data/lib/swarm_sdk/v3/mcp/stdio_transport.rb +135 -0
- data/lib/swarm_sdk/v3/mcp/tool_proxy.rb +53 -0
- data/lib/swarm_sdk/v3/memory/adapters/base.rb +297 -0
- data/lib/swarm_sdk/v3/memory/adapters/faiss_support.rb +194 -0
- data/lib/swarm_sdk/v3/memory/adapters/filesystem_adapter.rb +212 -0
- data/lib/swarm_sdk/v3/memory/adapters/sqlite_adapter.rb +507 -0
- data/lib/swarm_sdk/v3/memory/adapters/vector_utils.rb +88 -0
- data/lib/swarm_sdk/v3/memory/card.rb +206 -0
- data/lib/swarm_sdk/v3/memory/cluster.rb +146 -0
- data/lib/swarm_sdk/v3/memory/compressor.rb +496 -0
- data/lib/swarm_sdk/v3/memory/consolidator.rb +427 -0
- data/lib/swarm_sdk/v3/memory/context_builder.rb +339 -0
- data/lib/swarm_sdk/v3/memory/edge.rb +105 -0
- data/lib/swarm_sdk/v3/memory/embedder.rb +185 -0
- data/lib/swarm_sdk/v3/memory/exposure_tracker.rb +104 -0
- data/lib/swarm_sdk/v3/memory/ingestion_pipeline.rb +394 -0
- data/lib/swarm_sdk/v3/memory/retriever.rb +289 -0
- data/lib/swarm_sdk/v3/memory/store.rb +489 -0
- data/lib/swarm_sdk/v3/skills/loader.rb +147 -0
- data/lib/swarm_sdk/v3/skills/manifest.rb +45 -0
- data/lib/swarm_sdk/v3/sub_task_agent.rb +248 -0
- data/lib/swarm_sdk/v3/tools/base.rb +80 -0
- data/lib/swarm_sdk/v3/tools/bash.rb +174 -0
- data/lib/swarm_sdk/v3/tools/clock.rb +32 -0
- data/lib/swarm_sdk/v3/tools/edit.rb +111 -0
- data/lib/swarm_sdk/v3/tools/glob.rb +96 -0
- data/lib/swarm_sdk/v3/tools/grep.rb +200 -0
- data/lib/swarm_sdk/v3/tools/message_teammate.rb +15 -0
- data/lib/swarm_sdk/v3/tools/message_user.rb +15 -0
- data/lib/swarm_sdk/v3/tools/read.rb +181 -0
- data/lib/swarm_sdk/v3/tools/read_tracker.rb +40 -0
- data/lib/swarm_sdk/v3/tools/registry.rb +208 -0
- data/lib/swarm_sdk/v3/tools/sub_task.rb +183 -0
- data/lib/swarm_sdk/v3/tools/think.rb +88 -0
- data/lib/swarm_sdk/v3/tools/write.rb +87 -0
- data/lib/swarm_sdk/v3.rb +145 -0
- metadata +84 -148
- data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -175
- data/lib/swarm_sdk/agent/builder.rb +0 -680
- data/lib/swarm_sdk/agent/chat.rb +0 -1432
- data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -375
- data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +0 -204
- data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +0 -480
- data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +0 -85
- data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -290
- data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +0 -116
- data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +0 -83
- data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +0 -134
- data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
- data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -146
- data/lib/swarm_sdk/agent/context.rb +0 -115
- data/lib/swarm_sdk/agent/context_manager.rb +0 -315
- data/lib/swarm_sdk/agent/definition.rb +0 -581
- data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -226
- data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -161
- data/lib/swarm_sdk/agent/tool_registry.rb +0 -189
- data/lib/swarm_sdk/agent_registry.rb +0 -146
- data/lib/swarm_sdk/builders/base_builder.rb +0 -553
- data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
- data/lib/swarm_sdk/concerns/cleanupable.rb +0 -39
- data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
- data/lib/swarm_sdk/concerns/validatable.rb +0 -55
- data/lib/swarm_sdk/config.rb +0 -367
- data/lib/swarm_sdk/configuration/parser.rb +0 -397
- data/lib/swarm_sdk/configuration/translator.rb +0 -283
- data/lib/swarm_sdk/configuration.rb +0 -165
- data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
- data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -102
- data/lib/swarm_sdk/context_compactor.rb +0 -335
- data/lib/swarm_sdk/context_management/builder.rb +0 -128
- data/lib/swarm_sdk/context_management/context.rb +0 -328
- data/lib/swarm_sdk/custom_tool_registry.rb +0 -226
- data/lib/swarm_sdk/defaults.rb +0 -251
- data/lib/swarm_sdk/events_to_messages.rb +0 -199
- data/lib/swarm_sdk/hooks/adapter.rb +0 -359
- data/lib/swarm_sdk/hooks/context.rb +0 -197
- data/lib/swarm_sdk/hooks/definition.rb +0 -80
- data/lib/swarm_sdk/hooks/error.rb +0 -29
- data/lib/swarm_sdk/hooks/executor.rb +0 -146
- data/lib/swarm_sdk/hooks/registry.rb +0 -147
- data/lib/swarm_sdk/hooks/result.rb +0 -150
- data/lib/swarm_sdk/hooks/shell_executor.rb +0 -256
- data/lib/swarm_sdk/hooks/tool_call.rb +0 -35
- data/lib/swarm_sdk/hooks/tool_result.rb +0 -62
- data/lib/swarm_sdk/log_collector.rb +0 -227
- data/lib/swarm_sdk/log_stream.rb +0 -127
- data/lib/swarm_sdk/markdown_parser.rb +0 -75
- data/lib/swarm_sdk/model_aliases.json +0 -8
- data/lib/swarm_sdk/models.json +0 -44002
- data/lib/swarm_sdk/models.rb +0 -161
- data/lib/swarm_sdk/node_context.rb +0 -245
- data/lib/swarm_sdk/observer/builder.rb +0 -81
- data/lib/swarm_sdk/observer/config.rb +0 -45
- data/lib/swarm_sdk/observer/manager.rb +0 -236
- data/lib/swarm_sdk/patterns/agent_observer.rb +0 -160
- data/lib/swarm_sdk/permissions/config.rb +0 -239
- data/lib/swarm_sdk/permissions/error_formatter.rb +0 -121
- data/lib/swarm_sdk/permissions/path_matcher.rb +0 -35
- data/lib/swarm_sdk/permissions/validator.rb +0 -173
- data/lib/swarm_sdk/permissions_builder.rb +0 -122
- data/lib/swarm_sdk/plugin.rb +0 -309
- data/lib/swarm_sdk/plugin_registry.rb +0 -101
- data/lib/swarm_sdk/proc_helpers.rb +0 -53
- data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -117
- data/lib/swarm_sdk/restore_result.rb +0 -65
- data/lib/swarm_sdk/result.rb +0 -212
- data/lib/swarm_sdk/snapshot.rb +0 -156
- data/lib/swarm_sdk/snapshot_from_events.rb +0 -397
- data/lib/swarm_sdk/state_restorer.rb +0 -476
- data/lib/swarm_sdk/state_snapshot.rb +0 -334
- data/lib/swarm_sdk/swarm/agent_initializer.rb +0 -648
- data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -195
- data/lib/swarm_sdk/swarm/builder.rb +0 -256
- data/lib/swarm_sdk/swarm/executor.rb +0 -290
- data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -151
- data/lib/swarm_sdk/swarm/lazy_delegate_chat.rb +0 -372
- data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -360
- data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -270
- data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
- data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -392
- data/lib/swarm_sdk/swarm.rb +0 -843
- data/lib/swarm_sdk/swarm_loader.rb +0 -145
- data/lib/swarm_sdk/swarm_registry.rb +0 -136
- data/lib/swarm_sdk/tools/base.rb +0 -63
- data/lib/swarm_sdk/tools/bash.rb +0 -280
- data/lib/swarm_sdk/tools/clock.rb +0 -46
- data/lib/swarm_sdk/tools/delegate.rb +0 -389
- data/lib/swarm_sdk/tools/document_converters/base_converter.rb +0 -83
- data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +0 -99
- data/lib/swarm_sdk/tools/document_converters/html_converter.rb +0 -101
- data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +0 -78
- data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +0 -194
- data/lib/swarm_sdk/tools/edit.rb +0 -145
- data/lib/swarm_sdk/tools/glob.rb +0 -166
- data/lib/swarm_sdk/tools/grep.rb +0 -235
- data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +0 -43
- data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +0 -167
- data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
- data/lib/swarm_sdk/tools/mcp_tool_stub.rb +0 -198
- data/lib/swarm_sdk/tools/multi_edit.rb +0 -236
- data/lib/swarm_sdk/tools/path_resolver.rb +0 -92
- data/lib/swarm_sdk/tools/read.rb +0 -261
- data/lib/swarm_sdk/tools/registry.rb +0 -205
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +0 -117
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +0 -97
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +0 -108
- data/lib/swarm_sdk/tools/stores/read_tracker.rb +0 -96
- data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +0 -273
- data/lib/swarm_sdk/tools/stores/storage.rb +0 -142
- data/lib/swarm_sdk/tools/stores/todo_manager.rb +0 -65
- data/lib/swarm_sdk/tools/think.rb +0 -100
- data/lib/swarm_sdk/tools/todo_write.rb +0 -237
- data/lib/swarm_sdk/tools/web_fetch.rb +0 -264
- data/lib/swarm_sdk/tools/write.rb +0 -112
- data/lib/swarm_sdk/transcript_builder.rb +0 -278
- data/lib/swarm_sdk/utils.rb +0 -68
- data/lib/swarm_sdk/validation_result.rb +0 -33
- data/lib/swarm_sdk/version.rb +0 -5
- data/lib/swarm_sdk/workflow/agent_config.rb +0 -95
- data/lib/swarm_sdk/workflow/builder.rb +0 -227
- data/lib/swarm_sdk/workflow/executor.rb +0 -497
- data/lib/swarm_sdk/workflow/node_builder.rb +0 -593
- data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -250
- data/lib/swarm_sdk/workflow.rb +0 -589
- data/lib/swarm_sdk.rb +0 -718
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SwarmSDK
|
|
4
|
+
module V3
|
|
5
|
+
module Memory
|
|
6
|
+
# A self-contained memory unit (<=250 words)
|
|
7
|
+
#
|
|
8
|
+
# Cards are the atomic unit of the memory system. Each card captures
|
|
9
|
+
# a single idea, fact, decision, or concept with enough context to
|
|
10
|
+
# be understood in isolation.
|
|
11
|
+
#
|
|
12
|
+
# @example Create a fact card
|
|
13
|
+
# card = Card.new(
|
|
14
|
+
# text: "The API uses JWT tokens for authentication with RS256 signing.",
|
|
15
|
+
# type: :fact,
|
|
16
|
+
# entities: ["API", "JWT", "RS256"],
|
|
17
|
+
# source_turn_ids: ["turn_001"],
|
|
18
|
+
# )
|
|
19
|
+
class Card
|
|
20
|
+
TYPES = [:fact, :concept, :decision, :constraint, :preference, :incident].freeze
|
|
21
|
+
|
|
22
|
+
# @return [String] Unique card identifier (card_<hex>)
|
|
23
|
+
attr_reader :id
|
|
24
|
+
|
|
25
|
+
# @return [String] Card content (<=250 words, self-contained)
|
|
26
|
+
attr_accessor :text
|
|
27
|
+
|
|
28
|
+
# @return [Symbol] Card type (fact, concept, decision, constraint, preference, incident)
|
|
29
|
+
attr_reader :type
|
|
30
|
+
|
|
31
|
+
# @return [Array<String>] Named entities mentioned in the card
|
|
32
|
+
attr_accessor :entities
|
|
33
|
+
|
|
34
|
+
# @return [Array<String>] Turn IDs that contributed to this card
|
|
35
|
+
attr_accessor :source_turn_ids
|
|
36
|
+
|
|
37
|
+
# @return [Array<Float>, nil] Embedding vector (384 dimensions for MiniLM)
|
|
38
|
+
attr_accessor :embedding
|
|
39
|
+
|
|
40
|
+
# @return [Float] Importance score (0.0-1.0)
|
|
41
|
+
attr_accessor :importance
|
|
42
|
+
|
|
43
|
+
# @return [Float] Confidence score (0.0-1.0, default 1.0)
|
|
44
|
+
attr_accessor :confidence
|
|
45
|
+
|
|
46
|
+
# @return [Integer] Number of times this card was retrieved
|
|
47
|
+
attr_accessor :access_count
|
|
48
|
+
|
|
49
|
+
# @return [Time, nil] Last time this card was accessed
|
|
50
|
+
attr_accessor :last_accessed
|
|
51
|
+
|
|
52
|
+
# @return [Float] Dwell time weight (how long card was in context)
|
|
53
|
+
attr_accessor :dwell
|
|
54
|
+
|
|
55
|
+
# @return [Integer] Compression level (0=raw, 1=summary, 2=bullets, 3=schema, 4=embedding-only)
|
|
56
|
+
attr_accessor :compression_level
|
|
57
|
+
|
|
58
|
+
# @return [String, nil] ID of canonical card if this was merged
|
|
59
|
+
attr_accessor :canonical_id
|
|
60
|
+
|
|
61
|
+
# @return [Time] Creation timestamp
|
|
62
|
+
attr_reader :created_at
|
|
63
|
+
|
|
64
|
+
# @return [Time] Last update timestamp
|
|
65
|
+
attr_accessor :updated_at
|
|
66
|
+
|
|
67
|
+
# Create a new memory card
|
|
68
|
+
#
|
|
69
|
+
# @param text [String] Card content
|
|
70
|
+
# @param type [Symbol] Card type
|
|
71
|
+
# @param entities [Array<String>] Named entities
|
|
72
|
+
# @param source_turn_ids [Array<String>] Contributing turn IDs
|
|
73
|
+
# @param id [String, nil] Card ID (auto-generated if nil)
|
|
74
|
+
# @param embedding [Array<Float>, nil] Embedding vector
|
|
75
|
+
# @param importance [Float] Importance score
|
|
76
|
+
# @param confidence [Float] Confidence score (0.0-1.0)
|
|
77
|
+
# @param access_count [Integer] Access count
|
|
78
|
+
# @param last_accessed [Time, nil] Last access time
|
|
79
|
+
# @param dwell [Float] Dwell time weight
|
|
80
|
+
# @param compression_level [Integer] Compression level (0-4)
|
|
81
|
+
# @param canonical_id [String, nil] Canonical card ID
|
|
82
|
+
# @param created_at [Time, nil] Creation time
|
|
83
|
+
# @param updated_at [Time, nil] Update time
|
|
84
|
+
#
|
|
85
|
+
# @raise [ArgumentError] If type is invalid
|
|
86
|
+
def initialize(
|
|
87
|
+
text:,
|
|
88
|
+
type: :fact,
|
|
89
|
+
entities: [],
|
|
90
|
+
source_turn_ids: [],
|
|
91
|
+
id: nil,
|
|
92
|
+
embedding: nil,
|
|
93
|
+
importance: 0.5,
|
|
94
|
+
confidence: 1.0,
|
|
95
|
+
access_count: 0,
|
|
96
|
+
last_accessed: nil,
|
|
97
|
+
dwell: 0.0,
|
|
98
|
+
compression_level: 0,
|
|
99
|
+
canonical_id: nil,
|
|
100
|
+
created_at: nil,
|
|
101
|
+
updated_at: nil
|
|
102
|
+
)
|
|
103
|
+
@id = id || "card_#{SecureRandom.hex(6)}"
|
|
104
|
+
@text = text
|
|
105
|
+
@type = type.to_sym
|
|
106
|
+
@entities = Array(entities)
|
|
107
|
+
@source_turn_ids = Array(source_turn_ids)
|
|
108
|
+
@embedding = embedding
|
|
109
|
+
@importance = importance.to_f
|
|
110
|
+
@confidence = confidence.to_f
|
|
111
|
+
@access_count = access_count.to_i
|
|
112
|
+
@last_accessed = last_accessed
|
|
113
|
+
@dwell = dwell.to_f
|
|
114
|
+
@compression_level = compression_level.to_i
|
|
115
|
+
@canonical_id = canonical_id
|
|
116
|
+
@created_at = created_at || Time.now
|
|
117
|
+
@updated_at = updated_at || Time.now
|
|
118
|
+
|
|
119
|
+
validate!
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Record an access to this card (included in working context)
|
|
123
|
+
#
|
|
124
|
+
# Increments access count, updates last accessed time, and
|
|
125
|
+
# increases dwell weight to track how often this card has
|
|
126
|
+
# been included in the working context.
|
|
127
|
+
#
|
|
128
|
+
# @param dwell_increment [Float] Amount to add to dwell (default: 1.0)
|
|
129
|
+
# @return [void]
|
|
130
|
+
def record_access!(dwell_increment: 1.0)
|
|
131
|
+
@access_count += 1
|
|
132
|
+
@last_accessed = Time.now
|
|
133
|
+
@dwell += dwell_increment
|
|
134
|
+
@updated_at = Time.now
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Whether this card has been merged into a canonical card
|
|
138
|
+
#
|
|
139
|
+
# @return [Boolean]
|
|
140
|
+
def merged?
|
|
141
|
+
!@canonical_id.nil?
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Serialize to a hash for JSON storage
|
|
145
|
+
#
|
|
146
|
+
# @return [Hash] Serializable representation
|
|
147
|
+
def to_h
|
|
148
|
+
{
|
|
149
|
+
id: @id,
|
|
150
|
+
text: @text,
|
|
151
|
+
type: @type.to_s,
|
|
152
|
+
entities: @entities,
|
|
153
|
+
source_turn_ids: @source_turn_ids,
|
|
154
|
+
embedding: @embedding,
|
|
155
|
+
importance: @importance,
|
|
156
|
+
confidence: @confidence,
|
|
157
|
+
access_count: @access_count,
|
|
158
|
+
last_accessed: @last_accessed&.iso8601,
|
|
159
|
+
dwell: @dwell,
|
|
160
|
+
compression_level: @compression_level,
|
|
161
|
+
canonical_id: @canonical_id,
|
|
162
|
+
created_at: @created_at.iso8601,
|
|
163
|
+
updated_at: @updated_at.iso8601,
|
|
164
|
+
}
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
class << self
|
|
168
|
+
# Deserialize from a hash
|
|
169
|
+
#
|
|
170
|
+
# @param hash [Hash] Serialized card data
|
|
171
|
+
# @return [Card]
|
|
172
|
+
def from_h(hash)
|
|
173
|
+
hash = hash.transform_keys(&:to_sym)
|
|
174
|
+
new(
|
|
175
|
+
id: hash[:id],
|
|
176
|
+
text: hash[:text],
|
|
177
|
+
type: hash[:type]&.to_sym || :fact,
|
|
178
|
+
entities: hash[:entities] || [],
|
|
179
|
+
source_turn_ids: hash[:source_turn_ids] || [],
|
|
180
|
+
embedding: hash[:embedding],
|
|
181
|
+
importance: hash[:importance] || 0.5,
|
|
182
|
+
confidence: hash[:confidence] || 1.0,
|
|
183
|
+
access_count: hash[:access_count] || 0,
|
|
184
|
+
last_accessed: hash[:last_accessed] ? Time.parse(hash[:last_accessed]) : nil,
|
|
185
|
+
dwell: hash[:dwell] || 0.0,
|
|
186
|
+
compression_level: hash[:compression_level] || 0,
|
|
187
|
+
canonical_id: hash[:canonical_id],
|
|
188
|
+
created_at: hash[:created_at] ? Time.parse(hash[:created_at]) : nil,
|
|
189
|
+
updated_at: hash[:updated_at] ? Time.parse(hash[:updated_at]) : nil,
|
|
190
|
+
)
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
private
|
|
195
|
+
|
|
196
|
+
# @raise [ArgumentError] If type is invalid
|
|
197
|
+
def validate!
|
|
198
|
+
raise ArgumentError, "Invalid card type: #{@type}. Must be one of: #{TYPES.join(", ")}" unless TYPES.include?(@type)
|
|
199
|
+
raise ArgumentError, "Card text is required" if @text.nil? || @text.strip.empty?
|
|
200
|
+
raise ArgumentError, "Confidence must be 0.0-1.0" unless (0.0..1.0).cover?(@confidence)
|
|
201
|
+
raise ArgumentError, "Compression level must be 0-4" unless (0..4).cover?(@compression_level)
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SwarmSDK
|
|
4
|
+
module V3
|
|
5
|
+
module Memory
|
|
6
|
+
# A topic cluster grouping related memory cards
|
|
7
|
+
#
|
|
8
|
+
# Clusters provide a higher-level organization of memory cards
|
|
9
|
+
# by topic. Each cluster maintains a rolling summary and tracks
|
|
10
|
+
# its member cards.
|
|
11
|
+
#
|
|
12
|
+
# @example Create a cluster
|
|
13
|
+
# cluster = Cluster.new(
|
|
14
|
+
# title: "Authentication System",
|
|
15
|
+
# rolling_summary: "The project uses JWT-based auth with RS256 signing...",
|
|
16
|
+
# card_ids: ["card_a1b2c3", "card_d4e5f6"],
|
|
17
|
+
# )
|
|
18
|
+
class Cluster
|
|
19
|
+
# @return [String] Unique cluster identifier
|
|
20
|
+
attr_reader :id
|
|
21
|
+
|
|
22
|
+
# @return [String] Cluster title/topic
|
|
23
|
+
attr_accessor :title
|
|
24
|
+
|
|
25
|
+
# @return [Array<Float>, nil] Cluster centroid embedding
|
|
26
|
+
attr_accessor :embedding
|
|
27
|
+
|
|
28
|
+
# @return [String] Rolling summary of cluster contents
|
|
29
|
+
attr_accessor :rolling_summary
|
|
30
|
+
|
|
31
|
+
# @return [Array<String>] Decision log entries
|
|
32
|
+
attr_accessor :decision_log
|
|
33
|
+
|
|
34
|
+
# @return [Array<String>] Key entities in this cluster
|
|
35
|
+
attr_accessor :key_entities
|
|
36
|
+
|
|
37
|
+
# @return [Array<String>] Member card IDs
|
|
38
|
+
attr_accessor :card_ids
|
|
39
|
+
|
|
40
|
+
# @return [Time] Creation timestamp
|
|
41
|
+
attr_reader :created_at
|
|
42
|
+
|
|
43
|
+
# @return [Time] Last update timestamp
|
|
44
|
+
attr_accessor :updated_at
|
|
45
|
+
|
|
46
|
+
# Create a new cluster
|
|
47
|
+
#
|
|
48
|
+
# @param title [String] Cluster title
|
|
49
|
+
# @param id [String, nil] Cluster ID (auto-generated if nil)
|
|
50
|
+
# @param embedding [Array<Float>, nil] Centroid embedding
|
|
51
|
+
# @param rolling_summary [String] Summary of contents
|
|
52
|
+
# @param decision_log [Array<String>] Decision entries
|
|
53
|
+
# @param key_entities [Array<String>] Key entities
|
|
54
|
+
# @param card_ids [Array<String>] Member card IDs
|
|
55
|
+
# @param created_at [Time, nil] Creation time
|
|
56
|
+
# @param updated_at [Time, nil] Update time
|
|
57
|
+
def initialize(
|
|
58
|
+
title:,
|
|
59
|
+
id: nil,
|
|
60
|
+
embedding: nil,
|
|
61
|
+
rolling_summary: "",
|
|
62
|
+
decision_log: [],
|
|
63
|
+
key_entities: [],
|
|
64
|
+
card_ids: [],
|
|
65
|
+
created_at: nil,
|
|
66
|
+
updated_at: nil
|
|
67
|
+
)
|
|
68
|
+
@id = id || "cluster_#{SecureRandom.hex(6)}"
|
|
69
|
+
@title = title
|
|
70
|
+
@embedding = embedding
|
|
71
|
+
@rolling_summary = rolling_summary
|
|
72
|
+
@decision_log = Array(decision_log)
|
|
73
|
+
@key_entities = Array(key_entities)
|
|
74
|
+
@card_ids = Array(card_ids)
|
|
75
|
+
@created_at = created_at || Time.now
|
|
76
|
+
@updated_at = updated_at || Time.now
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Add a card to this cluster
|
|
80
|
+
#
|
|
81
|
+
# @param card_id [String] Card ID to add
|
|
82
|
+
# @return [void]
|
|
83
|
+
def add_card(card_id)
|
|
84
|
+
return if @card_ids.include?(card_id)
|
|
85
|
+
|
|
86
|
+
@card_ids << card_id
|
|
87
|
+
@updated_at = Time.now
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Remove a card from this cluster
|
|
91
|
+
#
|
|
92
|
+
# @param card_id [String] Card ID to remove
|
|
93
|
+
# @return [void]
|
|
94
|
+
def remove_card(card_id)
|
|
95
|
+
@card_ids.delete(card_id)
|
|
96
|
+
@updated_at = Time.now
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Number of cards in this cluster
|
|
100
|
+
#
|
|
101
|
+
# @return [Integer]
|
|
102
|
+
def size
|
|
103
|
+
@card_ids.size
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Serialize to a hash
|
|
107
|
+
#
|
|
108
|
+
# @return [Hash]
|
|
109
|
+
def to_h
|
|
110
|
+
{
|
|
111
|
+
id: @id,
|
|
112
|
+
title: @title,
|
|
113
|
+
embedding: @embedding,
|
|
114
|
+
rolling_summary: @rolling_summary,
|
|
115
|
+
decision_log: @decision_log,
|
|
116
|
+
key_entities: @key_entities,
|
|
117
|
+
card_ids: @card_ids,
|
|
118
|
+
created_at: @created_at.iso8601,
|
|
119
|
+
updated_at: @updated_at.iso8601,
|
|
120
|
+
}
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
class << self
|
|
124
|
+
# Deserialize from a hash
|
|
125
|
+
#
|
|
126
|
+
# @param hash [Hash] Serialized cluster data
|
|
127
|
+
# @return [Cluster]
|
|
128
|
+
def from_h(hash)
|
|
129
|
+
hash = hash.transform_keys(&:to_sym)
|
|
130
|
+
new(
|
|
131
|
+
id: hash[:id],
|
|
132
|
+
title: hash[:title],
|
|
133
|
+
embedding: hash[:embedding],
|
|
134
|
+
rolling_summary: hash[:rolling_summary] || "",
|
|
135
|
+
decision_log: hash[:decision_log] || [],
|
|
136
|
+
key_entities: hash[:key_entities] || [],
|
|
137
|
+
card_ids: hash[:card_ids] || [],
|
|
138
|
+
created_at: hash[:created_at] ? Time.parse(hash[:created_at]) : nil,
|
|
139
|
+
updated_at: hash[:updated_at] ? Time.parse(hash[:updated_at]) : nil,
|
|
140
|
+
)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|