@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.
- package/dist/agent/router.js +87 -34
- package/dist/agent/run.js +7 -0
- package/dist/agent/web/assets/index-CaFOQOgc.css +1 -0
- package/dist/agent/web/assets/index-DQmM39Em.js +104 -0
- package/dist/agent/web/index.html +2 -2
- package/dist/chat/base-chat-websocket.js +5 -2
- package/dist/chat/handler.js +16 -0
- package/dist/chat/host-opencode-handler.js +22 -0
- package/dist/chat/opencode-handler.js +22 -0
- package/dist/chat/opencode-server.js +98 -65
- package/dist/chat/opencode-websocket.js +11 -3
- package/dist/chat/websocket.js +4 -4
- package/dist/models/cache.js +70 -0
- package/dist/models/discovery.js +108 -0
- package/dist/sessions/cache.js +52 -0
- package/dist/workspace/manager.js +6 -0
- package/dist/workspace/state.js +9 -0
- package/package.json +3 -2
- package/dist/agent/web/assets/index-BHtbHpxa.js +0 -104
- package/dist/agent/web/assets/index-C_2MULGg.css +0 -1
|
@@ -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;
|
package/dist/workspace/state.js
CHANGED
|
@@ -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.
|
|
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
|
-
"
|
|
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"
|