lex-inner-speech 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/lib/legion/extensions/inner_speech/client.rb +15 -0
- data/lib/legion/extensions/inner_speech/helpers/constants.rb +49 -0
- data/lib/legion/extensions/inner_speech/helpers/inner_voice.rb +137 -0
- data/lib/legion/extensions/inner_speech/helpers/speech_stream.rb +124 -0
- data/lib/legion/extensions/inner_speech/helpers/utterance.rb +86 -0
- data/lib/legion/extensions/inner_speech/runners/inner_speech.rb +83 -0
- data/lib/legion/extensions/inner_speech/version.rb +9 -0
- metadata +68 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 4ab3daf8dea07c9c953b782bc0cddbffdd06170d128db9723ec9388aa58892a0
|
|
4
|
+
data.tar.gz: 762c31cd6ab0f38bcfad47a540b9900782f022448b14778a74bfa9a52b3da5ae
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 298a5228471e0fcd7557f13429ed0d8245ffa9b09377ace575e0643fde1c41fd0b5756d9f4657d0fa513bc720ea15b9caa76aa7e699d9b46f390f9a5bc57cb4a
|
|
7
|
+
data.tar.gz: 3fb165100c57f08b2ba4862d450b60eb6465ce09531c25b70c59279960ca84f09d690bd04b6a035f333899cc3468b7fde04c38e1dcdf4312363592b5e0321064
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module InnerSpeech
|
|
6
|
+
module Helpers
|
|
7
|
+
module Constants
|
|
8
|
+
MAX_UTTERANCES = 500
|
|
9
|
+
MAX_STREAM_LENGTH = 100
|
|
10
|
+
MAX_HISTORY = 200
|
|
11
|
+
|
|
12
|
+
# Speech condensation: inner speech is ~3x compressed vs external
|
|
13
|
+
CONDENSATION_RATIO = 0.33
|
|
14
|
+
|
|
15
|
+
# Rumination detection: same topic repeated N+ times
|
|
16
|
+
RUMINATION_THRESHOLD = 3
|
|
17
|
+
|
|
18
|
+
# Speed constants (utterances per tick)
|
|
19
|
+
AUTOMATIC_SPEED = 3
|
|
20
|
+
CONTROLLED_SPEED = 1
|
|
21
|
+
EGOCENTRIC_SPEED = 0.5
|
|
22
|
+
|
|
23
|
+
# Decay: how quickly old utterances lose salience
|
|
24
|
+
SALIENCE_DECAY = 0.05
|
|
25
|
+
SALIENCE_FLOOR = 0.01
|
|
26
|
+
|
|
27
|
+
SPEECH_MODES = %i[
|
|
28
|
+
planning rehearsal monitoring evaluating
|
|
29
|
+
questioning affirming narrating debating
|
|
30
|
+
comforting warning remembering imagining
|
|
31
|
+
].freeze
|
|
32
|
+
|
|
33
|
+
VOICE_TYPES = %i[
|
|
34
|
+
rational emotional cautious bold
|
|
35
|
+
critical supportive curious skeptical
|
|
36
|
+
].freeze
|
|
37
|
+
|
|
38
|
+
URGENCY_LABELS = {
|
|
39
|
+
(0.8..) => :critical,
|
|
40
|
+
(0.6...0.8) => :high,
|
|
41
|
+
(0.4...0.6) => :moderate,
|
|
42
|
+
(0.2...0.4) => :low,
|
|
43
|
+
(..0.2) => :background
|
|
44
|
+
}.freeze
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module InnerSpeech
|
|
6
|
+
module Helpers
|
|
7
|
+
class InnerVoice
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
attr_reader :stream, :voices, :active_voice, :history
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@stream = SpeechStream.new
|
|
14
|
+
@voices = VOICE_TYPES.dup
|
|
15
|
+
@active_voice = :rational
|
|
16
|
+
@history = []
|
|
17
|
+
@speed = CONTROLLED_SPEED
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def speak(content:, mode: :narrating, topic: :general, **)
|
|
21
|
+
utterance = @stream.append(
|
|
22
|
+
content: content,
|
|
23
|
+
mode: mode,
|
|
24
|
+
voice: @active_voice,
|
|
25
|
+
topic: topic,
|
|
26
|
+
**
|
|
27
|
+
)
|
|
28
|
+
record_event(:speak, utterance_id: utterance&.id) if utterance
|
|
29
|
+
utterance
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def switch_voice(voice:)
|
|
33
|
+
sym = voice.to_sym
|
|
34
|
+
return nil unless VOICE_TYPES.include?(sym)
|
|
35
|
+
|
|
36
|
+
old_voice = @active_voice
|
|
37
|
+
@active_voice = sym
|
|
38
|
+
record_event(:switch_voice, from: old_voice, to: sym)
|
|
39
|
+
@active_voice
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def plan(content:, topic: :general, **)
|
|
43
|
+
speak(content: content, mode: :planning, topic: topic, **)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def rehearse(content:, topic: :general, **)
|
|
47
|
+
speak(content: content, mode: :rehearsal, topic: topic, **)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def question(content:, topic: :general, **)
|
|
51
|
+
speak(content: content, mode: :questioning, topic: topic, **)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def evaluate(content:, topic: :general, **)
|
|
55
|
+
speak(content: content, mode: :evaluating, topic: topic, **)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def warn(content:, topic: :general, **)
|
|
59
|
+
speak(content: content, mode: :warning, topic: topic, urgency: 0.8, **)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def debate(content_a:, content_b:, topic: :general, **)
|
|
63
|
+
old_voice = @active_voice
|
|
64
|
+
@active_voice = :bold
|
|
65
|
+
utt_a = speak(content: content_a, mode: :debating, topic: topic, **)
|
|
66
|
+
@active_voice = :cautious
|
|
67
|
+
utt_b = speak(content: content_b, mode: :debating, topic: topic, **)
|
|
68
|
+
@active_voice = old_voice
|
|
69
|
+
[utt_a, utt_b].compact
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def interrupt(content:, **)
|
|
73
|
+
utterance = @stream.interrupt(content: content, **)
|
|
74
|
+
record_event(:interrupt, utterance_id: utterance&.id) if utterance
|
|
75
|
+
utterance
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
SPEED_MAP = {
|
|
79
|
+
automatic: AUTOMATIC_SPEED,
|
|
80
|
+
controlled: CONTROLLED_SPEED,
|
|
81
|
+
egocentric: EGOCENTRIC_SPEED
|
|
82
|
+
}.freeze
|
|
83
|
+
|
|
84
|
+
def set_speed(mode:)
|
|
85
|
+
@speed = SPEED_MAP.fetch(mode, CONTROLLED_SPEED)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def ruminating?
|
|
89
|
+
@stream.ruminating?
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def break_rumination(redirect_topic:)
|
|
93
|
+
return false unless ruminating?
|
|
94
|
+
|
|
95
|
+
speak(content: 'Let me think about something else.', mode: :narrating, topic: redirect_topic)
|
|
96
|
+
true
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def recent_speech(count: 5)
|
|
100
|
+
@stream.recent(count: count)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def narrative
|
|
104
|
+
@stream.narrative
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def condensed_narrative
|
|
108
|
+
@stream.condensed_stream.join(' ')
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def tick
|
|
112
|
+
@stream.decay_all
|
|
113
|
+
@stream.to_h.merge(active_voice: @active_voice, speed: @speed)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def to_h
|
|
117
|
+
{
|
|
118
|
+
active_voice: @active_voice,
|
|
119
|
+
speed: @speed,
|
|
120
|
+
stream_size: @stream.size,
|
|
121
|
+
ruminating: ruminating?,
|
|
122
|
+
total_utterances: @stream.counter,
|
|
123
|
+
history_size: @history.size
|
|
124
|
+
}
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
private
|
|
128
|
+
|
|
129
|
+
def record_event(type, **details)
|
|
130
|
+
@history << { type: type, at: Time.now.utc }.merge(details)
|
|
131
|
+
@history.shift while @history.size > MAX_HISTORY
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module InnerSpeech
|
|
6
|
+
module Helpers
|
|
7
|
+
class SpeechStream
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
attr_reader :utterances, :counter
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@utterances = []
|
|
14
|
+
@counter = 0
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def append(content:, mode: :narrating, **)
|
|
18
|
+
return nil if @utterances.size >= MAX_STREAM_LENGTH
|
|
19
|
+
|
|
20
|
+
@counter += 1
|
|
21
|
+
utterance = Utterance.new(
|
|
22
|
+
id: :"utt_#{@counter}",
|
|
23
|
+
content: content,
|
|
24
|
+
mode: mode,
|
|
25
|
+
**
|
|
26
|
+
)
|
|
27
|
+
@utterances << utterance
|
|
28
|
+
utterance
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def current
|
|
32
|
+
@utterances.last
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def recent(count: 5)
|
|
36
|
+
@utterances.last(count).map(&:to_h)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def by_mode(mode:)
|
|
40
|
+
@utterances.select { |u| u.mode == mode }.map(&:to_h)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def by_voice(voice:)
|
|
44
|
+
@utterances.select { |u| u.voice == voice }.map(&:to_h)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def by_topic(topic:)
|
|
48
|
+
@utterances.select { |u| u.topic == topic }.map(&:to_h)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def salient
|
|
52
|
+
@utterances.select(&:salient?).map(&:to_h)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def urgent
|
|
56
|
+
@utterances.select(&:urgent?).map(&:to_h)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def ruminating?
|
|
60
|
+
return false if @utterances.size < RUMINATION_THRESHOLD
|
|
61
|
+
|
|
62
|
+
recent_topics = @utterances.last(RUMINATION_THRESHOLD).map(&:topic)
|
|
63
|
+
recent_topics.uniq.size == 1
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def rumination_topic
|
|
67
|
+
return nil unless ruminating?
|
|
68
|
+
|
|
69
|
+
@utterances.last&.topic
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def decay_all
|
|
73
|
+
@utterances.each(&:decay_salience!)
|
|
74
|
+
prune_stale
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def interrupt(content:, mode: :warning, **)
|
|
78
|
+
append(content: content, mode: mode, urgency: 0.9, salience: 0.9, **)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def condensed_stream
|
|
82
|
+
@utterances.select(&:salient?).map(&:condensed_content)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def narrative
|
|
86
|
+
@utterances.map(&:content).join(' ')
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def clear
|
|
90
|
+
@utterances.clear
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def size
|
|
94
|
+
@utterances.size
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def to_h
|
|
98
|
+
{
|
|
99
|
+
size: @utterances.size,
|
|
100
|
+
total_generated: @counter,
|
|
101
|
+
ruminating: ruminating?,
|
|
102
|
+
rumination_topic: rumination_topic,
|
|
103
|
+
salient_count: @utterances.count(&:salient?),
|
|
104
|
+
urgent_count: @utterances.count(&:urgent?),
|
|
105
|
+
mode_distribution: mode_distribution
|
|
106
|
+
}
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
private
|
|
110
|
+
|
|
111
|
+
def prune_stale
|
|
112
|
+
@utterances.reject! { |u| u.salience <= SALIENCE_FLOOR }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def mode_distribution
|
|
116
|
+
dist = Hash.new(0)
|
|
117
|
+
@utterances.each { |u| dist[u.mode] += 1 }
|
|
118
|
+
dist
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module InnerSpeech
|
|
6
|
+
module Helpers
|
|
7
|
+
class Utterance
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
attr_reader :id, :content, :mode, :voice, :topic,
|
|
11
|
+
:urgency, :salience, :source_subsystem, :created_at
|
|
12
|
+
|
|
13
|
+
def initialize(id:, content:, mode: :narrating, **opts)
|
|
14
|
+
@id = id
|
|
15
|
+
@content = content
|
|
16
|
+
@mode = resolve_mode(mode)
|
|
17
|
+
apply_opts(opts)
|
|
18
|
+
@created_at = Time.now.utc
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def condensed_content
|
|
22
|
+
words = @content.split
|
|
23
|
+
keep = [(words.size * CONDENSATION_RATIO).ceil, 1].max
|
|
24
|
+
words.first(keep).join(' ')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def urgent?
|
|
28
|
+
@urgency >= 0.6
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def background?
|
|
32
|
+
@urgency < 0.2
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def decay_salience!
|
|
36
|
+
@salience = [@salience - SALIENCE_DECAY, SALIENCE_FLOOR].max
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def salient?
|
|
40
|
+
@salience >= 0.3
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def urgency_label
|
|
44
|
+
URGENCY_LABELS.each { |range, lbl| return lbl if range.cover?(@urgency) }
|
|
45
|
+
:background
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def to_h
|
|
49
|
+
{
|
|
50
|
+
id: @id,
|
|
51
|
+
content: @content,
|
|
52
|
+
condensed: condensed_content,
|
|
53
|
+
mode: @mode,
|
|
54
|
+
voice: @voice,
|
|
55
|
+
topic: @topic,
|
|
56
|
+
urgency: @urgency.round(4),
|
|
57
|
+
salience: @salience.round(4),
|
|
58
|
+
source_subsystem: @source_subsystem,
|
|
59
|
+
urgency_label: urgency_label
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def apply_opts(opts)
|
|
66
|
+
@voice = resolve_voice(opts.fetch(:voice, :rational))
|
|
67
|
+
@topic = opts.fetch(:topic, :general)
|
|
68
|
+
@urgency = opts.fetch(:urgency, 0.5).to_f.clamp(0.0, 1.0)
|
|
69
|
+
@salience = opts.fetch(:salience, 0.5).to_f.clamp(0.0, 1.0)
|
|
70
|
+
@source_subsystem = opts.fetch(:source_subsystem, :unknown)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def resolve_mode(mode)
|
|
74
|
+
sym = mode.to_sym
|
|
75
|
+
SPEECH_MODES.include?(sym) ? sym : :narrating
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def resolve_voice(voice)
|
|
79
|
+
sym = voice.to_sym
|
|
80
|
+
VOICE_TYPES.include?(sym) ? sym : :rational
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module InnerSpeech
|
|
6
|
+
module Runners
|
|
7
|
+
module InnerSpeech
|
|
8
|
+
include Helpers::Constants
|
|
9
|
+
include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
|
|
10
|
+
|
|
11
|
+
def inner_speak(content:, mode: :narrating, topic: :general, **)
|
|
12
|
+
utterance = voice.speak(content: content, mode: mode, topic: topic)
|
|
13
|
+
return { success: false, reason: :stream_full } unless utterance
|
|
14
|
+
|
|
15
|
+
{ success: true, utterance_id: utterance.id, mode: utterance.mode }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def inner_plan(content:, topic: :general, **)
|
|
19
|
+
utterance = voice.plan(content: content, topic: topic)
|
|
20
|
+
return { success: false, reason: :stream_full } unless utterance
|
|
21
|
+
|
|
22
|
+
{ success: true, utterance_id: utterance.id }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def inner_question(content:, topic: :general, **)
|
|
26
|
+
utterance = voice.question(content: content, topic: topic)
|
|
27
|
+
return { success: false, reason: :stream_full } unless utterance
|
|
28
|
+
|
|
29
|
+
{ success: true, utterance_id: utterance.id }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def inner_debate(content_a:, content_b:, topic: :general, **)
|
|
33
|
+
results = voice.debate(content_a: content_a, content_b: content_b, topic: topic)
|
|
34
|
+
{ success: true, utterances: results.map(&:id), count: results.size }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def switch_inner_voice(voice_type:, **)
|
|
38
|
+
result = voice.switch_voice(voice: voice_type)
|
|
39
|
+
return { success: false, reason: :invalid_voice } unless result
|
|
40
|
+
|
|
41
|
+
{ success: true, active_voice: result }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def inner_interrupt(content:, **)
|
|
45
|
+
utterance = voice.interrupt(content: content)
|
|
46
|
+
return { success: false, reason: :stream_full } unless utterance
|
|
47
|
+
|
|
48
|
+
{ success: true, utterance_id: utterance.id }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def break_inner_rumination(redirect_topic: :general, **)
|
|
52
|
+
result = voice.break_rumination(redirect_topic: redirect_topic)
|
|
53
|
+
{ success: true, rumination_broken: result }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def recent_inner_speech(count: 5, **)
|
|
57
|
+
speech = voice.recent_speech(count: count)
|
|
58
|
+
{ success: true, utterances: speech, count: speech.size }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def inner_narrative(**)
|
|
62
|
+
{ success: true, narrative: voice.narrative, condensed: voice.condensed_narrative }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def update_inner_speech(**)
|
|
66
|
+
result = voice.tick
|
|
67
|
+
{ success: true }.merge(result)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def inner_speech_stats(**)
|
|
71
|
+
{ success: true }.merge(voice.to_h)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def voice
|
|
77
|
+
@voice ||= Helpers::InnerVoice.new
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lex-inner-speech
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Esity
|
|
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: Vygotsky inner speech for LegionIO — internal monologue, dialogic voices,
|
|
27
|
+
rumination detection, and speech condensation
|
|
28
|
+
email:
|
|
29
|
+
- matthewdiverson@gmail.com
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- lib/legion/extensions/inner_speech/client.rb
|
|
35
|
+
- lib/legion/extensions/inner_speech/helpers/constants.rb
|
|
36
|
+
- lib/legion/extensions/inner_speech/helpers/inner_voice.rb
|
|
37
|
+
- lib/legion/extensions/inner_speech/helpers/speech_stream.rb
|
|
38
|
+
- lib/legion/extensions/inner_speech/helpers/utterance.rb
|
|
39
|
+
- lib/legion/extensions/inner_speech/runners/inner_speech.rb
|
|
40
|
+
- lib/legion/extensions/inner_speech/version.rb
|
|
41
|
+
homepage: https://github.com/LegionIO/lex-inner-speech
|
|
42
|
+
licenses:
|
|
43
|
+
- MIT
|
|
44
|
+
metadata:
|
|
45
|
+
homepage_uri: https://github.com/LegionIO/lex-inner-speech
|
|
46
|
+
source_code_uri: https://github.com/LegionIO/lex-inner-speech
|
|
47
|
+
documentation_uri: https://github.com/LegionIO/lex-inner-speech/blob/master/README.md
|
|
48
|
+
changelog_uri: https://github.com/LegionIO/lex-inner-speech/blob/master/CHANGELOG.md
|
|
49
|
+
bug_tracker_uri: https://github.com/LegionIO/lex-inner-speech/issues
|
|
50
|
+
rubygems_mfa_required: 'true'
|
|
51
|
+
rdoc_options: []
|
|
52
|
+
require_paths:
|
|
53
|
+
- lib
|
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
55
|
+
requirements:
|
|
56
|
+
- - ">="
|
|
57
|
+
- !ruby/object:Gem::Version
|
|
58
|
+
version: '3.4'
|
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
|
+
requirements:
|
|
61
|
+
- - ">="
|
|
62
|
+
- !ruby/object:Gem::Version
|
|
63
|
+
version: '0'
|
|
64
|
+
requirements: []
|
|
65
|
+
rubygems_version: 3.6.9
|
|
66
|
+
specification_version: 4
|
|
67
|
+
summary: Inner speech engine for LegionIO
|
|
68
|
+
test_files: []
|