pinecall 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/lib/pinecall/agent/config.rb +52 -6
- data/lib/pinecall/version.rb +1 -1
- data/lib/pinecall/wire/shapes_config.rb +2 -1
- data/sig/pinecall.rbs +4 -3
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e3afca7edf6bc33bb5b6fc9ebed23d76eecac2bb6039fb243d252d379e509e50
|
|
4
|
+
data.tar.gz: f3a39bb373fa2565bc6f49f04429d8f560dcc5cd8d01f9cc8d874f3ae452808d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bd6ea499f8cdbe11a9faf6e25715848c470755e8318705beee191db517446096866e79bd830c32ba77ed4c38c7da134ccdacf90ae973c7169d18baa5a58abd93
|
|
7
|
+
data.tar.gz: 9ee25075169e9581cafd1c58a67eee8b47705cc82bbd3d6aa8568b1a35db6ac20039089bb72de8004bbd973772679725208c3fdca5d469a8b292b2de53badd63
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,15 @@ version number is the human's call.
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.0.6] — A greeting is words or :improvise, a hangup is words or true, and the ears choose who ends the turn (2026-10-10)
|
|
10
|
+
|
|
11
|
+
- `greeting "…"` (said as written), `greeting :improvise` (the model opens on its prompt) and
|
|
12
|
+
`greeting improvise("…")` (with an instruction); `interruptible: true` for an opening the caller
|
|
13
|
+
may cut short, which by default they cannot. The `say:` / `reply:` keywords are gone.
|
|
14
|
+
- `hangup "…"` (when, in your words) or `hangup true` (whenever the model judges); `when:` is gone.
|
|
15
|
+
- `stt "…", end_of_turn: :stt | :livekit | :smart_turn`: who says the caller's turn is over, as
|
|
16
|
+
@pinecall/agents 0.9.26 says it. Needs runtime 0.1.43.
|
|
17
|
+
|
|
9
18
|
## [0.0.5] — The class declares its voice, its models and the rest, and wins (2026-10-10)
|
|
10
19
|
|
|
11
20
|
- **A class declares its environment again, and it wins over the settings.** Class macros `voice
|
|
@@ -16,12 +16,38 @@ module Pinecall
|
|
|
16
16
|
ENVIRONMENT = %i[language voice llm stt greeting hangup turn says hears knowledge docs memory record].freeze
|
|
17
17
|
|
|
18
18
|
# The ones written as the wire's own fields, keyword by keyword: `greeting say: "…"`.
|
|
19
|
-
AS_KEYWORDS = %i[
|
|
19
|
+
AS_KEYWORDS = %i[turn knowledge docs memory].freeze
|
|
20
20
|
|
|
21
21
|
NO_VOICE = "a voice the class declares names its vendor and the voice: voice \"<vendor>\", \"<voice id>\""
|
|
22
22
|
|
|
23
|
+
NO_OPENING = "a greeting is the words, as a string, or :improvise for the model's own: improvise(\"…\") gives it an instruction"
|
|
24
|
+
NO_ENDING = "hangup is when the model may end the call, in your words, or true whenever it judges the call done"
|
|
25
|
+
|
|
26
|
+
# The model opens the call: on its prompt alone (an empty instruction), or with this one.
|
|
27
|
+
Improvised = Data.define(:instruction, :interruptible)
|
|
28
|
+
|
|
23
29
|
NOTHING = Object.new.freeze
|
|
24
30
|
|
|
31
|
+
# An opening as the wire says it: words to `say`, or a `reply` the model opens on.
|
|
32
|
+
def self.greeting_of(opening, interruptible)
|
|
33
|
+
said = case opening
|
|
34
|
+
when :improvise then { reply: "" }
|
|
35
|
+
when Improvised then { reply: opening.instruction }
|
|
36
|
+
when String then { say: opening }
|
|
37
|
+
else raise DeclarationRefused, NO_OPENING
|
|
38
|
+
end
|
|
39
|
+
given = opening.is_a?(Improvised) ? opening.interruptible : interruptible
|
|
40
|
+
given.nil? ? said : { **said, allow_interruptions: given }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# When the model may end the call: an empty `when` is whenever it judges.
|
|
44
|
+
def self.hangup_of(ending)
|
|
45
|
+
return { when: "" } if ending == true
|
|
46
|
+
raise DeclarationRefused, NO_ENDING unless ending.is_a?(String) && !ending.strip.empty?
|
|
47
|
+
|
|
48
|
+
{ when: ending }
|
|
49
|
+
end
|
|
50
|
+
|
|
25
51
|
# `vendor/model`, or a vendor alone; the model id keeps every slash after the vendor's.
|
|
26
52
|
def self.model_of(named)
|
|
27
53
|
provider, _slash, model = named.to_s.partition("/")
|
|
@@ -55,11 +81,31 @@ module Pinecall
|
|
|
55
81
|
environment[:llm] = { **Config.model_of(model), temperature:, builds:, options: }.compact
|
|
56
82
|
end
|
|
57
83
|
|
|
58
|
-
# The ears, `vendor/model` or a vendor alone
|
|
59
|
-
|
|
84
|
+
# The ears, `vendor/model` or a vendor alone, and who says the caller's turn is over:
|
|
85
|
+
# `end_of_turn: "stt"` the ears themselves (Deepgram Flux), `"livekit"` or `"smart-turn"`.
|
|
86
|
+
def stt(model = NOTHING, builds: nil, options: nil, end_of_turn: nil)
|
|
60
87
|
return environment[:stt] if model.equal?(NOTHING)
|
|
61
88
|
|
|
62
|
-
|
|
89
|
+
ends = end_of_turn&.to_s&.tr("_", "-")
|
|
90
|
+
environment[:stt] = { **Config.model_of(model), builds:, options:, end_of_turn: ends }.compact
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# How a call opens: the words, said as written, or :improvise for the model's own. The
|
|
94
|
+
# caller cannot cut it short unless `interruptible: true`.
|
|
95
|
+
def greeting(opening = NOTHING, interruptible: nil)
|
|
96
|
+
return environment[:greeting] if opening.equal?(NOTHING)
|
|
97
|
+
|
|
98
|
+
environment[:greeting] = Config.greeting_of(opening, interruptible)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# The model opens the call with this instruction: `greeting improvise("…")`.
|
|
102
|
+
def improvise(instruction = "", interruptible: nil) = Improvised.new(instruction, interruptible)
|
|
103
|
+
|
|
104
|
+
# When the model may end the call: in your words, or `true` whenever it judges it done.
|
|
105
|
+
def hangup(ending = NOTHING)
|
|
106
|
+
return environment[:hangup] if ending.equal?(NOTHING)
|
|
107
|
+
|
|
108
|
+
environment[:hangup] = Config.hangup_of(ending)
|
|
63
109
|
end
|
|
64
110
|
|
|
65
111
|
# `language "es"`, `says [{ word: "GSA", spoken: "ge ese a" }]`, `record false`.
|
|
@@ -78,8 +124,8 @@ module Pinecall
|
|
|
78
124
|
environment[:hears] = words.flatten
|
|
79
125
|
end
|
|
80
126
|
|
|
81
|
-
# `
|
|
82
|
-
# `
|
|
127
|
+
# `turn endpointing_ms: 300`, `docs base: "…", k: 4`, `memory remember: […], forget: […]`,
|
|
128
|
+
# `knowledge path: "…", text: "…"`.
|
|
83
129
|
AS_KEYWORDS.each do |field|
|
|
84
130
|
define_method(field) do |**given|
|
|
85
131
|
return environment[field] if given.empty?
|
data/lib/pinecall/version.rb
CHANGED
|
@@ -23,7 +23,8 @@ module Pinecall
|
|
|
23
23
|
model: { kind: :str, required: true },
|
|
24
24
|
temperature: { kind: :float },
|
|
25
25
|
builds: { kind: :str },
|
|
26
|
-
options: { kind: :json }
|
|
26
|
+
options: { kind: :json },
|
|
27
|
+
end_of_turn: { kind: :enum, values: %w[stt livekit smart-turn] }
|
|
27
28
|
}.freeze,
|
|
28
29
|
"TurnConfig" => {
|
|
29
30
|
min_interruption_words: { kind: :int },
|
data/sig/pinecall.rbs
CHANGED
|
@@ -87,13 +87,14 @@ module Pinecall
|
|
|
87
87
|
# the environment the class declares, each over the agent's settings
|
|
88
88
|
def self.voice: (?String, ?String?, ?model: String?, ?builds: String?, ?options: Hash[untyped, untyped]?) -> untyped
|
|
89
89
|
def self.llm: (?String, ?temperature: Float?, ?builds: String?, ?options: Hash[untyped, untyped]?) -> untyped
|
|
90
|
-
def self.stt: (?String, ?builds: String?, ?options: Hash[untyped, untyped]?) -> untyped
|
|
90
|
+
def self.stt: (?String, ?builds: String?, ?options: Hash[untyped, untyped]?, ?end_of_turn: (String | Symbol)?) -> untyped
|
|
91
91
|
def self.language: (?String) -> untyped
|
|
92
92
|
def self.says: (?Array[Hash[Symbol, String]]) -> untyped
|
|
93
93
|
def self.record: (?bool) -> untyped
|
|
94
94
|
def self.hears: (*String | Array[String]) -> untyped
|
|
95
|
-
def self.greeting: (
|
|
96
|
-
def self.
|
|
95
|
+
def self.greeting: (?(String | Symbol | untyped), ?interruptible: bool?) -> untyped
|
|
96
|
+
def self.improvise: (?String, ?interruptible: bool?) -> untyped
|
|
97
|
+
def self.hangup: (?(String | true)) -> untyped
|
|
97
98
|
def self.turn: (**untyped) -> untyped
|
|
98
99
|
def self.knowledge: (**untyped) -> untyped
|
|
99
100
|
def self.docs: (**untyped) -> untyped
|