@vibecompany/247-cli 0.1.0 → 0.2.2

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 (70) hide show
  1. package/agent/dist/db/environments.d.ts +65 -0
  2. package/agent/dist/db/environments.d.ts.map +1 -0
  3. package/agent/dist/db/environments.js +243 -0
  4. package/agent/dist/db/environments.js.map +1 -0
  5. package/agent/dist/db/history.d.ts +37 -0
  6. package/agent/dist/db/history.d.ts.map +1 -0
  7. package/agent/dist/db/history.js +98 -0
  8. package/agent/dist/db/history.js.map +1 -0
  9. package/agent/dist/db/index.d.ts +37 -0
  10. package/agent/dist/db/index.d.ts.map +1 -0
  11. package/agent/dist/db/index.js +225 -0
  12. package/agent/dist/db/index.js.map +1 -0
  13. package/agent/dist/db/schema.d.ts +70 -0
  14. package/agent/dist/db/schema.d.ts.map +1 -0
  15. package/agent/dist/db/schema.js +79 -0
  16. package/agent/dist/db/schema.js.map +1 -0
  17. package/agent/dist/db/sessions.d.ts +75 -0
  18. package/agent/dist/db/sessions.d.ts.map +1 -0
  19. package/agent/dist/db/sessions.js +244 -0
  20. package/agent/dist/db/sessions.js.map +1 -0
  21. package/agent/dist/editor.d.ts +18 -0
  22. package/agent/dist/editor.d.ts.map +1 -0
  23. package/agent/dist/editor.js +220 -0
  24. package/agent/dist/editor.js.map +1 -0
  25. package/agent/dist/environments.d.ts +59 -0
  26. package/agent/dist/environments.d.ts.map +1 -0
  27. package/agent/dist/environments.js +229 -0
  28. package/agent/dist/environments.js.map +1 -0
  29. package/agent/dist/git.d.ts +39 -0
  30. package/agent/dist/git.d.ts.map +1 -0
  31. package/agent/dist/git.js +436 -0
  32. package/agent/dist/git.js.map +1 -0
  33. package/agent/dist/index.d.ts +2 -0
  34. package/agent/dist/index.d.ts.map +1 -0
  35. package/agent/dist/index.js +17 -0
  36. package/agent/dist/index.js.map +1 -0
  37. package/agent/dist/server.d.ts +2 -0
  38. package/agent/dist/server.d.ts.map +1 -0
  39. package/agent/dist/server.js +1062 -0
  40. package/agent/dist/server.js.map +1 -0
  41. package/agent/dist/terminal.d.ts +14 -0
  42. package/agent/dist/terminal.d.ts.map +1 -0
  43. package/agent/dist/terminal.js +115 -0
  44. package/agent/dist/terminal.js.map +1 -0
  45. package/dist/commands/init.d.ts.map +1 -1
  46. package/dist/commands/init.js +25 -14
  47. package/dist/commands/init.js.map +1 -1
  48. package/dist/commands/profile.d.ts +3 -0
  49. package/dist/commands/profile.d.ts.map +1 -0
  50. package/dist/commands/profile.js +156 -0
  51. package/dist/commands/profile.js.map +1 -0
  52. package/dist/commands/start.d.ts.map +1 -1
  53. package/dist/commands/start.js +21 -10
  54. package/dist/commands/start.js.map +1 -1
  55. package/dist/index.d.ts +3 -1
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +6 -1
  58. package/dist/index.js.map +1 -1
  59. package/dist/lib/config.d.ts +30 -5
  60. package/dist/lib/config.d.ts.map +1 -1
  61. package/dist/lib/config.js +85 -12
  62. package/dist/lib/config.js.map +1 -1
  63. package/dist/lib/process.d.ts +2 -1
  64. package/dist/lib/process.d.ts.map +1 -1
  65. package/dist/lib/process.js +10 -4
  66. package/dist/lib/process.js.map +1 -1
  67. package/hooks/.claude-plugin/plugin.json +5 -0
  68. package/hooks/hooks/hooks.json +61 -0
  69. package/hooks/scripts/notify-status.sh +89 -0
  70. package/package.json +22 -5
