@socrates-ai/cli 0.1.11 → 0.1.13

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/package.json +1 -1
  2. package/src/runtime.mjs +46 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@socrates-ai/cli",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "type": "module",
5
5
  "description": "Launch Socrates as a local-first AI workspace from npm.",
6
6
  "bin": {
package/src/runtime.mjs CHANGED
@@ -9,6 +9,7 @@ import { pipeline } from "node:stream/promises";
9
9
 
10
10
  const defaultRepo = "Ayushbh6/Socrates";
11
11
  const host = "127.0.0.1";
12
+ const defaultRuntimeVersionsToKeep = 2;
12
13
 
13
14
  export const defaultSocratesHome = () => path.join(os.homedir(), ".Socrates");
14
15
 
@@ -147,6 +148,7 @@ export const ensureRuntime = async ({ home, platformArch, version, reset = false
147
148
  const launcher = path.join(runtimeDir, "launcher.mjs");
148
149
 
149
150
  if (!reset && fs.existsSync(launcher)) {
151
+ cleanupRuntimeStorage({ home, currentVersion: resolvedVersion, log });
150
152
  return { version: resolvedVersion, runtimeDir };
151
153
  }
152
154
 
@@ -174,9 +176,33 @@ export const ensureRuntime = async ({ home, platformArch, version, reset = false
174
176
  if (!fs.existsSync(launcher)) {
175
177
  throw new Error(`Runtime archive did not contain launcher.mjs.`);
176
178
  }
179
+ cleanupRuntimeStorage({ home, currentVersion: resolvedVersion, log });
177
180
  return { version: resolvedVersion, runtimeDir };
178
181
  };
179
182
 
183
+ export const cleanupRuntimeStorage = ({ home, currentVersion, keepRecent = defaultRuntimeVersionsToKeep, log = () => undefined }) => {
184
+ const keepCount = Math.max(1, Number.isFinite(keepRecent) ? Math.floor(keepRecent) : defaultRuntimeVersionsToKeep);
185
+ const versions = runtimeStorageVersions(home);
186
+ const sorted = versions
187
+ .filter((entry) => entry.name !== currentVersion)
188
+ .sort((left, right) => right.modifiedAt - left.modifiedAt || right.name.localeCompare(left.name));
189
+ const keep = new Set([currentVersion, ...sorted.slice(0, Math.max(0, keepCount - 1)).map((entry) => entry.name)]);
190
+ const removed = [];
191
+ for (const root of [runtimeRoot(home), runtimeCacheDir(home)]) {
192
+ if (!fs.existsSync(root)) continue;
193
+ for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
194
+ if (!entry.isDirectory() || !isRuntimeVersionTag(entry.name) || keep.has(entry.name)) continue;
195
+ const target = path.join(root, entry.name);
196
+ fs.rmSync(target, { recursive: true, force: true });
197
+ removed.push(target);
198
+ }
199
+ }
200
+ if (removed.length > 0) {
201
+ log(`Removed old Socrates runtime/cache versions: ${Array.from(new Set(removed.map((item) => path.basename(item)))).sort().join(", ")}`);
202
+ }
203
+ return { kept: Array.from(keep).sort(), removed };
204
+ };
205
+
180
206
  export const runRuntime = ({ runtimeDir, socratesHome, backendPort, webPort, nodePath, onReady }) =>
181
207
  new Promise((resolve, reject) => {
182
208
  const launcher = path.join(runtimeDir, "launcher.mjs");
@@ -248,6 +274,26 @@ export const selectAsset = (assets, name) => {
248
274
  return asset;
249
275
  };
250
276
 
277
+ const runtimeStorageVersions = (home) => {
278
+ const byName = new Map();
279
+ for (const root of [runtimeRoot(home), runtimeCacheDir(home)]) {
280
+ if (!fs.existsSync(root)) continue;
281
+ for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
282
+ if (!entry.isDirectory() || !isRuntimeVersionTag(entry.name)) continue;
283
+ const fullPath = path.join(root, entry.name);
284
+ const modifiedAt = fs.statSync(fullPath).mtimeMs;
285
+ const existing = byName.get(entry.name);
286
+ byName.set(entry.name, {
287
+ name: entry.name,
288
+ modifiedAt: Math.max(existing?.modifiedAt ?? 0, modifiedAt),
289
+ });
290
+ }
291
+ }
292
+ return Array.from(byName.values());
293
+ };
294
+
295
+ const isRuntimeVersionTag = (value) => /^v\d+\.\d+\.\d+(?:[-+][A-Za-z0-9.-]+)?$/.test(value);
296
+
251
297
  const fetchRelease = async (version) => {
252
298
  const repo = process.env.SOCRATES_RELEASE_REPO ?? defaultRepo;
253
299
  if (version) {