@extentos/mcp-server 0.0.94 → 0.1.2

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.
Files changed (43) hide show
  1. package/dist/tools/data/capabilities.d.ts +49 -0
  2. package/dist/tools/data/capabilities.d.ts.map +1 -1
  3. package/dist/tools/data/capabilities.js +37 -0
  4. package/dist/tools/data/capabilities.js.map +1 -1
  5. package/dist/tools/data/capabilityPatterns.d.ts.map +1 -1
  6. package/dist/tools/data/capabilityPatterns.js +499 -6
  7. package/dist/tools/data/capabilityPatterns.js.map +1 -1
  8. package/dist/tools/data/codeExamples.d.ts.map +1 -1
  9. package/dist/tools/data/codeExamples.js +916 -2
  10. package/dist/tools/data/codeExamples.js.map +1 -1
  11. package/dist/tools/data/version.d.ts +12 -0
  12. package/dist/tools/data/version.d.ts.map +1 -1
  13. package/dist/tools/data/version.js +17 -0
  14. package/dist/tools/data/version.js.map +1 -1
  15. package/dist/tools/definitions.d.ts.map +1 -1
  16. package/dist/tools/definitions.js +63 -3
  17. package/dist/tools/definitions.js.map +1 -1
  18. package/dist/tools/docs/index.d.ts.map +1 -1
  19. package/dist/tools/docs/index.js +115 -4
  20. package/dist/tools/docs/index.js.map +1 -1
  21. package/dist/tools/handlers/assertToolCalled.d.ts +3 -0
  22. package/dist/tools/handlers/assertToolCalled.d.ts.map +1 -0
  23. package/dist/tools/handlers/assertToolCalled.js +208 -0
  24. package/dist/tools/handlers/assertToolCalled.js.map +1 -0
  25. package/dist/tools/handlers/generateConnectionModule.js +21 -2
  26. package/dist/tools/handlers/generateConnectionModule.js.map +1 -1
  27. package/dist/tools/handlers/getCredentialGuide.d.ts.map +1 -1
  28. package/dist/tools/handlers/getCredentialGuide.js +33 -6
  29. package/dist/tools/handlers/getCredentialGuide.js.map +1 -1
  30. package/dist/tools/handlers/getProductionChecklist.d.ts.map +1 -1
  31. package/dist/tools/handlers/getProductionChecklist.js +52 -1
  32. package/dist/tools/handlers/getProductionChecklist.js.map +1 -1
  33. package/dist/tools/handlers/injectAssistantUtterance.d.ts +3 -0
  34. package/dist/tools/handlers/injectAssistantUtterance.d.ts.map +1 -0
  35. package/dist/tools/handlers/injectAssistantUtterance.js +378 -0
  36. package/dist/tools/handlers/injectAssistantUtterance.js.map +1 -0
  37. package/dist/tools/handlers/validateIntegration.d.ts.map +1 -1
  38. package/dist/tools/handlers/validateIntegration.js +67 -0
  39. package/dist/tools/handlers/validateIntegration.js.map +1 -1
  40. package/dist/tools/registry.d.ts.map +1 -1
  41. package/dist/tools/registry.js +4 -0
  42. package/dist/tools/registry.js.map +1 -1
  43. package/package.json +1 -1
@@ -16,11 +16,11 @@ import com.extentos.glasses.core.Photos
16
16
  import com.extentos.glasses.core.Resolution
17
17
  import com.extentos.glasses.core.valueOrNull
18
18
 
19
- // F-R3-9: Photos helpers (in com.extentos.glasses.core.Photos) — pass
20
- // photo.uri to bridge data: and file: URI schemes uniformly. All four
21
- // return nullable (null on unreadable URI, unrecognized scheme, decode
22
- // failure, or OOM — never throw). Three are \`suspend\` (decode runs on
23
- // Dispatchers.IO under the hood); mediaTypeFromUri is synchronous.
19
+ // F-R3-9 + iter4: Photos helpers (in com.extentos.glasses.core.Photos) —
20
+ // pass photo.uri to bridge data: and file: URI schemes uniformly. All
21
+ // return nullable / Boolean (null on unreadable URI, unrecognized scheme,
22
+ // decode failure, or OOM — never throw). Most are \`suspend\` (decode +
23
+ // stream-copy run on Dispatchers.IO); mediaTypeFromUri is synchronous.
24
24
  // suspend fun Photos.loadBase64(uri: String): String?
25
25
  // — base64 of the photo bytes (NO "data:image/...;base64," prefix).
26
26
  // Fast path on data: URIs: returns the substring after the comma
@@ -29,6 +29,14 @@ import com.extentos.glasses.core.valueOrNull
29
29
  // — raw bytes (for ML pipelines that want the unencoded source).
30
30
  // suspend fun Photos.loadBitmap(uri: String): android.graphics.Bitmap?
31
31
  // — decoded Bitmap (for Compose: \`bitmap?.asImageBitmap()\`).
32
+ // suspend fun Photos.copyToFile(uri: String, dst: File): Boolean
33
+ // — persist the photo to a stable file path. Mirrors
34
+ // Videos.copyToFile. Handles data: / file:// / absolute path
35
+ // uniformly; creates parent dirs; overwrites existing dst.
36
+ // Returns false on any failure. Use this — NOT manual loadBytes +
37
+ // writeBytes — when saving a captured photo into your app's
38
+ // library / gallery directory (the canonical "save_photo" tool
39
+ // pattern; see getCapabilityGuide(feature:"assistant_vision")).
32
40
  // fun Photos.mediaTypeFromUri(uri: String): String?
33
41
  // — "image/jpeg" / "image/png" / "image/webp" / "image/gif" /
34
42
  // "image/heic". For data: URIs: parses the embedded MIME directly.
@@ -781,6 +789,483 @@ _ = glasses.conversation?.onWake(phrase: "hey assistant") { ctx in
781
789
  ],
782
790
  relatedExamples: ["conversation_agent_loop"],
783
791
  };
