@hasna/mementos 0.9.0 → 0.10.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 +10 -0
- package/dist/cli/index.js +279 -3
- package/dist/mcp/index.js +26 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,8 +8,11 @@ Agents save, recall, search, and share memories across sessions. Memories are sc
|
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
bun add -g @hasna/mementos
|
|
11
|
+
mementos init
|
|
11
12
|
```
|
|
12
13
|
|
|
14
|
+
That's it. `init` registers the MCP with Claude Code, installs the session stop hook, and configures the server to start automatically on login.
|
|
15
|
+
|
|
13
16
|
## Quick Start
|
|
14
17
|
|
|
15
18
|
```bash
|
|
@@ -27,6 +30,9 @@ mementos inject --format compact --project-id <id>
|
|
|
27
30
|
|
|
28
31
|
# Get stats
|
|
29
32
|
mementos stats
|
|
33
|
+
|
|
34
|
+
# Check everything is working
|
|
35
|
+
mementos doctor
|
|
30
36
|
```
|
|
31
37
|
|
|
32
38
|
## MCP Server
|
|
@@ -34,6 +40,10 @@ mementos stats
|
|
|
34
40
|
### Install into Claude Code (recommended)
|
|
35
41
|
|
|
36
42
|
```bash
|
|
43
|
+
# One-command setup (MCP + stop hook + auto-start):
|
|
44
|
+
mementos init
|
|
45
|
+
|
|
46
|
+
# Or just the MCP server:
|
|
37
47
|
mementos mcp --claude
|
|
38
48
|
# Or manually:
|
|
39
49
|
claude mcp add --transport stdio --scope user mementos -- mementos-mcp
|
package/dist/cli/index.js
CHANGED
|
@@ -7443,6 +7443,236 @@ function resolveKeyOrId(keyOrId, opts, globalOpts) {
|
|
|
7443
7443
|
return null;
|
|
7444
7444
|
}
|
|
7445
7445
|
program2.name("mementos").description("Universal memory system for AI agents").version(getPackageVersion()).option("--project <path>", "Project path for scoping").option("--json", "Output as JSON").option("--format <fmt>", "Output format: compact, json, csv, yaml").option("--agent <name>", "Agent name or ID").option("--session <id>", "Session ID");
|
|
7446
|
+
program2.command("init").description("One-command setup: register MCP, install stop hook, configure auto-start").action(async () => {
|
|
7447
|
+
const { platform } = process;
|
|
7448
|
+
const home = homedir2();
|
|
7449
|
+
const isMac = platform === "darwin";
|
|
7450
|
+
console.log("");
|
|
7451
|
+
console.log(chalk.bold(" mementos \u2014 setting up your memory layer"));
|
|
7452
|
+
console.log("");
|
|
7453
|
+
async function run(cmd) {
|
|
7454
|
+
try {
|
|
7455
|
+
const proc = Bun.spawn(cmd, {
|
|
7456
|
+
stdout: "pipe",
|
|
7457
|
+
stderr: "pipe"
|
|
7458
|
+
});
|
|
7459
|
+
const [out, err, exitCode] = await Promise.all([
|
|
7460
|
+
new Response(proc.stdout).text(),
|
|
7461
|
+
new Response(proc.stderr).text(),
|
|
7462
|
+
proc.exited
|
|
7463
|
+
]);
|
|
7464
|
+
return { ok: exitCode === 0, output: (out + err).trim() };
|
|
7465
|
+
} catch (e) {
|
|
7466
|
+
return { ok: false, output: e instanceof Error ? e.message : String(e) };
|
|
7467
|
+
}
|
|
7468
|
+
}
|
|
7469
|
+
let mcpAlreadyInstalled = false;
|
|
7470
|
+
let mcpError = null;
|
|
7471
|
+
try {
|
|
7472
|
+
const list = await run(["claude", "mcp", "list"]);
|
|
7473
|
+
if (list.output.includes("mementos")) {
|
|
7474
|
+
mcpAlreadyInstalled = true;
|
|
7475
|
+
} else {
|
|
7476
|
+
const add = await run([
|
|
7477
|
+
"claude",
|
|
7478
|
+
"mcp",
|
|
7479
|
+
"add",
|
|
7480
|
+
"--transport",
|
|
7481
|
+
"stdio",
|
|
7482
|
+
"--scope",
|
|
7483
|
+
"user",
|
|
7484
|
+
"mementos",
|
|
7485
|
+
"--",
|
|
7486
|
+
"mementos-mcp"
|
|
7487
|
+
]);
|
|
7488
|
+
if (!add.ok) {
|
|
7489
|
+
mcpError = add.output || "unknown error";
|
|
7490
|
+
}
|
|
7491
|
+
}
|
|
7492
|
+
} catch (e) {
|
|
7493
|
+
mcpError = e instanceof Error ? e.message : String(e);
|
|
7494
|
+
}
|
|
7495
|
+
if (mcpAlreadyInstalled) {
|
|
7496
|
+
console.log(chalk.dim(" \xB7 MCP already registered"));
|
|
7497
|
+
} else if (mcpError) {
|
|
7498
|
+
console.log(chalk.red(` \u2717 Failed to register MCP: ${mcpError}`));
|
|
7499
|
+
console.log(chalk.dim(" (Is Claude Code installed? Try: claude mcp add --transport stdio --scope user mementos -- mementos-mcp)"));
|
|
7500
|
+
} else {
|
|
7501
|
+
console.log(chalk.green(" \u2713 MCP server registered with Claude Code"));
|
|
7502
|
+
}
|
|
7503
|
+
const hooksDir = join3(home, ".claude", "hooks");
|
|
7504
|
+
const hookDest = join3(hooksDir, "mementos-stop-hook.ts");
|
|
7505
|
+
const settingsPath = join3(home, ".claude", "settings.json");
|
|
7506
|
+
const hookCommand = `bun ${hookDest}`;
|
|
7507
|
+
let hookAlreadyInstalled = false;
|
|
7508
|
+
let hookError = null;
|
|
7509
|
+
try {
|
|
7510
|
+
let settings = {};
|
|
7511
|
+
if (existsSync3(settingsPath)) {
|
|
7512
|
+
try {
|
|
7513
|
+
settings = JSON.parse(readFileSync2(settingsPath, "utf-8"));
|
|
7514
|
+
} catch {
|
|
7515
|
+
settings = {};
|
|
7516
|
+
}
|
|
7517
|
+
}
|
|
7518
|
+
const hooksObj = settings["hooks"] || {};
|
|
7519
|
+
const stopHooks = hooksObj["Stop"] || [];
|
|
7520
|
+
const alreadyHasMementos = stopHooks.some((entry) => entry.hooks?.some((h) => h.command && h.command.includes("mementos")));
|
|
7521
|
+
if (alreadyHasMementos) {
|
|
7522
|
+
hookAlreadyInstalled = true;
|
|
7523
|
+
} else {
|
|
7524
|
+
if (!existsSync3(hooksDir)) {
|
|
7525
|
+
mkdirSync3(hooksDir, { recursive: true });
|
|
7526
|
+
}
|
|
7527
|
+
if (!existsSync3(hookDest)) {
|
|
7528
|
+
const packageDir = dirname3(dirname3(fileURLToPath(import.meta.url)));
|
|
7529
|
+
const candidatePaths = [
|
|
7530
|
+
join3(packageDir, "scripts", "hooks", "claude-stop-hook.ts"),
|
|
7531
|
+
join3(packageDir, "..", "scripts", "hooks", "claude-stop-hook.ts"),
|
|
7532
|
+
join3(home, ".bun", "install", "global", "node_modules", "@hasna", "mementos", "scripts", "hooks", "claude-stop-hook.ts")
|
|
7533
|
+
];
|
|
7534
|
+
let hookSourceFound = false;
|
|
7535
|
+
for (const src of candidatePaths) {
|
|
7536
|
+
if (existsSync3(src)) {
|
|
7537
|
+
copyFileSync(src, hookDest);
|
|
7538
|
+
hookSourceFound = true;
|
|
7539
|
+
break;
|
|
7540
|
+
}
|
|
7541
|
+
}
|
|
7542
|
+
if (!hookSourceFound) {
|
|
7543
|
+
const inlineHook = `#!/usr/bin/env bun
|
|
7544
|
+
const MEMENTOS_URL = process.env["MEMENTOS_URL"] ?? "http://localhost:19428";
|
|
7545
|
+
const MEMENTOS_AGENT = process.env["MEMENTOS_AGENT"];
|
|
7546
|
+
|
|
7547
|
+
async function main() {
|
|
7548
|
+
let stdinData = "";
|
|
7549
|
+
try {
|
|
7550
|
+
for await (const chunk of Bun.stdin.stream()) {
|
|
7551
|
+
stdinData += new TextDecoder().decode(chunk);
|
|
7552
|
+
}
|
|
7553
|
+
} catch { /* stdin may be closed */ }
|
|
7554
|
+
|
|
7555
|
+
if (!stdinData.trim()) return;
|
|
7556
|
+
|
|
7557
|
+
let payload: unknown;
|
|
7558
|
+
try { payload = JSON.parse(stdinData); } catch { return; }
|
|
7559
|
+
|
|
7560
|
+
try {
|
|
7561
|
+
await fetch(\`\${MEMENTOS_URL}/api/sessions/ingest\`, {
|
|
7562
|
+
method: "POST",
|
|
7563
|
+
headers: { "Content-Type": "application/json" },
|
|
7564
|
+
body: JSON.stringify({
|
|
7565
|
+
transcript: payload,
|
|
7566
|
+
agent: MEMENTOS_AGENT,
|
|
7567
|
+
source: "claude-stop-hook",
|
|
7568
|
+
}),
|
|
7569
|
+
signal: AbortSignal.timeout(5000),
|
|
7570
|
+
});
|
|
7571
|
+
} catch { /* server not running \u2014 silently skip */ }
|
|
7572
|
+
}
|
|
7573
|
+
|
|
7574
|
+
main().catch(() => {});
|
|
7575
|
+
`;
|
|
7576
|
+
writeFileSync2(hookDest, inlineHook, "utf-8");
|
|
7577
|
+
}
|
|
7578
|
+
}
|
|
7579
|
+
const newStopEntry = {
|
|
7580
|
+
matcher: "",
|
|
7581
|
+
hooks: [{ type: "command", command: hookCommand }]
|
|
7582
|
+
};
|
|
7583
|
+
hooksObj["Stop"] = [...stopHooks, newStopEntry];
|
|
7584
|
+
settings["hooks"] = hooksObj;
|
|
7585
|
+
writeFileSync2(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
7586
|
+
}
|
|
7587
|
+
} catch (e) {
|
|
7588
|
+
hookError = e instanceof Error ? e.message : String(e);
|
|
7589
|
+
}
|
|
7590
|
+
if (hookAlreadyInstalled) {
|
|
7591
|
+
console.log(chalk.dim(" \xB7 Stop hook already installed"));
|
|
7592
|
+
} else if (hookError) {
|
|
7593
|
+
console.log(chalk.red(` \u2717 Failed to install stop hook: ${hookError}`));
|
|
7594
|
+
} else {
|
|
7595
|
+
console.log(chalk.green(" \u2713 Stop hook installed (sessions \u2192 memories)"));
|
|
7596
|
+
}
|
|
7597
|
+
let autoStartAlreadyInstalled = false;
|
|
7598
|
+
let autoStartError = null;
|
|
7599
|
+
if (!isMac) {
|
|
7600
|
+
console.log(chalk.dim(` \xB7 Auto-start skipped (not macOS \u2014 platform: ${platform})`));
|
|
7601
|
+
} else {
|
|
7602
|
+
const plistPath = join3(home, "Library", "LaunchAgents", "com.hasna.mementos.plist");
|
|
7603
|
+
const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
7604
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
7605
|
+
<plist version="1.0">
|
|
7606
|
+
<dict>
|
|
7607
|
+
<key>Label</key>
|
|
7608
|
+
<string>com.hasna.mementos</string>
|
|
7609
|
+
<key>ProgramArguments</key>
|
|
7610
|
+
<array>
|
|
7611
|
+
<string>/bin/sh</string>
|
|
7612
|
+
<string>-c</string>
|
|
7613
|
+
<string>PATH="$HOME/.bun/bin:$PATH" mementos-serve</string>
|
|
7614
|
+
</array>
|
|
7615
|
+
<key>RunAtLoad</key>
|
|
7616
|
+
<true/>
|
|
7617
|
+
<key>KeepAlive</key>
|
|
7618
|
+
<true/>
|
|
7619
|
+
<key>StandardErrorPath</key>
|
|
7620
|
+
<string>/tmp/mementos.log</string>
|
|
7621
|
+
<key>StandardOutPath</key>
|
|
7622
|
+
<string>/tmp/mementos.log</string>
|
|
7623
|
+
</dict>
|
|
7624
|
+
</plist>
|
|
7625
|
+
`;
|
|
7626
|
+
try {
|
|
7627
|
+
if (existsSync3(plistPath)) {
|
|
7628
|
+
autoStartAlreadyInstalled = true;
|
|
7629
|
+
} else {
|
|
7630
|
+
const launchAgentsDir = join3(home, "Library", "LaunchAgents");
|
|
7631
|
+
if (!existsSync3(launchAgentsDir)) {
|
|
7632
|
+
mkdirSync3(launchAgentsDir, { recursive: true });
|
|
7633
|
+
}
|
|
7634
|
+
writeFileSync2(plistPath, plistContent, "utf-8");
|
|
7635
|
+
}
|
|
7636
|
+
} catch (e) {
|
|
7637
|
+
autoStartError = e instanceof Error ? e.message : String(e);
|
|
7638
|
+
}
|
|
7639
|
+
if (autoStartAlreadyInstalled) {
|
|
7640
|
+
console.log(chalk.dim(" \xB7 Auto-start already configured"));
|
|
7641
|
+
} else if (autoStartError) {
|
|
7642
|
+
console.log(chalk.red(` \u2717 Failed to configure auto-start: ${autoStartError}`));
|
|
7643
|
+
} else {
|
|
7644
|
+
console.log(chalk.green(" \u2713 Auto-start configured (starts on login)"));
|
|
7645
|
+
}
|
|
7646
|
+
if (!autoStartAlreadyInstalled && !autoStartError) {
|
|
7647
|
+
const plistPath2 = join3(home, "Library", "LaunchAgents", "com.hasna.mementos.plist");
|
|
7648
|
+
const loadResult = await run(["launchctl", "load", plistPath2]);
|
|
7649
|
+
if (!loadResult.ok) {
|
|
7650
|
+
console.log(chalk.dim(` \xB7 launchctl load: ${loadResult.output || "already loaded"}`));
|
|
7651
|
+
}
|
|
7652
|
+
}
|
|
7653
|
+
}
|
|
7654
|
+
let serverRunning = false;
|
|
7655
|
+
try {
|
|
7656
|
+
const res = await fetch("http://127.0.0.1:19428/api/health", {
|
|
7657
|
+
signal: AbortSignal.timeout(1500)
|
|
7658
|
+
});
|
|
7659
|
+
serverRunning = res.ok;
|
|
7660
|
+
} catch {}
|
|
7661
|
+
if (serverRunning) {
|
|
7662
|
+
console.log(chalk.green(" \u2713 Server running on http://127.0.0.1:19428"));
|
|
7663
|
+
} else {
|
|
7664
|
+
console.log(chalk.dim(" \xB7 Server not yet running \u2014 it will start automatically on next login"));
|
|
7665
|
+
console.log(chalk.dim(" (Or start it now: mementos-serve)"));
|
|
7666
|
+
}
|
|
7667
|
+
console.log("");
|
|
7668
|
+
console.log(chalk.bold(" You're all set. Restart Claude Code to activate."));
|
|
7669
|
+
console.log("");
|
|
7670
|
+
console.log(" Quick start:");
|
|
7671
|
+
console.log(` ${chalk.cyan('mementos save "my-preference" "I prefer bun over npm"')}`);
|
|
7672
|
+
console.log(` ${chalk.cyan("mementos list")}`);
|
|
7673
|
+
console.log(` ${chalk.cyan("mementos doctor")}`);
|
|
7674
|
+
console.log("");
|
|
7675
|
+
});
|
|
7446
7676
|
program2.command("save <key> <value>").description("Save a memory (create or upsert)").option("-c, --category <cat>", "Category: preference, fact, knowledge, history").option("-s, --scope <scope>", "Scope: global, shared, private").option("--importance <n>", "Importance 1-10", parseInt).option("--tags <tags>", "Comma-separated tags").option("--summary <text>", "Brief summary").option("--ttl <duration>", "Time-to-live: 30s, 5m, 2h, 1d, 1w, or milliseconds").option("--source <src>", "Source: user, agent, system, auto, imported").option("--template <name>", "Apply a template: correction, preference, decision, learning").action((key, value, opts) => {
|
|
7447
7677
|
try {
|
|
7448
7678
|
const globalOpts = program2.opts();
|
|
@@ -8121,7 +8351,7 @@ program2.command("clean").description("Remove expired memories and enforce quota
|
|
|
8121
8351
|
handleError(e);
|
|
8122
8352
|
}
|
|
8123
8353
|
});
|
|
8124
|
-
program2.command("
|
|
8354
|
+
program2.command("register-agent <name>").alias("init-agent").description("Register an agent (returns ID)").option("-d, --description <text>", "Agent description").option("-r, --role <role>", "Agent role").option("-p, --project <id>", "Lock agent to a project (sets active_project_id)").action((name, opts) => {
|
|
8125
8355
|
try {
|
|
8126
8356
|
const globalOpts = program2.opts();
|
|
8127
8357
|
const agent = registerAgent(name, undefined, opts.description, opts.role, opts.project);
|
|
@@ -8564,6 +8794,51 @@ program2.command("doctor").description("Diagnose common issues with the mementos
|
|
|
8564
8794
|
} catch {
|
|
8565
8795
|
checks.push({ name: "REST server", status: "warn", detail: "Could not check REST server" });
|
|
8566
8796
|
}
|
|
8797
|
+
try {
|
|
8798
|
+
const mcpProc = Bun.spawn(["claude", "mcp", "list"], { stdout: "pipe", stderr: "pipe" });
|
|
8799
|
+
const [mcpOut, , mcpExit] = await Promise.all([
|
|
8800
|
+
new Response(mcpProc.stdout).text(),
|
|
8801
|
+
new Response(mcpProc.stderr).text(),
|
|
8802
|
+
mcpProc.exited
|
|
8803
|
+
]);
|
|
8804
|
+
if (mcpExit === 0 && mcpOut.includes("mementos")) {
|
|
8805
|
+
checks.push({ name: "MCP server", status: "ok", detail: "registered with Claude Code" });
|
|
8806
|
+
} else if (mcpExit !== 0) {
|
|
8807
|
+
checks.push({ name: "MCP server", status: "warn", detail: "claude not installed or not accessible" });
|
|
8808
|
+
} else {
|
|
8809
|
+
checks.push({ name: "MCP server", status: "warn", detail: "not registered \u2192 run: mementos init" });
|
|
8810
|
+
}
|
|
8811
|
+
} catch {
|
|
8812
|
+
checks.push({ name: "MCP server", status: "warn", detail: "could not check (is claude CLI installed?)" });
|
|
8813
|
+
}
|
|
8814
|
+
try {
|
|
8815
|
+
const settingsFilePath = join3(homedir2(), ".claude", "settings.json");
|
|
8816
|
+
if (existsSync3(settingsFilePath)) {
|
|
8817
|
+
const settings = JSON.parse(readFileSync2(settingsFilePath, "utf-8"));
|
|
8818
|
+
const hooksObj = settings["hooks"] || {};
|
|
8819
|
+
const stopHooks = hooksObj["Stop"] || [];
|
|
8820
|
+
const hasMementos = stopHooks.some((e) => e.hooks?.some((h) => h.command && h.command.includes("mementos")));
|
|
8821
|
+
checks.push({
|
|
8822
|
+
name: "Stop hook",
|
|
8823
|
+
status: hasMementos ? "ok" : "warn",
|
|
8824
|
+
detail: hasMementos ? "installed (sessions \u2192 memories)" : "not installed \u2192 run: mementos init"
|
|
8825
|
+
});
|
|
8826
|
+
} else {
|
|
8827
|
+
checks.push({ name: "Stop hook", status: "warn", detail: "~/.claude/settings.json not found \u2192 run: mementos init" });
|
|
8828
|
+
}
|
|
8829
|
+
} catch {
|
|
8830
|
+
checks.push({ name: "Stop hook", status: "warn", detail: "could not check stop hook" });
|
|
8831
|
+
}
|
|
8832
|
+
if (process.platform === "darwin") {
|
|
8833
|
+
const plistFilePath = join3(homedir2(), "Library", "LaunchAgents", "com.hasna.mementos.plist");
|
|
8834
|
+
checks.push({
|
|
8835
|
+
name: "Auto-start",
|
|
8836
|
+
status: existsSync3(plistFilePath) ? "ok" : "warn",
|
|
8837
|
+
detail: existsSync3(plistFilePath) ? "configured (starts on login)" : "not configured \u2192 run: mementos init"
|
|
8838
|
+
});
|
|
8839
|
+
} else {
|
|
8840
|
+
checks.push({ name: "Auto-start", status: "ok", detail: `n/a on ${process.platform}` });
|
|
8841
|
+
}
|
|
8567
8842
|
outputDoctorResults(globalOpts, checks);
|
|
8568
8843
|
});
|
|
8569
8844
|
function outputDoctorResults(globalOpts, checks) {
|
|
@@ -9418,7 +9693,7 @@ function diffLines(oldText, newText) {
|
|
|
9418
9693
|
}
|
|
9419
9694
|
}
|
|
9420
9695
|
program2.command("completions <shell>").description("Output shell completion script (bash, zsh, fish)").action((shell) => {
|
|
9421
|
-
const commands = "save recall list update forget search stats export import clean inject context pin unpin archive versions stale doctor tail diff
|
|
9696
|
+
const commands = "init setup save recall list update forget search stats export import clean inject context pin unpin archive versions stale doctor tail diff register-agent agents projects bulk completions config backup restore report profile mcp";
|
|
9422
9697
|
const commandList = commands.split(" ");
|
|
9423
9698
|
switch (shell.toLowerCase()) {
|
|
9424
9699
|
case "bash": {
|
|
@@ -9464,7 +9739,8 @@ compdef _mementos mementos`);
|
|
|
9464
9739
|
doctor: "Check database health",
|
|
9465
9740
|
tail: "Watch recent memories",
|
|
9466
9741
|
diff: "Show memory changes",
|
|
9467
|
-
init: "
|
|
9742
|
+
init: "One-command onboarding setup (MCP + hook + auto-start)",
|
|
9743
|
+
"register-agent": "Register an agent (returns ID)",
|
|
9468
9744
|
agents: "Manage agents",
|
|
9469
9745
|
projects: "Manage projects",
|
|
9470
9746
|
bulk: "Bulk operations",
|
package/dist/mcp/index.js
CHANGED
|
@@ -11124,7 +11124,33 @@ server.tool("memory_session_list", "List session memory extraction jobs.", {
|
|
|
11124
11124
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
11125
11125
|
}
|
|
11126
11126
|
});
|
|
11127
|
+
async function ensureRestServerRunning() {
|
|
11128
|
+
try {
|
|
11129
|
+
const res = await fetch("http://127.0.0.1:19428/api/memories?limit=0", {
|
|
11130
|
+
signal: AbortSignal.timeout(500)
|
|
11131
|
+
});
|
|
11132
|
+
if (res.ok || res.status === 200)
|
|
11133
|
+
return;
|
|
11134
|
+
} catch {}
|
|
11135
|
+
const proc = Bun.spawn(["mementos-serve"], {
|
|
11136
|
+
detached: true,
|
|
11137
|
+
stdout: Bun.file("/tmp/mementos.log"),
|
|
11138
|
+
stderr: Bun.file("/tmp/mementos.log")
|
|
11139
|
+
});
|
|
11140
|
+
proc.unref();
|
|
11141
|
+
for (let i = 0;i < 6; i++) {
|
|
11142
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
11143
|
+
try {
|
|
11144
|
+
const res = await fetch("http://127.0.0.1:19428/api/memories?limit=0", {
|
|
11145
|
+
signal: AbortSignal.timeout(400)
|
|
11146
|
+
});
|
|
11147
|
+
if (res.ok || res.status === 200)
|
|
11148
|
+
return;
|
|
11149
|
+
} catch {}
|
|
11150
|
+
}
|
|
11151
|
+
}
|
|
11127
11152
|
async function main() {
|
|
11153
|
+
await ensureRestServerRunning();
|
|
11128
11154
|
loadWebhooksFromDb();
|
|
11129
11155
|
const transport = new StdioServerTransport;
|
|
11130
11156
|
await server.connect(transport);
|