@d-id/client-sdk 1.2.7-staging.363 → 1.2.8-staging.365

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.
@@ -0,0 +1,471 @@
1
+ import { c as Ue, C as z, S as f, a as Oe, b as je, A as g, d as Ne, l as le, e as ze, t as Be, f as A, g as O, h as Je, i as Qe, j as R, n as We } from "./index-BXfxP3Yk.js";
2
+ function qe() {
3
+ try {
4
+ return Intl.DateTimeFormat().resolvedOptions().timeZone ?? "";
5
+ } catch {
6
+ return "";
7
+ }
8
+ }
9
+ function He() {
10
+ if (typeof navigator > "u")
11
+ return "";
12
+ const l = navigator.userAgent ?? "", C = (navigator.platform ?? "").toLowerCase();
13
+ let u = "Unknown";
14
+ /android/i.test(l) ? u = "Android" : /iphone|ipad|ipod/i.test(l) ? u = "iOS" : C.includes("win") ? u = "Windows" : C.includes("mac") ? u = "Mac OS X" : C.includes("linux") && (u = "Linux");
15
+ const i = u === "Android" || u === "iOS" || /Mobi/i.test(l);
16
+ return `${u}, ${i ? "Mobile" : "Desktop"}`;
17
+ }
18
+ function Xe() {
19
+ const l = {}, C = qe();
20
+ C && (l.timezone = C);
21
+ const u = He();
22
+ return u && (l.device = u), l;
23
+ }
24
+ function Ze(l, C, u, i) {
25
+ const M = Ue(l, `${C}/v2/agents/${u}`, i);
26
+ return {
27
+ async createStream(h) {
28
+ return M.post("/sessions", h);
29
+ }
30
+ };
31
+ }
32
+ const Ge = {
33
+ [f.ChatAnswer]: z.Answer,
34
+ [f.ChatPartial]: z.Partial
35
+ }, pe = 2e4;
36
+ async function Ye() {
37
+ try {
38
+ return await import("./livekit-client.esm-DypJ_fOm.js");
39
+ } catch {
40
+ throw new Error(
41
+ "LiveKit client is required for this streaming manager. Please install it using: npm install livekit-client"
42
+ );
43
+ }
44
+ }
45
+ const en = {
46
+ excellent: O.Strong,
47
+ good: O.Strong,
48
+ poor: O.Weak,
49
+ lost: O.Unknown,
50
+ unknown: O.Unknown
51
+ }, D = (l = "Stream Error") => new ze(l);
52
+ function fe(l, C, u) {
53
+ var i, M;
54
+ throw C("Failed to connect to LiveKit room:", l), (i = u.onConnectionStateChange) == null || i.call(u, A.Fail, "internal:init-error"), (M = u.onError) == null || M.call(u, l, { sessionId: "" }), l;
55
+ }
56
+ async function tn(l, C, u) {
57
+ var ae;
58
+ const i = Oe(u.debug || !1, "LiveKitStreamingManager"), { Room: M, RoomEvent: h, ConnectionState: k, Track: X } = await Ye(), { callbacks: n, auth: ge, baseURL: he, analytics: Z } = u;
59
+ let a = null, E = !1;
60
+ const G = je.Fluent;
61
+ let L = null;
62
+ const b = { isPublishing: !1, publication: null }, B = { isPublishing: !1, publication: null };
63
+ let m = null, S = null, j = null, V = !1;
64
+ a = new M({
65
+ adaptiveStream: !1,
66
+ // Must be false to use mediaStreamTrack directly
67
+ dynacast: !0
68
+ });
69
+ let P = null, v = g.Idle, I = !0;
70
+ const F = /* @__PURE__ */ new Set(), me = Ze(ge, he || Ne, l, n.onError);
71
+ let y, $, K, Y = !0;
72
+ try {
73
+ const e = await me.createStream({
74
+ transport: C.transport,
75
+ chat_persist: C.chat_persist ?? !0,
76
+ verbose: u.verbose ?? !1
77
+ }), { id: t, session_token: o, session_url: r, interrupt_enabled: s } = e;
78
+ (ae = n.onStreamCreated) == null || ae.call(n, { session_id: t, stream_id: t, agent_id: l }), y = t, $ = o, K = r, Y = s ?? !0, await a.prepareConnection(K, $);
79
+ } catch (e) {
80
+ fe(e, i, n);
81
+ }
82
+ if (!K || !$ || !y)
83
+ return Promise.reject(new Error("Failed to initialize LiveKit stream"));
84
+ a.on(h.ConnectionStateChanged, ye).on(h.ConnectionQualityChanged, Te).on(h.ParticipantConnected, ve).on(h.ParticipantDisconnected, we).on(h.TrackSubscribed, Ee).on(h.TrackUnsubscribed, Pe).on(h.DataReceived, Me).on(h.MediaDevicesError, ke).on(h.TranscriptionReceived, Ce).on(h.EncryptionError, Ie).on(h.TrackSubscriptionFailed, $e);
85
+ function Ce(e, t) {
86
+ t != null && t.isLocal && (le.update(), v === g.Talking && (v = g.Idle));
87
+ }
88
+ async function Se() {
89
+ const e = Xe();
90
+ if (!(!a || Object.keys(e).length === 0))
91
+ try {
92
+ await a.localParticipant.setAttributes(e);
93
+ } catch (t) {
94
+ i("Failed to set user context attributes", t);
95
+ }
96
+ }
97
+ try {
98
+ await a.connect(K, $), i("LiveKit room joined successfully"), Se(), P = setTimeout(() => {
99
+ var t;
100
+ i(
101
+ `Track subscription timeout - no track subscribed within ${pe / 1e3} seconds after connect`
102
+ ), P = null;
103
+ const e = D("Track subscription timeout");
104
+ Z.track("connectivity-error", {
105
+ error: Be(e),
106
+ sessionId: y
107
+ }), (t = n.onError) == null || t.call(n, e, { sessionId: y }), H("internal:track-subscription-timeout");
108
+ }, pe);
109
+ } catch (e) {
110
+ fe(e, i, n);
111
+ }
112
+ Z.enrich({
113
+ "stream-type": G
114
+ });
115
+ function ye(e) {
116
+ var t, o, r, s;
117
+ switch (i("Connection state changed:", e), e) {
118
+ case k.Connecting:
119
+ i("CALLBACK: onConnectionStateChange(Connecting)"), (t = n.onConnectionStateChange) == null || t.call(n, A.Connecting, "livekit:connecting");
120
+ break;
121
+ case k.Connected:
122
+ i("LiveKit room connected successfully"), E = !0;
123
+ break;
124
+ case k.Disconnected:
125
+ i("LiveKit room disconnected"), E = !1, V = !1, b.publication = null, B.publication = null, (o = n.onConnectionStateChange) == null || o.call(n, A.Disconnected, "livekit:disconnected");
126
+ break;
127
+ case k.Reconnecting:
128
+ i("LiveKit room reconnecting..."), (r = n.onConnectionStateChange) == null || r.call(n, A.Connecting, "livekit:reconnecting");
129
+ break;
130
+ case k.SignalReconnecting:
131
+ i("LiveKit room signal reconnecting..."), (s = n.onConnectionStateChange) == null || s.call(n, A.Connecting, "livekit:signal-reconnecting");
132
+ break;
133
+ }
134
+ }
135
+ function Te(e, t) {
136
+ var o;
137
+ i("Connection quality:", e), t != null && t.isLocal && ((o = n.onConnectivityStateChange) == null || o.call(n, en[e]));
138
+ }
139
+ function ve(e) {
140
+ i("Participant connected:", e.identity);
141
+ }
142
+ function we(e) {
143
+ i("Participant disconnected:", e.identity), H("livekit:participant-disconnected");
144
+ }
145
+ function Ae() {
146
+ var e;
147
+ j !== R.Start && (i("CALLBACK: onVideoStateChange(Start)"), j = R.Start, (e = n.onVideoStateChange) == null || e.call(n, R.Start));
148
+ }
149
+ function ee(e) {
150
+ var t;
151
+ j !== R.Stop && (i("CALLBACK: onVideoStateChange(Stop)"), j = R.Stop, (t = n.onVideoStateChange) == null || t.call(n, R.Stop, e));
152
+ }
153
+ function Ee(e, t, o) {
154
+ var s, d, p;
155
+ i(`Track subscribed: ${e.kind} from ${o.identity}`);
156
+ const r = e.mediaStreamTrack;
157
+ if (!r) {
158
+ i(`No mediaStreamTrack available for ${e.kind}`);
159
+ return;
160
+ }
161
+ L ? (L.addTrack(r), i(`Added ${e.kind} track to shared MediaStream`)) : (L = new MediaStream([r]), i(`Created shared MediaStream with ${e.kind} track`)), e.kind === "audio" && (S = Qe(
162
+ () => e.getRTCStatsReport(),
163
+ ({ sttLatency: c, serviceLatency: T }) => {
164
+ var ce, se, de;
165
+ const x = le.get(!0);
166
+ let U = 0;
167
+ if (c) {
168
+ const ue = ((se = (ce = m == null ? void 0 : m.getReport()) == null ? void 0 : ce.webRTCStats) == null ? void 0 : se.avgRtt) ?? 0;
169
+ U = ue > 0 ? Math.round(ue * 1e3) : 0;
170
+ }
171
+ const _ = x > 0 ? x + (c ?? 0) + U : void 0, w = _ !== void 0 && T !== void 0 ? _ - T : void 0;
172
+ (de = n.onFirstAudioDetected) == null || de.call(n, { latency: _, networkLatency: w });
173
+ }
174
+ )), e.kind === "video" && ((s = n.onStreamReady) == null || s.call(n), i("CALLBACK: onSrcObjectReady"), (d = n.onSrcObjectReady) == null || d.call(n, L), V || (V = !0, i("CALLBACK: onConnectionStateChange(Connected)"), (p = n.onConnectionStateChange) == null || p.call(n, A.Connected, "livekit:track-subscribed")), m = Je(
175
+ () => e.getRTCStatsReport(),
176
+ () => E,
177
+ We,
178
+ (c, T) => {
179
+ i(`Video state change: ${c}`), c === R.Start ? (P && (clearTimeout(P), P = null, i("Track subscription timeout cleared")), Ae()) : c === R.Stop && ee(T);
180
+ }
181
+ ), m.start());
182
+ }
183
+ function Pe(e, t, o) {
184
+ i(`Track unsubscribed: ${e.kind} from ${o.identity}`), e.kind === "audio" && (S == null || S.destroy(), S = null), e.kind === "video" && (ee(m == null ? void 0 : m.getReport()), m == null || m.stop(), m = null);
185
+ }
186
+ function ne(e, t) {
187
+ var r;
188
+ const o = Ge[e];
189
+ o && ((r = n.onMessage) == null || r.call(n, o, { event: o, ...t }));
190
+ }
191
+ function J(e, t) {
192
+ var o, r, s, d, p;
193
+ if (e === f.ToolCallStarted) {
194
+ const c = t;
195
+ I = c.interruptible !== !1, (o = n.onInterruptibleChange) == null || o.call(n, I), F.add(c.call_id), v = g.ToolActive, (r = n.onAgentActivityStateChange) == null || r.call(n, g.ToolActive), (s = n.onToolEvent) == null || s.call(n, f.ToolCallStarted, c);
196
+ return;
197
+ }
198
+ if (e === f.ToolCallDone) {
199
+ const c = t;
200
+ te(c.call_id), (d = n.onToolEvent) == null || d.call(n, f.ToolCallDone, c);
201
+ return;
202
+ }
203
+ if (e === f.ToolCallError) {
204
+ const c = t;
205
+ te(c.call_id), (p = n.onToolEvent) == null || p.call(n, f.ToolCallError, c);
206
+ }
207
+ }
208
+ function te(e) {
209
+ var t;
210
+ F.delete(e), F.size === 0 && v === g.ToolActive && (v = g.Idle, (t = n.onAgentActivityStateChange) == null || t.call(n, g.Idle));
211
+ }
212
+ function Re(e, t) {
213
+ var o, r, s, d, p, c;
214
+ if (I = ((o = t.metadata) == null ? void 0 : o.interruptible) !== !1, (r = n.onInterruptibleChange) == null || r.call(n, I), e === f.StreamVideoCreated) {
215
+ v = g.Talking, (s = n.onAgentActivityStateChange) == null || s.call(n, g.Talking), S == null || S.arm({
216
+ sttLatency: (d = t == null ? void 0 : t.stt) == null ? void 0 : d.latency,
217
+ serviceLatency: t == null ? void 0 : t.serviceLatency
218
+ });
219
+ return;
220
+ }
221
+ if (F.size > 0) {
222
+ v !== g.ToolActive && (v = g.ToolActive, (p = n.onAgentActivityStateChange) == null || p.call(n, g.ToolActive));
223
+ return;
224
+ }
225
+ I && (v = g.Idle, (c = n.onAgentActivityStateChange) == null || c.call(n, g.Idle));
226
+ }
227
+ function N(e, t) {
228
+ var d, p, c, T;
229
+ const o = ((p = (d = m == null ? void 0 : m.getReport()) == null ? void 0 : d.webRTCStats) == null ? void 0 : p.avgRtt) ?? 0, r = o > 0 ? Math.round(o / 2 * 1e3) : 0, s = { ...t, downstreamNetworkLatency: r };
230
+ u.debug && ((c = t == null ? void 0 : t.metadata) != null && c.sentiment) && (s.sentiment = {
231
+ id: t.metadata.sentiment.id,
232
+ name: t.metadata.sentiment.sentiment
233
+ }), (T = n.onMessage) == null || T.call(n, e, s), Re(e, t);
234
+ }
235
+ function Le(e, t) {
236
+ var o;
237
+ (o = n.onMessage) == null || o.call(n, z.Transcribe, { event: z.Transcribe, ...t }), queueMicrotask(() => {
238
+ var r;
239
+ (r = n.onAgentActivityStateChange) == null || r.call(n, g.Loading);
240
+ });
241
+ }
242
+ const be = {
243
+ [f.ChatAnswer]: ne,
244
+ [f.ChatPartial]: ne,
245
+ [f.ToolCallStarted]: J,
246
+ [f.ToolCallDone]: J,
247
+ [f.ToolCallError]: J,
248
+ [f.StreamVideoCreated]: N,
249
+ [f.StreamVideoDone]: N,
250
+ [f.StreamVideoError]: N,
251
+ [f.StreamVideoRejected]: N,
252
+ [f.ChatAudioTranscribed]: Le
253
+ };
254
+ function Me(e, t, o, r) {
255
+ const s = new TextDecoder().decode(e);
256
+ try {
257
+ const d = JSON.parse(s), p = r || d.subject;
258
+ if (i("Data received:", { subject: p, data: d }), !p) return;
259
+ const c = be[p];
260
+ c == null || c(p, d);
261
+ } catch (d) {
262
+ i("Failed to parse data channel message:", d);
263
+ }
264
+ }
265
+ function ke(e) {
266
+ var t;
267
+ i("Media devices error:", e), (t = n.onError) == null || t.call(n, D(), { sessionId: y });
268
+ }
269
+ function Ie(e) {
270
+ var t;
271
+ i("Encryption error:", e), (t = n.onError) == null || t.call(n, D(), { sessionId: y });
272
+ }
273
+ function $e(e, t, o) {
274
+ i("Track subscription failed:", { trackSid: e, participant: t, reason: o });
275
+ }
276
+ function Ke(e, t, o) {
277
+ for (const [r, s] of o)
278
+ if (s.source === t && s.track) {
279
+ const d = s.track.mediaStreamTrack;
280
+ if (d === e || (d == null ? void 0 : d.id) === e.id)
281
+ return s;
282
+ }
283
+ return null;
284
+ }
285
+ async function ie(e, t, o, r, s, d) {
286
+ var x, U, _;
287
+ if (!E || !a)
288
+ throw i(`Room is not connected, cannot publish ${r} stream`), new Error("Room is not connected");
289
+ if (e.isPublishing) {
290
+ i(`${r} publish already in progress, skipping`);
291
+ return;
292
+ }
293
+ const p = o(t);
294
+ if (p.length === 0)
295
+ throw new Error(`No ${r} track found in the provided MediaStream`);
296
+ const c = p[0], T = Ke(c, r, s());
297
+ if (T) {
298
+ i(`${r} track is already published, skipping`, {
299
+ trackId: c.id,
300
+ publishedTrackId: (U = (x = T.track) == null ? void 0 : x.mediaStreamTrack) == null ? void 0 : U.id
301
+ }), e.publication = T;
302
+ return;
303
+ }
304
+ if ((_ = e.publication) != null && _.track) {
305
+ const w = e.publication.track.mediaStreamTrack;
306
+ w !== c && (w == null ? void 0 : w.id) !== c.id && (i(`Unpublishing existing ${r} track before publishing new one`), await d());
307
+ }
308
+ i(`Publishing ${r} track from provided MediaStream`, { trackId: c.id }), e.isPublishing = !0;
309
+ try {
310
+ e.publication = await a.localParticipant.publishTrack(c, { source: r }), i(`${r} track published successfully`, { trackSid: e.publication.trackSid });
311
+ } catch (w) {
312
+ throw i(`Failed to publish ${r} track:`, w), w;
313
+ } finally {
314
+ e.isPublishing = !1;
315
+ }
316
+ }
317
+ async function oe(e, t) {
318
+ if (!(!e.publication || !e.publication.track))
319
+ try {
320
+ a && (await a.localParticipant.unpublishTrack(e.publication.track, !1), i(`${t} track unpublished`));
321
+ } catch (o) {
322
+ i(`Error unpublishing ${t} track:`, o);
323
+ } finally {
324
+ e.publication = null;
325
+ }
326
+ }
327
+ async function _e(e) {
328
+ return ie(
329
+ b,
330
+ e,
331
+ (t) => t.getAudioTracks(),
332
+ X.Source.Microphone,
333
+ () => a.localParticipant.audioTrackPublications,
334
+ Q
335
+ );
336
+ }
337
+ async function Q() {
338
+ return oe(b, "Microphone");
339
+ }
340
+ async function De(e) {
341
+ if (!E || !a)
342
+ throw i("Cannot replace microphone track: room is not connected"), new Error("Room is not connected");
343
+ if (e.kind !== "audio")
344
+ throw i("Cannot replace microphone track: not an audio track", { kind: e.kind }), new Error("Microphone track must be an audio track");
345
+ if (b.isPublishing)
346
+ throw i("Cannot replace microphone track: publish in progress"), new Error("Microphone publish in progress");
347
+ const t = b.publication;
348
+ if (!t || !t.track)
349
+ throw i("Cannot replace microphone track: no publication to replace"), new Error("No microphone publication to replace");
350
+ try {
351
+ b.isPublishing = !0, await t.track.replaceTrack(e), i("Microphone track replaced", { trackId: e.id, trackSid: t.trackSid });
352
+ } finally {
353
+ b.isPublishing = !1;
354
+ }
355
+ }
356
+ async function Ve(e) {
357
+ return ie(
358
+ B,
359
+ e,
360
+ (t) => t.getVideoTracks(),
361
+ X.Source.Camera,
362
+ () => a.localParticipant.videoTrackPublications,
363
+ W
364
+ );
365
+ }
366
+ async function W() {
367
+ return oe(B, "Camera");
368
+ }
369
+ function Fe() {
370
+ L && (L.getTracks().forEach((e) => e.stop()), L = null);
371
+ }
372
+ async function q(e, t) {
373
+ var o, r;
374
+ if (!E || !a) {
375
+ i("Room is not connected for sending messages"), (o = n.onError) == null || o.call(n, D(), {
376
+ sessionId: y
377
+ });
378
+ return;
379
+ }
380
+ try {
381
+ await a.localParticipant.sendText(e, { topic: t }), i("Message sent successfully:", e);
382
+ } catch (s) {
383
+ i("Failed to send message:", s), (r = n.onError) == null || r.call(n, D(), { sessionId: y });
384
+ }
385
+ }
386
+ async function re(e) {
387
+ var t;
388
+ try {
389
+ const r = JSON.parse(e).topic;
390
+ return q("", r);
391
+ } catch (o) {
392
+ i("Failed to send data channel message:", o), (t = n.onError) == null || t.call(n, D(), { sessionId: y });
393
+ }
394
+ }
395
+ function xe(e) {
396
+ return q(
397
+ e,
398
+ "lk.chat"
399
+ /* Chat */
400
+ );
401
+ }
402
+ async function H(e) {
403
+ var t, o;
404
+ P && (clearTimeout(P), P = null), S == null || S.destroy(), S = null, a && ((t = n.onConnectionStateChange) == null || t.call(n, A.Disconnecting, e), await Promise.all([Q(), W()]), await a.disconnect()), Fe(), E = !1, V = !1, F.clear(), (o = n.onAgentActivityStateChange) == null || o.call(n, g.Idle), v = g.Idle;
405
+ }
406
+ return {
407
+ speak(e) {
408
+ const t = typeof e == "string" ? e : JSON.stringify(e);
409
+ return q(
410
+ t,
411
+ "did.speak"
412
+ /* Speak */
413
+ );
414
+ },
415
+ disconnect: () => H("user:disconnect"),
416
+ async reconnect() {
417
+ var e, t;
418
+ if ((a == null ? void 0 : a.state) === k.Connected) {
419
+ i("Room is already connected");
420
+ return;
421
+ }
422
+ if (!a || !K || !$)
423
+ throw i("Cannot reconnect: missing room, URL or token"), new Error("Cannot reconnect: session not available");
424
+ i("Reconnecting to LiveKit room, state:", a.state), V = !1, (e = n.onConnectionStateChange) == null || e.call(n, A.Connecting, "user:reconnect");
425
+ try {
426
+ if (await a.connect(K, $), i("Room reconnected"), E = !0, a.remoteParticipants.size === 0) {
427
+ if (i("Waiting for agent to join..."), !await new Promise((r) => {
428
+ const s = setTimeout(() => {
429
+ a == null || a.off(h.ParticipantConnected, d), r(!1);
430
+ }, 5e3), d = () => {
431
+ clearTimeout(s), a == null || a.off(h.ParticipantConnected, d), r(!0);
432
+ };
433
+ a == null || a.on(h.ParticipantConnected, d);
434
+ }))
435
+ throw i("Agent did not join within timeout"), await a.disconnect(), new Error("Agent did not rejoin the room");
436
+ i("Agent joined, reconnection successful");
437
+ }
438
+ } catch (o) {
439
+ throw i("Failed to reconnect:", o), (t = n.onConnectionStateChange) == null || t.call(n, A.Fail, "user:reconnect-failed"), o;
440
+ }
441
+ },
442
+ sendDataChannelMessage: re,
443
+ sendTextMessage: xe,
444
+ publishMicrophoneStream: _e,
445
+ unpublishMicrophoneStream: Q,
446
+ replaceMicrophoneTrack: De,
447
+ publishCameraStream: Ve,
448
+ unpublishCameraStream: W,
449
+ interrupt(e) {
450
+ e !== "text" && re(JSON.stringify({
451
+ topic: "did.interrupt"
452
+ /* Interrupt */
453
+ }));
454
+ },
455
+ registerRpcMethod(e, t) {
456
+ a == null || a.registerRpcMethod(e, t);
457
+ },
458
+ unregisterRpcMethod(e) {
459
+ a == null || a.unregisterRpcMethod(e);
460
+ },
461
+ sessionId: y,
462
+ streamId: y,
463
+ streamType: G,
464
+ interruptAvailable: Y,
465
+ isInterruptible: I
466
+ };
467
+ }
468
+ export {
469
+ tn as createLiveKitStreamingManager,
470
+ fe as handleInitError
471
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Best-effort user context (location + device) resolved entirely on the client
3
+ * and attached to the LiveKit participant as attributes on connect. The agent
4
+ * backend reads these to enrich the LLM context (see `get_user_context`).
5
+ *
6
+ * `location` is the IANA timezone (e.g. `America/New_York`) — a coarse but
7
+ * network-free location proxy. `device` is a short human-readable descriptor.
8
+ */
9
+ /**
10
+ * Non-empty `{ timezone, device }` attributes to attach to the participant.
11
+ * Keys with no resolvable value are omitted. The backend infers the user's
12
+ * country from the timezone (a timezone identifies a country reliably, but its
13
+ * reference city is not the user's actual city).
14
+ */
15
+ export declare function getUserContextAttributes(): Record<string, string>;
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@d-id/client-sdk",
3
3
  "private": false,
4
- "version": "1.2.7-staging.363",
4
+ "version": "1.2.8-staging.365",
5
5
  "type": "module",
6
6
  "description": "d-id client sdk",
7
7
  "repository": {