@@ -0,0 +1,244 @@
1
+ import { getDatabase } from './index.js';
2
+ import { recordStatusChange } from './history.js';
3
+ /**
4
+ * Get a session by name
5
+ */
6
+ export function getSession(name) {
7
+ const db = getDatabase();
8
+ const row = db.prepare('SELECT * FROM sessions WHERE name = ?').get(name);
9
+ return row ?? null;
10
+ }
11
+ /**
12
+ * Get all active (non-archived) sessions
13
+ */
14
+ export function getAllSessions() {
15
+ const db = getDatabase();
16
+ return db
17
+ .prepare('SELECT * FROM sessions WHERE archived_at IS NULL ORDER BY last_activity DESC')
18
+ .all();
19
+ }
20
+ /**
21
+ * Get all archived sessions
22
+ */
23
+ export function getArchivedSessions() {
24
+ const db = getDatabase();
25
+ return db
26
+ .prepare('SELECT * FROM sessions WHERE archived_at IS NOT NULL ORDER BY archived_at DESC')
27
+ .all();
28
+ }
29
+ /**
30
+ * Get sessions by project
31
+ */
32
+ export function getSessionsByProject(project) {
33
+ const db = getDatabase();
34
+ return db
35
+ .prepare('SELECT * FROM sessions WHERE project = ? ORDER BY last_activity DESC')
36
+ .all(project);
37
+ }
38
+ /**
39
+ * Upsert a session (insert or update)
40
+ * Records status history if status changed
41
+ */
42
+ export function upsertSession(name, input) {
43
+ const db = getDatabase();
44
+ const now = Date.now();
45
+ // Check existing session for status change detection
46
+ const existing = getSession(name);
47
+ const statusChanged = !existing || existing.status !== input.status;
48
+ const stmt = db.prepare(`
49
+ INSERT INTO sessions (
50
+ name, project, status, attention_reason, last_event,
51
+ last_activity, last_status_change, environment_id, created_at, updated_at
52
+ )
53
+ VALUES (
54
+ @name, @project, @status, @attentionReason, @lastEvent,
55
+ @lastActivity, @lastStatusChange, @environmentId, @createdAt, @updatedAt
56
+ )
57
+ ON CONFLICT(name) DO UPDATE SET
58
+ status = @status,
59
+ attention_reason = @attentionReason,
60
+ last_event = @lastEvent,
61
+ last_activity = @lastActivity,
62
+ last_status_change = @lastStatusChange,
63
+ environment_id = COALESCE(@environmentId, environment_id),
64
+ updated_at = @updatedAt
65
+ `);
66
+ stmt.run({
67
+ name,
68
+ project: input.project,
69
+ status: input.status,
70
+ attentionReason: input.attentionReason ?? null,
71
+ lastEvent: input.lastEvent ?? null,
72
+ lastActivity: input.lastActivity,
73
+ lastStatusChange: statusChanged ? now : (existing?.last_status_change ?? now),
74
+ environmentId: input.environmentId ?? null,
75
+ createdAt: existing?.created_at ?? now,
76
+ updatedAt: now,
77
+ });
78
+ // Record status history if status changed
79
+ if (statusChanged) {
80
+ recordStatusChange(name, input.status, input.attentionReason ?? null, input.lastEvent ?? null);
81
+ }
82
+ return getSession(name);
83
+ }
84
+ /**
85
+ * Update session status only
86
+ */
87
+ export function updateSessionStatus(name, status, attentionReason, lastEvent) {
88
+ const db = getDatabase();
89
+ const now = Date.now();
90
+ const existing = getSession(name);
91
+ if (!existing) {
92
+ return false;
93
+ }
94
+ const statusChanged = existing.status !== status;
95
+ const stmt = db.prepare(`
96
+ UPDATE sessions SET
97
+ status = ?,
98
+ attention_reason = ?,
99
+ last_event = COALESCE(?, last_event),
100
+ last_activity = ?,
101
+ last_status_change = ?,
102
+ updated_at = ?
103
+ WHERE name = ?
104
+ `);
105
+ stmt.run(status, attentionReason ?? null, lastEvent, now, statusChanged ? now : existing.last_status_change, now, name);
106
+ // Record status history if status changed
107
+ if (statusChanged) {
108
+ recordStatusChange(name, status, attentionReason ?? null, lastEvent ?? null);
109
+ }
110
+ return true;
111
+ }
112
+ /**
113
+ * Delete a session
114
+ */
115
+ export function deleteSession(name) {
116
+ const db = getDatabase();
117
+ const result = db.prepare('DELETE FROM sessions WHERE name = ?').run(name);
118
+ return result.changes > 0;
119
+ }
120
+ /**
121
+ * Archive a session (mark as done and keep in history)
122
+ * Returns the archived session or null if not found
123
+ */
124
+ export function archiveSession(name) {
125
+ const db = getDatabase();
126
+ const now = Date.now();
127
+ const existing = getSession(name);
128
+ if (!existing) {
129
+ return null;
130
+ }
131
+ // Already archived
132
+ if (existing.archived_at) {
133
+ return existing;
134
+ }
135
+ db.prepare(`
136
+ UPDATE sessions SET
137
+ archived_at = ?,
138
+ updated_at = ?
139
+ WHERE name = ?
140
+ `).run(now, now, name);
141
+ console.log(`[DB] Archived session: ${name}`);
142
+ return getSession(name);
143
+ }
144
+ /**
145
+ * Cleanup stale sessions (older than maxAge)
146
+ * - Non-archived sessions: delete if last_activity older than maxAge
147
+ * - Archived sessions: delete if archived_at older than archivedMaxAge
148
+ * Returns number of deleted sessions
149
+ */
150
+ export function cleanupStaleSessions(maxAge, archivedMaxAge) {
151
+ const db = getDatabase();
152
+ const now = Date.now();
153
+ const cutoff = now - maxAge;
154
+ // Delete stale non-archived sessions
155
+ const activeResult = db
156
+ .prepare('DELETE FROM sessions WHERE archived_at IS NULL AND last_activity < ?')
157
+ .run(cutoff);
158
+ let archivedDeleted = 0;
159
+ if (archivedMaxAge) {
160
+ const archivedCutoff = now - archivedMaxAge;
161
+ const archivedResult = db
162
+ .prepare('DELETE FROM sessions WHERE archived_at IS NOT NULL AND archived_at < ?')
163
+ .run(archivedCutoff);
164
+ archivedDeleted = archivedResult.changes;
165
+ }
166
+ const totalDeleted = activeResult.changes + archivedDeleted;
167
+ if (totalDeleted > 0) {
168
+ console.log(`[DB] Cleaned up ${activeResult.changes} stale sessions, ${archivedDeleted} old archived sessions`);
169
+ }
170
+ return totalDeleted;
171
+ }
172
+ /**
173
+ * Reconcile sessions with active tmux sessions
174
+ * - Sessions in DB but not in tmux: mark as idle or delete if old
175
+ * - Sessions in tmux but not in DB: create with idle status
176
+ * - Archived sessions are skipped (they don't have tmux sessions)
177
+ */
178
+ export function reconcileWithTmux(activeTmuxSessions) {
179
+ const dbSessions = getAllSessions(); // Only gets non-archived sessions
180
+ const now = Date.now();
181
+ const maxAge = 24 * 60 * 60 * 1000; // 24 hours
182
+ console.log(`[DB] Reconciling ${dbSessions.length} DB sessions with ${activeTmuxSessions.size} tmux sessions`);
183
+ // Handle sessions in DB but not in tmux (skip archived - they're already handled)
184
+ for (const session of dbSessions) {
185
+ if (!activeTmuxSessions.has(session.name)) {
186
+ const age = now - session.last_activity;
187
+ if (age > maxAge) {
188
+ // Delete old sessions
189
+ deleteSession(session.name);
190
+ console.log(`[DB] Deleted stale session: ${session.name}`);
191
+ }
192
+ else if (session.status !== 'idle') {
193
+ // Mark as idle since tmux session is gone
194
+ updateSessionStatus(session.name, 'idle', null, 'session_ended');
195
+ console.log(`[DB] Marked session as idle: ${session.name}`);
196
+ }
197
+ }
198
+ }
199
+ // Handle sessions in tmux but not in DB
200
+ // These will be created when they receive their first status update
201
+ // We don't create them here because we don't have project info
202
+ }
203
+ /**
204
+ * Get session environment mapping
205
+ */
206
+ export function getSessionEnvironmentId(sessionName) {
207
+ const db = getDatabase();
208
+ const row = db
209
+ .prepare('SELECT environment_id FROM session_environments WHERE session_name = ?')
210
+ .get(sessionName);
211
+ return row?.environment_id ?? null;
212
+ }
213
+ /**
214
+ * Set session environment mapping
215
+ */
216
+ export function setSessionEnvironmentId(sessionName, environmentId) {
217
+ const db = getDatabase();
218
+ db.prepare(`
219
+ INSERT OR REPLACE INTO session_environments (session_name, environment_id)
220
+ VALUES (?, ?)
221
+ `).run(sessionName, environmentId);
222
+ }
223
+ /**
224
+ * Clear session environment mapping
225
+ */
226
+ export function clearSessionEnvironmentId(sessionName) {
227
+ const db = getDatabase();
228
+ db.prepare('DELETE FROM session_environments WHERE session_name = ?').run(sessionName);
229
+ }
230
+ /**
231
+ * Convert DbSession to HookStatus format (for compatibility with existing code)
232
+ */
233
+ export function toHookStatus(session) {
234
+ return {
235
+ status: session.status,
236
+ attentionReason: session.attention_reason ?? undefined,
237
+ lastEvent: session.last_event ?? '',
238
+ lastActivity: session.last_activity,
239
+ lastStatusChange: session.last_status_change,
240
+ project: session.project,
241
+ archivedAt: session.archived_at ?? undefined,
242
+ };
243
+ }
244
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/db/sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { ChildProcess } from 'child_process';
2
+ import type { EditorConfig, EditorStatus } from '@vibecompany/247-shared';
3
+ interface EditorInstance {
4
+ project: string;
5
+ port: number;
6
+ process: ChildProcess;
7
+ startedAt: number;
8
+ lastActivity: number;
9
+ }
10
+ export declare function initEditor(config: EditorConfig | undefined, basePath: string): Promise<void>;
11
+ export declare function getOrStartEditor(project: string): Promise<EditorInstance>;
12
+ export declare function stopEditor(project: string): boolean;
13
+ export declare function getEditorStatus(project: string): EditorStatus;
14
+ export declare function getAllEditors(): EditorStatus[];
15
+ export declare function updateEditorActivity(project: string): void;
16
+ export declare function shutdownAllEditors(): void;
17
+ export {};
18
+ //# sourceMappingURL=editor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../src/editor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,YAAY,EAAY,MAAM,eAAe,CAAC;AAE9D,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE1E,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,YAAY,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAmBD,wBAAsB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAalG;AA2ED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CA+E/E;AAGD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAUnD;AAYD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAW7D;AAGD,wBAAgB,aAAa,IAAI,YAAY,EAAE,CAE9C;AAGD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAK1D;AAgBD,wBAAgB,kBAAkB,IAAI,IAAI,CAKzC"}
@@ -0,0 +1,220 @@
1
+ import { spawn, execSync } from 'child_process';
2
+ import { createConnection } from 'net';
3
+ // Active code-server instances (one per project)
4
+ const editorInstances = new Map();
5
+ // Port allocation tracking
6
+ const usedPorts = new Set();
7
+ // Default config if not provided
8
+ const DEFAULT_CONFIG = {
9
+ enabled: true,
10
+ portRange: { start: 4680, end: 4699 },
11
+ idleTimeout: 30 * 60 * 1000, // 30 minutes
12
+ };
13
+ let editorConfig = DEFAULT_CONFIG;
14
+ let projectsBasePath = '~/Dev';
15
+ // Initialize editor manager with config
16
+ export async function initEditor(config, basePath) {
17
+ editorConfig = config || DEFAULT_CONFIG;
18
+ projectsBasePath = basePath;
19
+ if (editorConfig.enabled) {
20
+ // Kill any orphan code-server processes from previous runs
21
+ console.log('[Editor] Cleaning up orphan code-server processes...');
22
+ await killOrphanCodeServers();
23
+ // Start idle cleanup interval (check every 5 minutes)
24
+ setInterval(cleanupIdleEditors, 5 * 60 * 1000);
25
+ console.log('[Editor] Manager initialized, idle timeout:', editorConfig.idleTimeout / 1000, 's');
26
+ }
27
+ }
28
+ // Check if a port is actually in use by trying to connect
29
+ function isPortInUse(port) {
30
+ return new Promise((resolve) => {
31
+ const socket = createConnection({ port, host: '127.0.0.1' });
32
+ socket.setTimeout(500);
33
+ socket.on('connect', () => {
34
+ socket.destroy();
35
+ resolve(true);
36
+ });
37
+ socket.on('timeout', () => {
38
+ socket.destroy();
39
+ resolve(false);
40
+ });
41
+ socket.on('error', () => {
42
+ socket.destroy();
43
+ resolve(false);
44
+ });
45
+ });
46
+ }
47
+ // Kill any orphan code-server processes on the port range
48
+ async function killOrphanCodeServers() {
49
+ try {
50
+ // Find code-server processes listening on our port range
51
+ const result = execSync(`lsof -i :${editorConfig.portRange.start}-${editorConfig.portRange.end} -t 2>/dev/null || true`, { encoding: 'utf8' }).trim();
52
+ if (result) {
53
+ const pids = result.split('\n').filter(Boolean);
54
+ for (const pid of pids) {
55
+ try {
56
+ console.log(`[Editor] Killing orphan process on port range: PID ${pid}`);
57
+ process.kill(parseInt(pid), 'SIGTERM');
58
+ }
59
+ catch {
60
+ // Process may have already exited
61
+ }
62
+ }
63
+ // Wait a bit for processes to terminate
64
+ await new Promise(resolve => setTimeout(resolve, 500));
65
+ }
66
+ }
67
+ catch {
68
+ // lsof may not be available or no processes found
69
+ }
70
+ }
71
+ // Allocate next available port from range (checks actual usage)
72
+ async function allocatePort() {
73
+ for (let port = editorConfig.portRange.start; port <= editorConfig.portRange.end; port++) {
74
+ if (!usedPorts.has(port)) {
75
+ // Double-check the port is actually free
76
+ const inUse = await isPortInUse(port);
77
+ if (!inUse) {
78
+ usedPorts.add(port);
79
+ return port;
80
+ }
81
+ else {
82
+ console.log(`[Editor] Port ${port} is in use by another process, skipping`);
83
+ }
84
+ }
85
+ }
86
+ return null;
87
+ }
88
+ // Release port back to pool
89
+ function releasePort(port) {
90
+ usedPorts.delete(port);
91
+ }
92
+ // Get or start code-server for a project
93
+ export async function getOrStartEditor(project) {
94
+ // Check if already running
95
+ const existing = editorInstances.get(project);
96
+ if (existing) {
97
+ existing.lastActivity = Date.now();
98
+ return existing;
99
+ }
100
+ // Allocate port (checks actual port availability)
101
+ const port = await allocatePort();
102
+ if (!port) {
103
+ throw new Error('No available ports for code-server');
104
+ }
105
+ // Resolve project path
106
+ const projectPath = `${projectsBasePath}/${project}`.replace('~', process.env.HOME);
107
+ console.log(`[Editor] Starting code-server for ${project} on port ${port}`);
108
+ // Spawn code-server process with extended PATH for Homebrew
109
+ const env = {
110
+ ...process.env,
111
+ PATH: `/opt/homebrew/bin:/usr/local/bin:${process.env.PATH}`,
112
+ };
113
+ const codeServer = spawn('code-server', [
114
+ '--bind-addr', `127.0.0.1:${port}`,
115
+ '--auth', 'none',
116
+ '--disable-telemetry',
117
+ '--disable-update-check',
118
+ '--disable-proxy',
119
+ projectPath,
120
+ ], {
121
+ stdio: ['ignore', 'pipe', 'pipe'],
122
+ detached: false,
123
+ env,
124
+ });
125
+ const instance = {
126
+ project,
127
+ port,
128
+ process: codeServer,
129
+ startedAt: Date.now(),
130
+ lastActivity: Date.now(),
131
+ };
132
+ // Handle process events
133
+ codeServer.on('error', (err) => {
134
+ console.error(`[Editor] code-server error for ${project}:`, err);
135
+ cleanupInstance(project);
136
+ });
137
+ codeServer.on('exit', (code) => {
138
+ console.log(`[Editor] code-server for ${project} exited with code ${code}`);
139
+ cleanupInstance(project);
140
+ });
141
+ // Log output for debugging
142
+ codeServer.stdout?.on('data', (data) => {
143
+ const msg = data.toString().trim();
144
+ if (msg.includes('HTTP server listening')) {
145
+ console.log(`[Editor] code-server ready for ${project} at http://127.0.0.1:${port}`);
146
+ }
147
+ });
148
+ codeServer.stderr?.on('data', (data) => {
149
+ const msg = data.toString().trim();
150
+ // Filter out noisy messages
151
+ if (!msg.includes('libva error') && !msg.includes('GLIBCXX')) {
152
+ console.error(`[Editor] ${project}:`, msg);
153
+ }
154
+ });
155
+ editorInstances.set(project, instance);
156
+ // Wait for code-server to be ready (simple delay for now)
157
+ await new Promise(resolve => setTimeout(resolve, 2000));
158
+ return instance;
159
+ }
160
+ // Stop code-server for a project
161
+ export function stopEditor(project) {
162
+ const instance = editorInstances.get(project);
163
+ if (!instance) {
164
+ return false;
165
+ }
166
+ console.log(`[Editor] Stopping code-server for ${project}`);
167
+ instance.process.kill('SIGTERM');
168
+ cleanupInstance(project);
169
+ return true;
170
+ }
171
+ // Cleanup instance resources
172
+ function cleanupInstance(project) {
173
+ const instance = editorInstances.get(project);
174
+ if (instance) {
175
+ releasePort(instance.port);
176
+ editorInstances.delete(project);
177
+ }
178
+ }
179
+ // Get status of editor for a project
180
+ export function getEditorStatus(project) {
181
+ const instance = editorInstances.get(project);
182
+ return {
183
+ project,
184
+ running: !!instance,
185
+ port: instance?.port,
186
+ pid: instance?.process.pid,
187
+ startedAt: instance?.startedAt,
188
+ lastActivity: instance?.lastActivity,
189
+ };
190
+ }
191
+ // Get all running editors
192
+ export function getAllEditors() {
193
+ return Array.from(editorInstances.keys()).map(getEditorStatus);
194
+ }
195
+ // Update last activity timestamp (called when proxy forwards requests)
196
+ export function updateEditorActivity(project) {
197
+ const instance = editorInstances.get(project);
198
+ if (instance) {
199
+ instance.lastActivity = Date.now();
200
+ }
201
+ }
202
+ // Cleanup idle editors (called periodically)
203
+ function cleanupIdleEditors() {
204
+ const now = Date.now();
205
+ for (const [project, instance] of editorInstances) {
206
+ const idleTime = now - instance.lastActivity;
207
+ if (idleTime > editorConfig.idleTimeout) {
208
+ console.log(`[Editor] Stopping idle code-server for ${project} (idle ${Math.round(idleTime / 1000)}s)`);
209
+ stopEditor(project);
210
+ }
211
+ }
212
+ }
213
+ // Graceful shutdown - stop all editors
214
+ export function shutdownAllEditors() {
215
+ console.log(`[Editor] Shutting down ${editorInstances.size} code-server instances`);
216
+ for (const project of editorInstances.keys()) {
217
+ stopEditor(project);
218
+ }
219
+ }
220
+ //# sourceMappingURL=editor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor.js","sourceRoot":"","sources":["../src/editor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import type { Environment, EnvironmentMetadata, EnvironmentProvider, CreateEnvironmentRequest, UpdateEnvironmentRequest } from '@vibecompany/247-shared';
2
+ /**
3
+ * Load environments from disk
4
+ */
5
+ export declare function loadEnvironments(): void;
6
+ /**
7
+ * Get all environments (full data, agent-side only)
8
+ */
9
+ export declare function getAllEnvironments(): Environment[];
10
+ /**
11
+ * Get all environments as safe metadata (for dashboard)
12
+ */
13
+ export declare function getEnvironmentsMetadata(): EnvironmentMetadata[];
14
+ /**
15
+ * Get single environment by ID (full data)
16
+ */
17
+ export declare function getEnvironment(id: string): Environment | undefined;
18
+ /**
19
+ * Get single environment metadata
20
+ */
21
+ export declare function getEnvironmentMetadata(id: string): EnvironmentMetadata | undefined;
22
+ /**
23
+ * Get default environment
24
+ */
25
+ export declare function getDefaultEnvironment(): Environment | undefined;
26
+ /**
27
+ * Create new environment
28
+ */
29
+ export declare function createEnvironment(req: CreateEnvironmentRequest): Environment;
30
+ /**
31
+ * Update environment
32
+ */
33
+ export declare function updateEnvironment(id: string, req: UpdateEnvironmentRequest): Environment | null;
34
+ /**
35
+ * Delete environment
36
+ */
37
+ export declare function deleteEnvironment(id: string): boolean;
38
+ /**
39
+ * Get environment variables for terminal injection
40
+ * Returns the variables for the specified environment, or default if not found
41
+ */
42
+ export declare function getEnvironmentVariables(environmentId?: string): Record<string, string>;
43
+ /**
44
+ * Track which environment a session uses
45
+ */
46
+ export declare function setSessionEnvironment(sessionName: string, environmentId: string): void;
47
+ /**
48
+ * Get the environment ID for a session
49
+ */
50
+ export declare function getSessionEnvironment(sessionName: string): string | undefined;
51
+ /**
52
+ * Clear session environment tracking (when session is killed)
53
+ */
54
+ export declare function clearSessionEnvironment(sessionName: string): void;
55
+ /**
56
+ * Create environment from preset
57
+ */
58
+ export declare function createEnvironmentFromPreset(provider: EnvironmentProvider, name: string, customVariables?: Record<string, string>): Environment;
59
+ //# sourceMappingURL=environments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environments.d.ts","sourceRoot":"","sources":["../src/environments.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,yBAAyB,CAAC;AAejC;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CA8BvC;AA8BD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,WAAW,EAAE,CAElD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,mBAAmB,EAAE,CAE/D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAElE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAIlF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,WAAW,GAAG,SAAS,CAE/D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,wBAAwB,GAAG,WAAW,CA2B5E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,wBAAwB,GAAG,WAAW,GAAG,IAAI,CA4B/F;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAiBrD;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAatF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAEtF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE7E;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAEjE;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,mBAAmB,EAC7B,IAAI,EAAE,MAAM,EACZ,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACvC,WAAW,CAUb"}