@introspection-sdk/introspection-browser 0.5.4 → 0.5.5

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 (48) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/README.md +45 -33
  3. package/dist/api/client.d.ts +31 -11
  4. package/dist/api/client.d.ts.map +1 -1
  5. package/dist/api/client.js +80 -20
  6. package/dist/api/client.js.map +1 -1
  7. package/dist/api/http.d.ts +23 -0
  8. package/dist/api/http.d.ts.map +1 -1
  9. package/dist/api/http.js +38 -0
  10. package/dist/api/http.js.map +1 -1
  11. package/dist/api/index.d.ts +11 -11
  12. package/dist/api/index.d.ts.map +1 -1
  13. package/dist/api/index.js +10 -10
  14. package/dist/api/index.js.map +1 -1
  15. package/dist/api/runner.d.ts +45 -0
  16. package/dist/api/runner.d.ts.map +1 -0
  17. package/dist/api/runner.js +87 -0
  18. package/dist/api/runner.js.map +1 -0
  19. package/dist/api/runtimes.d.ts +12 -0
  20. package/dist/api/runtimes.d.ts.map +1 -0
  21. package/dist/api/runtimes.js +14 -0
  22. package/dist/api/runtimes.js.map +1 -0
  23. package/dist/api/tasks.d.ts +8 -47
  24. package/dist/api/tasks.d.ts.map +1 -1
  25. package/dist/api/tasks.js +7 -130
  26. package/dist/api/tasks.js.map +1 -1
  27. package/package.json +3 -3
  28. package/src/api/client.ts +129 -22
  29. package/src/api/http.ts +56 -0
  30. package/src/api/index.ts +40 -12
  31. package/src/api/runner.ts +127 -0
  32. package/src/api/runtimes.ts +32 -0
  33. package/src/api/tasks.ts +18 -158
  34. package/dist/api/conversations.d.ts +0 -84
  35. package/dist/api/conversations.d.ts.map +0 -1
  36. package/dist/api/conversations.js +0 -172
  37. package/dist/api/conversations.js.map +0 -1
  38. package/dist/api/files.d.ts +0 -61
  39. package/dist/api/files.d.ts.map +0 -1
  40. package/dist/api/files.js +0 -141
  41. package/dist/api/files.js.map +0 -1
  42. package/dist/api/shares.d.ts +0 -29
  43. package/dist/api/shares.d.ts.map +0 -1
  44. package/dist/api/shares.js +0 -52
  45. package/dist/api/shares.js.map +0 -1
  46. package/src/api/conversations.ts +0 -214
  47. package/src/api/files.ts +0 -179
  48. package/src/api/shares.ts +0 -65
package/src/api/index.ts CHANGED
@@ -11,18 +11,18 @@
11
11
  * import { IntrospectionApiClient } from "@introspection-sdk/introspection-browser/api";
12
12
  *
13
13
  * const client = new IntrospectionApiClient({
14
- * dpUrl: "https://dp.us.introspection.dev",
14
+ * cpUrl: "https://api.introspection.dev",
15
15
  * // your backend mints the Introspection access token (the session's
16
16
  * // project is derived from its claims — no projectId option needed)
17
17
  * getToken: () => fetch("/api/introspection/token").then((r) => r.text()),
18
18
  * });
19
19
  *
