@canaryai/cli 0.2.5 → 0.2.6

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 (49) hide show
  1. package/dist/{chunk-ILEPYWZX.js → chunk-A44B2PEA.js} +2 -2
  2. package/dist/chunk-AHYNXUHF.js +37 -0
  3. package/dist/chunk-AHYNXUHF.js.map +1 -0
  4. package/dist/chunk-P5Z2Y5VV.js +94 -0
  5. package/dist/chunk-P5Z2Y5VV.js.map +1 -0
  6. package/dist/chunk-PDC425CK.js +46893 -0
  7. package/dist/chunk-PDC425CK.js.map +1 -0
  8. package/dist/{chunk-FIQBGAKW.js → chunk-RYCPA32L.js} +4 -4
  9. package/dist/{chunk-FIQBGAKW.js.map → chunk-RYCPA32L.js.map} +1 -1
  10. package/dist/chunk-VKVL7WBN.js +50 -0
  11. package/dist/{debug-workflow-PT3OUR3V.js → debug-workflow-G5ZAZCYG.js} +6 -3
  12. package/dist/{debug-workflow-PT3OUR3V.js.map → debug-workflow-G5ZAZCYG.js.map} +1 -1
  13. package/dist/dist-5CSYV6PJ.js +336 -0
  14. package/dist/dist-5CSYV6PJ.js.map +1 -0
  15. package/dist/{docs-RUZXLATL.js → docs-QLCF2LS6.js} +5 -3
  16. package/dist/{docs-RUZXLATL.js.map → docs-QLCF2LS6.js.map} +1 -1
  17. package/dist/{feature-flag-S5B5GLPP.js → feature-flag-2FDSKOVX.js} +2 -2
  18. package/dist/index.js +15 -13
  19. package/dist/index.js.map +1 -1
  20. package/dist/{issues-4ZEDHPLW.js → issues-6ZDNDSD6.js} +2 -2
  21. package/dist/{knobs-RKUVK3HC.js → knobs-MZRTYS3P.js} +2 -2
  22. package/dist/{local-browser-J6WGFLVD.js → local-browser-5ZVPHF5H.js} +6 -3
  23. package/dist/{local-browser-J6WGFLVD.js.map → local-browser-5ZVPHF5H.js.map} +1 -1
  24. package/dist/{mcp-HGYBMDYZ.js → mcp-Q666YHHT.js} +14 -13
  25. package/dist/mcp-Q666YHHT.js.map +1 -0
  26. package/dist/pdf-extract-XYDS42VL.js +13 -0
  27. package/dist/pdf-extract-XYDS42VL.js.map +1 -0
  28. package/dist/pdfjs-HMUKB5WW.js +35243 -0
  29. package/dist/pdfjs-HMUKB5WW.js.map +1 -0
  30. package/dist/{psql-WVIHMC6A.js → psql-2YPIRMDY.js} +2 -2
  31. package/dist/{record-MMFESD4M.js → record-W5QERB5Z.js} +6 -4
  32. package/dist/{record-MMFESD4M.js.map → record-W5QERB5Z.js.map} +1 -1
  33. package/dist/{redis-RGHECKV5.js → redis-A7GWM23E.js} +2 -2
  34. package/dist/{release-ZOD4Y2BF.js → release-L4IXOHDF.js} +2 -2
  35. package/dist/runner/preload.js +2 -2
  36. package/dist/src-GSLFE4NP.js +146 -0
  37. package/dist/src-GSLFE4NP.js.map +1 -0
  38. package/dist/test.js +2 -2
  39. package/package.json +2 -3
  40. package/dist/chunk-VLFUCAPZ.js +0 -12
  41. package/dist/mcp-HGYBMDYZ.js.map +0 -1
  42. /package/dist/{chunk-ILEPYWZX.js.map → chunk-A44B2PEA.js.map} +0 -0
  43. /package/dist/{chunk-VLFUCAPZ.js.map → chunk-VKVL7WBN.js.map} +0 -0
  44. /package/dist/{feature-flag-S5B5GLPP.js.map → feature-flag-2FDSKOVX.js.map} +0 -0
  45. /package/dist/{issues-4ZEDHPLW.js.map → issues-6ZDNDSD6.js.map} +0 -0
  46. /package/dist/{knobs-RKUVK3HC.js.map → knobs-MZRTYS3P.js.map} +0 -0
  47. /package/dist/{psql-WVIHMC6A.js.map → psql-2YPIRMDY.js.map} +0 -0
  48. /package/dist/{redis-RGHECKV5.js.map → redis-A7GWM23E.js.map} +0 -0
  49. /package/dist/{release-ZOD4Y2BF.js.map → release-L4IXOHDF.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
2
2
  import {
3
3
  __require
4
- } from "./chunk-VLFUCAPZ.js";
4
+ } from "./chunk-VKVL7WBN.js";
5
5
 
