monomind 1.10.30 → 1.10.31

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 (26) hide show
  1. package/.claude/helpers/handlers/adr-draft-handler.cjs +64 -0
  2. package/.claude/helpers/handlers/agent-start-handler.cjs +99 -0
  3. package/.claude/helpers/handlers/graph-status-handler.cjs +38 -0
  4. package/.claude/helpers/handlers/session-restore-handler.cjs +45 -40
  5. package/.claude/helpers/hook-handler.cjs +6 -158
  6. package/package.json +1 -1
  7. package/packages/@monomind/cli/dist/src/browser/actions.d.ts +15 -0
  8. package/packages/@monomind/cli/dist/src/browser/actions.js +91 -0
  9. package/packages/@monomind/cli/dist/src/browser/batch.d.ts +13 -0
  10. package/packages/@monomind/cli/dist/src/browser/batch.js +11 -0
  11. package/packages/@monomind/cli/dist/src/browser/console-log.d.ts +22 -0
  12. package/packages/@monomind/cli/dist/src/browser/console-log.js +55 -0
  13. package/packages/@monomind/cli/dist/src/browser/dialog.d.ts +11 -0
  14. package/packages/@monomind/cli/dist/src/browser/dialog.js +36 -0
  15. package/packages/@monomind/cli/dist/src/browser/emulation.d.ts +15 -0
  16. package/packages/@monomind/cli/dist/src/browser/emulation.js +62 -0
  17. package/packages/@monomind/cli/dist/src/browser/find.d.ts +21 -0
  18. package/packages/@monomind/cli/dist/src/browser/find.js +118 -0
  19. package/packages/@monomind/cli/dist/src/browser/index.d.ts +7 -0
  20. package/packages/@monomind/cli/dist/src/browser/index.js +7 -0
  21. package/packages/@monomind/cli/dist/src/browser/pdf.d.ts +15 -0
  22. package/packages/@monomind/cli/dist/src/browser/pdf.js +27 -0
  23. package/packages/@monomind/cli/dist/src/browser/storage.d.ts +11 -0
  24. package/packages/@monomind/cli/dist/src/browser/storage.js +43 -0
  25. package/packages/@monomind/cli/dist/src/commands/browse.js +939 -18
  26. package/packages/@monomind/cli/package.json +1 -1
