@fronx/use-claude-code 0.1.0
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 +273 -0
- package/dist/client/connection.d.ts +101 -0
- package/dist/client/connection.d.ts.map +1 -0
- package/dist/client/connection.js +379 -0
- package/dist/client/connection.js.map +1 -0
- package/dist/client/event-emitter.d.ts +32 -0
- package/dist/client/event-emitter.d.ts.map +1 -0
- package/dist/client/event-emitter.js +72 -0
- package/dist/client/event-emitter.js.map +1 -0
- package/dist/client/index.d.ts +30 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +29 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/state-machine.d.ts +61 -0
- package/dist/client/state-machine.d.ts.map +1 -0
- package/dist/client/state-machine.js +292 -0
- package/dist/client/state-machine.js.map +1 -0
- package/dist/client/stream-processor.d.ts +46 -0
- package/dist/client/stream-processor.d.ts.map +1 -0
- package/dist/client/stream-processor.js +173 -0
- package/dist/client/stream-processor.js.map +1 -0
- package/dist/react/hook.d.ts +55 -0
- package/dist/react/hook.d.ts.map +1 -0
- package/dist/react/hook.js +132 -0
- package/dist/react/hook.js.map +1 -0
- package/dist/react/index.d.ts +49 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +48 -0
- package/dist/react/index.js.map +1 -0
- package/dist/server/claude-spawn.d.ts +52 -0
- package/dist/server/claude-spawn.d.ts.map +1 -0
- package/dist/server/claude-spawn.js +147 -0
- package/dist/server/claude-spawn.js.map +1 -0
- package/dist/server/conversation.d.ts +113 -0
- package/dist/server/conversation.d.ts.map +1 -0
- package/dist/server/conversation.js +520 -0
- package/dist/server/conversation.js.map +1 -0
- package/dist/server/index.d.ts +35 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +39 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/sse-emitter.d.ts +42 -0
- package/dist/server/sse-emitter.d.ts.map +1 -0
- package/dist/server/sse-emitter.js +56 -0
- package/dist/server/sse-emitter.js.map +1 -0
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +3 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/tool-utils.d.ts +25 -0
- package/dist/shared/tool-utils.d.ts.map +1 -0
- package/dist/shared/tool-utils.js +49 -0
- package/dist/shared/tool-utils.js.map +1 -0
- package/dist/shared/types.d.ts +82 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +5 -0
- package/dist/shared/types.js.map +1 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
# @anthropic/claude-code-lib
|
|
2
|
+
|
|
3
|
+
A reusable library for integrating Claude Code CLI conversations into applications.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Server-side**: Spawn and manage Claude CLI processes, handle conversation lifecycle, stream responses via SSE
|
|
8
|
+
- **Client-side**: Parse SSE streams, manage connection state, handle reconnection with exponential backoff
|
|
9
|
+
- **React**: `useClaudeConversation` hook for easy integration
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @anthropic/claude-code-lib
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### Server (Node.js)
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { ClaudeManager } from '@anthropic/claude-code-lib/server';
|
|
23
|
+
|
|
24
|
+
const manager = new ClaudeManager({
|
|
25
|
+
sessionDir: './data/sessions',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Start a conversation
|
|
29
|
+
const conversation = manager.start('user-123', {
|
|
30
|
+
systemPrompt: 'You are a helpful assistant.',
|
|
31
|
+
cwd: process.cwd(),
|
|
32
|
+
initialMessage: 'Hello!',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Subscribe to SSE events
|
|
36
|
+
conversation.subscribe(res);
|
|
37
|
+
|
|
38
|
+
// Send additional messages
|
|
39
|
+
conversation.send('How does this work?');
|
|
40
|
+
|
|
41
|
+
// Stop generation (SIGINT)
|
|
42
|
+
conversation.stop();
|
|
43
|
+
|
|
44
|
+
// Clear conversation
|
|
45
|
+
manager.clear('user-123');
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Client (Browser)
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { ClaudeConnection } from '@anthropic/claude-code-lib/client';
|
|
52
|
+
|
|
53
|
+
const connection = new ClaudeConnection({
|
|
54
|
+
baseUrl: '/api/claude',
|
|
55
|
+
conversationId: 'user-123',
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
connection.on('stateChange', () => {
|
|
59
|
+
console.log('Messages:', connection.messages);
|
|
60
|
+
console.log('Streaming:', connection.streamingSegments);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
connection.on('result', () => {
|
|
64
|
+
console.log('Response complete');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Check status and connect
|
|
68
|
+
await connection.connect();
|
|
69
|
+
|
|
70
|
+
// Start a new conversation
|
|
71
|
+
await connection.start('Hello!');
|
|
72
|
+
|
|
73
|
+
// Send a message
|
|
74
|
+
await connection.send('How does this work?');
|
|
75
|
+
|
|
76
|
+
// Stop generation
|
|
77
|
+
await connection.stop();
|
|
78
|
+
|
|
79
|
+
// Clear session
|
|
80
|
+
await connection.clear();
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### React
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
import { useClaudeConversation } from '@anthropic/claude-code-lib/react';
|
|
87
|
+
|
|
88
|
+
function Chat({ projectId }) {
|
|
89
|
+
const {
|
|
90
|
+
messages,
|
|
91
|
+
status,
|
|
92
|
+
isStreaming,
|
|
93
|
+
streamingSegments,
|
|
94
|
+
hasPersistedSession,
|
|
95
|
+
start,
|
|
96
|
+
send,
|
|
97
|
+
stop,
|
|
98
|
+
clear,
|
|
99
|
+
resume,
|
|
100
|
+
} = useClaudeConversation({
|
|
101
|
+
baseUrl: '/api/claude',
|
|
102
|
+
conversationId: projectId,
|
|
103
|
+
onResult: () => console.log('Response complete'),
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<div>
|
|
108
|
+
{/* Completed messages */}
|
|
109
|
+
{messages.map(msg => (
|
|
110
|
+
<div key={msg.id} className={msg.role}>
|
|
111
|
+
{msg.content}
|
|
112
|
+
</div>
|
|
113
|
+
))}
|
|
114
|
+
|
|
115
|
+
{/* Streaming content */}
|
|
116
|
+
{streamingSegments.map((seg, i) =>
|
|
117
|
+
seg.type === 'text' ? (
|
|
118
|
+
<div key={i}>{seg.content}</div>
|
|
119
|
+
) : (
|
|
120
|
+
<div key={i}>Running: {seg.name} {seg.param}</div>
|
|
121
|
+
)
|
|
122
|
+
)}
|
|
123
|
+
|
|
124
|
+
{/* Resume link for persisted sessions */}
|
|
125
|
+
{status === 'disconnected' && hasPersistedSession && (
|
|
126
|
+
<button onClick={resume}>Resume Previous Session</button>
|
|
127
|
+
)}
|
|
128
|
+
|
|
129
|
+
{/* Controls */}
|
|
130
|
+
<input type="text" id="message" />
|
|
131
|
+
<button onClick={() => send(document.getElementById('message').value)}>
|
|
132
|
+
Send
|
|
133
|
+
</button>
|
|
134
|
+
{isStreaming && <button onClick={stop}>Stop</button>}
|
|
135
|
+
</div>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## API Reference
|
|
141
|
+
|
|
142
|
+
### Server
|
|
143
|
+
|
|
144
|
+
#### `ClaudeManager`
|
|
145
|
+
|
|
146
|
+
Main class for managing Claude conversations.
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
interface ClaudeManagerConfig {
|
|
150
|
+
sessionDir: string; // Where to persist sessions
|
|
151
|
+
claudePath?: string; // Path to claude CLI (default: 'claude')
|
|
152
|
+
defaultAllowedTools?: string[]; // Default tools to allow
|
|
153
|
+
autoPrewarm?: boolean; // Auto-prewarm after clear (default: false)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
interface StartOptions {
|
|
157
|
+
systemPrompt: string | { file: string };
|
|
158
|
+
cwd: string;
|
|
159
|
+
allowedTools?: string[];
|
|
160
|
+
initialMessage?: string;
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Methods:
|
|
165
|
+
- `start(id, options)` - Start a new conversation
|
|
166
|
+
- `get(id)` - Get an active conversation
|
|
167
|
+
- `resume(id, options)` - Resume from persisted session
|
|
168
|
+
- `stop(id)` - Stop current response (SIGINT)
|
|
169
|
+
- `clear(id)` - Kill process and delete session
|
|
170
|
+
- `prewarm(id, options)` - Spawn without sending message
|
|
171
|
+
- `getStatus(id)` - Get conversation status
|
|
172
|
+
- `hasPersistedSession(id)` - Check for saved session
|
|
173
|
+
|
|
174
|
+
### Client
|
|
175
|
+
|
|
176
|
+
#### `ClaudeConnection`
|
|
177
|
+
|
|
178
|
+
Event-emitter based connection manager.
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
interface ClaudeConnectionConfig {
|
|
182
|
+
baseUrl: string;
|
|
183
|
+
conversationId: string;
|
|
184
|
+
reconnect?: {
|
|
185
|
+
maxRetries?: number; // Default: 10
|
|
186
|
+
baseDelay?: number; // Default: 1000ms
|
|
187
|
+
maxDelay?: number; // Default: 30000ms
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Properties (read-only):
|
|
193
|
+
- `status` - 'checking' | 'disconnected' | 'connecting' | 'connected' | 'reconnecting'
|
|
194
|
+
- `messages` - Array of completed messages
|
|
195
|
+
- `isStreaming` - Whether currently streaming
|
|
196
|
+
- `streamingSegments` - Current streaming content (text and tools)
|
|
197
|
+
- `hasPersistedSession` - Whether a saved session exists
|
|
198
|
+
- `lastError` - Most recent error
|
|
199
|
+
|
|
200
|
+
Methods:
|
|
201
|
+
- `connect()` - Check status and connect
|
|
202
|
+
- `disconnect()` - Close connection
|
|
203
|
+
- `start(message?)` - Start new conversation
|
|
204
|
+
- `send(message)` - Send message
|
|
205
|
+
- `stop()` - Stop generation
|
|
206
|
+
- `clear()` - Clear session
|
|
207
|
+
- `resume()` - Resume saved session
|
|
208
|
+
- `prewarm()` - Prewarm for faster response
|
|
209
|
+
|
|
210
|
+
Events:
|
|
211
|
+
- `stateChange` - Any state property changed
|
|
212
|
+
- `message` - New message added
|
|
213
|
+
- `streaming` - Streaming segments updated
|
|
214
|
+
- `tool` - Tool invocation
|
|
215
|
+
- `result` - Response complete
|
|
216
|
+
- `error` - Error occurred
|
|
217
|
+
|
|
218
|
+
### React
|
|
219
|
+
|
|
220
|
+
#### `useClaudeConversation`
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
interface UseClaudeConversationOptions {
|
|
224
|
+
baseUrl: string;
|
|
225
|
+
conversationId: string;
|
|
226
|
+
autoConnect?: boolean; // Default: true
|
|
227
|
+
reconnect?: ReconnectConfig;
|
|
228
|
+
onResult?: () => void; // Called when response completes
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Returns all ClaudeConnection properties and methods as React state.
|
|
233
|
+
|
|
234
|
+
## HTTP API
|
|
235
|
+
|
|
236
|
+
The package expects these server endpoints:
|
|
237
|
+
|
|
238
|
+
| Endpoint | Method | Purpose |
|
|
239
|
+
|----------|--------|---------|
|
|
240
|
+
| `/:id/status` | GET | Check conversation status |
|
|
241
|
+
| `/:id/start` | POST | Start new conversation |
|
|
242
|
+
| `/:id/connect` | GET | SSE stream for updates |
|
|
243
|
+
| `/:id/message` | POST | Send message |
|
|
244
|
+
| `/:id/stop` | POST | Stop generation |
|
|
245
|
+
| `/:id/clear` | POST | Clear session |
|
|
246
|
+
| `/:id/resume` | POST | Resume saved session |
|
|
247
|
+
| `/:id/prewarm` | POST | Prewarm conversation |
|
|
248
|
+
|
|
249
|
+
## Architecture
|
|
250
|
+
|
|
251
|
+
### Streaming
|
|
252
|
+
|
|
253
|
+
When Claude runs tools, the streaming behavior differs from simple responses:
|
|
254
|
+
|
|
255
|
+
1. `assistant` events stream the **full** response content
|
|
256
|
+
2. `result` events may only contain the **final** portion after tool execution
|
|
257
|
+
|
|
258
|
+
The state machine accumulates streaming content correctly. Always use `streamingSegments` for display, not just the `result` event.
|
|
259
|
+
|
|
260
|
+
### Session Persistence
|
|
261
|
+
|
|
262
|
+
Sessions are saved to disk after each message, enabling:
|
|
263
|
+
- Resume after page reload
|
|
264
|
+
- Resume after server restart
|
|
265
|
+
- Multi-device continuation
|
|
266
|
+
|
|
267
|
+
### Prewarming
|
|
268
|
+
|
|
269
|
+
Call `prewarm()` before the user is likely to start a conversation. This spawns Claude without sending a message, making the first response faster.
|
|
270
|
+
|
|
271
|
+
## License
|
|
272
|
+
|
|
273
|
+
MIT
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ClaudeConnection - Framework-agnostic core for Claude Code integration.
|
|
3
|
+
*
|
|
4
|
+
* Handles:
|
|
5
|
+
* - Dual-connection pattern: POST+SSE for start/resume, then EventSource for ongoing
|
|
6
|
+
* - Reconnection with exponential backoff
|
|
7
|
+
* - Session ID filtering to ignore stale events after clear
|
|
8
|
+
* - Streaming segments accumulation (text interleaved with tools)
|
|
9
|
+
*/
|
|
10
|
+
import { EventEmitter } from './event-emitter.js';
|
|
11
|
+
import { type ConnectionStatus } from './state-machine.js';
|
|
12
|
+
import type { Message, StreamSegment, ClaudeError, ReconnectConfig } from '../shared/types.js';
|
|
13
|
+
export interface ClaudeConnectionConfig {
|
|
14
|
+
baseUrl: string;
|
|
15
|
+
conversationId: string;
|
|
16
|
+
reconnect?: ReconnectConfig;
|
|
17
|
+
}
|
|
18
|
+
export interface ClaudeConnectionEvents {
|
|
19
|
+
stateChange: () => void;
|
|
20
|
+
message: (message: Message) => void;
|
|
21
|
+
streaming: (segments: StreamSegment[]) => void;
|
|
22
|
+
tool: (tool: {
|
|
23
|
+
name: string;
|
|
24
|
+
param?: string;
|
|
25
|
+
}) => void;
|
|
26
|
+
result: () => void;
|
|
27
|
+
error: (error: ClaudeError) => void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* ClaudeConnection manages the connection to a Claude conversation.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* const connection = new ClaudeConnection({
|
|
34
|
+
* baseUrl: '/api/claude',
|
|
35
|
+
* conversationId: 'user-123',
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* connection.on('message', (msg) => console.log(msg));
|
|
39
|
+
* connection.on('result', () => console.log('Response complete'));
|
|
40
|
+
* connection.connect();
|
|
41
|
+
*
|
|
42
|
+
* // Later
|
|
43
|
+
* await connection.send('Hello!');
|
|
44
|
+
*/
|
|
45
|
+
export declare class ClaudeConnection extends EventEmitter<ClaudeConnectionEvents> {
|
|
46
|
+
private config;
|
|
47
|
+
private reconnectConfig;
|
|
48
|
+
private eventSource;
|
|
49
|
+
private state;
|
|
50
|
+
private needNewTextSegment;
|
|
51
|
+
private reconnectAttempt;
|
|
52
|
+
constructor(config: ClaudeConnectionConfig);
|
|
53
|
+
get status(): ConnectionStatus;
|
|
54
|
+
get messages(): Message[];
|
|
55
|
+
get isStreaming(): boolean;
|
|
56
|
+
get streamingSegments(): StreamSegment[];
|
|
57
|
+
get hasPersistedSession(): boolean;
|
|
58
|
+
get lastError(): ClaudeError | null;
|
|
59
|
+
/**
|
|
60
|
+
* Check status and connect if active.
|
|
61
|
+
* Call this on mount to restore state.
|
|
62
|
+
*/
|
|
63
|
+
connect(): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Disconnect from the conversation.
|
|
66
|
+
*/
|
|
67
|
+
disconnect(): void;
|
|
68
|
+
/**
|
|
69
|
+
* Start a new conversation.
|
|
70
|
+
*/
|
|
71
|
+
start(initialMessage?: string): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Send a message in an active conversation.
|
|
74
|
+
*/
|
|
75
|
+
send(message: string): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Stop the current response generation (SIGINT).
|
|
78
|
+
*/
|
|
79
|
+
stop(): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Clear the session history and delete persisted session.
|
|
82
|
+
*/
|
|
83
|
+
clear(): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Resume a persisted session.
|
|
86
|
+
*/
|
|
87
|
+
resume(): Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* Prewarm the conversation for faster first response.
|
|
90
|
+
*/
|
|
91
|
+
prewarm(): Promise<void>;
|
|
92
|
+
private updateState;
|
|
93
|
+
private handleEvent;
|
|
94
|
+
private processResponseStream;
|
|
95
|
+
private connectEventSource;
|
|
96
|
+
private closeEventSource;
|
|
97
|
+
private attemptReconnect;
|
|
98
|
+
private calculateRetryDelay;
|
|
99
|
+
private sleep;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/client/connection.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAEL,KAAK,gBAAgB,EAStB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAY,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAQzG,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACpC,SAAS,EAAE,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,IAAI,CAAC;IAC/C,IAAI,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACvD,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,KAAK,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;CACrC;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,gBAAiB,SAAQ,YAAY,CAAC,sBAAsB,CAAC;IACxE,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,eAAe,CAA4B;IACnD,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,gBAAgB,CAAK;gBAEjB,MAAM,EAAE,sBAAsB;IAW1C,IAAI,MAAM,IAAI,gBAAgB,CAE7B;IAED,IAAI,QAAQ,IAAI,OAAO,EAAE,CAExB;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,iBAAiB,IAAI,aAAa,EAAE,CAEvC;IAED,IAAI,mBAAmB,IAAI,OAAO,CAEjC;IAED,IAAI,SAAS,IAAI,WAAW,GAAG,IAAI,CAElC;IAED;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA2B9B;;OAEG;IACH,UAAU,IAAI,IAAI;IAKlB;;OAEG;IACG,KAAK,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6BnD;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6B1C;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB5B;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IA2B7B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAY9B,OAAO,CAAC,WAAW;IA8BnB,OAAO,CAAC,WAAW;YAiBL,qBAAqB;IA8BnC,OAAO,CAAC,kBAAkB;IAoC1B,OAAO,CAAC,gBAAgB;YAOV,gBAAgB;IAmD9B,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,KAAK;CAGd"}
|