@hardlydifficult/ai-msg 1.0.0 → 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 +36 -14
- package/dist/extractJson.d.ts +1 -1
- package/dist/extractJson.d.ts.map +1 -1
- package/dist/extractJson.js +26 -17
- package/dist/extractJson.js.map +1 -1
- package/dist/extractTyped.d.ts +1 -1
- package/dist/extractTyped.d.ts.map +1 -1
- package/dist/extractTyped.js +9 -6
- package/dist/extractTyped.js.map +1 -1
- package/dist/findBalanced.d.ts +1 -0
- package/dist/findBalanced.d.ts.map +1 -1
- package/dist/findBalanced.js +16 -0
- package/dist/findBalanced.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,35 +18,54 @@ npm install @hardlydifficult/ai-msg zod
|
|
|
18
18
|
|
|
19
19
|
## Usage
|
|
20
20
|
|
|
21
|
-
### `extractJson(text): unknown
|
|
21
|
+
### `extractJson(text, sentinel?): unknown[]`
|
|
22
22
|
|
|
23
|
-
Extracts
|
|
23
|
+
Extracts all valid JSON values from text using a three-pass strategy:
|
|
24
24
|
|
|
25
25
|
1. Direct `JSON.parse` of the trimmed text
|
|
26
26
|
2. Search markdown code blocks (json-tagged first, then any)
|
|
27
|
-
3. Find balanced `{}` or `[]` substrings in prose
|
|
27
|
+
3. Find all balanced `{}` or `[]` substrings in prose
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
Always returns an array. Returns `[]` when no JSON is found.
|
|
30
|
+
|
|
31
|
+
````typescript
|
|
30
32
|
import { extractJson } from "@hardlydifficult/ai-msg";
|
|
31
33
|
|
|
32
34
|
extractJson('{"key": "value"}');
|
|
33
|
-
// { key: "value" }
|
|
35
|
+
// [{ key: "value" }]
|
|
34
36
|
|
|
35
37
|
extractJson('Here is the result:\n```json\n{"key": "value"}\n```\nDone.');
|
|
36
|
-
// { key: "value" }
|
|
38
|
+
// [{ key: "value" }]
|
|
37
39
|
|
|
38
40
|
extractJson('The answer is {"key": "value"} as shown.');
|
|
39
|
-
// { key: "value" }
|
|
41
|
+
// [{ key: "value" }]
|
|
40
42
|
|
|
41
43
|
extractJson("no json here");
|
|
42
|
-
//
|
|
44
|
+
// []
|
|
45
|
+
````
|
|
46
|
+
|
|
47
|
+
Multiple JSON values are returned when present:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
extractJson('First {"a": 1} then {"b": 2} done.');
|
|
51
|
+
// [{ a: 1 }, { b: 2 }]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The optional `sentinel` parameter short-circuits extraction — if the text contains the sentinel string, an empty array is returned immediately:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
extractJson("NO_FINDINGS: the scan completed with no issues.", "NO_FINDINGS");
|
|
58
|
+
// []
|
|
59
|
+
|
|
60
|
+
extractJson('{"result": "found"}', "NO_FINDINGS");
|
|
61
|
+
// [{ result: "found" }]
|
|
43
62
|
```
|
|
44
63
|
|
|
45
64
|
### `extractCodeBlock(text, lang?): string[]`
|
|
46
65
|
|
|
47
66
|
Extracts all markdown code blocks from text. Optionally filters by language tag.
|
|
48
67
|
|
|
49
|
-
|
|
68
|
+
````typescript
|
|
50
69
|
import { extractCodeBlock } from "@hardlydifficult/ai-msg";
|
|
51
70
|
|
|
52
71
|
extractCodeBlock("```ts\nconst x = 1;\n```");
|
|
@@ -57,11 +76,11 @@ extractCodeBlock("```json\n{}\n```\n```ts\nconst x = 1;\n```", "json");
|
|
|
57
76
|
|
|
58
77
|
extractCodeBlock("no code blocks");
|
|
59
78
|
// []
|
|
60
|
-
|
|
79
|
+
````
|
|
61
80
|
|
|
62
|
-
### `extractTyped<T>(text, schema): T
|
|
81
|
+
### `extractTyped<T>(text, schema, sentinel?): T[]`
|
|
63
82
|
|
|
64
|
-
Extracts JSON from text and validates
|
|
83
|
+
Extracts all JSON values from text and validates each against a Zod schema. Only values that pass validation are included. Requires `zod` as a peer dependency.
|
|
65
84
|
|
|
66
85
|
```typescript
|
|
67
86
|
import { extractTyped } from "@hardlydifficult/ai-msg";
|
|
@@ -70,8 +89,11 @@ import { z } from "zod";
|
|
|
70
89
|
const Person = z.object({ name: z.string(), age: z.number() });
|
|
71
90
|
|
|
72
91
|
extractTyped('{"name": "Alice", "age": 30}', Person);
|
|
73
|
-
// { name: "Alice", age: 30 }
|
|
92
|
+
// [{ name: "Alice", age: 30 }]
|
|
74
93
|
|
|
75
94
|
extractTyped('{"name": "Alice", "age": "thirty"}', Person);
|
|
76
|
-
//
|
|
95
|
+
// []
|
|
96
|
+
|
|
97
|
+
extractTyped("NO_FINDINGS", Person, "NO_FINDINGS");
|
|
98
|
+
// []
|
|
77
99
|
```
|
package/dist/extractJson.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function extractJson(text: string): unknown;
|
|
1
|
+
export declare function extractJson(text: string, sentinel?: string): unknown[];
|
|
2
2
|
//# sourceMappingURL=extractJson.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractJson.d.ts","sourceRoot":"","sources":["../src/extractJson.ts"],"names":[],"mappings":"AAWA,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"extractJson.d.ts","sourceRoot":"","sources":["../src/extractJson.ts"],"names":[],"mappings":"AAWA,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,EAAE,CAgDtE"}
|
package/dist/extractJson.js
CHANGED
|
@@ -11,40 +11,49 @@ function tryParse(text) {
|
|
|
11
11
|
return undefined;
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
-
function extractJson(text) {
|
|
14
|
+
function extractJson(text, sentinel) {
|
|
15
|
+
// Sentinel check — if the text contains the sentinel, treat as "no findings"
|
|
16
|
+
if (sentinel !== undefined && text.includes(sentinel)) {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
15
19
|
// Pass 1: try the whole text
|
|
16
20
|
const direct = tryParse(text.trim());
|
|
17
21
|
if (direct !== undefined) {
|
|
18
|
-
return direct;
|
|
22
|
+
return [direct];
|
|
19
23
|
}
|
|
20
24
|
// Pass 2: code blocks — json-tagged first, then any
|
|
25
|
+
const fromBlocks = [];
|
|
21
26
|
for (const block of (0, extractCodeBlock_js_1.extractCodeBlock)(text, "json")) {
|
|
22
27
|
const parsed = tryParse(block.trim());
|
|
23
28
|
if (parsed !== undefined) {
|
|
24
|
-
|
|
29
|
+
fromBlocks.push(parsed);
|
|
25
30
|
}
|
|
26
31
|
}
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
if (fromBlocks.length === 0) {
|
|
33
|
+
for (const block of (0, extractCodeBlock_js_1.extractCodeBlock)(text)) {
|
|
34
|
+
const parsed = tryParse(block.trim());
|
|
35
|
+
if (parsed !== undefined) {
|
|
36
|
+
fromBlocks.push(parsed);
|
|
37
|
+
}
|
|
31
38
|
}
|
|
32
39
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
if (fromBlocks.length > 0) {
|
|
41
|
+
return fromBlocks;
|
|
42
|
+
}
|
|
43
|
+
// Pass 3: all balanced braces / brackets in prose
|
|
44
|
+
const results = [];
|
|
45
|
+
for (const match of (0, findBalanced_js_1.findAllBalanced)(text, "{", "}")) {
|
|
46
|
+
const parsed = tryParse(match);
|
|
37
47
|
if (parsed !== undefined) {
|
|
38
|
-
|
|
48
|
+
results.push(parsed);
|
|
39
49
|
}
|
|
40
50
|
}
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
const parsed = tryParse(arr);
|
|
51
|
+
for (const match of (0, findBalanced_js_1.findAllBalanced)(text, "[", "]")) {
|
|
52
|
+
const parsed = tryParse(match);
|
|
44
53
|
if (parsed !== undefined) {
|
|
45
|
-
|
|
54
|
+
results.push(parsed);
|
|
46
55
|
}
|
|
47
56
|
}
|
|
48
|
-
return
|
|
57
|
+
return results;
|
|
49
58
|
}
|
|
50
59
|
//# sourceMappingURL=extractJson.js.map
|
package/dist/extractJson.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractJson.js","sourceRoot":"","sources":["../src/extractJson.ts"],"names":[],"mappings":";;AAWA,
|
|
1
|
+
{"version":3,"file":"extractJson.js","sourceRoot":"","sources":["../src/extractJson.ts"],"names":[],"mappings":";;AAWA,kCAgDC;AA3DD,+DAAyD;AACzD,uDAAoD;AAEpD,SAAS,QAAQ,CAAC,IAAY;IAC5B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAgB,WAAW,CAAC,IAAY,EAAE,QAAiB;IACzD,6EAA6E;IAC7E,IAAI,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,6BAA6B;IAC7B,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACrC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,CAAC,MAAM,CAAC,CAAC;IAClB,CAAC;IAED,oDAAoD;IACpD,MAAM,UAAU,GAAc,EAAE,CAAC;IACjC,KAAK,MAAM,KAAK,IAAI,IAAA,sCAAgB,EAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;QACnD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACtC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,KAAK,MAAM,KAAK,IAAI,IAAA,sCAAgB,EAAC,IAAI,CAAC,EAAE,CAAC;YAC3C,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YACtC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,kDAAkD;IAClD,MAAM,OAAO,GAAc,EAAE,CAAC;IAC9B,KAAK,MAAM,KAAK,IAAI,IAAA,iCAAe,EAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,IAAA,iCAAe,EAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/extractTyped.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractTyped.d.ts","sourceRoot":"","sources":["../src/extractTyped.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AAInC,wBAAgB,YAAY,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"extractTyped.d.ts","sourceRoot":"","sources":["../src/extractTyped.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AAInC,wBAAgB,YAAY,CAAC,CAAC,EAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,CAAC,EAAE,CAUL"}
|
package/dist/extractTyped.js
CHANGED
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.extractTyped = extractTyped;
|
|
4
4
|
const extractJson_js_1 = require("./extractJson.js");
|
|
5
|
-
function extractTyped(text, schema) {
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
function extractTyped(text, schema, sentinel) {
|
|
6
|
+
const results = (0, extractJson_js_1.extractJson)(text, sentinel);
|
|
7
|
+
const validated = [];
|
|
8
|
+
for (const json of results) {
|
|
9
|
+
const result = schema.safeParse(json);
|
|
10
|
+
if (result.success) {
|
|
11
|
+
validated.push(result.data);
|
|
12
|
+
}
|
|
9
13
|
}
|
|
10
|
-
|
|
11
|
-
return result.success ? result.data : null;
|
|
14
|
+
return validated;
|
|
12
15
|
}
|
|
13
16
|
//# sourceMappingURL=extractTyped.js.map
|
package/dist/extractTyped.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractTyped.js","sourceRoot":"","sources":["../src/extractTyped.ts"],"names":[],"mappings":";;AAIA,
|
|
1
|
+
{"version":3,"file":"extractTyped.js","sourceRoot":"","sources":["../src/extractTyped.ts"],"names":[],"mappings":";;AAIA,oCAcC;AAhBD,qDAA+C;AAE/C,SAAgB,YAAY,CAC1B,IAAY,EACZ,MAAkB,EAClB,QAAiB;IAEjB,MAAM,OAAO,GAAG,IAAA,4BAAW,EAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAQ,EAAE,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
package/dist/findBalanced.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findBalanced.d.ts","sourceRoot":"","sources":["../src/findBalanced.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CA6Cf"}
|
|
1
|
+
{"version":3,"file":"findBalanced.d.ts","sourceRoot":"","sources":["../src/findBalanced.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CA6Cf;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,MAAM,EAAE,CAiBV"}
|
package/dist/findBalanced.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.findBalanced = findBalanced;
|
|
4
|
+
exports.findAllBalanced = findAllBalanced;
|
|
4
5
|
function findBalanced(text, openChar, closeChar) {
|
|
5
6
|
const start = text.indexOf(openChar);
|
|
6
7
|
if (start === -1) {
|
|
@@ -40,4 +41,19 @@ function findBalanced(text, openChar, closeChar) {
|
|
|
40
41
|
}
|
|
41
42
|
return null;
|
|
42
43
|
}
|
|
44
|
+
function findAllBalanced(text, openChar, closeChar) {
|
|
45
|
+
const results = [];
|
|
46
|
+
let offset = 0;
|
|
47
|
+
while (offset < text.length) {
|
|
48
|
+
const remaining = text.slice(offset);
|
|
49
|
+
const match = findBalanced(remaining, openChar, closeChar);
|
|
50
|
+
if (match === null) {
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
results.push(match);
|
|
54
|
+
const matchStart = remaining.indexOf(openChar);
|
|
55
|
+
offset += matchStart + match.length;
|
|
56
|
+
}
|
|
57
|
+
return results;
|
|
58
|
+
}
|
|
43
59
|
//# sourceMappingURL=findBalanced.js.map
|
package/dist/findBalanced.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findBalanced.js","sourceRoot":"","sources":["../src/findBalanced.ts"],"names":[],"mappings":";;AAAA,oCAiDC;
|
|
1
|
+
{"version":3,"file":"findBalanced.js","sourceRoot":"","sources":["../src/findBalanced.ts"],"names":[],"mappings":";;AAAA,oCAiDC;AAED,0CAqBC;AAxED,SAAgB,YAAY,CAC1B,IAAY,EACZ,QAAgB,EAChB,SAAiB;IAEjB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrC,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEnB,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,GAAG,KAAK,CAAC;YAChB,SAAS;QACX,CAAC;QAED,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAChB,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACf,QAAQ,GAAG,CAAC,QAAQ,CAAC;YACrB,SAAS;QACX,CAAC;QAED,IAAI,QAAQ,EAAE,CAAC;YACb,SAAS;QACX,CAAC;QAED,IAAI,EAAE,KAAK,QAAQ,EAAE,CAAC;YACpB,KAAK,EAAE,CAAC;QACV,CAAC;aAAM,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YAC5B,KAAK,EAAE,CAAC;YACR,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;gBAChB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAgB,eAAe,CAC7B,IAAY,EACZ,QAAgB,EAChB,SAAiB;IAEjB,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,OAAO,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,YAAY,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC3D,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,MAAM;QACR,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC/C,MAAM,IAAI,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC;IACtC,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|