@@ -0,0 +1,55 @@
1
+ let consoleMessages = [];
2
+ let pageErrors = [];
3
+ export function setupConsoleCapture(client, sessionId) {
4
+ client.on('Runtime.consoleAPICalled', (params, sid) => {
5
+ if (sid !== sessionId)
6
+ return;
7
+ const args = params.args ?? [];
8
+ const text = args.map((a) => a.description ?? String(a.value ?? '')).join(' ');
9
+ consoleMessages.push({
10
+ type: params.type ?? 'log',
11
+ text,
12
+ timestamp: Date.now(),
13
+ });
14
+ });
15
+ client.on('Log.entryAdded', (params, sid) => {
16
+ if (sid !== sessionId)
17
+ return;
18
+ const entry = params.entry;
19
+ consoleMessages.push({
20
+ type: entry.level ?? 'log',
21
+ text: entry.text ?? '',
22
+ timestamp: Date.now(),
23
+ url: entry.url,
24
+ lineNumber: entry.lineNumber,
25
+ });
26
+ });
27
+ client.on('Runtime.exceptionThrown', (params, sid) => {
28
+ if (sid !== sessionId)
29
+ return;
30
+ const detail = params.exceptionDetails;
31
+ pageErrors.push({
32
+ text: detail.text ?? 'Unknown error',
33
+ url: detail.url,
34
+ lineNumber: detail.lineNumber,
35
+ columnNumber: detail.columnNumber,
36
+ timestamp: Date.now(),
37
+ });
38
+ });
39
+ }
40
+ export async function enableConsoleCapture(client, sessionId) {
41
+ await client.send('Log.enable', {}, sessionId);
42
+ }
43
+ export function getConsoleMessages() {
44
+ return [...consoleMessages];
45
+ }
46
+ export function clearConsoleMessages() {
47
+ consoleMessages = [];
48
+ }
49
+ export function getPageErrors() {
50
+ return [...pageErrors];
51
+ }
52
+ export function clearPageErrors() {
53
+ pageErrors = [];
54
+ }
55
+ //# sourceMappingURL=console-log.js.map
@@ -0,0 +1,11 @@
1
+ import type { CdpClient } from './cdp.js';
2
+ export interface DialogInfo {
3
+ type: 'alert' | 'confirm' | 'prompt' | 'beforeunload';
4
+ message: string;
5
+ defaultPrompt?: string;
6
+ }
7
+ export declare function setupDialogAutoHandling(client: CdpClient, sessionId: string, autoAccept?: boolean): void;
8
+ export declare function acceptDialog(client: CdpClient, sessionId: string, text?: string): Promise<void>;
9
+ export declare function dismissDialog(client: CdpClient, sessionId: string): Promise<void>;
10
+ export declare function getDialogStatus(): DialogInfo | null;
11
+ //# sourceMappingURL=dialog.d.ts.map
@@ -0,0 +1,36 @@
1
+ let pendingDialog = null;
2
+ export function setupDialogAutoHandling(client, sessionId, autoAccept = true) {
3
+ client.on('Page.javascriptDialogOpening', async (params, sid) => {
4
+ if (sid !== sessionId)
5
+ return;
6
+ const info = {
7
+ type: params.type,
8
+ message: params.message,
9
+ defaultPrompt: params.defaultPrompt,
10
+ };
11
+ pendingDialog = info;
12
+ if (autoAccept && (info.type === 'alert' || info.type === 'beforeunload')) {
13
+ await client.send('Page.handleJavaScriptDialog', { accept: true }, sessionId);
14
+ pendingDialog = null;
15
+ }
16
+ });
17
+ client.on('Page.javascriptDialogClosed', (_, sid) => {
18
+ if (sid === sessionId)
19
+ pendingDialog = null;
20
+ });
21
+ }
22
+ export async function acceptDialog(client, sessionId, text) {
23
+ await client.send('Page.handleJavaScriptDialog', {
24
+ accept: true,
25
+ promptText: text,
26
+ }, sessionId);
27
+ pendingDialog = null;
28
+ }
29
+ export async function dismissDialog(client, sessionId) {
30
+ await client.send('Page.handleJavaScriptDialog', { accept: false }, sessionId);
31
+ pendingDialog = null;
32
+ }
33
+ export function getDialogStatus() {
34
+ return pendingDialog;
35
+ }
36
+ //# sourceMappingURL=dialog.js.map
@@ -0,0 +1,15 @@
1
+ import type { CdpClient } from './cdp.js';
2
+ export interface DeviceProfile {
3
+ width: number;
4
+ height: number;
5
+ deviceScaleFactor: number;
6
+ mobile: boolean;
7
+ userAgent: string;
8
+ }
9
+ export declare function emulateDevice(client: CdpClient, sessionId: string, deviceName: string): Promise<void>;
10
+ export declare function setGeolocation(client: CdpClient, sessionId: string, latitude: number, longitude: number, accuracy?: number): Promise<void>;
11
+ export declare function setOfflineMode(client: CdpClient, sessionId: string, offline: boolean): Promise<void>;
12
+ export declare function setColorScheme(client: CdpClient, sessionId: string, scheme: 'dark' | 'light' | 'no-preference'): Promise<void>;
13
+ export declare function setBasicAuth(client: CdpClient, sessionId: string, username: string, password: string): Promise<void>;
14
+ export declare function listDevices(): string[];
15
+ //# sourceMappingURL=emulation.d.ts.map
@@ -0,0 +1,62 @@
1
+ const DEVICES = {
2
+ 'iPhone 14': {
3
+ width: 390, height: 844, deviceScaleFactor: 3, mobile: true,
4
+ userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1',
5
+ },
6
+ 'iPhone SE': {
7
+ width: 375, height: 667, deviceScaleFactor: 2, mobile: true,
8
+ userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1',
9
+ },
10
+ 'iPad': {
11
+ width: 768, height: 1024, deviceScaleFactor: 2, mobile: true,
12
+ userAgent: 'Mozilla/5.0 (iPad; CPU OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1',
13
+ },
14
+ 'Galaxy S21': {
15
+ width: 360, height: 800, deviceScaleFactor: 3, mobile: true,
16
+ userAgent: 'Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36',
17
+ },
18
+ 'Pixel 5': {
19
+ width: 393, height: 851, deviceScaleFactor: 2.75, mobile: true,
20
+ userAgent: 'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36',
21
+ },
22
+ };
23
+ export async function emulateDevice(client, sessionId, deviceName) {
24
+ const device = DEVICES[deviceName];
25
+ if (!device) {
26
+ throw new Error(`Unknown device: "${deviceName}". Available: ${Object.keys(DEVICES).join(', ')}`);
27
+ }
28
+ await client.send('Emulation.setDeviceMetricsOverride', {
29
+ width: device.width,
30
+ height: device.height,
31
+ deviceScaleFactor: device.deviceScaleFactor,
32
+ mobile: device.mobile,
33
+ }, sessionId);
34
+ await client.send('Emulation.setUserAgentOverride', { userAgent: device.userAgent }, sessionId);
35
+ await client.send('Emulation.setTouchEmulationEnabled', { enabled: device.mobile }, sessionId);
36
+ }
37
+ export async function setGeolocation(client, sessionId, latitude, longitude, accuracy = 100) {
38
+ await client.send('Emulation.setGeolocationOverride', { latitude, longitude, accuracy }, sessionId);
39
+ }
40
+ export async function setOfflineMode(client, sessionId, offline) {
41
+ await client.send('Network.emulateNetworkConditions', {
42
+ offline,
43
+ latency: 0,
44
+ downloadThroughput: -1,
45
+ uploadThroughput: -1,
46
+ }, sessionId);
47
+ }
48
+ export async function setColorScheme(client, sessionId, scheme) {
49
+ await client.send('Emulation.setEmulatedMedia', {
50
+ features: [{ name: 'prefers-color-scheme', value: scheme }],
51
+ }, sessionId);
52
+ }
53
+ export async function setBasicAuth(client, sessionId, username, password) {
54
+ const encoded = Buffer.from(`${username}:${password}`).toString('base64');
55
+ await client.send('Network.setExtraHTTPHeaders', {
56
+ headers: { Authorization: `Basic ${encoded}` },
57
+ }, sessionId);
58
+ }
59
+ export function listDevices() {
60
+ return Object.keys(DEVICES);
61
+ }
62
+ //# sourceMappingURL=emulation.js.map
@@ -0,0 +1,21 @@
1
+ import type { CdpClient } from './cdp.js';
2
+ import type { ElementRef } from './types.js';
3
+ export type FindAction = 'click' | 'fill' | 'type' | 'hover' | 'focus' | 'check' | 'uncheck' | 'text';
4
+ export interface FindOptions {
5
+ name?: string;
6
+ exact?: boolean;
7
+ nth?: number;
8
+ first?: boolean;
9
+ last?: boolean;
10
+ }
11
+ export declare function findBySelector(client: CdpClient, sessionId: string, selector: string, options?: FindOptions): Promise<string | null>;
12
+ export declare function findByRole(client: CdpClient, sessionId: string, refs: Map<string, ElementRef>, role: string, options?: FindOptions): Promise<ElementRef | null>;
13
+ export declare function findByText(client: CdpClient, sessionId: string, refs: Map<string, ElementRef>, text: string, options?: FindOptions): Promise<ElementRef | null>;
14
+ export declare function findByLabel(client: CdpClient, sessionId: string, refs: Map<string, ElementRef>, label: string, options?: FindOptions): Promise<ElementRef | null>;
15
+ export declare function findByTestId(client: CdpClient, sessionId: string, testId: string): Promise<string | null>;
16
+ export declare function isVisible(client: CdpClient, sessionId: string, ref: ElementRef): Promise<boolean>;
17
+ export declare function isEnabled(client: CdpClient, sessionId: string, ref: ElementRef): Promise<boolean>;
18
+ export declare function isChecked(client: CdpClient, sessionId: string, ref: ElementRef): Promise<boolean>;
19
+ export declare function scrollIntoView(client: CdpClient, sessionId: string, ref: ElementRef): Promise<void>;
20
+ export declare function highlightElement(client: CdpClient, sessionId: string, ref: ElementRef): Promise<void>;
21
+ //# sourceMappingURL=find.d.ts.map
@@ -0,0 +1,118 @@
1
+ import { evaluateJs } from './actions.js';
2
+ import { getObjectIdForRef } from './snapshot.js';
3
+ export async function findBySelector(client, sessionId, selector, options = {}) {
4
+ let expr;
5
+ if (options.nth !== undefined) {
6
+ expr = `document.querySelectorAll(${JSON.stringify(selector)})[${options.nth - 1}]?.outerHTML ?? null`;
7
+ }
8
+ else if (options.last) {
9
+ expr = `Array.from(document.querySelectorAll(${JSON.stringify(selector)})).at(-1)?.outerHTML ?? null`;
10
+ }
11
+ else {
12
+ expr = `document.querySelector(${JSON.stringify(selector)})?.outerHTML ?? null`;
13
+ }
14
+ return evaluateJs(client, sessionId, expr);
15
+ }
16
+ export async function findByRole(client, sessionId, refs, role, options = {}) {
17
+ const lowerRole = role.toLowerCase();
18
+ const candidates = [...refs.values()].filter((r) => r.role.toLowerCase() === lowerRole);
19
+ let matches = candidates;
20
+ if (options.name) {
21
+ const nameLower = options.name.toLowerCase();
22
+ matches = options.exact
23
+ ? candidates.filter((r) => r.name.toLowerCase() === nameLower)
24
+ : candidates.filter((r) => r.name.toLowerCase().includes(nameLower));
25
+ }
26
+ if (matches.length === 0)
27
+ return null;
28
+ if (options.nth !== undefined)
29
+ return matches[options.nth - 1] ?? null;
30
+ if (options.last)
31
+ return matches[matches.length - 1];
32
+ return matches[0];
33
+ }
34
+ export async function findByText(client, sessionId, refs, text, options = {}) {
35
+ const lower = text.toLowerCase();
36
+ const candidates = [...refs.values()].filter((r) => options.exact ? r.name.toLowerCase() === lower : r.name.toLowerCase().includes(lower));
37
+ if (options.nth !== undefined)
38
+ return candidates[options.nth - 1] ?? null;
39
+ if (options.last)
40
+ return candidates[candidates.length - 1];
41
+ return candidates[0] ?? null;
42
+ }
43
+ export async function findByLabel(client, sessionId, refs, label, options = {}) {
44
+ return findByText(client, sessionId, refs, label, options);
45
+ }
46
+ export async function findByTestId(client, sessionId, testId) {
47
+ const selectors = [
48
+ `[data-testid="${testId}"]`,
49
+ `[data-test-id="${testId}"]`,
50
+ `[data-test="${testId}"]`,
51
+ ];
52
+ for (const sel of selectors) {
53
+ const result = await evaluateJs(client, sessionId, `!!document.querySelector(${JSON.stringify(sel)})`);
54
+ if (result)
55
+ return sel;
56
+ }
57
+ return null;
58
+ }
59
+ export async function isVisible(client, sessionId, ref) {
60
+ const objectId = await getObjectIdForRef(client, sessionId, ref);
61
+ if (!objectId)
62
+ return false;
63
+ const result = await client.send('Runtime.callFunctionOn', {
64
+ functionDeclaration: `function() {
65
+ const rect = this.getBoundingClientRect();
66
+ const style = window.getComputedStyle(this);
67
+ return rect.width > 0 && rect.height > 0 &&
68
+ style.display !== 'none' &&
69
+ style.visibility !== 'hidden' &&
70
+ style.opacity !== '0';
71
+ }`,
72
+ objectId,
73
+ returnByValue: true,
74
+ }, sessionId);
75
+ return result.result?.value ?? false;
76
+ }
77
+ export async function isEnabled(client, sessionId, ref) {
78
+ return !ref.disabled;
79
+ }
80
+ export async function isChecked(client, sessionId, ref) {
81
+ const objectId = await getObjectIdForRef(client, sessionId, ref);
82
+ if (!objectId)
83
+ return false;
84
+ const result = await client.send('Runtime.callFunctionOn', {
85
+ functionDeclaration: 'function() { return !!this.checked; }',
86
+ objectId,
87
+ returnByValue: true,
88
+ }, sessionId);
89
+ return result.result?.value ?? false;
90
+ }
91
+ export async function scrollIntoView(client, sessionId, ref) {
92
+ const objectId = await getObjectIdForRef(client, sessionId, ref);
93
+ if (!objectId)
94
+ throw new Error(`Cannot scroll: ref @${ref.ref} not found in DOM`);
95
+ await client.send('Runtime.callFunctionOn', {
96
+ functionDeclaration: 'function() { this.scrollIntoView({ behavior: "smooth", block: "center" }); }',
97
+ objectId,
98
+ }, sessionId);
99
+ }
100
+ export async function highlightElement(client, sessionId, ref) {
101
+ const objectId = await getObjectIdForRef(client, sessionId, ref);
102
+ if (!objectId)
103
+ return;
104
+ await client.send('Runtime.callFunctionOn', {
105
+ functionDeclaration: `function() {
106
+ const prev = this.style.outline;
107
+ const prevBg = this.style.backgroundColor;
108
+ this.style.outline = '3px solid #ff5722';
109
+ this.style.backgroundColor = 'rgba(255, 87, 34, 0.1)';
110
+ setTimeout(() => {
111
+ this.style.outline = prev;
112
+ this.style.backgroundColor = prevBg;
113
+ }, 2000);
114
+ }`,
115
+ objectId,
116
+ }, sessionId);
117
+ }
118
+ //# sourceMappingURL=find.js.map
@@ -8,4 +8,11 @@ export * from './network.js';
8
8
  export * from './screenshot.js';
