@shahmilsaari/memory-core 0.2.0 → 0.2.3

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 (2) hide show
  1. package/dist/cli.js +122 -26
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -530,9 +530,18 @@ import { join as join2 } from "path";
530
530
  var localEnv = join2(process.cwd(), ".memory-core.env");
531
531
  config({ path: existsSync2(localEnv) ? localEnv : join2(process.cwd(), ".env") });
532
532
  var Config = {
533
- databaseUrl: process.env.DATABASE_URL ?? "",
534
- ollamaUrl: process.env.OLLAMA_URL ?? "http://localhost:11434",
535
- ollamaModel: process.env.OLLAMA_MODEL ?? "nomic-embed-text"
533
+ get databaseUrl() {
534
+ return process.env.DATABASE_URL ?? "";
535
+ },
536
+ get ollamaUrl() {
537
+ return process.env.OLLAMA_URL ?? "http://localhost:11434";
538
+ },
539
+ get ollamaModel() {
540
+ return process.env.OLLAMA_MODEL ?? "nomic-embed-text";
541
+ },
542
+ get chatModel() {
543
+ return process.env.OLLAMA_CHAT_MODEL ?? "llama3.2";
544
+ }
536
545
  };
537
546
 
538
547
  // src/embedding.ts
@@ -1157,7 +1166,9 @@ function startWatch(options = {}) {
1157
1166
  }
1158
1167
 
1159
1168
  // src/cli.ts
