@mearl/native-host 2.0.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.
- package/README.md +99 -0
- package/dist/agent/codex-provider.d.ts +45 -0
- package/dist/agent/event-transport.d.ts +3 -0
- package/dist/agent/instructions.d.ts +1 -0
- package/dist/agent/manager.d.ts +44 -0
- package/dist/agent/process-env.d.ts +6 -0
- package/dist/agent/provider.d.ts +53 -0
- package/dist/agent/qoder-provider.d.ts +49 -0
- package/dist/agent/skill-manager.d.ts +28 -0
- package/dist/agent/workspace-directory.d.ts +4 -0
- package/dist/analytics.d.ts +1 -0
- package/dist/browser-inventory.d.ts +33 -0
- package/dist/browser-registry.d.ts +78 -0
- package/dist/cdp-backend/action-registry.d.ts +35 -0
- package/dist/cdp-backend/browser-handlers.d.ts +7 -0
- package/dist/cdp-backend/buffers.d.ts +46 -0
- package/dist/cdp-backend/cdp-session.d.ts +60 -0
- package/dist/cdp-backend/cdp-utils.d.ts +66 -0
- package/dist/cdp-backend/client.d.ts +47 -0
- package/dist/cdp-backend/composite-handlers.d.ts +19 -0
- package/dist/cdp-backend/controlled-indicator.d.ts +17 -0
- package/dist/cdp-backend/cookie-transfer.d.ts +25 -0
- package/dist/cdp-backend/discover.d.ts +28 -0
- package/dist/cdp-backend/domain-manager.d.ts +4 -0
- package/dist/cdp-backend/handlers.d.ts +29 -0
- package/dist/cdp-backend/http-handlers.d.ts +7 -0
- package/dist/cdp-backend/interaction-handlers.d.ts +16 -0
- package/dist/cdp-backend/mock-handlers.d.ts +6 -0
- package/dist/cdp-backend/navigation-observer.d.ts +7 -0
- package/dist/cdp-backend/page-observer.d.ts +5 -0
- package/dist/cdp-backend/recording-handlers.d.ts +9 -0
- package/dist/cdp-backend/request-handlers.d.ts +7 -0
- package/dist/cdp-backend/snapshot-handlers.d.ts +6 -0
- package/dist/cdp-backend/tab-handlers.d.ts +7 -0
- package/dist/cdp-backend/tdbank-handlers.d.ts +13 -0
- package/dist/cdp-backend/timezone-handlers.d.ts +3 -0
- package/dist/cloud-connector.d.ts +56 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +26945 -0
- package/dist/install.d.ts +36 -0
- package/dist/install.js +220 -0
- package/dist/managed-browser.d.ts +85 -0
- package/package.json +44 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified Native Messaging Host installer for Mearl.
|
|
3
|
+
*
|
|
4
|
+
* Registers a Chrome Native Messaging Host manifest so that the browser
|
|
5
|
+
* extension can launch the native-host process via `chrome.runtime.connectNative()`.
|
|
6
|
+
*
|
|
7
|
+
* Both MCP and Skills integration modes share this installer. By default it
|
|
8
|
+
* installs both hosts (they run the same binary and share one Unix socket, so
|
|
9
|
+
* the two integrations can be used at the same time); pass a specific `--mode`
|
|
10
|
+
* (CLI) or `mode` option (API) to install just one.
|
|
11
|
+
*
|
|
12
|
+
* CLI:
|
|
13
|
+
* mearl-native-host --init [--mode skills|mcp|both] [--extension-id <id>]
|
|
14
|
+
*
|
|
15
|
+
* API:
|
|
16
|
+
* import { installNativeHost } from '@mearl/native-host';
|
|
17
|
+
* await installNativeHost(); // installs both
|
|
18
|
+
*/
|
|
19
|
+
export type IntegrationMode = 'skills' | 'mcp';
|
|
20
|
+
export interface InstallOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Integration mode. Determines the host name. Defaults to `'both'`, which
|
|
23
|
+
* installs the manifests for both Skills and MCP so the two integrations can
|
|
24
|
+
* be used simultaneously (they share the same Unix socket and handlers).
|
|
25
|
+
*/
|
|
26
|
+
mode?: IntegrationMode | 'both';
|
|
27
|
+
/** Chrome extension ID. Defaults to the published store ID. */
|
|
28
|
+
extensionId?: string;
|
|
29
|
+
/** Suppress console output when `true`. Uses stderr to avoid interfering with stdio transport. */
|
|
30
|
+
silent?: boolean;
|
|
31
|
+
/** Skip installation if the manifest file already exists. Defaults to `false`. */
|
|
32
|
+
skipIfExists?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export declare function resolveHostDir(): string;
|
|
35
|
+
export declare function installNativeHost(options?: InstallOptions): Promise<boolean>;
|
|
36
|
+
export declare function runCli(argv: string[]): Promise<void>;
|
package/dist/install.js
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
// src/install.ts
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import { execFileSync } from "node:child_process";
|
|
6
|
+
import { createRequire } from "node:module";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
var DEFAULT_EXTENSION_ID = "aoehhjnofngknnjefamjbplchbolghkm";
|
|
9
|
+
var HOST_NAME_BY_MODE = {
|
|
10
|
+
skills: "com.alibaba.mearl.skills",
|
|
11
|
+
mcp: "com.alibaba.mearl.mcp"
|
|
12
|
+
};
|
|
13
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
var __dirname = path.dirname(__filename);
|
|
15
|
+
var ALL_MODES = ["skills", "mcp"];
|
|
16
|
+
function resolveHostDir() {
|
|
17
|
+
switch (process.platform) {
|
|
18
|
+
case "darwin":
|
|
19
|
+
return path.join(
|
|
20
|
+
os.homedir(),
|
|
21
|
+
"Library/Application Support/Google/Chrome/NativeMessagingHosts"
|
|
22
|
+
);
|
|
23
|
+
case "linux":
|
|
24
|
+
return path.join(os.homedir(), ".config/google-chrome/NativeMessagingHosts");
|
|
25
|
+
case "win32":
|
|
26
|
+
return path.join(
|
|
27
|
+
process.env.PROGRAMDATA || "C:\\ProgramData",
|
|
28
|
+
"Google\\Chrome\\NativeMessagingHosts"
|
|
29
|
+
);
|
|
30
|
+
default:
|
|
31
|
+
throw new Error(`Unsupported platform: ${process.platform}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function resolveNativeHostPath() {
|
|
35
|
+
const siblingPath = path.join(__dirname, "index.js");
|
|
36
|
+
if (fs.existsSync(siblingPath)) {
|
|
37
|
+
return siblingPath;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const require2 = createRequire(import.meta.url);
|
|
41
|
+
return require2.resolve("@mearl/native-host/runtime");
|
|
42
|
+
} catch {
|
|
43
|
+
throw new Error(
|
|
44
|
+
"Cannot locate native-host runtime entry point. Ensure @mearl/native-host is installed correctly."
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function registerWindowsNativeHost(hostName, manifestPath) {
|
|
49
|
+
const regKey = `HKCU\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\${hostName}`;
|
|
50
|
+
execFileSync("reg", ["add", regKey, "/ve", "/t", "REG_SZ", "/d", manifestPath, "/f"], {
|
|
51
|
+
stdio: "pipe"
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function createLauncherScript(hostDir, hostPath, hostName) {
|
|
55
|
+
const nodePath = path.resolve(process.execPath);
|
|
56
|
+
if (process.platform === "win32") {
|
|
57
|
+
const launcherPath2 = path.join(hostDir, `${hostName}-launcher.cmd`);
|
|
58
|
+
const content2 = `@echo off\r
|
|
59
|
+
"${nodePath}" "${hostPath}" %*\r
|
|
60
|
+
`;
|
|
61
|
+
fs.writeFileSync(launcherPath2, content2, "utf-8");
|
|
62
|
+
return launcherPath2;
|
|
63
|
+
}
|
|
64
|
+
const launcherPath = path.join(hostDir, `${hostName}-launcher.sh`);
|
|
65
|
+
const content = [
|
|
66
|
+
"#!/bin/sh",
|
|
67
|
+
`NODE_BIN=${JSON.stringify(nodePath)}`,
|
|
68
|
+
`HOST_SCRIPT=${JSON.stringify(hostPath)}`,
|
|
69
|
+
'exec "$NODE_BIN" "$HOST_SCRIPT" "$@"',
|
|
70
|
+
""
|
|
71
|
+
].join("\n");
|
|
72
|
+
fs.writeFileSync(launcherPath, content, "utf-8");
|
|
73
|
+
fs.chmodSync(launcherPath, 493);
|
|
74
|
+
return launcherPath;
|
|
75
|
+
}
|
|
76
|
+
async function installNativeHost(options = {}) {
|
|
77
|
+
const {
|
|
78
|
+
mode = "both",
|
|
79
|
+
extensionId = DEFAULT_EXTENSION_ID,
|
|
80
|
+
silent = false,
|
|
81
|
+
skipIfExists = false
|
|
82
|
+
} = options;
|
|
83
|
+
if (mode === "both") {
|
|
84
|
+
const results = await Promise.all(
|
|
85
|
+
ALL_MODES.map((m) => installNativeHost({ ...options, mode: m }))
|
|
86
|
+
);
|
|
87
|
+
return results.every(Boolean);
|
|
88
|
+
}
|
|
89
|
+
const hostName = HOST_NAME_BY_MODE[mode];
|
|
90
|
+
if (!hostName) {
|
|
91
|
+
throw new Error(`Unknown mode: ${mode}. Expected 'skills' or 'mcp'.`);
|
|
92
|
+
}
|
|
93
|
+
const log = (...args) => {
|
|
94
|
+
if (!silent) console.error(...args);
|
|
95
|
+
};
|
|
96
|
+
try {
|
|
97
|
+
const hostDir = resolveHostDir();
|
|
98
|
+
if (skipIfExists) {
|
|
99
|
+
const manifestPath2 = path.join(hostDir, `${hostName}.json`);
|
|
100
|
+
if (fs.existsSync(manifestPath2)) {
|
|
101
|
+
log(`✅ Already installed: ${manifestPath2}`);
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (!fs.existsSync(hostDir)) {
|
|
106
|
+
fs.mkdirSync(hostDir, { recursive: true });
|
|
107
|
+
log(`✅ Created directory: ${hostDir}`);
|
|
108
|
+
}
|
|
109
|
+
const resolvedHostPath = resolveNativeHostPath();
|
|
110
|
+
log(`✅ Native host path: ${resolvedHostPath}`);
|
|
111
|
+
const launcherPath = createLauncherScript(hostDir, resolvedHostPath, hostName);
|
|
112
|
+
log(`✅ Launcher script: ${launcherPath}`);
|
|
113
|
+
const manifest = {
|
|
114
|
+
name: hostName,
|
|
115
|
+
description: "Mearl Native Messaging Bridge",
|
|
116
|
+
path: launcherPath,
|
|
117
|
+
type: "stdio",
|
|
118
|
+
allowed_origins: [`chrome-extension://${extensionId}/`]
|
|
119
|
+
};
|
|
120
|
+
const manifestPath = path.join(hostDir, `${hostName}.json`);
|
|
121
|
+
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
122
|
+
if (process.platform === "win32") {
|
|
123
|
+
registerWindowsNativeHost(hostName, manifestPath);
|
|
124
|
+
log(`✅ Windows registry key created for: ${hostName}`);
|
|
125
|
+
} else {
|
|
126
|
+
fs.chmodSync(manifestPath, 420);
|
|
127
|
+
}
|
|
128
|
+
log(`✅ Manifest installed: ${manifestPath}`);
|
|
129
|
+
log(`✅ Extension ID: ${extensionId}`);
|
|
130
|
+
log(`✅ Host name: ${hostName}`);
|
|
131
|
+
return true;
|
|
132
|
+
} catch (error) {
|
|
133
|
+
log(`❌ Installation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
134
|
+
if (error instanceof Error && "code" in error && error.code === "EACCES") {
|
|
135
|
+
log("\n Permission denied. Try running with sudo.");
|
|
136
|
+
}
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function parseCliArgs(argv) {
|
|
141
|
+
let mode = "both";
|
|
142
|
+
let extensionId;
|
|
143
|
+
let skipIfExists = false;
|
|
144
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
145
|
+
const arg = argv[i];
|
|
146
|
+
if (arg === "--help" || arg === "-h") {
|
|
147
|
+
return { showHelp: true, mode, skipIfExists };
|
|
148
|
+
}
|
|
149
|
+
if (arg === "--mode" || arg.startsWith("--mode=")) {
|
|
150
|
+
const value = arg.includes("=") ? arg.slice("--mode=".length) : argv[++i];
|
|
151
|
+
if (value !== "skills" && value !== "mcp" && value !== "both") {
|
|
152
|
+
console.error(`❌ Invalid mode: ${value}. Expected 'skills', 'mcp', or 'both'.`);
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
mode = value;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (arg === "--extension-id" || arg.startsWith("--extension-id=")) {
|
|
159
|
+
extensionId = arg.includes("=") ? arg.slice("--extension-id=".length) : argv[++i];
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (arg === "--skip-if-exists") {
|
|
163
|
+
skipIfExists = true;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (arg === "--init") {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return { showHelp: false, mode, extensionId, skipIfExists };
|
|
171
|
+
}
|
|
172
|
+
function printHelp() {
|
|
173
|
+
console.error(`Usage:
|
|
174
|
+
mearl-native-host --init [options]
|
|
175
|
+
|
|
176
|
+
Options:
|
|
177
|
+
--mode <skills|mcp|both> Integration mode (default: both — installs both hosts)
|
|
178
|
+
--extension-id <id> Chrome extension ID (default: ${DEFAULT_EXTENSION_ID})
|
|
179
|
+
-h, --help Show this help message
|
|
180
|
+
|
|
181
|
+
Examples:
|
|
182
|
+
mearl-native-host --init
|
|
183
|
+
mearl-native-host --init --mode mcp
|
|
184
|
+
mearl-native-host --init --extension-id abcdefghijklmnopqrstuvwxyzabcdef`);
|
|
185
|
+
}
|
|
186
|
+
async function runCli(argv) {
|
|
187
|
+
const parsed = parseCliArgs(argv);
|
|
188
|
+
if (parsed.showHelp) {
|
|
189
|
+
printHelp();
|
|
190
|
+
process.exit(0);
|
|
191
|
+
}
|
|
192
|
+
if (parsed.extensionId && !/^[a-z]{32}$/.test(parsed.extensionId)) {
|
|
193
|
+
console.error(`❌ Invalid extension ID: ${parsed.extensionId}`);
|
|
194
|
+
console.error(" Must be a 32-character lowercase string (see chrome://extensions/)");
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
const success = await installNativeHost({
|
|
198
|
+
mode: parsed.mode,
|
|
199
|
+
extensionId: parsed.extensionId,
|
|
200
|
+
skipIfExists: parsed.skipIfExists
|
|
201
|
+
});
|
|
202
|
+
if (success) {
|
|
203
|
+
console.error(`
|
|
204
|
+
✅ Installation complete!
|
|
205
|
+
|
|
206
|
+
Next steps:
|
|
207
|
+
1. Ensure Chrome is running (the extension auto-connects to native host)
|
|
208
|
+
2. Start using CLI commands
|
|
209
|
+
|
|
210
|
+
Verify:
|
|
211
|
+
mearl get_requests --payload '{"count":1}'
|
|
212
|
+
`);
|
|
213
|
+
}
|
|
214
|
+
process.exit(success ? 0 : 1);
|
|
215
|
+
}
|
|
216
|
+
export {
|
|
217
|
+
installNativeHost,
|
|
218
|
+
resolveHostDir,
|
|
219
|
+
runCli
|
|
220
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/** Managed Chrome lifecycle for isolated, optionally headless browser instances. */
|
|
2
|
+
import { type DaemonRecord } from '@mearl/daemon-core';
|
|
3
|
+
import { type TransferableCookie } from './cdp-backend/cookie-transfer.js';
|
|
4
|
+
export type ManagedBrowserUserAgentMode = 'default' | 'desktop';
|
|
5
|
+
export interface ManagedBrowserLaunchParams {
|
|
6
|
+
name: string;
|
|
7
|
+
headless?: boolean;
|
|
8
|
+
userAgentMode?: ManagedBrowserUserAgentMode;
|
|
9
|
+
persistent?: boolean;
|
|
10
|
+
executablePath?: string;
|
|
11
|
+
url?: string;
|
|
12
|
+
accountId?: string | number;
|
|
13
|
+
havanaId?: string | number;
|
|
14
|
+
site?: string | number;
|
|
15
|
+
query?: string;
|
|
16
|
+
tabId?: number;
|
|
17
|
+
copyCookieDomains?: string[];
|
|
18
|
+
}
|
|
19
|
+
export interface TdbankSsoTicket {
|
|
20
|
+
ssoUrl: string;
|
|
21
|
+
account: {
|
|
22
|
+
accountId?: string;
|
|
23
|
+
havanaId: string;
|
|
24
|
+
site: string;
|
|
25
|
+
loginId?: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
interface ManagedBrowserRecord extends DaemonRecord {
|
|
29
|
+
pid: number;
|
|
30
|
+
hostPid: number;
|
|
31
|
+
browserId: string;
|
|
32
|
+
name: string;
|
|
33
|
+
headless: boolean;
|
|
34
|
+
persistent: boolean;
|
|
35
|
+
userDataDir: string;
|
|
36
|
+
executablePath: string;
|
|
37
|
+
cdpPort: number;
|
|
38
|
+
createdAt: string;
|
|
39
|
+
account?: {
|
|
40
|
+
accountId?: string;
|
|
41
|
+
loginId?: string;
|
|
42
|
+
nickname: string;
|
|
43
|
+
};
|
|
44
|
+
copiedCookies?: {
|
|
45
|
+
domains: string[];
|
|
46
|
+
count: number;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export interface ManagedBrowserSummary {
|
|
50
|
+
browserId: string;
|
|
51
|
+
name: string;
|
|
52
|
+
headless: boolean;
|
|
53
|
+
persistent: boolean;
|
|
54
|
+
cdpPort: number;
|
|
55
|
+
createdAt: string;
|
|
56
|
+
account?: ManagedBrowserRecord['account'];
|
|
57
|
+
copiedCookies?: ManagedBrowserRecord['copiedCookies'];
|
|
58
|
+
running: boolean;
|
|
59
|
+
}
|
|
60
|
+
export interface ManagedBrowserManagerDeps {
|
|
61
|
+
nativeHostScript: string;
|
|
62
|
+
prepareTdbankSso: (data: ManagedBrowserLaunchParams) => Promise<TdbankSsoTicket>;
|
|
63
|
+
exportCookies: (domains: string[]) => Promise<TransferableCookie[]>;
|
|
64
|
+
log: (...args: any[]) => void;
|
|
65
|
+
}
|
|
66
|
+
/** Use one case-insensitive identity for registry, locking, and persistent profile paths. */
|
|
67
|
+
export declare function managedBrowserId(name: string): string;
|
|
68
|
+
export declare function chromeExecutableCandidates(platform?: NodeJS.Platform): string[];
|
|
69
|
+
export declare function resolveChromeExecutable(explicitPath?: string): string;
|
|
70
|
+
export declare function desktopChromeUserAgent(version: string, platform?: NodeJS.Platform): string;
|
|
71
|
+
export declare function resolveChromeVersion(executablePath: string): string;
|
|
72
|
+
export declare function resolveUserAgentMode(value: unknown): ManagedBrowserUserAgentMode;
|
|
73
|
+
export declare function buildManagedChromeArgs(options: {
|
|
74
|
+
userDataDir: string;
|
|
75
|
+
headless: boolean;
|
|
76
|
+
userAgent?: string;
|
|
77
|
+
}): string[];
|
|
78
|
+
/** Verify both PID liveness and the instance-specific command line before managing a process. */
|
|
79
|
+
export declare function isManagedProcess(pid: number, commandMarker: string, platform?: NodeJS.Platform): boolean;
|
|
80
|
+
export declare function listManagedBrowsers(): ManagedBrowserSummary[];
|
|
81
|
+
export declare function launchManagedBrowser(input: ManagedBrowserLaunchParams, deps: ManagedBrowserManagerDeps): Promise<Record<string, any>>;
|
|
82
|
+
export declare function closeManagedBrowser(selector: string, options?: {
|
|
83
|
+
deleteProfile?: boolean;
|
|
84
|
+
}): Promise<Record<string, any>>;
|
|
85
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mearl/native-host",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Native Messaging Host for Mearl — bridges Chrome Extension and local socket server",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/install.js",
|
|
7
|
+
"types": "dist/install.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/install.d.ts",
|
|
11
|
+
"default": "./dist/install.js"
|
|
12
|
+
},
|
|
13
|
+
"./runtime": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"bin": {
|
|
16
|
+
"mearl-native-host": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"keywords": [
|
|
22
|
+
"mearl",
|
|
23
|
+
"chrome-extension",
|
|
24
|
+
"native-messaging"
|
|
25
|
+
],
|
|
26
|
+
"license": "ISC",
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"registry": "https://registry.npmjs.org"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@agentclientprotocol/sdk": "^1.2.1",
|
|
32
|
+
"@types/node": "^24.9.1",
|
|
33
|
+
"esbuild": "^0.25.2",
|
|
34
|
+
"typescript": "^5.8.3",
|
|
35
|
+
"@mearl/daemon-core": "2.0.0",
|
|
36
|
+
"@mearl/browser-core": "2.0.0"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "rm -rf dist/ && node build.mjs",
|
|
40
|
+
"typecheck": "tsc --noEmit",
|
|
41
|
+
"test": "vitest run",
|
|
42
|
+
"postinstall": "node dist/index.js --init || true"
|
|
43
|
+
}
|
|
44
|
+
}
|