@extentos/mcp-server 0.0.67 → 0.0.69
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.
- package/dist/tools/data/capabilityPatterns.d.ts.map +1 -1
- package/dist/tools/data/capabilityPatterns.js +12 -4
- package/dist/tools/data/capabilityPatterns.js.map +1 -1
- package/dist/tools/data/codeExamples.d.ts.map +1 -1
- package/dist/tools/data/codeExamples.js +216 -32
- package/dist/tools/data/codeExamples.js.map +1 -1
- package/dist/tools/handlers/getCredentialGuide.d.ts.map +1 -1
- package/dist/tools/handlers/getCredentialGuide.js +58 -23
- package/dist/tools/handlers/getCredentialGuide.js.map +1 -1
- package/dist/tools/handlers/inspectIntegration.d.ts.map +1 -1
- package/dist/tools/handlers/inspectIntegration.js +6 -2
- package/dist/tools/handlers/inspectIntegration.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilityPatterns.d.ts","sourceRoot":"","sources":["../../../src/tools/data/capabilityPatterns.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;
|
|
1
|
+
{"version":3,"file":"capabilityPatterns.d.ts","sourceRoot":"","sources":["../../../src/tools/data/capabilityPatterns.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAiTD,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAS7D,CAAC;AAEF,eAAO,MAAM,yBAAyB,UAAwC,CAAC"}
|
|
@@ -11,16 +11,22 @@ const CAPTURE_PHOTO = {
|
|
|
11
11
|
feature: "capture_photo",
|
|
12
12
|
summary: "One-shot still photo from the glasses camera. Returns a Photo with `uri` (transport-shaped — data: in BrowserSim, file: in RealMeta / LocalSim), width, height, format.",
|
|
13
13
|
kotlin: `import com.extentos.glasses.core.PhotoConfig
|
|
14
|
+
import com.extentos.glasses.core.PhotoFormat
|
|
14
15
|
import com.extentos.glasses.core.Photos
|
|
16
|
+
import com.extentos.glasses.core.Resolution
|
|
15
17
|
import com.extentos.glasses.core.valueOrNull
|
|
16
18
|
|
|
17
19
|
val photo = glasses.camera.capturePhoto(
|
|
18
|
-
PhotoConfig(resolution =
|
|
20
|
+
PhotoConfig(resolution = Resolution.MEDIUM, format = PhotoFormat.JPEG)
|
|
19
21
|
).valueOrNull() ?: return // ExtentosResult.Err — see Errors.kt for failure shapes
|
|
20
22
|
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
// Photo.uri is nullable (library shape — a successful capture can still
|
|
24
|
+
// return a Photo whose URI got dropped at the transport boundary). Null-
|
|
25
|
+
// check before passing to the Photos helpers; loadBase64 / mediaTypeFromUri
|
|
26
|
+
// both require non-null String.
|
|
27
|
+
val uri = photo.uri ?: return
|
|
28
|
+
val base64 = Photos.loadBase64(uri)
|
|
29
|
+
val mediaType = Photos.mediaTypeFromUri(uri) // "image/jpeg"`,
|
|
24
30
|
swift: `let result = await glasses.camera.capturePhoto(
|
|
25
31
|
config: PhotoConfig(resolution: .medium, format: .jpeg)
|
|
26
32
|
)
|
|
@@ -34,6 +40,8 @@ let image = await photo.loadImage()
|
|
|
34
40
|
let base64 = image?.jpegData(compressionQuality: 0.85)?.base64EncodedString()
|
|
35
41
|
let mediaType = "image/jpeg"`,
|
|
36
42
|
gotchas: [
|
|
43
|
+
"PhotoConfig takes TYPED ENUMS, not strings: `PhotoConfig(resolution = Resolution.MEDIUM, format = PhotoFormat.JPEG)`. Resolution enum: LOW, MEDIUM, HIGH. PhotoFormat enum: JPEG, HEIC. Both live in com.extentos.glasses.core (flat package — see library_api topic).",
|
|
44
|
+
"Photo.uri is `String?` (nullable). The Photos helpers (loadBase64 / loadBytes / loadBitmap / mediaTypeFromUri) require non-null String. Null-check `photo.uri` before passing.",
|
|
37
45
|
"Photo URI shape varies by transport (data: vs file:). Use Photos.loadBase64(uri) helpers to bridge — don't try to AsyncImage / URL.init() the URI directly.",
|
|
38
46
|
"Resolution HIGH adds ~400ms latency on Gen 1 hardware vs MEDIUM. MEDIUM is the right default; only use HIGH for downstream models that genuinely need detail.",
|
|
39
47
|
"Capture blocks while outgoing_video_stream is active (camera exclusivity). If both are needed, set audio_video_coexistence_policy = prefer_video.",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilityPatterns.js","sourceRoot":"","sources":["../../../src/tools/data/capabilityPatterns.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,iEAAiE;AACjE,+DAA+D;AAC/D,iCAAiC;AACjC,EAAE;AACF,iEAAiE;AACjE,qEAAqE;AACrE,mEAAmE;AACnE,0CAA0C;AAW1C,MAAM,aAAa,GAAoB;IACrC,OAAO,EAAE,eAAe;IACxB,OAAO,EACL,yKAAyK;IAC3K,MAAM,EAAE
|
|
1
|
+
{"version":3,"file":"capabilityPatterns.js","sourceRoot":"","sources":["../../../src/tools/data/capabilityPatterns.ts"],"names":[],"mappings":"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"}
|
|
@@ -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;AA6zBD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAQrD,CAAC;AAEF,eAAO,MAAM,qBAAqB,UAAoC,CAAC"}
|
|
@@ -196,12 +196,15 @@ const PHOTO_DESCRIBE_VOICE = {
|
|
|
196
196
|
code: {
|
|
197
197
|
kotlin: `import com.extentos.glasses.core.ExtentosGlasses
|
|
198
198
|
import com.extentos.glasses.core.PhotoConfig
|
|
199
|
+
import com.extentos.glasses.core.PhotoFormat
|
|
200
|
+
import com.extentos.glasses.core.Photos
|
|
201
|
+
import com.extentos.glasses.core.Resolution
|
|
199
202
|
import com.extentos.glasses.core.Transcript
|
|
200
203
|
import com.extentos.glasses.core.valueOrNull
|
|
201
204
|
|
|
202
205
|
class VisionHandler(
|
|
203
206
|
private val glasses: ExtentosGlasses,
|
|
204
|
-
private val vision: VisionClient, // USER PROVIDES —
|
|
207
|
+
private val vision: VisionClient, // USER PROVIDES — see getCodeExample('byok_anthropic') for the canonical Vision client
|
|
205
208
|
) {
|
|
206
209
|
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
|
207
210
|
|
|
@@ -211,14 +214,24 @@ class VisionHandler(
|
|
|
211
214
|
if ("describe what you see" !in t.text.lowercase()) return@collect
|
|
212
215
|
|
|
213
216
|
val photo = glasses.camera.capturePhoto(
|
|
214
|
-
PhotoConfig(resolution =
|
|
217
|
+
PhotoConfig(resolution = Resolution.MEDIUM, format = PhotoFormat.JPEG)
|
|
215
218
|
).valueOrNull() ?: run {
|
|
216
219
|
glasses.audio.speak("I couldn't take a photo.")
|
|
217
220
|
return@collect
|
|
218
221
|
}
|
|
222
|
+
val uri = photo.uri ?: run {
|
|
223
|
+
glasses.audio.speak("Photo had no URI.")
|
|
224
|
+
return@collect
|
|
225
|
+
}
|
|
226
|
+
val base64 = Photos.loadBase64(uri) ?: run {
|
|
227
|
+
glasses.audio.speak("Couldn't decode the photo.")
|
|
228
|
+
return@collect
|
|
229
|
+
}
|
|
230
|
+
val mediaType = Photos.mediaTypeFromUri(uri) ?: "image/jpeg"
|
|
219
231
|
|
|
220
232
|
val description = vision.describe(
|
|
221
|
-
|
|
233
|
+
imageBase64 = base64,
|
|
234
|
+
mediaType = mediaType,
|
|
222
235
|
prompt = "Describe this scene briefly, conversationally.",
|
|
223
236
|
)
|
|
224
237
|
glasses.audio.speak(description.ifBlank { "I couldn't describe that one." })
|
|
@@ -274,9 +287,12 @@ class VisionHandler(
|
|
|
274
287
|
},
|
|
275
288
|
explanation: "Voice wake → photo capture → vision LLM → spoken response. The photo URL shape varies by transport (data: in BrowserSim, file: in RealMeta + LocalSim). Android consumers use Photos.loadBase64(uri) / Photos.mediaTypeFromUri(uri) helpers; iOS consumers use the bundled `photo.loadImage()` extension on Photo to materialize a UIImage from either scheme.",
|
|
276
289
|
gotchas: [
|
|
290
|
+
"PhotoConfig takes TYPED ENUMS: `PhotoConfig(resolution = Resolution.MEDIUM, format = PhotoFormat.JPEG)`. Not strings. Same enum types live in com.extentos.glasses.core — see getCapabilityGuide('capture_photo') for the full call shape.",
|
|
291
|
+
"Photo.uri is nullable — guard before passing to Photos.loadBase64 / mediaTypeFromUri. A successful capture can still return a Photo with no URI at the transport boundary.",
|
|
277
292
|
"capturePhoto blocks until the photo is captured (~300-500ms on Meta DAT). Don't call it on a UI thread.",
|
|
278
293
|
"Android: Photos.loadBase64(uri) bridges both data: and file: URIs into bytes ready for Claude Vision / GPT-4V request bodies. iOS: `photo.loadImage()` (extension on Photo) returns a UIImage; for base64 you encode the JPEG/PNG data yourself via Data.base64EncodedString().",
|
|
279
|
-
"Vision LLM response time is 2-8 seconds p95; the user is staring at the glasses waiting. Consider an earcon at capture time so they know it worked.",
|
|
294
|
+
"Vision LLM response time is 2-8 seconds p95; the user is staring at the glasses waiting. Consider an earcon (`glasses.audio.earcon(EarconSound.START)`) at capture time so they know it worked.",
|
|
295
|
+
"VisionClient is a USER-PROVIDED stub — see getCodeExample('byok_anthropic') for the canonical Anthropic Claude Vision wrapper (request shape: content blocks with type:image / source:base64 + type:text). The byok_anthropic pattern is paste-ready in both Kotlin and Swift.",
|
|
280
296
|
],
|
|
281
297
|
relatedFeatures: ["capture_photo", "voice_command", "transcription_incremental"],
|
|
282
298
|
};
|
|
@@ -510,13 +526,15 @@ struct ContentView: View {
|
|
|
510
526
|
};
|
|
511
527
|
const BYOK_ANTHROPIC = {
|
|
512
528
|
pattern: "byok_anthropic",
|
|
513
|
-
title: "BYOK Anthropic Claude API client (
|
|
514
|
-
description: "Minimal AnthropicClient that voice_qa_assistant and photo_describe_voice reference. There is no first-party Anthropic Kotlin SDK; this is the canonical OkHttp + kotlinx.serialization wrapper around POST /v1/messages. iOS uses URLSession + Codable. Paste, then wire the API key through resValue (Android) / Info.plist (iOS) per getCredentialGuide.",
|
|
529
|
+
title: "BYOK Anthropic Claude API client (text + Vision, OkHttp / URLSession)",
|
|
530
|
+
description: "Minimal AnthropicClient that voice_qa_assistant and photo_describe_voice reference. Two methods: `ask(question, history)` for text-only Q&A, `describe(imageBase64, mediaType, prompt)` for Claude Vision (image content blocks). There is no first-party Anthropic Kotlin SDK; this is the canonical OkHttp + kotlinx.serialization wrapper around POST /v1/messages. iOS uses URLSession + Codable. Paste, then wire the API key through resValue (Android) / Info.plist (iOS) per getCredentialGuide.",
|
|
515
531
|
code: {
|
|
516
532
|
kotlin: `import kotlinx.coroutines.Dispatchers
|
|
517
533
|
import kotlinx.coroutines.withContext
|
|
534
|
+
import kotlinx.serialization.SerialName
|
|
518
535
|
import kotlinx.serialization.Serializable
|
|
519
536
|
import kotlinx.serialization.json.Json
|
|
537
|
+
import kotlinx.serialization.json.JsonClassDiscriminator
|
|
520
538
|
import okhttp3.MediaType.Companion.toMediaType
|
|
521
539
|
import okhttp3.OkHttpClient
|
|
522
540
|
import okhttp3.Request
|
|
@@ -533,20 +551,83 @@ class AnthropicClient(
|
|
|
533
551
|
private val maxTokens: Int = 1024,
|
|
534
552
|
private val client: OkHttpClient = OkHttpClient(),
|
|
535
553
|
) {
|
|
536
|
-
private val json = Json { ignoreUnknownKeys = true }
|
|
554
|
+
private val json = Json { ignoreUnknownKeys = true; encodeDefaults = true }
|
|
555
|
+
|
|
556
|
+
// ---- Wire schema ----
|
|
557
|
+
|
|
558
|
+
@Serializable
|
|
559
|
+
private data class ImageSource(
|
|
560
|
+
val type: String = "base64",
|
|
561
|
+
@SerialName("media_type") val mediaType: String,
|
|
562
|
+
val data: String,
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
@OptIn(kotlinx.serialization.ExperimentalSerializationApi::class)
|
|
566
|
+
@JsonClassDiscriminator("type")
|
|
567
|
+
@Serializable
|
|
568
|
+
private sealed interface ContentBlock {
|
|
569
|
+
@Serializable @SerialName("text") data class Text(val text: String) : ContentBlock
|
|
570
|
+
@Serializable @SerialName("image") data class Image(val source: ImageSource) : ContentBlock
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
@Serializable
|
|
574
|
+
private data class Message(val role: String, val content: List<ContentBlock>)
|
|
575
|
+
|
|
576
|
+
@Serializable
|
|
577
|
+
private data class Req(
|
|
578
|
+
val model: String,
|
|
579
|
+
@SerialName("max_tokens") val maxTokens: Int,
|
|
580
|
+
val messages: List<Message>,
|
|
581
|
+
val system: String? = null,
|
|
582
|
+
)
|
|
537
583
|
|
|
538
|
-
@Serializable private data class Msg(val role: String, val content: String)
|
|
539
|
-
@Serializable private data class Req(val model: String, val max_tokens: Int, val messages: List<Msg>)
|
|
540
584
|
@Serializable private data class ResBlock(val type: String, val text: String? = null)
|
|
541
585
|
@Serializable private data class Res(val content: List<ResBlock>)
|
|
542
586
|
|
|
587
|
+
// ---- Public API ----
|
|
588
|
+
|
|
589
|
+
/** Text-only Q&A. Anthropic's content field accepts either a bare String or a
|
|
590
|
+
* list of ContentBlock; we use the list shape so this client can also do Vision. */
|
|
543
591
|
suspend fun ask(question: String, history: List<String> = emptyList()): String =
|
|
592
|
+
post(
|
|
593
|
+
messages = buildList {
|
|
594
|
+
for (turn in history) {
|
|
595
|
+
add(Message("user", listOf(ContentBlock.Text(turn))))
|
|
596
|
+
}
|
|
597
|
+
add(Message("user", listOf(ContentBlock.Text(question))))
|
|
598
|
+
},
|
|
599
|
+
)
|
|
600
|
+
|
|
601
|
+
/** Vision: send one image (base64) + a text prompt. Use Photos.loadBase64(uri) and
|
|
602
|
+
* Photos.mediaTypeFromUri(uri) (from com.extentos.glasses.core.Photos) to source
|
|
603
|
+
* the imageBase64 + mediaType from a Photo returned by glasses.camera.capturePhoto(). */
|
|
604
|
+
suspend fun describe(
|
|
605
|
+
imageBase64: String,
|
|
606
|
+
mediaType: String,
|
|
607
|
+
prompt: String,
|
|
608
|
+
system: String? = null,
|
|
609
|
+
): String = post(
|
|
610
|
+
messages = listOf(
|
|
611
|
+
Message(
|
|
612
|
+
"user",
|
|
613
|
+
listOf(
|
|
614
|
+
ContentBlock.Image(ImageSource(mediaType = mediaType, data = imageBase64)),
|
|
615
|
+
ContentBlock.Text(prompt),
|
|
616
|
+
),
|
|
617
|
+
),
|
|
618
|
+
),
|
|
619
|
+
system = system,
|
|
620
|
+
)
|
|
621
|
+
|
|
622
|
+
// ---- Transport ----
|
|
623
|
+
|
|
624
|
+
private suspend fun post(messages: List<Message>, system: String? = null): String =
|
|
544
625
|
withContext(Dispatchers.IO) {
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
626
|
+
if (apiKey.isBlank()) return@withContext ""
|
|
627
|
+
val body = json.encodeToString(
|
|
628
|
+
Req.serializer(),
|
|
629
|
+
Req(model = model, maxTokens = maxTokens, messages = messages, system = system),
|
|
630
|
+
)
|
|
550
631
|
val request = Request.Builder()
|
|
551
632
|
.url("https://api.anthropic.com/v1/messages")
|
|
552
633
|
.header("x-api-key", apiKey)
|
|
@@ -555,22 +636,36 @@ class AnthropicClient(
|
|
|
555
636
|
.post(body.toRequestBody("application/json".toMediaType()))
|
|
556
637
|
.build()
|
|
557
638
|
client.newCall(request).execute().use { response ->
|
|
558
|
-
val payload = response.body?.string() ?:
|
|
559
|
-
if (!response.isSuccessful)
|
|
639
|
+
val payload = response.body?.string() ?: return@withContext ""
|
|
640
|
+
if (!response.isSuccessful) {
|
|
641
|
+
android.util.Log.w("AnthropicClient", "HTTP \${response.code}: \${payload.take(500)}")
|
|
642
|
+
return@withContext ""
|
|
643
|
+
}
|
|
560
644
|
json.decodeFromString(Res.serializer(), payload)
|
|
561
|
-
.content.firstOrNull { it.type == "text" }?.text
|
|
645
|
+
.content.firstOrNull { it.type == "text" }?.text.orEmpty().trim()
|
|
562
646
|
}
|
|
563
647
|
}
|
|
564
648
|
}
|
|
565
649
|
|
|
566
650
|
// Wire-up — your handler retrieves the API key from the resource string
|
|
567
|
-
// emitted by your build.gradle.kts (see getCredentialGuide
|
|
568
|
-
// resValue pattern), then passes it to a single client instance
|
|
569
|
-
// at Application scope:
|
|
651
|
+
// emitted by your build.gradle.kts (see getCredentialGuide('anthropic')
|
|
652
|
+
// for the resValue pattern), then passes it to a single client instance
|
|
653
|
+
// held at Application scope:
|
|
570
654
|
//
|
|
571
655
|
// val apiKey = context.getString(R.string.anthropic_api_key)
|
|
572
656
|
// val anthropic = AnthropicClient(apiKey)
|
|
573
|
-
//
|
|
657
|
+
//
|
|
658
|
+
// // text:
|
|
659
|
+
// val answer = anthropic.ask("How many bench reps did I do today?")
|
|
660
|
+
//
|
|
661
|
+
// // vision (paired with capture_photo + Photos helpers):
|
|
662
|
+
// val photo = glasses.camera.capturePhoto(
|
|
663
|
+
// PhotoConfig(resolution = Resolution.MEDIUM, format = PhotoFormat.JPEG)
|
|
664
|
+
// ).valueOrNull() ?: return
|
|
665
|
+
// val uri = photo.uri ?: return
|
|
666
|
+
// val b64 = Photos.loadBase64(uri) ?: return
|
|
667
|
+
// val mt = Photos.mediaTypeFromUri(uri) ?: "image/jpeg"
|
|
668
|
+
// val answer = anthropic.describe(b64, mt, "What card is showing?")`,
|
|
574
669
|
swift: `import Foundation
|
|
575
670
|
|
|
576
671
|
actor AnthropicClient {
|
|
@@ -585,17 +680,88 @@ actor AnthropicClient {
|
|
|
585
680
|
self.maxTokens = maxTokens
|
|
586
681
|
}
|
|
587
682
|
|
|
588
|
-
|
|
589
|
-
|
|
683
|
+
// ---- Wire schema ----
|
|
684
|
+
|
|
685
|
+
private struct ImageSource: Codable {
|
|
686
|
+
let type: String // "base64"
|
|
687
|
+
let media_type: String
|
|
688
|
+
let data: String
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
private enum ContentBlock: Codable {
|
|
692
|
+
case text(String)
|
|
693
|
+
case image(ImageSource)
|
|
694
|
+
|
|
695
|
+
private struct TextWire: Codable { let type: String; let text: String }
|
|
696
|
+
private struct ImageWire: Codable { let type: String; let source: ImageSource }
|
|
697
|
+
|
|
698
|
+
func encode(to encoder: Encoder) throws {
|
|
699
|
+
switch self {
|
|
700
|
+
case .text(let t):
|
|
701
|
+
try TextWire(type: "text", text: t).encode(to: encoder)
|
|
702
|
+
case .image(let s):
|
|
703
|
+
try ImageWire(type: "image", source: s).encode(to: encoder)
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
init(from decoder: Decoder) throws {
|
|
708
|
+
// Anthropic responses don't echo image blocks; only text comes back.
|
|
709
|
+
let wire = try TextWire(from: decoder)
|
|
710
|
+
self = .text(wire.text)
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
private struct Message: Codable { let role: String; let content: [ContentBlock] }
|
|
715
|
+
private struct Req: Codable {
|
|
716
|
+
let model: String
|
|
717
|
+
let max_tokens: Int
|
|
718
|
+
let messages: [Message]
|
|
719
|
+
let system: String?
|
|
720
|
+
}
|
|
590
721
|
private struct ResBlock: Codable { let type: String; let text: String? }
|
|
591
722
|
private struct Res: Codable { let content: [ResBlock] }
|
|
592
723
|
|
|
724
|
+
// ---- Public API ----
|
|
725
|
+
|
|
726
|
+
/// Text-only Q&A.
|
|
593
727
|
func ask(question: String, history: [String] = []) async throws -> String {
|
|
594
|
-
var
|
|
595
|
-
|
|
728
|
+
var messages = history.map {
|
|
729
|
+
Message(role: "user", content: [.text($0)])
|
|
730
|
+
}
|
|
731
|
+
messages.append(Message(role: "user", content: [.text(question)]))
|
|
732
|
+
return try await post(messages: messages, system: nil)
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/// Vision: one image (base64) + a text prompt. Source the imageBase64 +
|
|
736
|
+
/// mediaType from a Photo returned by glasses.camera.capturePhoto() and
|
|
737
|
+
/// the photo.loadImage() / data extraction helpers in com.extentos.glasses.core.
|
|
738
|
+
func describe(
|
|
739
|
+
imageBase64: String,
|
|
740
|
+
mediaType: String,
|
|
741
|
+
prompt: String,
|
|
742
|
+
system: String? = nil,
|
|
743
|
+
) async throws -> String {
|
|
744
|
+
let messages = [
|
|
745
|
+
Message(
|
|
746
|
+
role: "user",
|
|
747
|
+
content: [
|
|
748
|
+
.image(ImageSource(type: "base64", media_type: mediaType, data: imageBase64)),
|
|
749
|
+
.text(prompt),
|
|
750
|
+
],
|
|
751
|
+
),
|
|
752
|
+
]
|
|
753
|
+
return try await post(messages: messages, system: system)
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// ---- Transport ----
|
|
757
|
+
|
|
758
|
+
private func post(messages: [Message], system: String?) async throws -> String {
|
|
759
|
+
guard !apiKey.isEmpty else { return "" }
|
|
596
760
|
var request = URLRequest(url: endpoint)
|
|
597
761
|
request.httpMethod = "POST"
|
|
598
|
-
request.httpBody = try JSONEncoder().encode(
|
|
762
|
+
request.httpBody = try JSONEncoder().encode(
|
|
763
|
+
Req(model: model, max_tokens: maxTokens, messages: messages, system: system)
|
|
764
|
+
)
|
|
599
765
|
request.setValue(apiKey, forHTTPHeaderField: "x-api-key")
|
|
600
766
|
request.setValue("2023-06-01", forHTTPHeaderField: "anthropic-version")
|
|
601
767
|
request.setValue("application/json", forHTTPHeaderField: "content-type")
|
|
@@ -620,17 +786,35 @@ actor AnthropicClient {
|
|
|
620
786
|
//
|
|
621
787
|
// let key = Bundle.main.object(forInfoDictionaryKey: "ANTHROPIC_API_KEY") as? String ?? ""
|
|
622
788
|
// let anthropic = AnthropicClient(apiKey: key)
|
|
623
|
-
//
|
|
789
|
+
//
|
|
790
|
+
// // text:
|
|
791
|
+
// let answer = try await anthropic.ask(question: "How many bench reps today?")
|
|
792
|
+
//
|
|
793
|
+
// // vision (paired with capture_photo + photo.loadImage helpers):
|
|
794
|
+
// let result = await glasses.camera.capturePhoto(
|
|
795
|
+
// config: PhotoConfig(resolution: .medium, format: .jpeg)
|
|
796
|
+
// )
|
|
797
|
+
// guard case .success(let photo) = result else { return }
|
|
798
|
+
// guard let image = await photo.loadImage(),
|
|
799
|
+
// let jpeg = image.jpegData(compressionQuality: 0.85) else { return }
|
|
800
|
+
// let b64 = jpeg.base64EncodedString()
|
|
801
|
+
// let answer = try await anthropic.describe(
|
|
802
|
+
// imageBase64: b64,
|
|
803
|
+
// mediaType: "image/jpeg",
|
|
804
|
+
// prompt: "What's the next blackjack move?"
|
|
805
|
+
// )`,
|
|
624
806
|
},
|
|
625
|
-
explanation: "Minimal direct client. There's no first-party Anthropic Kotlin SDK; this is the wire-protocol wrapper voice_qa_assistant and photo_describe_voice patterns reference as `AnthropicClient`. Kotlin uses OkHttp + kotlinx-serialization (
|
|
807
|
+
explanation: "Minimal direct client supporting BOTH text Q&A (`ask`) and Claude Vision (`describe`). There's no first-party Anthropic Kotlin SDK; this is the wire-protocol wrapper voice_qa_assistant and photo_describe_voice patterns reference as `AnthropicClient`. Kotlin uses OkHttp + kotlinx-serialization with a `JsonClassDiscriminator(\"type\")` sealed ContentBlock that mirrors Anthropic's polymorphic content shape (text + image). Swift uses URLSession + Codable with manual encode/decode for the same polymorphism. The customer holds one instance at Application scope and passes it to handlers via DI.",
|
|
626
808
|
gotchas: [
|
|
627
809
|
"API key MUST come from a build-injected resource (resValue on Android, xcconfig on iOS). Don't paste literals — they leak into git. See getCredentialGuide for the storage pattern.",
|
|
628
810
|
"Anthropic-version header is required and version-pinned — bump '2023-06-01' when Anthropic releases a new API version that adds features you need.",
|
|
629
|
-
"
|
|
630
|
-
"
|
|
631
|
-
"
|
|
811
|
+
"Vision content-block shape: each user message's `content` is a LIST of blocks. Image block: `{ type: \"image\", source: { type: \"base64\", media_type, data } }`. Text block: `{ type: \"text\", text }`. Image first, then text prompt — Claude reads them in order. media_type must match what Photos.mediaTypeFromUri returned (image/jpeg, image/png, image/webp).",
|
|
812
|
+
"max_tokens defaults to 1024 here — bump for longer answers, but the glasses TTS engine will speak whatever comes back, so consider trimming on your side before speak() rather than asking for unbounded length. For Vision specifically, 256 is often plenty (you typically want a short action: hit / stand / split, not paragraphs).",
|
|
813
|
+
"history is a list of prior user turns. For real multi-turn you'll likely want to interleave 'user' and 'assistant' roles — extend the schema's role enum and pass alternating turns.",
|
|
814
|
+
"OkHttp's .execute() blocks the calling thread — wrapping in withContext(Dispatchers.IO) keeps it off the main dispatcher. Don't call ask() / describe() from the UI thread directly.",
|
|
815
|
+
"Vision LLM response p95 is 2-8 seconds. Play an earcon (`glasses.audio.earcon(EarconSound.START)`) BEFORE the call so the user knows the request fired.",
|
|
632
816
|
],
|
|
633
|
-
relatedFeatures: [],
|
|
817
|
+
relatedFeatures: ["capture_photo"],
|
|
634
818
|
};
|
|
635
819
|
export const CODE_EXAMPLES = {
|
|
636
820
|
voice_qa_assistant: VOICE_QA_ASSISTANT,
|
|
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwCV;QACE,KAAK,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2CT;KACC;IACD,WAAW,EACT,ojBAAojB;IACtjB,OAAO,EAAE;QACP,2QAA2Q;QAC3Q,oSAAoS;QACpS,ySAAyS;QACzS,msBAAmsB;QACnsB,sIAAsI;QACtI,+HAA+H;QAC/H,yKAAyK;QACzK,0WAA0W;KAC3W;IACD,eAAe,EAAE,CAAC,eAAe,EAAE,2BAA2B,EAAE,cAAc,CAAC;CAChF,CAAC;AAEF,MAAM,cAAc,GAAgB;IAClC,OAAO,EAAE,gBAAgB;IACzB,KAAK,EAAE,gDAAgD;IACvD,WAAW,EACT,uMAAuM;IACzM,IAAI,EAAE;QACJ,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2BV;QACE,KAAK,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgCT;KACC;IACD,WAAW,EACT,+ZAA+Z;IACja,OAAO,EAAE;QACP,8IAA8I;QAC9I,6PAA6P;QAC7P,kLAAkL;KACnL;IACD,eAAe,EAAE,CAAC,2BAA2B,CAAC;CAC/C,CAAC;AAEF,MAAM,oBAAoB,GAAgB;IACxC,OAAO,EAAE,sBAAsB;IAC/B,KAAK,EAAE,gDAAgD;IACvD,WAAW,EACT,0NAA0N;IAC5N,IAAI,EAAE;QACJ,MAAM,EAAE
|
|
1
|
+
{"version":3,"file":"codeExamples.js","sourceRoot":"","sources":["../../../src/tools/data/codeExamples.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getCredentialGuide.d.ts","sourceRoot":"","sources":["../../../src/tools/handlers/getCredentialGuide.ts"],"names":[],"mappings":"AASA,OAAO,EAA6B,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AA8I5E,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"getCredentialGuide.d.ts","sourceRoot":"","sources":["../../../src/tools/handlers/getCredentialGuide.ts"],"names":[],"mappings":"AASA,OAAO,EAA6B,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AA8I5E,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,CAcjE"}
|
|
@@ -130,7 +130,8 @@ export function handleGetCredentialGuide(raw) {
|
|
|
130
130
|
return parsed.error;
|
|
131
131
|
const { platform, services, handlers } = parsed;
|
|
132
132
|
const metaCredentials = buildMetaCredentials(platform);
|
|
133
|
-
const
|
|
133
|
+
const singletonLink = services.length === 1 && handlers.length === 1;
|
|
134
|
+
const serviceCredentials = services.map((svc) => buildServiceGuide(svc, handlers, platform, singletonLink));
|
|
134
135
|
const summary = buildSummary(platform, metaCredentials, serviceCredentials);
|
|
135
136
|
const keyStorage = buildKeyStorageGuidance(platform);
|
|
136
137
|
return okResponse({ metaCredentials, serviceCredentials, keyStorage, summary });
|
|
@@ -158,8 +159,16 @@ function buildMetaCredentials(platform) {
|
|
|
158
159
|
};
|
|
159
160
|
return { required: true, steps, configChange };
|
|
160
161
|
}
|
|
161
|
-
function buildServiceGuide(service, handlers, platform) {
|
|
162
|
-
|
|
162
|
+
function buildServiceGuide(service, handlers, platform, singletonLink) {
|
|
163
|
+
// F-DOGFOOD-F45 (2026-05-12): when exactly ONE handler is provided AND
|
|
164
|
+
// ONE service is requested, the caller has implicitly linked them.
|
|
165
|
+
// The keyword-based guessServiceForHandler heuristic frequently fails
|
|
166
|
+
// (e.g. "BlackjackHandler" doesn't match any keyword) — but if the
|
|
167
|
+
// caller bothered to pass both, they belong together. Skip the
|
|
168
|
+
// heuristic in the singleton case.
|
|
169
|
+
const forHandlers = singletonLink
|
|
170
|
+
? handlers
|
|
171
|
+
: handlers.filter((h) => guessServiceForHandler(h) === service);
|
|
163
172
|
if (service === "custom") {
|
|
164
173
|
return {
|
|
165
174
|
service,
|
|
@@ -169,7 +178,7 @@ function buildServiceGuide(service, handlers, platform) {
|
|
|
169
178
|
"Decide on a key storage strategy: Android keystore / iOS Keychain / BuildConfig / Info.plist / server proxy.",
|
|
170
179
|
"Pass the key to your handler via dependency injection or constructor args.",
|
|
171
180
|
],
|
|
172
|
-
codeExample: sampleCode(platform, "YOUR_API_KEY"),
|
|
181
|
+
codeExample: sampleCode(platform, "YOUR_API_KEY", service),
|
|
173
182
|
};
|
|
174
183
|
}
|
|
175
184
|
const guide = PROVIDER_GUIDES[service];
|
|
@@ -181,32 +190,58 @@ function buildServiceGuide(service, handlers, platform) {
|
|
|
181
190
|
...guide.steps,
|
|
182
191
|
`Docs: ${guide.docsUrl}`,
|
|
183
192
|
],
|
|
184
|
-
codeExample: sampleCode(platform, guide.keyName),
|
|
193
|
+
codeExample: sampleCode(platform, guide.keyName, service),
|
|
185
194
|
};
|
|
186
195
|
}
|
|
187
|
-
function sampleCode(platform, keyName) {
|
|
196
|
+
function sampleCode(platform, keyName, service) {
|
|
197
|
+
// F-DOGFOOD-F46 (2026-05-12): the code example used to reference a
|
|
198
|
+
// fake YourClient/.analyze() stub — same paste-and-pray hazard as
|
|
199
|
+
// F18. For known providers that ship a real client example
|
|
200
|
+
// (currently only Anthropic via byok_anthropic), point at it
|
|
201
|
+
// directly. Other services still get the stub message but it
|
|
202
|
+
// explicitly says "stub" so agents don't paste it verbatim.
|
|
203
|
+
const knownClientExample = {
|
|
204
|
+
anthropic: "byok_anthropic",
|
|
205
|
+
};
|
|
206
|
+
const clientPattern = knownClientExample[service];
|
|
188
207
|
if (platform === "android") {
|
|
189
|
-
|
|
190
|
-
`android { defaultConfig { resValue("string", "${keyName.toLowerCase()}", System.getenv("${keyName}") ?: "") } }\n\n
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
208
|
+
const wiring = `// app/build.gradle.kts\n` +
|
|
209
|
+
`android { defaultConfig { resValue("string", "${keyName.toLowerCase()}", System.getenv("${keyName}") ?: "") } }\n\n`;
|
|
210
|
+
const handlerInvocation = clientPattern
|
|
211
|
+
? `// Paste the canonical client from getCodeExample('${clientPattern}'). It exposes\n` +
|
|
212
|
+
`// ask(question, history) for text Q&A AND describe(imageBase64, mediaType, prompt)\n` +
|
|
213
|
+
`// for Claude Vision. Wire-up:\n` +
|
|
214
|
+
`val key = context.getString(R.string.${keyName.toLowerCase()})\n` +
|
|
215
|
+
`val client = AnthropicClient(apiKey = key)\n` +
|
|
216
|
+
`// text: client.ask("...")\n` +
|
|
217
|
+
`// vision: client.describe(b64, mediaType, "What's in this?")`
|
|
218
|
+
: `// In your handler — replace YourClient with your provider's real SDK / wire client.\n` +
|
|
219
|
+
`// Stub shape (don't paste verbatim — YourClient doesn't exist):\n` +
|
|
220
|
+
`val key = context.getString(R.string.${keyName.toLowerCase()})\n` +
|
|
221
|
+
`// val client = YourClient(apiKey = key) // <-- TODO: implement\n` +
|
|
222
|
+
`// return client.analyze(image)`;
|
|
223
|
+
return (wiring +
|
|
224
|
+
handlerInvocation +
|
|
225
|
+
`\n\n// resValue is preferred over buildConfigField because Kotlin compile-\n` +
|
|
198
226
|
`// time constants inlined from BuildConfig don't re-inline when the\n` +
|
|
199
227
|
`// resValue rotates — the kotlin incremental compiler doesn't notice\n` +
|
|
200
228
|
`// the literal changed, so old binaries silently keep the old key.`);
|
|
201
229
|
}
|
|
202
|
-
|
|
203
|
-
`<key>${keyName}</key>\n<string>$(${keyName})</string> <!-- inject via xcconfig, not checked in -->\n\n
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
230
|
+
const plist = `// Info.plist\n` +
|
|
231
|
+
`<key>${keyName}</key>\n<string>$(${keyName})</string> <!-- inject via xcconfig, not checked in -->\n\n`;
|
|
232
|
+
const handlerInvocation = clientPattern
|
|
233
|
+
? `// Paste the canonical client from getCodeExample('${clientPattern}'). It exposes\n` +
|
|
234
|
+
`// ask(question:history:) and describe(imageBase64:mediaType:prompt:) — both Swift\n` +
|
|
235
|
+
`// async throws. Wire-up:\n` +
|
|
236
|
+
`let key = Bundle.main.object(forInfoDictionaryKey: "${keyName}") as? String ?? ""\n` +
|
|
237
|
+
`let client = AnthropicClient(apiKey: key)\n` +
|
|
238
|
+
`// text: try await client.ask(question: "...")\n` +
|
|
239
|
+
`// vision: try await client.describe(imageBase64: b64, mediaType: "image/jpeg", prompt: "...")`
|
|
240
|
+
: `// Stub — YourClient doesn't exist; wire your provider's actual SDK here.\n` +
|
|
241
|
+
`let key = Bundle.main.object(forInfoDictionaryKey: "${keyName}") as? String ?? ""\n` +
|
|
242
|
+
`// let client = YourClient(apiKey: key) // <-- TODO: implement\n` +
|
|
243
|
+
`// return try await client.analyze(image)`;
|
|
244
|
+
return plist + handlerInvocation;
|
|
210
245
|
}
|
|
211
246
|
function guessServiceForHandler(name) {
|
|
212
247
|
const n = name.toLowerCase();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getCredentialGuide.js","sourceRoot":"","sources":["../../../src/tools/handlers/getCredentialGuide.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"getCredentialGuide.js","sourceRoot":"","sources":["../../../src/tools/handlers/getCredentialGuide.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspectIntegration.d.ts","sourceRoot":"","sources":["../../../src/tools/handlers/inspectIntegration.ts"],"names":[],"mappings":"AAWA,OAAO,EAA6B,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AA2B5E,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"inspectIntegration.d.ts","sourceRoot":"","sources":["../../../src/tools/handlers/inspectIntegration.ts"],"names":[],"mappings":"AAWA,OAAO,EAA6B,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AA2B5E,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,CAmGjE"}
|
|
@@ -43,8 +43,12 @@ export function handleInspectIntegration(raw) {
|
|
|
43
43
|
}
|
|
44
44
|
const gaps = [];
|
|
45
45
|
const manifestVersion = manifest.manifestVersion;
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
// F-DOGFOOD-F44 (2026-05-12): generateConnectionModule emits v2; the
|
|
47
|
+
// shape difference vs v1 is the dropped DSL surface (spec, triggers,
|
|
48
|
+
// app_callback handler tables) which the inspector already doesn't
|
|
49
|
+
// touch. Both versions are valid for the post-pivot inspection scope.
|
|
50
|
+
if (manifestVersion !== 1 && manifestVersion !== 2) {
|
|
51
|
+
gaps.push(`manifestVersion is ${JSON.stringify(manifestVersion)} — this tool understands versions 1 and 2 only.`);
|
|
48
52
|
}
|
|
49
53
|
const generatedFiles = Array.isArray(manifest.generatedFiles)
|
|
50
54
|
? manifest.generatedFiles
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspectIntegration.js","sourceRoot":"","sources":["../../../src/tools/handlers/inspectIntegration.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,EAAE;AACF,oEAAoE;AACpE,oEAAoE;AACpE,mEAAmE;AACnE,2EAA2E;AAC3E,oEAAoE;AACpE,0CAA0C;AAE1C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,aAAa,EAAmB,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAuBhE,MAAM,UAAU,GAAG,oBAAoB,CAAC;AAExC,MAAM,UAAU,wBAAwB,CAAC,GAAY;IACnD,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAE,GAA+B,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtF,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAEzD,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,wBAAwB,CAAC,CAAC;IACjE,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,OAAO,UAAU,CAAC;YAChB,KAAK,EAAE,KAAK;YACZ,QAAQ,EAAE,IAAI;YACd,oBAAoB,EAAE,EAAE;YACxB,UAAU,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;YAC1D,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE;YAChD,oBAAoB,EAAE,IAAI;YAC1B,IAAI,EAAE;gBACJ,gCAAgC,YAAY,0DAA0D;aACvG;SACF,CAAC,CAAC;IACL,CAAC;IAED,IAAI,QAAiC,CAAC;IACtC,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAA4B,CAAC;IACvF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,aAAa,CAAC;YACnB,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,2CAA2C,UAAU,CAAC,CAAC,CAAC,GAAG;YACpE,OAAO,EAAE,yGAAyG;YAClH,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,eAAe,GAAG,QAAQ,CAAC,eAAe,CAAC;IACjD,IAAI,eAAe,KAAK,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"inspectIntegration.js","sourceRoot":"","sources":["../../../src/tools/handlers/inspectIntegration.ts"],"names":[],"mappings":"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"}
|