@memories.sh/cli 0.3.2 → 0.4.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/dist/index.js +113 -12
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ import { Command as Command29 } from "commander";
|
|
|
33
33
|
// src/commands/init.ts
|
|
34
34
|
import { Command } from "commander";
|
|
35
35
|
import chalk3 from "chalk";
|
|
36
|
-
import { confirm } from "@inquirer/prompts";
|
|
36
|
+
import { confirm, checkbox } from "@inquirer/prompts";
|
|
37
37
|
|
|
38
38
|
// src/lib/auth.ts
|
|
39
39
|
import { readFile, writeFile, mkdir, unlink } from "fs/promises";
|
|
@@ -121,6 +121,9 @@ var MEMORIES_MCP_CONFIG = {
|
|
|
121
121
|
command: "npx",
|
|
122
122
|
args: ["-y", "@memories.sh/cli", "serve"]
|
|
123
123
|
};
|
|
124
|
+
function getAllTools() {
|
|
125
|
+
return [...TOOLS];
|
|
126
|
+
}
|
|
124
127
|
function detectTools(cwd = process.cwd()) {
|
|
125
128
|
const home = homedir2();
|
|
126
129
|
const detected = [];
|
|
@@ -271,10 +274,32 @@ var initCommand = new Command("init").description("Initialize memories - set up
|
|
|
271
274
|
success("Global scope (rules apply to all projects)");
|
|
272
275
|
}
|
|
273
276
|
step(3, 4, "Detecting AI coding tools...");
|
|
274
|
-
|
|
277
|
+
let detected = detectTools(cwd);
|
|
275
278
|
if (detected.length === 0) {
|
|
276
|
-
dim("No AI coding tools detected
|
|
277
|
-
|
|
279
|
+
dim("No AI coding tools auto-detected.");
|
|
280
|
+
if (!opts.skipMcp) {
|
|
281
|
+
const allTools = getAllTools();
|
|
282
|
+
const selected = await checkbox({
|
|
283
|
+
message: "Which tools do you want to configure?",
|
|
284
|
+
choices: allTools.map((t) => ({
|
|
285
|
+
name: t.name,
|
|
286
|
+
value: t,
|
|
287
|
+
checked: false
|
|
288
|
+
}))
|
|
289
|
+
});
|
|
290
|
+
if (selected.length > 0) {
|
|
291
|
+
detected = selected.map((tool) => ({
|
|
292
|
+
tool,
|
|
293
|
+
hasConfig: false,
|
|
294
|
+
hasMcp: false,
|
|
295
|
+
hasInstructions: false,
|
|
296
|
+
globalConfig: false
|
|
297
|
+
}));
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (detected.length === 0) {
|
|
302
|
+
dim("No tools selected. MCP will work with any tool that supports it.");
|
|
278
303
|
} else {
|
|
279
304
|
for (const d of detected) {
|
|
280
305
|
const scope = d.globalConfig ? chalk3.dim(" [global]") : "";
|
|
@@ -1238,6 +1263,8 @@ import { Command as Command11 } from "commander";
|
|
|
1238
1263
|
// src/mcp/index.ts
|
|
1239
1264
|
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
1240
1265
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
1266
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
1267
|
+
import { createServer } from "http";
|
|
1241
1268
|
import { z } from "zod";
|
|
1242
1269
|
var TYPE_LABELS2 = {
|
|
1243
1270
|
rule: "\u{1F4CC} RULE",
|
|
@@ -1261,7 +1288,7 @@ function formatMemoriesSection(memories, title) {
|
|
|
1261
1288
|
return `## ${title}
|
|
1262
1289
|
${memories.map(formatMemory4).join("\n")}`;
|
|
1263
1290
|
}
|
|
1264
|
-
async function
|
|
1291
|
+
async function createMcpServer() {
|
|
1265
1292
|
const projectId = getProjectId();
|
|
1266
1293
|
const server = new McpServer({
|
|
1267
1294
|
name: "memories",
|
|
@@ -1619,19 +1646,93 @@ Find the memory ID first with search_memories or list_memories.`,
|
|
|
1619
1646
|
}
|
|
1620
1647
|
}
|
|
1621
1648
|
);
|
|
1649
|
+
return server;
|
|
1650
|
+
}
|
|
1651
|
+
async function startMcpServer() {
|
|
1652
|
+
const server = await createMcpServer();
|
|
1622
1653
|
const transport = new StdioServerTransport();
|
|
1623
1654
|
await server.connect(transport);
|
|
1624
1655
|
}
|
|
1656
|
+
async function startMcpHttpServer(options) {
|
|
1657
|
+
const { port, host, cors } = options;
|
|
1658
|
+
const server = await createMcpServer();
|
|
1659
|
+
const transport = new StreamableHTTPServerTransport({
|
|
1660
|
+
sessionIdGenerator: void 0
|
|
1661
|
+
// Stateless mode
|
|
1662
|
+
});
|
|
1663
|
+
await server.connect(transport);
|
|
1664
|
+
const httpServer = createServer(async (req, res) => {
|
|
1665
|
+
if (cors) {
|
|
1666
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
1667
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
1668
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
|
|
1669
|
+
}
|
|
1670
|
+
if (req.method === "OPTIONS") {
|
|
1671
|
+
res.writeHead(204);
|
|
1672
|
+
res.end();
|
|
1673
|
+
return;
|
|
1674
|
+
}
|
|
1675
|
+
const url = new URL(req.url || "/", `http://${host}:${port}`);
|
|
1676
|
+
if (url.pathname === "/health") {
|
|
1677
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1678
|
+
res.end(JSON.stringify({ status: "ok" }));
|
|
1679
|
+
return;
|
|
1680
|
+
}
|
|
1681
|
+
if (url.pathname === "/mcp" || url.pathname === "/") {
|
|
1682
|
+
try {
|
|
1683
|
+
let body = void 0;
|
|
1684
|
+
if (req.method === "POST") {
|
|
1685
|
+
const chunks = [];
|
|
1686
|
+
for await (const chunk of req) {
|
|
1687
|
+
chunks.push(chunk);
|
|
1688
|
+
}
|
|
1689
|
+
const rawBody = Buffer.concat(chunks).toString("utf-8");
|
|
1690
|
+
if (rawBody) {
|
|
1691
|
+
body = JSON.parse(rawBody);
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
await transport.handleRequest(req, res, body);
|
|
1695
|
+
} catch (error2) {
|
|
1696
|
+
console.error("[memories] Error handling MCP request:", error2);
|
|
1697
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1698
|
+
res.end(JSON.stringify({ error: "Internal server error" }));
|
|
1699
|
+
}
|
|
1700
|
+
return;
|
|
1701
|
+
}
|
|
1702
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1703
|
+
res.end(JSON.stringify({ error: "Not found" }));
|
|
1704
|
+
});
|
|
1705
|
+
httpServer.listen(port, host);
|
|
1706
|
+
await new Promise(() => {
|
|
1707
|
+
});
|
|
1708
|
+
}
|
|
1625
1709
|
|
|
1626
1710
|
// src/commands/serve.ts
|
|
1627
|
-
var serveCommand = new Command11("serve").description("Start the MCP server
|
|
1711
|
+
var serveCommand = new Command11("serve").description("Start the MCP server").option("--sse", "Use SSE/HTTP transport instead of stdio (for web clients like v0)").option("-p, --port <port>", "Port for SSE server", "3030").option("--host <host>", "Host to bind to", "127.0.0.1").option("--cors", "Enable CORS for cross-origin requests").action(async (opts) => {
|
|
1628
1712
|
const projectId = getProjectId();
|
|
1629
|
-
if (
|
|
1630
|
-
|
|
1713
|
+
if (opts.sse) {
|
|
1714
|
+
const port = parseInt(opts.port || "3030", 10);
|
|
1715
|
+
const host = opts.host || "127.0.0.1";
|
|
1716
|
+
console.log(`[memories] Starting MCP server with SSE transport`);
|
|
1717
|
+
console.log(`[memories] Listening on http://${host}:${port}`);
|
|
1718
|
+
if (projectId) {
|
|
1719
|
+
console.log(`[memories] Project: ${projectId}`);
|
|
1720
|
+
} else {
|
|
1721
|
+
console.log(`[memories] Global only (not in a git repo)`);
|
|
1722
|
+
}
|
|
1723
|
+
if (opts.cors) {
|
|
1724
|
+
console.log(`[memories] CORS enabled`);
|
|
1725
|
+
}
|
|
1726
|
+
console.log(`[memories] Connect v0 or other clients to: http://${host}:${port}/mcp`);
|
|
1727
|
+
await startMcpHttpServer({ port, host, cors: opts.cors });
|
|
1631
1728
|
} else {
|
|
1632
|
-
|
|
1729
|
+
if (projectId) {
|
|
1730
|
+
console.error(`[memories] MCP server starting (project: ${projectId})`);
|
|
1731
|
+
} else {
|
|
1732
|
+
console.error("[memories] MCP server starting (global only - not in a git repo)");
|
|
1733
|
+
}
|
|
1734
|
+
await startMcpServer();
|
|
1633
1735
|
}
|
|
1634
|
-
await startMcpServer();
|
|
1635
1736
|
});
|
|
1636
1737
|
|
|
1637
1738
|
// src/commands/sync.ts
|
|
@@ -1803,7 +1904,7 @@ import { writeFile as writeFile5, readFile as readFile5, mkdir as mkdir4 } from
|
|
|
1803
1904
|
import { existsSync as existsSync5, watch as fsWatch } from "fs";
|
|
1804
1905
|
import { dirname as dirname2, resolve, join as join5 } from "path";
|
|
1805
1906
|
import { homedir as homedir4 } from "os";
|
|
1806
|
-
import { checkbox } from "@inquirer/prompts";
|
|
1907
|
+
import { checkbox as checkbox2 } from "@inquirer/prompts";
|
|
1807
1908
|
var MARKER = "Generated by memories.sh";
|
|
1808
1909
|
var VALID_TYPES6 = ["rule", "decision", "fact", "note"];
|
|
1809
1910
|
function groupByType(memories) {
|
|
@@ -2045,7 +2146,7 @@ var generateCommand = new Command13("generate").description("Generate IDE rule/i
|
|
|
2045
2146
|
generateCommand.outputHelp();
|
|
2046
2147
|
return;
|
|
2047
2148
|
}
|
|
2048
|
-
const selected = await
|
|
2149
|
+
const selected = await checkbox2({
|
|
2049
2150
|
message: "Select targets to generate",
|
|
2050
2151
|
choices: TARGETS.map((t) => ({
|
|
2051
2152
|
name: `${t.name} ${chalk12.dim(`\u2192 ${t.defaultPath}`)}`,
|