20
- * await client.connect(); // → intro_dp_session cookie
21
- * const run = await client.tasks.start({
22
- * prompt: "Summarize my latest order",
23
- * agent_name: "support-agent",
20
+ * const runner = await client.runtimes("support-agent").run({
24
21
  * identity: { user_id: "u_42" },
25
22
  * });
23
+ * const run = await runner.tasks.start({
24
+ * prompt: "Summarize my latest order",
25
+ * });
26
26
  * for await (const ev of run.stream()) console.log(ev.event, ev.data);
27
27
  * ```
28
28
  */
@@ -31,6 +31,20 @@ export {
31
31
  IntrospectionApiClient,
32
32
  type IntrospectionApiClientOptions,
33
33
  } from "./client.js";
34
+ export {
35
+ BrowserRunner,
36
+ Runner,
37
+ type BrowserRunnerOwner,
38
+ type BrowserRunnerSource,
39
+ } from "./runner.js";
40
+ export {
41
+ BrowserRuntimesClient,
42
+ BrowserRuntimeHandle,
43
+ attachBrowserRuntimes,
44
+ isUuid,
45
+ type BrowserRuntimeHandleFactory,
46
+ type BrowserRuntimeRunRequestBody,
47
+ } from "./runtimes.js";
34
48
  export {
35
49
  TasksClient,
36
50
  TaskRunsClient,
@@ -39,16 +53,20 @@ export {
39
53
  type StartTaskParams,
40
54
  } from "./tasks.js";
41
55
  export {
42
- FilesClient,
56
+ ConversationItemsClient,
57
+ ConversationsClient,
43
58
  FileVersionsClient,
59
+ FilesClient,
60
+ SharesClient,
44
61
  type FileUploadBody,
45
- } from "./files.js";
62
+ } from "@introspection-sdk/http";
46
63
  export {
47
- ConversationsClient,
48
- ConversationItemsClient,
49
- } from "./conversations.js";
50
- export { SharesClient } from "./shares.js";
51
- export { BrowserHttpClient, type BrowserHttpConfig } from "./http.js";
64
+ BrowserBearerHttpClient,
65
+ BrowserHttpClient,
66
+ type BrowserApiHttpClient,
67
+ type BrowserBearerHttpConfig,
68
+ type BrowserHttpConfig,
69
+ } from "./http.js";
52
70
  export { parseSse } from "./sse.js";
53
71
  export {
54
72
  Paginator,
@@ -86,6 +104,15 @@ export type {
86
104
  ShareResourceType,
87
105
  ShareCreateParams,
88
106
  ShareListParams,
107
+ Recipe,
108
+ RunRequest,
109
+ RunnerContext,
110
+ RunnerDeployment,
111
+ RunnerSpec,
112
+ Runtime,
113
+ RuntimeCreate,
114
+ RuntimeListParams,
115
+ RuntimeUpdate,
89
116
  } from "@introspection-sdk/types";
90
117
  export {
91
118
  IntrospectionAPIError,
@@ -93,4 +120,5 @@ export {
93
120
  InsufficientScopeError,
94
121
  NotFoundError,
95
122
  NetworkError,
123
+ RunnerExpiredError,
96
124
  } from "@introspection-sdk/types";
@@ -0,0 +1,127 @@
1
+ import {
2
+ RunnerExpiredError,
3
+ type RunnerContext,
4
+ type RunnerDeployment,
5
+ type RunnerSpec,
6
+ type RunRequest,
7
+ type Uuid,
8
+ } from "@introspection-sdk/types";
9
+ import {
10
+ ConversationsClient,
11
+ FilesClient,
12
+ SharesClient,
13
+ TasksClient,
14
+ } from "@introspection-sdk/http";
15
+ import { BrowserBearerHttpClient } from "./http.js";
16
+
17
+ export type BrowserRunnerSource =
18
+ | { kind: "runtime"; id: Uuid; options?: RunRequest }
19
+ | { kind: "experiment"; id: Uuid; options?: RunRequest };
20
+
21
+ export interface BrowserRunnerOwner {
22
+ readonly additionalHeaders?: Record<string, string>;
23
+ readonly fetch?: typeof fetch;
24
+ requestFreshRunnerSpec(source: BrowserRunnerSource): Promise<RunnerSpec>;
25
+ }
26
+
27
+ /**
28
+ * Browser-side live handle to a Data Plane runner. Mirrors the Node Runner
29
+ * shape but uses browser-safe fetch transport and CP-minted bearer tokens.
30
+ */
31
+ export class BrowserRunner {
32
+ private spec: RunnerSpec;
33
+ private http: BrowserBearerHttpClient;
34
+ private closed = false;
35
+
36
+ readonly tasks: TasksClient;
37
+ readonly files: FilesClient;
38
+ readonly conversations: ConversationsClient;
39
+ readonly shares: SharesClient;
40
+
41
+ constructor(
42
+ private readonly owner: BrowserRunnerOwner,
43
+ private readonly source: BrowserRunnerSource,
44
+ spec: RunnerSpec,
45
+ ) {
46
+ this.spec = spec;
47
+ this.http = this.buildHttp(spec);
48
+ const guarded = this.guardedHttp();
49
+ this.tasks = new TasksClient(guarded);
50
+ this.files = new FilesClient(guarded);
51
+ this.conversations = new ConversationsClient(guarded);
52
+ this.shares = new SharesClient(guarded);
53
+ }
54
+
55
+ get dpEndpoint(): string {
56
+ return this.spec.deployment.endpoint;
57
+ }
58
+
59
+ get deployment(): Readonly<RunnerDeployment> {
60
+ return Object.freeze({ ...this.spec.deployment });
61
+ }
62
+
63
+ get expires_at(): string {
64
+ return this.spec.expires_at;
65
+ }
66
+
67
+ get session_id(): string {
68
+ return this.spec.session_id;
69
+ }
70
+
71
+ get context(): Readonly<RunnerContext> {
72
+ return Object.freeze({ ...this.spec.runtime_context });
73
+ }
74
+
75
+ get isClosed(): boolean {
76
+ return this.closed;
77
+ }
78
+
79
+ async refresh(): Promise<void> {
80
+ this.assertOpen();
81
+ const fresh = await this.owner.requestFreshRunnerSpec(this.source);
82
+ this.spec = fresh;
83
+ this.http = this.buildHttp(fresh);
84
+ }
85
+
86
+ async close(): Promise<void> {
87
+ this.closed = true;
88
+ }
89
+
90
+ private buildHttp(spec: RunnerSpec): BrowserBearerHttpClient {
91
+ return new BrowserBearerHttpClient({
92
+ apiUrl: spec.deployment.endpoint,
93
+ token: spec.session_token,
94
+ additionalHeaders: this.owner.additionalHeaders,
95
+ fetch: this.owner.fetch,
96
+ });
97
+ }
98
+
99
+ private guardedHttp(): BrowserBearerHttpClient {
100
+ const proxy: BrowserBearerHttpClient = Object.create(this.http);
101
+ proxy.request = async <T>(
102
+ opts: Parameters<BrowserBearerHttpClient["request"]>[0],
103
+ ): Promise<T> => {
104
+ this.assertOpen();
105
+ return this.http.request<T>(opts);
106
+ };
107
+ proxy.stream = async (
108
+ opts: Parameters<BrowserBearerHttpClient["stream"]>[0],
109
+ ): Promise<Response> => {
110
+ this.assertOpen();
111
+ return this.http.stream(opts);
112
+ };
113
+ return proxy;
114
+ }
115
+
116
+ private assertOpen(): void {
117
+ if (this.closed) {
118
+ throw new RunnerExpiredError({
119
+ message: "Runner has been closed",
120
+ status: 401,
121
+ code: "runner_expired",
122
+ });
123
+ }
124
+ }
125
+ }
126
+
127
+ export { BrowserRunner as Runner };
@@ -0,0 +1,32 @@
1
+ import {
2
+ RuntimeHandle,
3
+ RuntimesClient,
4
+ attachRuntimes,
5
+ isUuid,
6
+ type RuntimeHandleFactory,
7
+ type RuntimeRunRequestBody,
8
+ } from "@introspection-sdk/http";
9
+ import type { BrowserApiHttpClient } from "./http.js";
10
+ import { BrowserRunner, type BrowserRunnerOwner } from "./runner.js";
11
+
12
+ export { isUuid };
13
+ export type { RuntimeRunRequestBody as BrowserRuntimeRunRequestBody };
14
+
15
+ export class BrowserRuntimesClient extends RuntimesClient<BrowserRunner> {
16
+ constructor(http: BrowserApiHttpClient, owner: BrowserRunnerOwner) {
17
+ super(http, (source, spec) => new BrowserRunner(owner, source, spec));
18
+ }
19
+ }
20
+
21
+ export { RuntimeHandle as BrowserRuntimeHandle };
22
+
23
+ export type BrowserRuntimeHandleFactory = RuntimeHandleFactory<BrowserRunner>;
24
+
25
+ export function attachBrowserRuntimes(
26
+ http: BrowserApiHttpClient,
27
+ owner: BrowserRunnerOwner,
28
+ ): BrowserRuntimesClient & BrowserRuntimeHandleFactory {
29
+ const api = new BrowserRuntimesClient(http, owner);
30
+ return attachRuntimes(api) as BrowserRuntimesClient &
31
+ BrowserRuntimeHandleFactory;
32
+ }
package/src/api/tasks.ts CHANGED
@@ -1,19 +1,10 @@
1
- import type {
2
- Paginated,
3
- RunIdentityInput,
4
- SseEvent,
5
- Task,
6
- TaskCancelResponse,
7
- TaskCreateResponse,
8
- TaskListParams,
9
- TaskRun,
10
- TaskRunCreateParams,
11
- TaskRunResponse,
12
- TaskUpdateParams,
13
- } from "@introspection-sdk/types";
14
- import { Paginator, cursorPaginate } from "@introspection-sdk/http";
15
- import { BrowserHttpClient } from "./http.js";
16
- import { parseSse } from "./sse.js";
1
+ import type { RunIdentityInput } from "@introspection-sdk/types";
2
+ import {
3
+ RunHandle,
4
+ TaskRunsClient,
5
+ TasksClient as SharedTasksClient,
6
+ type ResourceHttpClient,
7
+ } from "@introspection-sdk/http";
17
8
 
18
9
  /**
19
10
  * Body for creating a task directly against the DP from the browser.
@@ -65,149 +56,18 @@ function toTaskBody(params: CreateTaskParams): Record<string, unknown> {
65
56
  return body;
66
57
  }
67
58
 
68
- /** Live handle on a task's run: stream its events, collect text, cancel. */
69
- export class RunHandle {
70
- constructor(
71
- public readonly task: Task | null,
72
- public readonly run: TaskRun,
73
- private readonly runs: TaskRunsClient,
74
- ) {}
75
-
76
- stream(): AsyncIterable<SseEvent> {
77
- return this.runs.stream(this.run.task_id, this.run.id);
78
- }
79
-
80
- cancel(): Promise<TaskCancelResponse> {
81
- return this.runs.cancel(this.run.task_id, this.run.id);
82
- }
83
-
84
- /** Convenience: concatenate `data` from `text`/`message` SSE frames. */
85
- async text(): Promise<string> {
86
- let out = "";
87
- for await (const ev of this.stream()) {
88
- if (ev.event === "text" || ev.event === "message") out += ev.data;
89
- }
90
- return out;
91
- }
92
- }
93
-
94
- export class TaskRunsClient {
95
- constructor(private readonly http: BrowserHttpClient) {}
96
-
97
- async create(taskId: string, body: TaskRunCreateParams): Promise<RunHandle> {
98
- const res = await this.http.request<TaskRunResponse>({
99
- method: "POST",
100
- path: `/v1/tasks/${encodeURIComponent(taskId)}/runs`,
101
- body,
102
- });
103
- return new RunHandle(null, res.run, this);
104
- }
105
-
106
- get(taskId: string, runId: string): Promise<TaskRun> {
107
- return this.http.request<TaskRun>({
108
- method: "GET",
109
- path: `/v1/tasks/${encodeURIComponent(taskId)}/runs/${encodeURIComponent(runId)}`,
110
- });
111
- }
112
-
113
- cancel(taskId: string, runId: string): Promise<TaskCancelResponse> {
114
- return this.http.request<TaskCancelResponse>({
115
- method: "POST",
116
- path: `/v1/tasks/${encodeURIComponent(taskId)}/runs/${encodeURIComponent(runId)}/cancel`,
117
- });
118
- }
119
-
120
- async *stream(taskId: string, runId: string): AsyncIterable<SseEvent> {
121
- const res = await this.http.stream({
122
- path: `/v1/tasks/${encodeURIComponent(taskId)}/runs/${encodeURIComponent(runId)}/stream`,
123
- });
124
- yield* parseSse(res);
125
- }
126
- }
127
-
128
59
  /**
129
- * Cookie-authenticated `/v1/tasks` client. Mirrors the Node SDK's
130
- * `TasksApi` shape but is bound to a DP session cookie rather than a
131
- * bearer token, and lets the caller select the agent on create.
60
+ * Cookie-authenticated `/v1/tasks` client. The implementation is shared with
61
+ * Node's runner-bound task client; this browser subclass only adds the
62
+ * `identity -> metadata.identity` body mapping used by cookie-session calls.
132
63
  */
133
- export class TasksClient {
134
- readonly runs: TaskRunsClient;
135
-
136
- constructor(private readonly http: BrowserHttpClient) {
137
- this.runs = new TaskRunsClient(http);
138
- }
139
-
140
- /**
141
- * Tasks matching `params`. `await` it for the first page (preserving
142
- * the wire envelope's counts + `next` cursor), or `for await` it to
143
- * stream every task across pages (fetched lazily — `limit` sets the
144
- * page size, `next` the starting cursor; stop early to stop fetching).
145
- *
146
- * Mirrors the Node SDK's `TasksApi.list`, which is the source of truth
147
- * for the `/v1/tasks` shape.
148
- */
149
- list(params?: TaskListParams): Paginator<Task> {
150
- return cursorPaginate(
151
- (next) =>
152
- this.http.request<Paginated<Task>>({
153
- method: "GET",
154
- path: "/v1/tasks",
155
- query: { ...params, next } as Record<string, unknown>,
156
- }),
157
- params?.next,
158
- );
159
- }
160
-
161
- create(body: CreateTaskParams): Promise<TaskCreateResponse> {
162
- return this.http.request<TaskCreateResponse>({
163
- method: "POST",
164
- path: "/v1/tasks",
165
- body: toTaskBody(body),
166
- });
167
- }
168
-
169
- get(taskId: string): Promise<Task> {
170
- return this.http.request<Task>({
171
- method: "GET",
172
- path: `/v1/tasks/${encodeURIComponent(taskId)}`,
173
- });
174
- }
175
-
176
- update(taskId: string, body: TaskUpdateParams): Promise<Task> {
177
- return this.http.request<Task>({
178
- method: "PATCH",
179
- path: `/v1/tasks/${encodeURIComponent(taskId)}`,
180
- body,
181
- });
182
- }
183
-
184
- delete(taskId: string): Promise<void> {
185
- return this.http.request<void>({
186
- method: "DELETE",
187
- path: `/v1/tasks/${encodeURIComponent(taskId)}`,
188
- expect: "empty",
189
- });
190
- }
191
-
192
- archive(taskId: string): Promise<void> {
193
- return this.http.request<void>({
194
- method: "POST",
195
- path: `/v1/tasks/${encodeURIComponent(taskId)}/archive`,
196
- expect: "empty",
197
- });
198
- }
199
-
200
- unarchive(taskId: string): Promise<void> {
201
- return this.http.request<void>({
202
- method: "POST",
203
- path: `/v1/tasks/${encodeURIComponent(taskId)}/unarchive`,
204
- expect: "empty",
205
- });
206
- }
207
-
208
- /** Sugar: create a task + return a handle on its initial run. */
209
- async start(params: StartTaskParams): Promise<RunHandle> {
210
- const res = await this.create(params);
211
- return new RunHandle(res.task, res.run, this.runs);
64
+ export class TasksClient extends SharedTasksClient<
65
+ CreateTaskParams,
66
+ StartTaskParams
67
+ > {
68
+ constructor(http: ResourceHttpClient) {
69
+ super(http, toTaskBody);
212
70
  }
213
71
  }
72
+
73
+ export { RunHandle, TaskRunsClient };
@@ -1,84 +0,0 @@
1
- /**
2
- * Cookie-authenticated, read-only Conversations client for the browser
3
- * (`/v1/conversations`).
4
- *
5
- * Mirrors the Node SDK's runner-bound `ConversationsApi`, but rides the
6
- * DP `intro_dp_session` cookie via {@link BrowserHttpClient} instead of a
7
- * bearer token — so a single-page app reads conversation history with the
8
- * same identity session it uses for tasks and files. Conversations are a
9
- * projection over the immutable telemetry store: list summaries, walk a
10
- * conversation's items, or `retrieve()` the resolved state of one turn.
11
- */
12
- import type { ConversationItem, ConversationItemInclude, ConversationItemList, ConversationItemListParams, ConversationListParams, ConversationResponse, ConversationSummary } from "@introspection-sdk/types";
13
- import { Paginator } from "@introspection-sdk/http";
14
- import { BrowserHttpClient } from "./http.js";
15
- /**
16
- * Items of a conversation (`/v1/conversations/{id}/items`). Read-only.
17
- *
18
- * Paging is OpenAI-style underneath: the envelope has NO `next` token —
19
- * `list()` drives `after` = the previous page's `last_id` while
20
- * `has_more` is true.
21
- */
22
- export declare class ConversationItemsClient {
23
- private readonly http;
24
- constructor(http: BrowserHttpClient);
25
- /**
26
- * List items of a conversation. `await` the result for the first page
27
- * (an OpenAI-style {@link ConversationItemList} envelope), or
28
- * `for await` it to stream every item across pages (fetched lazily —
29
- * `limit` sets the page size, `after` the starting cursor; stop early to
30
- * stop fetching). Pass `order: "asc"` to walk the transcript from the
31
- * start.
32
- *
33
- * Items carry the turn-local delta in `input_messages` — only the
34
- * messages new to that turn. Use `get()` for the full input history.
35
- */
36
- list(conversationId: string, params?: ConversationItemListParams): Paginator<ConversationItem, ConversationItemList>;
37
- /**
38
- * Fetch a single conversation item. Unlike the list route, the
39
- * detail's `input_messages` is the FULL input history for that span.
40
- */
41
- get(conversationId: string, itemId: string, params?: {
42
- include?: ConversationItemInclude[];
43
- }): Promise<ConversationItem>;
44
- }
45
- /**
46
- * Read-only Conversations client (`/v1/conversations`).
47
- *
48
- * Both `list()` and `items.list()` are auto-paging, but they drive
49
- * different wire protocols underneath: `list()` walks the standard
50
- * Introspection cursor envelope's opaque `next` token, while
51
- * `items.list()` walks an OpenAI-style envelope via `after` = the
52
- * previous page's `last_id` while `has_more` is true.
53
- */
54
- export declare class ConversationsClient {
55
- private readonly http;
56
- /** Items of a conversation — `conversations.items.list(...)` etc. */
57
- readonly items: ConversationItemsClient;
58
- constructor(http: BrowserHttpClient);
59
- /**
60
- * List conversation summaries matching `params`. `await` the result for
61
- * the first page, or `for await` it to stream every summary across
62
- * pages (fetched lazily — `limit` sets the page size, `next` the
63
- * starting cursor; stop early to stop fetching).
64
- */
65
- list(params?: ConversationListParams): Paginator<ConversationSummary>;
66
- /**
67
- * Responses-API-style retrieve: load the state of a conversation as of
68
- * one item — the full input history, output, system instructions, and
69
- * tool definitions of that turn.
70
- *
71
- * When `itemId` is omitted, the latest LLM turn is used: the first
72
- * item (in descending order) whose `node_type` is `"assistant"` or
73
- * whose `operation_name` is `"chat"`, falling back to the first item
74
- * with a non-null `output_message`. Returns `null` when the
75
- * conversation has no items.
76
- *
77
- * For the full per-turn transcript instead, iterate
78
- * `items.list(conversationId, { order: "asc" })`.
79
- */
80
- retrieve(conversationId: string, itemId?: string): Promise<ConversationResponse | null>;
81
- /** Scan items in descending order for the most recent LLM turn. */
82
- private findLatestTurnId;
83
- }
84
- //# sourceMappingURL=conversations.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"conversations.d.ts","sourceRoot":"","sources":["../../src/api/conversations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,EACpB,0BAA0B,EAC1B,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EAIpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,SAAS,EAAkB,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAS9C;;;;;;GAMG;AACH,qBAAa,uBAAuB;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,iBAAiB;IAEpD;;;;;;;;;;OAUG;IACH,IAAI,CACF,cAAc,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,0BAA0B,GAClC,SAAS,CAAC,gBAAgB,EAAE,oBAAoB,CAAC;IAiBpD;;;OAGG;IACH,GAAG,CACD,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,uBAAuB,EAAE,CAAA;KAAE,GAC/C,OAAO,CAAC,gBAAgB,CAAC;CAO7B;AAED;;;;;;;;GAQG;AACH,qBAAa,mBAAmB;IAIlB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,uBAAuB,CAAC;gBAEX,IAAI,EAAE,iBAAiB;IAIpD;;;;;OAKG;IACH,IAAI,CAAC,MAAM,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC,mBAAmB,CAAC;IAYrE;;;;;;;;;;;;;OAaG;IACG,QAAQ,CACZ,cAAc,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IA6BvC,mEAAmE;YACrD,gBAAgB;CAc/B"}