@extentos/mcp-server 0.0.71 → 0.0.72
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codeExamples.d.ts","sourceRoot":"","sources":["../../../src/tools/data/codeExamples.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE;QACJ,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;
|
|
1
|
+
{"version":3,"file":"codeExamples.d.ts","sourceRoot":"","sources":["../../../src/tools/data/codeExamples.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE;QACJ,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AA+0BD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAQrD,CAAC;AAEF,eAAO,MAAM,qBAAqB,UAAoC,CAAC"}
|
|
@@ -17,7 +17,6 @@ const VOICE_QA_ASSISTANT = {
|
|
|
17
17
|
code: {
|
|
18
18
|
kotlin: `import com.extentos.glasses.core.AudioRecordConfig
|
|
19
19
|
import com.extentos.glasses.core.ExtentosGlasses
|
|
20
|
-
import com.extentos.glasses.core.Transcript
|
|
21
20
|
import com.extentos.glasses.core.valueOrNull
|
|
22
21
|
|
|
23
22
|
class CoachHandler(
|
|
@@ -27,15 +26,27 @@ class CoachHandler(
|
|
|
27
26
|
) {
|
|
28
27
|
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
|
29
28
|
|
|
30
|
-
fun start()
|
|
31
|
-
glasses.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
fun start() {
|
|
30
|
+
// glasses.voice.onPhrase registers a wake phrase + handler in one
|
|
31
|
+
// call. The library subscribes to transcriptions() under the
|
|
32
|
+
// hood; while the handler is running, "isActive" flips true so
|
|
33
|
+
// any declared stops can fire. Registration also surfaces the
|
|
34
|
+
// phrase on the connection page (\"Say to me: 'ask my coach'\")
|
|
35
|
+
// and the simulator's right-rail click-to-fire chips.
|
|
36
|
+
//
|
|
37
|
+
// For complex matching (regex, stateful guards), subscribe to
|
|
38
|
+
// glasses.audio.transcriptions() directly and optionally call
|
|
39
|
+
// glasses.voice.registerHint(...) to keep UI affordances in
|
|
40
|
+
// sync. See the matcher gotcha below.
|
|
41
|
+
glasses.voice.onPhrase(
|
|
42
|
+
phrase = "ask my coach",
|
|
43
|
+
label = "Ask",
|
|
44
|
+
stops = listOf("stop"),
|
|
45
|
+
) {
|
|
35
46
|
glasses.audio.speak("What would you like to know?")
|
|
36
47
|
|
|
37
|
-
// Multi-turn loop: keep listening until user goes silent
|
|
38
|
-
// says "stop". Each turn captures one utterance via the
|
|
48
|
+
// Multi-turn loop: keep listening until user goes silent
|
|
49
|
+
// or says "stop". Each turn captures one utterance via the
|
|
39
50
|
// built-in silence-VAD (silence_timeout_seconds = 3).
|
|
40
51
|
while (currentCoroutineContext().isActive) {
|
|
41
52
|
val recording = glasses.audio.recordDiscrete(
|
|
@@ -60,7 +71,7 @@ class CoachHandler(
|
|
|
60
71
|
private let glasses: any ExtentosGlasses
|
|
61
72
|
private let anthropic: AnthropicClient
|
|
62
73
|
private let workouts: WorkoutRepository
|
|
63
|
-
private var
|
|
74
|
+
private var registration: VoiceRegistration?
|
|
64
75
|
|
|
65
76
|
init(glasses: any ExtentosGlasses, anthropic: AnthropicClient, workouts: WorkoutRepository) {
|
|
66
77
|
self.glasses = glasses
|
|
@@ -69,41 +80,48 @@ class CoachHandler(
|
|
|
69
80
|
}
|
|
70
81
|
|
|
71
82
|
func start() {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
83
|
+
// glasses.voice.onPhrase mirrors the Android API: register the
|
|
84
|
+
// wake phrase + handler in one call, plus optional 'stops' for
|
|
85
|
+
// the connection page / simulator UI to render nested affordances.
|
|
86
|
+
registration = glasses.voice.onPhrase(
|
|
87
|
+
phrase: "ask my coach",
|
|
88
|
+
label: "Ask",
|
|
89
|
+
stops: ["stop"]
|
|
90
|
+
) { [weak self] in
|
|
91
|
+
await self?.runConversation()
|
|
92
|
+
}
|
|
93
|
+
}
|
|
77
94
|
|
|
78
|
-
|
|
95
|
+
private func runConversation() async {
|
|
96
|
+
_ = await glasses.audio.speak("What would you like to know?")
|
|
79
97
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
98
|
+
// Multi-turn loop — silence-VAD per turn.
|
|
99
|
+
while !Task.isCancelled {
|
|
100
|
+
let result = await glasses.audio.recordDiscrete(
|
|
101
|
+
config: AudioRecordConfig(silenceTimeoutSeconds: 3)
|
|
102
|
+
)
|
|
103
|
+
guard case .success(let recording) = result else { break }
|
|
86
104
|
|
|
87
|
-
|
|
88
|
-
|
|
105
|
+
let question = recording.transcript.trimmingCharacters(in: .whitespaces)
|
|
106
|
+
if question.isEmpty || question.lowercased().contains("stop") { break }
|
|
89
107
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
}
|
|
108
|
+
if let answer = try? await anthropic.ask(
|
|
109
|
+
question: question,
|
|
110
|
+
workoutHistory: workouts.recent()
|
|
111
|
+
) {
|
|
112
|
+
_ = await glasses.audio.speak(answer)
|
|
97
113
|
}
|
|
98
114
|
}
|
|
99
115
|
}
|
|
100
116
|
|
|
101
|
-
func stop() {
|
|
117
|
+
func stop() { registration?.cancel() }
|
|
102
118
|
}`,
|
|
103
119
|
},
|
|
104
|
-
explanation: "
|
|
120
|
+
explanation: "Four SDK primitives wired together: (1) glasses.voice.onPhrase(phrase, label, stops) { handler } — sugar over glasses.audio.transcriptions() that ALSO surfaces the phrase on the connection page and the simulator's click-to-fire panel; matches by case-insensitive substring on the FINAL transcript, runs the handler with isActive=true so nested stops can fire. (2) glasses.audio.recordDiscrete(silenceTimeoutSeconds) — one-shot capture that auto-stops on N seconds of silence and returns the transcribed text. (3) glasses.audio.speak() — TTS via the platform engine. (4) Customers who need regex / stateful matching can subscribe to glasses.audio.transcriptions() directly and optionally call glasses.voice.registerHint(...) to keep the UI affordances in sync. The while-loop is multi-turn voice mode (the F23 friction-log finding); break-condition is silence (recordDiscrete returns null), an empty utterance, or the user saying 'stop'.",
|
|
105
121
|
gotchas: [
|
|
106
|
-
"transcriptions()
|
|
122
|
+
"glasses.voice.onPhrase wraps glasses.audio.transcriptions() with a default case-insensitive `contains` match. For exact / regex / stateful matching, drop down to transcriptions().collect { ... is Transcript.Final ... } and (optionally) call glasses.voice.registerHint(phrase, label, stops) to keep the UI affordances visible. Both forms coexist.",
|
|
123
|
+
"Voice hint cards on the simulator's right rail fire by injecting the phrase as a synthetic stt_transcript — the dispatch path matches a real utterance bit-for-bit, so any matcher you write (onPhrase or raw) is exercised identically in sim and production.",
|
|
124
|
+
"If you need raw access: transcriptions() yields BOTH partial and final transcripts — Transcript is a sealed interface (Partial | Final). Always pattern-match `is Transcript.Final` before reading t.text, or you'll fire the wake on a half-heard phrase. Swift uses .partial/.final enum cases.",
|
|
107
125
|
"recordDiscrete returns ExtentosResult<AudioRecording, AudioError> — unwrap with .valueOrNull() (Kotlin) or `case .success(let r)` (Swift). The Kotlin Result/getOrNull pattern from kotlin.Result does NOT apply here; ExtentosResult is its own type defined in com.extentos.glasses.core.Errors.",
|
|
108
126
|
"recordDiscrete blocks until silence — call it from a coroutine/Task that's safe to suspend. Inside the while-loop is fine because it's already in a launched scope. See getCapabilityGuide('record_audio') for the full silence-VAD gotchas (maxDurationSeconds cap, raw_audio_uri shape, HFP routing).",
|
|
109
127
|
"Re-entrancy: the OUTER transcriptions() collector and the INNER recordDiscrete BOTH talk to the platform STT engine, but on Meta DAT they share the same mic stream — recordDiscrete owns it exclusively for the duration of its call. While recordDiscrete is capturing, the outer transcriptions Flow may pause (no emissions arrive) and then resume after recordDiscrete returns. Implication: the wake-phrase matcher won't re-fire on the recorded utterance unless you LEAVE the inner loop and the user re-says the wake phrase. The outer collector resuming mid-utterance after recordDiscrete returns is also harmless — the partial that triggers wake-match is the user's NEXT utterance, not the previous question.",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codeExamples.js","sourceRoot":"","sources":["../../../src/tools/data/codeExamples.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,sEAAsE;AACtE,sEAAsE;AACtE,uDAAuD;AACvD,sCAAsC;AACtC,EAAE;AACF,qEAAqE;AACrE,uDAAuD;AACvD,wEAAwE;AACxE,kEAAkE;AAClE,oEAAoE;AACpE,2DAA2D;AAe3D,MAAM,kBAAkB,GAAgB;IACtC,OAAO,EAAE,oBAAoB;IAC7B,KAAK,EAAE,qDAAqD;IAC5D,WAAW,EACT,kSAAkS;IACpS,IAAI,EAAE;QACJ,MAAM,EAAE
|
|
1
|
+
{"version":3,"file":"codeExamples.js","sourceRoot":"","sources":["../../../src/tools/data/codeExamples.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
// scaffold a project pointing at 1.0.0 (no probe code) while running
|
|
7
7
|
// 0.0.7+ server-side smarts that needed 1.1.x to function.
|
|
8
8
|
//
|
|
9
|
-
// Pre-public-Maven note: 1.1.
|
|
9
|
+
// Pre-public-Maven note: 1.1.30-pair currently lives only on the dev's
|
|
10
10
|
// mavenLocal (./gradlew :glasses-core:publishToMavenLocal). Until a
|
|
11
11
|
// public Maven Central / JitPack publish lands, scaffolded projects
|
|
12
12
|
// require the dev to run mavenLocal-publish first. Document next to
|
|
13
13
|
// the dependency notation in generateConnectionModule.
|
|
14
14
|
export const VERSION_INFO = {
|
|
15
|
-
latestStable: "1.1.
|
|
15
|
+
latestStable: "1.1.30-pair",
|
|
16
16
|
specVersion: "1.0",
|
|
17
17
|
android: {
|
|
18
18
|
minimumSdk: 31,
|
|
@@ -34,7 +34,7 @@ export const VERSION_INFO = {
|
|
|
34
34
|
kotlinVersion: "2.1.20",
|
|
35
35
|
// Toolchain minimums (F-R4-8 from DOGFOOD_R4). The library's transitive
|
|
36
36
|
// Compose deps determine the floor:
|
|
37
|
-
// - com.extentos:glasses-ui:1.1.
|
|
37
|
+
// - com.extentos:glasses-ui:1.1.30-pair brings in androidx.compose.* 1.9.0
|
|
38
38
|
// (via compose-bom 2024.10.00 and direct deps)
|
|
39
39
|
// - Compose 1.9.0 AAR-metadata declares "requires AGP >= 8.6.0"
|
|
40
40
|
// - AGP 8.6+ requires Gradle 8.7+ (Android Gradle Plugin compatibility table)
|
|
@@ -58,13 +58,13 @@ export const VERSION_INFO = {
|
|
|
58
58
|
},
|
|
59
59
|
artifacts: {
|
|
60
60
|
android: {
|
|
61
|
-
core: "com.extentos:glasses:1.1.
|
|
62
|
-
ui: "com.extentos:glasses-ui:1.1.
|
|
63
|
-
debug: "com.extentos:glasses-debug:1.1.
|
|
61
|
+
core: "com.extentos:glasses:1.1.30-pair",
|
|
62
|
+
ui: "com.extentos:glasses-ui:1.1.30-pair",
|
|
63
|
+
debug: "com.extentos:glasses-debug:1.1.30-pair",
|
|
64
64
|
},
|
|
65
65
|
ios: {
|
|
66
66
|
package: "https://github.com/extentos/swift-glasses",
|
|
67
|
-
version: "1.1.
|
|
67
|
+
version: "1.1.30-pair",
|
|
68
68
|
products: ["GlassesCore", "GlassesUI", "GlassesDebug", "GlassesLifecycle", "GlassesTesting"],
|
|
69
69
|
},
|
|
70
70
|
},
|