lex-context 0.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.
- checksums.yaml +7 -0
- data/README.md +80 -0
- data/lib/legion/extensions/context/client.rb +22 -0
- data/lib/legion/extensions/context/helpers/constants.rb +30 -0
- data/lib/legion/extensions/context/helpers/context_manager.rb +146 -0
- data/lib/legion/extensions/context/helpers/frame.rb +95 -0
- data/lib/legion/extensions/context/runners/context.rb +90 -0
- data/lib/legion/extensions/context/version.rb +9 -0
- data/lib/legion/extensions/context.rb +16 -0
- metadata +65 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: a471dc0eb03821a6242b22bf9d1355d2aca38b6152498dd473c56ee96b3c0013
|
|
4
|
+
data.tar.gz: 83023441c865a754e6a3397750a7e95f050181d9f0fe8650f0c0a7830ed9d094
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 87c59f574c3683a53f7b3e9018a9a2205fe916099dde07cc984155bd6ed2270cd1448f6ed87db6868ddfbf35525219044516df260f73312d0bdbeb0428cba944
|
|
7
|
+
data.tar.gz: aae221c9aee738367fd76f7c4052cbb81dcfed652052ec6cf53fe1f736dbec0cf5c4962587d1916237f697d23fa5ea00d4e081325d261f6d08c35401e4bb51db
|
data/README.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# lex-context
|
|
2
|
+
|
|
3
|
+
A LegionIO cognitive architecture extension for contextual framing and situation modeling. Maintains context frames that shape perception, memory retrieval, and action selection. Tracks context switches with measurable switch costs and familiarity-based discounts — switching to a familiar frame costs less than switching to an unfamiliar one.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
Manages a registry of **frames** — each representing a situated context with a domain, a set of cues (tokens that activate the frame), and a strength score. An active frame stack (up to 10 deep) tracks the current cognitive situation.
|
|
8
|
+
|
|
9
|
+
- **Create frames** representing different operational contexts (coding, reviewing, planning)
|
|
10
|
+
- **Activate frames** explicitly or let `auto_switch` select the best match from input cues
|
|
11
|
+
- **Measure switch costs** — base 0.15 cost reduced by familiarity and same-domain bonuses, increased by rapid successive switches
|
|
12
|
+
- **Decay frames** over time — unused frames weaken and are eventually pruned from the registry
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
require 'lex-context'
|
|
18
|
+
|
|
19
|
+
client = Legion::Extensions::Context::Client.new
|
|
20
|
+
|
|
21
|
+
# Create context frames
|
|
22
|
+
coding = client.create_context(
|
|
23
|
+
name: 'software_development',
|
|
24
|
+
domain: :technical,
|
|
25
|
+
cues: [:code, :function, :test, :deploy, :bug]
|
|
26
|
+
)
|
|
27
|
+
# => { success: true, frame: { id: "uuid...", name: "software_development",
|
|
28
|
+
# domain: :technical, strength: 1.0, familiarity: 0.3, label: :dominant, ... } }
|
|
29
|
+
|
|
30
|
+
review = client.create_context(
|
|
31
|
+
name: 'code_review',
|
|
32
|
+
domain: :technical,
|
|
33
|
+
cues: [:review, :pr, :feedback, :approve, :merge]
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
frame_id = coding[:frame][:id]
|
|
37
|
+
|
|
38
|
+
# Activate a frame explicitly
|
|
39
|
+
client.activate_context(frame_id: frame_id)
|
|
40
|
+
# => { success: true, frame: { ... }, switch_cost: 0.0 }
|
|
41
|
+
|
|
42
|
+
# Detect matching frames from input cues
|
|
43
|
+
client.detect_context(input_cues: [:review, :pr, :feedback])
|
|
44
|
+
# => { success: true, candidates: [{ frame: {...}, relevance: 0.6 }],
|
|
45
|
+
# count: 1, best: { name: "code_review", relevance: 0.6 } }
|
|
46
|
+
|
|
47
|
+
# Automatically switch to the best-matching frame
|
|
48
|
+
client.auto_switch(input_cues: [:review, :pr])
|
|
49
|
+
# => { success: true, switched: true, frame: { ... }, switch_cost: 0.12 }
|
|
50
|
+
|
|
51
|
+
# Current active frame
|
|
52
|
+
client.current_context
|
|
53
|
+
# => { success: true, frame: { name: "code_review", ... } }
|
|
54
|
+
|
|
55
|
+
# Add a cue to an existing frame
|
|
56
|
+
client.add_cue(frame_id: frame_id, cue: :refactor)
|
|
57
|
+
# => { success: true, frame: { ... } }
|
|
58
|
+
|
|
59
|
+
# Periodic maintenance: decay all frames, remove stale ones
|
|
60
|
+
client.update_context
|
|
61
|
+
# => { success: true, frame_count: 2, active: "code_review" }
|
|
62
|
+
|
|
63
|
+
# Stats
|
|
64
|
+
client.context_stats
|
|
65
|
+
# => { success: true, stats: { frame_count: 2, active_frame: "code_review",
|
|
66
|
+
# stack_depth: 1, switch_count: 1, avg_switch_cost: 0.12,
|
|
67
|
+
# by_domain: { technical: 2 } } }
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Development
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
bundle install
|
|
74
|
+
bundle exec rspec
|
|
75
|
+
bundle exec rubocop
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## License
|
|
79
|
+
|
|
80
|
+
MIT
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/context/helpers/constants'
|
|
4
|
+
require 'legion/extensions/context/helpers/frame'
|
|
5
|
+
require 'legion/extensions/context/helpers/context_manager'
|
|
6
|
+
require 'legion/extensions/context/runners/context'
|
|
7
|
+
|
|
8
|
+
module Legion
|
|
9
|
+
module Extensions
|
|
10
|
+
module Context
|
|
11
|
+
class Client
|
|
12
|
+
include Runners::Context
|
|
13
|
+
|
|
14
|
+
attr_reader :context_manager
|
|
15
|
+
|
|
16
|
+
def initialize(context_manager: nil, **)
|
|
17
|
+
@context_manager = context_manager || Helpers::ContextManager.new
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Context
|
|
6
|
+
module Helpers
|
|
7
|
+
module Constants
|
|
8
|
+
MAX_FRAMES = 50
|
|
9
|
+
MAX_FRAME_STACK = 10
|
|
10
|
+
FRAME_DECAY = 0.02
|
|
11
|
+
FRAME_STRENGTH_FLOOR = 0.05
|
|
12
|
+
SWITCH_COST = 0.15
|
|
13
|
+
SWITCH_COOLDOWN = 5
|
|
14
|
+
FAMILIARITY_ALPHA = 0.12
|
|
15
|
+
DEFAULT_FAMILIARITY = 0.3
|
|
16
|
+
RELEVANCE_THRESHOLD = 0.2
|
|
17
|
+
MAX_CUES_PER_FRAME = 30
|
|
18
|
+
MAX_HISTORY = 200
|
|
19
|
+
|
|
20
|
+
FRAME_LABELS = {
|
|
21
|
+
(0.8..) => :dominant,
|
|
22
|
+
(0.5...0.8) => :active,
|
|
23
|
+
(0.2...0.5) => :background,
|
|
24
|
+
(..0.2) => :fading
|
|
25
|
+
}.freeze
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Context
|
|
6
|
+
module Helpers
|
|
7
|
+
class ContextManager
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
attr_reader :frames, :active_stack, :switch_history
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@frames = []
|
|
14
|
+
@active_stack = []
|
|
15
|
+
@switch_history = []
|
|
16
|
+
@last_switch_at = nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def create_frame(name:, domain: :general, cues: [])
|
|
20
|
+
frame = Frame.new(name: name, domain: domain, cues: cues)
|
|
21
|
+
@frames << frame
|
|
22
|
+
trim_frames
|
|
23
|
+
frame
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def activate(frame_id)
|
|
27
|
+
frame = find(frame_id)
|
|
28
|
+
return nil unless frame
|
|
29
|
+
|
|
30
|
+
previous = current_frame
|
|
31
|
+
cost = 0.0
|
|
32
|
+
|
|
33
|
+
if previous && previous.id != frame_id
|
|
34
|
+
cost = compute_switch_cost(previous, frame)
|
|
35
|
+
previous.deactivate
|
|
36
|
+
record_switch(from: previous, to: frame, cost: cost)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
@active_stack.reject! { |f| f.id == frame_id }
|
|
40
|
+
@active_stack.push(frame)
|
|
41
|
+
@active_stack.shift while @active_stack.size > MAX_FRAME_STACK
|
|
42
|
+
frame.activate
|
|
43
|
+
{ frame: frame, switch_cost: cost }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def current_frame
|
|
47
|
+
@active_stack.last
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def detect_context(input_cues)
|
|
51
|
+
scored = @frames.map { |f| [f, f.match_score(input_cues)] }
|
|
52
|
+
scored.select! { |_, score| score >= RELEVANCE_THRESHOLD }
|
|
53
|
+
scored.sort_by! { |_, score| -score }
|
|
54
|
+
scored.map { |f, score| { frame: f, relevance: score } }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def auto_switch(input_cues)
|
|
58
|
+
candidates = detect_context(input_cues)
|
|
59
|
+
return nil if candidates.empty?
|
|
60
|
+
|
|
61
|
+
best = candidates.first
|
|
62
|
+
current = current_frame
|
|
63
|
+
|
|
64
|
+
return nil if current && current.id == best[:frame].id
|
|
65
|
+
|
|
66
|
+
activate(best[:frame].id)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def find(frame_id)
|
|
70
|
+
@frames.find { |f| f.id == frame_id }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def find_by_name(name)
|
|
74
|
+
@frames.select { |f| f.name == name }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def in_domain(domain)
|
|
78
|
+
@frames.select { |f| f.domain == domain }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def decay_all
|
|
82
|
+
@frames.each(&:decay)
|
|
83
|
+
@frames.reject!(&:stale?)
|
|
84
|
+
@active_stack.reject!(&:stale?)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def remove(frame_id)
|
|
88
|
+
@frames.reject! { |f| f.id == frame_id }
|
|
89
|
+
@active_stack.reject! { |f| f.id == frame_id }
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def switch_cost_average
|
|
93
|
+
return 0.0 if @switch_history.empty?
|
|
94
|
+
|
|
95
|
+
@switch_history.sum { |s| s[:cost] }.to_f / @switch_history.size
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def to_h
|
|
99
|
+
{
|
|
100
|
+
frame_count: @frames.size,
|
|
101
|
+
active_frame: current_frame&.name,
|
|
102
|
+
stack_depth: @active_stack.size,
|
|
103
|
+
switch_count: @switch_history.size,
|
|
104
|
+
avg_switch_cost: switch_cost_average.round(4),
|
|
105
|
+
by_domain: @frames.group_by(&:domain).transform_values(&:size)
|
|
106
|
+
}
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
private
|
|
110
|
+
|
|
111
|
+
def compute_switch_cost(from_frame, to_frame)
|
|
112
|
+
base = SWITCH_COST
|
|
113
|
+
familiarity_discount = to_frame.familiarity * 0.2
|
|
114
|
+
domain_bonus = from_frame.domain == to_frame.domain ? 0.02 : 0.0
|
|
115
|
+
cooldown_penalty = in_cooldown? ? 0.1 : 0.0
|
|
116
|
+
(base - familiarity_discount - domain_bonus + cooldown_penalty).clamp(0.0, 1.0)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def in_cooldown?
|
|
120
|
+
return false unless @last_switch_at
|
|
121
|
+
|
|
122
|
+
(Time.now.utc - @last_switch_at) < SWITCH_COOLDOWN
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def record_switch(from:, to:, cost:)
|
|
126
|
+
@last_switch_at = Time.now.utc
|
|
127
|
+
@switch_history << {
|
|
128
|
+
from: from.name,
|
|
129
|
+
to: to.name,
|
|
130
|
+
cost: cost,
|
|
131
|
+
at: @last_switch_at
|
|
132
|
+
}
|
|
133
|
+
@switch_history.shift while @switch_history.size > MAX_HISTORY
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def trim_frames
|
|
137
|
+
return unless @frames.size > MAX_FRAMES
|
|
138
|
+
|
|
139
|
+
@frames.sort_by!(&:strength)
|
|
140
|
+
@frames.shift(@frames.size - MAX_FRAMES)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Context
|
|
8
|
+
module Helpers
|
|
9
|
+
class Frame
|
|
10
|
+
include Constants
|
|
11
|
+
|
|
12
|
+
attr_reader :id, :name, :domain, :cues, :strength, :familiarity,
|
|
13
|
+
:created_at, :last_activated, :activation_count
|
|
14
|
+
|
|
15
|
+
def initialize(name:, domain: :general, cues: [])
|
|
16
|
+
@id = SecureRandom.uuid
|
|
17
|
+
@name = name
|
|
18
|
+
@domain = domain
|
|
19
|
+
@cues = cues.first(MAX_CUES_PER_FRAME)
|
|
20
|
+
@strength = 1.0
|
|
21
|
+
@familiarity = DEFAULT_FAMILIARITY
|
|
22
|
+
@created_at = Time.now.utc
|
|
23
|
+
@last_activated = @created_at
|
|
24
|
+
@activation_count = 0
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def activate
|
|
28
|
+
@last_activated = Time.now.utc
|
|
29
|
+
@activation_count += 1
|
|
30
|
+
@strength = [@strength + 0.1, 1.0].min
|
|
31
|
+
update_familiarity(1.0)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def deactivate
|
|
35
|
+
update_familiarity(0.0)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def decay
|
|
39
|
+
@strength = [(@strength - FRAME_DECAY), 0.0].max
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def match_score(input_cues)
|
|
43
|
+
return 0.0 if @cues.empty? || input_cues.empty?
|
|
44
|
+
|
|
45
|
+
overlap = (@cues & input_cues).size
|
|
46
|
+
overlap.to_f / @cues.size
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def add_cue(cue)
|
|
50
|
+
return if @cues.include?(cue)
|
|
51
|
+
|
|
52
|
+
@cues << cue
|
|
53
|
+
@cues.shift if @cues.size > MAX_CUES_PER_FRAME
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def remove_cue(cue)
|
|
57
|
+
@cues.delete(cue)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def label
|
|
61
|
+
FRAME_LABELS.each do |range, lbl|
|
|
62
|
+
return lbl if range.cover?(@strength)
|
|
63
|
+
end
|
|
64
|
+
:fading
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def stale?
|
|
68
|
+
@strength < FRAME_STRENGTH_FLOOR
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def to_h
|
|
72
|
+
{
|
|
73
|
+
id: @id,
|
|
74
|
+
name: @name,
|
|
75
|
+
domain: @domain,
|
|
76
|
+
strength: @strength,
|
|
77
|
+
familiarity: @familiarity,
|
|
78
|
+
label: label,
|
|
79
|
+
cues: @cues.dup,
|
|
80
|
+
activation_count: @activation_count,
|
|
81
|
+
created_at: @created_at,
|
|
82
|
+
last_activated: @last_activated
|
|
83
|
+
}
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def update_familiarity(signal)
|
|
89
|
+
@familiarity = ((FAMILIARITY_ALPHA * signal) + ((1.0 - FAMILIARITY_ALPHA) * @familiarity)).clamp(0.0, 1.0)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Context
|
|
6
|
+
module Runners
|
|
7
|
+
module Context
|
|
8
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
9
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
|
|
11
|
+
def create_context(name:, domain: :general, cues: [], **)
|
|
12
|
+
frame = context_manager.create_frame(name: name, domain: domain, cues: cues)
|
|
13
|
+
Legion::Logging.debug "[context] created frame=#{name} domain=#{domain} cues=#{cues.size}"
|
|
14
|
+
{ success: true, frame: frame.to_h }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def activate_context(frame_id:, **)
|
|
18
|
+
result = context_manager.activate(frame_id)
|
|
19
|
+
return { success: false, reason: :not_found } unless result
|
|
20
|
+
|
|
21
|
+
frame = result[:frame]
|
|
22
|
+
Legion::Logging.debug "[context] activated frame=#{frame.name} cost=#{result[:switch_cost].round(3)}"
|
|
23
|
+
{ success: true, frame: frame.to_h, switch_cost: result[:switch_cost] }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def detect_context(input_cues:, **)
|
|
27
|
+
matches = context_manager.detect_context(input_cues)
|
|
28
|
+
Legion::Logging.debug "[context] detect: #{matches.size} candidates for #{input_cues.size} cues"
|
|
29
|
+
{
|
|
30
|
+
success: true,
|
|
31
|
+
candidates: matches.map { |m| { frame: m[:frame].to_h, relevance: m[:relevance] } },
|
|
32
|
+
count: matches.size,
|
|
33
|
+
best: matches.first && { name: matches.first[:frame].name, relevance: matches.first[:relevance] }
|
|
34
|
+
}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def auto_switch(input_cues:, **)
|
|
38
|
+
result = context_manager.auto_switch(input_cues)
|
|
39
|
+
return { success: true, switched: false, reason: :no_better_match } unless result
|
|
40
|
+
|
|
41
|
+
frame = result[:frame]
|
|
42
|
+
Legion::Logging.debug "[context] auto-switched to frame=#{frame.name} cost=#{result[:switch_cost].round(3)}"
|
|
43
|
+
{ success: true, switched: true, frame: frame.to_h, switch_cost: result[:switch_cost] }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def current_context(**)
|
|
47
|
+
frame = context_manager.current_frame
|
|
48
|
+
return { success: true, frame: nil } unless frame
|
|
49
|
+
|
|
50
|
+
{ success: true, frame: frame.to_h }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def update_context(**)
|
|
54
|
+
context_manager.decay_all
|
|
55
|
+
Legion::Logging.debug "[context] tick: frames=#{context_manager.frames.size} active=#{context_manager.current_frame&.name}"
|
|
56
|
+
{ success: true, frame_count: context_manager.frames.size, active: context_manager.current_frame&.name }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def add_cue(frame_id:, cue:, **)
|
|
60
|
+
frame = context_manager.find(frame_id)
|
|
61
|
+
return { success: false, reason: :not_found } unless frame
|
|
62
|
+
|
|
63
|
+
frame.add_cue(cue)
|
|
64
|
+
{ success: true, frame: frame.to_h }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def frames_in_domain(domain:, **)
|
|
68
|
+
frames = context_manager.in_domain(domain)
|
|
69
|
+
{ success: true, frames: frames.map(&:to_h), count: frames.size }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def remove_context(frame_id:, **)
|
|
73
|
+
context_manager.remove(frame_id)
|
|
74
|
+
{ success: true }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def context_stats(**)
|
|
78
|
+
{ success: true, stats: context_manager.to_h }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def context_manager
|
|
84
|
+
@context_manager ||= Helpers::ContextManager.new
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/context/version'
|
|
4
|
+
require 'legion/extensions/context/helpers/constants'
|
|
5
|
+
require 'legion/extensions/context/helpers/frame'
|
|
6
|
+
require 'legion/extensions/context/helpers/context_manager'
|
|
7
|
+
require 'legion/extensions/context/runners/context'
|
|
8
|
+
require 'legion/extensions/context/client'
|
|
9
|
+
|
|
10
|
+
module Legion
|
|
11
|
+
module Extensions
|
|
12
|
+
module Context
|
|
13
|
+
extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lex-context
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Matthew Iverson
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: legion-gaia
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
description: Models situated conceptualization — maintains context frames that shape
|
|
27
|
+
perception, memory retrieval, and action selection. Tracks context switches with
|
|
28
|
+
measurable switch costs and familiarity-based discount.
|
|
29
|
+
email:
|
|
30
|
+
- matt@iverson.io
|
|
31
|
+
executables: []
|
|
32
|
+
extensions: []
|
|
33
|
+
extra_rdoc_files: []
|
|
34
|
+
files:
|
|
35
|
+
- README.md
|
|
36
|
+
- lib/legion/extensions/context.rb
|
|
37
|
+
- lib/legion/extensions/context/client.rb
|
|
38
|
+
- lib/legion/extensions/context/helpers/constants.rb
|
|
39
|
+
- lib/legion/extensions/context/helpers/context_manager.rb
|
|
40
|
+
- lib/legion/extensions/context/helpers/frame.rb
|
|
41
|
+
- lib/legion/extensions/context/runners/context.rb
|
|
42
|
+
- lib/legion/extensions/context/version.rb
|
|
43
|
+
homepage: https://github.com/LegionIO/lex-context
|
|
44
|
+
licenses:
|
|
45
|
+
- MIT
|
|
46
|
+
metadata:
|
|
47
|
+
rubygems_mfa_required: 'true'
|
|
48
|
+
rdoc_options: []
|
|
49
|
+
require_paths:
|
|
50
|
+
- lib
|
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
52
|
+
requirements:
|
|
53
|
+
- - ">="
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: '3.4'
|
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
requirements: []
|
|
62
|
+
rubygems_version: 3.6.9
|
|
63
|
+
specification_version: 4
|
|
64
|
+
summary: Contextual framing and situation model for LegionIO
|
|
65
|
+
test_files: []
|