@enactprotocol/shared 1.0.12
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/LocalToolResolver.d.ts +84 -0
- package/dist/LocalToolResolver.js +353 -0
- package/dist/api/enact-api.d.ts +124 -0
- package/dist/api/enact-api.js +406 -0
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.js +2 -0
- package/dist/api/types.d.ts +83 -0
- package/dist/api/types.js +1 -0
- package/dist/core/DaggerExecutionProvider.d.ts +169 -0
- package/dist/core/DaggerExecutionProvider.js +996 -0
- package/dist/core/DirectExecutionProvider.d.ts +23 -0
- package/dist/core/DirectExecutionProvider.js +406 -0
- package/dist/core/EnactCore.d.ts +138 -0
- package/dist/core/EnactCore.js +609 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +3 -0
- package/dist/exec/index.d.ts +3 -0
- package/dist/exec/index.js +3 -0
- package/dist/exec/logger.d.ts +11 -0
- package/dist/exec/logger.js +57 -0
- package/dist/exec/validate.d.ts +5 -0
- package/dist/exec/validate.js +167 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +29 -0
- package/dist/lib/enact-direct.d.ts +156 -0
- package/dist/lib/enact-direct.js +158 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +1 -0
- package/dist/security/index.d.ts +3 -0
- package/dist/security/index.js +3 -0
- package/dist/security/security.d.ts +23 -0
- package/dist/security/security.js +137 -0
- package/dist/security/sign.d.ts +103 -0
- package/dist/security/sign.js +532 -0
- package/dist/security/verification-enforcer.d.ts +41 -0
- package/dist/security/verification-enforcer.js +181 -0
- package/dist/services/McpCoreService.d.ts +102 -0
- package/dist/services/McpCoreService.js +120 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/types.d.ts +130 -0
- package/dist/types.js +3 -0
- package/dist/utils/config.d.ts +32 -0
- package/dist/utils/config.js +78 -0
- package/dist/utils/env-loader.d.ts +54 -0
- package/dist/utils/env-loader.js +270 -0
- package/dist/utils/help.d.ts +36 -0
- package/dist/utils/help.js +248 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.js +7 -0
- package/dist/utils/logger.d.ts +35 -0
- package/dist/utils/logger.js +75 -0
- package/dist/utils/silent-monitor.d.ts +67 -0
- package/dist/utils/silent-monitor.js +242 -0
- package/dist/utils/timeout.d.ts +5 -0
- package/dist/utils/timeout.js +23 -0
- package/dist/utils/version.d.ts +4 -0
- package/dist/utils/version.js +14 -0
- package/dist/web/env-manager-server.d.ts +29 -0
- package/dist/web/env-manager-server.js +367 -0
- package/dist/web/index.d.ts +1 -0
- package/dist/web/index.js +1 -0
- package/package.json +79 -0
- package/src/LocalToolResolver.ts +424 -0
- package/src/api/enact-api.ts +569 -0
- package/src/api/index.ts +2 -0
- package/src/api/types.ts +93 -0
- package/src/core/DaggerExecutionProvider.ts +1308 -0
- package/src/core/DirectExecutionProvider.ts +484 -0
- package/src/core/EnactCore.ts +833 -0
- package/src/core/index.ts +3 -0
- package/src/exec/index.ts +3 -0
- package/src/exec/logger.ts +63 -0
- package/src/exec/validate.ts +238 -0
- package/src/index.ts +42 -0
- package/src/lib/enact-direct.ts +258 -0
- package/src/lib/index.ts +1 -0
- package/src/security/index.ts +3 -0
- package/src/security/security.ts +188 -0
- package/src/security/sign.ts +797 -0
- package/src/security/verification-enforcer.ts +268 -0
- package/src/services/McpCoreService.ts +203 -0
- package/src/services/index.ts +1 -0
- package/src/types.ts +190 -0
- package/src/utils/config.ts +97 -0
- package/src/utils/env-loader.ts +370 -0
- package/src/utils/help.ts +257 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/logger.ts +83 -0
- package/src/utils/silent-monitor.ts +328 -0
- package/src/utils/timeout.ts +26 -0
- package/src/utils/version.ts +16 -0
- package/src/web/env-manager-server.ts +465 -0
- package/src/web/index.ts +1 -0
- package/src/web/static/app.js +663 -0
- package/src/web/static/index.html +117 -0
- package/src/web/static/style.css +291 -0
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
export class EnactApiClient {
|
|
2
|
+
constructor(baseUrl = "https://enact.tools", supabaseUrl = "https://xjnhhxwxovjifdxdwzih.supabase.co") {
|
|
3
|
+
this.baseUrl = baseUrl.replace(/\/$/, ""); // Remove trailing slash
|
|
4
|
+
this.supabaseUrl = supabaseUrl.replace(/\/$/, "");
|
|
5
|
+
}
|
|
6
|
+
// Helper method to make authenticated requests
|
|
7
|
+
async makeRequest(endpoint, options = {}, token, tokenType = "jwt") {
|
|
8
|
+
const url = endpoint.startsWith("http")
|
|
9
|
+
? endpoint
|
|
10
|
+
: `${this.supabaseUrl}${endpoint}`;
|
|
11
|
+
const headers = {
|
|
12
|
+
"Content-Type": "application/json",
|
|
13
|
+
...options.headers,
|
|
14
|
+
};
|
|
15
|
+
// Add authentication headers if token provided
|
|
16
|
+
if (token) {
|
|
17
|
+
if (tokenType === "jwt") {
|
|
18
|
+
headers.Authorization = `Bearer ${token}`;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
headers["X-API-Key"] = token;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const response = await fetch(url, {
|
|
25
|
+
...options,
|
|
26
|
+
headers,
|
|
27
|
+
});
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
const errorData = await response
|
|
30
|
+
.json()
|
|
31
|
+
.catch(() => ({ error: "Unknown error" }));
|
|
32
|
+
throw new EnactApiError(`${errorData.error || response.statusText}`, response.status, endpoint);
|
|
33
|
+
}
|
|
34
|
+
const responseData = await response.json();
|
|
35
|
+
// Debug logging to help identify response structure issues
|
|
36
|
+
if (process.env.NODE_ENV === "development" || process.env.DEBUG) {
|
|
37
|
+
console.error(`API Response for ${endpoint}:`, responseData);
|
|
38
|
+
}
|
|
39
|
+
return responseData;
|
|
40
|
+
}
|
|
41
|
+
// =================
|
|
42
|
+
// PUBLIC ENDPOINTS
|
|
43
|
+
// =================
|
|
44
|
+
/**
|
|
45
|
+
* Get all tools (public, no auth required)
|
|
46
|
+
*/
|
|
47
|
+
async getTools(params) {
|
|
48
|
+
const searchParams = new URLSearchParams();
|
|
49
|
+
if (params?.limit)
|
|
50
|
+
searchParams.set("limit", params.limit.toString());
|
|
51
|
+
if (params?.offset)
|
|
52
|
+
searchParams.set("offset", params.offset.toString());
|
|
53
|
+
if (params?.tags)
|
|
54
|
+
searchParams.set("tags", params.tags.join(","));
|
|
55
|
+
if (params?.author)
|
|
56
|
+
searchParams.set("author", params.author);
|
|
57
|
+
const query = searchParams.toString();
|
|
58
|
+
const endpoint = `/functions/v1/tools${query ? `?${query}` : ""}`;
|
|
59
|
+
const response = await this.makeRequest(endpoint);
|
|
60
|
+
// Handle different response structures
|
|
61
|
+
if (Array.isArray(response)) {
|
|
62
|
+
return response;
|
|
63
|
+
}
|
|
64
|
+
else if (response.data && Array.isArray(response.data)) {
|
|
65
|
+
return response.data;
|
|
66
|
+
}
|
|
67
|
+
else if (response.tools && Array.isArray(response.tools)) {
|
|
68
|
+
return response.tools;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
console.warn("Unexpected response structure for getTools:", response);
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get specific tool details (public, no auth required)
|
|
77
|
+
*/
|
|
78
|
+
async getTool(name) {
|
|
79
|
+
const endpoint = `/functions/v1/tools/${encodeURIComponent(name)}`;
|
|
80
|
+
return this.makeRequest(endpoint);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get tool usage statistics (public, no auth required)
|
|
84
|
+
*/
|
|
85
|
+
async getToolUsage(name) {
|
|
86
|
+
const endpoint = `/functions/v1/tools/${encodeURIComponent(name)}/usage`;
|
|
87
|
+
return this.makeRequest(endpoint);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Log tool usage (public, no auth required)
|
|
91
|
+
*/
|
|
92
|
+
async logToolUsage(name, usage) {
|
|
93
|
+
const endpoint = `/functions/v1/tools/${encodeURIComponent(name)}/usage`;
|
|
94
|
+
return this.makeRequest(endpoint, {
|
|
95
|
+
method: "POST",
|
|
96
|
+
body: JSON.stringify(usage),
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Search tools with semantic/text search (public, no auth required)
|
|
101
|
+
*/
|
|
102
|
+
async searchTools(query) {
|
|
103
|
+
const endpoint = "/functions/v1/tools-search";
|
|
104
|
+
try {
|
|
105
|
+
// Log the request for debugging
|
|
106
|
+
if (process.env.NODE_ENV === "development" || process.env.DEBUG) {
|
|
107
|
+
console.error(`Search request to ${endpoint}:`, JSON.stringify(query, null, 2));
|
|
108
|
+
}
|
|
109
|
+
const response = await this.makeRequest(endpoint, {
|
|
110
|
+
method: "POST",
|
|
111
|
+
body: JSON.stringify(query),
|
|
112
|
+
});
|
|
113
|
+
// Handle different response structures
|
|
114
|
+
if (Array.isArray(response)) {
|
|
115
|
+
return response;
|
|
116
|
+
}
|
|
117
|
+
else if (response.data && Array.isArray(response.data)) {
|
|
118
|
+
return response.data;
|
|
119
|
+
}
|
|
120
|
+
else if (response.results && Array.isArray(response.results)) {
|
|
121
|
+
return response.results;
|
|
122
|
+
}
|
|
123
|
+
else if (response.tools && Array.isArray(response.tools)) {
|
|
124
|
+
return response.tools;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
console.warn("Unexpected response structure for searchTools:", response);
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
// Enhanced error logging
|
|
133
|
+
if (error instanceof EnactApiError) {
|
|
134
|
+
console.error(`Search API error (${error.statusCode}): ${error.message}`);
|
|
135
|
+
console.error(`Endpoint: ${error.endpoint}`);
|
|
136
|
+
// If it's a 502 error, provide more specific guidance
|
|
137
|
+
if (error.statusCode === 502) {
|
|
138
|
+
console.error("502 Bad Gateway error - this usually indicates:");
|
|
139
|
+
console.error("• The API server is temporarily unavailable");
|
|
140
|
+
console.error("• The search service is overloaded");
|
|
141
|
+
console.error("• Network connectivity issues");
|
|
142
|
+
console.error("• Try again in a few moments");
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
console.error("Unexpected search error:", error);
|
|
147
|
+
}
|
|
148
|
+
// Re-throw the error
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// ===================
|
|
153
|
+
// AUTHENTICATED ENDPOINTS
|
|
154
|
+
// ===================
|
|
155
|
+
/**
|
|
156
|
+
* Publish/create new tool (requires authentication)
|
|
157
|
+
*/
|
|
158
|
+
async publishTool(tool, token, tokenType = "cli") {
|
|
159
|
+
const endpoint = "/functions/v1/tools";
|
|
160
|
+
return this.makeRequest(endpoint, {
|
|
161
|
+
method: "POST",
|
|
162
|
+
body: JSON.stringify(tool),
|
|
163
|
+
}, token, tokenType);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Update existing tool (requires authentication, must be owner)
|
|
167
|
+
*/
|
|
168
|
+
async updateTool(name, tool, token, tokenType = "cli") {
|
|
169
|
+
const endpoint = `/functions/v1/tools/${encodeURIComponent(name)}`;
|
|
170
|
+
return this.makeRequest(endpoint, {
|
|
171
|
+
method: "PUT",
|
|
172
|
+
body: JSON.stringify(tool),
|
|
173
|
+
}, token, tokenType);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Delete tool (requires authentication, must be owner)
|
|
177
|
+
*/
|
|
178
|
+
async deleteTool(name, token, tokenType = "cli") {
|
|
179
|
+
const endpoint = `/functions/v1/tools/${encodeURIComponent(name)}`;
|
|
180
|
+
return this.makeRequest(endpoint, {
|
|
181
|
+
method: "DELETE",
|
|
182
|
+
}, token, tokenType);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Create new CLI token (requires JWT authentication)
|
|
186
|
+
*/
|
|
187
|
+
async createCLIToken(tokenData, jwtToken) {
|
|
188
|
+
const endpoint = "/functions/v1/cli-token";
|
|
189
|
+
return this.makeRequest(endpoint, {
|
|
190
|
+
method: "POST",
|
|
191
|
+
body: JSON.stringify(tokenData),
|
|
192
|
+
}, jwtToken, "jwt");
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* List user's CLI tokens (requires JWT authentication)
|
|
196
|
+
*/
|
|
197
|
+
async getCLITokens(jwtToken) {
|
|
198
|
+
const endpoint = "/functions/v1/cli-token";
|
|
199
|
+
return this.makeRequest(endpoint, {
|
|
200
|
+
method: "GET",
|
|
201
|
+
}, jwtToken, "jwt");
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Delete CLI token (requires JWT authentication, must be owner)
|
|
205
|
+
*/
|
|
206
|
+
async deleteCLIToken(tokenId, jwtToken) {
|
|
207
|
+
const endpoint = `/functions/v1/cli-token/${tokenId}`;
|
|
208
|
+
return this.makeRequest(endpoint, {
|
|
209
|
+
method: "DELETE",
|
|
210
|
+
}, jwtToken, "jwt");
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Exchange OAuth authorization code for access token
|
|
214
|
+
*/
|
|
215
|
+
async exchangeOAuthCode(oauthData) {
|
|
216
|
+
const endpoint = "/functions/v1/cli-oauth";
|
|
217
|
+
return this.makeRequest(endpoint, {
|
|
218
|
+
method: "POST",
|
|
219
|
+
body: JSON.stringify(oauthData),
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Generate embeddings for tools (requires authentication)
|
|
224
|
+
*/
|
|
225
|
+
async generateEmbeddings(data, token, tokenType = "cli") {
|
|
226
|
+
const endpoint = "/functions/v1/generate-embeddings";
|
|
227
|
+
return this.makeRequest(endpoint, {
|
|
228
|
+
method: "POST",
|
|
229
|
+
body: JSON.stringify(data),
|
|
230
|
+
}, token, tokenType);
|
|
231
|
+
}
|
|
232
|
+
// ===================
|
|
233
|
+
// CONVENIENCE METHODS
|
|
234
|
+
// ===================
|
|
235
|
+
/**
|
|
236
|
+
* Check if a tool exists
|
|
237
|
+
*/
|
|
238
|
+
async toolExists(name) {
|
|
239
|
+
try {
|
|
240
|
+
await this.getTool(name);
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
if (error instanceof Error && error.message.includes("404")) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
throw error;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Publish or update tool based on existence
|
|
252
|
+
*/
|
|
253
|
+
async publishOrUpdateTool(tool, token, tokenType = "cli") {
|
|
254
|
+
let exists;
|
|
255
|
+
try {
|
|
256
|
+
exists = await this.toolExists(tool.name);
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
exists = false;
|
|
260
|
+
}
|
|
261
|
+
if (exists) {
|
|
262
|
+
const result = await this.updateTool(tool.name, tool, token, tokenType);
|
|
263
|
+
return { isUpdate: true, result };
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
const result = await this.publishTool(tool, token, tokenType);
|
|
267
|
+
return { isUpdate: false, result };
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Search tools by tags
|
|
272
|
+
*/
|
|
273
|
+
async getToolsByTags(tags, limit = 20) {
|
|
274
|
+
return this.searchTools({
|
|
275
|
+
query: tags.join(" "),
|
|
276
|
+
tags,
|
|
277
|
+
limit,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Get tools by author
|
|
282
|
+
*/
|
|
283
|
+
async getToolsByAuthor(author, limit = 20) {
|
|
284
|
+
return this.getTools({
|
|
285
|
+
author,
|
|
286
|
+
limit,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Get a user's public key
|
|
291
|
+
*/
|
|
292
|
+
async getUserPublicKey(userId) {
|
|
293
|
+
const url = `${this.supabaseUrl}/functions/v1/tools/user/public-key/${userId}`;
|
|
294
|
+
const headers = {
|
|
295
|
+
Accept: "application/json",
|
|
296
|
+
"Content-Type": "application/json",
|
|
297
|
+
};
|
|
298
|
+
try {
|
|
299
|
+
const response = await fetch(url, {
|
|
300
|
+
method: "GET",
|
|
301
|
+
headers,
|
|
302
|
+
});
|
|
303
|
+
if (!response.ok) {
|
|
304
|
+
const errorText = await response.text();
|
|
305
|
+
let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
306
|
+
try {
|
|
307
|
+
const errorJson = JSON.parse(errorText);
|
|
308
|
+
if (errorJson.message) {
|
|
309
|
+
errorMessage = errorJson.message;
|
|
310
|
+
}
|
|
311
|
+
else if (errorJson.error) {
|
|
312
|
+
errorMessage = errorJson.error;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
// If we can't parse JSON, stick with the original error message
|
|
317
|
+
}
|
|
318
|
+
throw new EnactApiError(errorMessage, response.status);
|
|
319
|
+
}
|
|
320
|
+
const data = await response.json();
|
|
321
|
+
return data;
|
|
322
|
+
}
|
|
323
|
+
catch (error) {
|
|
324
|
+
if (error instanceof EnactApiError) {
|
|
325
|
+
throw error;
|
|
326
|
+
}
|
|
327
|
+
// Handle network errors
|
|
328
|
+
if (error instanceof Error) {
|
|
329
|
+
if (error.message.includes("fetch")) {
|
|
330
|
+
throw new EnactApiError("Network error: Could not connect to Enact API", 0);
|
|
331
|
+
}
|
|
332
|
+
throw new EnactApiError(error.message, 0);
|
|
333
|
+
}
|
|
334
|
+
throw new EnactApiError("Unknown error occurred", 0);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
// ===================
|
|
338
|
+
// OAUTH FLOW HELPERS
|
|
339
|
+
// ===================
|
|
340
|
+
/**
|
|
341
|
+
* Generate OAuth authorization URL
|
|
342
|
+
*/
|
|
343
|
+
generateOAuthUrl(options) {
|
|
344
|
+
const params = new URLSearchParams({
|
|
345
|
+
response_type: "code",
|
|
346
|
+
client_id: options.clientId,
|
|
347
|
+
redirect_uri: options.redirectUri,
|
|
348
|
+
scope: options.scope,
|
|
349
|
+
state: options.state,
|
|
350
|
+
code_challenge: options.codeChallenge,
|
|
351
|
+
code_challenge_method: options.codeChallengeMethod,
|
|
352
|
+
});
|
|
353
|
+
return `${this.baseUrl}/auth/cli/oauth?${params.toString()}`;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Validate tool definition before publishing
|
|
357
|
+
*/
|
|
358
|
+
validateTool(tool) {
|
|
359
|
+
const errors = [];
|
|
360
|
+
if (!tool.name || typeof tool.name !== "string") {
|
|
361
|
+
errors.push("Tool name is required and must be a string");
|
|
362
|
+
}
|
|
363
|
+
else if (!/^[a-zA-Z0-9_-]+\/[a-zA-Z0-9_\/-]+$/.test(tool.name)) {
|
|
364
|
+
errors.push("Tool name must follow hierarchical format: org/package/tool-name");
|
|
365
|
+
}
|
|
366
|
+
if (!tool.description || typeof tool.description !== "string") {
|
|
367
|
+
errors.push("Tool description is required and must be a string");
|
|
368
|
+
}
|
|
369
|
+
if (!tool.command || typeof tool.command !== "string") {
|
|
370
|
+
errors.push("Tool command is required and must be a string");
|
|
371
|
+
}
|
|
372
|
+
if (tool.timeout && typeof tool.timeout === "string") {
|
|
373
|
+
if (!/^\d+[smh]$/.test(tool.timeout)) {
|
|
374
|
+
errors.push('Timeout must be in Go duration format (e.g., "30s", "5m", "1h")');
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
if (tool.tags && !Array.isArray(tool.tags)) {
|
|
378
|
+
errors.push("Tags must be an array of strings");
|
|
379
|
+
}
|
|
380
|
+
if (tool.inputSchema && typeof tool.inputSchema !== "object") {
|
|
381
|
+
errors.push("inputSchema must be a valid JSON Schema object");
|
|
382
|
+
}
|
|
383
|
+
if (tool.outputSchema && typeof tool.outputSchema !== "object") {
|
|
384
|
+
errors.push("outputSchema must be a valid JSON Schema object");
|
|
385
|
+
}
|
|
386
|
+
return {
|
|
387
|
+
valid: errors.length === 0,
|
|
388
|
+
errors,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
// Export a default instance
|
|
393
|
+
export const enactApi = new EnactApiClient();
|
|
394
|
+
// Export error types for better error handling
|
|
395
|
+
export class EnactApiError extends Error {
|
|
396
|
+
constructor(message, statusCode, endpoint) {
|
|
397
|
+
super(message);
|
|
398
|
+
this.statusCode = statusCode;
|
|
399
|
+
this.endpoint = endpoint;
|
|
400
|
+
this.name = "EnactApiError";
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
// Helper function to create API client with custom configuration
|
|
404
|
+
export function createEnactApiClient(baseUrl, supabaseUrl) {
|
|
405
|
+
return new EnactApiClient(baseUrl, supabaseUrl);
|
|
406
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export interface EnactToolDefinition {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
command: string;
|
|
5
|
+
version?: string;
|
|
6
|
+
timeout?: string;
|
|
7
|
+
tags?: string[];
|
|
8
|
+
inputSchema?: any;
|
|
9
|
+
outputSchema?: any;
|
|
10
|
+
examples?: any[];
|
|
11
|
+
annotations?: {
|
|
12
|
+
title?: string;
|
|
13
|
+
readOnlyHint?: boolean;
|
|
14
|
+
destructiveHint?: boolean;
|
|
15
|
+
idempotentHint?: boolean;
|
|
16
|
+
openWorldHint?: boolean;
|
|
17
|
+
};
|
|
18
|
+
env?: Record<string, {
|
|
19
|
+
description: string;
|
|
20
|
+
source?: string;
|
|
21
|
+
required: boolean;
|
|
22
|
+
default?: string;
|
|
23
|
+
}>;
|
|
24
|
+
resources?: {
|
|
25
|
+
memory?: string;
|
|
26
|
+
gpu?: string;
|
|
27
|
+
disk?: string;
|
|
28
|
+
};
|
|
29
|
+
signature?: {
|
|
30
|
+
algorithm: string;
|
|
31
|
+
type: string;
|
|
32
|
+
signer: string;
|
|
33
|
+
created: string;
|
|
34
|
+
value: string;
|
|
35
|
+
role?: string;
|
|
36
|
+
};
|
|
37
|
+
signatures?: Record<string, any>;
|
|
38
|
+
raw_content?: string;
|
|
39
|
+
namespace?: string;
|
|
40
|
+
enact?: string;
|
|
41
|
+
[key: string]: any;
|
|
42
|
+
}
|
|
43
|
+
export interface ToolSearchQuery {
|
|
44
|
+
query: string;
|
|
45
|
+
limit?: number;
|
|
46
|
+
tags?: string[];
|
|
47
|
+
format?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface ToolUsage {
|
|
50
|
+
action: "view" | "download" | "execute";
|
|
51
|
+
metadata?: any;
|
|
52
|
+
}
|
|
53
|
+
export interface CLITokenCreate {
|
|
54
|
+
name?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface OAuthTokenExchange {
|
|
57
|
+
grant_type: "authorization_code";
|
|
58
|
+
code: string;
|
|
59
|
+
redirect_uri: string;
|
|
60
|
+
client_id: string;
|
|
61
|
+
code_verifier: string;
|
|
62
|
+
}
|
|
63
|
+
export interface ApiResponse<T = any> {
|
|
64
|
+
success: boolean;
|
|
65
|
+
data?: T;
|
|
66
|
+
error?: string;
|
|
67
|
+
}
|
|
68
|
+
export interface VerificationPolicy {
|
|
69
|
+
minimumSignatures?: number;
|
|
70
|
+
trustedSigners?: string[];
|
|
71
|
+
allowedAlgorithms?: string[];
|
|
72
|
+
}
|
|
73
|
+
export interface EnactExecOptions {
|
|
74
|
+
help?: boolean;
|
|
75
|
+
input?: string;
|
|
76
|
+
params?: string;
|
|
77
|
+
timeout?: string;
|
|
78
|
+
dry?: boolean;
|
|
79
|
+
verbose?: boolean;
|
|
80
|
+
skipVerification?: boolean;
|
|
81
|
+
verifyPolicy?: string;
|
|
82
|
+
force?: boolean;
|
|
83
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { ExecutionProvider, type EnactTool, type ExecutionEnvironment, type ExecutionResult } from "../types.js";
|
|
2
|
+
export interface DaggerExecutionOptions {
|
|
3
|
+
baseImage?: string;
|
|
4
|
+
workdir?: string;
|
|
5
|
+
enableNetwork?: boolean;
|
|
6
|
+
enableHostFS?: boolean;
|
|
7
|
+
maxMemory?: string;
|
|
8
|
+
maxCPU?: string;
|
|
9
|
+
cacheVolume?: string;
|
|
10
|
+
useShell?: boolean;
|
|
11
|
+
engineTimeout?: number;
|
|
12
|
+
maxRetries?: number;
|
|
13
|
+
enableEngineHealthCheck?: boolean;
|
|
14
|
+
}
|
|
15
|
+
interface CommandResult {
|
|
16
|
+
stdout: string;
|
|
17
|
+
stderr: string;
|
|
18
|
+
exitCode: number;
|
|
19
|
+
}
|
|
20
|
+
interface EngineHealthStatus {
|
|
21
|
+
isHealthy: boolean;
|
|
22
|
+
lastCheck: Date;
|
|
23
|
+
consecutiveFailures: number;
|
|
24
|
+
}
|
|
25
|
+
export declare class DaggerExecutionProvider extends ExecutionProvider {
|
|
26
|
+
private client;
|
|
27
|
+
private options;
|
|
28
|
+
private tempDir;
|
|
29
|
+
private connectionCleanup;
|
|
30
|
+
private engineHealth;
|
|
31
|
+
private abortController;
|
|
32
|
+
private activeSessions;
|
|
33
|
+
private isShuttingDown;
|
|
34
|
+
constructor(options?: DaggerExecutionOptions);
|
|
35
|
+
setup(tool: EnactTool): Promise<boolean>;
|
|
36
|
+
/**
|
|
37
|
+
* Enhanced cleanup with comprehensive engine management and session tracking
|
|
38
|
+
*/
|
|
39
|
+
cleanup(): Promise<boolean>;
|
|
40
|
+
/**
|
|
41
|
+
* Enhanced engine cleanup with better container detection
|
|
42
|
+
*/
|
|
43
|
+
private performEngineCleanup;
|
|
44
|
+
/**
|
|
45
|
+
* Check engine health with comprehensive diagnostics
|
|
46
|
+
*/
|
|
47
|
+
private checkEngineHealth;
|
|
48
|
+
/**
|
|
49
|
+
* Reset engine container when health check fails
|
|
50
|
+
*/
|
|
51
|
+
private resetEngineContainer;
|
|
52
|
+
/**
|
|
53
|
+
* Start periodic engine health monitoring
|
|
54
|
+
*/
|
|
55
|
+
private startEngineHealthMonitoring;
|
|
56
|
+
/**
|
|
57
|
+
* Wait for active sessions to complete with timeout
|
|
58
|
+
*/
|
|
59
|
+
private waitForActiveSessions;
|
|
60
|
+
resolveEnvironmentVariables(envConfig: Record<string, any>, namespace?: string): Promise<Record<string, any>>;
|
|
61
|
+
execute(tool: EnactTool, inputs: Record<string, any>, environment: ExecutionEnvironment): Promise<ExecutionResult>;
|
|
62
|
+
/**
|
|
63
|
+
* Categorize errors for better handling
|
|
64
|
+
*/
|
|
65
|
+
private categorizeError;
|
|
66
|
+
executeCommand(command: string, inputs: Record<string, any>, environment: ExecutionEnvironment, timeout?: string, options?: {
|
|
67
|
+
verbose?: boolean;
|
|
68
|
+
showSpinner?: boolean;
|
|
69
|
+
streamOutput?: boolean;
|
|
70
|
+
}): Promise<CommandResult>;
|
|
71
|
+
/**
|
|
72
|
+
* Execute command using Dagger connect with proper session management
|
|
73
|
+
*/
|
|
74
|
+
private executeWithConnect;
|
|
75
|
+
/**
|
|
76
|
+
* Enhanced container setup with better tool detection and installation
|
|
77
|
+
*/
|
|
78
|
+
private setupContainer;
|
|
79
|
+
/**
|
|
80
|
+
* Install common tools that Enact commands might need
|
|
81
|
+
* Enhanced with better error handling and timeout
|
|
82
|
+
*/
|
|
83
|
+
private installCommonTools;
|
|
84
|
+
/**
|
|
85
|
+
* Execute command in container with enhanced error handling
|
|
86
|
+
*/
|
|
87
|
+
private executeInContainer;
|
|
88
|
+
/**
|
|
89
|
+
* Enhanced execution error parsing
|
|
90
|
+
*/
|
|
91
|
+
private parseExecutionError;
|
|
92
|
+
/**
|
|
93
|
+
* Apply resource limits based on Enact tool specifications
|
|
94
|
+
*/
|
|
95
|
+
private applyResourceLimits;
|
|
96
|
+
/**
|
|
97
|
+
* Substitute template variables in Enact commands with enhanced security
|
|
98
|
+
*/
|
|
99
|
+
private substituteCommandVariables;
|
|
100
|
+
/**
|
|
101
|
+
* Enhanced shell argument escaping
|
|
102
|
+
*/
|
|
103
|
+
private escapeShellArg;
|
|
104
|
+
/**
|
|
105
|
+
* Prepare input files for Enact tools that expect file inputs
|
|
106
|
+
*/
|
|
107
|
+
private prepareInputFiles;
|
|
108
|
+
/**
|
|
109
|
+
* Heuristics to determine if input should be treated as file content
|
|
110
|
+
*/
|
|
111
|
+
private looksLikeFileContent;
|
|
112
|
+
/**
|
|
113
|
+
* Check if content looks like common file types
|
|
114
|
+
*/
|
|
115
|
+
private hasCommonFileExtensions;
|
|
116
|
+
/**
|
|
117
|
+
* Generate appropriate filename for input content
|
|
118
|
+
*/
|
|
119
|
+
private getInputFileName;
|
|
120
|
+
/**
|
|
121
|
+
* Map MIME types to file extensions
|
|
122
|
+
*/
|
|
123
|
+
private getExtensionFromMimeType;
|
|
124
|
+
/**
|
|
125
|
+
* Enhanced command parsing for non-shell execution
|
|
126
|
+
*/
|
|
127
|
+
private parseCommand;
|
|
128
|
+
/**
|
|
129
|
+
* Enhanced timeout promise with abort signal support
|
|
130
|
+
*/
|
|
131
|
+
private createTimeoutPromise;
|
|
132
|
+
/**
|
|
133
|
+
* Parse command output according to Enact tool output schema
|
|
134
|
+
*/
|
|
135
|
+
private parseOutput;
|
|
136
|
+
/**
|
|
137
|
+
* Execute command with exec.ts style interface for backwards compatibility
|
|
138
|
+
*/
|
|
139
|
+
executeCommandExecStyle(command: string, timeout: string, verbose?: boolean, envVars?: Record<string, string>): Promise<void>;
|
|
140
|
+
/**
|
|
141
|
+
* Enhanced cleanup handlers with graceful shutdown
|
|
142
|
+
*/
|
|
143
|
+
private registerCleanupHandlers;
|
|
144
|
+
/**
|
|
145
|
+
* Graceful shutdown with proper async cleanup
|
|
146
|
+
*/
|
|
147
|
+
private gracefulShutdown;
|
|
148
|
+
/**
|
|
149
|
+
* Enhanced force cleanup for synchronous exit handlers
|
|
150
|
+
*/
|
|
151
|
+
private forceCleanup;
|
|
152
|
+
/**
|
|
153
|
+
* Get current engine status for debugging
|
|
154
|
+
*/
|
|
155
|
+
getEngineStatus(): {
|
|
156
|
+
health: EngineHealthStatus;
|
|
157
|
+
activeSessions: number;
|
|
158
|
+
isShuttingDown: boolean;
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* Manually trigger engine reset (for debugging/testing)
|
|
162
|
+
*/
|
|
163
|
+
resetEngine(): Promise<void>;
|
|
164
|
+
/**
|
|
165
|
+
* Check if provider is ready for new executions
|
|
166
|
+
*/
|
|
167
|
+
isReady(): boolean;
|
|
168
|
+
}
|
|
169
|
+
export {};
|