6
6
  // src/runner/config.ts
7
7
  import path2 from "path";
@@ -1288,4 +1288,4 @@ export {
1288
1288
  wrapExpect,
1289
1289
  wrapPage
1290
1290
  };
1291
- //# sourceMappingURL=chunk-ILEPYWZX.js.map
1291
+ //# sourceMappingURL=chunk-A44B2PEA.js.map
@@ -0,0 +1,37 @@
1
+ import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
2
+
3
+ // ../tmp/src/index.ts
4
+ import os from "os";
5
+ import path from "path";
6
+ import fs from "fs";
7
+ import { mkdir, mkdtemp } from "fs/promises";
8
+ import { randomUUID } from "crypto";
9
+ var CANARY_TMP_DIR = path.join(os.tmpdir(), "canary");
10
+ var DIR_MODE = 448;
11
+ var dirEnsured = false;
12
+ var ensureSync = () => {
13
+ if (dirEnsured) return;
14
+ fs.mkdirSync(CANARY_TMP_DIR, { recursive: true, mode: DIR_MODE });
15
+ dirEnsured = true;
16
+ };
17
+ var getCanaryTmpDir = () => {
18
+ ensureSync();
19
+ return CANARY_TMP_DIR;
20
+ };
21
+ var getSubDir = (name) => {
22
+ ensureSync();
23
+ const dir = path.join(CANARY_TMP_DIR, name);
24
+ fs.mkdirSync(dir, { recursive: true, mode: DIR_MODE });
25
+ return dir;
26
+ };
27
+ var makeTempDirSync = (prefix) => {
28
+ ensureSync();
29
+ return fs.mkdtempSync(path.join(CANARY_TMP_DIR, prefix));
30
+ };
31
+
32
+ export {
33
+ getCanaryTmpDir,
34
+ getSubDir,
35
+ makeTempDirSync
36
+ };
37
+ //# sourceMappingURL=chunk-AHYNXUHF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../tmp/src/index.ts"],"sourcesContent":["/**\n * Canary Temp Directory Helpers\n *\n * Centralizes all temporary file/directory creation under a single\n * `/tmp/canary/` base directory. This ensures the cleanup daemon only\n * removes files we own, not OS or third-party temp entries.\n *\n * All public functions lazily ensure the base directory exists on first\n * use, so callers never need to worry about directory creation.\n *\n * @module tmp\n * @see packages/tmp/README.md\n */\n\nimport os from 'node:os';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport { mkdir, mkdtemp } from 'node:fs/promises';\nimport { randomUUID } from 'node:crypto';\n\n/** Base directory for all canary temp files */\nconst CANARY_TMP_DIR = path.join(os.tmpdir(), 'canary');\n\n/** Restrictive permissions: owner-only access (rwx------) */\nconst DIR_MODE = 0o700;\n\n/**\n * Tracks whether the base directory has been created this process.\n * Once created, skip redundant mkdir calls.\n */\nlet dirEnsured = false;\n\nconst ensureSync = (): void => {\n if (dirEnsured) return;\n fs.mkdirSync(CANARY_TMP_DIR, { recursive: true, mode: DIR_MODE });\n dirEnsured = true;\n};\n\nconst ensureAsync = async (): Promise<void> => {\n if (dirEnsured) return;\n await mkdir(CANARY_TMP_DIR, { recursive: true, mode: DIR_MODE });\n dirEnsured = true;\n};\n\n/** Get the canary tmp base directory path (lazily ensures dir exists) */\nexport const getCanaryTmpDir = (): string => {\n ensureSync();\n return CANARY_TMP_DIR;\n};\n\n/** Ensure the canary base directory exists (async, idempotent) */\nexport const ensureCanaryTmpDir = async (): Promise<string> => {\n await ensureAsync();\n return CANARY_TMP_DIR;\n};\n\n/**\n * Get a named subdirectory under the canary tmp dir, creating it if needed.\n *\n * Accepts nested paths (e.g. `'workflow-runs/abc-123'`).\n *\n * @example\n * const dir = getSubDir('cache-agent');\n * // => '/tmp/canary/cache-agent' (created with 0o700 permissions)\n */\nexport const getSubDir = (name: string): string => {\n ensureSync();\n const dir = path.join(CANARY_TMP_DIR, name);\n fs.mkdirSync(dir, { recursive: true, mode: DIR_MODE });\n return dir;\n};\n\n/**\n * Async version of getSubDir. Prefer this in async contexts to avoid\n * blocking the event loop on first call.\n */\nexport const getSubDirAsync = async (name: string): Promise<string> => {\n await ensureAsync();\n const dir = path.join(CANARY_TMP_DIR, name);\n await mkdir(dir, { recursive: true, mode: DIR_MODE });\n return dir;\n};\n\n/** Create a temp directory under /tmp/canary/ with the given prefix */\nexport const makeTempDir = async (prefix: string): Promise<string> => {\n await ensureAsync();\n return mkdtemp(path.join(CANARY_TMP_DIR, prefix));\n};\n\n/** Synchronous version of makeTempDir */\nexport const makeTempDirSync = (prefix: string): string => {\n ensureSync();\n return fs.mkdtempSync(path.join(CANARY_TMP_DIR, prefix));\n};\n\n/** Generate a temp file path under /tmp/canary/ (ensures dir exists, does NOT create the file) */\nexport const getTempFilePath = (prefix: string, suffix: string = ''): string => {\n ensureSync();\n return path.join(CANARY_TMP_DIR, `${prefix}${randomUUID()}${suffix}`);\n};\n"],"mappings":";;;AAcA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,SAAS,OAAO,eAAe;AAC/B,SAAS,kBAAkB;AAG3B,IAAM,iBAAiB,KAAK,KAAK,GAAG,OAAO,GAAG,QAAQ;AAGtD,IAAM,WAAW;AAMjB,IAAI,aAAa;AAEjB,IAAM,aAAa,MAAY;AAC7B,MAAI,WAAY;AAChB,KAAG,UAAU,gBAAgB,EAAE,WAAW,MAAM,MAAM,SAAS,CAAC;AAChE,eAAa;AACf;AASO,IAAM,kBAAkB,MAAc;AAC3C,aAAW;AACX,SAAO;AACT;AAiBO,IAAM,YAAY,CAAC,SAAyB;AACjD,aAAW;AACX,QAAM,MAAM,KAAK,KAAK,gBAAgB,IAAI;AAC1C,KAAG,UAAU,KAAK,EAAE,WAAW,MAAM,MAAM,SAAS,CAAC;AACrD,SAAO;AACT;AAoBO,IAAM,kBAAkB,CAAC,WAA2B;AACzD,aAAW;AACX,SAAO,GAAG,YAAY,KAAK,KAAK,gBAAgB,MAAM,CAAC;AACzD;","names":[]}
@@ -0,0 +1,94 @@
1
+ import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
2
+
3
+ // ../browser-core/src/pdf-extract.ts
4
+ import * as fs from "fs/promises";
5
+
6
+ // ../browser-core/src/logger.ts
7
+ var consoleLogger = {
8
+ debug: (msg, data) => {
9
+ if (data) console.debug(msg, data);
10
+ else console.debug(msg);
11
+ },
12
+ info: (msg, data) => {
13
+ if (data) console.info(msg, data);
14
+ else console.info(msg);
15
+ },
16
+ warn: (msg, data) => {
17
+ if (data) console.warn(msg, data);
18
+ else console.warn(msg);
19
+ },
20
+ error: (msg, data) => {
21
+ if (data) console.error(msg, data);
22
+ else console.error(msg);
23
+ }
24
+ };
25
+
26
+ // ../browser-core/src/pdf-extract.ts
27
+ var _logger = consoleLogger;
28
+ function setPdfExtractLogger(l) {
29
+ _logger = l;
30
+ }
31
+ var MAX_FILE_SIZE_BYTES = 50 * 1024 * 1024;
32
+ var MAX_OUTPUT_CHARS = 1e5;
33
+ async function extractPdfTextFromBuffer(buffer) {
34
+ if (buffer.length > MAX_FILE_SIZE_BYTES) {
35
+ _logger.warn("[PdfExtract] PDF too large for text extraction", {
36
+ sizeBytes: buffer.length,
37
+ maxBytes: MAX_FILE_SIZE_BYTES
38
+ });
39
+ return {
40
+ text: `[PDF too large for text extraction: ${formatBytes(buffer.length)} exceeds ${formatBytes(MAX_FILE_SIZE_BYTES)} limit]`,
41
+ totalPages: 0
42
+ };
43
+ }
44
+ const { extractText } = await import("./dist-5CSYV6PJ.js");
45
+ const uint8 = new Uint8Array(buffer);
46
+ const result = await extractText(uint8, { mergePages: true });
47
+ let text = result.text ?? "";
48
+ const totalPages = result.totalPages ?? 0;
49
+ if (text.length > MAX_OUTPUT_CHARS) {
50
+ _logger.info("[PdfExtract] Truncating extracted text", {
51
+ originalLength: text.length,
52
+ truncatedTo: MAX_OUTPUT_CHARS,
53
+ totalPages
54
+ });
55
+ text = text.slice(0, MAX_OUTPUT_CHARS) + `
56
+
57
+ [Text truncated at ${MAX_OUTPUT_CHARS} characters]`;
58
+ }
59
+ _logger.info("[PdfExtract] Text extracted successfully", {
60
+ textLength: text.length,
61
+ totalPages,
62
+ sizeBytes: buffer.length
63
+ });
64
+ return { text, totalPages };
65
+ }
66
+ async function extractPdfText(filePath) {
67
+ const stat2 = await fs.stat(filePath);
68
+ if (stat2.size > MAX_FILE_SIZE_BYTES) {
69
+ _logger.warn("[PdfExtract] PDF file too large for text extraction", {
70
+ filePath,
71
+ sizeBytes: stat2.size,
72
+ maxBytes: MAX_FILE_SIZE_BYTES
73
+ });
74
+ return {
75
+ text: `[PDF too large for text extraction: ${formatBytes(stat2.size)} exceeds ${formatBytes(MAX_FILE_SIZE_BYTES)} limit]`,
76
+ totalPages: 0
77
+ };
78
+ }
79
+ const buffer = await fs.readFile(filePath);
80
+ return extractPdfTextFromBuffer(Buffer.from(buffer));
81
+ }
82
+ function formatBytes(bytes) {
83
+ if (bytes < 1024) return `${bytes}B`;
84
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
85
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
86
+ }
87
+
88
+ export {
89
+ consoleLogger,
90
+ setPdfExtractLogger,
91
+ extractPdfTextFromBuffer,
92
+ extractPdfText
93
+ };
94
+ //# sourceMappingURL=chunk-P5Z2Y5VV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../browser-core/src/pdf-extract.ts","../../browser-core/src/logger.ts"],"sourcesContent":["/**\n * PDF text extraction utility.\n *\n * Uses `unpdf` to extract text content from PDF files and buffers.\n * Includes size guards to prevent excessive memory usage.\n *\n * @module pdf-extract\n */\n\nimport * as fs from 'fs/promises';\nimport { consoleLogger, type BrowserLogger } from './logger.js';\n\nlet _logger: BrowserLogger = consoleLogger;\n\nexport function setPdfExtractLogger(l: BrowserLogger): void {\n _logger = l;\n}\n\nconst MAX_FILE_SIZE_BYTES = 50 * 1024 * 1024; // 50MB\nconst MAX_OUTPUT_CHARS = 100_000;\n\n/**\n * Extract text content from a PDF buffer.\n * Returns the extracted text and total page count.\n */\nexport async function extractPdfTextFromBuffer(\n buffer: Buffer\n): Promise<{ text: string; totalPages: number }> {\n if (buffer.length > MAX_FILE_SIZE_BYTES) {\n _logger.warn('[PdfExtract] PDF too large for text extraction', {\n sizeBytes: buffer.length,\n maxBytes: MAX_FILE_SIZE_BYTES,\n });\n return {\n text: `[PDF too large for text extraction: ${formatBytes(buffer.length)} exceeds ${formatBytes(MAX_FILE_SIZE_BYTES)} limit]`,\n totalPages: 0,\n };\n }\n\n const { extractText } = await import('unpdf');\n const uint8 = new Uint8Array(buffer);\n const result = await extractText(uint8, { mergePages: true });\n\n let text = result.text ?? '';\n const totalPages = result.totalPages ?? 0;\n\n if (text.length > MAX_OUTPUT_CHARS) {\n _logger.info('[PdfExtract] Truncating extracted text', {\n originalLength: text.length,\n truncatedTo: MAX_OUTPUT_CHARS,\n totalPages,\n });\n text = text.slice(0, MAX_OUTPUT_CHARS) + `\\n\\n[Text truncated at ${MAX_OUTPUT_CHARS} characters]`;\n }\n\n _logger.info('[PdfExtract] Text extracted successfully', {\n textLength: text.length,\n totalPages,\n sizeBytes: buffer.length,\n });\n\n return { text, totalPages };\n}\n\n/**\n * Extract text content from a PDF file on disk.\n */\nexport async function extractPdfText(\n filePath: string\n): Promise<{ text: string; totalPages: number }> {\n const stat = await fs.stat(filePath);\n\n if (stat.size > MAX_FILE_SIZE_BYTES) {\n _logger.warn('[PdfExtract] PDF file too large for text extraction', {\n filePath,\n sizeBytes: stat.size,\n maxBytes: MAX_FILE_SIZE_BYTES,\n });\n return {\n text: `[PDF too large for text extraction: ${formatBytes(stat.size)} exceeds ${formatBytes(MAX_FILE_SIZE_BYTES)} limit]`,\n totalPages: 0,\n };\n }\n\n const buffer = await fs.readFile(filePath);\n return extractPdfTextFromBuffer(Buffer.from(buffer));\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes}B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n}\n","/**\n * Browser Logger Interface\n *\n * Abstracts logging so browser-core works in any environment:\n * - Cloud (apps/api): Wraps pino logger\n * - CLI (canary-cli): Uses console logger\n *\n * @module logger\n */\n\nexport interface BrowserLogger {\n debug(msg: string, data?: Record<string, unknown>): void;\n info(msg: string, data?: Record<string, unknown>): void;\n warn(msg: string, data?: Record<string, unknown>): void;\n error(msg: string, data?: Record<string, unknown>): void;\n}\n\n/**\n * Default console-based logger. Works everywhere without dependencies.\n */\nexport const consoleLogger: BrowserLogger = {\n debug: (msg, data) => {\n if (data) console.debug(msg, data);\n else console.debug(msg);\n },\n info: (msg, data) => {\n if (data) console.info(msg, data);\n else console.info(msg);\n },\n warn: (msg, data) => {\n if (data) console.warn(msg, data);\n else console.warn(msg);\n },\n error: (msg, data) => {\n if (data) console.error(msg, data);\n else console.error(msg);\n },\n};\n"],"mappings":";;;AASA,YAAY,QAAQ;;;ACWb,IAAM,gBAA+B;AAAA,EAC1C,OAAO,CAAC,KAAK,SAAS;AACpB,QAAI,KAAM,SAAQ,MAAM,KAAK,IAAI;AAAA,QAC5B,SAAQ,MAAM,GAAG;AAAA,EACxB;AAAA,EACA,MAAM,CAAC,KAAK,SAAS;AACnB,QAAI,KAAM,SAAQ,KAAK,KAAK,IAAI;AAAA,QAC3B,SAAQ,KAAK,GAAG;AAAA,EACvB;AAAA,EACA,MAAM,CAAC,KAAK,SAAS;AACnB,QAAI,KAAM,SAAQ,KAAK,KAAK,IAAI;AAAA,QAC3B,SAAQ,KAAK,GAAG;AAAA,EACvB;AAAA,EACA,OAAO,CAAC,KAAK,SAAS;AACpB,QAAI,KAAM,SAAQ,MAAM,KAAK,IAAI;AAAA,QAC5B,SAAQ,MAAM,GAAG;AAAA,EACxB;AACF;;;ADzBA,IAAI,UAAyB;AAEtB,SAAS,oBAAoB,GAAwB;AAC1D,YAAU;AACZ;AAEA,IAAM,sBAAsB,KAAK,OAAO;AACxC,IAAM,mBAAmB;AAMzB,eAAsB,yBACpB,QAC+C;AAC/C,MAAI,OAAO,SAAS,qBAAqB;AACvC,YAAQ,KAAK,kDAAkD;AAAA,MAC7D,WAAW,OAAO;AAAA,MAClB,UAAU;AAAA,IACZ,CAAC;AACD,WAAO;AAAA,MACL,MAAM,uCAAuC,YAAY,OAAO,MAAM,CAAC,YAAY,YAAY,mBAAmB,CAAC;AAAA,MACnH,YAAY;AAAA,IACd;AAAA,EACF;AAEA,QAAM,EAAE,YAAY,IAAI,MAAM,OAAO,oBAAO;AAC5C,QAAM,QAAQ,IAAI,WAAW,MAAM;AACnC,QAAM,SAAS,MAAM,YAAY,OAAO,EAAE,YAAY,KAAK,CAAC;AAE5D,MAAI,OAAO,OAAO,QAAQ;AAC1B,QAAM,aAAa,OAAO,cAAc;AAExC,MAAI,KAAK,SAAS,kBAAkB;AAClC,YAAQ,KAAK,0CAA0C;AAAA,MACrD,gBAAgB,KAAK;AAAA,MACrB,aAAa;AAAA,MACb;AAAA,IACF,CAAC;AACD,WAAO,KAAK,MAAM,GAAG,gBAAgB,IAAI;AAAA;AAAA,qBAA0B,gBAAgB;AAAA,EACrF;AAEA,UAAQ,KAAK,4CAA4C;AAAA,IACvD,YAAY,KAAK;AAAA,IACjB;AAAA,IACA,WAAW,OAAO;AAAA,EACpB,CAAC;AAED,SAAO,EAAE,MAAM,WAAW;AAC5B;AAKA,eAAsB,eACpB,UAC+C;AAC/C,QAAMA,QAAO,MAAS,QAAK,QAAQ;AAEnC,MAAIA,MAAK,OAAO,qBAAqB;AACnC,YAAQ,KAAK,uDAAuD;AAAA,MAClE;AAAA,MACA,WAAWA,MAAK;AAAA,MAChB,UAAU;AAAA,IACZ,CAAC;AACD,WAAO;AAAA,MACL,MAAM,uCAAuC,YAAYA,MAAK,IAAI,CAAC,YAAY,YAAY,mBAAmB,CAAC;AAAA,MAC/G,YAAY;AAAA,IACd;AAAA,EACF;AAEA,QAAM,SAAS,MAAS,YAAS,QAAQ;AACzC,SAAO,yBAAyB,OAAO,KAAK,MAAM,CAAC;AACrD;AAEA,SAAS,YAAY,OAAuB;AAC1C,MAAI,QAAQ,KAAM,QAAO,GAAG,KAAK;AACjC,MAAI,QAAQ,OAAO,KAAM,QAAO,IAAI,QAAQ,MAAM,QAAQ,CAAC,CAAC;AAC5D,SAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,CAAC,CAAC;AAC9C;","names":["stat"]}