@gricha/perry 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.
@@ -0,0 +1,52 @@
1
+ import { promises as fs } from 'fs';
2
+ import path from 'path';
3
+ const CACHE_FILE = 'recent-sessions.json';
4
+ const MAX_RECENT = 20;
5
+ export class SessionsCacheManager {
6
+ cachePath;
7
+ cache = null;
8
+ constructor(configDir) {
9
+ this.cachePath = path.join(configDir, CACHE_FILE);
10
+ }
11
+ async load() {
12
+ if (this.cache) {
13
+ return this.cache;
14
+ }
15
+ try {
16
+ const content = await fs.readFile(this.cachePath, 'utf-8');
17
+ this.cache = JSON.parse(content);
18
+ return this.cache;
19
+ }
20
+ catch {
21
+ this.cache = { recent: [] };
22
+ return this.cache;
23
+ }
24
+ }
25
+ async save() {
26
+ if (!this.cache)
27
+ return;
28
+ await fs.mkdir(path.dirname(this.cachePath), { recursive: true });
29
+ await fs.writeFile(this.cachePath, JSON.stringify(this.cache, null, 2), 'utf-8');
30
+ }
31
+ async getRecent(limit = 10) {
32
+ const cache = await this.load();
33
+ return cache.recent.slice(0, limit);
34
+ }
35
+ async recordAccess(workspaceName, sessionId, agentType) {
36
+ const cache = await this.load();
37
+ cache.recent = cache.recent.filter((s) => !(s.workspaceName === workspaceName && s.sessionId === sessionId));
38
+ cache.recent.unshift({
39
+ workspaceName,
40
+ sessionId,
41
+ agentType,
42
+ lastAccessed: new Date().toISOString(),
43
+ });
44
+ cache.recent = cache.recent.slice(0, MAX_RECENT);
45
+ await this.save();
46
+ }
47
+ async removeForWorkspace(workspaceName) {
48
+ const cache = await this.load();
49
+ cache.recent = cache.recent.filter((s) => s.workspaceName !== workspaceName);
50
+ await this.save();
51
+ }
52
+ }
@@ -343,6 +343,9 @@ export class WorkspaceManager {
343
343
  await this.syncWorkspaceStatus(workspace);
344
344
  return workspace;
345
345
  }
346
+ async touch(name) {
347
+ return this.state.touchWorkspace(name);
348
+ }
346
349
  async create(options) {
347
350
  const { name, clone, env } = options;
348
351
  const containerName = getContainerName(name);
@@ -360,6 +363,7 @@ export class WorkspaceManager {
360
363
  ports: {
361
364
  ssh: 0,
362
365
  },
366
+ lastUsed: new Date().toISOString(),
363
367
  };
364
368
  await this.state.setWorkspace(workspace);
365
369
  try {
@@ -461,6 +465,7 @@ export class WorkspaceManager {
461
465
  const running = await docker.containerRunning(containerName);
462
466
  if (running) {
463
467
  workspace.status = 'running';
468
+ workspace.lastUsed = new Date().toISOString();
464
469
  await this.state.setWorkspace(workspace);
465
470
  return workspace;
466
471
  }
@@ -468,6 +473,7 @@ export class WorkspaceManager {
468
473
  await docker.waitForContainerReady(containerName);
469
474
  await this.setupWorkspaceCredentials(containerName, name);
470
475
  workspace.status = 'running';
476
+ workspace.lastUsed = new Date().toISOString();
471
477
  await this.state.setWorkspace(workspace);
472
478
  await this.runPostStartScript(containerName);
473
479
  return workspace;
@@ -94,4 +94,13 @@ export class StateManager {
94
94
  await this.setWorkspace(workspace);
95
95
  return workspace;
96
96
  }
97
+ async touchWorkspace(name) {
98
+ const workspace = await this.getWorkspace(name);
99
+ if (!workspace) {
100
+ return null;
101
+ }
102
+ workspace.lastUsed = new Date().toISOString();
103
+ await this.setWorkspace(workspace);
104
+ return workspace;
105
+ }
97
106
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gricha/perry",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Self-contained CLI for spinning up Docker-in-Docker development environments with SSH and proxy helpers.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -22,7 +22,8 @@
22
22
  "format": "oxfmt --write src/ test/",
23
23
  "format:check": "oxfmt --check src/ test/",
24
24
  "check": "bun run lint && bun run format:check && bun x tsc --noEmit",
25
- "validate": "bun run check && bun run build && bun run test"
25
+ "lint:web": "cd web && bun run lint",
26
+ "validate": "bun run check && bun run build && bun run test && bun run lint:web && bun run test:web"
26
27
  },
27
28
  "engines": {
28
29
  "bun": ">=1.3.5"