maestro-agent-sdk 0.1.26 → 0.1.28

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 (65) hide show
  1. package/README.md +20 -0
  2. package/dist/core/agent.d.ts +28 -0
  3. package/dist/core/agent.d.ts.map +1 -1
  4. package/dist/core/agent.js +2 -0
  5. package/dist/core/agent.js.map +1 -1
  6. package/dist/core/is-abort-error.d.ts +18 -0
  7. package/dist/core/is-abort-error.d.ts.map +1 -1
  8. package/dist/core/is-abort-error.js +34 -0
  9. package/dist/core/is-abort-error.js.map +1 -1
  10. package/dist/core/loop.d.ts.map +1 -1
  11. package/dist/core/loop.js +69 -14
  12. package/dist/core/loop.js.map +1 -1
  13. package/dist/core/tool-result-truncation.d.ts +34 -0
  14. package/dist/core/tool-result-truncation.d.ts.map +1 -0
  15. package/dist/core/tool-result-truncation.js +162 -0
  16. package/dist/core/tool-result-truncation.js.map +1 -0
  17. package/dist/index.d.ts +7 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +7 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/memory/active-task-template.d.ts +7 -4
  22. package/dist/memory/active-task-template.d.ts.map +1 -1
  23. package/dist/memory/active-task-template.js +19 -4
  24. package/dist/memory/active-task-template.js.map +1 -1
  25. package/dist/memory/aux-model-map.d.ts +49 -0
  26. package/dist/memory/aux-model-map.d.ts.map +1 -0
  27. package/dist/memory/aux-model-map.js +103 -0
  28. package/dist/memory/aux-model-map.js.map +1 -0
  29. package/dist/memory/compressor.d.ts +34 -59
  30. package/dist/memory/compressor.d.ts.map +1 -1
  31. package/dist/memory/compressor.js +222 -89
  32. package/dist/memory/compressor.js.map +1 -1
  33. package/dist/platform/config.d.ts +5 -0
  34. package/dist/platform/config.d.ts.map +1 -1
  35. package/dist/platform/config.js +9 -0
  36. package/dist/platform/config.js.map +1 -1
  37. package/dist/platform/version.d.ts +1 -1
  38. package/dist/platform/version.js +1 -1
  39. package/dist/provider.d.ts +18 -6
  40. package/dist/provider.d.ts.map +1 -1
  41. package/dist/provider.js +71 -8
  42. package/dist/provider.js.map +1 -1
  43. package/dist/providers/codex-auth.d.ts +149 -0
  44. package/dist/providers/codex-auth.d.ts.map +1 -0
  45. package/dist/providers/codex-auth.js +332 -0
  46. package/dist/providers/codex-auth.js.map +1 -0
  47. package/dist/providers/codex-stream.d.ts +42 -0
  48. package/dist/providers/codex-stream.d.ts.map +1 -0
  49. package/dist/providers/codex-stream.js +330 -0
  50. package/dist/providers/codex-stream.js.map +1 -0
  51. package/dist/providers/codex-translators.d.ts +105 -0
  52. package/dist/providers/codex-translators.d.ts.map +1 -0
  53. package/dist/providers/codex-translators.js +244 -0
  54. package/dist/providers/codex-translators.js.map +1 -0
  55. package/dist/providers/codex.d.ts +145 -0
  56. package/dist/providers/codex.d.ts.map +1 -0
  57. package/dist/providers/codex.js +417 -0
  58. package/dist/providers/codex.js.map +1 -0
  59. package/dist/registry.d.ts.map +1 -1
  60. package/dist/registry.js +25 -1
  61. package/dist/registry.js.map +1 -1
  62. package/dist/types.d.ts +24 -0
  63. package/dist/types.d.ts.map +1 -1
  64. package/dist/types.js.map +1 -1
  65. package/package.json +17 -1
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Maestro ↔ Codex Responses API format translators.
3
+ *
4
+ * The Responses API is OpenAI's newer thread-style endpoint. It speaks a
5
+ * different shape than Chat Completions:
6
+ *
7
+ * - Messages aren't a `messages` array — they're "input items" with
8
+ * polymorphic types (`message`, `function_call`, `function_call_output`,
9
+ * `reasoning`).
10
+ * - Tools live as top-level items, not inside an assistant message.
11
+ * - Text parts split by direction: user → `input_text`, assistant →
12
+ * `output_text`. Mixing them yields 400.
13
+ * - There is no `system` role; the instructions ride in a top-level
14
+ * `instructions` field on the request body.
15
+ *
16
+ * This module owns those translations and nothing else — the provider class
17
+ * stays focused on HTTP / streaming concerns.
18
+ *
19
+ * Hermes reference: `agent/codex_responses_adapter.py::_chat_messages_to_responses_input`
20
+ * and `_responses_tools`. We diverge from hermes in two places:
21
+ *
22
+ * 1. We start from Maestro's Anthropic-shaped `ProviderContentBlock[]`, not
23
+ * from OpenAI Chat Completions messages. Hermes does this conversion in
24
+ * two hops (Anthropic → ChatCompletions → Responses); we do it in one to
25
+ * keep the data path shorter and the type signatures honest.
26
+ *
27
+ * 2. We don't replay `codex_reasoning_items` / `codex_message_items` from
28
+ * prior turns yet. Reasoning replay (with `encrypted_content`) is what
29
+ * lets the Responses API maintain a coherent reasoning chain across
30
+ * turns — but maestro's loop currently drops the encrypted blobs after
31
+ * each turn, so there's nothing to replay. A future PR can extend
32
+ * `ProviderContentBlock` with a `codex_encrypted_reasoning` variant and
33
+ * wire the replay here.
34
+ */
35
+ export function translateToolsToResponses(tools) {
36
+ if (!tools || tools.length === 0)
37
+ return undefined;
38
+ const out = [];
39
+ for (const t of tools) {
40
+ if (!t?.name || t.name.length === 0)
41
+ continue;
42
+ out.push({
43
+ type: "function",
44
+ name: t.name,
45
+ description: t.description ?? "",
46
+ strict: false,
47
+ parameters: t.input_schema ?? {
48
+ type: "object",
49
+ properties: {},
50
+ },
51
+ });
52
+ }
53
+ return out.length > 0 ? out : undefined;
54
+ }
55
+ /**
56
+ * Convert one Maestro message into one-or-more Responses input items.
57
+ *
58
+ * Why one message can produce multiple items:
59
+ * - An assistant message with `text` + `tool_use` emits a `message` item AND
60
+ * one `function_call` per tool_use, in that exact order.
61
+ * - A user message with `tool_result` blocks emits a separate
62
+ * `function_call_output` per result. Text/image blocks accompanying the
63
+ * tool_results are flushed as their own `message` item before each result
64
+ * so call-result ordering with surrounding text is preserved (matches
65
+ * DeepSeek/Anthropic intent).
66
+ */
67
+ export function translateMessageToResponsesItems(msg) {
68
+ // String-content fast path covers DeepSeek-style plain text replays.
69
+ if (typeof msg.content === "string") {
70
+ return [
71
+ {
72
+ type: "message",
73
+ role: msg.role,
74
+ content: msg.content,
75
+ },
76
+ ];
77
+ }
78
+ if (msg.role === "user") {
79
+ return translateUserBlocks(msg.content);
80
+ }
81
+ return translateAssistantBlocks(msg.content);
82
+ }
83
+ function translateUserBlocks(blocks) {
84
+ const out = [];
85
+ let buffered = [];
86
+ const flush = () => {
87
+ if (buffered.length === 0)
88
+ return;
89
+ out.push({
90
+ type: "message",
91
+ role: "user",
92
+ content: condenseUserParts(buffered),
93
+ });
94
+ buffered = [];
95
+ };
96
+ for (const block of blocks) {
97
+ if (block.type === "text") {
98
+ if (block.text.length > 0)
99
+ buffered.push({ type: "input_text", text: block.text });
100
+ }
101
+ else if (block.type === "image") {
102
+ const url = imageBlockToDataUrl(block.source);
103
+ if (url)
104
+ buffered.push({ type: "input_image", image_url: url });
105
+ }
106
+ else if (block.type === "document") {
107
+ // Responses API doesn't accept PDF blocks directly at user message
108
+ // level — placeholder so the model knows the attachment existed.
109
+ // Caller should pre-extract text (e.g. via Read tool) for real content.
110
+ buffered.push({
111
+ type: "input_text",
112
+ text: `[document ${block.source.media_type}; PDF not visible to GPT-5 directly — extract text first.]`,
113
+ });
114
+ }
115
+ else if (block.type === "tool_result") {
116
+ // tool_result MUST be its own item; flush any accumulated user content
117
+ // first so ordering with surrounding text/image is preserved.
118
+ flush();
119
+ out.push({
120
+ type: "function_call_output",
121
+ call_id: block.tool_use_id,
122
+ output: toolResultToResponsesOutput(block.content),
123
+ });
124
+ }
125
+ // Other block types (tool_use, thinking) don't legally appear on user
126
+ // messages — silently skip if encountered.
127
+ }
128
+ flush();
129
+ return out;
130
+ }
131
+ function translateAssistantBlocks(blocks) {
132
+ const out = [];
133
+ const textParts = [];
134
+ // Collect text first so the assistant message lands once, before any
135
+ // function_calls. The Responses API doesn't require this order strictly
136
+ // (it tolerates [function_call, message] too) but the matching chat-side
137
+ // semantics are "the assistant said X, then called tool Y" — we keep that
138
+ // narrative order in the replay.
139
+ for (const block of blocks) {
140
+ if (block.type === "text" && block.text.length > 0) {
141
+ textParts.push({ type: "output_text", text: block.text });
142
+ }
143
+ // We could surface `thinking` blocks here as `reasoning` items, but doing
144
+ // so without the `encrypted_content` blob the model originally produced
145
+ // would just be plain-text reasoning the API treats as ordinary assistant
146
+ // output — that hurts more than it helps (reveals chain-of-thought to
147
+ // anything that later reads the rollout). Drop until we plumb encrypted
148
+ // replay end-to-end.
149
+ }
150
+ if (textParts.length > 0) {
151
+ out.push({ type: "message", role: "assistant", content: textParts });
152
+ }
153
+ for (const block of blocks) {
154
+ if (block.type === "tool_use") {
155
+ out.push({
156
+ type: "function_call",
157
+ call_id: block.id,
158
+ name: block.name,
159
+ arguments: JSON.stringify(block.input ?? {}),
160
+ });
161
+ }
162
+ }
163
+ return out;
164
+ }
165
+ /**
166
+ * If a user message ends up as a single text part, collapse to a plain string
167
+ * — keeps the wire shape predictable and avoids tripping any validator that
168
+ * expects a string when no image is attached. Mixed / image-bearing messages
169
+ * keep the array form. Mirrors DeepSeek's `condenseUserParts`.
170
+ */
171
+ function condenseUserParts(parts) {
172
+ if (parts.length === 1 && parts[0].type === "input_text")
173
+ return parts[0].text;
174
+ return parts;
175
+ }
176
+ /**
177
+ * Build a `data:<mime>;base64,<data>` URL from a Maestro image source. The
178
+ * Responses API accepts either a hosted URL or a data URL — we always emit
179
+ * the latter so the host doesn't need to publish a temporary URL.
180
+ *
181
+ * Returns `undefined` for malformed sources rather than throwing — the
182
+ * containing message still flows, just without the image part.
183
+ */
184
+ function imageBlockToDataUrl(source) {
185
+ if (source.type === "url" && source.url)
186
+ return source.url;
187
+ if (source.type === "base64" && source.data) {
188
+ const mime = source.media_type ?? "image/png";
189
+ return `data:${mime};base64,${source.data}`;
190
+ }
191
+ return undefined;
192
+ }
193
+ /**
194
+ * Convert a `tool_result.content` value into the shape the Responses API
195
+ * accepts inside `function_call_output.output`.
196
+ *
197
+ * - String → string (fast path; the majority of tools return plain text).
198
+ * - Block array of only text → joined string (smaller wire payload).
199
+ * - Mixed array (text + image) → structured array; image blocks become
200
+ * `input_image` parts. Document blocks become a text placeholder for the
201
+ * same reason as user-message documents.
202
+ */
203
+ function toolResultToResponsesOutput(content) {
204
+ if (typeof content === "string")
205
+ return content;
206
+ const parts = [];
207
+ for (const b of content) {
208
+ if (b.type === "text") {
209
+ parts.push({ type: "input_text", text: b.text });
210
+ }
211
+ else if (b.type === "image") {
212
+ const url = imageBlockToDataUrl(b.source);
213
+ if (url)
214
+ parts.push({ type: "input_image", image_url: url });
215
+ }
216
+ else if (b.type === "document") {
217
+ const bytes = b.source.data ? Math.floor((b.source.data.length * 3) / 4) : 0;
218
+ parts.push({
219
+ type: "input_text",
220
+ text: `[document ${b.source.media_type} ${bytes} bytes — extract text first.]`,
221
+ });
222
+ }
223
+ }
224
+ // All-text → collapse to a single string for compactness.
225
+ if (parts.every((p) => p.type === "input_text")) {
226
+ return parts.map((p) => p.text).join("\n");
227
+ }
228
+ return parts;
229
+ }
230
+ /**
231
+ * Top-level: translate the full Maestro message history into a flat array of
232
+ * Responses input items. The `system` string is consumed by the provider into
233
+ * the request's `instructions` field — it does NOT appear here.
234
+ */
235
+ export function translateMessagesToResponses(messages) {
236
+ const out = [];
237
+ for (const msg of messages) {
238
+ for (const item of translateMessageToResponsesItems(msg)) {
239
+ out.push(item);
240
+ }
241
+ }
242
+ return out;
243
+ }
244
+ //# sourceMappingURL=codex-translators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-translators.js","sourceRoot":"","sources":["../../src/providers/codex-translators.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * CodexResponsesProvider — call OpenAI's Responses API through the ChatGPT
3
+ * Codex backend using a `codex login` OAuth token.
4
+ *
5
+ * High-level shape:
6
+ *
7
+ * ┌────────────────────────┐ ┌──────────────────────────────────────┐
8
+ * │ AIAgent loop │ │ CodexResponsesProvider │
9
+ * │ ProviderMessage[] ─┼───▶│ - resolveAccessToken (refresh-aware)│
10
+ * │ │ │ - translateMessagesToResponses │
11
+ * │ │ │ - translateToolsToResponses │
12
+ * │ │ │ - POST /responses (stream:true) │
13
+ * │ ProviderStreamChunk ◀┼────│ - parseCodexStream │
14
+ * └────────────────────────┘ └──────────────────────────────────────┘
15
+ *
16
+ * Pinned constraints (verified empirically against
17
+ * `https://chatgpt.com/backend-api/codex/responses` on 2026-05-23):
18
+ *
19
+ * - **Stream is required**: non-streaming requests return
20
+ * `400 {"detail":"Stream must be set to true"}`.
21
+ * - **Model whitelist**: ChatGPT-account requests are limited to a small
22
+ * set of codex-issued model slugs (`gpt-5.5`, `gpt-5.4`, `gpt-5.4-mini`,
23
+ * `gpt-5.3-codex`, `gpt-5.2`, ...). Passing `gpt-5` returns 400 with
24
+ * `not supported when using Codex with a ChatGPT account`.
25
+ * - **Cloudflare headers required**: `originator: codex_cli_rs` plus a
26
+ * codex-shaped `User-Agent` are mandatory on non-residential IPs.
27
+ * - **`store: false`**: required when the rollout lives on the client side.
28
+ * Without it, the server expects subsequent requests to look items up
29
+ * by `id` and 404s when they can't.
30
+ *
31
+ * What this provider does NOT cover (deliberate scope cuts):
32
+ *
33
+ * - Reasoning chain replay across turns (would need `encrypted_content`
34
+ * plumbed into the message history). Reasoning summaries flow through
35
+ * as `thinking` blocks for the current turn only.
36
+ * - Built-in hosted tools (`web_search`, `file_search`). Only
37
+ * user-supplied function tools are wired.
38
+ * - Token-bucket rate-limit handling. The backend rate-limits aggressively
39
+ * for free accounts; surfacing a structured retry hint can be a follow-up.
40
+ *
41
+ * Hermes reference: `agent/transports/codex.py` + `_run_codex_stream`. We
42
+ * implement the same wire contract using only `fetch` and the SSE parser in
43
+ * `codex-stream.ts`, with no httpx / OpenAI SDK dependency.
44
+ */
45
+ import { type CodexAuthError } from "../providers/codex-auth.js";
46
+ import type { Provider, ProviderCompleteOptions, ProviderResponse, ProviderStreamChunk } from "../providers/base.js";
47
+ import type { EffortLevel } from "../types.js";
48
+ /**
49
+ * Map maestro's `EffortLevel` to the Responses API `reasoning.effort` string.
50
+ *
51
+ * Codex backend accepts `low | medium | high | xhigh`. The 5-tier maestro
52
+ * scale collapses as follows:
53
+ * - `low` / `medium` / `high` → direct passthrough.
54
+ * - `xhigh` → passthrough (Codex actually supports this tier on gpt-5.x).
55
+ * - `max` → `xhigh`. Codex has no `max`; we pick the deepest tier the
56
+ * backend exposes rather than silently dropping the user's intent.
57
+ */
58
+ export declare function effortForCodex(e: EffortLevel | undefined): string | undefined;
59
+ export interface CodexProviderOptions {
60
+ /** Override the Codex backend URL. Defaults to the ChatGPT-hosted
61
+ * endpoint. The `/responses` suffix is appended automatically. */
62
+ baseUrl?: string;
63
+ /** Override the timeout for the OAuth refresh round-trip. The streaming
64
+ * request itself uses `fetchTimeoutMs` (see below) — the agent loop also
65
+ * owns abort via signal. */
66
+ refreshTimeoutMs?: number;
67
+ /**
68
+ * Skew window (seconds) for the refresh decision. When the cached access
69
+ * token is within this many seconds of `exp`, the next provider call
70
+ * refreshes before making the API request. Defaults to 5 minutes — large
71
+ * enough to cover one long streaming turn without rolling over mid-stream.
72
+ */
73
+ refreshSkewSeconds?: number;
74
+ /**
75
+ * Wall-clock ceiling on a single `/responses` POST before we abort and
76
+ * surface a TimeoutError. Default 600_000 ms (10 minutes) — Bun's bundled
77
+ * undici otherwise enforces a 5-minute `headersTimeout` that fires on
78
+ * gpt-5.5 with ~1MB+ request bodies (v0.1.28 production repro). Raising
79
+ * the wall to 10 min gives the model breathing room while keeping a
80
+ * bounded worst case if the server hangs entirely. Combined with the
81
+ * caller's `abortSignal` via `AbortSignal.any`, so a user-initiated abort
82
+ * still wins immediately.
83
+ */
84
+ fetchTimeoutMs?: number;
85
+ }
86
+ /**
87
+ * Provider implementation. Construct once per process; safe to share across
88
+ * concurrent agent turns (token refresh is best-effort idempotent under the
89
+ * skew check + on-disk persistence).
90
+ */
91
+ export declare class CodexResponsesProvider implements Provider {
92
+ private readonly baseUrl;
93
+ private readonly refreshTimeoutMs;
94
+ private readonly refreshSkewSeconds;
95
+ private readonly fetchTimeoutMs;
96
+ constructor(opts?: CodexProviderOptions);
97
+ /**
98
+ * Build the AbortSignal we pass to `fetch`. Combines an explicit
99
+ * wall-clock timeout (`this.fetchTimeoutMs`) with the caller's optional
100
+ * abort signal so either path can short-circuit the request:
101
+ * - User abort fires → request cancels immediately.
102
+ * - Timeout fires → DOMException(name="TimeoutError") surfaces, which
103
+ * the v0.1.28 `isTimeoutError` helper catches in `provider.ts`.
104
+ *
105
+ * Why explicit timeout: Bun's undici default `headersTimeout` is 300_000
106
+ * ms (5 min) and fires regardless of user signal. Long requests on the
107
+ * heavy gpt-5.* tiers with large bodies blew through that wall in
108
+ * production. We raise the ceiling to 10 minutes (configurable) and pin
109
+ * the same value across the initial POST and the 401-refresh retry below.
110
+ */
111
+ private buildFetchSignal;
112
+ /**
113
+ * Factory parity with `DeepseekProvider.fromEnv()` — for Codex the "env"
114
+ * inputs are really the on-disk `~/.codex/auth.json` (no API key env var
115
+ * makes sense for OAuth). The factory still throws early if the auth file
116
+ * is missing or stale, so a host can fail fast at startup instead of on
117
+ * the first user message.
118
+ */
119
+ static fromEnv(opts?: CodexProviderOptions): CodexResponsesProvider;
120
+ /**
121
+ * Streaming entry point. The Codex backend rejects non-streaming requests
122
+ * outright, so this is the load-bearing method — `complete()` is just a
123
+ * convenience wrapper around it.
124
+ */
125
+ stream(opts: ProviderCompleteOptions): AsyncGenerator<ProviderStreamChunk>;
126
+ /**
127
+ * Non-streaming entry point. The Codex backend doesn't support
128
+ * `stream: false`, so we drain `stream()` into a single `ProviderResponse`.
129
+ * Callers that want progressive UI updates should use `stream()` directly.
130
+ *
131
+ * The reconstruction follows DeepseekProvider's convention:
132
+ * - text deltas collapse into one `text` content block per stream;
133
+ * - tool_use_start + tool_use_input_delta + tool_use_complete bundle
134
+ * into one `tool_use` block with parsed JSON args;
135
+ * - thinking_complete blocks are forwarded verbatim.
136
+ *
137
+ * Block order in the returned `content`: thinking → text → tool_use,
138
+ * matching the assistant-history convention the loop expects on replay.
139
+ */
140
+ complete(opts: ProviderCompleteOptions): Promise<ProviderResponse>;
141
+ }
142
+ export { CodexAuthError } from "../providers/codex-auth.js";
143
+ export type { CodexProviderOptions as _CodexProviderOptions };
144
+ export type _CodexAuthError = CodexAuthError;
145
+ //# sourceMappingURL=codex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/providers/codex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAGH,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EACV,QAAQ,EACR,uBAAuB,EAEvB,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,kBAAkB,CAAC;AAO1B,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,SAAS,CAAC;AAOvD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAe7E;AAED,MAAM,WAAW,oBAAoB;IACnC;uEACmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;iCAE6B;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,qBAAa,sBAAuB,YAAW,QAAQ;IACrD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IACxD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,IAAI,GAAE,oBAAyB;IAO3C;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,CAAC,IAAI,GAAE,oBAAyB,GAAG,sBAAsB;IAIvE;;;;OAIG;IACI,MAAM,CAAC,IAAI,EAAE,uBAAuB,GAAG,cAAc,CAAC,mBAAmB,CAAC;IA4IjF;;;;;;;;;;;;;OAaG;IACG,QAAQ,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAsDzE;AAgGD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,YAAY,EAAE,oBAAoB,IAAI,qBAAqB,EAAE,CAAC;AAE9D,MAAM,MAAM,eAAe,GAAG,cAAc,CAAC"}