1160
- function printBanner(projectName, agentCount) {
1169
+ function printBanner(projectName, agentCount, status) {
1170
+ const pg2 = status ? status.postgresOk ? chalk3.green(" \u2713 PostgreSQL ") + chalk3.bold("connected") : chalk3.red(" \u2717 PostgreSQL ") + chalk3.bold("not connected \u2014 check DATABASE_URL") : chalk3.green(" \u2713 Memory ") + chalk3.bold("PostgreSQL + pgvector ready");
1171
+ const ol = status ? status.ollamaOk ? chalk3.green(" \u2713 Ollama ") + chalk3.bold(`connected (model: ${status.chatModel})`) : chalk3.red(" \u2717 Ollama ") + chalk3.bold("not running \u2014 start with: ollama serve") : null;
1161
1172
  const lines = [
1162
1173
  "",
1163
1174
  chalk3.cyan(" \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 "),
@@ -1171,7 +1182,8 @@ function printBanner(projectName, agentCount) {
1171
1182
  "",
1172
1183
  chalk3.green(` \u2713 Project `) + chalk3.bold(projectName),
1173
1184
  chalk3.green(` \u2713 Agents `) + chalk3.bold(`${agentCount} AI agents configured`),
1174
- chalk3.green(` \u2713 Memory `) + chalk3.bold("PostgreSQL + pgvector ready"),
1185
+ pg2,
1186
+ ...ol ? [ol] : [],
1175
1187
  "",
1176
1188
  chalk3.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
1177
1189
  chalk3.dim(" Built by ") + chalk3.bold.white("Shahmil Saari"),
@@ -1186,6 +1198,35 @@ function printBanner(projectName, agentCount) {
1186
1198
  ];
1187
1199
  lines.forEach((l) => console.log(l));
1188
1200
  }
1201
+ async function checkConnections(dbUrl, ollamaUrl, chatModel) {
1202
+ const spinner = ora("Checking connections\u2026").start();
1203
+ let postgresOk = false;
1204
+ let ollamaOk = false;
1205
+ try {
1206
+ const { Pool: Pool2 } = (await import("pg")).default;
1207
+ const testPool = new Pool2({ connectionString: dbUrl, connectionTimeoutMillis: 5e3 });
1208
+ await testPool.query("SELECT 1");
1209
+ await testPool.end();
1210
+ postgresOk = true;
1211
+ } catch {
1212
+ postgresOk = false;
1213
+ }
1214
+ try {
1215
+ const res = await fetch(`${ollamaUrl}/api/tags`, { signal: AbortSignal.timeout(5e3) });
1216
+ ollamaOk = res.ok;
1217
+ } catch {
1218
+ ollamaOk = false;
1219
+ }
1220
+ spinner.stop();
1221
+ console.log(
1222
+ postgresOk ? chalk3.green(" \u2713 PostgreSQL") + chalk3.dim(" \u2014 connected") : chalk3.red(" \u2717 PostgreSQL") + chalk3.dim(" \u2014 cannot connect. Check DATABASE_URL and that PostgreSQL is running.")
1223
+ );
1224
+ console.log(
1225
+ ollamaOk ? chalk3.green(" \u2713 Ollama ") + chalk3.dim(` \u2014 connected (${chatModel})`) : chalk3.red(" \u2717 Ollama ") + chalk3.dim(" \u2014 not reachable. Run: ollama serve")
1226
+ );
1227
+ console.log();
1228
+ return { postgresOk, ollamaOk, chatModel };
1229
+ }
1189
1230
  var { version } = JSON.parse(readFileSync5(new URL("../package.json", import.meta.url), "utf-8"));
1190
1231
  var CONFIG_FILE = ".memory-core.json";
1191
1232
  function readProjectConfig() {
@@ -1208,27 +1249,77 @@ program.command("init").description("Initialize memory-core in the current proje
1208
1249
  const envPath = join6(process.cwd(), ".memory-core.env");
1209
1250
  const hasEnv = existsSync6(envPath) || existsSync6(join6(process.cwd(), ".env")) || !!process.env.DATABASE_URL;
1210
1251
  if (!hasEnv) {
1211
- console.log(chalk3.dim(" No .memory-core.env found \u2014 let's set up your database connection.\n"));
1252
+ console.log(chalk3.dim(" No .memory-core.env found \u2014 let's set up your connection.\n"));
1212
1253
  const dbUser = process.env.USER ?? process.env.USERNAME ?? "postgres";
1213
- const dbUrl = await input({
1214
- message: "PostgreSQL connection URL?",
1215
- default: `postgresql://${dbUser}@localhost:5432/memory_core`
1216
- });
1217
- const ollamaUrl = await input({
1218
- message: "Ollama URL?",
1219
- default: "http://localhost:11434"
1220
- });
1221
- const chatModelChoice = await select({
1222
- message: "Which Ollama model for code checking?",
1223
- choices: [
1224
- { name: "llama3.2 (fast, 2GB, recommended for most machines)", value: "llama3.2" },
1225
- { name: "qwen2.5-coder (better code understanding, 4.7GB)", value: "qwen2.5-coder" },
1226
- { name: "mistral (balanced, 4.1GB)", value: "mistral" },
1227
- { name: "codellama (code-focused, 3.8GB)", value: "codellama" },
1228
- { name: "Other (enter manually)", value: "__custom__" }
1229
- ]
1230
- });
1231
- const chatModel = chatModelChoice === "__custom__" ? await input({ message: "Model name (must be available in your Ollama)?", default: "llama3.2" }) : chatModelChoice;
1254
+ let dbUrl = "";
1255
+ while (true) {
1256
+ dbUrl = await input({
1257
+ message: "PostgreSQL connection URL?",
1258
+ default: dbUrl || `postgresql://${dbUser}@localhost:5432/memory_core`
1259
+ });
1260
+ const pgSpinner = ora(" Testing PostgreSQL connection\u2026").start();
1261
+ try {
1262
+ const { Pool: Pool2 } = (await import("pg")).default;
1263
+ const testPool = new Pool2({ connectionString: dbUrl, connectionTimeoutMillis: 5e3 });
1264
+ await testPool.query("SELECT 1");
1265
+ await testPool.end();
1266
+ pgSpinner.succeed(chalk3.green("PostgreSQL connected"));
1267
+ break;
1268
+ } catch (err) {
1269
+ pgSpinner.fail(chalk3.red(`Cannot connect: ${err.message}`));
1270
+ console.log(chalk3.yellow(" Please check that PostgreSQL is running and the URL is correct.\n"));
1271
+ }
1272
+ }
1273
+ let ollamaUrl = "";
1274
+ while (true) {
1275
+ ollamaUrl = await input({
1276
+ message: "Ollama URL?",
1277
+ default: ollamaUrl || "http://localhost:11434"
1278
+ });
1279
+ const ollamaSpinner = ora(" Testing Ollama connection\u2026").start();
1280
+ try {
1281
+ const res = await fetch(`${ollamaUrl}/api/tags`, { signal: AbortSignal.timeout(5e3) });
1282
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
1283
+ ollamaSpinner.succeed(chalk3.green("Ollama connected"));
1284
+ break;
1285
+ } catch (err) {
1286
+ ollamaSpinner.fail(chalk3.red(`Cannot reach Ollama: ${err.message}`));
1287
+ console.log(chalk3.yellow(" Make sure Ollama is running: ollama serve\n"));
1288
+ }
1289
+ }
1290
+ let chatModel = "";
1291
+ while (true) {
1292
+ const chatModelChoice = await select({
1293
+ message: "Which Ollama model for code checking?",
1294
+ choices: [
1295
+ { name: "llama3.2 (fast, 2GB, recommended for most machines)", value: "llama3.2" },
1296
+ { name: "qwen2.5-coder (better code understanding, 4.7GB)", value: "qwen2.5-coder" },
1297
+ { name: "mistral (balanced, 4.1GB)", value: "mistral" },
1298
+ { name: "codellama (code-focused, 3.8GB)", value: "codellama" },
1299
+ { name: "Other (enter manually)", value: "__custom__" }
1300
+ ]
1301
+ });
1302
+ chatModel = chatModelChoice === "__custom__" ? await input({ message: "Model name?", default: "llama3.2" }) : chatModelChoice;
1303
+ const modelSpinner = ora(` Checking if ${chatModel} is installed\u2026`).start();
1304
+ try {
1305
+ const res = await fetch(`${ollamaUrl}/api/tags`, { signal: AbortSignal.timeout(5e3) });
1306
+ const data = await res.json();
1307
+ const installed = (data.models ?? []).some(
1308
+ (m) => m.name === chatModel || m.name.startsWith(`${chatModel}:`)
1309
+ );
1310
+ if (installed) {
1311
+ modelSpinner.succeed(chalk3.green(`${chatModel} is installed and ready`));
1312
+ break;
1313
+ } else {
1314
+ modelSpinner.fail(chalk3.red(`${chatModel} is not installed in your Ollama`));
1315
+ console.log(chalk3.yellow(` Run: ollama pull ${chatModel} \u2014 or pick a different model.
1316
+ `));
1317
+ }
1318
+ } catch {
1319
+ modelSpinner.warn(chalk3.yellow("Could not verify model \u2014 continuing anyway"));
1320
+ break;
1321
+ }
1322
+ }
1232
1323
  const envContent = [
1233
1324
  `DATABASE_URL=${dbUrl}`,
1234
1325
  `OLLAMA_URL=${ollamaUrl}`,
@@ -1347,7 +1438,12 @@ program.command("init").description("Initialize memory-core in the current proje
1347
1438
  );
1348
1439
  writeProjectConfig(config2);
1349
1440
  spinner.succeed(`Generated ${written.length} files`);
1350
- printBanner(config2.projectName, written.length);
1441
+ const status = await checkConnections(
1442
+ process.env.DATABASE_URL ?? "",
1443
+ process.env.OLLAMA_URL ?? "http://localhost:11434",
1444
+ process.env.OLLAMA_CHAT_MODEL ?? "llama3.2"
1445
+ );
1446
+ printBanner(config2.projectName, written.length, status);
1351
1447
  await closePool();
1352
1448
  });
1353
1449
  program.command("sync").description("Re-pull memories and regenerate all AI agent files").action(async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shahmilsaari/memory-core",
3
- "version": "0.2.0",
3
+ "version": "0.2.3",
4
4
  "description": "Universal AI memory core — generate AI context files from architecture profiles with RAG support",
5
5
  "type": "module",
6
6
  "bin": {