9
9
  export * from './session.js';
10
10
  export * from './tabs.js';
11
+ export * from './dialog.js';
12
+ export * from './console-log.js';
13
+ export * from './storage.js';
14
+ export * from './find.js';
15
+ export * from './pdf.js';
16
+ export * from './emulation.js';
17
+ export * from './batch.js';
11
18
  //# sourceMappingURL=index.d.ts.map
@@ -8,4 +8,11 @@ export * from './network.js';
8
8
  export * from './screenshot.js';
9
9
  export * from './session.js';
10
10
  export * from './tabs.js';
11
+ export * from './dialog.js';
12
+ export * from './console-log.js';
13
+ export * from './storage.js';
14
+ export * from './find.js';
15
+ export * from './pdf.js';
16
+ export * from './emulation.js';
17
+ export * from './batch.js';
11
18
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,15 @@
1
+ import type { CdpClient } from './cdp.js';
2
+ export interface PdfOptions {
3
+ path?: string;
4
+ landscape?: boolean;
5
+ paperWidth?: number;
6
+ paperHeight?: number;
7
+ marginTop?: number;
8
+ marginBottom?: number;
9
+ marginLeft?: number;
10
+ marginRight?: number;
11
+ printBackground?: boolean;
12
+ scale?: number;
13
+ }
14
+ export declare function capturePdf(client: CdpClient, sessionId: string, options?: PdfOptions): Promise<string>;
15
+ //# sourceMappingURL=pdf.d.ts.map
@@ -0,0 +1,27 @@
1
+ import { writeFile } from 'fs/promises';
2
+ import { join } from 'path';
3
+ import { tmpdir } from 'os';
4
+ export async function capturePdf(client, sessionId, options = {}) {
5
+ const params = {
6
+ landscape: options.landscape ?? false,
7
+ printBackground: options.printBackground ?? true,
8
+ scale: options.scale ?? 1,
9
+ };
10
+ if (options.paperWidth)
11
+ params.paperWidth = options.paperWidth;
12
+ if (options.paperHeight)
13
+ params.paperHeight = options.paperHeight;
14
+ if (options.marginTop !== undefined)
15
+ params.marginTop = options.marginTop;
16
+ if (options.marginBottom !== undefined)
17
+ params.marginBottom = options.marginBottom;
18
+ if (options.marginLeft !== undefined)
19
+ params.marginLeft = options.marginLeft;
20
+ if (options.marginRight !== undefined)
21
+ params.marginRight = options.marginRight;
22
+ const result = await client.send('Page.printToPDF', params, sessionId);
23
+ const outputPath = options.path ?? join(tmpdir(), `monomind-pdf-${Date.now()}.pdf`);
24
+ await writeFile(outputPath, Buffer.from(result.data, 'base64'));
25
+ return outputPath;
26
+ }
27
+ //# sourceMappingURL=pdf.js.map
@@ -0,0 +1,11 @@
1
+ import type { CdpClient } from './cdp.js';
2
+ export declare function getLocalStorageKey(client: CdpClient, sessionId: string, key: string): Promise<string | null>;
3
+ export declare function setLocalStorageKey(client: CdpClient, sessionId: string, key: string, value: string): Promise<void>;
4
+ export declare function removeLocalStorageKey(client: CdpClient, sessionId: string, key: string): Promise<void>;
5
+ export declare function clearLocalStorage(client: CdpClient, sessionId: string): Promise<void>;
6
+ export declare function getAllLocalStorage(client: CdpClient, sessionId: string): Promise<Record<string, string>>;
7
+ export declare function getSessionStorageKey(client: CdpClient, sessionId: string, key: string): Promise<string | null>;
8
+ export declare function setSessionStorageKey(client: CdpClient, sessionId: string, key: string, value: string): Promise<void>;
9
+ export declare function clearSessionStorage(client: CdpClient, sessionId: string): Promise<void>;
10
+ export declare function getAllSessionStorage(client: CdpClient, sessionId: string): Promise<Record<string, string>>;
11
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1,43 @@
1
+ import { evaluateJs } from './actions.js';
2
+ export async function getLocalStorageKey(client, sessionId, key) {
3
+ const result = await evaluateJs(client, sessionId, `localStorage.getItem(${JSON.stringify(key)})`);
4
+ return result;
5
+ }
6
+ export async function setLocalStorageKey(client, sessionId, key, value) {
7
+ await evaluateJs(client, sessionId, `localStorage.setItem(${JSON.stringify(key)}, ${JSON.stringify(value)})`);
8
+ }
9
+ export async function removeLocalStorageKey(client, sessionId, key) {
10
+ await evaluateJs(client, sessionId, `localStorage.removeItem(${JSON.stringify(key)})`);
11
+ }
12
+ export async function clearLocalStorage(client, sessionId) {
13
+ await evaluateJs(client, sessionId, 'localStorage.clear()');
14
+ }
15
+ export async function getAllLocalStorage(client, sessionId) {
16
+ const result = await evaluateJs(client, sessionId, 'JSON.stringify(Object.fromEntries(Object.entries(localStorage)))');
17
+ try {
18
+ return JSON.parse(result);
19
+ }
20
+ catch {
21
+ return {};
22
+ }
23
+ }
24
+ export async function getSessionStorageKey(client, sessionId, key) {
25
+ const result = await evaluateJs(client, sessionId, `sessionStorage.getItem(${JSON.stringify(key)})`);
26
+ return result;
27
+ }
28
+ export async function setSessionStorageKey(client, sessionId, key, value) {
29
+ await evaluateJs(client, sessionId, `sessionStorage.setItem(${JSON.stringify(key)}, ${JSON.stringify(value)})`);
30
+ }
31
+ export async function clearSessionStorage(client, sessionId) {
32
+ await evaluateJs(client, sessionId, 'sessionStorage.clear()');
33
+ }
34
+ export async function getAllSessionStorage(client, sessionId) {
35
+ const result = await evaluateJs(client, sessionId, 'JSON.stringify(Object.fromEntries(Object.entries(sessionStorage)))');
36
+ try {
37
+ return JSON.parse(result);
38
+ }
39
+ catch {
40
+ return {};
41
+ }
42
+ }
43
+ //# sourceMappingURL=storage.js.map