claude-code-acp-ts 0.16.1 → 0.24.3

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/dist/tools.js CHANGED
@@ -1,32 +1,28 @@
1
- import { SYSTEM_REMINDER } from "./mcp-server.js";
2
- import * as diff from "diff";
3
- const acpUnqualifiedToolNames = {
4
- read: "Read",
5
- edit: "Edit",
6
- write: "Write",
7
- bash: "Bash",
8
- killShell: "KillShell",
9
- bashOutput: "BashOutput",
10
- };
11
- export const ACP_TOOL_NAME_PREFIX = "mcp__acp__";
12
- export const acpToolNames = {
13
- read: ACP_TOOL_NAME_PREFIX + acpUnqualifiedToolNames.read,
14
- edit: ACP_TOOL_NAME_PREFIX + acpUnqualifiedToolNames.edit,
15
- write: ACP_TOOL_NAME_PREFIX + acpUnqualifiedToolNames.write,
16
- bash: ACP_TOOL_NAME_PREFIX + acpUnqualifiedToolNames.bash,
17
- killShell: ACP_TOOL_NAME_PREFIX + acpUnqualifiedToolNames.killShell,
18
- bashOutput: ACP_TOOL_NAME_PREFIX + acpUnqualifiedToolNames.bashOutput,
19
- };
20
- export const EDIT_TOOL_NAMES = [acpToolNames.edit, acpToolNames.write];
21
- export function toolInfoFromToolUse(toolUse) {
1
+ import path from "node:path";
2
+ /**
3
+ * Convert an absolute file path to a project-relative path for display.
4
+ * Returns the original path if it's outside the project directory or if no cwd is provided.
5
+ */
6
+ export function toDisplayPath(filePath, cwd) {
7
+ if (!cwd)
8
+ return filePath;
9
+ const resolvedCwd = path.resolve(cwd);
10
+ const resolvedFile = path.resolve(filePath);
11
+ if (resolvedFile.startsWith(resolvedCwd + path.sep) || resolvedFile === resolvedCwd) {
12
+ return path.relative(resolvedCwd, resolvedFile);
13
+ }
14
+ return filePath;
15
+ }
16
+ export function toolInfoFromToolUse(toolUse, supportsTerminalOutput = false, cwd) {
22
17
  const name = toolUse.name;
23
- const input = toolUse.input;
24
18
  switch (name) {
25
- case "Task":
19
+ case "Agent":
20
+ case "Task": {
21
+ const input = toolUse.input;
26
22
  return {
27
23
  title: input?.description ? input.description : "Task",
28
24
  kind: "think",
29
- content: input && input.prompt
25
+ content: input && "prompt" in input
30
26
  ? [
31
27
  {
32
28
  type: "content",
@@ -35,119 +31,50 @@ export function toolInfoFromToolUse(toolUse) {
35
31
  ]
36
32
  : [],
37
33
  };
38
- case "NotebookRead":
39
- return {
40
- title: input?.notebook_path ? `Read Notebook ${input.notebook_path}` : "Read Notebook",
41
- kind: "read",
42
- content: [],
43
- locations: input?.notebook_path ? [{ path: input.notebook_path }] : [],
44
- };
45
- case "NotebookEdit":
46
- return {
47
- title: input?.notebook_path ? `Edit Notebook ${input.notebook_path}` : "Edit Notebook",
48
- kind: "edit",
49
- content: input && input.new_source
50
- ? [
51
- {
52
- type: "content",
53
- content: { type: "text", text: input.new_source },
54
- },
55
- ]
56
- : [],
57
- locations: input?.notebook_path ? [{ path: input.notebook_path }] : [],
58
- };
59
- case "Bash":
60
- case acpToolNames.bash:
61
- return {
62
- title: input?.command ? "`" + input.command.replaceAll("`", "\\`") + "`" : "Terminal",
63
- kind: "execute",
64
- content: input && input.description
65
- ? [
66
- {
67
- type: "content",
68
- content: { type: "text", text: input.description },
69
- },
70
- ]
71
- : [],
72
- };
73
- case "BashOutput":
74
- case acpToolNames.bashOutput:
75
- return {
76
- title: "Tail Logs",
77
- kind: "execute",
78
- content: [],
79
- };
80
- case "KillShell":
81
- case acpToolNames.killShell:
34
+ }
35
+ case "Bash": {
36
+ const input = toolUse.input;
82
37
  return {
83
- title: "Kill Process",
38
+ title: input?.command ? input.command : "Terminal",
84
39
  kind: "execute",
85
- content: [],
40
+ content: supportsTerminalOutput
41
+ ? [{ type: "terminal", terminalId: toolUse.id }]
42
+ : input && input.description
43
+ ? [
44
+ {
45
+ type: "content",
46
+ content: { type: "text", text: input.description },
47
+ },
48
+ ]
49
+ : [],
86
50
  };
87
- case acpToolNames.read: {
51
+ }
52
+ case "Read": {
53
+ const input = toolUse.input;
88
54
  let limit = "";
89
- if (input.limit) {
90
- limit =
91
- " (" + ((input.offset ?? 0) + 1) + " - " + ((input.offset ?? 0) + input.limit) + ")";
55
+ if (input.limit && input.limit > 0) {
56
+ limit = " (" + (input.offset ?? 1) + " - " + ((input.offset ?? 1) + input.limit - 1) + ")";
92
57
  }
93
58
  else if (input.offset) {
94
- limit = " (from line " + (input.offset + 1) + ")";
59
+ limit = " (from line " + input.offset + ")";
95
60
  }
61
+ const displayPath = input.file_path ? toDisplayPath(input.file_path, cwd) : "File";
96
62
  return {
97
- title: "Read " + (input.file_path ?? "File") + limit,
63
+ title: "Read " + displayPath + limit,
98
64
  kind: "read",
99
65
  locations: input.file_path
100
66
  ? [
101
67
  {
102
68
  path: input.file_path,
103
- line: input.offset ?? 0,
69
+ line: input.offset ?? 1,
104
70
  },
105
71
  ]
106
72
  : [],
107
73
  content: [],
108
74
  };
109
75
  }
110
- case "Read":
111
- return {
112
- title: "Read File",
113
- kind: "read",
114
- content: [],
115
- locations: input.file_path
116
- ? [
117
- {
118
- path: input.file_path,
119
- line: input.offset ?? 0,
120
- },
121
- ]
122
- : [],
123
- };
124
- case "LS":
125
- return {
126
- title: `List the ${input?.path ? "`" + input.path + "`" : "current"} directory's contents`,
127
- kind: "search",
128
- content: [],
129
- locations: [],
130
- };
131
- case acpToolNames.edit:
132
- case "Edit": {
133
- const path = input?.file_path ?? input?.file_path;
134
- return {
135
- title: path ? `Edit \`${path}\`` : "Edit",
136
- kind: "edit",
137
- content: input && path
138
- ? [
139
- {
140
- type: "diff",
141
- path,
142
- oldText: input.old_string ?? null,
143
- newText: input.new_string ?? "",
144
- },
145
- ]
146
- : [],
147
- locations: path ? [{ path }] : undefined,
148
- };
149
- }
150
- case acpToolNames.write: {
76
+ case "Write": {
77
+ const input = toolUse.input;
151
78
  let content = [];
152
79
  if (input && input.file_path) {
153
80
  content = [
@@ -167,30 +94,37 @@ export function toolInfoFromToolUse(toolUse) {
167
94
  },
168
95
  ];
169
96
  }
97
+ const displayPath = input?.file_path ? toDisplayPath(input.file_path, cwd) : undefined;
170
98
  return {
171
- title: input?.file_path ? `Write ${input.file_path}` : "Write",
99
+ title: displayPath ? `Write ${displayPath}` : "Write",
172
100
  kind: "edit",
173
101
  content,
174
102
  locations: input?.file_path ? [{ path: input.file_path }] : [],
175
103
  };
176
104
  }
177
- case "Write":
105
+ case "Edit": {
106
+ const input = toolUse.input;
107
+ let content = [];
108
+ if (input && input.file_path && (input.old_string || input.new_string)) {
109
+ content = [
110
+ {
111
+ type: "diff",
112
+ path: input.file_path,
113
+ oldText: input.old_string || null,
114
+ newText: input.new_string ?? "",
115
+ },
116
+ ];
117
+ }
118
+ const displayPath = input?.file_path ? toDisplayPath(input.file_path, cwd) : undefined;
178
119
  return {
179
- title: input?.file_path ? `Write ${input.file_path}` : "Write",
120
+ title: displayPath ? `Edit ${displayPath}` : "Edit",
180
121
  kind: "edit",
181
- content: input && input.file_path
182
- ? [
183
- {
184
- type: "diff",
185
- path: input.file_path,
186
- oldText: null,
187
- newText: input.content,
188
- },
189
- ]
190
- : [],
122
+ content,
191
123
  locations: input?.file_path ? [{ path: input.file_path }] : [],
192
124
  };
125
+ }
193
126
  case "Glob": {
127
+ const input = toolUse.input;
194
128
  let label = "Find";
195
129
  if (input.path) {
196
130
  label += ` \`${input.path}\``;
@@ -206,6 +140,7 @@ export function toolInfoFromToolUse(toolUse) {
206
140
  };
207
141
  }
208
142
  case "Grep": {
143
+ const input = toolUse.input;
209
144
  let label = "grep";
210
145
  if (input["-i"]) {
211
146
  label += " -i";
@@ -224,13 +159,13 @@ export function toolInfoFromToolUse(toolUse) {
224
159
  }
225
160
  if (input.output_mode) {
226
161
  switch (input.output_mode) {
227
- case "FilesWithMatches":
162
+ case "files_with_matches":
228
163
  label += " -l";
229
164
  break;
230
- case "Count":
165
+ case "count":
231
166
  label += " -c";
232
167
  break;
233
- case "Content":
168
+ case "content":
234
169
  default:
235
170
  break;
236
171
  }
@@ -259,7 +194,8 @@ export function toolInfoFromToolUse(toolUse) {
259
194
  content: [],
260
195
  };
261
196
  }
262
- case "WebFetch":
197
+ case "WebFetch": {
198
+ const input = toolUse.input;
263
199
  return {
264
200
  title: input?.url ? `Fetch ${input.url}` : "Fetch",
265
201
  kind: "fetch",
@@ -272,7 +208,9 @@ export function toolInfoFromToolUse(toolUse) {
272
208
  ]
273
209
  : [],
274
210
  };
211
+ }
275
212
  case "WebSearch": {
213
+ const input = toolUse.input;
276
214
  let label = `"${input.query}"`;
277
215
  if (input.allowed_domains && input.allowed_domains.length > 0) {
278
216
  label += ` (allowed: ${input.allowed_domains.join(", ")})`;
@@ -286,7 +224,8 @@ export function toolInfoFromToolUse(toolUse) {
286
224
  content: [],
287
225
  };
288
226
  }
289
- case "TodoWrite":
227
+ case "TodoWrite": {
228
+ const input = toolUse.input;
290
229
  return {
291
230
  title: Array.isArray(input?.todos)
292
231
  ? `Update TODOs: ${input.todos.map((todo) => todo.content).join(", ")}`
@@ -294,15 +233,19 @@ export function toolInfoFromToolUse(toolUse) {
294
233
  kind: "think",
295
234
  content: [],
296
235
  };
297
- case "ExitPlanMode":
236
+ }
237
+ case "ExitPlanMode": {
238
+ const planInput = toolUse.input;
298
239
  return {
299
240
  title: "Ready to code?",
300
241
  kind: "switch_mode",
301
- content: input && input.plan
302
- ? [{ type: "content", content: { type: "text", text: input.plan } }]
242
+ content: planInput?.plan
243
+ ? [{ type: "content", content: { type: "text", text: planInput.plan } }]
303
244
  : [],
304
245
  };
246
+ }
305
247
  case "Other": {
248
+ const input = toolUse.input;
306
249
  let output;
307
250
  try {
308
251
  output = JSON.stringify(input, null, 2);
@@ -332,7 +275,7 @@ export function toolInfoFromToolUse(toolUse) {
332
275
  };
333
276
  }
334
277
  }
335
- export function toolUpdateFromToolResult(toolResult, toolUse) {
278
+ export function toolUpdateFromToolResult(toolResult, toolUse, supportsTerminalOutput = false) {
336
279
  if ("is_error" in toolResult &&
337
280
  toolResult.is_error &&
338
281
  toolResult.content &&
@@ -342,7 +285,6 @@ export function toolUpdateFromToolResult(toolResult, toolUse) {
342
285
  }
343
286
  switch (toolUse?.name) {
344
287
  case "Read":
345
- case acpToolNames.read:
346
288
  if (Array.isArray(toolResult.content) && toolResult.content.length > 0) {
347
289
  return {
348
290
  content: toolResult.content.map((content) => ({
@@ -350,9 +292,9 @@ export function toolUpdateFromToolResult(toolResult, toolUse) {
350
292
  content: content.type === "text"
351
293
  ? {
352
294
  type: "text",
353
- text: markdownEscape(content.text.replace(SYSTEM_REMINDER, "")),
295
+ text: markdownEscape(content.text),
354
296
  }
355
- : content,
297
+ : toAcpContentBlock(content, false),
356
298
  })),
357
299
  };
358
300
  }
@@ -363,83 +305,82 @@ export function toolUpdateFromToolResult(toolResult, toolUse) {
363
305
  type: "content",
364
306
  content: {
365
307
  type: "text",
366
- text: markdownEscape(toolResult.content.replace(SYSTEM_REMINDER, "")),
308
+ text: markdownEscape(toolResult.content),
367
309
  },
368
310
  },
369
311
  ],
370
312
  };
371
313
  }
372
314
  return {};
373
- case acpToolNames.edit: {
374
- const content = [];
375
- const locations = [];
376
- if (Array.isArray(toolResult.content) &&
377
- toolResult.content.length > 0 &&
378
- "text" in toolResult.content[0] &&
379
- typeof toolResult.content[0].text === "string") {
380
- const patches = diff.parsePatch(toolResult.content[0].text);
381
- console.error(JSON.stringify(patches));
382
- for (const { oldFileName, newFileName, hunks } of patches) {
383
- for (const { lines, newStart } of hunks) {
384
- const oldText = [];
385
- const newText = [];
386
- for (const line of lines) {
387
- if (line.startsWith("-")) {
388
- oldText.push(line.slice(1));
389
- }
390
- else if (line.startsWith("+")) {
391
- newText.push(line.slice(1));
392
- }
393
- else {
394
- oldText.push(line.slice(1));
395
- newText.push(line.slice(1));
396
- }
397
- }
398
- if (oldText.length > 0 || newText.length > 0) {
399
- locations.push({ path: newFileName || oldFileName, line: newStart });
400
- content.push({
401
- type: "diff",
402
- path: newFileName || oldFileName,
403
- oldText: oldText.join("\n") || null,
404
- newText: newText.join("\n"),
405
- });
406
- }
407
- }
408
- }
315
+ case "Bash": {
316
+ const result = toolResult.content;
317
+ const terminalId = "tool_use_id" in toolResult ? String(toolResult.tool_use_id) : "";
318
+ const isError = "is_error" in toolResult && toolResult.is_error;
319
+ // Extract output and exit code from either format:
320
+ // 1. BetaBashCodeExecutionResultBlock: { type: "bash_code_execution_result", stdout, stderr, return_code }
321
+ // 2. Plain string content from a regular tool_result
322
+ // 3. Array content (e.g. [{ type: "text", text: "..." }])
323
+ let output = "";
324
+ let exitCode = isError ? 1 : 0;
325
+ if (result &&
326
+ typeof result === "object" &&
327
+ "type" in result &&
328
+ result.type === "bash_code_execution_result") {
329
+ const bashResult = result;
330
+ output = [bashResult.stdout, bashResult.stderr].filter(Boolean).join("\n");
331
+ exitCode = bashResult.return_code;
409
332
  }
410
- const result = {};
411
- if (content.length > 0) {
412
- result.content = content;
333
+ else if (typeof result === "string") {
334
+ output = result;
413
335
  }
414
- if (locations.length > 0) {
415
- result.locations = locations;
336
+ else if (Array.isArray(result) &&
337
+ result.length > 0 &&
338
+ "text" in result[0] &&
339
+ typeof result[0].text === "string") {
340
+ output = result.map((c) => c.text).join("\n");
341
+ }
342
+ if (supportsTerminalOutput) {
343
+ return {
344
+ content: [{ type: "terminal", terminalId }],
345
+ _meta: {
346
+ terminal_info: {
347
+ terminal_id: terminalId,
348
+ },
349
+ terminal_output: {
350
+ terminal_id: terminalId,
351
+ data: output,
352
+ },
353
+ terminal_exit: {
354
+ terminal_id: terminalId,
355
+ exit_code: exitCode,
356
+ signal: null,
357
+ },
358
+ },
359
+ };
416
360
  }
417
- return result;
361
+ // Fallback: format output as a code block without terminal _meta
362
+ if (output.trim()) {
363
+ return {
364
+ content: [
365
+ {
366
+ type: "content",
367
+ content: {
368
+ type: "text",
369
+ text: `\`\`\`console\n${output.trimEnd()}\n\`\`\``,
370
+ },
371
+ },
372
+ ],
373
+ };
374
+ }
375
+ return {};
418
376
  }
419
- case acpToolNames.bash:
420
- case "edit":
421
- case "Edit":
422
- case acpToolNames.write:
377
+ case "Edit": // Edit is handled in hooks
423
378
  case "Write": {
424
379
  return {};
425
380
  }
426
381
  case "ExitPlanMode": {
427
382
  return { title: "Exited Plan Mode" };
428
383
  }
429
- case "Task":
430
- case "NotebookEdit":
431
- case "NotebookRead":
432
- case "TodoWrite":
433
- case "exit_plan_mode":
434
- case "Bash":
435
- case "BashOutput":
436
- case "KillBash":
437
- case "LS":
438
- case "Glob":
439
- case "Grep":
440
- case "WebFetch":
441
- case "WebSearch":
442
- case "Other":
443
384
  default: {
444
385
  return toAcpContentUpdate(toolResult.content, "is_error" in toolResult ? toolResult.is_error : false);
445
386
  }
@@ -551,6 +492,52 @@ export function markdownEscape(text) {
551
492
  }
552
493
  return escape + "\n" + text + (text.endsWith("\n") ? "" : "\n") + escape;
553
494
  }
495
+ /**
496
+ * Builds diff ToolUpdate content from the structured Edit toolResponse provided
497
+ * by the PostToolUse hook. Unlike parsing the plain unified diff string, this uses
498
+ * the pre-parsed structuredPatch which supports multiple replacement sites (replaceAll)
499
+ * and always includes context lines for better readability.
500
+ */
501
+ export function toolUpdateFromEditToolResponse(toolResponse) {
502
+ if (!toolResponse || typeof toolResponse !== "object")
503
+ return {};
504
+ const response = toolResponse;
505
+ if (!response.filePath || !Array.isArray(response.structuredPatch))
506
+ return {};
507
+ const content = [];
508
+ const locations = [];
509
+ for (const { lines, newStart } of response.structuredPatch) {
510
+ const oldText = [];
511
+ const newText = [];
512
+ for (const line of lines) {
513
+ if (line.startsWith("-")) {
514
+ oldText.push(line.slice(1));
515
+ }
516
+ else if (line.startsWith("+")) {
517
+ newText.push(line.slice(1));
518
+ }
519
+ else {
520
+ oldText.push(line.slice(1));
521
+ newText.push(line.slice(1));
522
+ }
523
+ }
524
+ if (oldText.length > 0 || newText.length > 0) {
525
+ locations.push({ path: response.filePath, line: newStart });
526
+ content.push({
527
+ type: "diff",
528
+ path: response.filePath,
529
+ oldText: oldText.join("\n") || null,
530
+ newText: newText.join("\n"),
531
+ });
532
+ }
533
+ }
534
+ const result = {};
535
+ if (content.length > 0)
536
+ result.content = content;
537
+ if (locations.length > 0)
538
+ result.locations = locations;
539
+ return result;
540
+ }
554
541
  /* A global variable to store callbacks that should be executed when receiving hooks from Claude Code */
555
542
  const toolUseCallbacks = {};
556
543
  /* Setup callbacks that will be called when receiving hooks from Claude Code */
@@ -580,43 +567,3 @@ export const createPostToolUseHook = (logger = console, options) => async (input
580
567
  }
581
568
  return { continue: true };
582
569
  };
583
- /**
584
- * Creates a PreToolUse hook that checks permissions using the SettingsManager.
585
- * This runs before the SDK's built-in permission rules, allowing us to enforce
586
- * our own permission settings for ACP-prefixed tools.
587
- */
588
- export const createPreToolUseHook = (settingsManager, logger = console) => async (input, _toolUseID) => {
589
- if (input.hook_event_name !== "PreToolUse") {
590
- return { continue: true };
591
- }
592
- const toolName = input.tool_name;
593
- const toolInput = input.tool_input;
594
- const permissionCheck = settingsManager.checkPermission(toolName, toolInput);
595
- if (permissionCheck.decision !== "ask") {
596
- logger.log(`[PreToolUseHook] Tool: ${toolName}, Decision: ${permissionCheck.decision}, Rule: ${permissionCheck.rule}`);
597
- }
598
- switch (permissionCheck.decision) {
599
- case "allow":
600
- return {
601
- continue: true,
602
- hookSpecificOutput: {
603
- hookEventName: "PreToolUse",
604
- permissionDecision: "allow",
605
- permissionDecisionReason: `Allowed by settings rule: ${permissionCheck.rule}`,
606
- },
607
- };
608
- case "deny":
609
- return {
610
- continue: true,
611
- hookSpecificOutput: {
612
- hookEventName: "PreToolUse",
613
- permissionDecision: "deny",
614
- permissionDecisionReason: `Denied by settings rule: ${permissionCheck.rule}`,
615
- },
616
- };
617
- case "ask":
618
- default:
619
- // Let the normal permission flow continue
620
- return { continue: true };
621
- }
622
- };
package/dist/utils.d.ts CHANGED
@@ -16,18 +16,4 @@ export declare function unreachable(value: never, logger?: Logger): void;
16
16
  export declare function sleep(time: number): Promise<void>;
17
17
  export declare function loadManagedSettings(): ClaudeCodeSettings | null;
18
18
  export declare function applyEnvironmentSettings(settings: ClaudeCodeSettings): void;
19
- export interface ExtractLinesResult {
20
- content: string;
21
- wasLimited: boolean;
22
- linesRead: number;
23
- }
24
- /**
25
- * Extracts lines from file content with byte limit enforcement.
26
- *
27
- * @param fullContent - The complete file content
28
- * @param maxContentLength - Maximum number of UTF-16 Code Units to return
29
- * @returns Object containing extracted content and metadata
30
- */
31
- export declare function extractLinesWithByteLimit(fullContent: string, maxContentLength: number): ExtractLinesResult;
32
- export declare function encodeProjectPath(cwd: string): string;
33
19
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjE,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAA0B,MAAM,eAAe,CAAC;AAG3E,qBAAa,QAAQ,CAAC,CAAC,CAAE,YAAW,aAAa,CAAC,CAAC,CAAC;IAClD,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,IAAI,CAAS;IAErB,IAAI,CAAC,IAAI,EAAE,CAAC;IASZ,GAAG;IAQH,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC;CAgB3C;AAGD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,QAAQ,GAAG,cAAc,CAAC,UAAU,CAAC,CAclF;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,QAAQ,GAAG,cAAc,CAAC,UAAU,CAAC,CAUlF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,GAAE,MAAgB,QAQjE;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEjD;AAED,wBAAgB,mBAAmB,IAAI,kBAAkB,GAAG,IAAI,CAM/D;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAM3E;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,gBAAgB,EAAE,MAAM,GACvB,kBAAkB,CA8CpB;AAKD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUrD"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjE,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAA0B,MAAM,eAAe,CAAC;AAG3E,qBAAa,QAAQ,CAAC,CAAC,CAAE,YAAW,aAAa,CAAC,CAAC,CAAC;IAClD,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,IAAI,CAAS;IAErB,IAAI,CAAC,IAAI,EAAE,CAAC;IASZ,GAAG;IAQH,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC;CAgB3C;AAGD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,QAAQ,GAAG,cAAc,CAAC,UAAU,CAAC,CAclF;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,QAAQ,GAAG,cAAc,CAAC,UAAU,CAAC,CAUlF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,GAAE,MAAgB,QAQjE;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEjD;AAED,wBAAgB,mBAAmB,IAAI,kBAAkB,GAAG,IAAI,CAM/D;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAM3E"}