sub-agents-mcp 0.1.4 → 0.2.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.
Files changed (36) hide show
  1. package/README.md +253 -140
  2. package/dist/config/ServerConfig.d.ts +9 -0
  3. package/dist/config/ServerConfig.d.ts.map +1 -1
  4. package/dist/config/ServerConfig.js +17 -0
  5. package/dist/config/ServerConfig.js.map +1 -1
  6. package/dist/server/McpServer.d.ts +1 -0
  7. package/dist/server/McpServer.d.ts.map +1 -1
  8. package/dist/server/McpServer.js +18 -2
  9. package/dist/server/McpServer.js.map +1 -1
  10. package/dist/session/SessionHistoryFormatter.d.ts +32 -0
  11. package/dist/session/SessionHistoryFormatter.d.ts.map +1 -0
  12. package/dist/session/SessionHistoryFormatter.js +62 -0
  13. package/dist/session/SessionHistoryFormatter.js.map +1 -0
  14. package/dist/session/SessionManager.d.ts +158 -0
  15. package/dist/session/SessionManager.d.ts.map +1 -0
  16. package/dist/session/SessionManager.js +410 -0
  17. package/dist/session/SessionManager.js.map +1 -0
  18. package/dist/session/ToonConverter.d.ts +172 -0
  19. package/dist/session/ToonConverter.d.ts.map +1 -0
  20. package/dist/session/ToonConverter.js +593 -0
  21. package/dist/session/ToonConverter.js.map +1 -0
  22. package/dist/session/ToonUtils.d.ts +23 -0
  23. package/dist/session/ToonUtils.d.ts.map +1 -0
  24. package/dist/session/ToonUtils.js +75 -0
  25. package/dist/session/ToonUtils.js.map +1 -0
  26. package/dist/tools/RunAgentTool.d.ts +62 -4
  27. package/dist/tools/RunAgentTool.d.ts.map +1 -1
  28. package/dist/tools/RunAgentTool.js +223 -46
  29. package/dist/tools/RunAgentTool.js.map +1 -1
  30. package/dist/types/SessionData.d.ts +63 -0
  31. package/dist/types/SessionData.d.ts.map +1 -0
  32. package/dist/types/SessionData.js +3 -0
  33. package/dist/types/SessionData.js.map +1 -0
  34. package/dist/utils/Logger.js +2 -2
  35. package/dist/utils/Logger.js.map +1 -1
  36. package/package.json +1 -1
