haansi 0.1.6 → 0.1.8
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/haansi.js +191 -38
- package/package.json +1 -1
package/dist/haansi.js
CHANGED
|
@@ -34,6 +34,36 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
34
34
|
));
|
|
35
35
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
36
36
|
|
|
37
|
+
// package.json
|
|
38
|
+
var require_package = __commonJS({
|
|
39
|
+
"package.json"(exports2, module2) {
|
|
40
|
+
module2.exports = {
|
|
41
|
+
name: "haansi",
|
|
42
|
+
version: "0.1.8",
|
|
43
|
+
description: "Haansi CLI - Session collector and MCP server for Claude Code",
|
|
44
|
+
bin: {
|
|
45
|
+
haansi: "./dist/haansi.js"
|
|
46
|
+
},
|
|
47
|
+
files: [
|
|
48
|
+
"dist/",
|
|
49
|
+
"README.md"
|
|
50
|
+
],
|
|
51
|
+
scripts: {
|
|
52
|
+
build: "node build.mjs",
|
|
53
|
+
prepublishOnly: "npm run build"
|
|
54
|
+
},
|
|
55
|
+
devDependencies: {
|
|
56
|
+
esbuild: "^0.27.0",
|
|
57
|
+
typescript: "^5.7.2",
|
|
58
|
+
"@types/node": "^22.10.1"
|
|
59
|
+
},
|
|
60
|
+
engines: {
|
|
61
|
+
node: ">=18.0.0"
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
37
67
|
// src/commands/init.ts
|
|
38
68
|
var init_exports = {};
|
|
39
69
|
__export(init_exports, {
|
|
@@ -106,7 +136,7 @@ var init_init = __esm({
|
|
|
106
136
|
});
|
|
107
137
|
|
|
108
138
|
// ../../node_modules/dotenv/package.json
|
|
109
|
-
var
|
|
139
|
+
var require_package2 = __commonJS({
|
|
110
140
|
"../../node_modules/dotenv/package.json"(exports2, module2) {
|
|
111
141
|
module2.exports = {
|
|
112
142
|
name: "dotenv",
|
|
@@ -180,7 +210,7 @@ var require_main = __commonJS({
|
|
|
180
210
|
var path = require("path");
|
|
181
211
|
var os = require("os");
|
|
182
212
|
var crypto6 = require("crypto");
|
|
183
|
-
var packageJson =
|
|
213
|
+
var packageJson = require_package2();
|
|
184
214
|
var version3 = packageJson.version;
|
|
185
215
|
var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
|
|
186
216
|
function parse4(src) {
|
|
@@ -486,12 +516,12 @@ var init_logger = __esm({
|
|
|
486
516
|
}
|
|
487
517
|
debug(message, context) {
|
|
488
518
|
if (this.level <= 0 /* DEBUG */) {
|
|
489
|
-
console.
|
|
519
|
+
console.error(this.formatMessage("DEBUG", message, context));
|
|
490
520
|
}
|
|
491
521
|
}
|
|
492
522
|
info(message, context) {
|
|
493
523
|
if (this.level <= 1 /* INFO */) {
|
|
494
|
-
console.
|
|
524
|
+
console.error(this.formatMessage("INFO", message, context));
|
|
495
525
|
}
|
|
496
526
|
}
|
|
497
527
|
warn(message, context) {
|
|
@@ -56869,6 +56899,14 @@ var setup_mcp_exports = {};
|
|
|
56869
56899
|
__export(setup_mcp_exports, {
|
|
56870
56900
|
setupMcp: () => setupMcp
|
|
56871
56901
|
});
|
|
56902
|
+
function resolveHaansiBin() {
|
|
56903
|
+
try {
|
|
56904
|
+
const binPath = (0, import_node_child_process.execSync)("which haansi", { encoding: "utf-8" }).trim();
|
|
56905
|
+
if (binPath) return binPath;
|
|
56906
|
+
} catch {
|
|
56907
|
+
}
|
|
56908
|
+
return "haansi";
|
|
56909
|
+
}
|
|
56872
56910
|
async function setupMcp() {
|
|
56873
56911
|
let config6 = {};
|
|
56874
56912
|
if ((0, import_node_fs2.existsSync)(CLAUDE_JSON)) {
|
|
@@ -56883,23 +56921,26 @@ async function setupMcp() {
|
|
|
56883
56921
|
if (!config6.mcpServers) {
|
|
56884
56922
|
config6.mcpServers = {};
|
|
56885
56923
|
}
|
|
56924
|
+
const haansiBin = resolveHaansiBin();
|
|
56886
56925
|
config6.mcpServers["haansi-solutions"] = {
|
|
56887
|
-
command:
|
|
56888
|
-
args: ["
|
|
56926
|
+
command: haansiBin,
|
|
56927
|
+
args: ["mcp-server"]
|
|
56889
56928
|
};
|
|
56890
56929
|
(0, import_node_fs2.writeFileSync)(CLAUDE_JSON, JSON.stringify(config6, null, 2) + "\n", "utf-8");
|
|
56891
56930
|
console.log(`MCP server configured in ${CLAUDE_JSON}`);
|
|
56931
|
+
console.log(` command: ${haansiBin} mcp-server`);
|
|
56892
56932
|
console.log(
|
|
56893
|
-
"
|
|
56933
|
+
"\nRestart Claude Code to activate the haansi-solutions MCP server."
|
|
56894
56934
|
);
|
|
56895
56935
|
}
|
|
56896
|
-
var import_node_fs2, import_node_path2, import_node_os2, CLAUDE_JSON;
|
|
56936
|
+
var import_node_fs2, import_node_path2, import_node_os2, import_node_child_process, CLAUDE_JSON;
|
|
56897
56937
|
var init_setup_mcp = __esm({
|
|
56898
56938
|
"src/commands/setup-mcp.ts"() {
|
|
56899
56939
|
"use strict";
|
|
56900
56940
|
import_node_fs2 = require("node:fs");
|
|
56901
56941
|
import_node_path2 = require("node:path");
|
|
56902
56942
|
import_node_os2 = require("node:os");
|
|
56943
|
+
import_node_child_process = require("node:child_process");
|
|
56903
56944
|
CLAUDE_JSON = (0, import_node_path2.join)((0, import_node_os2.homedir)(), ".claude.json");
|
|
56904
56945
|
}
|
|
56905
56946
|
});
|
|
@@ -56911,7 +56952,7 @@ __export(setup_daemon_exports, {
|
|
|
56911
56952
|
});
|
|
56912
56953
|
function findHaansiBin() {
|
|
56913
56954
|
try {
|
|
56914
|
-
return (0,
|
|
56955
|
+
return (0, import_node_child_process2.execSync)("which haansi", { encoding: "utf-8" }).trim();
|
|
56915
56956
|
} catch {
|
|
56916
56957
|
throw new Error(
|
|
56917
56958
|
"Could not find haansi in PATH. Make sure it is installed globally (npm install -g haansi)."
|
|
@@ -56955,7 +56996,7 @@ async function setupDaemon(uninstall) {
|
|
|
56955
56996
|
return;
|
|
56956
56997
|
}
|
|
56957
56998
|
try {
|
|
56958
|
-
(0,
|
|
56999
|
+
(0, import_node_child_process2.execSync)(`launchctl unload "${PLIST_PATH}"`, { stdio: "pipe" });
|
|
56959
57000
|
} catch {
|
|
56960
57001
|
}
|
|
56961
57002
|
(0, import_node_fs3.unlinkSync)(PLIST_PATH);
|
|
@@ -56966,10 +57007,10 @@ async function setupDaemon(uninstall) {
|
|
|
56966
57007
|
(0, import_node_fs3.mkdirSync)((0, import_node_path3.join)((0, import_node_os3.homedir)(), ".haansi"), { recursive: true });
|
|
56967
57008
|
(0, import_node_fs3.writeFileSync)(PLIST_PATH, buildPlist(haansiPath), "utf-8");
|
|
56968
57009
|
try {
|
|
56969
|
-
(0,
|
|
57010
|
+
(0, import_node_child_process2.execSync)(`launchctl unload "${PLIST_PATH}"`, { stdio: "pipe" });
|
|
56970
57011
|
} catch {
|
|
56971
57012
|
}
|
|
56972
|
-
(0,
|
|
57013
|
+
(0, import_node_child_process2.execSync)(`launchctl load "${PLIST_PATH}"`, { stdio: "inherit" });
|
|
56973
57014
|
console.log("Daemon installed and started.");
|
|
56974
57015
|
console.log(`Plist : ${PLIST_PATH}`);
|
|
56975
57016
|
console.log(`Logs : ${LOG_FILE}`);
|
|
@@ -56977,11 +57018,11 @@ async function setupDaemon(uninstall) {
|
|
|
56977
57018
|
The daemon will start automatically on every login.`);
|
|
56978
57019
|
console.log(`To uninstall: haansi setup-daemon --uninstall`);
|
|
56979
57020
|
}
|
|
56980
|
-
var
|
|
57021
|
+
var import_node_child_process2, import_node_fs3, import_node_path3, import_node_os3, PLIST_LABEL, PLIST_PATH, LOG_FILE;
|
|
56981
57022
|
var init_setup_daemon = __esm({
|
|
56982
57023
|
"src/commands/setup-daemon.ts"() {
|
|
56983
57024
|
"use strict";
|
|
56984
|
-
|
|
57025
|
+
import_node_child_process2 = require("node:child_process");
|
|
56985
57026
|
import_node_fs3 = require("node:fs");
|
|
56986
57027
|
import_node_path3 = require("node:path");
|
|
56987
57028
|
import_node_os3 = require("node:os");
|
|
@@ -57112,7 +57153,9 @@ var init_config = __esm({
|
|
|
57112
57153
|
// src/commands/list.ts
|
|
57113
57154
|
var list_exports = {};
|
|
57114
57155
|
__export(list_exports, {
|
|
57115
|
-
list: () => list
|
|
57156
|
+
list: () => list,
|
|
57157
|
+
saveKnowledge: () => saveKnowledge,
|
|
57158
|
+
searchKnowledge: () => searchKnowledge
|
|
57116
57159
|
});
|
|
57117
57160
|
function resolveToken4() {
|
|
57118
57161
|
if (process.env.HAANSI_TOKEN) return process.env.HAANSI_TOKEN;
|
|
@@ -57135,6 +57178,21 @@ async function apiGet3(path, token, apiUrl) {
|
|
|
57135
57178
|
}
|
|
57136
57179
|
return response.json();
|
|
57137
57180
|
}
|
|
57181
|
+
async function apiPost2(path, body, token, apiUrl) {
|
|
57182
|
+
const response = await fetch(`${apiUrl}/api/v1${path}`, {
|
|
57183
|
+
method: "POST",
|
|
57184
|
+
headers: {
|
|
57185
|
+
Authorization: `Bearer ${token}`,
|
|
57186
|
+
"Content-Type": "application/json"
|
|
57187
|
+
},
|
|
57188
|
+
body: JSON.stringify(body)
|
|
57189
|
+
});
|
|
57190
|
+
if (!response.ok) {
|
|
57191
|
+
const text = await response.text().catch(() => "");
|
|
57192
|
+
throw new Error(`API error ${response.status}: ${text.slice(0, 200)}`);
|
|
57193
|
+
}
|
|
57194
|
+
return response.json();
|
|
57195
|
+
}
|
|
57138
57196
|
async function list(options) {
|
|
57139
57197
|
const apiUrl = process.env.HAANSI_API_URL ?? DEFAULT_API_URL5;
|
|
57140
57198
|
const token = resolveToken4();
|
|
@@ -57161,6 +57219,41 @@ async function list(options) {
|
|
|
57161
57219
|
console.log(`
|
|
57162
57220
|
${data.results.length} result(s)`);
|
|
57163
57221
|
}
|
|
57222
|
+
async function searchKnowledge(options) {
|
|
57223
|
+
const apiUrl = process.env.HAANSI_API_URL ?? DEFAULT_API_URL5;
|
|
57224
|
+
const token = resolveToken4();
|
|
57225
|
+
let url2 = `/sessions/knowledge/search?q=${encodeURIComponent(options.query)}&limit=${options.limit}`;
|
|
57226
|
+
if (options.artifactType) {
|
|
57227
|
+
url2 += `&artifact_type=${encodeURIComponent(options.artifactType)}`;
|
|
57228
|
+
}
|
|
57229
|
+
const data = await apiGet3(url2, token, apiUrl);
|
|
57230
|
+
if (!data.results || data.results.length === 0) {
|
|
57231
|
+
console.log("No knowledge artifacts found matching your query.");
|
|
57232
|
+
return;
|
|
57233
|
+
}
|
|
57234
|
+
const separator = "\n" + "\u2500".repeat(60) + "\n";
|
|
57235
|
+
console.log(data.results.join(separator));
|
|
57236
|
+
console.log(`
|
|
57237
|
+
${data.results.length} result(s)`);
|
|
57238
|
+
}
|
|
57239
|
+
async function saveKnowledge(options) {
|
|
57240
|
+
const apiUrl = process.env.HAANSI_API_URL ?? DEFAULT_API_URL5;
|
|
57241
|
+
const token = resolveToken4();
|
|
57242
|
+
const body = {
|
|
57243
|
+
problem_description: options.problem,
|
|
57244
|
+
solution_summary: options.solution,
|
|
57245
|
+
source_tool: "haansi-cli"
|
|
57246
|
+
};
|
|
57247
|
+
if (options.sessionType) body.session_type = options.sessionType;
|
|
57248
|
+
if (options.complexity) body.complexity = options.complexity;
|
|
57249
|
+
if (options.tags) body.tags = options.tags;
|
|
57250
|
+
const data = await apiPost2("/sessions/knowledge", body, token, apiUrl);
|
|
57251
|
+
console.log("Knowledge saved successfully.");
|
|
57252
|
+
console.log(` ID: ${data.id}`);
|
|
57253
|
+
console.log(` Problem: ${data.problem_description}`);
|
|
57254
|
+
console.log(` Solution: ${data.solution_summary}`);
|
|
57255
|
+
console.log("\nThis is now searchable via `haansi search-solutions`.");
|
|
57256
|
+
}
|
|
57164
57257
|
var import_node_fs5, import_node_path5, import_node_os5, DEFAULT_API_URL5, CREDENTIALS_FILE5;
|
|
57165
57258
|
var init_list = __esm({
|
|
57166
57259
|
"src/commands/list.ts"() {
|
|
@@ -57174,8 +57267,13 @@ var init_list = __esm({
|
|
|
57174
57267
|
});
|
|
57175
57268
|
|
|
57176
57269
|
// src/index.ts
|
|
57270
|
+
var { version: VERSION } = require_package();
|
|
57177
57271
|
var command = process.argv[2];
|
|
57178
57272
|
async function run2() {
|
|
57273
|
+
if (command === "--version" || command === "-v") {
|
|
57274
|
+
console.log(VERSION);
|
|
57275
|
+
return;
|
|
57276
|
+
}
|
|
57179
57277
|
switch (command) {
|
|
57180
57278
|
case "init": {
|
|
57181
57279
|
const { init: init2 } = await Promise.resolve().then(() => (init_init(), init_exports));
|
|
@@ -57226,11 +57324,13 @@ Collector done: ${uploaded} uploaded, ${skipped} unchanged, ${errors} errors`
|
|
|
57226
57324
|
await config6(process.argv.slice(3));
|
|
57227
57325
|
break;
|
|
57228
57326
|
}
|
|
57327
|
+
// ── Solution & Knowledge commands (consistent with MCP tool names) ──
|
|
57328
|
+
case "search-solutions":
|
|
57229
57329
|
case "search": {
|
|
57230
57330
|
const { list: list2 } = await Promise.resolve().then(() => (init_list(), list_exports));
|
|
57231
57331
|
const query = process.argv[3];
|
|
57232
57332
|
if (!query || query.startsWith("--")) {
|
|
57233
|
-
console.error("Usage: haansi search <query> [--limit <n>]");
|
|
57333
|
+
console.error("Usage: haansi search-solutions <query> [--limit <n>]");
|
|
57234
57334
|
process.exit(1);
|
|
57235
57335
|
}
|
|
57236
57336
|
const limitIdx = process.argv.indexOf("--limit");
|
|
@@ -57238,6 +57338,7 @@ Collector done: ${uploaded} uploaded, ${skipped} unchanged, ${errors} errors`
|
|
|
57238
57338
|
await list2({ search: query, limit });
|
|
57239
57339
|
break;
|
|
57240
57340
|
}
|
|
57341
|
+
case "list-solutions":
|
|
57241
57342
|
case "list": {
|
|
57242
57343
|
const { list: list2 } = await Promise.resolve().then(() => (init_list(), list_exports));
|
|
57243
57344
|
const searchIdx = process.argv.indexOf("--search");
|
|
@@ -57247,6 +57348,43 @@ Collector done: ${uploaded} uploaded, ${skipped} unchanged, ${errors} errors`
|
|
|
57247
57348
|
await list2({ search, limit });
|
|
57248
57349
|
break;
|
|
57249
57350
|
}
|
|
57351
|
+
case "search-knowledge": {
|
|
57352
|
+
const { searchKnowledge: searchKnowledge2 } = await Promise.resolve().then(() => (init_list(), list_exports));
|
|
57353
|
+
const query = process.argv[3];
|
|
57354
|
+
if (!query || query.startsWith("--")) {
|
|
57355
|
+
console.error(
|
|
57356
|
+
"Usage: haansi search-knowledge <query> [--type <artifact_type>] [--limit <n>]"
|
|
57357
|
+
);
|
|
57358
|
+
process.exit(1);
|
|
57359
|
+
}
|
|
57360
|
+
const typeIdx = process.argv.indexOf("--type");
|
|
57361
|
+
const artifactType = typeIdx !== -1 ? process.argv[typeIdx + 1] : void 0;
|
|
57362
|
+
const limitIdx = process.argv.indexOf("--limit");
|
|
57363
|
+
const limit = limitIdx !== -1 ? parseInt(process.argv[limitIdx + 1], 10) : 10;
|
|
57364
|
+
await searchKnowledge2({ query, artifactType, limit });
|
|
57365
|
+
break;
|
|
57366
|
+
}
|
|
57367
|
+
case "save-knowledge": {
|
|
57368
|
+
const { saveKnowledge: saveKnowledge2 } = await Promise.resolve().then(() => (init_list(), list_exports));
|
|
57369
|
+
const problemIdx = process.argv.indexOf("--problem");
|
|
57370
|
+
const solutionIdx = process.argv.indexOf("--solution");
|
|
57371
|
+
if (problemIdx === -1 || solutionIdx === -1) {
|
|
57372
|
+
console.error(
|
|
57373
|
+
'Usage: haansi save-knowledge --problem "description" --solution "summary" [--type <session_type>] [--complexity <simple|moderate|complex>] [--tags tag1,tag2]'
|
|
57374
|
+
);
|
|
57375
|
+
process.exit(1);
|
|
57376
|
+
}
|
|
57377
|
+
const problem = process.argv[problemIdx + 1];
|
|
57378
|
+
const solution = process.argv[solutionIdx + 1];
|
|
57379
|
+
const typeIdx = process.argv.indexOf("--type");
|
|
57380
|
+
const sessionType = typeIdx !== -1 ? process.argv[typeIdx + 1] : void 0;
|
|
57381
|
+
const complexityIdx = process.argv.indexOf("--complexity");
|
|
57382
|
+
const complexity = complexityIdx !== -1 ? process.argv[complexityIdx + 1] : void 0;
|
|
57383
|
+
const tagsIdx = process.argv.indexOf("--tags");
|
|
57384
|
+
const tags = tagsIdx !== -1 ? process.argv[tagsIdx + 1].split(",") : void 0;
|
|
57385
|
+
await saveKnowledge2({ problem, solution, sessionType, complexity, tags });
|
|
57386
|
+
break;
|
|
57387
|
+
}
|
|
57250
57388
|
case "help":
|
|
57251
57389
|
default: {
|
|
57252
57390
|
printUsage();
|
|
@@ -57257,37 +57395,52 @@ Collector done: ${uploaded} uploaded, ${skipped} unchanged, ${errors} errors`
|
|
|
57257
57395
|
}
|
|
57258
57396
|
function printUsage() {
|
|
57259
57397
|
console.log(`
|
|
57260
|
-
Haansi CLI \u2014 Session collector and MCP server for Claude Code
|
|
57398
|
+
Haansi CLI v${VERSION} \u2014 Session collector and MCP server for Claude Code
|
|
57261
57399
|
|
|
57262
57400
|
Usage:
|
|
57263
57401
|
haansi <command> [options]
|
|
57264
57402
|
|
|
57265
57403
|
Commands:
|
|
57266
|
-
init
|
|
57267
|
-
collect
|
|
57268
|
-
config get [key]
|
|
57269
|
-
config set <key> <val>
|
|
57270
|
-
|
|
57271
|
-
|
|
57272
|
-
|
|
57273
|
-
|
|
57274
|
-
|
|
57275
|
-
|
|
57276
|
-
|
|
57277
|
-
|
|
57278
|
-
|
|
57279
|
-
|
|
57404
|
+
init Authenticate and save your API token
|
|
57405
|
+
collect Upload new/changed Claude sessions once
|
|
57406
|
+
config get [key] Show your preferences (e.g. session_mode)
|
|
57407
|
+
config set <key> <val> Update a preference
|
|
57408
|
+
|
|
57409
|
+
search-solutions <query> Semantic search over mined solutions
|
|
57410
|
+
list-solutions List recent mined solutions
|
|
57411
|
+
search-knowledge <query> Search knowledge artifacts (cards, decisions, etc.)
|
|
57412
|
+
save-knowledge Save a problem/solution for future retrieval
|
|
57413
|
+
|
|
57414
|
+
daemon Run the collector on a schedule (every 30 min)
|
|
57415
|
+
mcp-server Start the Haansi MCP server (used by Claude Code)
|
|
57416
|
+
setup-mcp Add haansi-solutions MCP entry to ~/.claude.json
|
|
57417
|
+
setup-daemon Install launchd service to auto-start daemon on login (macOS)
|
|
57418
|
+
help Show this help message
|
|
57419
|
+
|
|
57420
|
+
Options:
|
|
57421
|
+
--version, -v Show installed version
|
|
57422
|
+
--limit <n> Number of results (default: 5 for search, 10 for list)
|
|
57423
|
+
|
|
57424
|
+
Options for search-knowledge:
|
|
57425
|
+
--type <artifact_type> Filter by type (knowledge_card, decision_record, etc.)
|
|
57426
|
+
|
|
57427
|
+
Options for save-knowledge:
|
|
57428
|
+
--problem "description" Problem description (required)
|
|
57429
|
+
--solution "summary" Solution summary (required)
|
|
57430
|
+
--type <session_type> Session type (bug_fix, feature, refactor, general)
|
|
57431
|
+
--complexity <level> simple, moderate, or complex
|
|
57432
|
+
--tags tag1,tag2 Comma-separated tags
|
|
57280
57433
|
|
|
57281
57434
|
Options for collect:
|
|
57282
|
-
--force-all
|
|
57283
|
-
--dry-run
|
|
57284
|
-
--limit <n>
|
|
57435
|
+
--force-all Re-upload all sessions, not just new ones
|
|
57436
|
+
--dry-run Scan without uploading
|
|
57437
|
+
--limit <n> Upload at most n sessions
|
|
57285
57438
|
|
|
57286
57439
|
Environment variables:
|
|
57287
|
-
HAANSI_TOKEN
|
|
57288
|
-
HAANSI_API_URL
|
|
57289
|
-
CLAUDE_PROJECT_PATH
|
|
57290
|
-
CLAUDE_COLLECT_SCHEDULE
|
|
57440
|
+
HAANSI_TOKEN API token (or use \`haansi init\` to save it)
|
|
57441
|
+
HAANSI_API_URL API base URL (default: https://api.haansi.co)
|
|
57442
|
+
CLAUDE_PROJECT_PATH Collect from a specific project path only
|
|
57443
|
+
CLAUDE_COLLECT_SCHEDULE Cron expression for daemon (default: */30 * * * *)
|
|
57291
57444
|
`);
|
|
57292
57445
|
}
|
|
57293
57446
|
run2().catch((err) => {
|