@aaep/typescript-producer 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,170 @@
1
+ # TypeScript Minimal Producer Example
2
+
3
+ A minimal but complete AAEP producer implementation in TypeScript, designed for Node.js (18+). Demonstrates the manual loop pattern with full safety machinery and HTTP/SSE transport.
4
+
5
+ If you're building AAEP producers in the TypeScript/Node.js ecosystem — whether for browser-side agents, Electron-based AT software, or Node backend agents — this is the example to copy.
6
+
7
+ ---
8
+
9
+ ## What this example demonstrates
10
+
11
+ - A complete AAEP emitter implemented in idiomatic TypeScript
12
+ - Strict type definitions for every event type (matching the JSON Schemas)
13
+ - Native Node.js streams and `fetch` (no framework dependency)
14
+ - HTTP/SSE transport using Node's `http` module
15
+ - The same safety machinery as the Python examples: irreversible+high MUST default reject, secret redaction, critical urgency on errored events
16
+ - Confirmation flow with `Promise`-based blocking
17
+ - Streaming output with sentence-boundary coalescing
18
+ - All 12 core AAEP event types emitted from a typical agent session
19
+ - Conformance Level 2 compatible
20
+
21
+ ---
22
+
23
+ ## When to use this example
24
+
25
+ **Pick this pattern when:**
26
+ - You're building agents in Node.js, TypeScript, or modern JavaScript
27
+ - You need AAEP support in browser-side agent UIs
28
+ - You're building AT software in Electron, Tauri, or similar frameworks
29
+ - You want strict type definitions for AAEP events in your codebase
30
+
31
+ **Pick a Python example when:** your agent stack is Python.
32
+
33
+ ---
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ cd examples/producers/typescript-minimal
39
+ npm install
40
+ npm run build
41
+ ```
42
+
43
+ Requires Node.js 18 or newer.
44
+
45
+ ---
46
+
47
+ ## Quick start
48
+
49
+ ```typescript
50
+ import { AAEPEmitter, AgentLoop, makeId } from 'aaep-typescript-producer';
51
+
52
+ // Step 1: create an emitter with your transport
53
+ const emitter = new AAEPEmitter({
54
+ sendEvent: (event) => {
55
+ // Forward to subscribers (HTTP/SSE, WebSocket, etc.)
56
+ console.log(JSON.stringify(event));
57
+ },
58
+ agentId: 'my-agent',
59
+ agentName: 'My Agent',
60
+ });
61
+
62
+ // Step 2: create an agent loop
63
+ const agent = new AgentLoop(emitter);
64
+
65
+ // Step 3: run a session
66
+ const sessionId = await agent.run('Tell me about retirement planning.');
67
+ ```
68
+
69
+ The agent emits AAEP events through the configured transport as it runs. The same safety guarantees as Python: irreversible actions trigger confirmation events, errors emit critical-urgency terminal events, streaming output coalesces at sentence boundaries.
70
+
71
+ ---
72
+
73
+ ## Running the included demo
74
+
75
+ ```bash
76
+ npm run demo
77
+ ```
78
+
79
+ Runs three scenarios (basic query, tool use, irreversible tool with confirmation) and prints every emitted AAEP event in real time.
80
+
81
+ ---
82
+
83
+ ## Running the conformance suite against it
84
+
85
+ ```bash
86
+ # Terminal 1: start the server (port 8084)
87
+ npm run server
88
+
89
+ # Terminal 2: run the Python conformance suite against the TypeScript server
90
+ aaep-conformance producer --endpoint http://localhost:8084 --level 2
91
+ ```
92
+
93
+ The Python `aaep-conformance` package can verify any HTTP/SSE AAEP producer regardless of implementation language. Cross-language conformance is mechanically demonstrated.
94
+
95
+ ---
96
+
97
+ ## Project layout
98
+
99
+ ```
100
+ typescript-minimal/
101
+ ├── README.md
102
+ ├── package.json
103
+ ├── tsconfig.json
104
+ ├── src/
105
+ │ ├── index.ts # Public API exports
106
+ │ ├── types.ts # TypeScript types matching the AAEP schemas
107
+ │ ├── emitter.ts # AAEPEmitter class
108
+ │ ├── coalescer.ts # StreamCoalescer for sentence-boundary buffering
109
+ │ ├── agent.ts # AgentLoop with mock LLM
110
+ │ └── server.ts # HTTP/SSE server
111
+ └── test/
112
+ ├── emitter.test.ts
113
+ └── coalescer.test.ts
114
+ ```
115
+
116
+ ---
117
+
118
+ ## Key design decisions
119
+
120
+ ### 1. Strict TypeScript types
121
+
122
+ Every AAEP event has a corresponding TypeScript interface (`SessionStartedEvent`, `ToolInvokedEvent`, etc.). The emitter methods are strongly typed so editor autocomplete shows valid field names and the compiler catches missing required fields. Types match the JSON Schemas exactly.
123
+
124
+ ### 2. No framework dependencies
125
+
126
+ The example uses only the Node.js standard library plus type definitions. No Express, no Fastify, no agent framework — just the language and runtime. This makes the integration pattern clear and ensures the example survives ecosystem churn.
127
+
128
+ ### 3. Runtime safety enforcement (same as Python)
129
+
130
+ The `awaitConfirmation` method throws if called with `irreversible: true`, `riskLevel: 'high'`, and `defaultDecision: 'accept'`. This matches the JSON Schema's if/then rule AND the Python emitter's runtime check. The safety contract is enforced at every layer.
131
+
132
+ ### 4. Promise-based confirmation blocking
133
+
134
+ JavaScript doesn't have Python's `asyncio.Future`, but `Promise` works the same way. `awaitConfirmation()` returns a reply token; calling code does `await emitter.waitForDecision(token)` to block until the subscriber replies via `submitReply()`.
135
+
136
+ ### 5. Compatible with browser-side agents
137
+
138
+ The emitter code is environment-agnostic (no Node-specific imports in `emitter.ts`). You can use the same `AAEPEmitter` in a browser bundle for browser-side agents. Only `server.ts` is Node-specific.
139
+
140
+ ---
141
+
142
+ ## Cross-language conformance verification
143
+
144
+ This example demonstrates that **AAEP is genuinely language-agnostic**. The same `aaep-conformance` Python tool that verifies the Python examples also verifies this TypeScript example without modification.
145
+
146
+ To prove this end-to-end:
147
+
148
+ ```bash
149
+ # Run all 5 servers simultaneously
150
+ python -m aaep_minimal_producer.server --port 8080 & # Python manual loop
151
+ python -m aaep_langchain.server --port 8081 & # LangChain callback
152
+ python -m aaep_anthropic_sdk.server --port 8082 & # Anthropic SDK
153
+ python -m aaep_maf.server --port 8083 & # Microsoft Agent Framework
154
+ npm run server & # TypeScript (port 8084)
155
+
156
+ # Run conformance against all 5
157
+ for port in 8080 8081 8082 8083 8084; do
158
+ aaep-conformance producer --endpoint http://localhost:$port --level 2
159
+ done
160
+ ```
161
+
162
+ If all 5 pass Level 2, AAEP is interoperable across 4 Python integration patterns AND TypeScript. That's the mechanical proof of "AAEP is language-agnostic" — not a claim, a result.
163
+
164
+ ---
165
+
166
+ ## See also
167
+
168
+ - [`../python-minimal/`](../python-minimal/) — the Python reference (same machinery, different language)
169
+ - [Implementer's Guide §3.7](../../../guides/IMPLEMENTERS_GUIDE.md) — TypeScript integration specifics
170
+ - [Node.js SSE documentation](https://nodejs.org/api/http.html) — upstream reference for the transport
@@ -0,0 +1,41 @@
1
+ /**
2
+ * AgentLoop — TypeScript port of the Python python-minimal AgentLoop.
3
+ *
4
+ * Production-grade reference of the manual loop pattern with a mock LLM
5
+ * for portability. Replace `_MockLLM` with a real client (Anthropic, OpenAI,
6
+ * Azure OpenAI, etc.) for production use.
7
+ */
8
+ import { AAEPEmitter } from "./emitter.js";
9
+ export interface ToolDescriptor {
10
+ name: string;
11
+ description: string;
12
+ handler: (args: Record<string, unknown>) => unknown | Promise<unknown>;
13
+ riskLevel?: "low" | "medium" | "high";
14
+ irreversible?: boolean;
15
+ }
16
+ export interface AgentLoopOptions {
17
+ emitter: AAEPEmitter;
18
+ tools?: ToolDescriptor[];
19
+ }
20
+ export declare class AgentLoop {
21
+ private readonly emitter;
22
+ private readonly tools;
23
+ private readonly llm;
24
+ private readonly activeSessions;
25
+ constructor(options: AgentLoopOptions);
26
+ /**
27
+ * Run a complete agent session. Returns the session_id.
28
+ *
29
+ * The session is fully owned by this method: it emits all lifecycle
30
+ * events including the terminal event, even on exception.
31
+ */
32
+ run(userMessage: string, opts?: {
33
+ userId?: string;
34
+ }): Promise<string>;
35
+ /** Cancel an in-progress session. Returns true if cancellation was issued. */
36
+ cancel(sessionId: string): boolean;
37
+ private runLoop;
38
+ private executeTool;
39
+ private defaultTools;
40
+ }
41
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACH,WAAW,EAKd,MAAM,cAAc,CAAC;AAMtB,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvE,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACtC,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAKD,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;CAC5B;AAKD,qBAAa,SAAS;IAClB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA8B;IACpD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAW;IAC/B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA2C;gBAE9D,OAAO,EAAE,gBAAgB;IAQrC;;;;;OAKG;IACG,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAoB/E,8EAA8E;IAC9E,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;YASpB,OAAO;YAgIP,WAAW;IAuFzB,OAAO,CAAC,YAAY;CAuCvB"}
package/dist/agent.js ADDED
@@ -0,0 +1,336 @@
1
+ /**
2
+ * AgentLoop — TypeScript port of the Python python-minimal AgentLoop.
3
+ *
4
+ * Production-grade reference of the manual loop pattern with a mock LLM
5
+ * for portability. Replace `_MockLLM` with a real client (Anthropic, OpenAI,
6
+ * Azure OpenAI, etc.) for production use.
7
+ */
8
+ import { classifyErrorCategory, classifyRisk, makeId, safeArgsSummary, } from "./emitter.js";
9
+ import { StreamCoalescer } from "./coalescer.js";
10
+ // === The agent loop ===
11
+ export class AgentLoop {
12
+ emitter;
13
+ tools;
14
+ llm;
15
+ activeSessions = new Map();
16
+ constructor(options) {
17
+ this.emitter = options.emitter;
18
+ this.tools = new Map((options.tools ?? this.defaultTools()).map((t) => [t.name, t]));
19
+ this.llm = new _MockLLM();
20
+ }
21
+ /**
22
+ * Run a complete agent session. Returns the session_id.
23
+ *
24
+ * The session is fully owned by this method: it emits all lifecycle
25
+ * events including the terminal event, even on exception.
26
+ */
27
+ async run(userMessage, opts = {}) {
28
+ const sessionId = this.emitter.startSession({
29
+ summaryNormal: `Processing: ${userMessage.slice(0, 80)}`,
30
+ requestText: userMessage,
31
+ requestedBy: opts.userId ? `user:${opts.userId}` : undefined,
32
+ toolsAvailable: Array.from(this.tools.keys()),
33
+ });
34
+ const abortController = new AbortController();
35
+ this.activeSessions.set(sessionId, abortController);
36
+ try {
37
+ await this.runLoop(sessionId, userMessage, abortController.signal);
38
+ }
39
+ finally {
40
+ this.activeSessions.delete(sessionId);
41
+ }
42
+ return sessionId;
43
+ }
44
+ /** Cancel an in-progress session. Returns true if cancellation was issued. */
45
+ cancel(sessionId) {
46
+ const controller = this.activeSessions.get(sessionId);
47
+ if (!controller)
48
+ return false;
49
+ controller.abort();
50
+ return true;
51
+ }
52
+ // === Internal: the thinking-and-acting loop ===
53
+ async runLoop(sessionId, userMessage, abortSignal) {
54
+ const startTime = Date.now();
55
+ let currentState = "idle";
56
+ let toolCount = 0;
57
+ let coalescer = null;
58
+ const messages = [
59
+ { role: "user", content: userMessage },
60
+ ];
61
+ try {
62
+ while (true) {
63
+ if (abortSignal.aborted) {
64
+ throw new DOMException("Cancelled", "AbortError");
65
+ }
66
+ // Transition to thinking
67
+ if (currentState !== "thinking") {
68
+ this.emitter.stateChanged({
69
+ sessionId,
70
+ fromState: currentState,
71
+ toState: "thinking",
72
+ summaryNormal: "Considering the request.",
73
+ });
74
+ currentState = "thinking";
75
+ }
76
+ const response = await this.llm.complete(messages, Array.from(this.tools.values()));
77
+ if (response.toolCalls.length > 0) {
78
+ // Tools requested
79
+ this.emitter.stateChanged({
80
+ sessionId,
81
+ fromState: "thinking",
82
+ toState: "calling_tool",
83
+ summaryNormal: `Preparing to call ${response.toolCalls.length} tool(s).`,
84
+ });
85
+ currentState = "calling_tool";
86
+ const toolResults = [];
87
+ for (const toolCall of response.toolCalls) {
88
+ const result = await this.executeTool(sessionId, toolCall);
89
+ toolCount++;
90
+ toolResults.push({ tool_call_id: toolCall.id, result });
91
+ }
92
+ messages.push({
93
+ role: "assistant",
94
+ content: response.text,
95
+ });
96
+ messages.push({
97
+ role: "tool_results",
98
+ content: toolResults,
99
+ });
100
+ continue;
101
+ }
102
+ // No more tools; stream output
103
+ this.emitter.stateChanged({
104
+ sessionId,
105
+ fromState: "thinking",
106
+ toState: "writing_output",
107
+ summaryNormal: "Generating response.",
108
+ });
109
+ currentState = "writing_output";
110
+ const outputId = makeId("out");
111
+ coalescer = new StreamCoalescer({
112
+ emitter: this.emitter,
113
+ sessionId,
114
+ outputId,
115
+ coalesceAt: "sentence",
116
+ });
117
+ for await (const chunk of this.llm.stream(response)) {
118
+ if (abortSignal.aborted) {
119
+ throw new DOMException("Cancelled", "AbortError");
120
+ }
121
+ coalescer.addToken(chunk);
122
+ }
123
+ coalescer.finish();
124
+ coalescer = null;
125
+ break;
126
+ }
127
+ // Success
128
+ const durationMs = Date.now() - startTime;
129
+ this.emitter.completeSession({
130
+ sessionId,
131
+ summaryNormal: "Response complete.",
132
+ durationMs,
133
+ toolInvocationsCount: toolCount,
134
+ });
135
+ }
136
+ catch (error) {
137
+ if (coalescer) {
138
+ try {
139
+ coalescer.finish();
140
+ }
141
+ catch {
142
+ // Already finished or in bad state; swallow
143
+ }
144
+ }
145
+ if (error instanceof DOMException && error.name === "AbortError") {
146
+ this.emitter.cancelledSession({
147
+ sessionId,
148
+ cancelledBy: "system",
149
+ summaryNormal: "Session cancelled.",
150
+ });
151
+ }
152
+ else {
153
+ const err = error instanceof Error ? error : new Error(String(error));
154
+ this.emitter.errorSession({
155
+ sessionId,
156
+ errorCategory: classifyErrorCategory(err),
157
+ summaryNormal: `Error: ${err.name}`,
158
+ errorMessage: err.message.slice(0, 1000),
159
+ recoverable: err.name === "TimeoutError" || err.message.toLowerCase().includes("network"),
160
+ });
161
+ }
162
+ throw error;
163
+ }
164
+ }
165
+ // === Internal: execute one tool with full AAEP cycle ===
166
+ async executeTool(sessionId, toolCall) {
167
+ const descriptor = this.tools.get(toolCall.name);
168
+ const aaepCallId = makeId("call");
169
+ const args = toolCall.arguments;
170
+ const { riskLevel, irreversible } = descriptor
171
+ ? {
172
+ riskLevel: descriptor.riskLevel ?? "low",
173
+ irreversible: descriptor.irreversible ?? false,
174
+ }
175
+ : classifyRisk(toolCall.name);
176
+ // Emit tool.invoked BEFORE side effect
177
+ this.emitter.toolInvoked({
178
+ sessionId,
179
+ tool: toolCall.name,
180
+ toolCallId: aaepCallId,
181
+ argsSummary: safeArgsSummary(args),
182
+ riskLevel,
183
+ irreversible,
184
+ summaryNormal: `Calling ${toolCall.name}.`,
185
+ });
186
+ // Confirmation gating for irreversible or high-risk
187
+ if (irreversible || riskLevel === "high") {
188
+ const replyToken = this.emitter.awaitConfirmation({
189
+ sessionId,
190
+ action: `Call ${toolCall.name} with: ${safeArgsSummary(args, 200)}`,
191
+ consequence: irreversible
192
+ ? "This action cannot be easily undone."
193
+ : "This action will be executed.",
194
+ timeoutSeconds: 300,
195
+ defaultDecision: "reject",
196
+ riskLevel,
197
+ irreversible,
198
+ summaryNormal: `Confirm: call ${toolCall.name}?`,
199
+ });
200
+ const decision = await this.emitter.waitForDecision(replyToken);
201
+ if (decision !== "accept") {
202
+ this.emitter.toolCompleted({
203
+ sessionId,
204
+ tool: toolCall.name,
205
+ toolCallId: aaepCallId,
206
+ status: "error",
207
+ errorMessage: "User declined to authorize this action.",
208
+ });
209
+ return `<user declined to call ${toolCall.name}>`;
210
+ }
211
+ }
212
+ // Execute the tool
213
+ try {
214
+ if (!descriptor) {
215
+ throw new Error(`No handler for tool ${JSON.stringify(toolCall.name)}`);
216
+ }
217
+ const result = await descriptor.handler(args);
218
+ this.emitter.toolCompleted({
219
+ sessionId,
220
+ tool: toolCall.name,
221
+ toolCallId: aaepCallId,
222
+ status: "success",
223
+ summaryNormal: String(result).slice(0, 200),
224
+ });
225
+ return result;
226
+ }
227
+ catch (error) {
228
+ const err = error instanceof Error ? error : new Error(String(error));
229
+ const isTimeout = err.name === "TimeoutError" || err.message.includes("timeout");
230
+ this.emitter.toolCompleted({
231
+ sessionId,
232
+ tool: toolCall.name,
233
+ toolCallId: aaepCallId,
234
+ status: isTimeout ? "timeout" : "error",
235
+ errorMessage: err.message.slice(0, 1000),
236
+ });
237
+ throw error;
238
+ }
239
+ }
240
+ // === Default mock tools ===
241
+ defaultTools() {
242
+ return [
243
+ {
244
+ name: "fetch_balance",
245
+ description: "Look up an account balance",
246
+ handler: async (args) => {
247
+ await sleep(300);
248
+ const account = args.account ?? "checking";
249
+ const balances = {
250
+ checking: "$3,247.18",
251
+ savings: "$12,891.40",
252
+ };
253
+ return balances[account] ?? "$0.00";
254
+ },
255
+ riskLevel: "low",
256
+ irreversible: false,
257
+ },
258
+ {
259
+ name: "send_email",
260
+ description: "Send an email",
261
+ handler: async (args) => {
262
+ await sleep(500);
263
+ return `Email sent to ${args.to ?? "recipient"}`;
264
+ },
265
+ riskLevel: "high",
266
+ irreversible: true,
267
+ },
268
+ {
269
+ name: "transfer_funds",
270
+ description: "Move money between accounts",
271
+ handler: async (args) => {
272
+ await sleep(700);
273
+ return `Transferred $${args.amount} from ${args.from} to ${args.to}`;
274
+ },
275
+ riskLevel: "high",
276
+ irreversible: true,
277
+ },
278
+ ];
279
+ }
280
+ }
281
+ class _MockLLM {
282
+ calls = 0;
283
+ async complete(messages, _tools) {
284
+ await sleep(400);
285
+ this.calls++;
286
+ const lastMsg = messages[messages.length - 1];
287
+ const lastText = typeof lastMsg?.content === "string" ? lastMsg.content : "";
288
+ const lower = lastText.toLowerCase();
289
+ // On the first call, sometimes call a tool to exercise the flow
290
+ if (this.calls === 1) {
291
+ if (lower.includes("balance")) {
292
+ return {
293
+ text: "Let me check that for you.",
294
+ toolCalls: [{
295
+ id: `tool_${this.calls}`,
296
+ name: "fetch_balance",
297
+ arguments: { account: "checking" },
298
+ }],
299
+ };
300
+ }
301
+ if (lower.includes("email")) {
302
+ return {
303
+ text: "I'll send that email.",
304
+ toolCalls: [{
305
+ id: `tool_${this.calls}`,
306
+ name: "send_email",
307
+ arguments: {
308
+ to: "recipient@example.com",
309
+ subject: "Re: your request",
310
+ },
311
+ }],
312
+ };
313
+ }
314
+ }
315
+ // No more tools; return final output (caller will stream the text)
316
+ return { text: "", toolCalls: [] };
317
+ }
318
+ async *stream(_response) {
319
+ const chunks = [
320
+ "Here's what I found. ",
321
+ "Your account is in good standing ",
322
+ "with no pending issues. ",
323
+ "Is there anything else ",
324
+ "I can help you with?",
325
+ ];
326
+ for (const chunk of chunks) {
327
+ await sleep(50);
328
+ yield chunk;
329
+ }
330
+ }
331
+ }
332
+ // === Helpers ===
333
+ function sleep(ms) {
334
+ return new Promise((resolve) => setTimeout(resolve, ms));
335
+ }
336
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAEH,qBAAqB,EACrB,YAAY,EACZ,MAAM,EACN,eAAe,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAsBjD,yBAAyB;AAEzB,MAAM,OAAO,SAAS;IACD,OAAO,CAAc;IACrB,KAAK,CAA8B;IACnC,GAAG,CAAW;IACd,cAAc,GAAiC,IAAI,GAAG,EAAE,CAAC;IAE1E,YAAY,OAAyB;QACjC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,CAChB,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CACjE,CAAC;QACF,IAAI,CAAC,GAAG,GAAG,IAAI,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,GAAG,CAAC,WAAmB,EAAE,OAA4B,EAAE;QACzD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;YACxC,aAAa,EAAE,eAAe,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;YACxD,WAAW,EAAE,WAAW;YACxB,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS;YAC5D,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SAChD,CAAC,CAAC;QAEH,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAC9C,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;QAEpD,IAAI,CAAC;YACD,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,WAAW,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;QACvE,CAAC;gBAAS,CAAC;YACP,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC1C,CAAC;QAED,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,8EAA8E;IAC9E,MAAM,CAAC,SAAiB;QACpB,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACtD,IAAI,CAAC,UAAU;YAAE,OAAO,KAAK,CAAC;QAC9B,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,iDAAiD;IAEzC,KAAK,CAAC,OAAO,CACjB,SAAiB,EACjB,WAAmB,EACnB,WAAwB;QAExB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,YAAY,GAAG,MAAM,CAAC;QAC1B,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,SAAS,GAA2B,IAAI,CAAC;QAC7C,MAAM,QAAQ,GAA8C;YACxD,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE;SACzC,CAAC;QAEF,IAAI,CAAC;YACD,OAAO,IAAI,EAAE,CAAC;gBACV,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;oBACtB,MAAM,IAAI,YAAY,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;gBACtD,CAAC;gBAED,yBAAyB;gBACzB,IAAI,YAAY,KAAK,UAAU,EAAE,CAAC;oBAC9B,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;wBACtB,SAAS;wBACT,SAAS,EAAE,YAAY;wBACvB,OAAO,EAAE,UAAU;wBACnB,aAAa,EAAE,0BAA0B;qBAC5C,CAAC,CAAC;oBACH,YAAY,GAAG,UAAU,CAAC;gBAC9B,CAAC;gBAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;gBAEpF,IAAI,QAAQ,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAChC,kBAAkB;oBAClB,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;wBACtB,SAAS;wBACT,SAAS,EAAE,UAAU;wBACrB,OAAO,EAAE,cAAc;wBACvB,aAAa,EAAE,qBAAqB,QAAQ,CAAC,SAAS,CAAC,MAAM,WAAW;qBAC3E,CAAC,CAAC;oBACH,YAAY,GAAG,cAAc,CAAC;oBAE9B,MAAM,WAAW,GAAqD,EAAE,CAAC;oBACzE,KAAK,MAAM,QAAQ,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;wBACxC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;wBAC3D,SAAS,EAAE,CAAC;wBACZ,WAAW,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;oBAC5D,CAAC;oBAED,QAAQ,CAAC,IAAI,CAAC;wBACV,IAAI,EAAE,WAAW;wBACjB,OAAO,EAAE,QAAQ,CAAC,IAAI;qBACzB,CAAC,CAAC;oBACH,QAAQ,CAAC,IAAI,CAAC;wBACV,IAAI,EAAE,cAAc;wBACpB,OAAO,EAAE,WAAW;qBACvB,CAAC,CAAC;oBACH,SAAS;gBACb,CAAC;gBAED,+BAA+B;gBAC/B,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;oBACtB,SAAS;oBACT,SAAS,EAAE,UAAU;oBACrB,OAAO,EAAE,gBAAgB;oBACzB,aAAa,EAAE,sBAAsB;iBACxC,CAAC,CAAC;gBACH,YAAY,GAAG,gBAAgB,CAAC;gBAEhC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC/B,SAAS,GAAG,IAAI,eAAe,CAAC;oBAC5B,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,SAAS;oBACT,QAAQ;oBACR,UAAU,EAAE,UAAU;iBACzB,CAAC,CAAC;gBAEH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAClD,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;wBACtB,MAAM,IAAI,YAAY,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;oBACtD,CAAC;oBACD,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAC9B,CAAC;gBACD,SAAS,CAAC,MAAM,EAAE,CAAC;gBACnB,SAAS,GAAG,IAAI,CAAC;gBACjB,MAAM;YACV,CAAC;YAED,UAAU;YACV,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAC1C,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC;gBACzB,SAAS;gBACT,aAAa,EAAE,oBAAoB;gBACnC,UAAU;gBACV,oBAAoB,EAAE,SAAS;aAClC,CAAC,CAAC;QAEP,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACtB,IAAI,SAAS,EAAE,CAAC;gBACZ,IAAI,CAAC;oBACD,SAAS,CAAC,MAAM,EAAE,CAAC;gBACvB,CAAC;gBAAC,MAAM,CAAC;oBACL,4CAA4C;gBAChD,CAAC;YACL,CAAC;YAED,IAAI,KAAK,YAAY,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC/D,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC;oBAC1B,SAAS;oBACT,WAAW,EAAE,QAAQ;oBACrB,aAAa,EAAE,oBAAoB;iBACtC,CAAC,CAAC;YACP,CAAC;iBAAM,CAAC;gBACJ,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;gBACtE,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;oBACtB,SAAS;oBACT,aAAa,EAAE,qBAAqB,CAAC,GAAG,CAAC;oBACzC,aAAa,EAAE,UAAU,GAAG,CAAC,IAAI,EAAE;oBACnC,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;oBACxC,WAAW,EAAE,GAAG,CAAC,IAAI,KAAK,cAAc,IAAI,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;iBAC5F,CAAC,CAAC;YACP,CAAC;YACD,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;IAED,0DAA0D;IAElD,KAAK,CAAC,WAAW,CACrB,SAAiB,EACjB,QAA0E;QAE1E,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC;QAEhC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,UAAU;YAC1C,CAAC,CAAC;gBACI,SAAS,EAAE,UAAU,CAAC,SAAS,IAAI,KAAK;gBACxC,YAAY,EAAE,UAAU,CAAC,YAAY,IAAI,KAAK;aACjD;YACH,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAElC,uCAAuC;QACvC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC;YACrB,SAAS;YACT,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,UAAU,EAAE,UAAU;YACtB,WAAW,EAAE,eAAe,CAAC,IAAI,CAAC;YAClC,SAAS;YACT,YAAY;YACZ,aAAa,EAAE,WAAW,QAAQ,CAAC,IAAI,GAAG;SAC7C,CAAC,CAAC;QAEH,oDAAoD;QACpD,IAAI,YAAY,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;YACvC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC;gBAC9C,SAAS;gBACT,MAAM,EAAE,QAAQ,QAAQ,CAAC,IAAI,UAAU,eAAe,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE;gBACnE,WAAW,EAAE,YAAY;oBACrB,CAAC,CAAC,sCAAsC;oBACxC,CAAC,CAAC,+BAA+B;gBACrC,cAAc,EAAE,GAAG;gBACnB,eAAe,EAAE,QAAQ;gBACzB,SAAS;gBACT,YAAY;gBACZ,aAAa,EAAE,iBAAiB,QAAQ,CAAC,IAAI,GAAG;aACnD,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;YAEhE,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBACxB,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;oBACvB,SAAS;oBACT,IAAI,EAAE,QAAQ,CAAC,IAAI;oBACnB,UAAU,EAAE,UAAU;oBACtB,MAAM,EAAE,OAAO;oBACf,YAAY,EAAE,yCAAyC;iBAC1D,CAAC,CAAC;gBACH,OAAO,0BAA0B,QAAQ,CAAC,IAAI,GAAG,CAAC;YACtD,CAAC;QACL,CAAC;QAED,mBAAmB;QACnB,IAAI,CAAC;YACD,IAAI,CAAC,UAAU,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC5E,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAE9C,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;gBACvB,SAAS;gBACT,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,UAAU,EAAE,UAAU;gBACtB,MAAM,EAAE,SAAS;gBACjB,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;aAC9C,CAAC,CAAC;YACH,OAAO,MAAM,CAAC;QAElB,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACtB,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACtE,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,KAAK,cAAc,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YACjF,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;gBACvB,SAAS;gBACT,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,UAAU,EAAE,UAAU;gBACtB,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO;gBACvC,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;aAC3C,CAAC,CAAC;YACH,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;IAED,6BAA6B;IAErB,YAAY;QAChB,OAAO;YACH;gBACI,IAAI,EAAE,eAAe;gBACrB,WAAW,EAAE,4BAA4B;gBACzC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;oBACpB,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;oBACjB,MAAM,OAAO,GAAI,IAAI,CAAC,OAAkB,IAAI,UAAU,CAAC;oBACvD,MAAM,QAAQ,GAA2B;wBACrC,QAAQ,EAAE,WAAW;wBACrB,OAAO,EAAE,YAAY;qBACxB,CAAC;oBACF,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC;gBACxC,CAAC;gBACD,SAAS,EAAE,KAAK;gBAChB,YAAY,EAAE,KAAK;aACtB;YACD;gBACI,IAAI,EAAE,YAAY;gBAClB,WAAW,EAAE,eAAe;gBAC5B,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;oBACpB,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;oBACjB,OAAO,iBAAiB,IAAI,CAAC,EAAE,IAAI,WAAW,EAAE,CAAC;gBACrD,CAAC;gBACD,SAAS,EAAE,MAAM;gBACjB,YAAY,EAAE,IAAI;aACrB;YACD;gBACI,IAAI,EAAE,gBAAgB;gBACtB,WAAW,EAAE,6BAA6B;gBAC1C,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;oBACpB,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;oBACjB,OAAO,gBAAgB,IAAI,CAAC,MAAM,SAAS,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,EAAE,EAAE,CAAC;gBACzE,CAAC;gBACD,SAAS,EAAE,MAAM;gBACjB,YAAY,EAAE,IAAI;aACrB;SACJ,CAAC;IACN,CAAC;CACJ;AAWD,MAAM,QAAQ;IACF,KAAK,GAAG,CAAC,CAAC;IAElB,KAAK,CAAC,QAAQ,CACV,QAAmD,EACnD,MAAwB;QAExB,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QACjB,IAAI,CAAC,KAAK,EAAE,CAAC;QAEb,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,OAAO,OAAO,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7E,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;QAErC,gEAAgE;QAChE,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;YACnB,IAAI,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC5B,OAAO;oBACH,IAAI,EAAE,4BAA4B;oBAClC,SAAS,EAAE,CAAC;4BACR,EAAE,EAAE,QAAQ,IAAI,CAAC,KAAK,EAAE;4BACxB,IAAI,EAAE,eAAe;4BACrB,SAAS,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE;yBACrC,CAAC;iBACL,CAAC;YACN,CAAC;YACD,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC1B,OAAO;oBACH,IAAI,EAAE,uBAAuB;oBAC7B,SAAS,EAAE,CAAC;4BACR,EAAE,EAAE,QAAQ,IAAI,CAAC,KAAK,EAAE;4BACxB,IAAI,EAAE,YAAY;4BAClB,SAAS,EAAE;gCACP,EAAE,EAAE,uBAAuB;gCAC3B,OAAO,EAAE,kBAAkB;6BAC9B;yBACJ,CAAC;iBACL,CAAC;YACN,CAAC;QACL,CAAC;QAED,mEAAmE;QACnE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,CAAC,MAAM,CAAC,SAA0B;QACpC,MAAM,MAAM,GAAG;YACX,uBAAuB;YACvB,mCAAmC;YACnC,0BAA0B;YAC1B,yBAAyB;YACzB,sBAAsB;SACzB,CAAC;QACF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACzB,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;YAChB,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;CACJ;AAGD,kBAAkB;AAElB,SAAS,KAAK,CAAC,EAAU;IACrB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * StreamCoalescer — TypeScript port of the Python StreamCoalescer.
3
+ *
4
+ * Buffers streaming tokens and emits agent.output.streaming events at
5
+ * coalesce boundaries (default: sentence boundaries). The boundary
6
+ * detection regexes match the Python implementation exactly.
7
+ *
8
+ * Usage:
9
+ * const coalescer = new StreamCoalescer({
10
+ * emitter,
11
+ * sessionId: "sess_x",
12
+ * outputId: "out_y",
13
+ * coalesceAt: "sentence",
14
+ * });
15
+ * coalescer.addToken("Hello ");
16
+ * coalescer.addToken("world. "); // sentence boundary -> emit
17
+ * coalescer.addToken("Goodbye.");
18
+ * coalescer.finish(); // final emit with complete=true
19
+ */
20
+ import type { CoalesceHint } from "./types.js";
21
+ import { AAEPEmitter } from "./emitter.js";
22
+ export interface StreamCoalescerOptions {
23
+ emitter: AAEPEmitter;
24
+ sessionId: string;
25
+ outputId: string;
26
+ coalesceAt?: CoalesceHint;
27
+ language?: string;
28
+ }
29
+ export declare class StreamCoalescer {
30
+ private readonly emitter;
31
+ private readonly sessionId;
32
+ private readonly outputId;
33
+ private readonly coalesceAt;
34
+ private readonly language;
35
+ private buffer;
36
+ private position;
37
+ private finished;
38
+ constructor(options: StreamCoalescerOptions);
39
+ /**
40
+ * Add a token to the buffer. May emit one or more events if coalesce
41
+ * boundaries are crossed by the addition.
42
+ */
43
+ addToken(token: string): void;
44
+ /**
45
+ * Flush any remaining buffer and emit the final completion event
46
+ * (complete=true). Idempotent; safe to call multiple times.
47
+ */
48
+ finish(): void;
49
+ /** Inspect the current buffered text (for tests). */
50
+ get bufferedText(): string;
51
+ /** Whether finish() has been called. */
52
+ get isFinished(): boolean;
53
+ private flushAtBoundary;
54
+ private findBoundaries;
55
+ private emitChunk;
56
+ }
57
+ //# sourceMappingURL=coalescer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coalescer.d.ts","sourceRoot":"","sources":["../src/coalescer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,MAAM,WAAW,sBAAsB;IACnC,OAAO,EAAE,WAAW,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAGD,qBAAa,eAAe;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAe;IAC1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAE9C,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,QAAQ,CAAS;gBAEb,OAAO,EAAE,sBAAsB;IAQ3C;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAQ7B;;;OAGG;IACH,MAAM,IAAI,IAAI;IAQd,qDAAqD;IACrD,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,wCAAwC;IACxC,IAAI,UAAU,IAAI,OAAO,CAExB;IAID,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,cAAc;IAwBtB,OAAO,CAAC,SAAS;CAepB"}