@enactprotocol/cli 1.2.3 → 1.2.4

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 (3) hide show
  1. package/dist/index.js +566 -166
  2. package/dist/index.js.bak +566 -166
  3. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -158,31 +158,52 @@ var require_src = __commonJS((exports, module) => {
158
158
  });
159
159
 
160
160
  // ../shared/dist/utils/config.js
161
- import { homedir as homedir2 } from "os";
162
- import { join as join2 } from "path";
163
- import { existsSync as existsSync2 } from "fs";
164
- import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
161
+ import { homedir } from "os";
162
+ import { join } from "path";
163
+ import { existsSync } from "fs";
164
+ import { mkdir, readFile, writeFile } from "fs/promises";
165
165
  async function ensureConfig() {
166
- if (!existsSync2(CONFIG_DIR2)) {
167
- await mkdir2(CONFIG_DIR2, { recursive: true });
166
+ if (!existsSync(CONFIG_DIR)) {
167
+ await mkdir(CONFIG_DIR, { recursive: true });
168
168
  }
169
- if (!existsSync2(CONFIG_FILE)) {
170
- await writeFile2(CONFIG_FILE, JSON.stringify({ history: [] }, null, 2));
169
+ if (!existsSync(CONFIG_FILE)) {
170
+ const defaultConfig = {
171
+ history: [],
172
+ urls: {
173
+ frontend: DEFAULT_FRONTEND_URL,
174
+ api: DEFAULT_API_URL
175
+ }
176
+ };
177
+ await writeFile(CONFIG_FILE, JSON.stringify(defaultConfig, null, 2));
171
178
  }
172
179
  }
173
180
  async function readConfig() {
174
181
  await ensureConfig();
175
182
  try {
176
- const data = await readFile2(CONFIG_FILE, "utf8");
177
- return JSON.parse(data);
183
+ const data = await readFile(CONFIG_FILE, "utf8");
184
+ const config = JSON.parse(data);
185
+ if (!config.urls) {
186
+ config.urls = {
187
+ frontend: DEFAULT_FRONTEND_URL,
188
+ api: DEFAULT_API_URL
189
+ };
190
+ await writeConfig(config);
191
+ }
192
+ return config;
178
193
  } catch (error) {
179
194
  console.error("Failed to read config:", error.message);
180
- return { history: [] };
195
+ return {
196
+ history: [],
197
+ urls: {
198
+ frontend: DEFAULT_FRONTEND_URL,
199
+ api: DEFAULT_API_URL
200
+ }
201
+ };
181
202
  }
182
203
  }
183
204
  async function writeConfig(config) {
184
205
  await ensureConfig();
185
- await writeFile2(CONFIG_FILE, JSON.stringify(config, null, 2));
206
+ await writeFile(CONFIG_FILE, JSON.stringify(config, null, 2));
186
207
  }
187
208
  async function addToHistory(filePath) {
188
209
  const config = await readConfig();
@@ -208,10 +229,190 @@ async function getDefaultUrl() {
208
229
  const config = await readConfig();
209
230
  return config.defaultUrl;
210
231
  }
211
- var CONFIG_DIR2, CONFIG_FILE;
232
+ async function getFrontendUrl() {
233
+ if (process.env.ENACT_FRONTEND_URL) {
234
+ return process.env.ENACT_FRONTEND_URL;
235
+ }
236
+ const config = await readConfig();
237
+ if (config.urls?.frontend) {
238
+ return config.urls.frontend;
239
+ }
240
+ return DEFAULT_FRONTEND_URL;
241
+ }
242
+ async function getApiUrl() {
243
+ if (process.env.ENACT_API_URL) {
244
+ return process.env.ENACT_API_URL;
245
+ }
246
+ const config = await readConfig();
247
+ if (config.urls?.api) {
248
+ return config.urls.api;
249
+ }
250
+ return DEFAULT_API_URL;
251
+ }
252
+ async function setFrontendUrl(url) {
253
+ const config = await readConfig();
254
+ if (!config.urls) {
255
+ config.urls = {};
256
+ }
257
+ config.urls.frontend = url;
258
+ await writeConfig(config);
259
+ }
260
+ async function setApiUrl(url) {
261
+ const config = await readConfig();
262
+ if (!config.urls) {
263
+ config.urls = {};
264
+ }
265
+ config.urls.api = url;
266
+ await writeConfig(config);
267
+ }
268
+ async function resetUrls() {
269
+ const config = await readConfig();
270
+ if (config.urls) {
271
+ delete config.urls.frontend;
272
+ delete config.urls.api;
273
+ }
274
+ await writeConfig(config);
275
+ }
276
+ async function getUrlConfig() {
277
+ const config = await readConfig();
278
+ let frontendValue = DEFAULT_FRONTEND_URL;
279
+ let frontendSource = "default";
280
+ if (config.urls?.frontend) {
281
+ frontendValue = config.urls.frontend;
282
+ frontendSource = "config";
283
+ }
284
+ if (process.env.ENACT_FRONTEND_URL) {
285
+ frontendValue = process.env.ENACT_FRONTEND_URL;
286
+ frontendSource = "environment";
287
+ }
288
+ let apiValue = DEFAULT_API_URL;
289
+ let apiSource = "default";
290
+ if (config.urls?.api) {
291
+ apiValue = config.urls.api;
292
+ apiSource = "config";
293
+ }
294
+ if (process.env.ENACT_API_URL) {
295
+ apiValue = process.env.ENACT_API_URL;
296
+ apiSource = "environment";
297
+ }
298
+ return {
299
+ frontend: { value: frontendValue, source: frontendSource },
300
+ api: { value: apiValue, source: apiSource }
301
+ };
302
+ }
303
+ async function ensureTrustedKeysDir() {
304
+ if (!existsSync(CONFIG_DIR)) {
305
+ await mkdir(CONFIG_DIR, { recursive: true });
306
+ }
307
+ if (!existsSync(TRUSTED_KEYS_DIR)) {
308
+ await mkdir(TRUSTED_KEYS_DIR, { recursive: true });
309
+ }
310
+ const defaultKeyFile = join(TRUSTED_KEYS_DIR, "enact-protocol-official.pem");
311
+ const defaultMetaFile = join(TRUSTED_KEYS_DIR, "enact-protocol-official.meta");
312
+ if (!existsSync(defaultKeyFile)) {
313
+ await writeFile(defaultKeyFile, DEFAULT_ENACT_PUBLIC_KEY);
314
+ }
315
+ if (!existsSync(defaultMetaFile)) {
316
+ const defaultMeta = {
317
+ name: "Enact Protocol Official",
318
+ description: "Official Enact Protocol signing key for verified tools",
319
+ addedAt: new Date().toISOString(),
320
+ source: "default",
321
+ keyFile: "enact-protocol-official.pem"
322
+ };
323
+ await writeFile(defaultMetaFile, JSON.stringify(defaultMeta, null, 2));
324
+ }
325
+ }
326
+ async function getTrustedKeys() {
327
+ await ensureTrustedKeysDir();
328
+ const keys = [];
329
+ try {
330
+ const { readdir } = await import("fs/promises");
331
+ const files = await readdir(TRUSTED_KEYS_DIR);
332
+ const pemFiles = files.filter((f) => f.endsWith(".pem"));
333
+ for (const pemFile of pemFiles) {
334
+ try {
335
+ const keyId = pemFile.replace(".pem", "");
336
+ const keyPath = join(TRUSTED_KEYS_DIR, pemFile);
337
+ const metaPath = join(TRUSTED_KEYS_DIR, `${keyId}.meta`);
338
+ const publicKey = await readFile(keyPath, "utf8");
339
+ let meta = {
340
+ name: keyId,
341
+ addedAt: new Date().toISOString(),
342
+ source: "user",
343
+ keyFile: pemFile
344
+ };
345
+ if (existsSync(metaPath)) {
346
+ try {
347
+ const metaData = await readFile(metaPath, "utf8");
348
+ meta = { ...meta, ...JSON.parse(metaData) };
349
+ } catch {}
350
+ }
351
+ keys.push({
352
+ id: keyId,
353
+ name: meta.name,
354
+ publicKey: publicKey.trim(),
355
+ description: meta.description,
356
+ addedAt: meta.addedAt,
357
+ source: meta.source,
358
+ keyFile: pemFile
359
+ });
360
+ } catch (error) {
361
+ console.warn(`Warning: Could not read key file ${pemFile}:`, error);
362
+ }
363
+ }
364
+ } catch (error) {
365
+ console.error("Failed to read trusted keys directory:", error);
366
+ }
367
+ return keys;
368
+ }
369
+ async function addTrustedKey(keyData) {
370
+ await ensureTrustedKeysDir();
371
+ const keyFile = `${keyData.id}.pem`;
372
+ const metaFile = `${keyData.id}.meta`;
373
+ const keyPath = join(TRUSTED_KEYS_DIR, keyFile);
374
+ const metaPath = join(TRUSTED_KEYS_DIR, metaFile);
375
+ if (existsSync(keyPath)) {
376
+ throw new Error(`Key with ID '${keyData.id}' already exists`);
377
+ }
378
+ await writeFile(keyPath, keyData.publicKey);
379
+ const meta = {
380
+ name: keyData.name,
381
+ description: keyData.description,
382
+ addedAt: new Date().toISOString(),
383
+ source: keyData.source || "user",
384
+ keyFile
385
+ };
386
+ await writeFile(metaPath, JSON.stringify(meta, null, 2));
387
+ }
388
+ async function removeTrustedKey(keyId) {
389
+ const keyPath = join(TRUSTED_KEYS_DIR, `${keyId}.pem`);
390
+ const metaPath = join(TRUSTED_KEYS_DIR, `${keyId}.meta`);
391
+ if (!existsSync(keyPath)) {
392
+ throw new Error(`Trusted key '${keyId}' not found`);
393
+ }
394
+ const { unlink } = await import("fs/promises");
395
+ await unlink(keyPath);
396
+ if (existsSync(metaPath)) {
397
+ await unlink(metaPath);
398
+ }
399
+ }
400
+ async function getTrustedKey(keyId) {
401
+ const keys = await getTrustedKeys();
402
+ return keys.find((k3) => k3.id === keyId) || null;
403
+ }
404
+ async function isKeyTrusted(publicKey) {
405
+ const keys = await getTrustedKeys();
406
+ return keys.some((k3) => k3.publicKey.trim() === publicKey.trim());
407
+ }
408
+ var CONFIG_DIR, CONFIG_FILE, TRUSTED_KEYS_DIR, DEFAULT_FRONTEND_URL = "https://enact.tools", DEFAULT_API_URL = "https://xjnhhxwxovjifdxdwzih.supabase.co", DEFAULT_ENACT_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
409
+ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8VyE3jGm5yT2mKnPx1dQF7q8Z2Kv
410
+ 7mX9YnE2mK8vF3tY9pL6xH2dF8sK3mN7wQ5vT2gR8sL4xN6pM9uE3wF2Qw==
411
+ -----END PUBLIC KEY-----`;
212
412
  var init_config = __esm(() => {
213
- CONFIG_DIR2 = join2(homedir2(), ".enact");
214
- CONFIG_FILE = join2(CONFIG_DIR2, "config.json");
413
+ CONFIG_DIR = join(homedir(), ".enact");
414
+ CONFIG_FILE = join(CONFIG_DIR, "config.json");
415
+ TRUSTED_KEYS_DIR = join(CONFIG_DIR, "trusted-keys");
215
416
  });
216
417
 
217
418
  // ../../node_modules/dotenv/package.json
@@ -289,7 +490,7 @@ var require_main = __commonJS((exports, module) => {
289
490
  var packageJson = require_package();
290
491
  var version = packageJson.version;
291
492
  var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
292
- function parse2(src) {
493
+ function parse(src) {
293
494
  const obj = {};
294
495
  let lines = src.toString();
295
496
  lines = lines.replace(/\r\n?/mg, `
@@ -557,7 +758,7 @@ var require_main = __commonJS((exports, module) => {
557
758
  _parseVault,
558
759
  config,
559
760
  decrypt,
560
- parse: parse2,
761
+ parse,
561
762
  populate
562
763
  };
563
764
  exports.configDotenv = DotenvModule.configDotenv;
@@ -571,10 +772,10 @@ var require_main = __commonJS((exports, module) => {
571
772
  });
572
773
 
573
774
  // ../shared/dist/utils/env-loader.js
574
- import { join as join3 } from "path";
575
- import { homedir as homedir3 } from "os";
576
- import { existsSync as existsSync3 } from "fs";
577
- import { readFile as readFile3 } from "fs/promises";
775
+ import { join as join2 } from "path";
776
+ import { homedir as homedir2 } from "os";
777
+ import { existsSync as existsSync2 } from "fs";
778
+ import { readFile as readFile2 } from "fs/promises";
578
779
  function extractPackageNamespace(toolName) {
579
780
  const parts = toolName.split("/");
580
781
  if (parts.length < 2) {
@@ -586,7 +787,7 @@ function extractPackageNamespace(toolName) {
586
787
  return parts[0];
587
788
  }
588
789
  function getPackageEnvPath(packageNamespace) {
589
- return join3(CONFIG_DIR3, "env", packageNamespace, ".env");
790
+ return join2(CONFIG_DIR2, "env", packageNamespace, ".env");
590
791
  }
591
792
  function decryptValue(encryptedValue) {
592
793
  try {
@@ -597,11 +798,11 @@ function decryptValue(encryptedValue) {
597
798
  }
598
799
  async function readPackageEnvConfig(packageNamespace) {
599
800
  const envFile = getPackageEnvPath(packageNamespace);
600
- if (!existsSync3(envFile)) {
801
+ if (!existsSync2(envFile)) {
601
802
  return { variables: {} };
602
803
  }
603
804
  try {
604
- const data = await readFile3(envFile, "utf8");
805
+ const data = await readFile2(envFile, "utf8");
605
806
  if (data.trim().startsWith("{")) {
606
807
  return JSON.parse(data);
607
808
  } else {
@@ -630,7 +831,7 @@ function loadPackageEnvFile(toolName) {
630
831
  try {
631
832
  const packageNamespace = extractPackageNamespace(toolName);
632
833
  const packageEnvPath = getPackageEnvPath(packageNamespace);
633
- if (!existsSync3(packageEnvPath)) {
834
+ if (!existsSync2(packageEnvPath)) {
634
835
  return {};
635
836
  }
636
837
  const result = import_dotenv.config({ path: packageEnvPath });
@@ -741,10 +942,10 @@ function generateConfigLink(missingVars, toolName) {
741
942
  const encodedPackage = encodeURIComponent(packageNamespace);
742
943
  return `${webUrl}/?vars=${encodedVars}&package=${encodedPackage}`;
743
944
  }
744
- var import_dotenv, CONFIG_DIR3;
945
+ var import_dotenv, CONFIG_DIR2;
745
946
  var init_env_loader = __esm(() => {
746
947
  import_dotenv = __toESM(require_main(), 1);
747
- CONFIG_DIR3 = join3(homedir3(), ".enact");
948
+ CONFIG_DIR2 = join2(homedir2(), ".enact");
748
949
  import_dotenv.config();
749
950
  });
750
951
 
@@ -820,10 +1021,10 @@ var require_picocolors2 = __commonJS((exports, module) => {
820
1021
 
821
1022
  // ../shared/dist/utils/help.js
822
1023
  import { readFileSync } from "fs";
823
- import { join as join4 } from "path";
1024
+ import { join as join3 } from "path";
824
1025
  function getVersion() {
825
1026
  try {
826
- const packageJsonPath = join4(__dirname, "../../package.json");
1027
+ const packageJsonPath = join3(__dirname, "../../package.json");
827
1028
  const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
828
1029
  return packageJson.version || "0.1.0";
829
1030
  } catch (error) {
@@ -833,47 +1034,47 @@ function getVersion() {
833
1034
  function showHelp() {
834
1035
  const version = getVersion();
835
1036
  console.error(`
836
- ${import_picocolors4.default.bold("Enact CLI")} ${import_picocolors4.default.dim(`v${version}`)}
837
- ${import_picocolors4.default.dim("A CLI tool for managing and publishing Enact tools")}
838
-
839
- ${import_picocolors4.default.bold("Usage:")}
840
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("<command>")} [options]
841
-
842
- ${import_picocolors4.default.bold("Commands:")}
843
- ${import_picocolors4.default.green("auth")} Manage authentication (login, logout, status, token)
844
- ${import_picocolors4.default.green("env")} Manage environment variables (set, get, list, delete)
845
- ${import_picocolors4.default.green("exec")} Execute a tool by fetching and running it
846
- ${import_picocolors4.default.green("init")} Create a new tool definition
847
- ${import_picocolors4.default.green("mcp")} MCP client integration (install, list, status)
848
- ${import_picocolors4.default.green("publish")} Publish a tool to the registry
849
- ${import_picocolors4.default.green("search")} Search for tools in the registry
850
- ${import_picocolors4.default.green("sign")} Sign and verify tools with cryptographic signatures
851
- ${import_picocolors4.default.green("remote")} Manage remote servers (add, list, remove)
852
- ${import_picocolors4.default.green("user")} User operations (get public key)
853
-
854
- ${import_picocolors4.default.bold("Global Options:")}
855
- ${import_picocolors4.default.yellow("--help, -h")} Show help message
856
- ${import_picocolors4.default.yellow("--version, -v")} Show version information
857
-
858
- ${import_picocolors4.default.bold("Examples:")}
859
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.dim("# Interactive mode")}
860
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("search")} ${import_picocolors4.default.yellow("--tags")} web,api ${import_picocolors4.default.dim("# Search tools by tags")}
861
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("exec")} enact/text/slugify ${import_picocolors4.default.dim("# Execute a tool")}
862
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("mcp")} install ${import_picocolors4.default.yellow("--client")} claude-desktop ${import_picocolors4.default.dim("# Install MCP server")}
863
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("mcp")} install ${import_picocolors4.default.yellow("--client")} goose ${import_picocolors4.default.dim("# Install for Goose AI")}
864
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("env")} set API_KEY --encrypt ${import_picocolors4.default.dim("# Set encrypted env var")}
865
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("sign")} verify my-tool.yaml ${import_picocolors4.default.dim("# Verify tool signatures")}
866
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("publish")} my-tool.yaml ${import_picocolors4.default.dim("# Publish a tool")}
867
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("auth")} login ${import_picocolors4.default.dim("# Login with OAuth")}
868
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("init")} ${import_picocolors4.default.yellow("--minimal")} ${import_picocolors4.default.dim("# Create minimal tool template")}
869
-
870
- ${import_picocolors4.default.bold("More Help:")}
871
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("<command>")} ${import_picocolors4.default.yellow("--help")} ${import_picocolors4.default.dim("# Show command-specific help")}
1037
+ ${import_picocolors3.default.bold("Enact CLI")} ${import_picocolors3.default.dim(`v${version}`)}
1038
+ ${import_picocolors3.default.dim("A CLI tool for managing and publishing Enact tools")}
1039
+
1040
+ ${import_picocolors3.default.bold("Usage:")}
1041
+ ${import_picocolors3.default.cyan("enact")} ${import_picocolors3.default.green("<command>")} [options]
1042
+
1043
+ ${import_picocolors3.default.bold("Commands:")}
1044
+ ${import_picocolors3.default.green("auth")} Manage authentication (login, logout, status, token)
1045
+ ${import_picocolors3.default.green("env")} Manage environment variables (set, get, list, delete)
1046
+ ${import_picocolors3.default.green("exec")} Execute a tool by fetching and running it
1047
+ ${import_picocolors3.default.green("init")} Create a new tool definition
1048
+ ${import_picocolors3.default.green("mcp")} MCP client integration (install, list, status)
1049
+ ${import_picocolors3.default.green("publish")} Publish a tool to the registry
1050
+ ${import_picocolors3.default.green("search")} Search for tools in the registry
1051
+ ${import_picocolors3.default.green("sign")} Sign and verify tools with cryptographic signatures
1052
+ ${import_picocolors3.default.green("remote")} Manage remote servers (add, list, remove)
1053
+ ${import_picocolors3.default.green("user")} User operations (get public key)
1054
+
1055
+ ${import_picocolors3.default.bold("Global Options:")}
1056
+ ${import_picocolors3.default.yellow("--help, -h")} Show help message
1057
+ ${import_picocolors3.default.yellow("--version, -v")} Show version information
1058
+
1059
+ ${import_picocolors3.default.bold("Examples:")}
1060
+ ${import_picocolors3.default.cyan("enact")} ${import_picocolors3.default.dim("# Interactive mode")}
1061
+ ${import_picocolors3.default.cyan("enact")} ${import_picocolors3.default.green("search")} ${import_picocolors3.default.yellow("--tags")} web,api ${import_picocolors3.default.dim("# Search tools by tags")}
1062
+ ${import_picocolors3.default.cyan("enact")} ${import_picocolors3.default.green("exec")} enact/text/slugify ${import_picocolors3.default.dim("# Execute a tool")}
1063
+ ${import_picocolors3.default.cyan("enact")} ${import_picocolors3.default.green("mcp")} install ${import_picocolors3.default.yellow("--client")} claude-desktop ${import_picocolors3.default.dim("# Install MCP server")}
1064
+ ${import_picocolors3.default.cyan("enact")} ${import_picocolors3.default.green("mcp")} install ${import_picocolors3.default.yellow("--client")} goose ${import_picocolors3.default.dim("# Install for Goose AI")}
1065
+ ${import_picocolors3.default.cyan("enact")} ${import_picocolors3.default.green("env")} set API_KEY --encrypt ${import_picocolors3.default.dim("# Set encrypted env var")}
1066
+ ${import_picocolors3.default.cyan("enact")} ${import_picocolors3.default.green("sign")} verify my-tool.yaml ${import_picocolors3.default.dim("# Verify tool signatures")}
1067
+ ${import_picocolors3.default.cyan("enact")} ${import_picocolors3.default.green("publish")} my-tool.yaml ${import_picocolors3.default.dim("# Publish a tool")}
1068
+ ${import_picocolors3.default.cyan("enact")} ${import_picocolors3.default.green("auth")} login ${import_picocolors3.default.dim("# Login with OAuth")}
1069
+ ${import_picocolors3.default.cyan("enact")} ${import_picocolors3.default.green("init")} ${import_picocolors3.default.yellow("--minimal")} ${import_picocolors3.default.dim("# Create minimal tool template")}
1070
+
1071
+ ${import_picocolors3.default.bold("More Help:")}
1072
+ ${import_picocolors3.default.cyan("enact")} ${import_picocolors3.default.green("<command>")} ${import_picocolors3.default.yellow("--help")} ${import_picocolors3.default.dim("# Show command-specific help")}
872
1073
  `);
873
1074
  }
874
- var import_picocolors4, __dirname = "/Users/keithgroves/projects/enact/enact-cli/packages/shared/dist/utils";
1075
+ var import_picocolors3, __dirname = "/Users/keithgroves/projects/enact/enact-cli/packages/shared/dist/utils";
875
1076
  var init_help = __esm(() => {
876
- import_picocolors4 = __toESM(require_picocolors2(), 1);
1077
+ import_picocolors3 = __toESM(require_picocolors2(), 1);
877
1078
  });
878
1079
 
879
1080
  // ../shared/dist/utils/logger.js
@@ -882,29 +1083,29 @@ function setLogLevel(level) {
882
1083
  }
883
1084
  function debug(message) {
884
1085
  if (currentLogLevel <= LogLevel.DEBUG) {
885
- console.error(import_picocolors5.default.dim(`\uD83D\uDD0D ${message}`));
1086
+ console.error(import_picocolors4.default.dim(`\uD83D\uDD0D ${message}`));
886
1087
  }
887
1088
  }
888
1089
  function info(message) {
889
1090
  if (currentLogLevel <= LogLevel.INFO) {
890
- console.error(import_picocolors5.default.blue(`ℹ️ ${message}`));
1091
+ console.error(import_picocolors4.default.blue(`ℹ️ ${message}`));
891
1092
  }
892
1093
  }
893
1094
  function success(message) {
894
1095
  if (currentLogLevel <= LogLevel.SUCCESS) {
895
- console.error(import_picocolors5.default.green(`✓ ${message}`));
1096
+ console.error(import_picocolors4.default.green(`✓ ${message}`));
896
1097
  }
897
1098
  }
898
1099
  function warn(message) {
899
1100
  if (currentLogLevel <= LogLevel.WARN) {
900
- console.error(import_picocolors5.default.yellow(`⚠️ ${message}`));
1101
+ console.error(import_picocolors4.default.yellow(`⚠️ ${message}`));
901
1102
  }
902
1103
  }
903
1104
  function error(message, details) {
904
1105
  if (currentLogLevel <= LogLevel.ERROR) {
905
- console.error(import_picocolors5.default.red(`✗ Error: ${message}`));
1106
+ console.error(import_picocolors4.default.red(`✗ Error: ${message}`));
906
1107
  if (details && currentLogLevel === LogLevel.DEBUG) {
907
- console.error(import_picocolors5.default.dim("Details:"));
1108
+ console.error(import_picocolors4.default.dim("Details:"));
908
1109
  console.error(details);
909
1110
  }
910
1111
  }
@@ -918,9 +1119,9 @@ function table(data, columns) {
918
1119
  }
919
1120
  }
920
1121
  }
921
- var import_picocolors5, LogLevel, currentLogLevel;
1122
+ var import_picocolors4, LogLevel, currentLogLevel;
922
1123
  var init_logger = __esm(() => {
923
- import_picocolors5 = __toESM(require_picocolors2(), 1);
1124
+ import_picocolors4 = __toESM(require_picocolors2(), 1);
924
1125
  (function(LogLevel2) {
925
1126
  LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
926
1127
  LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
@@ -1156,7 +1357,7 @@ function parseTimeout(timeout) {
1156
1357
 
1157
1358
  // ../shared/dist/utils/version.js
1158
1359
  import { readFileSync as readFileSync2 } from "fs";
1159
- import { join as join5, dirname } from "path";
1360
+ import { join as join4, dirname } from "path";
1160
1361
  import { fileURLToPath } from "url";
1161
1362
  function showVersion() {
1162
1363
  let version = "0.0.1-dev";
@@ -1166,7 +1367,7 @@ function showVersion() {
1166
1367
  } else {
1167
1368
  const currentFile = typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url);
1168
1369
  const sharedDir = dirname(dirname(dirname(currentFile)));
1169
- const packageJsonPath = join5(sharedDir, "package.json");
1370
+ const packageJsonPath = join4(sharedDir, "package.json");
1170
1371
  const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf8"));
1171
1372
  version = packageJson.version;
1172
1373
  }
@@ -1175,13 +1376,13 @@ function showVersion() {
1175
1376
  }
1176
1377
  const versionText = `v${version}`;
1177
1378
  console.error(`
1178
- ${import_picocolors6.default.bold("Enact CLI")} ${import_picocolors6.default.cyan(versionText)}
1179
- ${import_picocolors6.default.dim("A tool to create and publish enact documents.")}
1379
+ ${import_picocolors5.default.bold("Enact CLI")} ${import_picocolors5.default.cyan(versionText)}
1380
+ ${import_picocolors5.default.dim("A tool to create and publish enact documents.")}
1180
1381
  `);
1181
1382
  }
1182
- var import_picocolors6, __filename = "/Users/keithgroves/projects/enact/enact-cli/packages/shared/dist/utils/version.js";
1383
+ var import_picocolors5, __filename = "/Users/keithgroves/projects/enact/enact-cli/packages/shared/dist/utils/version.js";
1183
1384
  var init_version = __esm(() => {
1184
- import_picocolors6 = __toESM(require_picocolors2(), 1);
1385
+ import_picocolors5 = __toESM(require_picocolors2(), 1);
1185
1386
  });
1186
1387
 
1187
1388
  // ../shared/dist/utils/index.js
@@ -1198,23 +1399,34 @@ __export(exports_utils, {
1198
1399
  showVersion: () => showVersion,
1199
1400
  showHelp: () => showHelp,
1200
1401
  setLogLevel: () => setLogLevel,
1402
+ setFrontendUrl: () => setFrontendUrl,
1201
1403
  setDefaultUrl: () => setDefaultUrl,
1404
+ setApiUrl: () => setApiUrl,
1202
1405
  resolveToolEnvironmentVariables: () => resolveToolEnvironmentVariables,
1406
+ resetUrls: () => resetUrls,
1407
+ removeTrustedKey: () => removeTrustedKey,
1203
1408
  readConfig: () => readConfig,
1204
1409
  parseTimeout: () => parseTimeout,
1205
1410
  loadPackageEnvironmentVariables: () => loadPackageEnvironmentVariables,
1411
+ isKeyTrusted: () => isKeyTrusted,
1206
1412
  info: () => info,
1207
1413
  globalMonitor: () => globalMonitor,
1208
1414
  getWebServerUrl: () => getWebServerUrl,
1415
+ getUrlConfig: () => getUrlConfig,
1416
+ getTrustedKeys: () => getTrustedKeys,
1417
+ getTrustedKey: () => getTrustedKey,
1209
1418
  getPackageEnvironmentVariables: () => getPackageEnvironmentVariables,
1210
1419
  getHistory: () => getHistory,
1420
+ getFrontendUrl: () => getFrontendUrl,
1211
1421
  getDefaultUrl: () => getDefaultUrl,
1422
+ getApiUrl: () => getApiUrl,
1212
1423
  generateConfigLink: () => generateConfigLink,
1213
1424
  extractPackageNamespace: () => extractPackageNamespace,
1214
1425
  error: () => error,
1215
1426
  ensureSilent: () => ensureSilent,
1216
1427
  ensureConfig: () => ensureConfig,
1217
1428
  debug: () => debug,
1429
+ addTrustedKey: () => addTrustedKey,
1218
1430
  addToHistory: () => addToHistory,
1219
1431
  McpSilentOperationMonitor: () => McpSilentOperationMonitor,
1220
1432
  LogLevel: () => LogLevel
@@ -214303,11 +214515,11 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
214303
214515
  };
214304
214516
 
214305
214517
  // src/commands/auth.ts
214306
- var import_picocolors3 = __toESM(require_picocolors(), 1);
214307
- import { existsSync } from "fs";
214308
- import { readFile, writeFile, mkdir } from "fs/promises";
214309
- import { join } from "path";
214310
- import { homedir } from "os";
214518
+ var import_picocolors6 = __toESM(require_picocolors(), 1);
214519
+ import { existsSync as existsSync3 } from "fs";
214520
+ import { readFile as readFile3, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
214521
+ import { join as join5 } from "path";
214522
+ import { homedir as homedir3 } from "os";
214311
214523
  import { createServer } from "http";
214312
214524
  import { parse } from "url";
214313
214525
  import { randomBytes, createHash } from "crypto";
@@ -214315,11 +214527,18 @@ import { exec } from "child_process";
214315
214527
  import { promisify } from "util";
214316
214528
 
214317
214529
  // ../shared/dist/api/enact-api.js
214530
+ init_config();
214531
+
214318
214532
  class EnactApiClient {
214319
- constructor(baseUrl = "https://enact.tools", supabaseUrl = "https://xjnhhxwxovjifdxdwzih.supabase.co") {
214533
+ constructor(baseUrl, supabaseUrl) {
214320
214534
  this.baseUrl = baseUrl.replace(/\/$/, "");
214321
214535
  this.supabaseUrl = supabaseUrl.replace(/\/$/, "");
214322
214536
  }
214537
+ static async create(baseUrl, supabaseUrl) {
214538
+ const frontendUrl = baseUrl || await getFrontendUrl();
214539
+ const apiUrl = supabaseUrl || await getApiUrl();
214540
+ return new EnactApiClient(frontendUrl, apiUrl);
214541
+ }
214323
214542
  async makeRequest(endpoint, options = {}, token, tokenType = "jwt") {
214324
214543
  const url = endpoint.startsWith("http") ? endpoint : `${this.supabaseUrl}${endpoint}`;
214325
214544
  const headers = {
@@ -214601,7 +214820,7 @@ class EnactApiClient {
214601
214820
  };
214602
214821
  }
214603
214822
  }
214604
- var enactApi = new EnactApiClient;
214823
+ var enactApi = new EnactApiClient("https://enact.tools", "https://xjnhhxwxovjifdxdwzih.supabase.co");
214605
214824
 
214606
214825
  class EnactApiError extends Error {
214607
214826
  constructor(message, statusCode, endpoint) {
@@ -214612,14 +214831,17 @@ class EnactApiError extends Error {
214612
214831
  }
214613
214832
  }
214614
214833
  function createEnactApiClient(baseUrl, supabaseUrl) {
214615
- return new EnactApiClient(baseUrl, supabaseUrl);
214834
+ const defaultFrontend = "https://enact.tools";
214835
+ const defaultApi = "https://xjnhhxwxovjifdxdwzih.supabase.co";
214836
+ return new EnactApiClient(baseUrl || defaultFrontend, supabaseUrl || defaultApi);
214616
214837
  }
214617
214838
  // src/commands/auth.ts
214839
+ init_utils();
214618
214840
  var execAsync = promisify(exec);
214619
- var CONFIG_DIR = join(homedir(), ".enact");
214620
- var AUTH_FILE = join(CONFIG_DIR, "auth.json");
214621
- var DEFAULT_SERVER = "https://enact.tools";
214841
+ var CONFIG_DIR3 = join5(homedir3(), ".enact");
214842
+ var AUTH_FILE = join5(CONFIG_DIR3, "auth.json");
214622
214843
  async function handleAuthCommand(args, options) {
214844
+ const defaultServer = await getFrontendUrl();
214623
214845
  if (options.help || !args[0]) {
214624
214846
  console.error(`
214625
214847
  Usage: enact auth <subcommand> [options]
@@ -214634,16 +214856,16 @@ Subcommands:
214634
214856
 
214635
214857
  Options:
214636
214858
  --help, -h Show this help message
214637
- --server <url> Specify the enact server URL (default: ${DEFAULT_SERVER})
214859
+ --server <url> Specify the enact server URL (default: ${defaultServer})
214638
214860
  --port <number> Local callback port for OAuth (default: 8080)
214639
214861
  `);
214640
214862
  return;
214641
214863
  }
214642
214864
  const subCommand = args[0];
214643
- const serverUrl = options.server || DEFAULT_SERVER;
214865
+ const serverUrl = options.server || defaultServer;
214644
214866
  const callbackPort = options.port || 8080;
214645
214867
  await ensureAuthConfig();
214646
- Ie(import_picocolors3.default.bgBlue(import_picocolors3.default.white(" Enact Authentication ")));
214868
+ Ie(import_picocolors6.default.bgBlue(import_picocolors6.default.white(" Enact Authentication ")));
214647
214869
  switch (subCommand) {
214648
214870
  case "login": {
214649
214871
  await handleLogin(serverUrl, callbackPort);
@@ -214662,7 +214884,7 @@ Options:
214662
214884
  break;
214663
214885
  }
214664
214886
  default:
214665
- Se(import_picocolors3.default.red(`✗ Unknown auth subcommand "${subCommand}"`));
214887
+ Se(import_picocolors6.default.red(`✗ Unknown auth subcommand "${subCommand}"`));
214666
214888
  return;
214667
214889
  }
214668
214890
  }
@@ -214674,7 +214896,7 @@ async function handleLogin(serverUrl, callbackPort) {
214674
214896
  message: "You are already authenticated. Continue with new login?"
214675
214897
  });
214676
214898
  if (!useExisting) {
214677
- Se(import_picocolors3.default.yellow("Login cancelled"));
214899
+ Se(import_picocolors6.default.yellow("Login cancelled"));
214678
214900
  return;
214679
214901
  }
214680
214902
  }
@@ -214696,14 +214918,14 @@ async function handleLogin(serverUrl, callbackPort) {
214696
214918
  try {
214697
214919
  server2 = await startCallbackServerWithFallback(callbackPort, serverUrl, codeVerifier, state);
214698
214920
  s.stop("OAuth server started");
214699
- } catch (error) {
214921
+ } catch (error2) {
214700
214922
  s.stop("OAuth server could not start, using manual mode");
214701
214923
  server2 = null;
214702
214924
  }
214703
214925
  Me(`Opening browser to: ${authUrl}`, "OAuth Login");
214704
214926
  try {
214705
214927
  await openBrowser(authUrl);
214706
- } catch (error) {
214928
+ } catch (error2) {
214707
214929
  Me(`Please open this URL in your browser: ${authUrl}`, "Manual Browser Open Required");
214708
214930
  }
214709
214931
  if (server2) {
@@ -214730,14 +214952,14 @@ async function handleLogin(serverUrl, callbackPort) {
214730
214952
  }
214731
214953
  });
214732
214954
  if (typeof authCode === "symbol") {
214733
- Se(import_picocolors3.default.yellow("Login cancelled"));
214955
+ Se(import_picocolors6.default.yellow("Login cancelled"));
214734
214956
  return;
214735
214957
  }
214736
214958
  await exchangeCodeForToken(authCode, redirectUri, codeVerifier, serverUrl);
214737
214959
  }
214738
- Se(import_picocolors3.default.green("✓ Successfully authenticated with Enact!"));
214739
- } catch (error) {
214740
- Se(import_picocolors3.default.red(`✗ Login failed: ${error.message}`));
214960
+ Se(import_picocolors6.default.green("✓ Successfully authenticated with Enact!"));
214961
+ } catch (error2) {
214962
+ Se(import_picocolors6.default.red(`✗ Login failed: ${error2.message}`));
214741
214963
  } finally {
214742
214964
  process.exit(0);
214743
214965
  }
@@ -214751,13 +214973,13 @@ async function startCallbackServerWithFallback(port, serverUrl, codeVerifier, st
214751
214973
  const {
214752
214974
  code,
214753
214975
  state: returnedState,
214754
- error,
214976
+ error: error2,
214755
214977
  error_description
214756
214978
  } = parsedUrl.query;
214757
214979
  res.setHeader("Access-Control-Allow-Origin", "*");
214758
214980
  res.setHeader("Content-Type", "text/html");
214759
- if (error) {
214760
- const errorMsg = error_description || error;
214981
+ if (error2) {
214982
+ const errorMsg = error_description || error2;
214761
214983
  res.writeHead(400);
214762
214984
  res.end(`
214763
214985
  <html>
@@ -214816,19 +215038,19 @@ async function startCallbackServerWithFallback(port, serverUrl, codeVerifier, st
214816
215038
  `);
214817
215039
  server2.close();
214818
215040
  server2.emit("authComplete");
214819
- } catch (error2) {
214820
- console.error("Token exchange error:", error2);
215041
+ } catch (error3) {
215042
+ console.error("Token exchange error:", error3);
214821
215043
  res.writeHead(500);
214822
215044
  res.end(`
214823
215045
  <html>
214824
215046
  <body style="font-family: Arial, sans-serif; text-align: center; padding: 50px;">
214825
215047
  <h1 style="color: red;">❌ Authentication Failed</h1>
214826
- <p><strong>Error:</strong> ${error2.message}</p>
215048
+ <p><strong>Error:</strong> ${error3.message}</p>
214827
215049
  <p>You can close this window and check your terminal for more details.</p>
214828
215050
  </body>
214829
215051
  </html>
214830
215052
  `);
214831
- server2.emit("authError", error2);
215053
+ server2.emit("authError", error3);
214832
215054
  }
214833
215055
  } else {
214834
215056
  res.writeHead(404);
@@ -214847,11 +215069,11 @@ async function startCallbackServerWithFallback(port, serverUrl, codeVerifier, st
214847
215069
  console.error(`OAuth callback server listening on http://localhost:${port}`);
214848
215070
  resolve(server2);
214849
215071
  });
214850
- server2.on("error", (error) => {
214851
- if (error.code === "EADDRINUSE") {
215072
+ server2.on("error", (error2) => {
215073
+ if (error2.code === "EADDRINUSE") {
214852
215074
  reject(new Error(`Port ${port} is already in use`));
214853
215075
  } else {
214854
- reject(error);
215076
+ reject(error2);
214855
215077
  }
214856
215078
  });
214857
215079
  });
@@ -214880,11 +215102,11 @@ async function exchangeCodeForToken(code, redirectUri, codeVerifier, serverUrl)
214880
215102
  server: serverUrl
214881
215103
  });
214882
215104
  console.error("✓ Token stored successfully");
214883
- } catch (error) {
214884
- if (error instanceof EnactApiError) {
214885
- throw new Error(`Token exchange failed: ${error.message}`);
215105
+ } catch (error2) {
215106
+ if (error2 instanceof EnactApiError) {
215107
+ throw new Error(`Token exchange failed: ${error2.message}`);
214886
215108
  }
214887
- throw error;
215109
+ throw error2;
214888
215110
  }
214889
215111
  }
214890
215112
  async function handleLogout() {
@@ -214898,45 +215120,45 @@ async function handleLogout() {
214898
215120
  message: "Are you sure you want to logout?"
214899
215121
  });
214900
215122
  if (!shouldLogout) {
214901
- Se(import_picocolors3.default.yellow("Logout cancelled"));
215123
+ Se(import_picocolors6.default.yellow("Logout cancelled"));
214902
215124
  return;
214903
215125
  }
214904
215126
  const s = Y2();
214905
215127
  s.start("Logging out...");
214906
215128
  await writeAuthConfig({});
214907
215129
  s.stop("Logged out successfully");
214908
- Se(import_picocolors3.default.green("✓ You have been logged out"));
215130
+ Se(import_picocolors6.default.green("✓ You have been logged out"));
214909
215131
  }
214910
215132
  async function handleStatus() {
214911
215133
  const currentAuth = await readAuthConfig();
214912
215134
  if (!currentAuth.token) {
214913
215135
  Me("Not authenticated", "Status");
214914
- Se(import_picocolors3.default.yellow('Run "enact auth login" to authenticate'));
215136
+ Se(import_picocolors6.default.yellow('Run "enact auth login" to authenticate'));
214915
215137
  return;
214916
215138
  }
214917
215139
  const isExpired = currentAuth.expiresAt && new Date(currentAuth.expiresAt) <= new Date;
214918
215140
  if (isExpired) {
214919
215141
  Me("Token has expired", "Status");
214920
- Se(import_picocolors3.default.yellow('Run "enact auth login" to re-authenticate'));
215142
+ Se(import_picocolors6.default.yellow('Run "enact auth login" to re-authenticate'));
214921
215143
  return;
214922
215144
  }
214923
215145
  const expiresIn = currentAuth.expiresAt ? Math.round((new Date(currentAuth.expiresAt).getTime() - Date.now()) / 1000 / 60 / 60) : "unknown";
214924
215146
  Me(`Authenticated
214925
215147
  Expires: ${currentAuth.expiresAt || "unknown"}
214926
215148
  Expires in: ${expiresIn} hours`, "Status");
214927
- Se(import_picocolors3.default.green("✓ Authentication valid"));
215149
+ Se(import_picocolors6.default.green("✓ Authentication valid"));
214928
215150
  }
214929
215151
  async function handleShowToken() {
214930
215152
  const currentAuth = await readAuthConfig();
214931
215153
  if (!currentAuth.token) {
214932
215154
  Me("Not authenticated", "Status");
214933
- Se(import_picocolors3.default.yellow('Run "enact auth login" to authenticate'));
215155
+ Se(import_picocolors6.default.yellow('Run "enact auth login" to authenticate'));
214934
215156
  return;
214935
215157
  }
214936
215158
  const isExpired = currentAuth.expiresAt && new Date(currentAuth.expiresAt) <= new Date;
214937
215159
  if (isExpired) {
214938
215160
  Me("Token has expired", "Status");
214939
- Se(import_picocolors3.default.yellow('Run "enact auth login" to re-authenticate'));
215161
+ Se(import_picocolors6.default.yellow('Run "enact auth login" to re-authenticate'));
214940
215162
  return;
214941
215163
  }
214942
215164
  const maskedToken = currentAuth.token.length > 12 ? `${currentAuth.token.slice(0, 8)}...${currentAuth.token.slice(-4)}` : currentAuth.token;
@@ -214971,23 +215193,23 @@ async function openBrowser(url) {
214971
215193
  await execAsync(command);
214972
215194
  }
214973
215195
  async function ensureAuthConfig() {
214974
- if (!existsSync(CONFIG_DIR)) {
214975
- await mkdir(CONFIG_DIR, { recursive: true });
215196
+ if (!existsSync3(CONFIG_DIR3)) {
215197
+ await mkdir2(CONFIG_DIR3, { recursive: true });
214976
215198
  }
214977
- if (!existsSync(AUTH_FILE)) {
215199
+ if (!existsSync3(AUTH_FILE)) {
214978
215200
  await writeAuthConfig({});
214979
215201
  }
214980
215202
  }
214981
215203
  async function readAuthConfig() {
214982
215204
  try {
214983
- const text = await readFile(AUTH_FILE, "utf8");
215205
+ const text = await readFile3(AUTH_FILE, "utf8");
214984
215206
  return JSON.parse(text);
214985
215207
  } catch (e2) {
214986
215208
  return {};
214987
215209
  }
214988
215210
  }
214989
- async function writeAuthConfig(config) {
214990
- await writeFile(AUTH_FILE, JSON.stringify(config, null, 2), "utf8");
215211
+ async function writeAuthConfig(config2) {
215212
+ await writeFile2(AUTH_FILE, JSON.stringify(config2, null, 2), "utf8");
214991
215213
  }
214992
215214
  async function getCurrentToken() {
214993
215215
  try {
@@ -214999,7 +215221,7 @@ async function getCurrentToken() {
214999
215221
  return null;
215000
215222
  }
215001
215223
  return auth.token;
215002
- } catch (error) {
215224
+ } catch (error2) {
215003
215225
  return null;
215004
215226
  }
215005
215227
  }
@@ -216537,6 +216759,7 @@ async function checkMcpServerInstalled(client, serverType = "main") {
216537
216759
 
216538
216760
  // src/commands/config.ts
216539
216761
  var import_picocolors12 = __toESM(require_picocolors(), 1);
216762
+ init_utils();
216540
216763
  import fs from "fs/promises";
216541
216764
  import path from "path";
216542
216765
  import { existsSync as existsSync8 } from "fs";
@@ -216724,6 +216947,13 @@ function showConfigHelp() {
216724
216947
  console.log(" get <key> Get specific configuration value");
216725
216948
  console.log(" set <key> <value> Set configuration value");
216726
216949
  console.log(" reset Reset to default configuration");
216950
+ console.log(" urls Show current URL configuration");
216951
+ console.log(" set-frontend-url Set frontend URL (for OAuth, registry)");
216952
+ console.log(" set-api-url Set API URL (for backend calls)");
216953
+ console.log(" reset-urls Reset URLs to defaults");
216954
+ console.log(" keys Show trusted public keys");
216955
+ console.log(" add-key Add a trusted public key");
216956
+ console.log(" remove-key <id> Remove a trusted public key");
216727
216957
  console.log(`
216728
216958
  Options:`);
216729
216959
  console.log(" --global Use global configuration (~/.enact-config.json)");
@@ -216744,6 +216974,160 @@ Examples:`);
216744
216974
  console.log(" enact config set daggerOptions.baseImage ubuntu:22.04");
216745
216975
  console.log(" enact config get executionProvider");
216746
216976
  console.log(" enact config list --global");
216977
+ console.log(" enact config urls");
216978
+ console.log(" enact config set-frontend-url https://my-instance.example.com");
216979
+ console.log(" enact config set-api-url https://api.example.com");
216980
+ console.log(" enact config keys");
216981
+ console.log(" enact config add-key");
216982
+ console.log(" enact config remove-key my-org-key");
216983
+ }
216984
+ async function showUrls() {
216985
+ const urlConfig = await getUrlConfig();
216986
+ console.log(import_picocolors12.default.cyan(`
216987
+ \uD83C\uDF10 URL Configuration:
216988
+ `));
216989
+ console.log(import_picocolors12.default.white("Frontend URL:"));
216990
+ console.log(` ${import_picocolors12.default.green(urlConfig.frontend.value)} ${import_picocolors12.default.gray(`(${urlConfig.frontend.source})`)}`);
216991
+ console.log(import_picocolors12.default.white("API URL:"));
216992
+ console.log(` ${import_picocolors12.default.green(urlConfig.api.value)} ${import_picocolors12.default.gray(`(${urlConfig.api.source})`)}`);
216993
+ console.log(import_picocolors12.default.gray(`
216994
+ Sources: default < config < environment`));
216995
+ }
216996
+ async function setUrl(type, url) {
216997
+ try {
216998
+ if (type === "frontend") {
216999
+ await setFrontendUrl(url);
217000
+ console.log(import_picocolors12.default.green(`✅ Frontend URL set to: ${url}`));
217001
+ } else {
217002
+ await setApiUrl(url);
217003
+ console.log(import_picocolors12.default.green(`✅ API URL set to: ${url}`));
217004
+ }
217005
+ console.log(import_picocolors12.default.gray("Use 'enact config urls' to view current configuration"));
217006
+ } catch (error2) {
217007
+ console.error(import_picocolors12.default.red(`Error setting ${type} URL: ${error2}`));
217008
+ process.exit(1);
217009
+ }
217010
+ }
217011
+ async function resetUrlsConfig() {
217012
+ try {
217013
+ await resetUrls();
217014
+ console.log(import_picocolors12.default.green("✅ URLs reset to defaults"));
217015
+ await showUrls();
217016
+ } catch (error2) {
217017
+ console.error(import_picocolors12.default.red(`Error resetting URLs: ${error2}`));
217018
+ process.exit(1);
217019
+ }
217020
+ }
217021
+ async function showTrustedKeys() {
217022
+ try {
217023
+ const keys = await getTrustedKeys();
217024
+ console.log(import_picocolors12.default.cyan(`
217025
+ \uD83D\uDD10 Trusted Keys:
217026
+ `));
217027
+ if (keys.length === 0) {
217028
+ console.log(import_picocolors12.default.gray("No trusted keys found"));
217029
+ return;
217030
+ }
217031
+ for (const key of keys) {
217032
+ const sourceColor = key.source === "default" ? import_picocolors12.default.blue : key.source === "organization" ? import_picocolors12.default.yellow : import_picocolors12.default.green;
217033
+ console.log(import_picocolors12.default.white(`${key.name} (${key.id})`));
217034
+ console.log(` ${sourceColor(`[${key.source}]`)} ${import_picocolors12.default.gray(`Added: ${new Date(key.addedAt).toLocaleDateString()}`)}`);
217035
+ if (key.description) {
217036
+ console.log(` ${import_picocolors12.default.gray(key.description)}`);
217037
+ }
217038
+ console.log(` ${import_picocolors12.default.gray(`Key: ${key.publicKey.substring(0, 50)}...`)}`);
217039
+ console.log();
217040
+ }
217041
+ } catch (error2) {
217042
+ console.error(import_picocolors12.default.red(`Error reading trusted keys: ${error2}`));
217043
+ process.exit(1);
217044
+ }
217045
+ }
217046
+ async function addTrustedKeyInteractive() {
217047
+ try {
217048
+ console.log(import_picocolors12.default.cyan(`
217049
+ \uD83D\uDD10 Add Trusted Key
217050
+ `));
217051
+ const id = await he({
217052
+ message: "Key ID (unique identifier):",
217053
+ placeholder: "my-org-key",
217054
+ validate: (value) => {
217055
+ if (!value)
217056
+ return "ID is required";
217057
+ if (!/^[a-zA-Z0-9-_]+$/.test(value))
217058
+ return "ID must contain only letters, numbers, hyphens, and underscores";
217059
+ }
217060
+ });
217061
+ const name = await he({
217062
+ message: "Key name (display name):",
217063
+ placeholder: "My Organization Key",
217064
+ validate: (value) => value ? undefined : "Name is required"
217065
+ });
217066
+ const description = await he({
217067
+ message: "Description (optional):",
217068
+ placeholder: "Key for verifying my organization's tools"
217069
+ });
217070
+ const publicKey = await he({
217071
+ message: "Public key (PEM format):",
217072
+ placeholder: "-----BEGIN PUBLIC KEY-----\\n...\\n-----END PUBLIC KEY-----",
217073
+ validate: (value) => {
217074
+ if (!value)
217075
+ return "Public key is required";
217076
+ if (!value.includes("BEGIN PUBLIC KEY"))
217077
+ return "Invalid PEM format";
217078
+ }
217079
+ });
217080
+ const source = await ve({
217081
+ message: "Key source:",
217082
+ options: [
217083
+ { value: "user", label: "Personal key" },
217084
+ { value: "organization", label: "Organization key" }
217085
+ ]
217086
+ });
217087
+ const keyData = {
217088
+ id,
217089
+ name,
217090
+ publicKey: publicKey.replace(/\\n/g, `
217091
+ `),
217092
+ description: description || undefined,
217093
+ source
217094
+ };
217095
+ await addTrustedKey(keyData);
217096
+ console.log(import_picocolors12.default.green(`✅ Trusted key '${keyData.name}' added successfully`));
217097
+ } catch (error2) {
217098
+ console.error(import_picocolors12.default.red(`Error adding trusted key: ${error2}`));
217099
+ process.exit(1);
217100
+ }
217101
+ }
217102
+ async function removeTrustedKeyById(keyId) {
217103
+ try {
217104
+ const key = await getTrustedKey(keyId);
217105
+ if (!key) {
217106
+ console.error(import_picocolors12.default.red(`Trusted key '${keyId}' not found`));
217107
+ process.exit(1);
217108
+ }
217109
+ let confirmMessage = `Remove trusted key '${key.name}' (${keyId})?`;
217110
+ if (keyId === "enact-protocol-official") {
217111
+ confirmMessage = `${import_picocolors12.default.yellow("⚠️ Warning:")} You are about to remove the default Enact Protocol key. This may prevent verification of official tools.
217112
+
217113
+ Remove trusted key '${key.name}' (${keyId})?`;
217114
+ }
217115
+ const confirm = await ye({
217116
+ message: confirmMessage
217117
+ });
217118
+ if (!confirm) {
217119
+ console.log(import_picocolors12.default.yellow("Operation cancelled"));
217120
+ return;
217121
+ }
217122
+ await removeTrustedKey(keyId);
217123
+ console.log(import_picocolors12.default.green(`✅ Trusted key '${key.name}' removed successfully`));
217124
+ if (keyId === "enact-protocol-official") {
217125
+ console.log(import_picocolors12.default.yellow("\uD83D\uDCA1 You can re-add the Enact Protocol key anytime with 'enact config add-key'"));
217126
+ }
217127
+ } catch (error2) {
217128
+ console.error(import_picocolors12.default.red(`Error removing trusted key: ${error2}`));
217129
+ process.exit(1);
217130
+ }
216747
217131
  }
216748
217132
  async function handleConfigCommand(args, options) {
216749
217133
  if (options.help) {
@@ -216778,6 +217162,42 @@ async function handleConfigCommand(args, options) {
216778
217162
  case "reset":
216779
217163
  await resetConfig(global2);
216780
217164
  break;
217165
+ case "urls":
217166
+ await showUrls();
217167
+ break;
217168
+ case "set-frontend-url":
217169
+ if (!args[1]) {
217170
+ console.error(import_picocolors12.default.red("Error: Missing URL"));
217171
+ console.log("Usage: enact config set-frontend-url <url>");
217172
+ process.exit(1);
217173
+ }
217174
+ await setUrl("frontend", args[1]);
217175
+ break;
217176
+ case "set-api-url":
217177
+ if (!args[1]) {
217178
+ console.error(import_picocolors12.default.red("Error: Missing URL"));
217179
+ console.log("Usage: enact config set-api-url <url>");
217180
+ process.exit(1);
217181
+ }
217182
+ await setUrl("api", args[1]);
217183
+ break;
217184
+ case "reset-urls":
217185
+ await resetUrlsConfig();
217186
+ break;
217187
+ case "keys":
217188
+ await showTrustedKeys();
217189
+ break;
217190
+ case "add-key":
217191
+ await addTrustedKeyInteractive();
217192
+ break;
217193
+ case "remove-key":
217194
+ if (!args[1]) {
217195
+ console.error(import_picocolors12.default.red("Error: Missing key ID"));
217196
+ console.log("Usage: enact config remove-key <key-id>");
217197
+ process.exit(1);
217198
+ }
217199
+ await removeTrustedKeyById(args[1]);
217200
+ break;
216781
217201
  default:
216782
217202
  if (!subcommand) {
216783
217203
  await interactiveConfig(global2);
@@ -226299,37 +226719,6 @@ class DaggerExecutionProvider extends ExecutionProvider {
226299
226719
  process.exit(1);
226300
226720
  }
226301
226721
  }
226302
- forceCleanup() {
226303
- if (this.isShuttingDown)
226304
- return;
226305
- try {
226306
- logger_default.info("\uD83D\uDD04 Force cleaning up Dagger engines...");
226307
- const result = spawnSync("docker", [
226308
- "ps",
226309
- "--all",
226310
- "--filter",
226311
- "name=dagger-engine",
226312
- "--format",
226313
- "{{.Names}}"
226314
- ], {
226315
- encoding: "utf8",
226316
- timeout: 5000
226317
- });
226318
- if (result.stdout) {
226319
- const names = result.stdout.trim().split(`
226320
- `).filter((n) => n.trim());
226321
- if (names.length > 0) {
226322
- logger_default.info(`Found ${names.length} engine containers, force removing...`);
226323
- for (const name of names) {
226324
- spawnSync("docker", ["rm", "-f", name.trim()], { timeout: 3000 });
226325
- }
226326
- logger_default.info("✅ Force cleanup completed");
226327
- }
226328
- }
226329
- } catch (error2) {
226330
- logger_default.debug("Force cleanup failed (this is usually fine):", error2);
226331
- }
226332
- }
226333
226722
  getEngineStatus() {
226334
226723
  return {
226335
226724
  health: { ...this.engineHealth },
@@ -229063,6 +229452,8 @@ class SigningService {
229063
229452
  }
229064
229453
 
229065
229454
  // ../shared/dist/core/EnactCore.js
229455
+ init_config();
229456
+
229066
229457
  class EnactCore {
229067
229458
  constructor(options = {}) {
229068
229459
  this.options = {
@@ -229075,6 +229466,15 @@ class EnactCore {
229075
229466
  this.apiClient = new EnactApiClient(this.options.apiUrl, this.options.supabaseUrl);
229076
229467
  this.executionProvider = this.createExecutionProvider();
229077
229468
  }
229469
+ static async create(options = {}) {
229470
+ const frontendUrl = options.apiUrl || await getFrontendUrl();
229471
+ const apiUrl = options.supabaseUrl || await getApiUrl();
229472
+ return new EnactCore({
229473
+ ...options,
229474
+ apiUrl: frontendUrl,
229475
+ supabaseUrl: apiUrl
229476
+ });
229477
+ }
229078
229478
  setAuthToken(token) {
229079
229479
  this.options.authToken = token;
229080
229480
  }
@@ -229628,7 +230028,7 @@ ${import_picocolors13.default.bold("EXAMPLES:")}
229628
230028
  author,
229629
230029
  format
229630
230030
  };
229631
- const apiClient = new EnactApiClient("https://enact.tools", "https://xjnhhxwxovjifdxdwzih.supabase.co");
230031
+ const apiClient = await EnactApiClient.create();
229632
230032
  const searchResults = await apiClient.searchTools(searchOptions);
229633
230033
  const results = [];
229634
230034
  for (const result of searchResults) {
@@ -229886,7 +230286,7 @@ Examples:
229886
230286
  toolDefinition = await loadLocalTool(toolIdentifier);
229887
230287
  spinner.stop("Local tool definition loaded");
229888
230288
  } else {
229889
- const apiClient = new EnactApiClient("https://enact.tools", "https://xjnhhxwxovjifdxdwzih.supabase.co");
230289
+ const apiClient = await EnactApiClient.create();
229890
230290
  toolDefinition = await apiClient.getTool(toolIdentifier);
229891
230291
  spinner.stop("Tool definition fetched");
229892
230292
  }
@@ -230114,7 +230514,7 @@ Environment variables:`));
230114
230514
  }
230115
230515
  if (!isLocalFile) {
230116
230516
  try {
230117
- const apiClient = new EnactApiClient("https://enact.tools", "https://xjnhhxwxovjifdxdwzih.supabase.co");
230517
+ const apiClient = await EnactApiClient.create();
230118
230518
  await apiClient.logToolUsage(toolIdentifier, {
230119
230519
  action: "execute",
230120
230520
  metadata: {
@@ -230217,7 +230617,7 @@ ${import_picocolors13.default.bold("EXAMPLES:")}
230217
230617
  Ie(import_picocolors13.default.bgBlue(import_picocolors13.default.black(" Getting Tool Info ")));
230218
230618
  const spinner = Y2();
230219
230619
  spinner.start(`Fetching ${toolName}...`);
230220
- const apiClient = new EnactApiClient("https://enact.tools", "https://xjnhhxwxovjifdxdwzih.supabase.co");
230620
+ const apiClient = await EnactApiClient.create();
230221
230621
  const toolDefinition = await apiClient.getTool(toolName);
230222
230622
  if (!toolDefinition) {
230223
230623
  spinner.stop("Tool not found");