@@ -0,0 +1,410 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SessionManager = void 0;
37
+ const node_fs_1 = require("node:fs");
38
+ const fs = __importStar(require("node:fs/promises"));
39
+ const path = __importStar(require("node:path"));
40
+ /**
41
+ * Session manager for handling session data persistence.
42
+ *
43
+ * Manages session data storage, retrieval, and cleanup operations.
44
+ * Ensures secure file handling with directory traversal prevention.
45
+ */
46
+ class SessionManager {
47
+ /**
48
+ * Creates a new SessionManager instance.
49
+ *
50
+ * Initializes the session directory synchronously to ensure it exists
51
+ * before any operations are performed.
52
+ *
53
+ * @param config - Session configuration containing directory path and retention settings
54
+ */
55
+ constructor(config) {
56
+ this.config = config;
57
+ this.initializeSessionDirectory();
58
+ }
59
+ /**
60
+ * Initializes the session directory by creating it if it doesn't exist.
61
+ * Uses synchronous file operations to ensure directory exists before returning.
62
+ *
63
+ * @private
64
+ * @throws {Error} If directory creation fails
65
+ */
66
+ initializeSessionDirectory() {
67
+ try {
68
+ (0, node_fs_1.mkdirSync)(this.config.sessionDir, { recursive: true });
69
+ }
70
+ catch (error) {
71
+ const errorMessage = error instanceof Error ? error.message : String(error);
72
+ console.error(`Failed to create session directory at ${this.config.sessionDir}:`, errorMessage);
73
+ throw new Error(`Session directory initialization failed: ${errorMessage}`);
74
+ }
75
+ }
76
+ /**
77
+ * Validates a session ID to ensure it only contains allowed characters.
78
+ * Prevents directory traversal attacks by rejecting IDs with path manipulation characters.
79
+ *
80
+ * Session IDs must:
81
+ * - Not be empty
82
+ * - Contain only alphanumeric characters, hyphens (-), and underscores (_)
83
+ * - Not contain path traversal sequences (../, ./, etc.)
84
+ *
85
+ * @param sessionId - The session ID to validate
86
+ * @throws {Error} If the session ID contains invalid characters or is empty
87
+ */
88
+ validateSessionId(sessionId) {
89
+ if (!sessionId || sessionId.length === 0) {
90
+ throw new Error('Invalid session ID: Session ID cannot be empty');
91
+ }
92
+ // Only allow alphanumeric characters, hyphens, and underscores
93
+ const validPattern = /^[a-zA-Z0-9_-]+$/;
94
+ if (!validPattern.test(sessionId)) {
95
+ throw new Error(`Invalid session ID: "${sessionId}" contains invalid characters. Only alphanumeric characters, hyphens (-), and underscores (_) are allowed`);
96
+ }
97
+ }
98
+ /**
99
+ * Builds a file path for a session file following the naming convention:
100
+ * [session_id]_[agent_type].json
101
+ *
102
+ * Security measures:
103
+ * - Validates session ID before processing
104
+ * - Uses path.basename to strip directory components
105
+ * - Verifies final path is within session directory
106
+ *
107
+ * @param sessionId - The session identifier (validated for security)
108
+ * @param agentType - The type of agent (e.g., 'rule-advisor', 'quality-fixer')
109
+ * @returns The full file path for the session file
110
+ * @throws {Error} If the session ID is invalid or if path traversal is detected
111
+ */
112
+ buildFilePath(sessionId, agentType) {
113
+ // Validate session ID to prevent directory traversal
114
+ this.validateSessionId(sessionId);
115
+ // Build filename following the naming convention
116
+ const fileName = `${sessionId}_${agentType}.json`;
117
+ // Strip any directory components for additional security
118
+ const safeFileName = path.basename(fileName);
119
+ // Join with session directory
120
+ const filePath = path.join(this.config.sessionDir, safeFileName);
121
+ // Verify the resolved path stays within the session directory
122
+ const normalizedPath = path.normalize(filePath);
123
+ const normalizedSessionDir = path.normalize(this.config.sessionDir);
124
+ if (!normalizedPath.startsWith(normalizedSessionDir)) {
125
+ throw new Error(`Invalid file path: Attempted directory traversal detected. Expected path within "${normalizedSessionDir}", got "${normalizedPath}"`);
126
+ }
127
+ return filePath;
128
+ }
129
+ /**
130
+ * Saves session data to a JSON file.
131
+ *
132
+ * If a session file already exists, the new request-response pair is appended
133
+ * to the existing history. Otherwise, a new session file is created.
134
+ *
135
+ * Error handling follows the error isolation principle:
136
+ * - Errors are logged but not thrown
137
+ * - The main execution flow continues even if session save fails
138
+ *
139
+ * Security features:
140
+ * - Session ID validation prevents directory traversal
141
+ * - File permissions are set to 0o600 (owner read/write only)
142
+ * - All file paths are verified to stay within session directory
143
+ *
144
+ * @param sessionId - The session identifier (alphanumeric, hyphens, underscores only)
145
+ * @param request - The request object containing agent, prompt, and optional parameters
146
+ * @param response - The response object containing stdout, stderr, exitCode, and executionTime
147
+ *
148
+ * @example
149
+ * await sessionManager.saveSession(
150
+ * 'session-001',
151
+ * { agent: 'rule-advisor', prompt: 'Analyze code' },
152
+ * { stdout: 'Analysis complete', stderr: '', exitCode: 0, executionTime: 100 }
153
+ * )
154
+ */
155
+ async saveSession(sessionId, request, response) {
156
+ try {
157
+ // Validate session ID to prevent directory traversal
158
+ this.validateSessionId(sessionId);
159
+ // Create session entry with current timestamp
160
+ const sessionEntry = {
161
+ timestamp: new Date(),
162
+ request,
163
+ response,
164
+ };
165
+ // Build or update session data
166
+ const sessionData = await this.buildSessionData(sessionId, request.agent, sessionEntry);
167
+ // Build file path (same file for same session_id + agent_type)
168
+ const filePath = this.buildFilePath(sessionId, request.agent);
169
+ // Serialize to JSON with pretty printing
170
+ const jsonContent = JSON.stringify(sessionData, null, 2);
171
+ // Write to file with restrictive permissions
172
+ await fs.writeFile(filePath, jsonContent, { mode: 0o600 });
173
+ }
174
+ catch (error) {
175
+ // Log error but do not throw - error isolation principle
176
+ this.logSaveError(sessionId, request.agent, error);
177
+ }
178
+ }
179
+ /**
180
+ * Builds session data by either creating a new session or appending to an existing one.
181
+ *
182
+ * @param sessionId - The session identifier
183
+ * @param agentType - The agent type
184
+ * @param sessionEntry - The new session entry to add
185
+ * @returns Complete session data ready to be saved
186
+ */
187
+ async buildSessionData(sessionId, agentType, sessionEntry) {
188
+ const existingSession = await this.loadExistingSession(sessionId, agentType);
189
+ if (existingSession) {
190
+ // Append to existing session history
191
+ return {
192
+ ...existingSession,
193
+ history: [...existingSession.history, sessionEntry],
194
+ lastUpdatedAt: new Date(),
195
+ };
196
+ }
197
+ // Create new session with initial entry
198
+ return {
199
+ sessionId,
200
+ agentType,
201
+ history: [sessionEntry],
202
+ createdAt: new Date(),
203
+ lastUpdatedAt: new Date(),
204
+ };
205
+ }
206
+ /**
207
+ * Logs structured error information when session save fails.
208
+ *
209
+ * @param sessionId - The session identifier
210
+ * @param agentType - The agent type
211
+ * @param error - The error that occurred
212
+ */
213
+ logSaveError(sessionId, agentType, error) {
214
+ const errorMessage = error instanceof Error ? error.message : String(error);
215
+ console.error('Failed to save session:', {
216
+ sessionId,
217
+ agentType,
218
+ error: errorMessage,
219
+ });
220
+ }
221
+ /**
222
+ * Loads a session by session ID and agent type.
223
+ *
224
+ * Searches for the most recent session file matching the session ID and agent type.
225
+ * If multiple files exist with the same session ID and agent type, returns the one with the latest timestamp.
226
+ *
227
+ * **CRITICAL**: Sub-agent isolation is enforced - sessions are isolated by agent type.
228
+ * Same session_id with different agent_type will return different sessions.
229
+ *
230
+ * Error handling follows the error isolation principle:
231
+ * - Returns null if session file does not exist
232
+ * - Returns null if JSON parsing fails
233
+ * - Errors are logged but not thrown
234
+ *
235
+ * @param sessionId - The session identifier (alphanumeric, hyphens, underscores only)
236
+ * @param agentType - The agent type to filter sessions (e.g., 'rule-advisor', 'task-executor')
237
+ * @returns The session data if found, null otherwise
238
+ *
239
+ * @example
240
+ * const session = await sessionManager.loadSession('session-001', 'rule-advisor')
241
+ * if (session) {
242
+ * console.log(`Loaded session with ${session.history.length} entries`)
243
+ * }
244
+ */
245
+ async loadSession(sessionId, agentType) {
246
+ try {
247
+ // Validate session ID to prevent directory traversal
248
+ this.validateSessionId(sessionId);
249
+ // Build expected file path
250
+ // File naming convention: [session_id]_[agent_type].json
251
+ const filePath = this.buildFilePath(sessionId, agentType);
252
+ // Check if file exists
253
+ try {
254
+ await fs.access(filePath);
255
+ }
256
+ catch {
257
+ // File does not exist
258
+ return null;
259
+ }
260
+ const fileContent = await fs.readFile(filePath, 'utf-8');
261
+ const sessionData = JSON.parse(fileContent);
262
+ // Convert date strings back to Date objects
263
+ return {
264
+ ...sessionData,
265
+ createdAt: new Date(sessionData.createdAt),
266
+ lastUpdatedAt: new Date(sessionData.lastUpdatedAt),
267
+ history: sessionData.history.map((entry) => ({
268
+ ...entry,
269
+ timestamp: new Date(entry.timestamp),
270
+ })),
271
+ };
272
+ }
273
+ catch (error) {
274
+ // Log error but return null - error isolation principle
275
+ this.logLoadError(sessionId, error);
276
+ return null;
277
+ }
278
+ }
279
+ /**
280
+ * Loads an existing session file if it exists.
281
+ *
282
+ * Searches for the most recent session file matching the session ID and agent type.
283
+ *
284
+ * @param sessionId - The session identifier
285
+ * @param agentType - The agent type
286
+ * @returns The session data if found, null otherwise
287
+ */
288
+ async loadExistingSession(sessionId, agentType) {
289
+ try {
290
+ // Build expected file path
291
+ // File naming convention: [session_id]_[agent_type].json
292
+ const filePath = this.buildFilePath(sessionId, agentType);
293
+ // Check if file exists
294
+ try {
295
+ await fs.access(filePath);
296
+ }
297
+ catch {
298
+ // File does not exist
299
+ return null;
300
+ }
301
+ const fileContent = await fs.readFile(filePath, 'utf-8');
302
+ const sessionData = JSON.parse(fileContent);
303
+ // Convert date strings back to Date objects
304
+ return {
305
+ ...sessionData,
306
+ createdAt: new Date(sessionData.createdAt),
307
+ lastUpdatedAt: new Date(sessionData.lastUpdatedAt),
308
+ history: sessionData.history.map((entry) => ({
309
+ ...entry,
310
+ timestamp: new Date(entry.timestamp),
311
+ })),
312
+ };
313
+ }
314
+ catch {
315
+ return null;
316
+ }
317
+ }
318
+ /**
319
+ * Logs structured error information when session load fails.
320
+ *
321
+ * @param sessionId - The session identifier
322
+ * @param error - The error that occurred
323
+ */
324
+ logLoadError(sessionId, error) {
325
+ const errorMessage = error instanceof Error ? error.message : String(error);
326
+ console.error('Failed to load session:', {
327
+ sessionId,
328
+ error: errorMessage,
329
+ });
330
+ }
331
+ /**
332
+ * Cleans up old session files based on retention period.
333
+ *
334
+ * Deletes session files older than the configured retention period (default 7 days).
335
+ * This is a best-effort operation - errors during deletion are logged but not thrown.
336
+ *
337
+ * Error handling follows the error isolation principle:
338
+ * - Individual file deletion failures do not stop the cleanup process
339
+ * - All errors are logged for debugging purposes
340
+ * - The method completes successfully even if some files cannot be deleted
341
+ *
342
+ * @example
343
+ * // Cleanup old sessions (runs silently, logs errors only)
344
+ * await sessionManager.cleanupOldSessions()
345
+ */
346
+ async cleanupOldSessions() {
347
+ try {
348
+ // List all files in the session directory
349
+ const files = await fs.readdir(this.config.sessionDir);
350
+ // Calculate cutoff time based on retention period
351
+ const retentionMs = this.config.retentionDays * 24 * 60 * 60 * 1000;
352
+ const cutoffTime = Date.now() - retentionMs;
353
+ let deletedCount = 0;
354
+ const deletedFiles = [];
355
+ // Process each file
356
+ for (const file of files) {
357
+ // Skip non-JSON files
358
+ if (!file.endsWith('.json')) {
359
+ continue;
360
+ }
361
+ const filePath = path.join(this.config.sessionDir, file);
362
+ try {
363
+ // Get file stats to check modification time
364
+ const stats = await fs.stat(filePath);
365
+ // Check if file is older than retention period
366
+ if (stats.mtimeMs < cutoffTime) {
367
+ try {
368
+ // Delete the old file
369
+ await fs.unlink(filePath);
370
+ deletedCount++;
371
+ deletedFiles.push(file);
372
+ }
373
+ catch (deleteError) {
374
+ // Log individual file deletion error but continue
375
+ const errorMessage = deleteError instanceof Error ? deleteError.message : String(deleteError);
376
+ console.error(`Failed to delete old session file: ${file}`, {
377
+ file,
378
+ error: errorMessage,
379
+ });
380
+ }
381
+ }
382
+ }
383
+ catch (statError) {
384
+ // Log stat error but continue with next file
385
+ const errorMessage = statError instanceof Error ? statError.message : String(statError);
386
+ console.error(`Failed to stat session file: ${file}`, {
387
+ file,
388
+ error: errorMessage,
389
+ });
390
+ }
391
+ }
392
+ // Log cleanup summary
393
+ if (deletedCount > 0) {
394
+ console.log('Cleaned up old session files:', {
395
+ deletedCount,
396
+ deletedFiles,
397
+ });
398
+ }
399
+ }
400
+ catch (error) {
401
+ // Log error but do not throw - error isolation principle
402
+ const errorMessage = error instanceof Error ? error.message : String(error);
403
+ console.error('Failed to cleanup old sessions:', {
404
+ error: errorMessage,
405
+ });
406
+ }
407
+ }
408
+ }
409
+ exports.SessionManager = SessionManager;
410
+ //# sourceMappingURL=SessionManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionManager.js","sourceRoot":"","sources":["../../src/session/SessionManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * TOON (Token Optimized Object Notation) converter utility.
3
+ *
4
+ * Converts JSON data to TOON format to reduce token consumption by 30-60%.
5
+ *
6
+ * Key optimizations:
7
+ * - Shortened key names (sessionId → sid, timestamp → ts, etc.)
8
+ * - Compact timestamp format (removes separators: 20250121 120000)
9
+ * - Filters out empty strings and empty arrays
10
+ * - Inline object representation {key:value,key2:value2}
11
+ * - Array format [count,]{item1,item2}
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const sessionData = {
16
+ * sessionId: 'abc123',
17
+ * agentType: 'rule-advisor',
18
+ * history: [...],
19
+ * createdAt: new Date('2025-01-21T12:00:00Z'),
20
+ * lastUpdatedAt: new Date('2025-01-21T12:00:00Z')
21
+ * }
22
+ * const toonStr = ToonConverter.convertToToon(sessionData)
23
+ * // Output: sid:abc123,agt:rule-advisor,h:[1,]{...},cat:20250121 120000,uat:20250121 120000
24
+ * ```
25
+ */
26
+ export declare class ToonConverter {
27
+ /**
28
+ * Converts JSON-compatible data to TOON format.
29
+ *
30
+ * TOON format features:
31
+ * - Removes quotes from keys
32
+ * - Uses compact array notation: [length,] { items }
33
+ * - Reduces unnecessary brackets and commas
34
+ * - Maintains data structure and readability
35
+ *
36
+ * @param jsonData - JSON-compatible data to convert
37
+ * @returns TOON-formatted string
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * const data = { sessionId: 'abc123', agentType: 'rule-advisor' }
42
+ * const toon = ToonConverter.convertToToon(data)
43
+ * // Returns: "sessionId: abc123\nagentType: rule-advisor"
44
+ * ```
45
+ */
46
+ static convertToToon(jsonData: unknown): string;
47
+ /**
48
+ * Map of common long keys to short keys for token reduction.
49
+ * @private
50
+ */
51
+ private static readonly KEY_MAP;
52
+ /**
53
+ * Recursively converts a value to TOON format string.
54
+ *
55
+ * @param value - Value to convert
56
+ * @param depth - Current nesting depth for indentation
57
+ * @returns TOON-formatted string
58
+ * @private
59
+ */
60
+ private static toToonString;
61
+ /**
62
+ * Converts an object to compact TOON format (for array items).
63
+ *
64
+ * @param value - Object to convert
65
+ * @returns Compact TOON string
66
+ * @private
67
+ */
68
+ private static toToonObjectCompact;
69
+ /**
70
+ * Formats a Date object to compact timestamp format.
71
+ *
72
+ * Converts ISO 8601 timestamp to compact format:
73
+ * - Input: 2025-01-21T12:00:00.000Z
74
+ * - Output: 20250121 120000
75
+ *
76
+ * This reduces token count by removing separators and milliseconds.
77
+ *
78
+ * @param date - Date object to format
79
+ * @returns Compact timestamp string
80
+ * @private
81
+ */
82
+ private static formatCompactTimestamp;
83
+ /**
84
+ * Checks if a string value needs to be quoted in TOON format.
85
+ *
86
+ * Strings are quoted if they contain:
87
+ * - Spaces
88
+ * - Special characters (except hyphen and underscore)
89
+ * - Start with a number
90
+ * - Reserved keywords (null, undefined, true, false)
91
+ *
92
+ * @param value - String value to check
93
+ * @returns True if the string needs quotes
94
+ * @private
95
+ */
96
+ private static needsQuotes;
97
+ /**
98
+ * Converts TOON format string back to JSON-compatible data.
99
+ *
100
+ * This method reverses the convertToToon operation, restoring the original data structure.
101
+ * - Expands short keys back to full keys
102
+ * - Parses compact timestamps back to Date objects
103
+ * - Reconstructs arrays and objects from TOON notation
104
+ *
105
+ * @param toonString - TOON-formatted string to convert
106
+ * @returns JSON-compatible data
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * const toonStr = "sid:abc123,agt:rule-advisor,h:[1,]{ts:20250121 120000},cat:20250121 120000"
111
+ * const data = ToonConverter.convertToJson(toonStr)
112
+ * // Returns: { sessionId: 'abc123', agentType: 'rule-advisor', history: [...], ... }
113
+ * ```
114
+ */
115
+ static convertToJson(toonString: string): unknown;
116
+ /**
117
+ * Reverse map from short keys to original keys.
118
+ * @private
119
+ */
120
+ private static readonly REVERSE_KEY_MAP;
121
+ /**
122
+ * Parses a TOON format string into a JSON-compatible value.
123
+ *
124
+ * @param input - TOON string to parse
125
+ * @returns Parsed value
126
+ * @private
127
+ */
128
+ private static parseToonString;
129
+ /**
130
+ * Parses a compact timestamp string back to Date object.
131
+ *
132
+ * Converts compact format to ISO 8601:
133
+ * - Input: 20250121 120000
134
+ * - Output: Date('2025-01-21T12:00:00.000Z')
135
+ *
136
+ * @param timestamp - Compact timestamp string
137
+ * @returns Date object
138
+ * @private
139
+ */
140
+ private static parseCompactTimestamp;
141
+ /**
142
+ * Parses TOON array notation.
143
+ *
144
+ * Format: [length,]item1,item2,item3
145
+ * or [length,]{item1},{item2}
146
+ *
147
+ * @param input - TOON array string
148
+ * @returns Parsed array
149
+ * @private
150
+ */
151
+ private static parseArray;
152
+ /**
153
+ * Parses TOON object notation.
154
+ *
155
+ * Format: key1:value1,key2:value2
156
+ * or {key1:value1,key2:value2}
157
+ *
158
+ * @param input - TOON object string
159
+ * @returns Parsed object
160
+ * @private
161
+ */
162
+ private static parseObject;
163
+ /**
164
+ * Parses a key:value pair and adds it to the result object.
165
+ *
166
+ * @param pair - Key:value pair string
167
+ * @param result - Result object to add to
168
+ * @private
169
+ */
170
+ private static parseKeyValue;
171
+ }
172
+ //# sourceMappingURL=ToonConverter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToonConverter.d.ts","sourceRoot":"","sources":["../../src/session/ToonConverter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,qBAAa,aAAa;IACxB;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM;IAe/C;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAa9B;IAED;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,YAAY;IAiE3B;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAmDlC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,MAAM,CAAC,sBAAsB;IASrC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAkB1B;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAgBjD;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAEtC;IAED;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;IAuD9B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAkBpC;;;;;;;;;OASG;IACH,OAAO,CAAC,MAAM,CAAC,UAAU;IAqEzB;;;;;;;;;OASG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAkG1B;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;CA2C7B"}