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