@kdonev/termscape 0.1.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/LICENSE +21 -0
- package/README.md +288 -0
- package/dist/agents/env.d.ts +36 -0
- package/dist/agents/env.d.ts.map +1 -0
- package/dist/agents/env.js +61 -0
- package/dist/agents/env.js.map +1 -0
- package/dist/agents/profiles.d.ts +45 -0
- package/dist/agents/profiles.d.ts.map +1 -0
- package/dist/agents/profiles.js +123 -0
- package/dist/agents/profiles.js.map +1 -0
- package/dist/agents/resolve.d.ts +16 -0
- package/dist/agents/resolve.d.ts.map +1 -0
- package/dist/agents/resolve.js +71 -0
- package/dist/agents/resolve.js.map +1 -0
- package/dist/agents/router.d.ts +29 -0
- package/dist/agents/router.d.ts.map +1 -0
- package/dist/agents/router.js +83 -0
- package/dist/agents/router.js.map +1 -0
- package/dist/agents/tokens.d.ts +21 -0
- package/dist/agents/tokens.d.ts.map +1 -0
- package/dist/agents/tokens.js +39 -0
- package/dist/agents/tokens.js.map +1 -0
- package/dist/agents/wiring.d.ts +30 -0
- package/dist/agents/wiring.d.ts.map +1 -0
- package/dist/agents/wiring.js +110 -0
- package/dist/agents/wiring.js.map +1 -0
- package/dist/browser.d.ts +13 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +34 -0
- package/dist/browser.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +200 -0
- package/dist/cli.js.map +1 -0
- package/dist/db/index.d.ts +14 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +24 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/migrations.d.ts +15 -0
- package/dist/db/migrations.d.ts.map +1 -0
- package/dist/db/migrations.js +176 -0
- package/dist/db/migrations.js.map +1 -0
- package/dist/db/store.d.ts +71 -0
- package/dist/db/store.d.ts.map +1 -0
- package/dist/db/store.js +341 -0
- package/dist/db/store.js.map +1 -0
- package/dist/hub.d.ts +188 -0
- package/dist/hub.d.ts.map +1 -0
- package/dist/hub.js +636 -0
- package/dist/hub.js.map +1 -0
- package/dist/hub.tgz +0 -0
- package/dist/mcp/server.d.ts +31 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +66 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/paths.d.ts +27 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +31 -0
- package/dist/paths.js.map +1 -0
- package/dist/protocol/address.d.ts +15 -0
- package/dist/protocol/address.d.ts.map +1 -0
- package/dist/protocol/address.js +39 -0
- package/dist/protocol/address.js.map +1 -0
- package/dist/protocol/domain.d.ts +151 -0
- package/dist/protocol/domain.d.ts.map +1 -0
- package/dist/protocol/domain.js +104 -0
- package/dist/protocol/domain.js.map +1 -0
- package/dist/protocol/index.d.ts +7 -0
- package/dist/protocol/index.d.ts.map +1 -0
- package/dist/protocol/index.js +7 -0
- package/dist/protocol/index.js.map +1 -0
- package/dist/protocol/inject.d.ts +29 -0
- package/dist/protocol/inject.d.ts.map +1 -0
- package/dist/protocol/inject.js +40 -0
- package/dist/protocol/inject.js.map +1 -0
- package/dist/protocol/mcp-tools.d.ts +45 -0
- package/dist/protocol/mcp-tools.d.ts.map +1 -0
- package/dist/protocol/mcp-tools.js +46 -0
- package/dist/protocol/mcp-tools.js.map +1 -0
- package/dist/protocol/peer.d.ts +304 -0
- package/dist/protocol/peer.d.ts.map +1 -0
- package/dist/protocol/peer.js +183 -0
- package/dist/protocol/peer.js.map +1 -0
- package/dist/protocol/ws.d.ts +416 -0
- package/dist/protocol/ws.d.ts.map +1 -0
- package/dist/protocol/ws.js +119 -0
- package/dist/protocol/ws.js.map +1 -0
- package/dist/remote/deployer.d.ts +78 -0
- package/dist/remote/deployer.d.ts.map +1 -0
- package/dist/remote/deployer.js +216 -0
- package/dist/remote/deployer.js.map +1 -0
- package/dist/remote/enroll.d.ts +14 -0
- package/dist/remote/enroll.d.ts.map +1 -0
- package/dist/remote/enroll.js +244 -0
- package/dist/remote/enroll.js.map +1 -0
- package/dist/remote/join-script.d.ts +29 -0
- package/dist/remote/join-script.d.ts.map +1 -0
- package/dist/remote/join-script.js +709 -0
- package/dist/remote/join-script.js.map +1 -0
- package/dist/remote/join.d.ts +19 -0
- package/dist/remote/join.d.ts.map +1 -0
- package/dist/remote/join.js +195 -0
- package/dist/remote/join.js.map +1 -0
- package/dist/remote/lan.d.ts +45 -0
- package/dist/remote/lan.d.ts.map +1 -0
- package/dist/remote/lan.js +105 -0
- package/dist/remote/lan.js.map +1 -0
- package/dist/remote/peer-serve.d.ts +27 -0
- package/dist/remote/peer-serve.d.ts.map +1 -0
- package/dist/remote/peer-serve.js +274 -0
- package/dist/remote/peer-serve.js.map +1 -0
- package/dist/remote/peer.d.ts +62 -0
- package/dist/remote/peer.d.ts.map +1 -0
- package/dist/remote/peer.js +250 -0
- package/dist/remote/peer.js.map +1 -0
- package/dist/remote/registry.d.ts +104 -0
- package/dist/remote/registry.d.ts.map +1 -0
- package/dist/remote/registry.js +359 -0
- package/dist/remote/registry.js.map +1 -0
- package/dist/remote/tarball.d.ts +9 -0
- package/dist/remote/tarball.d.ts.map +1 -0
- package/dist/remote/tarball.js +22 -0
- package/dist/remote/tarball.js.map +1 -0
- package/dist/server.d.ts +54 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +438 -0
- package/dist/server.js.map +1 -0
- package/dist/session/manager.d.ts +104 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +421 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/pty.d.ts +114 -0
- package/dist/session/pty.d.ts.map +1 -0
- package/dist/session/pty.js +300 -0
- package/dist/session/pty.js.map +1 -0
- package/package.json +49 -0
- package/web/assets/index-B2JtCtHa.css +1 -0
- package/web/assets/index-BOqZOoep.js +107 -0
- package/web/index.html +13 -0
package/dist/db/store.js
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { makeAddress, } from '../protocol/index.js';
|
|
2
|
+
export const DEFAULT_WINDOW = {
|
|
3
|
+
x: 0,
|
|
4
|
+
y: 0,
|
|
5
|
+
w: 720,
|
|
6
|
+
h: 460,
|
|
7
|
+
z: 0,
|
|
8
|
+
collapsed: false,
|
|
9
|
+
};
|
|
10
|
+
export class Store {
|
|
11
|
+
db;
|
|
12
|
+
constructor(db) {
|
|
13
|
+
this.db = db;
|
|
14
|
+
}
|
|
15
|
+
/* ---------------------------------------------------------------- hosts */
|
|
16
|
+
listHosts() {
|
|
17
|
+
const rows = this.db.prepare('SELECT * FROM host ORDER BY label').all();
|
|
18
|
+
// ssh_host/ssh_user are NOT NULL in the schema and enrolled hosts have
|
|
19
|
+
// neither, so '' is the stored sentinel. See migration 3.
|
|
20
|
+
return rows.map((r) => ({
|
|
21
|
+
id: r.id,
|
|
22
|
+
label: r.label,
|
|
23
|
+
kind: r.kind ?? 'ssh',
|
|
24
|
+
sshHost: r.ssh_host || null,
|
|
25
|
+
sshUser: r.ssh_user || null,
|
|
26
|
+
sshPort: r.ssh_port,
|
|
27
|
+
platform: r.platform ?? null,
|
|
28
|
+
hubVersion: r.hub_version,
|
|
29
|
+
state: r.state,
|
|
30
|
+
lastSeenAt: r.last_seen_at,
|
|
31
|
+
error: r.error,
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
getHost(id) {
|
|
35
|
+
return this.listHosts().find((h) => h.id === id) ?? null;
|
|
36
|
+
}
|
|
37
|
+
upsertHost(h) {
|
|
38
|
+
this.db
|
|
39
|
+
.prepare(`INSERT INTO host (id, label, kind, ssh_host, ssh_user, ssh_port, key_ref,
|
|
40
|
+
host_token, platform, hub_version, state, last_seen_at, error)
|
|
41
|
+
VALUES (@id, @label, @kind, @sshHost, @sshUser, @sshPort, @keyRef,
|
|
42
|
+
@hostToken, @platform, @hubVersion, @state, @lastSeenAt, @error)
|
|
43
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
44
|
+
label=@label, kind=@kind, ssh_host=@sshHost, ssh_user=@sshUser,
|
|
45
|
+
ssh_port=@sshPort, key_ref=COALESCE(@keyRef, key_ref),
|
|
46
|
+
host_token=COALESCE(@hostToken, host_token), platform=@platform,
|
|
47
|
+
hub_version=@hubVersion, state=@state, last_seen_at=@lastSeenAt,
|
|
48
|
+
error=@error`)
|
|
49
|
+
.run({
|
|
50
|
+
...h,
|
|
51
|
+
sshHost: h.sshHost ?? '',
|
|
52
|
+
sshUser: h.sshUser ?? '',
|
|
53
|
+
platform: h.platform ?? null,
|
|
54
|
+
keyRef: h.keyRef ?? null,
|
|
55
|
+
hostToken: h.hostToken ?? null,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
removeHost(id) {
|
|
59
|
+
this.db.prepare('DELETE FROM host WHERE id = ?').run(id);
|
|
60
|
+
}
|
|
61
|
+
hostKeyRef(id) {
|
|
62
|
+
const r = this.db.prepare('SELECT key_ref FROM host WHERE id = ?').get(id);
|
|
63
|
+
return r?.key_ref ?? null;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Match an enrolled host by the durable token it presents on reconnect.
|
|
67
|
+
* Server-side only — like key_ref, this never travels to the browser.
|
|
68
|
+
*/
|
|
69
|
+
hostByToken(token) {
|
|
70
|
+
const r = this.db.prepare('SELECT id FROM host WHERE host_token = ?').get(token);
|
|
71
|
+
return r ? this.getHost(r.id) : null;
|
|
72
|
+
}
|
|
73
|
+
/* ----------------------------------------------------------- workspaces */
|
|
74
|
+
listWorkspaces() {
|
|
75
|
+
const rows = this.db
|
|
76
|
+
.prepare('SELECT * FROM workspace WHERE archived_at IS NULL ORDER BY created_at')
|
|
77
|
+
.all();
|
|
78
|
+
return rows.map((r) => ({
|
|
79
|
+
id: r.id,
|
|
80
|
+
name: r.name,
|
|
81
|
+
kind: r.kind,
|
|
82
|
+
rootPath: r.root_path,
|
|
83
|
+
hostId: r.host_id,
|
|
84
|
+
color: r.color,
|
|
85
|
+
createdAt: r.created_at,
|
|
86
|
+
archivedAt: r.archived_at,
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
getWorkspace(id) {
|
|
90
|
+
return this.listWorkspaces().find((w) => w.id === id) ?? null;
|
|
91
|
+
}
|
|
92
|
+
getWorkspaceByName(name) {
|
|
93
|
+
return this.listWorkspaces().find((w) => w.name === name) ?? null;
|
|
94
|
+
}
|
|
95
|
+
insertWorkspace(w) {
|
|
96
|
+
this.db
|
|
97
|
+
.prepare(`INSERT INTO workspace (id, name, kind, root_path, host_id, color, created_at, archived_at)
|
|
98
|
+
VALUES (@id, @name, @kind, @rootPath, @hostId, @color, @createdAt, @archivedAt)`)
|
|
99
|
+
.run(w);
|
|
100
|
+
}
|
|
101
|
+
removeWorkspace(id) {
|
|
102
|
+
this.db.prepare('DELETE FROM workspace WHERE id = ?').run(id);
|
|
103
|
+
}
|
|
104
|
+
/* ------------------------------------------------------------- sessions */
|
|
105
|
+
rowToSession(r, resumable) {
|
|
106
|
+
return {
|
|
107
|
+
id: r.id,
|
|
108
|
+
workspaceId: r.workspace_id,
|
|
109
|
+
name: r.name,
|
|
110
|
+
address: makeAddress(r.workspace_name, r.name),
|
|
111
|
+
profile: r.profile,
|
|
112
|
+
cwd: r.cwd,
|
|
113
|
+
agentSessionUuid: r.agent_session_uuid,
|
|
114
|
+
spawnedBy: r.spawned_by,
|
|
115
|
+
state: r.state,
|
|
116
|
+
// Live status is held in memory by the SessionManager; a row loaded from
|
|
117
|
+
// disk is by definition not running, so it reads as unknown until start.
|
|
118
|
+
status: 'unknown',
|
|
119
|
+
statusText: r.status_text,
|
|
120
|
+
title: r.title,
|
|
121
|
+
pid: r.pid,
|
|
122
|
+
exitCode: r.exit_code,
|
|
123
|
+
cols: r.cols,
|
|
124
|
+
rows: r.rows,
|
|
125
|
+
resumable,
|
|
126
|
+
createdAt: r.created_at,
|
|
127
|
+
exitedAt: r.exited_at,
|
|
128
|
+
lastActiveAt: r.last_active_at,
|
|
129
|
+
window: {
|
|
130
|
+
x: r.x ?? DEFAULT_WINDOW.x,
|
|
131
|
+
y: r.y ?? DEFAULT_WINDOW.y,
|
|
132
|
+
w: r.w ?? DEFAULT_WINDOW.w,
|
|
133
|
+
h: r.h ?? DEFAULT_WINDOW.h,
|
|
134
|
+
z: r.z ?? DEFAULT_WINDOW.z,
|
|
135
|
+
collapsed: r.collapsed === 1,
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
selectSession = `
|
|
140
|
+
SELECT s.*, w.name AS workspace_name,
|
|
141
|
+
win.x, win.y, win.w, win.h, win.z, win.collapsed
|
|
142
|
+
FROM session s
|
|
143
|
+
JOIN workspace w ON w.id = s.workspace_id
|
|
144
|
+
LEFT JOIN window win ON win.session_id = s.id
|
|
145
|
+
`;
|
|
146
|
+
listSessions(isResumable) {
|
|
147
|
+
const rows = this.db
|
|
148
|
+
.prepare(`${this.selectSession} ORDER BY s.created_at`)
|
|
149
|
+
.all();
|
|
150
|
+
return rows.map((r) => this.rowToSession(r, isResumable(r.profile)));
|
|
151
|
+
}
|
|
152
|
+
getSession(id, isResumable) {
|
|
153
|
+
const r = this.db
|
|
154
|
+
.prepare(`${this.selectSession} WHERE s.id = ?`)
|
|
155
|
+
.get(id);
|
|
156
|
+
return r ? this.rowToSession(r, isResumable(r.profile)) : null;
|
|
157
|
+
}
|
|
158
|
+
namesInWorkspace(workspaceId) {
|
|
159
|
+
return this.db
|
|
160
|
+
.prepare('SELECT name FROM session WHERE workspace_id = ?')
|
|
161
|
+
.all(workspaceId).map((r) => r.name);
|
|
162
|
+
}
|
|
163
|
+
insertSession(s, spec) {
|
|
164
|
+
const tx = this.db.transaction(() => {
|
|
165
|
+
this.db
|
|
166
|
+
.prepare(`INSERT INTO session (
|
|
167
|
+
id, workspace_id, name, profile, cwd, agent_session_uuid,
|
|
168
|
+
argv_json, env_json, spawned_by, state, status_text, title,
|
|
169
|
+
pid, exit_code, cols, rows, created_at, exited_at, last_active_at)
|
|
170
|
+
VALUES (
|
|
171
|
+
@id, @workspaceId, @name, @profile, @cwd, @agentSessionUuid,
|
|
172
|
+
@argvJson, @envJson, @spawnedBy, @state, @statusText, @title,
|
|
173
|
+
@pid, @exitCode, @cols, @rows, @createdAt, @exitedAt, @lastActiveAt)`)
|
|
174
|
+
.run({
|
|
175
|
+
id: s.id,
|
|
176
|
+
workspaceId: s.workspaceId,
|
|
177
|
+
name: s.name,
|
|
178
|
+
profile: s.profile,
|
|
179
|
+
cwd: s.cwd,
|
|
180
|
+
agentSessionUuid: s.agentSessionUuid,
|
|
181
|
+
argvJson: JSON.stringify(spec.argv),
|
|
182
|
+
envJson: JSON.stringify(spec.env),
|
|
183
|
+
spawnedBy: s.spawnedBy,
|
|
184
|
+
state: s.state,
|
|
185
|
+
statusText: s.statusText,
|
|
186
|
+
title: s.title,
|
|
187
|
+
pid: s.pid,
|
|
188
|
+
exitCode: s.exitCode,
|
|
189
|
+
cols: s.cols,
|
|
190
|
+
rows: s.rows,
|
|
191
|
+
createdAt: s.createdAt,
|
|
192
|
+
exitedAt: s.exitedAt,
|
|
193
|
+
lastActiveAt: s.lastActiveAt,
|
|
194
|
+
});
|
|
195
|
+
this.saveWindow(s.id, s.window);
|
|
196
|
+
});
|
|
197
|
+
tx();
|
|
198
|
+
}
|
|
199
|
+
/** Fields that change over a session's life. Layout is written separately. */
|
|
200
|
+
updateSession(id, patch) {
|
|
201
|
+
const map = {
|
|
202
|
+
state: 'state',
|
|
203
|
+
pid: 'pid',
|
|
204
|
+
exitCode: 'exit_code',
|
|
205
|
+
statusText: 'status_text',
|
|
206
|
+
title: 'title',
|
|
207
|
+
cols: 'cols',
|
|
208
|
+
rows: 'rows',
|
|
209
|
+
exitedAt: 'exited_at',
|
|
210
|
+
lastActiveAt: 'last_active_at',
|
|
211
|
+
agentSessionUuid: 'agent_session_uuid',
|
|
212
|
+
};
|
|
213
|
+
const entries = Object.entries(patch).filter(([, v]) => v !== undefined);
|
|
214
|
+
if (entries.length === 0)
|
|
215
|
+
return;
|
|
216
|
+
const sets = entries.map(([k]) => `${map[k]} = @${k}`).join(', ');
|
|
217
|
+
this.db
|
|
218
|
+
.prepare(`UPDATE session SET ${sets} WHERE id = @id`)
|
|
219
|
+
.run({ id, ...Object.fromEntries(entries) });
|
|
220
|
+
}
|
|
221
|
+
getLaunchSpec(id) {
|
|
222
|
+
const r = this.db
|
|
223
|
+
.prepare('SELECT argv_json, env_json FROM session WHERE id = ?')
|
|
224
|
+
.get(id);
|
|
225
|
+
if (!r)
|
|
226
|
+
return null;
|
|
227
|
+
return { argv: JSON.parse(r.argv_json), env: JSON.parse(r.env_json) };
|
|
228
|
+
}
|
|
229
|
+
setLaunchSpec(id, spec) {
|
|
230
|
+
this.db
|
|
231
|
+
.prepare('UPDATE session SET argv_json = ?, env_json = ? WHERE id = ?')
|
|
232
|
+
.run(JSON.stringify(spec.argv), JSON.stringify(spec.env), id);
|
|
233
|
+
}
|
|
234
|
+
removeSession(id) {
|
|
235
|
+
this.db.prepare('DELETE FROM session WHERE id = ?').run(id);
|
|
236
|
+
}
|
|
237
|
+
/* --------------------------------------------------------------- layout */
|
|
238
|
+
saveWindow(sessionId, rect) {
|
|
239
|
+
this.db
|
|
240
|
+
.prepare(`INSERT INTO window (session_id, x, y, w, h, z, collapsed)
|
|
241
|
+
VALUES (@sessionId, @x, @y, @w, @h, @z, @collapsed)
|
|
242
|
+
ON CONFLICT(session_id) DO UPDATE SET
|
|
243
|
+
x=@x, y=@y, w=@w, h=@h, z=@z, collapsed=@collapsed`)
|
|
244
|
+
.run({ sessionId, ...rect, collapsed: rect.collapsed ? 1 : 0 });
|
|
245
|
+
}
|
|
246
|
+
getViewport() {
|
|
247
|
+
const r = this.db.prepare('SELECT * FROM viewport WHERE id = 1').get();
|
|
248
|
+
return r ? { panX: r.pan_x, panY: r.pan_y, zoom: r.zoom } : { panX: 0, panY: 0, zoom: 1 };
|
|
249
|
+
}
|
|
250
|
+
saveViewport(v) {
|
|
251
|
+
this.db
|
|
252
|
+
.prepare(`INSERT INTO viewport (id, pan_x, pan_y, zoom) VALUES (1, @panX, @panY, @zoom)
|
|
253
|
+
ON CONFLICT(id) DO UPDATE SET pan_x=@panX, pan_y=@panY, zoom=@zoom`)
|
|
254
|
+
.run(v);
|
|
255
|
+
}
|
|
256
|
+
/* -------------------------------------------------- remote window layout */
|
|
257
|
+
/**
|
|
258
|
+
* Layout for peer-hosted sessions, keyed by address. Remote session state
|
|
259
|
+
* itself is never cached here; the peer owns it.
|
|
260
|
+
*/
|
|
261
|
+
getRemoteWindows() {
|
|
262
|
+
const rows = this.db.prepare('SELECT * FROM remote_window').all();
|
|
263
|
+
return new Map(rows.map((r) => [
|
|
264
|
+
r.address,
|
|
265
|
+
{ x: r.x, y: r.y, w: r.w, h: r.h, z: r.z, collapsed: r.collapsed === 1 },
|
|
266
|
+
]));
|
|
267
|
+
}
|
|
268
|
+
saveRemoteWindow(address, hostId, rect) {
|
|
269
|
+
this.db
|
|
270
|
+
.prepare(`INSERT INTO remote_window (address, host_id, x, y, w, h, z, collapsed)
|
|
271
|
+
VALUES (@address, @hostId, @x, @y, @w, @h, @z, @collapsed)
|
|
272
|
+
ON CONFLICT(address) DO UPDATE SET
|
|
273
|
+
host_id=@hostId, x=@x, y=@y, w=@w, h=@h, z=@z, collapsed=@collapsed`)
|
|
274
|
+
.run({ address, hostId, ...rect, collapsed: rect.collapsed ? 1 : 0 });
|
|
275
|
+
}
|
|
276
|
+
removeRemoteWindow(address) {
|
|
277
|
+
this.db.prepare('DELETE FROM remote_window WHERE address = ?').run(address);
|
|
278
|
+
}
|
|
279
|
+
/* ----------------------------------------------- deferred removals */
|
|
280
|
+
/**
|
|
281
|
+
* Addresses the user closed while their host was unreachable, kept until
|
|
282
|
+
* that host can be told. Keyed by address for the same reason remote_window
|
|
283
|
+
* is: the owning hub's session id means nothing in this database.
|
|
284
|
+
*/
|
|
285
|
+
pendingRemovals(hostId) {
|
|
286
|
+
const rows = (hostId
|
|
287
|
+
? this.db.prepare('SELECT * FROM pending_removal WHERE host_id = ?').all(hostId)
|
|
288
|
+
: this.db.prepare('SELECT * FROM pending_removal').all());
|
|
289
|
+
return rows.map((r) => ({ address: r.address, hostId: r.host_id }));
|
|
290
|
+
}
|
|
291
|
+
addPendingRemoval(address, hostId) {
|
|
292
|
+
this.db
|
|
293
|
+
.prepare(`INSERT INTO pending_removal (address, host_id, requested_at)
|
|
294
|
+
VALUES (@address, @hostId, @requestedAt)
|
|
295
|
+
ON CONFLICT(address) DO UPDATE SET host_id=@hostId, requested_at=@requestedAt`)
|
|
296
|
+
.run({ address, hostId, requestedAt: Date.now() });
|
|
297
|
+
}
|
|
298
|
+
clearPendingRemoval(address) {
|
|
299
|
+
this.db.prepare('DELETE FROM pending_removal WHERE address = ?').run(address);
|
|
300
|
+
}
|
|
301
|
+
/* ------------------------------------------------------------ snapshots */
|
|
302
|
+
saveSnapshot(sessionId, serialized, cols, rows) {
|
|
303
|
+
this.db
|
|
304
|
+
.prepare(`INSERT INTO session_snapshot (session_id, serialized, cols, rows, captured_at)
|
|
305
|
+
VALUES (@sessionId, @serialized, @cols, @rows, @capturedAt)
|
|
306
|
+
ON CONFLICT(session_id) DO UPDATE SET
|
|
307
|
+
serialized=@serialized, cols=@cols, rows=@rows, captured_at=@capturedAt`)
|
|
308
|
+
.run({ sessionId, serialized, cols, rows, capturedAt: Date.now() });
|
|
309
|
+
}
|
|
310
|
+
getSnapshot(sessionId) {
|
|
311
|
+
const r = this.db
|
|
312
|
+
.prepare('SELECT serialized, cols, rows FROM session_snapshot WHERE session_id = ?')
|
|
313
|
+
.get(sessionId);
|
|
314
|
+
return r ?? null;
|
|
315
|
+
}
|
|
316
|
+
/* ------------------------------------------------------------- messages */
|
|
317
|
+
listMessages(limit = 500) {
|
|
318
|
+
const rows = this.db
|
|
319
|
+
.prepare('SELECT * FROM message ORDER BY sent_at DESC LIMIT ?')
|
|
320
|
+
.all(limit);
|
|
321
|
+
return rows
|
|
322
|
+
.map((r) => ({
|
|
323
|
+
id: r.id,
|
|
324
|
+
fromAddr: r.from_addr,
|
|
325
|
+
toAddr: r.to_addr,
|
|
326
|
+
body: r.body,
|
|
327
|
+
sentAt: r.sent_at,
|
|
328
|
+
deliveredAt: r.delivered_at,
|
|
329
|
+
deliveryState: r.delivery_state,
|
|
330
|
+
error: r.error,
|
|
331
|
+
}))
|
|
332
|
+
.reverse();
|
|
333
|
+
}
|
|
334
|
+
insertMessage(m) {
|
|
335
|
+
this.db
|
|
336
|
+
.prepare(`INSERT INTO message (id, from_addr, to_addr, body, sent_at, delivered_at, delivery_state, error)
|
|
337
|
+
VALUES (@id, @fromAddr, @toAddr, @body, @sentAt, @deliveredAt, @deliveryState, @error)`)
|
|
338
|
+
.run(m);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/db/store.ts"],"names":[],"mappings":"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"}
|
package/dist/hub.d.ts
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { type Message, type Host, type Session, type Viewport, type WindowRect, type Workspace } from './protocol/index.js';
|
|
3
|
+
import { type Db } from './db/index.js';
|
|
4
|
+
import { Store } from './db/store.js';
|
|
5
|
+
import { ProfileRegistry } from './agents/profiles.js';
|
|
6
|
+
import { TokenRegistry } from './agents/tokens.js';
|
|
7
|
+
import { MessageRouter } from './agents/router.js';
|
|
8
|
+
import { SessionManager } from './session/manager.js';
|
|
9
|
+
import type { AgentApi } from './mcp/server.js';
|
|
10
|
+
import { PeerRegistry } from './remote/registry.js';
|
|
11
|
+
import type { Uplink } from './remote/peer-serve.js';
|
|
12
|
+
export declare const HUB_VERSION = "0.1.0";
|
|
13
|
+
/** How many agents one workspace may hold, bounding runaway recursive spawns. */
|
|
14
|
+
export declare const DEFAULT_SPAWN_CAP = 12;
|
|
15
|
+
export interface HubOptions {
|
|
16
|
+
dbPath?: string;
|
|
17
|
+
spawnCap?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The hub: owns the database, the sessions, and the routing between agents.
|
|
21
|
+
* The web server and the MCP endpoint are thin layers over this.
|
|
22
|
+
*/
|
|
23
|
+
export declare class Hub extends EventEmitter implements AgentApi {
|
|
24
|
+
readonly db: Db;
|
|
25
|
+
readonly store: Store;
|
|
26
|
+
readonly profiles: ProfileRegistry;
|
|
27
|
+
readonly tokens: TokenRegistry;
|
|
28
|
+
readonly sessions: SessionManager;
|
|
29
|
+
readonly router: MessageRouter;
|
|
30
|
+
readonly peers: PeerRegistry;
|
|
31
|
+
/**
|
|
32
|
+
* The link back to the canvas this hub was attached to, if it was. Null on a
|
|
33
|
+
* hub that owns a canvas — which is what makes the difference between the
|
|
34
|
+
* two roles a null check rather than a flag.
|
|
35
|
+
*/
|
|
36
|
+
private uplink;
|
|
37
|
+
private announceTimer;
|
|
38
|
+
/** Live SSH tunnels, keyed by host id. Not persisted: they die with the hub. */
|
|
39
|
+
private readonly tunnels;
|
|
40
|
+
private readonly spawnCap;
|
|
41
|
+
constructor(opts?: HubOptions);
|
|
42
|
+
/**
|
|
43
|
+
* A persisted `connected` is a lie the moment this process starts: the
|
|
44
|
+
* tunnels and sockets died with the last one. Mark every host down, then
|
|
45
|
+
* redial the ones we know how to reach. Enrolled hosts are left alone —
|
|
46
|
+
* they dial us, and arrive on their own.
|
|
47
|
+
*/
|
|
48
|
+
private reconcileHostsOnBoot;
|
|
49
|
+
/** Local sessions plus every session reported by a connected peer. */
|
|
50
|
+
allSessions(): Session[];
|
|
51
|
+
/**
|
|
52
|
+
* Resolve an address to a local session, one on a peer we hold, one the
|
|
53
|
+
* canvas told us about, or nothing.
|
|
54
|
+
*
|
|
55
|
+
* The three are exclusive by construction: a hub either owns the canvas and
|
|
56
|
+
* has peers, or is attached to one and has an uplink. Never both.
|
|
57
|
+
*/
|
|
58
|
+
private locate;
|
|
59
|
+
/**
|
|
60
|
+
* Attach this hub to the canvas reachable over `uplink`.
|
|
61
|
+
*
|
|
62
|
+
* Called by whatever owns the socket, once, at wiring time. A hub that owns
|
|
63
|
+
* its own canvas never calls it.
|
|
64
|
+
*/
|
|
65
|
+
setUplink(uplink: Uplink | null): void;
|
|
66
|
+
setOrigin(origin: string): void;
|
|
67
|
+
createWorkspace(name: string, rootPath: string, hostId?: string | null): Workspace;
|
|
68
|
+
removeWorkspace(id: string): Promise<void>;
|
|
69
|
+
addHost(input: {
|
|
70
|
+
label: string;
|
|
71
|
+
sshHost: string;
|
|
72
|
+
sshUser: string;
|
|
73
|
+
sshPort: number;
|
|
74
|
+
privateKeyPath?: string;
|
|
75
|
+
}): Host;
|
|
76
|
+
/**
|
|
77
|
+
* Drop a host from the canvas, and stop the hub running on it.
|
|
78
|
+
*
|
|
79
|
+
* Stopping it matters more than it looks: that hub is a daemon on someone
|
|
80
|
+
* else's machine, and if it keeps running it holds its own install open —
|
|
81
|
+
* on Windows an in-use .node cannot be deleted, so re-joining that machine
|
|
82
|
+
* fails on a permission error rather than replacing the files.
|
|
83
|
+
*/
|
|
84
|
+
removeHost(hostId: string): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Deploy the hub to a host if needed, tunnel to it, and join it to the
|
|
87
|
+
* directory. The peer token is minted per connection and never written to
|
|
88
|
+
* the local database.
|
|
89
|
+
*/
|
|
90
|
+
connectHost(hostId: string): Promise<void>;
|
|
91
|
+
startSession(opts: {
|
|
92
|
+
workspaceId: string;
|
|
93
|
+
profile: string;
|
|
94
|
+
name?: string;
|
|
95
|
+
cwd?: string;
|
|
96
|
+
spawnedBy?: string | null;
|
|
97
|
+
}): Promise<Session>;
|
|
98
|
+
resumeWorkspace(workspaceId: string): Promise<Session[]>;
|
|
99
|
+
moveWindow(sessionId: string, rect: WindowRect): void;
|
|
100
|
+
setViewport(v: Viewport): void;
|
|
101
|
+
private requireSession;
|
|
102
|
+
whoami(sessionId: string): Promise<{
|
|
103
|
+
address: string;
|
|
104
|
+
workspace: string | null;
|
|
105
|
+
cwd: string;
|
|
106
|
+
profile: string;
|
|
107
|
+
spawnedBy: string | null;
|
|
108
|
+
}>;
|
|
109
|
+
/**
|
|
110
|
+
* One flat directory across every hub. An agent should not have to know or
|
|
111
|
+
* care whether a peer is on this machine or a remote one; the address is
|
|
112
|
+
* the whole interface.
|
|
113
|
+
*/
|
|
114
|
+
listAgents(sessionId: string, workspace?: string): Promise<{
|
|
115
|
+
address: string;
|
|
116
|
+
workspace: string | null;
|
|
117
|
+
profile: string;
|
|
118
|
+
state: "starting" | "running" | "stopped" | "exited" | "failed";
|
|
119
|
+
status: "idle" | "busy" | "unknown";
|
|
120
|
+
statusText: string | null;
|
|
121
|
+
host: string;
|
|
122
|
+
isYou: boolean;
|
|
123
|
+
}[]>;
|
|
124
|
+
sendMessage(sessionId: string, to: string, text: string): Promise<{
|
|
125
|
+
delivered: boolean;
|
|
126
|
+
to: string;
|
|
127
|
+
deliveredAt: number | null;
|
|
128
|
+
}>;
|
|
129
|
+
/**
|
|
130
|
+
* Tell every attached machine who is on the canvas.
|
|
131
|
+
*
|
|
132
|
+
* Coalesced, because a status change is a session change and agents change
|
|
133
|
+
* status several times a turn; the directory only needs to be right once the
|
|
134
|
+
* dust settles. Unrefed so a pending announcement never holds the hub up.
|
|
135
|
+
*/
|
|
136
|
+
private scheduleAnnounce;
|
|
137
|
+
/**
|
|
138
|
+
* The canvas as one machine on it should see it: everything, minus that
|
|
139
|
+
* machine's own agents. It has those already, and sending them back would
|
|
140
|
+
* have every agent over there listed twice.
|
|
141
|
+
*/
|
|
142
|
+
private directoryFor;
|
|
143
|
+
/**
|
|
144
|
+
* Deliver on behalf of an address this hub has already established.
|
|
145
|
+
*
|
|
146
|
+
* Three ways out, and which one is taken is the only difference between an
|
|
147
|
+
* agent in the next window, one on a machine this hub holds, and one only
|
|
148
|
+
* the canvas can reach. No caller sees which.
|
|
149
|
+
*/
|
|
150
|
+
deliverFrom(fromAddr: string, to: string, text: string): Promise<{
|
|
151
|
+
delivered: boolean;
|
|
152
|
+
to: string;
|
|
153
|
+
deliveredAt: number | null;
|
|
154
|
+
}>;
|
|
155
|
+
spawnAgent(sessionId: string, opts: {
|
|
156
|
+
profile?: string;
|
|
157
|
+
name?: string;
|
|
158
|
+
workspace?: string;
|
|
159
|
+
prompt?: string;
|
|
160
|
+
}): Promise<{
|
|
161
|
+
address: string;
|
|
162
|
+
workspace: string;
|
|
163
|
+
profile: string;
|
|
164
|
+
promptQueued: boolean;
|
|
165
|
+
}>;
|
|
166
|
+
/**
|
|
167
|
+
* Wait for a freshly spawned agent to produce output (its prompt) before
|
|
168
|
+
* injecting the first instruction. Bounded so a CLI that never prints
|
|
169
|
+
* cannot leave this hanging.
|
|
170
|
+
*/
|
|
171
|
+
private deliverInitialPrompt;
|
|
172
|
+
readScreen(sessionId: string, address: string, lines?: number): Promise<unknown>;
|
|
173
|
+
/**
|
|
174
|
+
* read_screen for a caller this hub has already established — either an
|
|
175
|
+
* agent of its own, or a peer that authenticated one and is asking on its
|
|
176
|
+
* behalf. Resolves the address the same three ways a delivery does.
|
|
177
|
+
*/
|
|
178
|
+
private readScreenAt;
|
|
179
|
+
setStatus(sessionId: string, text: string): Promise<{
|
|
180
|
+
ok: boolean;
|
|
181
|
+
}>;
|
|
182
|
+
stopAgent(sessionId: string, address: string): Promise<{
|
|
183
|
+
stopped: string;
|
|
184
|
+
}>;
|
|
185
|
+
messages(): Message[];
|
|
186
|
+
shutdown(): void;
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=hub.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hub.d.ts","sourceRoot":"","sources":["../src/hub.ts"],"names":[],"mappings":"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"}
|