@enactprotocol/shared 1.2.3 → 1.2.5

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.
@@ -2,7 +2,11 @@ import { EnactToolDefinition, ToolUsage, ToolSearchQuery, CLITokenCreate, OAuthT
2
2
  export declare class EnactApiClient {
3
3
  baseUrl: string;
4
4
  supabaseUrl: string;
5
- constructor(baseUrl?: string, supabaseUrl?: string);
5
+ constructor(baseUrl: string, supabaseUrl: string);
6
+ /**
7
+ * Create API client with config-based URLs
8
+ */
9
+ static create(baseUrl?: string, supabaseUrl?: string): Promise<EnactApiClient>;
6
10
  private makeRequest;
7
11
  /**
8
12
  * Get all tools (public, no auth required)
@@ -115,6 +119,7 @@ export declare class EnactApiClient {
115
119
  errors: string[];
116
120
  };
117
121
  }
122
+ export declare function createDefaultApiClient(): Promise<EnactApiClient>;
118
123
  export declare const enactApi: EnactApiClient;
119
124
  export declare class EnactApiError extends Error {
120
125
  statusCode?: number | undefined;
@@ -1,8 +1,17 @@
1
+ import { getFrontendUrl, getApiUrl } from "../utils/config";
1
2
  export class EnactApiClient {
2
- constructor(baseUrl = "https://enact.tools", supabaseUrl = "https://xjnhhxwxovjifdxdwzih.supabase.co") {
3
+ constructor(baseUrl, supabaseUrl) {
3
4
  this.baseUrl = baseUrl.replace(/\/$/, ""); // Remove trailing slash
4
5
  this.supabaseUrl = supabaseUrl.replace(/\/$/, "");
5
6
  }
7
+ /**
8
+ * Create API client with config-based URLs
9
+ */
10
+ static async create(baseUrl, supabaseUrl) {
11
+ const frontendUrl = baseUrl || await getFrontendUrl();
12
+ const apiUrl = supabaseUrl || await getApiUrl();
13
+ return new EnactApiClient(frontendUrl, apiUrl);
14
+ }
6
15
  // Helper method to make authenticated requests
7
16
  async makeRequest(endpoint, options = {}, token, tokenType = "jwt") {
8
17
  const url = endpoint.startsWith("http")
@@ -389,8 +398,12 @@ export class EnactApiClient {
389
398
  };
390
399
  }
391
400
  }
392
- // Export a default instance
393
- export const enactApi = new EnactApiClient();
401
+ // Export a default instance factory
402
+ export async function createDefaultApiClient() {
403
+ return await EnactApiClient.create();
404
+ }
405
+ // Keep backward compatibility with sync usage
406
+ export const enactApi = new EnactApiClient("https://enact.tools", "https://xjnhhxwxovjifdxdwzih.supabase.co");
394
407
  // Export error types for better error handling
395
408
  export class EnactApiError extends Error {
396
409
  constructor(message, statusCode, endpoint) {
@@ -402,5 +415,7 @@ export class EnactApiError extends Error {
402
415
  }
403
416
  // Helper function to create API client with custom configuration
404
417
  export function createEnactApiClient(baseUrl, supabaseUrl) {
405
- return new EnactApiClient(baseUrl, supabaseUrl);
418
+ const defaultFrontend = "https://enact.tools";
419
+ const defaultApi = "https://xjnhhxwxovjifdxdwzih.supabase.co";
420
+ return new EnactApiClient(baseUrl || defaultFrontend, supabaseUrl || defaultApi);
406
421
  }
@@ -87,4 +87,5 @@ export interface EnactExecOptions {
87
87
  verbose?: boolean;
88
88
  force?: boolean;
89
89
  dangerouslySkipVerification?: boolean;
90
+ mount?: string;
90
91
  }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Shared constants for Enact CLI
3
+ */
4
+ export declare const DEFAULT_FRONTEND_URL = "https://enact.tools";
5
+ export declare const DEFAULT_API_URL = "https://xjnhhxwxovjifdxdwzih.supabase.co";
6
+ export declare const ENV_FRONTEND_URL = "ENACT_FRONTEND_URL";
7
+ export declare const ENV_API_URL = "ENACT_API_URL";
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Shared constants for Enact CLI
3
+ */
4
+ // Frontend URL - used for OAuth redirects, registry browsing, documentation links
5
+ export const DEFAULT_FRONTEND_URL = "https://enact.tools";
6
+ // Backend API URL - used for all API calls (search, publish, etc.)
7
+ export const DEFAULT_API_URL = "https://xjnhhxwxovjifdxdwzih.supabase.co";
8
+ // Environment variable names for overriding defaults
9
+ export const ENV_FRONTEND_URL = "ENACT_FRONTEND_URL";
10
+ export const ENV_API_URL = "ENACT_API_URL";
@@ -72,6 +72,10 @@ export declare class DaggerExecutionProvider extends ExecutionProvider {
72
72
  * Execute command using Dagger connect with proper session management
73
73
  */
74
74
  private executeWithConnect;
75
+ /**
76
+ * Setup directory mounting for the container
77
+ */
78
+ private setupDirectoryMount;
75
79
  /**
76
80
  * Enhanced container setup with better tool detection and installation
77
81
  */
@@ -145,10 +149,6 @@ export declare class DaggerExecutionProvider extends ExecutionProvider {
145
149
  * Graceful shutdown with proper async cleanup
146
150
  */
147
151
  private gracefulShutdown;
148
- /**
149
- * Enhanced force cleanup for synchronous exit handlers
150
- */
151
- private forceCleanup;
152
152
  /**
153
153
  * Get current engine status for debugging
154
154
  */
@@ -504,6 +504,68 @@ export class DaggerExecutionProvider extends ExecutionProvider {
504
504
  });
505
505
  });
506
506
  }
507
+ /**
508
+ * Setup directory mounting for the container
509
+ */
510
+ async setupDirectoryMount(client, container, mountSpec) {
511
+ try {
512
+ // Parse mount specification (format: "localPath" or "localPath:containerPath")
513
+ let localPath;
514
+ let containerPath;
515
+ // Handle Windows drive letters (e.g., C:\path) vs mount separator (:)
516
+ const colonIndex = mountSpec.indexOf(':');
517
+ if (colonIndex > 0) {
518
+ // Check if this might be a Windows drive letter (single letter followed by colon)
519
+ const potentialDriveLetter = mountSpec.substring(0, colonIndex);
520
+ const isWindowsDrive = potentialDriveLetter.length === 1 && /[A-Za-z]/.test(potentialDriveLetter);
521
+ if (isWindowsDrive) {
522
+ // Look for the next colon that separates local from container path
523
+ const nextColonIndex = mountSpec.indexOf(':', colonIndex + 1);
524
+ if (nextColonIndex > 0) {
525
+ localPath = mountSpec.substring(0, nextColonIndex);
526
+ containerPath = mountSpec.substring(nextColonIndex + 1);
527
+ }
528
+ else {
529
+ // No container path specified, use default
530
+ localPath = mountSpec;
531
+ containerPath = '/workspace/src';
532
+ }
533
+ }
534
+ else {
535
+ // Regular path:container split
536
+ localPath = mountSpec.substring(0, colonIndex);
537
+ containerPath = mountSpec.substring(colonIndex + 1);
538
+ }
539
+ }
540
+ else if (colonIndex === 0) {
541
+ // Starts with colon (e.g., ":/app")
542
+ localPath = '';
543
+ containerPath = mountSpec.substring(1);
544
+ }
545
+ else {
546
+ localPath = mountSpec;
547
+ containerPath = '/workspace/src'; // Default container path
548
+ }
549
+ // Resolve local path to absolute path
550
+ const path = require('path');
551
+ const resolvedLocalPath = path.resolve(localPath);
552
+ // Check if local directory exists
553
+ const fs = require('fs');
554
+ if (!fs.existsSync(resolvedLocalPath)) {
555
+ throw new Error(`Mount source directory does not exist: ${resolvedLocalPath}`);
556
+ }
557
+ // Create Directory object from local path
558
+ const hostDirectory = client.host().directory(resolvedLocalPath);
559
+ // Mount directory in container using withMountedDirectory for better performance
560
+ container = container.withMountedDirectory(containerPath, hostDirectory);
561
+ logger.debug(`📂 Mounted ${resolvedLocalPath} -> ${containerPath}`);
562
+ return container;
563
+ }
564
+ catch (error) {
565
+ logger.error(`Failed to setup directory mount: ${error}`);
566
+ throw error;
567
+ }
568
+ }
507
569
  /**
508
570
  * Enhanced container setup with better tool detection and installation
509
571
  */
@@ -517,6 +579,10 @@ export class DaggerExecutionProvider extends ExecutionProvider {
517
579
  // Set working directory
518
580
  container = container.withWorkdir(this.options.workdir);
519
581
  logger.debug(`📁 Working directory set to: ${this.options.workdir}`);
582
+ // Handle directory mounting if specified
583
+ if (environment.mount) {
584
+ container = await this.setupDirectoryMount(client, container, environment.mount);
585
+ }
520
586
  // Add environment variables from Enact tool env config
521
587
  for (const [key, value] of Object.entries(environment.vars)) {
522
588
  container = container.withEnvVariable(key, String(value));
@@ -935,43 +1001,6 @@ export class DaggerExecutionProvider extends ExecutionProvider {
935
1001
  process.exit(1);
936
1002
  }
937
1003
  }
938
- /**
939
- * Enhanced force cleanup for synchronous exit handlers
940
- */
941
- forceCleanup() {
942
- if (this.isShuttingDown)
943
- return;
944
- try {
945
- logger.info("🔄 Force cleaning up Dagger engines...");
946
- const result = spawnSync("docker", [
947
- "ps",
948
- "--all",
949
- "--filter",
950
- "name=dagger-engine",
951
- "--format",
952
- "{{.Names}}",
953
- ], {
954
- encoding: "utf8",
955
- timeout: 5000,
956
- });
957
- if (result.stdout) {
958
- const names = result.stdout
959
- .trim()
960
- .split("\n")
961
- .filter((n) => n.trim());
962
- if (names.length > 0) {
963
- logger.info(`Found ${names.length} engine containers, force removing...`);
964
- for (const name of names) {
965
- spawnSync("docker", ["rm", "-f", name.trim()], { timeout: 3000 });
966
- }
967
- logger.info("✅ Force cleanup completed");
968
- }
969
- }
970
- }
971
- catch (error) {
972
- logger.debug("Force cleanup failed (this is usually fine):", error);
973
- }
974
- }
975
1004
  /**
976
1005
  * Get current engine status for debugging
977
1006
  */
@@ -28,12 +28,17 @@ export interface ToolExecuteOptions {
28
28
  verbose?: boolean;
29
29
  isLocalFile?: boolean;
30
30
  dangerouslySkipVerification?: boolean;
31
+ mount?: string;
31
32
  }
32
33
  export declare class EnactCore {
33
34
  private apiClient;
34
35
  private executionProvider;
35
36
  private options;
36
37
  constructor(options?: EnactCoreOptions);
38
+ /**
39
+ * Create EnactCore with config-based URLs
40
+ */
41
+ static create(options?: EnactCoreOptions): Promise<EnactCore>;
37
42
  /**
38
43
  * Set authentication token for API operations
39
44
  */
@@ -6,11 +6,12 @@ import { resolveToolEnvironmentVariables } from "../utils/env-loader.js";
6
6
  import logger from "../exec/logger.js";
7
7
  import yaml from "yaml";
8
8
  import { CryptoUtils, SecurityConfigManager, SigningService } from "@enactprotocol/security";
9
+ import { getFrontendUrl, getApiUrl } from "../utils/config";
9
10
  export class EnactCore {
10
11
  constructor(options = {}) {
11
12
  this.options = {
12
- apiUrl: "https://enact.tools",
13
- supabaseUrl: "https://xjnhhxwxovjifdxdwzih.supabase.co",
13
+ apiUrl: "https://enact.tools", // Default, will be overridden by factory
14
+ supabaseUrl: "https://xjnhhxwxovjifdxdwzih.supabase.co", // Default, will be overridden by factory
14
15
  executionProvider: "dagger",
15
16
  defaultTimeout: "30s",
16
17
  ...options,
@@ -19,6 +20,18 @@ export class EnactCore {
19
20
  // Initialize the appropriate execution provider
20
21
  this.executionProvider = this.createExecutionProvider();
21
22
  }
23
+ /**
24
+ * Create EnactCore with config-based URLs
25
+ */
26
+ static async create(options = {}) {
27
+ const frontendUrl = options.apiUrl || await getFrontendUrl();
28
+ const apiUrl = options.supabaseUrl || await getApiUrl();
29
+ return new EnactCore({
30
+ ...options,
31
+ apiUrl: frontendUrl,
32
+ supabaseUrl: apiUrl,
33
+ });
34
+ }
22
35
  /**
23
36
  * Set authentication token for API operations
24
37
  */
@@ -292,7 +305,7 @@ export class EnactCore {
292
305
  // Check trusted keys
293
306
  // const trustedKeys = KeyManager.getAllTrustedPublicKeys();
294
307
  const isValid = SigningService.verifyDocument(documentForVerification, referenceSignature, { includeFields: ['command'] });
295
- console.log("Final verification result:", isValid);
308
+ // console.log("Final verification result:", isValid);
296
309
  if (!isValid) {
297
310
  throw new Error(`Tool ${tool.name} has invalid signatures`);
298
311
  }
@@ -332,6 +345,7 @@ export class EnactCore {
332
345
  resources: {
333
346
  timeout: options.timeout || tool.timeout || this.options.defaultTimeout,
334
347
  },
348
+ mount: options.mount,
335
349
  });
336
350
  }
337
351
  catch (error) {
@@ -14,6 +14,15 @@ export declare class EnactDirect {
14
14
  authToken?: string;
15
15
  defaultTimeout?: string;
16
16
  });
17
+ /**
18
+ * Create EnactDirect with config-based URLs
19
+ */
20
+ static create(options?: {
21
+ apiUrl?: string;
22
+ supabaseUrl?: string;
23
+ authToken?: string;
24
+ defaultTimeout?: string;
25
+ }): Promise<EnactDirect>;
17
26
  /**
18
27
  * Execute a tool by name with inputs
19
28
  *
@@ -1,5 +1,6 @@
1
1
  // src/lib/enact-direct.ts - Library interface for direct usage by MCP servers
2
2
  import { EnactCore, } from "../core/EnactCore";
3
+ import { getFrontendUrl, getApiUrl } from "../utils/config";
3
4
  /**
4
5
  * Direct Enact Library Interface
5
6
  *
@@ -8,16 +9,27 @@ import { EnactCore, } from "../core/EnactCore";
8
9
  */
9
10
  export class EnactDirect {
10
11
  constructor(options = {}) {
12
+ // We need to handle async config loading in a factory method
11
13
  this.core = new EnactCore({
12
- apiUrl: options.apiUrl || process.env.ENACT_API_URL || "https://enact.tools",
13
- supabaseUrl: options.supabaseUrl ||
14
- process.env.ENACT_SUPABASE_URL ||
15
- "https://xjnhhxwxovjifdxdwzih.supabase.co",
14
+ apiUrl: options.apiUrl || process.env.ENACT_FRONTEND_URL || "https://enact.tools",
15
+ supabaseUrl: options.supabaseUrl || process.env.ENACT_API_URL || "https://xjnhhxwxovjifdxdwzih.supabase.co",
16
16
  executionProvider: "direct",
17
17
  authToken: options.authToken || process.env.ENACT_AUTH_TOKEN,
18
18
  defaultTimeout: options.defaultTimeout || "30s",
19
19
  });
20
20
  }
21
+ /**
22
+ * Create EnactDirect with config-based URLs
23
+ */
24
+ static async create(options = {}) {
25
+ const frontendUrl = options.apiUrl || process.env.ENACT_FRONTEND_URL || await getFrontendUrl();
26
+ const apiUrl = options.supabaseUrl || process.env.ENACT_API_URL || await getApiUrl();
27
+ return new EnactDirect({
28
+ ...options,
29
+ apiUrl: frontendUrl,
30
+ supabaseUrl: apiUrl,
31
+ });
32
+ }
21
33
  /**
22
34
  * Execute a tool by name with inputs
23
35
  *
@@ -6,6 +6,14 @@ export declare class McpCoreService {
6
6
  supabaseUrl?: string;
7
7
  authToken?: string;
8
8
  });
9
+ /**
10
+ * Create McpCoreService with config-based URLs
11
+ */
12
+ static create(options?: {
13
+ apiUrl?: string;
14
+ supabaseUrl?: string;
15
+ authToken?: string;
16
+ }): Promise<McpCoreService>;
9
17
  /**
10
18
  * Set authentication token
11
19
  */
@@ -1,5 +1,6 @@
1
1
  // src/services/McpCoreService.ts - Direct core integration for MCP server
2
2
  import { EnactCore } from "../core/EnactCore";
3
+ import { getFrontendUrl, getApiUrl } from "../utils/config";
3
4
  export class McpCoreService {
4
5
  constructor(options) {
5
6
  this.core = new EnactCore({
@@ -8,6 +9,18 @@ export class McpCoreService {
8
9
  authToken: options?.authToken,
9
10
  });
10
11
  }
12
+ /**
13
+ * Create McpCoreService with config-based URLs
14
+ */
15
+ static async create(options) {
16
+ const frontendUrl = options?.apiUrl || await getFrontendUrl();
17
+ const apiUrl = options?.supabaseUrl || await getApiUrl();
18
+ return new McpCoreService({
19
+ ...options,
20
+ apiUrl: frontendUrl,
21
+ supabaseUrl: apiUrl,
22
+ });
23
+ }
11
24
  /**
12
25
  * Set authentication token
13
26
  */
package/dist/types.d.ts CHANGED
@@ -117,6 +117,7 @@ export interface ExecutionEnvironment {
117
117
  timeout?: string;
118
118
  };
119
119
  namespace?: string;
120
+ mount?: string;
120
121
  }
121
122
  export declare abstract class ExecutionProvider {
122
123
  abstract setup(tool: EnactTool): Promise<boolean>;
@@ -1,6 +1,10 @@
1
1
  export interface EnactConfig {
2
2
  defaultUrl?: string;
3
3
  history?: string[];
4
+ urls?: {
5
+ frontend?: string;
6
+ api?: string;
7
+ };
4
8
  }
5
9
  /**
6
10
  * Ensure config directory and file exist
@@ -30,3 +34,78 @@ export declare function setDefaultUrl(url: string): Promise<void>;
30
34
  * Get the default publish URL
31
35
  */
32
36
  export declare function getDefaultUrl(): Promise<string | undefined>;
37
+ export interface TrustedKeyMeta {
38
+ name: string;
39
+ description?: string;
40
+ addedAt: string;
41
+ source: "default" | "user" | "organization";
42
+ keyFile: string;
43
+ }
44
+ export interface TrustedKey {
45
+ id: string;
46
+ name: string;
47
+ publicKey: string;
48
+ description?: string;
49
+ addedAt: string;
50
+ source: "default" | "user" | "organization";
51
+ keyFile: string;
52
+ }
53
+ /**
54
+ * Get the frontend URL with fallbacks
55
+ */
56
+ export declare function getFrontendUrl(): Promise<string>;
57
+ /**
58
+ * Get the API URL with fallbacks
59
+ */
60
+ export declare function getApiUrl(): Promise<string>;
61
+ /**
62
+ * Set the frontend URL in config
63
+ */
64
+ export declare function setFrontendUrl(url: string): Promise<void>;
65
+ /**
66
+ * Set the API URL in config
67
+ */
68
+ export declare function setApiUrl(url: string): Promise<void>;
69
+ /**
70
+ * Reset URLs to defaults
71
+ */
72
+ export declare function resetUrls(): Promise<void>;
73
+ /**
74
+ * Get current URL configuration
75
+ */
76
+ export declare function getUrlConfig(): Promise<{
77
+ frontend: {
78
+ value: string;
79
+ source: string;
80
+ };
81
+ api: {
82
+ value: string;
83
+ source: string;
84
+ };
85
+ }>;
86
+ /**
87
+ * Read all trusted keys from directory
88
+ */
89
+ export declare function getTrustedKeys(): Promise<TrustedKey[]>;
90
+ /**
91
+ * Add a trusted key
92
+ */
93
+ export declare function addTrustedKey(keyData: {
94
+ id: string;
95
+ name: string;
96
+ publicKey: string;
97
+ description?: string;
98
+ source?: "user" | "organization";
99
+ }): Promise<void>;
100
+ /**
101
+ * Remove a trusted key
102
+ */
103
+ export declare function removeTrustedKey(keyId: string): Promise<void>;
104
+ /**
105
+ * Get a specific trusted key
106
+ */
107
+ export declare function getTrustedKey(keyId: string): Promise<TrustedKey | null>;
108
+ /**
109
+ * Check if a public key is trusted
110
+ */
111
+ export declare function isKeyTrusted(publicKey: string): Promise<boolean>;