@ebowwa/codespaces-types 1.1.0 → 1.2.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/{dist/compile → compile}/index.js +41 -15
- package/compile/index.ts +553 -0
- package/compile/resources.js +116 -0
- package/compile/resources.ts +157 -0
- package/compile/schemas/resources.js +127 -0
- package/compile/schemas/resources.ts +144 -0
- package/{dist/compile → compile}/terminal-websocket.js +4 -1
- package/compile/terminal-websocket.ts +133 -0
- package/compile/time.js +30 -0
- package/compile/time.ts +32 -0
- package/{dist/compile → compile}/user/distributions.js +0 -1
- package/{dist/compile/user/distributions.d.ts → compile/user/distributions.ts} +0 -1
- package/{dist/compile → compile}/validation.js +23 -17
- package/compile/validation.ts +98 -0
- package/index.js +21 -0
- package/index.ts +5 -0
- package/package.json +38 -45
- package/runtime/ai.js +505 -0
- package/runtime/ai.ts +501 -0
- package/runtime/api.js +677 -0
- package/runtime/api.ts +857 -0
- package/runtime/database.js +94 -0
- package/runtime/database.ts +107 -0
- package/runtime/env.js +63 -0
- package/runtime/env.ts +68 -0
- package/{dist/runtime → runtime}/glm.js +7 -4
- package/runtime/glm.ts +36 -0
- package/runtime/index.js +28 -0
- package/{dist/runtime/index.js → runtime/index.ts} +1 -0
- package/runtime/ssh.js +47 -0
- package/runtime/ssh.ts +58 -0
- package/README.md +0 -65
- package/dist/compile/index.d.ts +0 -437
- package/dist/compile/index.d.ts.map +0 -1
- package/dist/compile/resources.d.ts +0 -69
- package/dist/compile/resources.d.ts.map +0 -1
- package/dist/compile/resources.js +0 -113
- package/dist/compile/schemas/resources.d.ts +0 -166
- package/dist/compile/schemas/resources.d.ts.map +0 -1
- package/dist/compile/schemas/resources.js +0 -123
- package/dist/compile/terminal-websocket.d.ts +0 -109
- package/dist/compile/terminal-websocket.d.ts.map +0 -1
- package/dist/compile/time.d.ts +0 -7
- package/dist/compile/time.d.ts.map +0 -1
- package/dist/compile/time.js +0 -27
- package/dist/compile/user/distributions.d.ts.map +0 -1
- package/dist/compile/validation.d.ts +0 -44
- package/dist/compile/validation.d.ts.map +0 -1
- package/dist/runtime/ai.d.ts +0 -1336
- package/dist/runtime/ai.d.ts.map +0 -1
- package/dist/runtime/ai.js +0 -416
- package/dist/runtime/api.d.ts +0 -1304
- package/dist/runtime/api.d.ts.map +0 -1
- package/dist/runtime/api.js +0 -673
- package/dist/runtime/database.d.ts +0 -376
- package/dist/runtime/database.d.ts.map +0 -1
- package/dist/runtime/database.js +0 -91
- package/dist/runtime/env.d.ts +0 -121
- package/dist/runtime/env.d.ts.map +0 -1
- package/dist/runtime/env.js +0 -54
- package/dist/runtime/glm.d.ts +0 -17
- package/dist/runtime/glm.d.ts.map +0 -1
- package/dist/runtime/index.d.ts +0 -13
- package/dist/runtime/index.d.ts.map +0 -1
- package/dist/runtime/ssh.d.ts +0 -111
- package/dist/runtime/ssh.d.ts.map +0 -1
- package/dist/runtime/ssh.js +0 -44
|
@@ -1,6 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Shared type definitions for frontend and server
|
|
3
4
|
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
17
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.LoopStatus = exports.VolumeStatus = exports.ActionStatus = exports.EnvironmentStatus = void 0;
|
|
21
|
+
exports.getEnvLocation = getEnvLocation;
|
|
22
|
+
exports.getEnvRegionName = getEnvRegionName;
|
|
23
|
+
exports.getEnvLocationLabel = getEnvLocationLabel;
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// WebSocket Types (shared between terminal and frontend)
|
|
26
|
+
// ============================================================================
|
|
27
|
+
__exportStar(require("./terminal-websocket.js"), exports);
|
|
4
28
|
// ============================================================================
|
|
5
29
|
// Application Types
|
|
6
30
|
// ============================================================================
|
|
@@ -20,7 +44,7 @@
|
|
|
20
44
|
* - "stopping" → "deleting"
|
|
21
45
|
* - "initializing" → "creating"
|
|
22
46
|
*/
|
|
23
|
-
|
|
47
|
+
var EnvironmentStatus;
|
|
24
48
|
(function (EnvironmentStatus) {
|
|
25
49
|
EnvironmentStatus["Running"] = "running";
|
|
26
50
|
EnvironmentStatus["Stopped"] = "stopped";
|
|
@@ -30,41 +54,41 @@ export var EnvironmentStatus;
|
|
|
30
54
|
EnvironmentStatus["Starting"] = "starting";
|
|
31
55
|
EnvironmentStatus["Stopping"] = "stopping";
|
|
32
56
|
EnvironmentStatus["Initializing"] = "initializing";
|
|
33
|
-
})(EnvironmentStatus || (EnvironmentStatus = {}));
|
|
57
|
+
})(EnvironmentStatus || (exports.EnvironmentStatus = EnvironmentStatus = {}));
|
|
34
58
|
/**
|
|
35
59
|
* Action status - used by HetznerAction
|
|
36
60
|
*/
|
|
37
|
-
|
|
61
|
+
var ActionStatus;
|
|
38
62
|
(function (ActionStatus) {
|
|
39
63
|
ActionStatus["Running"] = "running";
|
|
40
64
|
ActionStatus["Success"] = "success";
|
|
41
65
|
ActionStatus["Error"] = "error";
|
|
42
|
-
})(ActionStatus || (ActionStatus = {}));
|
|
66
|
+
})(ActionStatus || (exports.ActionStatus = ActionStatus = {}));
|
|
43
67
|
/**
|
|
44
68
|
* Volume status - used by HetznerVolume
|
|
45
69
|
*/
|
|
46
|
-
|
|
70
|
+
var VolumeStatus;
|
|
47
71
|
(function (VolumeStatus) {
|
|
48
72
|
VolumeStatus["Creating"] = "creating";
|
|
49
73
|
VolumeStatus["Available"] = "available";
|
|
50
74
|
VolumeStatus["Deleting"] = "deleting";
|
|
51
|
-
})(VolumeStatus || (VolumeStatus = {}));
|
|
75
|
+
})(VolumeStatus || (exports.VolumeStatus = VolumeStatus = {}));
|
|
52
76
|
/**
|
|
53
77
|
* Ralph Loop status - used by RalphLoop interface
|
|
54
78
|
*/
|
|
55
|
-
|
|
79
|
+
var LoopStatus;
|
|
56
80
|
(function (LoopStatus) {
|
|
57
81
|
LoopStatus["Running"] = "running";
|
|
58
82
|
LoopStatus["Stopped"] = "stopped";
|
|
59
83
|
LoopStatus["Error"] = "error";
|
|
60
84
|
LoopStatus["Completed"] = "completed";
|
|
61
|
-
})(LoopStatus || (LoopStatus = {}));
|
|
85
|
+
})(LoopStatus || (exports.LoopStatus = LoopStatus = {}));
|
|
62
86
|
/**
|
|
63
87
|
* Get the location object from an environment
|
|
64
88
|
* @param env - The environment object
|
|
65
89
|
* @returns The location object or null
|
|
66
90
|
*/
|
|
67
|
-
|
|
91
|
+
function getEnvLocation(env) {
|
|
68
92
|
if (!env)
|
|
69
93
|
return null;
|
|
70
94
|
return env.location || null;
|
|
@@ -74,23 +98,25 @@ export function getEnvLocation(env) {
|
|
|
74
98
|
* @param env - The environment object
|
|
75
99
|
* @returns The region name (e.g., "nbg1") or "Unknown"
|
|
76
100
|
*/
|
|
77
|
-
|
|
101
|
+
function getEnvRegionName(env) {
|
|
102
|
+
var _a;
|
|
78
103
|
if (!env)
|
|
79
104
|
return "Unknown";
|
|
80
|
-
return env.location
|
|
105
|
+
return ((_a = env.location) === null || _a === void 0 ? void 0 : _a.name) || "Unknown";
|
|
81
106
|
}
|
|
82
107
|
/**
|
|
83
108
|
* Get a human-readable location label with city and country
|
|
84
109
|
* @param env - The environment object
|
|
85
110
|
* @returns A formatted location string (e.g., "Nuremberg, DE" or "nbg1" as fallback)
|
|
86
111
|
*/
|
|
87
|
-
|
|
112
|
+
function getEnvLocationLabel(env) {
|
|
113
|
+
var _a, _b, _c;
|
|
88
114
|
if (!env)
|
|
89
115
|
return "Unknown";
|
|
90
116
|
// Show city, country for better UX
|
|
91
|
-
if (env.location
|
|
92
|
-
return
|
|
117
|
+
if (((_a = env.location) === null || _a === void 0 ? void 0 : _a.city) && ((_b = env.location) === null || _b === void 0 ? void 0 : _b.country)) {
|
|
118
|
+
return "".concat(env.location.city, ", ").concat(env.location.country);
|
|
93
119
|
}
|
|
94
120
|
// Fallback to location name
|
|
95
|
-
return env.location
|
|
121
|
+
return ((_c = env.location) === null || _c === void 0 ? void 0 : _c.name) || "Unknown";
|
|
96
122
|
}
|
package/compile/index.ts
ADDED
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared type definitions for frontend and server
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// WebSocket Types (shared between terminal and frontend)
|
|
7
|
+
// ============================================================================
|
|
8
|
+
|
|
9
|
+
export * from "./terminal-websocket.js";
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Hetzner API Types (shared between frontend and backend)
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Hetzner server type with pricing information
|
|
17
|
+
*/
|
|
18
|
+
export interface HetznerServerType {
|
|
19
|
+
id: number;
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
cores: number;
|
|
23
|
+
memory: number;
|
|
24
|
+
disk: number;
|
|
25
|
+
deprecated?: boolean;
|
|
26
|
+
prices: Array<{
|
|
27
|
+
location: string | null | undefined;
|
|
28
|
+
price_hourly: {
|
|
29
|
+
net: string;
|
|
30
|
+
gross: string;
|
|
31
|
+
};
|
|
32
|
+
price_monthly: {
|
|
33
|
+
net: string;
|
|
34
|
+
gross: string;
|
|
35
|
+
};
|
|
36
|
+
}>;
|
|
37
|
+
storage_type: "local" | "network";
|
|
38
|
+
cpu_type: "shared" | "dedicated";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Hetzner location/datacenter
|
|
43
|
+
*/
|
|
44
|
+
export interface HetznerLocation {
|
|
45
|
+
id: number;
|
|
46
|
+
name: string;
|
|
47
|
+
description: string;
|
|
48
|
+
country: string;
|
|
49
|
+
city: string;
|
|
50
|
+
latitude: number;
|
|
51
|
+
longitude: number;
|
|
52
|
+
network_zone: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Hetzner datacenter (specific facility within a location)
|
|
57
|
+
* Previously backend-only, now shared for full object graph preservation
|
|
58
|
+
*/
|
|
59
|
+
export interface HetznerDatacenter {
|
|
60
|
+
id: number;
|
|
61
|
+
name: string;
|
|
62
|
+
description: string;
|
|
63
|
+
location: HetznerLocation;
|
|
64
|
+
supported_server_types?: Array<{
|
|
65
|
+
id: number;
|
|
66
|
+
name: string;
|
|
67
|
+
}> | null;
|
|
68
|
+
available_server_types?: Array<{
|
|
69
|
+
id: number;
|
|
70
|
+
name: string;
|
|
71
|
+
}>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ============================================================================
|
|
75
|
+
// Application Types
|
|
76
|
+
// ============================================================================
|
|
77
|
+
|
|
78
|
+
// ============================================================================
|
|
79
|
+
// Shared Status Enums
|
|
80
|
+
// ============================================================================
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Environment status - used by Environment interface and HetznerServer mapping
|
|
84
|
+
*
|
|
85
|
+
* Hetzner API returns: "running" | "stopped" | "starting" | "stopping" | "initializing"
|
|
86
|
+
* Environment uses subset: "running" | "stopped" | "creating" | "deleting"
|
|
87
|
+
*
|
|
88
|
+
* Mapping:
|
|
89
|
+
* - "running" → "running"
|
|
90
|
+
* - "stopped" → "stopped"
|
|
91
|
+
* - "starting" → "creating"
|
|
92
|
+
* - "stopping" → "deleting"
|
|
93
|
+
* - "initializing" → "creating"
|
|
94
|
+
*/
|
|
95
|
+
export enum EnvironmentStatus {
|
|
96
|
+
Running = "running",
|
|
97
|
+
Stopped = "stopped",
|
|
98
|
+
Creating = "creating",
|
|
99
|
+
Deleting = "deleting",
|
|
100
|
+
// Additional Hetzner server statuses (for API compatibility)
|
|
101
|
+
Starting = "starting",
|
|
102
|
+
Stopping = "stopping",
|
|
103
|
+
Initializing = "initializing",
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Action status - used by HetznerAction
|
|
108
|
+
*/
|
|
109
|
+
export enum ActionStatus {
|
|
110
|
+
Running = "running",
|
|
111
|
+
Success = "success",
|
|
112
|
+
Error = "error",
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Volume status - used by HetznerVolume
|
|
117
|
+
*/
|
|
118
|
+
export enum VolumeStatus {
|
|
119
|
+
Creating = "creating",
|
|
120
|
+
Available = "available",
|
|
121
|
+
Deleting = "deleting",
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Ralph Loop status - used by RalphLoop interface
|
|
126
|
+
*/
|
|
127
|
+
export enum LoopStatus {
|
|
128
|
+
Running = "running",
|
|
129
|
+
Stopped = "stopped",
|
|
130
|
+
Error = "error",
|
|
131
|
+
Completed = "completed",
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Active port on a server
|
|
136
|
+
*/
|
|
137
|
+
export interface ActivePort {
|
|
138
|
+
port: number;
|
|
139
|
+
protocol: "tcp" | "udp";
|
|
140
|
+
service?: string;
|
|
141
|
+
state: "open" | "closed" | "filtered";
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// ============================================================================
|
|
145
|
+
// Base Permissions (shared between Environment and EnvironmentMetadata)
|
|
146
|
+
// ============================================================================
|
|
147
|
+
|
|
148
|
+
// TODO:
|
|
149
|
+
// https://tailscale.com/kb/1015/100.x-addresses
|
|
150
|
+
// - type for every tailnet device has local access to a private service IP address called Quad100 (100.100.100.100)
|
|
151
|
+
// - `Tailscale automatically assigns a unique IP address to each device in your Tailscale network`
|
|
152
|
+
/**
|
|
153
|
+
* Base permissions structure shared by Environment and EnvironmentMetadata
|
|
154
|
+
*/
|
|
155
|
+
export interface BasePermissions {
|
|
156
|
+
// Seed/clone configuration
|
|
157
|
+
seedConfig?: {
|
|
158
|
+
sourceEnvironmentId?: string;
|
|
159
|
+
dependencySnapshot?: string;
|
|
160
|
+
setupScript?: string;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// Authentication providers
|
|
164
|
+
logins?: {
|
|
165
|
+
github?: {
|
|
166
|
+
enabled: boolean;
|
|
167
|
+
username?: string;
|
|
168
|
+
tokenScopes?: string[];
|
|
169
|
+
};
|
|
170
|
+
doppler?: {
|
|
171
|
+
enabled: boolean;
|
|
172
|
+
project?: string;
|
|
173
|
+
config?: string;
|
|
174
|
+
};
|
|
175
|
+
tailscale?: {
|
|
176
|
+
enabled: boolean;
|
|
177
|
+
authKey?: string;
|
|
178
|
+
hostname?: string;
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
// VPN configurations
|
|
183
|
+
vpns?: Array<{
|
|
184
|
+
name: string;
|
|
185
|
+
type: "wireguard" | "openvpn" | "tailscale";
|
|
186
|
+
config: string;
|
|
187
|
+
connected: boolean;
|
|
188
|
+
}>;
|
|
189
|
+
|
|
190
|
+
// Generic plugin configuration
|
|
191
|
+
plugins?: Record<string, ClaudeCodePlugin>;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ============================================================================
|
|
195
|
+
// Environment Base (shared fields between Environment and EnvironmentMetadata)
|
|
196
|
+
// ============================================================================
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Base fields shared by Environment and EnvironmentMetadata
|
|
200
|
+
*/
|
|
201
|
+
export interface EnvironmentBase {
|
|
202
|
+
id: string;
|
|
203
|
+
description?: string;
|
|
204
|
+
project?: string;
|
|
205
|
+
owner?: string;
|
|
206
|
+
purpose?: string;
|
|
207
|
+
environmentType?: "development" | "staging" | "production" | "testing";
|
|
208
|
+
hoursActive?: number;
|
|
209
|
+
lastActive?: string;
|
|
210
|
+
activePorts?: ActivePort[];
|
|
211
|
+
/** Cloud-init bootstrap status */
|
|
212
|
+
bootstrapStatus?: "bootstrapping" | "ready" | "failed";
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// TODO: https://code.claude.com/docs/en/common-workflows
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Claude Code hook event types
|
|
219
|
+
*/
|
|
220
|
+
export type HookEventType =
|
|
221
|
+
| "SessionStart"
|
|
222
|
+
| "UserPromptSubmit"
|
|
223
|
+
| "PreToolUse"
|
|
224
|
+
| "PostToolUse"
|
|
225
|
+
| "PreCommand"
|
|
226
|
+
| "PostCommand"
|
|
227
|
+
| "Stop"
|
|
228
|
+
| "Error"
|
|
229
|
+
| "FileChange";
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Claude Code hook configuration
|
|
233
|
+
*/
|
|
234
|
+
export interface ClaudeCodeHook {
|
|
235
|
+
event: HookEventType;
|
|
236
|
+
description?: string;
|
|
237
|
+
command?: string;
|
|
238
|
+
output?: {
|
|
239
|
+
allow?: boolean;
|
|
240
|
+
context?: string;
|
|
241
|
+
modifyInput?: string;
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Claude Code agent configuration
|
|
247
|
+
*/
|
|
248
|
+
export interface ClaudeCodeAgent {
|
|
249
|
+
name: string;
|
|
250
|
+
description?: string;
|
|
251
|
+
instructions?: string;
|
|
252
|
+
model?: string;
|
|
253
|
+
temperature?: number;
|
|
254
|
+
maxTokens?: number;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Claude Code command configuration
|
|
259
|
+
*/
|
|
260
|
+
export interface ClaudeCodeCommand {
|
|
261
|
+
name: string;
|
|
262
|
+
description?: string;
|
|
263
|
+
instructions?: string;
|
|
264
|
+
agent?: string;
|
|
265
|
+
shouldConfirm?: boolean;
|
|
266
|
+
parameters?: Record<
|
|
267
|
+
string,
|
|
268
|
+
{
|
|
269
|
+
type: "string" | "boolean" | "number" | "array";
|
|
270
|
+
description?: string;
|
|
271
|
+
required?: boolean;
|
|
272
|
+
default?: unknown;
|
|
273
|
+
}
|
|
274
|
+
>;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Claude Code skill configuration
|
|
279
|
+
*/
|
|
280
|
+
export interface ClaudeCodeSkill {
|
|
281
|
+
name: string;
|
|
282
|
+
description?: string;
|
|
283
|
+
instructions?: string;
|
|
284
|
+
trigger?: {
|
|
285
|
+
patterns?: string[];
|
|
286
|
+
fileTypes?: string[];
|
|
287
|
+
always?: boolean;
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* MCP (Model Context Protocol) Server Configuration
|
|
293
|
+
*
|
|
294
|
+
* === LAYER 2: CLI Wrapper Plugin System ===
|
|
295
|
+
*
|
|
296
|
+
* MCP is NOT part of the OpenAI protocol (Layer 1).
|
|
297
|
+
* It's a separate plugin system for exposing tools/resources to AI models.
|
|
298
|
+
*
|
|
299
|
+
* These types are defined but NOT yet implemented in cheapspaces.
|
|
300
|
+
*
|
|
301
|
+
* Reference Implementation: tools/continue/core/context/mcp/
|
|
302
|
+
*
|
|
303
|
+
* Potential MCP Tools for Cheapspaces:
|
|
304
|
+
* - hetzner_create: Create new server (wrap HetznerClient.createServer())
|
|
305
|
+
* - hetzner_delete: Delete server (wrap HetznerClient.deleteServer())
|
|
306
|
+
* - hetzner_power: Power on/off (wrap powerOn/powerOff)
|
|
307
|
+
* - ssh_exec: Execute remote command (wrap execSSH())
|
|
308
|
+
* - ssh_upload: Upload file via SCP (wrap scpUpload())
|
|
309
|
+
* - ssh_download: Download file via SCP (wrap scpDownload())
|
|
310
|
+
* - resources_get: Get resource usage (wrap getResources())
|
|
311
|
+
*
|
|
312
|
+
* To implement (Layer 2 only):
|
|
313
|
+
* 1. Create MCPManagerSingleton (see continue's pattern)
|
|
314
|
+
* 2. Create MCPConnection wrapper for stdio/HTTP servers
|
|
315
|
+
* 3. Expose Hetzner/SSH operations as MCP tools
|
|
316
|
+
* 4. Integrate with AI chat for tool calling
|
|
317
|
+
*/
|
|
318
|
+
export interface MCPServerConfig {
|
|
319
|
+
name: string;
|
|
320
|
+
command: string; // For stdio-based servers
|
|
321
|
+
args?: string[];
|
|
322
|
+
env?: Record<string, string>;
|
|
323
|
+
cwd?: string;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Claude Code plugin configuration
|
|
328
|
+
*/
|
|
329
|
+
export interface ClaudeCodePlugin {
|
|
330
|
+
enabled: boolean;
|
|
331
|
+
name?: string;
|
|
332
|
+
description?: string;
|
|
333
|
+
version?: string;
|
|
334
|
+
author?: string;
|
|
335
|
+
commands?: ClaudeCodeCommand[];
|
|
336
|
+
agents?: ClaudeCodeAgent[];
|
|
337
|
+
skills?: ClaudeCodeSkill[];
|
|
338
|
+
hooks?: ClaudeCodeHook[];
|
|
339
|
+
mcpServers?: MCPServerConfig[];
|
|
340
|
+
config?: Record<string, unknown>;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Server image information
|
|
345
|
+
*/
|
|
346
|
+
export interface ServerImage {
|
|
347
|
+
id: number;
|
|
348
|
+
name: string;
|
|
349
|
+
description: string;
|
|
350
|
+
type: "snapshot" | "backup" | "system";
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Environment data - shared between frontend and server
|
|
355
|
+
*/
|
|
356
|
+
export interface Environment extends EnvironmentBase {
|
|
357
|
+
// Core identification (id, description from base)
|
|
358
|
+
name: string;
|
|
359
|
+
status:
|
|
360
|
+
| EnvironmentStatus.Running
|
|
361
|
+
| EnvironmentStatus.Stopped
|
|
362
|
+
| EnvironmentStatus.Creating
|
|
363
|
+
| EnvironmentStatus.Deleting;
|
|
364
|
+
|
|
365
|
+
// Action progress (0-100) for long-running operations
|
|
366
|
+
progress?: number;
|
|
367
|
+
|
|
368
|
+
// Server configuration
|
|
369
|
+
serverId: number;
|
|
370
|
+
serverType: string;
|
|
371
|
+
image: ServerImage;
|
|
372
|
+
location?: HetznerLocation;
|
|
373
|
+
datacenter?: HetznerDatacenter;
|
|
374
|
+
|
|
375
|
+
// Network addresses
|
|
376
|
+
ipv4: string | null;
|
|
377
|
+
ipv6: string | null;
|
|
378
|
+
|
|
379
|
+
// Metadata
|
|
380
|
+
createdAt: string;
|
|
381
|
+
lastUsed: string | null;
|
|
382
|
+
tags: string[];
|
|
383
|
+
|
|
384
|
+
// Resource usage metrics
|
|
385
|
+
resources?: {
|
|
386
|
+
cpuPercent: number;
|
|
387
|
+
memoryPercent: number;
|
|
388
|
+
memoryUsed: string;
|
|
389
|
+
memoryTotal: string;
|
|
390
|
+
diskPercent: number;
|
|
391
|
+
diskUsed: string;
|
|
392
|
+
diskTotal: string;
|
|
393
|
+
gpuPercent?: number;
|
|
394
|
+
gpuMemoryUsed?: string;
|
|
395
|
+
gpuMemoryTotal?: string;
|
|
396
|
+
lastUpdated?: string;
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
// Permissions and integrations
|
|
400
|
+
nodeAgent?: NodeAgentInfo;
|
|
401
|
+
|
|
402
|
+
permissions?: BasePermissions & {
|
|
403
|
+
// Available skills (Environment-specific)
|
|
404
|
+
skills?: Array<{
|
|
405
|
+
name: string;
|
|
406
|
+
enabled: boolean;
|
|
407
|
+
config?: Record<string, unknown>;
|
|
408
|
+
}>;
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Get the location object from an environment
|
|
414
|
+
* @param env - The environment object
|
|
415
|
+
* @returns The location object or null
|
|
416
|
+
*/
|
|
417
|
+
export function getEnvLocation(
|
|
418
|
+
env: Environment | undefined | null,
|
|
419
|
+
): HetznerLocation | null {
|
|
420
|
+
if (!env) return null;
|
|
421
|
+
return env.location || null;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Get the region name (short format like "nbg1") from an environment
|
|
426
|
+
* @param env - The environment object
|
|
427
|
+
* @returns The region name (e.g., "nbg1") or "Unknown"
|
|
428
|
+
*/
|
|
429
|
+
export function getEnvRegionName(env: Environment | undefined | null): string {
|
|
430
|
+
if (!env) return "Unknown";
|
|
431
|
+
return env.location?.name || "Unknown";
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Get a human-readable location label with city and country
|
|
436
|
+
* @param env - The environment object
|
|
437
|
+
* @returns A formatted location string (e.g., "Nuremberg, DE" or "nbg1" as fallback)
|
|
438
|
+
*/
|
|
439
|
+
export function getEnvLocationLabel(
|
|
440
|
+
env: Environment | undefined | null,
|
|
441
|
+
): string {
|
|
442
|
+
if (!env) return "Unknown";
|
|
443
|
+
// Show city, country for better UX
|
|
444
|
+
if (env.location?.city && env.location?.country) {
|
|
445
|
+
return `${env.location.city}, ${env.location.country}`;
|
|
446
|
+
}
|
|
447
|
+
// Fallback to location name
|
|
448
|
+
return env.location?.name || "Unknown";
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Environment metadata for storage
|
|
453
|
+
* Extends EnvironmentBase with storage-specific fields
|
|
454
|
+
*/
|
|
455
|
+
export interface EnvironmentMetadata extends EnvironmentBase {
|
|
456
|
+
sshKeyPath?: string;
|
|
457
|
+
permissions?: BasePermissions;
|
|
458
|
+
updatedAt?: string;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Node Agent - Ralph Loop orchestration service running on each VPS
|
|
463
|
+
*/
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Git worktree information
|
|
467
|
+
*/
|
|
468
|
+
export interface Worktree {
|
|
469
|
+
id: string;
|
|
470
|
+
branch: string;
|
|
471
|
+
commit: string;
|
|
472
|
+
path: string;
|
|
473
|
+
created?: string;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Ralph Loop status and progress
|
|
478
|
+
*/
|
|
479
|
+
export interface RalphLoop {
|
|
480
|
+
id: string;
|
|
481
|
+
worktree_id: string;
|
|
482
|
+
iteration: number;
|
|
483
|
+
max_iterations: number;
|
|
484
|
+
status: LoopStatus;
|
|
485
|
+
started_at: string;
|
|
486
|
+
last_activity?: string;
|
|
487
|
+
recent_commits?: Array<{ hash: string; message: string }>;
|
|
488
|
+
prompt?: string;
|
|
489
|
+
completion_promise?: string | null;
|
|
490
|
+
project_path?: string; // Relative path like ~/seed or ~/seed/worktrees/feature-x
|
|
491
|
+
git_info?: {
|
|
492
|
+
remote: string | null; // e.g., "ebowwa/seed" or null
|
|
493
|
+
branch: string | null; // e.g., "Bun-port" or null
|
|
494
|
+
};
|
|
495
|
+
// Ralph Iterative specific fields
|
|
496
|
+
phase?: "planning" | "executing" | "review" | "complete";
|
|
497
|
+
current_task?: string | null;
|
|
498
|
+
total_subtasks?: number;
|
|
499
|
+
completed_subtasks?: number;
|
|
500
|
+
subtasks?: Array<{
|
|
501
|
+
id: string;
|
|
502
|
+
title: string;
|
|
503
|
+
status: "pending" | "in_progress" | "completed";
|
|
504
|
+
}>;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Node Agent capacity metrics (system resources)
|
|
509
|
+
*/
|
|
510
|
+
export interface NodeCapacity {
|
|
511
|
+
cpu_percent: number;
|
|
512
|
+
memory_percent: number;
|
|
513
|
+
disk_percent: number;
|
|
514
|
+
claude_cpu_total?: number; // Total CPU % used by all Claude processes
|
|
515
|
+
claude_process_count?: number; // Number of active Claude processes
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Active Claude Code process info
|
|
520
|
+
*/
|
|
521
|
+
export interface ClaudeCodeProcess {
|
|
522
|
+
pid: number;
|
|
523
|
+
worktreeId?: string;
|
|
524
|
+
loopId?: string;
|
|
525
|
+
startTime: string; // ISO date string
|
|
526
|
+
command: string;
|
|
527
|
+
cpuPercent: number;
|
|
528
|
+
memoryPercent: number;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* Node Agent status response
|
|
533
|
+
*/
|
|
534
|
+
export interface NodeAgentStatus {
|
|
535
|
+
node_id: string;
|
|
536
|
+
hostname: string;
|
|
537
|
+
tailscale_ip: string;
|
|
538
|
+
capacity: NodeCapacity;
|
|
539
|
+
worktrees: Worktree[];
|
|
540
|
+
ralph_loops: RalphLoop[];
|
|
541
|
+
active_claude_processes?: ClaudeCodeProcess[];
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Node Agent connection info for UI display
|
|
546
|
+
*/
|
|
547
|
+
export interface NodeAgentInfo {
|
|
548
|
+
running: boolean;
|
|
549
|
+
port?: number;
|
|
550
|
+
status?: NodeAgentStatus;
|
|
551
|
+
lastChecked?: string;
|
|
552
|
+
error?: string;
|
|
553
|
+
}
|