792
+ // ── Phase 4 assistant runtime guides ──────────────────────────────────
793
+ const ASSISTANT_RUNTIME = {
794
+ feature: "assistant_runtime",
795
+ summary: "Phase 4 — umbrella entry for the `glasses.assistant` API. End-to-end voice provider abstraction: customer code is `glasses.assistant.start(provider) { tool(name, description) { body -> ToolResult } }`. The model owns wake / turn-taking / intent / confirmation; the customer writes tool bodies that act on app state. v1 ships OpenAI Realtime (`gpt-realtime` over WebSocket); Gemini Live in v1.5+. **Canonical replacement for the Phase 3 conversation runtime, which deprecates in v1.4.0 and removes in v2.0.0.** See per-feature entries (assistant_start, assistant_tool, assistant_provider_openai) for call-shape detail. Full composition example: `getCodeExample(pattern: \"assistant_agent_loop\")`. Conceptual guide: `searchDocs(topic: \"assistant_runtime\")`.",
796
+ kotlin: `// The whole runtime in one start block:
797
+ glasses.assistant.setOpenaiApiKey(BuildConfig.OPENAI_API_KEY)
798
+ glasses.assistant.start(
799
+ provider = AssistantProvider.OpenAi(model = "gpt-realtime", voice = "alloy"),
800
+ ) {
801
+ instructions = "You are a helpful assistant on smart glasses. Speak briefly."
802
+ tool("take_picture", "Take a photo with the glasses camera.") {
803
+ val photo = glasses.camera.capturePhoto().valueOrNull()
804
+ ?: return@tool ToolResult.Err("camera failed")
805
+ library.addPhoto(photo)
806
+ ToolResult.Ok("photo saved")
807
+ }
808
+ }`,
809
+ swift: `// The whole runtime in one start closure:
810
+ glasses.assistant.setOpenAiApiKey(Secrets.openAiKey)
811
+ _ = try await glasses.assistant.start(
812
+ provider: .openAI(model: "gpt-realtime", voice: "alloy")
813
+ ) { config in
814
+ config.instructions = "You are a helpful assistant on smart glasses. Speak briefly."
815
+ config.tool("take_picture", description: "Take a photo with the glasses camera.") {
816
+ // capturePhoto returns ExtentosResult<Photo, CaptureError> async
817
+ // (not throwing); extract the success branch via the .success
818
+ // accessor on ExtentosResult (Errors.swift).
819
+ guard let photo = (await glasses.camera.capturePhoto()).success else {
820
+ return .err("camera failed")
821
+ }
822
+ library.add(photo)
823
+ return .ok("photo saved")
824
+ }
825
+ }`,
826
+ gotchas: [
827
+ "**glasses.assistant is always-on — no opt-in.** Unlike Phase 3's nullable `glasses.conversation` (gated on conversationOptions in ExtentosConfig), Phase 4 ships zero on-device ML so there's no cost to always exposing the surface. No ConversationModels.ensureExtracted, no ONNX file paths, no cascaded options to wire.",
828
+ "**Singleton-active per ExtentosGlasses (synthesis #13).** At most one assistant.start() at a time. A second start while active throws AssistantException(AlreadyActive). Call `glasses.assistant.stop()` (or `session.stop()`) before starting a new one. v1 simplicity; can relax in v1.x if customer demand surfaces.",
829
+ "**Eight `assistant.*` lifecycle events emitted automatically (synthesis #15):** session_started / session_ended / user_spoke / assistant_spoke / tool_called / tool_result / reconnected / error. Visible via `glasses.runtime.events.filterIsInstance<RuntimeEvent.Assistant>()`, the simulator's right-rail AssistantPanel, and `getEventLog(filter: \"voice\")`. assistant.error climbs to filter:\"errors\" automatically.",
830
+ "**PII boundary differs from Phase 3.** Assistant events DO carry verbatim transcripts in user_spoke / assistant_spoke. Phase 3 conversation.* stripped text (only textLen) because the cascaded path routed transcripts through Extentos backend. Phase 4 BYOK contract sends transcripts device → openai.com directly without touching Extentos backend, so the platform-side PII enforcement doesn't apply. Customer apps own their data retention story.",
831
+ "**Library-owned transparent reconnection (synthesis #23).** OpenAI Realtime hard-caps sessions at 60 min; library proactively reconnects every ~50 min + on WS onFailure / onClosed. Customer code doesn't see the swap. `assistant.reconnected` event fires for observability. Conversation history (recent 40 turns) replays on each reconnect.",
832
+ "**BYOK key flows direct to OpenAI (synthesis #12).** `setOpenaiApiKey(key)` stores the key in the AssistantClient; when start() opens the WebSocket, the key goes into `Authorization: Bearer ...` for the wss://api.openai.com/v1/realtime connection. Extentos backend never sees the key. See `getCredentialGuide(service: \"openai\")` for the local.properties + resValue / Info.plist plumbing.",
833
+ "**What Extentos manages by default vs. what's yours.** The assistant runtime composes several layers of model behavior, and knowing the boundary helps you customize without fighting the SDK:\\n\\n • **Wire plumbing (SDK-owned, no opt-out)** — WebSocket lifecycle, PCMU audio codec, 50-minute proactive reconnect, session-update handshake. You don't touch these.\\n • **Provider defaults (SDK-owned, override on `AssistantProvider.OpenAi(...)`)** — model (`gpt-realtime-2`), voice (`alloy`), `turn_detection` (`server_vad`), `reasoningEffort` (`Low`). Override via the provider constructor when you need different behavior.\\n • **Tools you didn't write (SDK-owned, opt-out via `AssistantConfig` flag)** — `end_conversation` tool injected when `endOnIntent = true` (default). Customize *when* via your `instructions`; opt out via `endOnIntent = false`.\\n • **Conversation history (SDK-managed buffer; tunable + customizable via iter5.1 surface)** — local replay buffer capped at `AssistantConfig.historyCap` (default 100 turns), preserved across wake/sleep, replayed on reconnect. When the buffer approaches the cap, `AssistantConfig.historyCompaction` runs — default `Auto` summarizes oldest ~50% via gpt-4o-mini under the BYOK key (~$0.001 / compaction). Customer overrides: `Custom { turns -> ... }` for their own strategy, `DropOldest` for free/lossy, `None` for fully manual via `clearHistory` / `appendHistory` / `replaceHistory`.\\n • **`instructions` text (100% yours)** — Extentos does not modify your prompt. Whatever you write is what the model sees.\\n • **Mid-session primitives (you call them when you want)** — `session.setReasoningEffort(level)`, `session.updateInstructions(text)`, `session.cancelSpeak()`, `session.includeImage(uri, prompt)`, `session.conversationHistory(limit)`, plus iter5.1's `session.clearHistory()` / `appendHistory(turn)` / `replaceHistory(turns)`. Composable building blocks for escalation, persona swaps, interrupts, vision, forwarding context to stronger models, fresh-each-wake patterns, TTL resets, app-restart restoration. The SDK provides them; you decide which flows to build with them.\\n\\n**Principle for future SDK contributions:** universal-issue patches (things every voice assistant on glasses needs) sit on the SDK side with a documented opt-out. App-specific choices (personality, domain tools, language pinning, persona, custom compaction strategy) sit on the developer side. When in conflict, your `instructions` win on recency. To see what's actually being sent to OpenAI, enable debug-level logging on `OpenAiAssistantProvider` — the effective `session.update` payload (API key not included; it rides in the WS Authorization header) is logged on open + on every partial update + every reconnect.",
834
+ ],
835
+ relatedExamples: ["assistant_agent_loop", "agent_driven_e2e_full_loop"],
836
+ };
837
+ const ASSISTANT_START = {
838
+ feature: "assistant_start",
839
+ summary: "Open an assistant session. Two equivalent forms: sugar `start(provider) { tool(...) { ... } }` (trailing-lambda builder) and raw `createSession(AssistantConfig(...))` + `session.start()`. Sugar is idiomatic for the common case; raw is the customer-can-skip-it primitive for programmatic tool registration. Both return an `AssistantSession`. Singleton-active per synthesis #13.",
840
+ kotlin: `// Sugar form
841
+ val session = glasses.assistant.start(
842
+ provider = AssistantProvider.OpenAi(model = "gpt-realtime", voice = "alloy"),
843
+ ) {
844
+ instructions = "..."
845
+ tool("take_picture", "Take a photo.") { ToolResult.Ok("photo saved") }
846
+ }
847
+
848
+ // Raw form — equivalent
849
+ val session = glasses.assistant.createSession(AssistantConfig(
850
+ provider = AssistantProvider.OpenAi(...),
851
+ instructions = "...",
852
+ tools = listOf(
853
+ ToolDefinition("take_picture", "Take a photo.") { _ -> ToolResult.Ok("photo saved") },
854
+ ),
855
+ ))
856
+ session.start()
857
+
858
+ // Observe lifecycle:
859
+ session.state.collect { state -> /* Idle, Starting, Active, Reconnecting, Stopping, Ended */ }
860
+
861
+ // Stop when done:
862
+ session.stop() // or glasses.assistant.stop() — equivalent`,
863
+ swift: `// Sugar form
864
+ let session = try await glasses.assistant.start(
865
+ provider: .openAI(model: "gpt-realtime", voice: "alloy")
866
+ ) { config in
867
+ config.instructions = "..."
868
+ config.tool("take_picture", description: "Take a photo.") { .ok("photo saved") }
869
+ }
870
+
871
+ // Raw form — equivalent
872
+ let session = glasses.assistant.createSession(config: AssistantConfig(
873
+ provider: .openAI(model: "gpt-realtime", voice: "alloy"),
874
+ instructions: "...",
875
+ tools: [ToolDefinition(name: "take_picture", description: "Take a photo.") { _ in .ok("photo saved") }]
876
+ ))
877
+ try await session.start()
878
+
879
+ // Observe lifecycle (StateFlow-style — replays current on subscribe):
880
+ for await state in session.state.stream { /* idle, starting, active, reconnecting, stopping, ended */ }
881
+
882
+ // Stop when done (async, NOT throwing on iOS):
883
+ await session.stop() // or await glasses.assistant.stop() — equivalent`,
884
+ gotchas: [
885
+ "**`start()` is suspend / async throws — call from a coroutine / Task.** Opens the WebSocket, sends session.update, awaits session.updated handshake (~1-2s typical). Throws AssistantException(NoApiKey) if you haven't called setOpenaiApiKey; AssistantException(AlreadyActive) if another session is active; AssistantException(NetworkError) on WS open failure.",
886
+ "**Sugar form auto-starts the session; raw form does not.** `assistant.start(provider) { ... }` returns an already-Active session. `assistant.createSession(config)` returns an Idle session — you call `session.start()` to activate. The sugar is shorthand for `createSession + start`.",
887
+ "**Customer-can-skip-it (synthesis #7).** The raw form is the primitive; the sugar reduces to it. Every customer can replace `start { tool(...) { ... } }` with `createSession(AssistantConfig(tools = listOf(ToolDefinition(...), ...)))` + `start()` and get identical behavior. Useful for programmatic tool registration (loaded from config, conditional, etc.).",
888
+ "**`stop()` is idempotent.** Calling stop() on an Ended session is a no-op. Calling start() on an Ended session throws AssistantException(SessionEnded) — create a new session via createSession() to start fresh.",
889
+ ],
890
+ relatedExamples: ["assistant_agent_loop", "agent_driven_e2e_full_loop"],
891
+ };
892
+ const ASSISTANT_TOOL = {
893
+ feature: "assistant_tool",
894
+ summary: "Register a tool the assistant may call. Three overloads on the `AssistantConfigBuilder` receiver inside `start { ... }`: (1) no-arg `tool(name, description) { -> ToolResult }`, (2) typed-args `tool<Args>(name, description) { args -> ToolResult }` where Args is `@Serializable` (Kotlin) / `Codable` (Swift), (3) explicit-schema escape hatch `tool(name, description, schema = JsonObject(...)) { args -> ToolResult }`. **Cross-platform asymmetry (Q3, intentional):** Kotlin infers the schema from Args's SerialDescriptor at runtime; Swift requires explicit `schema:` parameter on the typed overload (no Mirror walk on types — see synthesis #8). JSON Schema sent to OpenAI is identical regardless of source platform.",
895
+ kotlin: `// No-arg tool (most common — camera, status, simple actions)
896
+ tool("take_picture", "Take a photo when the user asks to capture a moment.") {
897
+ ToolResult.Ok("photo saved")
898
+ }
899
+
900
+ // Typed-args tool — Args inferred from @Serializable type
901
+ @kotlinx.serialization.Serializable
902
+ data class SetReminderArgs(val text: String, val minutesFromNow: Int)
903
+
904
+ tool<SetReminderArgs>("set_reminder", "Set a timed reminder.") { args ->
905
+ reminders.add(args.text, delay = args.minutesFromNow.minutes)
906
+ ToolResult.Ok("reminder set for \${args.minutesFromNow} min")
907
+ }
908
+
909
+ // Explicit-schema escape hatch — for polymorphic types or format constraints
910
+ tool("set_filter", "Apply an image filter.", schema = buildJsonObject {
911
+ put("type", "object")
912
+ put("properties", buildJsonObject {
913
+ put("name", buildJsonObject { put("type", "string"); put("enum", buildJsonArray { add("sepia"); add("noir") }) })
914
+ })
915
+ put("required", buildJsonArray { add("name") })
916
+ }) { args ->
917
+ val filterName = args["name"]?.jsonPrimitive?.contentOrNull
918
+ ToolResult.Ok("filter applied: \$filterName")
919
+ }
920
+
921
+ // Per-tool blocking opt-out (synthesis #9 — default is non-blocking)
922
+ tool("get_battery", "Current battery percentage.", blocking = true) {
923
+ ToolResult.Ok("\${battery.percent()}%")
924
+ }`,
925
+ swift: `// No-arg tool
926
+ config.tool("take_picture", description: "Take a photo when the user asks to capture a moment.") {
927
+ .ok("photo saved")
928
+ }
929
+
930
+ // Typed-args tool — EXPLICIT schema required on Swift (Q3 asymmetry).
931
+ // v1 has no \`JSONSchema\` builder helper; the customer constructs the
932
+ // schema directly via \`JSONValue\` (Codable + Sendable). Args type
933
+ // is inferred from the closure parameter annotation, not a separate
934
+ // \`args:\` parameter — see Tool.swift's typed-overload signature.
935
+ struct SetReminderArgs: Codable, Sendable {
936
+ let text: String
937
+ let minutesFromNow: Int
938
+ }
939
+
940
+ let reminderSchema: JSONValue = .object([
941
+ "type": .string("object"),
942
+ "properties": .object([
943
+ "text": .object(["type": .string("string")]),
944
+ "minutesFromNow": .object(["type": .string("integer")]),
945
+ ]),
946
+ "required": .array([.string("text"), .string("minutesFromNow")]),
947
+ ])
948
+
949
+ config.tool(
950
+ "set_reminder",
951
+ description: "Set a timed reminder.",
952
+ schema: reminderSchema
953
+ ) { (args: SetReminderArgs) in
954
+ await reminders.add(args.text, delaySeconds: args.minutesFromNow * 60)
955
+ return .ok("reminder set for \\(args.minutesFromNow) min")
956
+ }
957
+
958
+ // Per-tool blocking opt-out (synthesis #9 — default is non-blocking)
959
+ config.tool("get_battery", description: "Current battery percentage.", blocking: true) {
960
+ .ok("\\(battery.percent())%")
961
+ }`,
962
+ gotchas: [
963
+ "**Tool descriptions matter — write them for the AI, not the engineer.** The model reads the description verbatim when deciding which tool to call. Use \"Take a photo when the user asks to capture a moment\" (describes WHEN to call) not \"Captures imagery via the camera SDK\" (describes implementation). Mock provider's word-overlap matcher also benefits from descriptions that contain keywords from likely user utterances.",
964
+ "**Tool body runs on Dispatchers.IO (Kotlin) / Swift Task (Swift).** Suspending camera / storage / HTTP calls are fine; CPU-heavy work won't block the main thread. Per-tool blocking opt-out via `blocking = true` parameter (synthesis #9) — true means the model waits silently for the result before speaking. Default false means the model says \"let me check...\" while the tool runs.",
965
+ "**`ToolResult.Ok(text)` vs `ToolResult.Err(message)`.** The `text` for Ok is what the model reads aloud / weaves into its reply. Keep it short + factual: \"photo saved\" not \"Image successfully persisted to local storage at /...\". For structured data the model needs to reason about, return it as a JSON string: `ToolResult.Ok(\"\"\"{\"km\": 12.4}\"\"\")`. Err is the user-facing failure message; the model surfaces it (\"sorry, the camera failed\").",
966
+ "**Customer-can-skip-it (synthesis #8) — the builder is sugar over `ToolDefinition`.** Every tool() call constructs a `ToolDefinition(name, description, schema, blocking, body)` and appends to the builder's list. Customers can skip the builder entirely and pass `tools = listOf(ToolDefinition(...))` to `AssistantConfig` directly for programmatic registration.",
967
+ "**Tools have full access to glasses.* + app state (synthesis #14).** No sandbox in v1. Tool body is regular customer-app code — it sees `glasses.camera`, `glasses.audio`, the app's DBs, view models, repositories, third-party SDKs. Security boundary stays at the app/OS level (Android permissions, iOS Info.plist) — not the SDK level. Per the indie/hobbyist target audience + BYOK provider model.",
968
+ ],
969
+ relatedExamples: ["assistant_agent_loop", "agent_driven_e2e_full_loop"],
970
+ };
971
+ const ASSISTANT_PROVIDER_OPENAI = {
972
+ feature: "assistant_provider_openai",
973
+ summary: "OpenAI Realtime provider configuration. `AssistantProvider.OpenAi(model, voice, turnDetection, reasoningEffort)` — model defaults to `gpt-realtime-2` (released 2026-05-08, strictly better at tool calling, parallel tool calls, 128k context, GPT-5-class reasoning); voice from OpenAI's catalog (`alloy`, `echo`, `shimmer`, `marin`); turnDetection defaults to `ServerVad(threshold = 0.5, prefixPaddingMs = 300, silenceDurationMs = 500)` per synthesis #10; reasoningEffort defaults to `Low` (OpenAI's own recommended default for voice agents — anything higher noticeably adds latency). BYOK key set out-of-band via `setOpenaiApiKey`. WebSocket transport in v1 (WebRTC v1.1+). GA wire format `audio/pcmu` (no rate field; G.711 intrinsic 8 kHz) per synthesis #6.",
974
+ kotlin: `// Default — gpt-realtime-2 + alloy + ServerVad + reasoning Low
975
+ val provider = AssistantProvider.OpenAi(
976
+ model = "gpt-realtime-2",
977
+ voice = "alloy",
978
+ )
979
+
980
+ // Custom VAD tuning — more aggressive turn-end detection
981
+ val provider = AssistantProvider.OpenAi(
982
+ model = "gpt-realtime-2",
983
+ voice = "marin",
984
+ turnDetection = TurnDetection.ServerVad(
985
+ threshold = 0.6,
986
+ prefixPaddingMs = 200,
987
+ silenceDurationMs = 350,
988
+ ),
989
+ )
990
+
991
+ // Semantic VAD — slower but smarter turn detection (model uses context
992
+ // to decide whether the user actually finished, vs paused mid-sentence)
993
+ val provider = AssistantProvider.OpenAi(
994
+ model = "gpt-realtime-2",
995
+ voice = "alloy",
996
+ turnDetection = TurnDetection.SemanticVad,
997
+ )
998
+
999
+ // Higher reasoning baseline for an analytical assistant. Users will
1000
+ // notice extra 2-5s on every reply; pick Low for casual chat, Medium
1001
+ // for advisory, High/Xhigh only when the product really benefits.
1002
+ val provider = AssistantProvider.OpenAi(
1003
+ model = "gpt-realtime-2",
1004
+ voice = "alloy",
1005
+ reasoningEffort = ReasoningEffort.Medium,
1006
+ )
1007
+
1008
+ // BYOK key — set ONCE at bootstrap; reused on every session.start() +
1009
+ // every reconnect within a session.
1010
+ glasses.assistant.setOpenaiApiKey(BuildConfig.OPENAI_API_KEY)`,
1011
+ swift: `// Default — gpt-realtime-2 + alloy + ServerVad + reasoning Low
1012
+ let provider: AssistantProvider = .openAI(model: "gpt-realtime-2", voice: "alloy")
1013
+
1014
+ // Custom VAD tuning
1015
+ let provider: AssistantProvider = .openAI(
1016
+ model: "gpt-realtime-2",
1017
+ voice: "marin",
1018
+ turnDetection: .serverVad(
1019
+ threshold: 0.6,
1020
+ prefixPaddingMs: 200,
1021
+ silenceDurationMs: 350
1022
+ )
1023
+ )
1024
+
1025
+ // Semantic VAD
1026
+ let provider: AssistantProvider = .openAI(
1027
+ model: "gpt-realtime-2",
1028
+ voice: "alloy",
1029
+ turnDetection: .semanticVad
1030
+ )
1031
+
1032
+ // Higher reasoning baseline (iOS parity for reasoningEffort lands with
1033
+ // the next Mac VPS handoff)
1034
+ // let provider: AssistantProvider = .openAI(
1035
+ // model: "gpt-realtime-2",
1036
+ // voice: "alloy",
1037
+ // reasoningEffort: .medium
1038
+ // )
1039
+
1040
+ // BYOK key
1041
+ glasses.assistant.setOpenAiApiKey(Secrets.openAiKey)`,
1042
+ gotchas: [
1043
+ "**Reasoning effort — four customization patterns.** The two SDK knobs (\`reasoningEffort\` on \`AssistantProvider.OpenAi\` + \`session.setReasoningEffort(level)\` mid-session) enable: (1) **Static default** — set it once on the provider, never change. 80% of apps live here. (2) **Model self-routes** — register a \`think_harder\` tool the model calls when it senses complexity; tool body calls \`session.setReasoningEffort(High)\`. (3) **User-explicit trigger** — same tool pattern with a description that says \"only call when the user explicitly asks to think more carefully.\" (4) **App UI toggle** — wire a \"deep thinking\" switch in your UI to \`session.setReasoningEffort\` directly. Don't bake auto-routing heuristics into your tool body — let the model decide via descriptions, that's what tool descriptions are for.",
1044
+ "**Reasoning levels: `Minimal | Low | Medium | High | Xhigh`.** OpenAI's spelling — wire value `xhigh`, not `very_high` (several community articles got this wrong). Each step up adds 1-5s of latency on the next response; Xhigh can hit 10s+ on hard prompts. Voice agents on glasses are latency-sensitive — keep the session baseline at Low and bump via the runtime setter for individual turns that warrant it.",
1045
+ "**Voice CAN be swapped mid-session on `gpt-realtime-2`** (unlike the original `gpt-realtime` where voice was locked once the model first spoke). The v1.4 SDK doesn't expose a runtime voice setter — stop + start a new session is the workaround. If a customer wants mid-session voice swap as a primitive, file a request; it's a thin shim over `session.update`.",
1046
+ "**Wire format is `audio/pcmu` with NO rate field (synthesis #6).** G.711 mulaw is intrinsically 8 kHz; the GA spec encodes that via the format type alone. Library handles the PCM↔mulaw codec internally — customer never sees raw bytes. Validated via Twilio's production GA integration. Fallback to `audio/pcm rate=24000` documented but unlikely needed.",
1047
+ "**60-min hard ceiling on OpenAI Realtime sessions.** Library proactively reconnects every ~50 min ahead of the ceiling; on WS onFailure / onClosed mid-session, coalesced reconnect via lifecycle mutex; recent 40 conversation turns replayed on each reconnect; customer never sees the swap. `assistant.reconnected` event fires for observability. Synthesis #23.",
1048
+ "**Parallel tool calls (new in `gpt-realtime-2`).** The model can fire multiple tool calls in one response — e.g. \"check my calendar AND get the weather\" → both tools dispatch in parallel. SDK already handles this via per-call_id state in OpenAiAssistantProvider (synthesis #9 non-blocking dispatch was already the design). No customer-side change needed; just write the tools and let the model batch them when it wants.",
1049
+ "**No Anthropic provider in v1 or v2 (synthesis #17).** Anthropic hasn't shipped a Realtime API. v2.0.0 ships OpenAI only; Gemini Live in v1.5+. Revisit Claude when Anthropic ships their equivalent.",
1050
+ "**Test with `AssistantProvider.Mock()` first (synthesis #16).** Mock is deterministic, sub-millisecond, $0; matches injected utterances against tool descriptions for deterministic CI. Save the OpenAi provider for end-to-end smoke + production.",
1051
+ ],
1052
+ relatedExamples: ["assistant_agent_loop", "agent_driven_e2e_full_loop"],
1053
+ };
1054
+ const ASSISTANT_VISION = {
1055
+ feature: "assistant_vision",
1056
+ summary: "Phase 4 v1.4 addition — `session.includeImage(uri, prompt = null)`. Add an image to the assistant's conversation context and auto-trigger a response: the model sees the image, speaks about it in its configured voice, and remembers it for follow-up questions in the same session. Canonical 'glasses analyze what I'm looking at' surface — pair with `glasses.camera.capturePhoto()` inside a tool body. URI accepts `data:` (sim's capturePhoto default), `http(s)://` (provider fetches), or `file://` / `content://` / bare absolute path (library reads + base64-encodes). Active-only — throws `AssistantException(NotReady)` otherwise. Mock provider stubs with a deterministic AssistantSpoke event for the agent-test loop. v1 ships against OpenAI Realtime's `conversation.item.create` with `input_image` content block.",
1057
+ kotlin: `// Canonical pattern — capturePhoto + includeImage inside a tool body.
1058
+ // The session is guaranteed Active here (the model only calls a tool
1059
+ // while Active), so the NotReady throw won't fire in practice.
1060
+ tool("describe_scene", "Describe what the user is currently looking at — call when the user asks 'what do you see' or 'describe this'.") {
1061
+ val photo = glasses.camera.capturePhoto().valueOrNull()
1062
+ ?: return@tool ToolResult.Err("camera failed")
1063
+ val uri = photo.uri
1064
+ ?: return@tool ToolResult.Err("photo had no uri")
1065
+ session.includeImage(uri)
1066
+ ToolResult.Ok("looking")
1067
+ }
1068
+
1069
+ // With a directed prompt — combine "look at this" with a specific
1070
+ // question. The prompt is sent as a user text alongside the image.
1071
+ tool("read_sign", "Read what's written on a sign in front of the user.") {
1072
+ val photo = glasses.camera.capturePhoto().valueOrNull()
1073
+ ?: return@tool ToolResult.Err("camera failed")
1074
+ val uri = photo.uri
1075
+ ?: return@tool ToolResult.Err("photo had no uri")
1076
+ session.includeImage(uri, prompt = "What does this sign say? Read it back verbatim.")
1077
+ ToolResult.Ok("reading")
1078
+ }
1079
+
1080
+ // Persistence sibling — save_photo. Use a DISTINCT tool from describe_scene
1081
+ // for the "save this picture" intent: the model picks based on user intent
1082
+ // ("save / capture / remember" → save_photo; "what / describe / tell me" →
1083
+ // describe_scene). DON'T fold both responsibilities into one tool: the
1084
+ // model can compose two tools when the user wants both (e.g. "save this
1085
+ // and tell me what it is" → save_photo + describe_scene back-to-back).
1086
+ //
1087
+ // SDK pairing: Photos.copyToFile mirrors Videos.copyToFile — one stream
1088
+ // copy that handles data:/file:// uniformly, creates parent dirs, returns
1089
+ // Boolean. Use it; don't hand-roll loadBytes + writeBytes.
1090
+ tool("save_photo", "Save a photo to the user's library WITHOUT describing it. Call for 'save this', 'capture this', 'take a picture', 'remember this view'.") {
1091
+ val photo = glasses.camera.capturePhoto().valueOrNull()
1092
+ ?: return@tool ToolResult.Err("camera failed")
1093
+ val uri = photo.uri
1094
+ ?: return@tool ToolResult.Err("photo had no uri")
1095
+ val ext = when (Photos.mediaTypeFromUri(uri)) {
1096
+ "image/png" -> "png"
1097
+ "image/webp" -> "webp"
1098
+ else -> "jpg"
1099
+ }
1100
+ val dst = File(library.photosDir, "photo-\${System.currentTimeMillis()}.\$ext")
1101
+ if (!Photos.copyToFile(uri, dst)) return@tool ToolResult.Err("could not save photo")
1102
+ library.addPhoto(dst.absolutePath, photo.width, photo.height)
1103
+ ToolResult.Ok("photo saved")
1104
+ }
1105
+
1106
+ // From a file path (real hardware case — content:// / file:// URI from
1107
+ // the platform camera intent). Same call shape — library handles the
1108
+ // read + base64 encode internally.
1109
+ session.includeImage("content://media/external/images/media/12345")`,
1110
+ swift: `// iOS port lands after Android stabilizes (see real-hardware-validation-backlog.md).
1111
+ // The Swift surface will mirror Kotlin's includeImage(uri:prompt:) signature.
1112
+ config.tool("describe_scene", description: "Describe what the user is currently looking at.") {
1113
+ guard let photo = (await self.glasses.camera.capturePhoto()).success else {
1114
+ return .err("camera failed")
1115
+ }
1116
+ guard let uri = photo.uri else { return .err("photo had no uri") }
1117
+ try await self.session?.includeImage(uri: uri)
1118
+ return .ok("looking")
1119
+ }`,
1120
+ gotchas: [
1121
+ "**Auto-triggers a response — that's the point.** `includeImage` is a one-call API: image goes in, the model speaks. If you want to stage an image without an immediate response (rare — e.g. accumulating multiple images then asking one question), drop down to the raw OpenAI provider primitive (not exposed in v1; file a request if you need it).",
1122
+ "**URI types map to wire format:** `data:image/...;base64,...` passes through verbatim (sim's capturePhoto returns this shape). `http(s)://...` passes through verbatim — OpenAI Realtime fetches the URL server-side; provider may reject for size / auth reasons, so prefer data: or base64 in production. `file://` / `content://` / bare path → library reads bytes via `Photos.loadBase64` + wraps with `mediaTypeFromUri` inferred MIME. Permission-gated like any other on-device read.",
1123
+ "**Active-only.** Same precondition as `session.say()` — throws `AssistantException(NotReady)` outside Active. Inside a tool body the state IS Active (the model only dispatches a tool while Active), so the typical usage is always safe. Don't call from `onWake { }` either — onWake fires fire-and-forget on a separate coroutine that may race with the Active transition; use a brief `delay` or call from the FIRST tool dispatch instead.",
1124
+ "**Image persists in conversation history at the provider.** Follow-up questions in the same session (\"what about the colors?\", \"is there text?\") work without re-sending. The library does NOT replay images on reconnect in v1 (the recent-40-turns replay covers text-only entries) — if a reconnect lands mid-image-conversation, the model loses raw visual access but keeps the conversation thread via the AssistantSpoke transcript.",
1125
+ "**Don't pass the photo bytes around manually.** The customer URI surface IS the API contract. Library handles base64 encoding, MIME detection, and the `conversation.item.create` wire shape. Manual base64-encoding inside a tool body is wasted code — just pass `photo.uri` and let the library figure out the rest.",
1126
+ "**Mock provider emits a deterministic stub event.** `MockAssistantProvider.includeImage` synthesizes an `AssistantSpoke(\"I see an image (uri=…)\")` so agent-driven tests can `assertEvent({ type: \"assistant.assistant_spoke\", contains: \"I see an image\" })` without a real vision model. For real vision behavior in CI you need the OpenAi provider — wire it via a build flavor (see assistant_agent_loop example for the BuildConfig pattern).",
1127
+ "**OpenAI Realtime image format (verified May 2026):** `conversation.item.create` → `item.type=\"message\"`, `role=\"user\"`, `content=[ {type:\"input_text\",text:...}, {type:\"input_image\",image_url:\"data:image/jpeg;base64,...\"} ]`. The text + image blocks can coexist; ordering is text-first so the prompt frames the image. After the item.create the library sends a follow-up `response.create` to trigger the model's response (same pattern as `say()`).",
1128
+ "**Describe vs save are TWO tools, not one (iter4 pattern).** `describe_scene` calls `includeImage` (model speaks about the photo, photo NOT persisted). `save_photo` calls `Photos.copyToFile` + your library's add-photo method (photo persisted, NOT described). The model picks based on user intent (\"what / describe / tell me\" → describe; \"save / capture / take a picture / remember\" → save) and can call BOTH back-to-back when the user wants both. Don't bake both responsibilities into one tool — splitting lets the model compose intents naturally and keeps each tool's description tight enough for the matcher (Mock + real-model alike) to disambiguate.",
1129
+ "**`Photos.copyToFile(uri, dst): Boolean` is the canonical photo-persist primitive (iter4).** Mirrors `Videos.copyToFile`: handles data: / file:// / absolute path uniformly, creates parent dirs, overwrites existing dst, returns false on any failure. Use it; don't hand-roll `Photos.loadBytes(uri)` + `File.writeBytes` — that's the same code with more lines and more failure modes to forget. Pick the file extension via `Photos.mediaTypeFromUri(uri)` (\"image/png\" → png, \"image/webp\" → webp, default jpg).",
1130
+ ],
1131
+ relatedExamples: ["assistant_agent_loop", "agent_driven_e2e_full_loop"],
1132
+ };
1133
+ const ASSISTANT_SESSION_RUNTIME = {
1134
+ feature: "assistant_session_runtime",
1135
+ summary: "Mid-session primitives on `AssistantSession` (iter5 addition). Four building blocks for runtime control: `setReasoningEffort` (change reasoning level mid-conversation), `updateInstructions` (swap the system prompt without losing context), `cancelSpeak` (programmatic barge-in — interrupt the model's in-flight utterance), `conversationHistory` (read-only snapshot of recent turns for forwarding to a stronger model). All four are Active-only (throws NotReady otherwise) except `conversationHistory` which is safe in any state. The SDK provides the primitives; you compose the flows.",
1136
+ kotlin: `// ── setReasoningEffort: model self-routes via a tool ───────────────
1137
+ // The model calls this tool when it senses a complex question. The
1138
+ // tool body bumps reasoning effort for subsequent turns. Pair with
1139
+ // "back_to_quick_chat" if you want to revert; skip it for sticky-high.
1140
+ tool("think_harder", "Call when the user asks something complex that needs deeper reasoning. The next response will take longer but be more thorough.") {
1141
+ session.setReasoningEffort(ReasoningEffort.High)
1142
+ ToolResult.Ok("thinking more carefully")
1143
+ }
1144
+
1145
+ tool("back_to_quick_chat", "Call when the user is done with the deep question and wants normal pace again.") {
1146
+ session.setReasoningEffort(ReasoningEffort.Low)
1147
+ ToolResult.Ok("back to quick mode")
1148
+ }
1149
+
1150
+ // ── updateInstructions: persona swap ───────────────────────────────
1151
+ tool("switch_to_formal", "When the user says something like 'be more formal' or 'professional voice now', switch persona.") {
1152
+ session.updateInstructions("""
1153
+ You are a professional, concise voice assistant. Respond in
1154
+ formal English. Keep replies brief and factual.
1155
+ """.trimIndent())
1156
+ ToolResult.Ok("switching to formal mode")
1157
+ }
1158
+
1159
+ // ── cancelSpeak: tool-driven interrupt ─────────────────────────────
1160
+ tool("stop_video", "Stop the current video recording.") {
1161
+ val clip = stopAndAwaitVideo() ?: return@tool ToolResult.Err("nothing recording")
1162
+ library.add(clip)
1163
+ // The model was mid-sentence about something else (maybe still
1164
+ // narrating its own previous reply); cut it off so the next
1165
+ // utterance comes from our tool result, not the prior context.
1166
+ session.cancelSpeak()
1167
+ ToolResult.Ok("video saved")
1168
+ }
1169
+
1170
+ // ── conversationHistory: escalation to a stronger model ────────────
1171
+ tool("ask_smart_model", "Use when the user asks something complex that needs a more powerful model — deep reasoning, long analysis, multi-step problems.") { args ->
1172
+ val question = args["question"]?.jsonPrimitive?.contentOrNull
1173
+ ?: return@tool ToolResult.Err("no question")
1174
+
1175
+ // Forward the recent conversation so the strong model has context.
1176
+ val context = session.conversationHistory(limit = 20).joinToString("\\n") {
1177
+ when (it) {
1178
+ is Turn.UserText -> "user: \${it.text}"
1179
+ is Turn.AssistantText -> "assistant: \${it.text}"
1180
+ is Turn.ToolInvocation -> "tool_call: \${it.name}(\${it.argsJson})"
1181
+ is Turn.ToolReturn -> "tool_result: \${it.output}"
1182
+ }
1183
+ }
1184
+
1185
+ val answer = myStrongModelClient.chat(
1186
+ model = "gpt-5",
1187
+ systemPrompt = "Continue this voice conversation. Be thorough.",
1188
+ userPrompt = "Recent context:\\n\\n\$context\\n\\nUser's current question: \$question",
1189
+ )
1190
+ ToolResult.Ok(answer) // realtime model reads this aloud
1191
+ }
1192
+
1193
+ // ── Conversation memory & compaction (iter5.1) ─────────────────
1194
+ //
1195
+ // **Two layers to understand:**
1196
+ // 1. OpenAI server-side session — exists only while WS is connected;
1197
+ // recreated every reconnect; no persistence at all.
1198
+ // 2. SDK local replay buffer — preserved across wake/sleep, replayed
1199
+ // to OpenAI on each connect. Capped at AssistantConfig.historyCap
1200
+ // (default 100). When the buffer approaches the cap, the
1201
+ // AssistantConfig.historyCompaction policy fires.
1202
+ //
1203
+ // **Default behavior:** Auto compaction — SDK summarizes oldest ~50%
1204
+ // via gpt-4o-mini using your BYOK key (~\$0.001 / compaction, every
1205
+ // ~30-45 min of talk), replaces them with one summary turn,
1206
+ // conversation continues indefinitely. Zero customer code required.
1207
+
1208
+ // ── Custom compactor (your own model + strategy) ───────────────
1209
+ glasses.assistant.start(provider) {
1210
+ instructions = "..."
1211
+ historyCap = 150 // raise if your conversations run long
1212
+
1213
+ historyCompaction = HistoryCompaction.Custom { turns ->
1214
+ // Customer-controlled. Could call a different model, write
1215
+ // to a vector DB, etc. Return the replacement buffer.
1216
+ val summary = myAnthropicClient.summarize(turns)
1217
+ val keepRecent = turns.takeLast(turns.size / 2)
1218
+ listOf(Turn.AssistantText("[summary] \$summary", System.currentTimeMillis())) + keepRecent
1219
+ }
1220
+
1221
+ tool("...") { ... }
1222
+ }
1223
+
1224
+ // ── Fresh-each-wake notetaker ──────────────────────────────────
1225
+ glasses.assistant.start(provider) {
1226
+ onWake { session.clearHistory() } // wipe before each turn-on
1227
+ historyCompaction = HistoryCompaction.DropOldest // disable Auto (no LLM cost)
1228
+ tool("...") { ... }
1229
+ }
1230
+
1231
+ // ── TTL reset (forget after long idle) ─────────────────────────
1232
+ var lastSleepAtMs = 0L
1233
+ glasses.assistant.start(provider) {
1234
+ onSleep { lastSleepAtMs = System.currentTimeMillis() }
1235
+ onWake {
1236
+ if (System.currentTimeMillis() - lastSleepAtMs > 5 * 60_000) {
1237
+ session.clearHistory()
1238
+ }
1239
+ }
1240
+ tool("...") { ... }
1241
+ }
1242
+
1243
+ // ── App-restart persistence (your storage; SDK doesn't persist) ─
1244
+ val savedTurns = mySavedHistoryStore.load() // your DataStore / Room / file
1245
+ if (savedTurns.isNotEmpty()) {
1246
+ session.replaceHistory(savedTurns) // SDK replays this on reconnect
1247
+ }
1248
+ // Save on each turn:
1249
+ glasses.runtime.events
1250
+ .filterIsInstance<RuntimeEvent.Assistant>()
1251
+ .onEach { mySavedHistoryStore.save(session.conversationHistory()) }
1252
+ .launchIn(scope)`,
1253
+ swift: `// iOS port for these four primitives lands with the next Mac VPS handoff.
1254
+ // Track in shared-context/real-hardware-validation-backlog.md.`,
1255
+ gotchas: [
1256
+ "**All four are Active-only except `conversationHistory`.** `setReasoningEffort` / `updateInstructions` / `cancelSpeak` throw `AssistantException(NotReady)` outside Active state — but tool bodies always run while Active (the model only dispatches a tool when the session is up), so the typical inside-a-tool-body usage is always safe. `conversationHistory` is safe in any state and returns an empty list pre-start or post-stop.",
1257
+ "**`setReasoningEffort` and `updateInstructions` mutate session state.** The new value persists until changed again OR the session ends. On a reconnect (transparent ~50-min cadence), the LATEST value gets sent — not the original config — so customer-driven changes survive reconnects naturally. No special handling needed.",
1258
+ "**`cancelSpeak` complements VAD-driven barge-in; it doesn't replace it.** The model already handles user-driven interruption when the VAD detects speech onset. This primitive is for the tool-driven / app-driven case where the developer wants to stop the model programmatically (e.g. after a tool completes and wants to deliver its result immediately, cutting off any filler the model was speaking).",
1259
+ "**`conversationHistory` returns at most the SDK's reconnect-replay cap (`AssistantConfig.historyCap`, default 100 as of iter5.1, was 40 in iter5).** Asking for more returns what's available. Order: chronological, oldest first. App can tune via `historyCap = N` in the start block; pair larger caps with `HistoryCompaction.Auto` (default) so conversations don't degrade silently past the model's quality cliff.",
1260
+ "**Memory compaction is automatic by default (`HistoryCompaction.Auto`, iter5.1).** When the local replay buffer crosses ~80% of `historyCap`, the SDK summarizes the oldest ~50% of turns via gpt-4o-mini using the customer's BYOK OpenAI key, replaces them with a single `[conversation summary] …` AssistantText turn, and the conversation continues indefinitely. Cost ~$0.001 per compaction (every ~30-45 min of talk). Customer can override the summarizer with `HistoryCompaction.Custom { turns -> ... }` for their own model / strategy, or disable with `HistoryCompaction.DropOldest` (free, lossy — original iter5 behavior). The summarizer makes outbound HTTP calls to api.openai.com/v1/chat/completions (NOT the Realtime endpoint); use `DropOldest` if you need to avoid that surface for compliance reasons.",
1261
+ "**Memory primitives compose (iter5.1):** `session.clearHistory()` wipes the buffer (any state, idempotent); `session.appendHistory(turn)` injects a turn for app-context hints or restored turns; `session.replaceHistory(turns)` swaps the entire buffer atomically. None of these trigger compaction. Customer composes patterns like fresh-each-wake (`onWake { session.clearHistory() }`), TTL reset (`onWake { if (idleTooLong) clearHistory() }`), or app-restart restoration (`session.replaceHistory(savedTurns)` before first wake). The SDK does NOT persist history to disk; that's the customer's storage layer.",
1262
+ "**`Turn.argsJson` is the serialized JSON string of tool arguments**, not a structured object. Customer code that wants typed args can re-parse with kotlinx.serialization (`Json.decodeFromString<MyArgs>(turn.argsJson)`) or pass the raw string to a downstream LLM. Kept as String to avoid leaking kotlinx.serialization types into the public surface — same precedent as how we kept `instructions` as raw String.",
1263
+ "**Mock provider records history too** (iter5). When you test escalation flows with `AssistantProvider.Mock()` + `injectAssistantUtterance`, the Mock builds up a conversation buffer just like the OpenAi runtime does. Your `ask_smart_model` tool's `session.conversationHistory()` call returns the inject sequence + tool I/O, so you can verify your escalation logic forwards the right context without ever talking to a real model.",
1264
+ "**`updateInstructions` does NOT change voice or model.** Those are provider-level locks (model: hard-locked at session start by OpenAI; voice: technically swappable mid-session on gpt-realtime-2 but not exposed by this primitive — file a request if you need it).",
1265
+ "**Don't write auto-routing heuristics inside the SDK** — let the model decide via tool descriptions. *\"Call think_harder when the user asks something that needs deep reasoning\"* + *\"Call back_to_quick_chat when they're done with the deep question\"* is enough; the model handles the orchestration. Per the SDK layering principle, the SDK provides primitives, the model + tool descriptions provide the flow.",
1266
+ ],
1267
+ relatedExamples: ["assistant_agent_loop", "agent_driven_e2e_full_loop"],
1268
+ };
784
1269
  export const CAPABILITY_GUIDES = {
785
1270
  capture_photo: CAPTURE_PHOTO,
786
1271
  capture_video: CAPTURE_VIDEO,
@@ -792,7 +1277,15 @@ export const CAPABILITY_GUIDES = {
792
1277
  connection_state: CONNECTION_STATE,
793
1278
  toggles: TOGGLES,
794
1279
  voice_command: VOICE_COMMAND,
795
- // Phase 3 conversation runtime primitives (see block above).
1280
+ // Phase 4 assistant runtime primitives (canonical voice-AI surface).
1281
+ assistant_runtime: ASSISTANT_RUNTIME,
1282
+ assistant_start: ASSISTANT_START,
1283
+ assistant_tool: ASSISTANT_TOOL,
1284
+ assistant_provider_openai: ASSISTANT_PROVIDER_OPENAI,
1285
+ assistant_vision: ASSISTANT_VISION,
1286
+ assistant_session_runtime: ASSISTANT_SESSION_RUNTIME,
1287
+ // Phase 3 conversation runtime primitives — DEPRECATED in v1.4.0,
1288
+ // REMOVED in v2.0.0. Kept here for the migration window.
796
1289
  conversation_runtime: CONVERSATION_RUNTIME,
797
1290
  conversation_on_wake: CONVERSATION_ON_WAKE,
798
1291
  conversation_listen: CONVERSATION_LISTEN,
@@ -1 +1 @@
1
- {"version":3,"file":"capabilityPatterns.js","sourceRoot":"","sources":["../../../src/tools/data/capabilityPatterns.ts"],"names":[],"mappings":"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"}
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mGA4CyF;IACjG,KAAK,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;6BA2BoB;IAC3B,OAAO,EAAE;QACP,wQAAwQ;QACxQ,wQAAwQ;QACxQ,6JAA6J;QAC7J,+JAA+J;QAC/J,mJAAmJ;QACnJ,kJAAkJ;QAClJ,uRAAuR;KACxR;IACD,eAAe,EAAE,CAAC,sBAAsB,CAAC;CAC1C,CAAC;AAEF,MAAM,YAAY,GAAoB;IACpC,OAAO,EAAE,cAAc;IACvB,OAAO,EACL,qPAAqP;IACvP,MAAM,EAAE;;;;;;;;;;;;yDAY+C;IACvD,KAAK,EAAE;;;;;;;;;gCASuB;IAC9B,OAAO,EAAE;QACP,kJAAkJ;QAClJ,wIAAwI;QACxI,iJAAiJ;QACjJ,iLAAiL;QACjL,wFAAwF;QACxF,uUAAuU;KACxU;IACD,eAAe,EAAE,CAAC,oBAAoB,EAAE,aAAa,CAAC;CACvD,CAAC;AAEF,MAAM,yBAAyB,GAAoB;IACjD,OAAO,EAAE,2BAA2B;IACpC,OAAO,EACL,wIAAwI;IAC1I,MAAM,EAAE;;;;;;;;;;;;EAYR;IACA,KAAK,EAAE;;;;;;;;;EASP;IACA,OAAO,EAAE;QACP,kQAAkQ;QAClQ,qOAAqO;QACrO,uKAAuK;QACvK,4MAA4M;QAC5M,8JAA8J;KAC/J;IACD,eAAe,EAAE,CAAC,oBAAoB,EAAE,uBAAuB,EAAE,aAAa,EAAE,sBAAsB,CAAC;CACxG,CAAC;AAEF,MAAM,gBAAgB,GAAoB;IACxC,OAAO,EAAE,OAAO;IAChB,OAAO,EACL,6rBAA6rB;IAC/rB,MAAM,EAAE;;;;;;;aAOG;IACX,KAAK,EAAE;;;;;;;;cAQK;IACZ,OAAO,EAAE;QACP,gJAAgJ;QAChJ,wKAAwK;QACxK,+LAA+L;QAC/L,kHAAkH;KACnH;IACD,eAAe,EAAE,CAAC,oBAAoB,EAAE,gBAAgB,EAAE,aAAa,EAAE,sBAAsB,CAAC;CACjG,CAAC;AAEF,MAAM,YAAY,GAAoB;IACpC,OAAO,EAAE,cAAc;IACvB,OAAO,EACL,4LAA4L;IAC9L,MAAM,EAAE;;;;;;;;;;EAUR;IACA,KAAK,EAAE;;;;;;;;;EASP;IACA,OAAO,EAAE;QACP,6LAA6L;QAC7L,2OAA2O;QAC3O,+LAA+L;QAC/L,+HAA+H;QAC/H,gHAAgH;KACjH;IACD,eAAe,EAAE,EAAE;CACpB,CAAC;AAEF,MAAM,YAAY,GAAoB;IACpC,OAAO,EAAE,cAAc;IACvB,OAAO,EACL,yJAAyJ;IAC3J,MAAM,EAAE;;;;;;;;;EASR;IACA,KAAK,EAAE;;;;;;;EAOP;IACA,OAAO,EAAE;QACP,8RAA8R;QAC9R,kJAAkJ;QAClJ,sHAAsH;QACtH,2GAA2G;QAC3G,uJAAuJ;KACxJ;IACD,eAAe,EAAE,EAAE;CACpB,CAAC;AAEF,MAAM,gBAAgB,GAAoB;IACxC,OAAO,EAAE,kBAAkB;IAC3B,OAAO,EACL,2MAA2M;IAC7M,MAAM,EAAE;;;;;;;;;EASR;IACA,KAAK,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8BP;IACA,OAAO,EAAE;QACP,2JAA2J;QAC3J,uPAAuP;KACxP;IACD,eAAe,EAAE,CAAC,uBAAuB,CAAC;CAC3C,CAAC;AAEF,MAAM,OAAO,GAAoB;IAC/B,OAAO,EAAE,SAAS;IAClB,OAAO,EACL,0SAA0S;IAC5S,MAAM,EAAE;;;;;;mFAMyE;IACjF,KAAK,EAAE;;;;;;;;;;;;;;;;;;;;;EAqBP;IACA,OAAO,EAAE;QACP,6MAA6M;QAC7M,4JAA4J;QAC5J,kHAAkH;QAClH,4JAA4J;KAC7J;IACD,eAAe,EAAE,EAAE;CACpB,CAAC;AAEF,MAAM,aAAa,GAAoB;IACrC,OAAO,EAAE,eAAe;IACxB,OAAO,EACL,84BAA84B;IACh5B,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8CAsCoC;IAC5C,KAAK,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8CAuCqC;IAC5C,OAAO,EAAE;QACP,kQAAkQ;QAClQ,mXAAmX;QACnX,2SAA2S;QAC3S,0QAA0Q;QAC1Q,uOAAuO;QACvO,4PAA4P;QAC5P,sQAAsQ;KACvQ;IACD,eAAe,EAAE,CAAC,oBAAoB,EAAE,gBAAgB,EAAE,aAAa,CAAC;CACzE,CAAC;AAEF,MAAM,aAAa,GAAoB;IACrC,OAAO,EAAE,eAAe;IACxB,OAAO,EACL,+XAA+X;IACjY,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gEA0EsD;IAC9D,KAAK,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6CF;IACL,OAAO,EAAE;QACP,yfAAyf;QACzf,2lBAA2lB;QAC3lB,mdAAmd;QACnd,6ZAA6Z;QAC7Z,6QAA6Q;QAC7Q,0UAA0U;QAC1U,kPAAkP;QAClP,sPAAsP;QACtP,4NAA4N;QAC5N,sZAAsZ;KACvZ;IACD,eAAe,EAAE,CAAC,aAAa,CAAC;CACjC,CAAC;AAEF,0EAA0E;AAC1E,EAAE;AACF,sEAAsE;AACtE,mEAAmE;AACnE,+DAA+D;AAC/D,4DAA4D;AAC5D,mEAAmE;AACnE,wEAAwE;AACxE,yCAAyC;AAEzC,MAAM,oBAAoB,GAAoB;IAC5C,OAAO,EAAE,sBAAsB;IAC/B,OAAO,EACL,gTAAgT;IAClT,MAAM,EAAE;;;;;;;;;;;;;;;;;EAiBR;IACA,KAAK,EAAE;;;;;;;;;;;;;;;;EAgBP;IACA,OAAO,EAAE;QACP,okBAAokB;QACpkB,2TAA2T;QAC3T,yjBAAyjB;QACzjB,0QAA0Q;KAC3Q;IACD,eAAe,EAAE,CAAC,yBAAyB,CAAC;CAC7C,CAAC;AAEF,MAAM,mBAAmB,GAAoB;IAC3C,OAAO,EAAE,qBAAqB;IAC9B,OAAO,EACL,uUAAuU;IACzU,MAAM,EAAE;;;;;;;;;;;;;;EAcR;IACA,KAAK,EAAE;;;;;;;;;;;;EAYP;IACA,OAAO,EAAE;QACP,4QAA4Q;QAC5Q,gPAAgP;QAChP,qVAAqV;QACrV,yRAAyR;KAC1R;IACD,eAAe,EAAE,CAAC,yBAAyB,CAAC;CAC7C,CAAC;AAEF,MAAM,kBAAkB,GAAoB;IAC1C,OAAO,EAAE,oBAAoB;IAC7B,OAAO,EACL,sVAAsV;IACxV,MAAM,EAAE;;;;;;;;;;;;;;;+CAeqC;IAC7C,KAAK,EAAE;;;;;;;;;;;;;;mDAc0C;IACjD,OAAO,EAAE;QACP,8TAA8T;QAC9T,uQAAuQ;QACvQ,4WAA4W;QAC5W,oPAAoP;KACrP;IACD,eAAe,EAAE,CAAC,yBAAyB,CAAC;CAC7C,CAAC;AAEF,MAAM,wBAAwB,GAAoB;IAChD,OAAO,EAAE,0BAA0B;IACnC,OAAO,EACL,yVAAyV;IAC3V,MAAM,EAAE;;;;;;;;;;;;;;;;;EAiBR;IACA,KAAK,EAAE;;;;;;;;;;;;;;;;EAgBP;IACA,OAAO,EAAE;QACP,6TAA6T;QAC7T,yQAAyQ;QACzQ,uVAAuV;QACvV,uOAAuO;QACvO,2ZAA2Z;KAC5Z;IACD,eAAe,EAAE,CAAC,yBAAyB,EAAE,gBAAgB,CAAC;CAC/D,CAAC;AAEF,MAAM,oBAAoB,GAAoB;IAC5C,OAAO,EAAE,sBAAsB;IAC/B,OAAO,EACL,gcAAgc;IAClc,MAAM,EAAE;;;;;;;;EAQR;IACA,KAAK,EAAE;;;;;;;;EAQP;IACA,OAAO,EAAE;QACP,gqBAAgqB;QAChqB,sXAAsX;QACtX,sQAAsQ;QACtQ,gQAAgQ;KACjQ;IACD,eAAe,EAAE,CAAC,yBAAyB,CAAC;CAC7C,CAAC;AAEF,yEAAyE;AAEzE,MAAM,iBAAiB,GAAoB;IACzC,OAAO,EAAE,mBAAmB;IAC5B,OAAO,EACL,wvBAAwvB;IAC1vB,MAAM,EAAE;;;;;;;;;;;;EAYR;IACA,KAAK,EAAE;;;;;;;;;;;;;;;;EAgBP;IACA,OAAO,EAAE;QACP,+TAA+T;QAC/T,yTAAyT;QACzT,gaAAga;QACha,6bAA6b;QAC7b,mVAAmV;QACnV,uYAAuY;QACvY,6sFAA6sF;KAC9sF;IACD,eAAe,EAAE,CAAC,sBAAsB,EAAE,4BAA4B,CAAC;CACxE,CAAC;AAEF,MAAM,eAAe,GAAoB;IACvC,OAAO,EAAE,iBAAiB;IAC1B,OAAO,EACL,0XAA0X;IAC5X,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;6DAsBmD;IAC3D,KAAK,EAAE;;;;;;;;;;;;;;;;;;;;yEAoBgE;IACvE,OAAO,EAAE;QACP,sWAAsW;QACtW,2RAA2R;QAC3R,sWAAsW;QACtW,mNAAmN;KACpN;IACD,eAAe,EAAE,CAAC,sBAAsB,EAAE,4BAA4B,CAAC;CACxE,CAAC;AAEF,MAAM,cAAc,GAAoB;IACtC,OAAO,EAAE,gBAAgB;IACzB,OAAO,EACL,0sBAA0sB;IAC5sB,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6BR;IACA,KAAK,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoCP;IACA,OAAO,EAAE;QACP,yaAAya;QACza,+XAA+X;QAC/X,scAAsc;QACtc,yWAAyW;QACzW,6YAA6Y;KAC9Y;IACD,eAAe,EAAE,CAAC,sBAAsB,EAAE,4BAA4B,CAAC;CACxE,CAAC;AAEF,MAAM,yBAAyB,GAAoB;IACjD,OAAO,EAAE,2BAA2B;IACpC,OAAO,EACL,svBAAsvB;IACxvB,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8DAoCoD;IAC5D,KAAK,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qDA8B4C;IACnD,OAAO,EAAE;QACP,4zBAA4zB;QAC5zB,wZAAwZ;QACxZ,wWAAwW;QACxW,iWAAiW;QACjW,uWAAuW;QACvW,uaAAua;QACva,uMAAuM;QACvM,qPAAqP;KACtP;IACD,eAAe,EAAE,CAAC,sBAAsB,EAAE,4BAA4B,CAAC;CACxE,CAAC;AAEF,MAAM,gBAAgB,GAAoB;IACxC,OAAO,EAAE,kBAAkB;IAC3B,OAAO,EACL,4yBAA4yB;IAC9yB,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oEAoD0D;IAClE,KAAK,EAAE;;;;;;;;;EASP;IACA,OAAO,EAAE;QACP,yVAAyV;QACzV,+dAA+d;QAC/d,mbAAmb;QACnb,ibAAib;QACjb,yTAAyT;QACzT,2bAA2b;QAC3b,0cAA0c;QAC1c,kpBAAkpB;QAClpB,6fAA6f;KAC9f;IACD,eAAe,EAAE,CAAC,sBAAsB,EAAE,4BAA4B,CAAC;CACxE,CAAC;AAEF,MAAM,yBAAyB,GAAoB;IACjD,OAAO,EAAE,2BAA2B;IACpC,OAAO,EACL,wkBAAwkB;IAC1kB,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAoHW;IACnB,KAAK,EAAE;gEACuD;IAC9D,OAAO,EAAE;QACP,4aAA4a;QAC5a,mUAAmU;QACnU,gZAAgZ;QAChZ,2ZAA2Z;QAC3Z,syBAAsyB;QACtyB,8lBAA8lB;QAC9lB,0ZAA0Z;QAC1Z,6aAA6a;QAC7a,wQAAwQ;QACxQ,2ZAA2Z;KAC5Z;IACD,eAAe,EAAE,CAAC,sBAAsB,EAAE,4BAA4B,CAAC;CACxE,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAoC;IAChE,aAAa,EAAE,aAAa;IAC5B,aAAa,EAAE,aAAa;IAC5B,YAAY,EAAE,YAAY;IAC1B,yBAAyB,EAAE,yBAAyB;IACpD,KAAK,EAAE,gBAAgB;IACvB,YAAY,EAAE,YAAY;IAC1B,YAAY,EAAE,YAAY;IAC1B,gBAAgB,EAAE,gBAAgB;IAClC,OAAO,EAAE,OAAO;IAChB,aAAa,EAAE,aAAa;IAC5B,qEAAqE;IACrE,iBAAiB,EAAE,iBAAiB;IACpC,eAAe,EAAE,eAAe;IAChC,cAAc,EAAE,cAAc;IAC9B,yBAAyB,EAAE,yBAAyB;IACpD,gBAAgB,EAAE,gBAAgB;IAClC,yBAAyB,EAAE,yBAAyB;IACpD,kEAAkE;IAClE,yDAAyD;IACzD,oBAAoB,EAAE,oBAAoB;IAC1C,oBAAoB,EAAE,oBAAoB;IAC1C,mBAAmB,EAAE,mBAAmB;IACxC,kBAAkB,EAAE,kBAAkB;IACtC,wBAAwB,EAAE,wBAAwB;CACnD,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,IAAI,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"codeExamples.d.ts","sourceRoot":"","sources":["../../../src/tools/data/codeExamples.ts"],"names":[],"mappings":"AAeA,6DAA6D;AAC7D,MAAM,WAAW,iBAAiB;IAChC,kEAAkE;IAClE,aAAa,EAAE,gBAAgB,GAAG,qBAAqB,GAAG,oBAAoB,GAAG,2BAA2B,CAAC;IAC7G,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,SAAS,EAAE,sBAAsB,CAAC;CACnC;AAED,6DAA6D;AAC7D,MAAM,WAAW,oBAAoB;IACnC,mEAAmE;IACnE,EAAE,EAAE,MAAM,CAAC;IACX,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,SAAS,EAAE,uBAAuB,GAAG,sBAAsB,CAAC;IAC5D;4EACwE;IACxE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,mEAAmE;AACnE,MAAM,WAAW,oBAAoB;IACnC,sBAAsB;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,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;IAC1B;;;;;;OAMG;IACH,oBAAoB,CAAC,EAAE;QACrB,OAAO,CAAC,EAAE,iBAAiB,EAAE,CAAC;QAC9B,gBAAgB,CAAC,EAAE,oBAAoB,EAAE,CAAC;KAC3C,CAAC;IACF;;;;;;OAMG;IACH,eAAe,CAAC,EAAE;QAChB,OAAO,CAAC,EAAE,oBAAoB,EAAE,CAAC;KAClC,CAAC;CACH;AA63DD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAUrD,CAAC;AAEF,eAAO,MAAM,qBAAqB,UAAoC,CAAC"}
1
+ {"version":3,"file":"codeExamples.d.ts","sourceRoot":"","sources":["../../../src/tools/data/codeExamples.ts"],"names":[],"mappings":"AAeA,6DAA6D;AAC7D,MAAM,WAAW,iBAAiB;IAChC,kEAAkE;IAClE,aAAa,EAAE,gBAAgB,GAAG,qBAAqB,GAAG,oBAAoB,GAAG,2BAA2B,CAAC;IAC7G,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,SAAS,EAAE,sBAAsB,CAAC;CACnC;AAED,6DAA6D;AAC7D,MAAM,WAAW,oBAAoB;IACnC,mEAAmE;IACnE,EAAE,EAAE,MAAM,CAAC;IACX,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,SAAS,EAAE,uBAAuB,GAAG,sBAAsB,CAAC;IAC5D;4EACwE;IACxE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,mEAAmE;AACnE,MAAM,WAAW,oBAAoB;IACnC,sBAAsB;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,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;IAC1B;;;;;;OAMG;IACH,oBAAoB,CAAC,EAAE;QACrB,OAAO,CAAC,EAAE,iBAAiB,EAAE,CAAC;QAC9B,gBAAgB,CAAC,EAAE,oBAAoB,EAAE,CAAC;KAC3C,CAAC;IACF;;;;;;OAMG;IACH,eAAe,CAAC,EAAE;QAChB,OAAO,CAAC,EAAE,oBAAoB,EAAE,CAAC;KAClC,CAAC;CACH;AAkxFD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAYrD,CAAC;AAEF,eAAO,MAAM,qBAAqB,UAAoC,CAAC"}