@enactprotocol/cli 1.2.2 → 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 +832 -230
  2. package/dist/index.js.bak +832 -230
  3. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -29,7 +29,7 @@ var __export = (target, all) => {
29
29
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
30
30
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
31
31
 
32
- // ../../node_modules/picocolors/picocolors.js
32
+ // node_modules/picocolors/picocolors.js
33
33
  var require_picocolors = __commonJS((exports, module) => {
34
34
  var p = process || {};
35
35
  var argv = p.argv || [];
@@ -99,7 +99,7 @@ var require_picocolors = __commonJS((exports, module) => {
99
99
  module.exports.createColors = createColors;
100
100
  });
101
101
 
102
- // ../../node_modules/sisteransi/src/index.js
102
+ // node_modules/sisteransi/src/index.js
103
103
  var require_src = __commonJS((exports, module) => {
104
104
  var ESC = "\x1B";
105
105
  var CSI = `${ESC}[`;
@@ -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,19 +942,89 @@ 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
 
952
+ // ../../node_modules/picocolors/picocolors.js
953
+ var require_picocolors2 = __commonJS((exports, module) => {
954
+ var p2 = process || {};
955
+ var argv = p2.argv || [];
956
+ var env = p2.env || {};
957
+ var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p2.platform === "win32" || (p2.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
958
+ var formatter = (open, close, replace = open) => (input) => {
959
+ let string = "" + input, index = string.indexOf(close, open.length);
960
+ return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
961
+ };
962
+ var replaceClose = (string, close, replace, index) => {
963
+ let result = "", cursor = 0;
964
+ do {
965
+ result += string.substring(cursor, index) + replace;
966
+ cursor = index + close.length;
967
+ index = string.indexOf(close, cursor);
968
+ } while (~index);
969
+ return result + string.substring(cursor);
970
+ };
971
+ var createColors = (enabled = isColorSupported) => {
972
+ let f = enabled ? formatter : () => String;
973
+ return {
974
+ isColorSupported: enabled,
975
+ reset: f("\x1B[0m", "\x1B[0m"),
976
+ bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
977
+ dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
978
+ italic: f("\x1B[3m", "\x1B[23m"),
979
+ underline: f("\x1B[4m", "\x1B[24m"),
980
+ inverse: f("\x1B[7m", "\x1B[27m"),
981
+ hidden: f("\x1B[8m", "\x1B[28m"),
982
+ strikethrough: f("\x1B[9m", "\x1B[29m"),
983
+ black: f("\x1B[30m", "\x1B[39m"),
984
+ red: f("\x1B[31m", "\x1B[39m"),
985
+ green: f("\x1B[32m", "\x1B[39m"),
986
+ yellow: f("\x1B[33m", "\x1B[39m"),
987
+ blue: f("\x1B[34m", "\x1B[39m"),
988
+ magenta: f("\x1B[35m", "\x1B[39m"),
989
+ cyan: f("\x1B[36m", "\x1B[39m"),
990
+ white: f("\x1B[37m", "\x1B[39m"),
991
+ gray: f("\x1B[90m", "\x1B[39m"),
992
+ bgBlack: f("\x1B[40m", "\x1B[49m"),
993
+ bgRed: f("\x1B[41m", "\x1B[49m"),
994
+ bgGreen: f("\x1B[42m", "\x1B[49m"),
995
+ bgYellow: f("\x1B[43m", "\x1B[49m"),
996
+ bgBlue: f("\x1B[44m", "\x1B[49m"),
997
+ bgMagenta: f("\x1B[45m", "\x1B[49m"),
998
+ bgCyan: f("\x1B[46m", "\x1B[49m"),
999
+ bgWhite: f("\x1B[47m", "\x1B[49m"),
1000
+ blackBright: f("\x1B[90m", "\x1B[39m"),
1001
+ redBright: f("\x1B[91m", "\x1B[39m"),
1002
+ greenBright: f("\x1B[92m", "\x1B[39m"),
1003
+ yellowBright: f("\x1B[93m", "\x1B[39m"),
1004
+ blueBright: f("\x1B[94m", "\x1B[39m"),
1005
+ magentaBright: f("\x1B[95m", "\x1B[39m"),
1006
+ cyanBright: f("\x1B[96m", "\x1B[39m"),
1007
+ whiteBright: f("\x1B[97m", "\x1B[39m"),
1008
+ bgBlackBright: f("\x1B[100m", "\x1B[49m"),
1009
+ bgRedBright: f("\x1B[101m", "\x1B[49m"),
1010
+ bgGreenBright: f("\x1B[102m", "\x1B[49m"),
1011
+ bgYellowBright: f("\x1B[103m", "\x1B[49m"),
1012
+ bgBlueBright: f("\x1B[104m", "\x1B[49m"),
1013
+ bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
1014
+ bgCyanBright: f("\x1B[106m", "\x1B[49m"),
1015
+ bgWhiteBright: f("\x1B[107m", "\x1B[49m")
1016
+ };
1017
+ };
1018
+ module.exports = createColors();
1019
+ module.exports.createColors = createColors;
1020
+ });
1021
+
751
1022
  // ../shared/dist/utils/help.js
752
1023
  import { readFileSync } from "fs";
753
- import { join as join4 } from "path";
1024
+ import { join as join3 } from "path";
754
1025
  function getVersion() {
755
1026
  try {
756
- const packageJsonPath = join4(__dirname, "../../package.json");
1027
+ const packageJsonPath = join3(__dirname, "../../package.json");
757
1028
  const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
758
1029
  return packageJson.version || "0.1.0";
759
1030
  } catch (error) {
@@ -763,47 +1034,47 @@ function getVersion() {
763
1034
  function showHelp() {
764
1035
  const version = getVersion();
765
1036
  console.error(`
766
- ${import_picocolors4.default.bold("Enact CLI")} ${import_picocolors4.default.dim(`v${version}`)}
767
- ${import_picocolors4.default.dim("A CLI tool for managing and publishing Enact tools")}
768
-
769
- ${import_picocolors4.default.bold("Usage:")}
770
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("<command>")} [options]
771
-
772
- ${import_picocolors4.default.bold("Commands:")}
773
- ${import_picocolors4.default.green("auth")} Manage authentication (login, logout, status, token)
774
- ${import_picocolors4.default.green("env")} Manage environment variables (set, get, list, delete)
775
- ${import_picocolors4.default.green("exec")} Execute a tool by fetching and running it
776
- ${import_picocolors4.default.green("init")} Create a new tool definition
777
- ${import_picocolors4.default.green("mcp")} MCP client integration (install, list, status)
778
- ${import_picocolors4.default.green("publish")} Publish a tool to the registry
779
- ${import_picocolors4.default.green("search")} Search for tools in the registry
780
- ${import_picocolors4.default.green("sign")} Sign and verify tools with cryptographic signatures
781
- ${import_picocolors4.default.green("remote")} Manage remote servers (add, list, remove)
782
- ${import_picocolors4.default.green("user")} User operations (get public key)
783
-
784
- ${import_picocolors4.default.bold("Global Options:")}
785
- ${import_picocolors4.default.yellow("--help, -h")} Show help message
786
- ${import_picocolors4.default.yellow("--version, -v")} Show version information
787
-
788
- ${import_picocolors4.default.bold("Examples:")}
789
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.dim("# Interactive mode")}
790
- ${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")}
791
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("exec")} enact/text/slugify ${import_picocolors4.default.dim("# Execute a tool")}
792
- ${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")}
793
- ${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")}
794
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("env")} set API_KEY --encrypt ${import_picocolors4.default.dim("# Set encrypted env var")}
795
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("sign")} verify my-tool.yaml ${import_picocolors4.default.dim("# Verify tool signatures")}
796
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("publish")} my-tool.yaml ${import_picocolors4.default.dim("# Publish a tool")}
797
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("auth")} login ${import_picocolors4.default.dim("# Login with OAuth")}
798
- ${import_picocolors4.default.cyan("enact")} ${import_picocolors4.default.green("init")} ${import_picocolors4.default.yellow("--minimal")} ${import_picocolors4.default.dim("# Create minimal tool template")}
799
-
800
- ${import_picocolors4.default.bold("More Help:")}
801
- ${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")}
802
1073
  `);
803
1074
  }
804
- 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";
805
1076
  var init_help = __esm(() => {
806
- import_picocolors4 = __toESM(require_picocolors(), 1);
1077
+ import_picocolors3 = __toESM(require_picocolors2(), 1);
807
1078
  });
808
1079
 
809
1080
  // ../shared/dist/utils/logger.js
@@ -812,29 +1083,29 @@ function setLogLevel(level) {
812
1083
  }
813
1084
  function debug(message) {
814
1085
  if (currentLogLevel <= LogLevel.DEBUG) {
815
- console.error(import_picocolors5.default.dim(`\uD83D\uDD0D ${message}`));
1086
+ console.error(import_picocolors4.default.dim(`\uD83D\uDD0D ${message}`));
816
1087
  }
817
1088
  }
818
1089
  function info(message) {
819
1090
  if (currentLogLevel <= LogLevel.INFO) {
820
- console.error(import_picocolors5.default.blue(`ℹ️ ${message}`));
1091
+ console.error(import_picocolors4.default.blue(`ℹ️ ${message}`));
821
1092
  }
822
1093
  }
823
1094
  function success(message) {
824
1095
  if (currentLogLevel <= LogLevel.SUCCESS) {
825
- console.error(import_picocolors5.default.green(`✓ ${message}`));
1096
+ console.error(import_picocolors4.default.green(`✓ ${message}`));
826
1097
  }
827
1098
  }
828
1099
  function warn(message) {
829
1100
  if (currentLogLevel <= LogLevel.WARN) {
830
- console.error(import_picocolors5.default.yellow(`⚠️ ${message}`));
1101
+ console.error(import_picocolors4.default.yellow(`⚠️ ${message}`));
831
1102
  }
832
1103
  }
833
1104
  function error(message, details) {
834
1105
  if (currentLogLevel <= LogLevel.ERROR) {
835
- console.error(import_picocolors5.default.red(`✗ Error: ${message}`));
1106
+ console.error(import_picocolors4.default.red(`✗ Error: ${message}`));
836
1107
  if (details && currentLogLevel === LogLevel.DEBUG) {
837
- console.error(import_picocolors5.default.dim("Details:"));
1108
+ console.error(import_picocolors4.default.dim("Details:"));
838
1109
  console.error(details);
839
1110
  }
840
1111
  }
@@ -848,9 +1119,9 @@ function table(data, columns) {
848
1119
  }
849
1120
  }
850
1121
  }
851
- var import_picocolors5, LogLevel, currentLogLevel;
1122
+ var import_picocolors4, LogLevel, currentLogLevel;
852
1123
  var init_logger = __esm(() => {
853
- import_picocolors5 = __toESM(require_picocolors(), 1);
1124
+ import_picocolors4 = __toESM(require_picocolors2(), 1);
854
1125
  (function(LogLevel2) {
855
1126
  LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
856
1127
  LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
@@ -1086,7 +1357,7 @@ function parseTimeout(timeout) {
1086
1357
 
1087
1358
  // ../shared/dist/utils/version.js
1088
1359
  import { readFileSync as readFileSync2 } from "fs";
1089
- import { join as join5, dirname } from "path";
1360
+ import { join as join4, dirname } from "path";
1090
1361
  import { fileURLToPath } from "url";
1091
1362
  function showVersion() {
1092
1363
  let version = "0.0.1-dev";
@@ -1096,7 +1367,7 @@ function showVersion() {
1096
1367
  } else {
1097
1368
  const currentFile = typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url);
1098
1369
  const sharedDir = dirname(dirname(dirname(currentFile)));
1099
- const packageJsonPath = join5(sharedDir, "package.json");
1370
+ const packageJsonPath = join4(sharedDir, "package.json");
1100
1371
  const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf8"));
1101
1372
  version = packageJson.version;
1102
1373
  }
@@ -1105,13 +1376,13 @@ function showVersion() {
1105
1376
  }
1106
1377
  const versionText = `v${version}`;
1107
1378
  console.error(`
1108
- ${import_picocolors6.default.bold("Enact CLI")} ${import_picocolors6.default.cyan(versionText)}
1109
- ${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.")}
1110
1381
  `);
1111
1382
  }
1112
- 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";
1113
1384
  var init_version = __esm(() => {
1114
- import_picocolors6 = __toESM(require_picocolors(), 1);
1385
+ import_picocolors5 = __toESM(require_picocolors2(), 1);
1115
1386
  });
1116
1387
 
1117
1388
  // ../shared/dist/utils/index.js
@@ -1128,23 +1399,34 @@ __export(exports_utils, {
1128
1399
  showVersion: () => showVersion,
1129
1400
  showHelp: () => showHelp,
1130
1401
  setLogLevel: () => setLogLevel,
1402
+ setFrontendUrl: () => setFrontendUrl,
1131
1403
  setDefaultUrl: () => setDefaultUrl,
1404
+ setApiUrl: () => setApiUrl,
1132
1405
  resolveToolEnvironmentVariables: () => resolveToolEnvironmentVariables,
1406
+ resetUrls: () => resetUrls,
1407
+ removeTrustedKey: () => removeTrustedKey,
1133
1408
  readConfig: () => readConfig,
1134
1409
  parseTimeout: () => parseTimeout,
1135
1410
  loadPackageEnvironmentVariables: () => loadPackageEnvironmentVariables,
1411
+ isKeyTrusted: () => isKeyTrusted,
1136
1412
  info: () => info,
1137
1413
  globalMonitor: () => globalMonitor,
1138
1414
  getWebServerUrl: () => getWebServerUrl,
1415
+ getUrlConfig: () => getUrlConfig,
1416
+ getTrustedKeys: () => getTrustedKeys,
1417
+ getTrustedKey: () => getTrustedKey,
1139
1418
  getPackageEnvironmentVariables: () => getPackageEnvironmentVariables,
1140
1419
  getHistory: () => getHistory,
1420
+ getFrontendUrl: () => getFrontendUrl,
1141
1421
  getDefaultUrl: () => getDefaultUrl,
1422
+ getApiUrl: () => getApiUrl,
1142
1423
  generateConfigLink: () => generateConfigLink,
1143
1424
  extractPackageNamespace: () => extractPackageNamespace,
1144
1425
  error: () => error,
1145
1426
  ensureSilent: () => ensureSilent,
1146
1427
  ensureConfig: () => ensureConfig,
1147
1428
  debug: () => debug,
1429
+ addTrustedKey: () => addTrustedKey,
1148
1430
  addToHistory: () => addToHistory,
1149
1431
  McpSilentOperationMonitor: () => McpSilentOperationMonitor,
1150
1432
  LogLevel: () => LogLevel
@@ -12327,13 +12609,71 @@ var require_pino = __commonJS((exports, module) => {
12327
12609
  module.exports.pino = pino;
12328
12610
  });
12329
12611
 
12612
+ // ../../node_modules/sisteransi/src/index.js
12613
+ var require_src2 = __commonJS((exports, module) => {
12614
+ var ESC = "\x1B";
12615
+ var CSI = `${ESC}[`;
12616
+ var beep = "\x07";
12617
+ var cursor = {
12618
+ to(x2, y3) {
12619
+ if (!y3)
12620
+ return `${CSI}${x2 + 1}G`;
12621
+ return `${CSI}${y3 + 1};${x2 + 1}H`;
12622
+ },
12623
+ move(x2, y3) {
12624
+ let ret = "";
12625
+ if (x2 < 0)
12626
+ ret += `${CSI}${-x2}D`;
12627
+ else if (x2 > 0)
12628
+ ret += `${CSI}${x2}C`;
12629
+ if (y3 < 0)
12630
+ ret += `${CSI}${-y3}A`;
12631
+ else if (y3 > 0)
12632
+ ret += `${CSI}${y3}B`;
12633
+ return ret;
12634
+ },
12635
+ up: (count = 1) => `${CSI}${count}A`,
12636
+ down: (count = 1) => `${CSI}${count}B`,
12637
+ forward: (count = 1) => `${CSI}${count}C`,
12638
+ backward: (count = 1) => `${CSI}${count}D`,
12639
+ nextLine: (count = 1) => `${CSI}E`.repeat(count),
12640
+ prevLine: (count = 1) => `${CSI}F`.repeat(count),
12641
+ left: `${CSI}G`,
12642
+ hide: `${CSI}?25l`,
12643
+ show: `${CSI}?25h`,
12644
+ save: `${ESC}7`,
12645
+ restore: `${ESC}8`
12646
+ };
12647
+ var scroll = {
12648
+ up: (count = 1) => `${CSI}S`.repeat(count),
12649
+ down: (count = 1) => `${CSI}T`.repeat(count)
12650
+ };
12651
+ var erase = {
12652
+ screen: `${CSI}2J`,
12653
+ up: (count = 1) => `${CSI}1J`.repeat(count),
12654
+ down: (count = 1) => `${CSI}J`.repeat(count),
12655
+ line: `${CSI}2K`,
12656
+ lineEnd: `${CSI}K`,
12657
+ lineStart: `${CSI}1K`,
12658
+ lines(count) {
12659
+ let clear = "";
12660
+ for (let i = 0;i < count; i++)
12661
+ clear += this.line + (i < count - 1 ? cursor.up() : "");
12662
+ if (count)
12663
+ clear += cursor.left;
12664
+ return clear;
12665
+ }
12666
+ };
12667
+ module.exports = { cursor, scroll, erase, beep };
12668
+ });
12669
+
12330
12670
  // ../../node_modules/@clack/core/dist/index.cjs
12331
12671
  var require_dist2 = __commonJS((exports) => {
12332
- var sisteransi = require_src();
12672
+ var sisteransi = require_src2();
12333
12673
  var node_process = __require("node:process");
12334
12674
  var s$2 = __require("node:readline");
12335
12675
  var node_stream = __require("node:stream");
12336
- var i$1 = require_picocolors();
12676
+ var i$1 = require_picocolors2();
12337
12677
  function _interopDefaultCompat(C3) {
12338
12678
  return C3 && typeof C3 == "object" && "default" in C3 ? C3.default : C3;
12339
12679
  }
@@ -12920,8 +13260,8 @@ var require_dist3 = __commonJS((exports) => {
12920
13260
  var node_util = __require("node:util");
12921
13261
  var core = require_dist2();
12922
13262
  var process$1 = __require("node:process");
12923
- var e2 = require_picocolors();
12924
- var sisteransi = require_src();
13263
+ var e2 = require_picocolors2();
13264
+ var sisteransi = require_src2();
12925
13265
  function _interopDefaultCompat(t) {
12926
13266
  return t && typeof t == "object" && "default" in t ? t.default : t;
12927
13267
  }
@@ -213472,10 +213812,10 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
213472
213812
  var import_picocolors14 = __toESM(require_picocolors(), 1);
213473
213813
  import { parseArgs } from "util";
213474
213814
 
213475
- // ../../node_modules/@clack/prompts/dist/index.mjs
213815
+ // node_modules/@clack/prompts/dist/index.mjs
213476
213816
  import { stripVTControlCharacters as S2 } from "node:util";
213477
213817
 
213478
- // ../../node_modules/@clack/core/dist/index.mjs
213818
+ // node_modules/@clack/core/dist/index.mjs
213479
213819
  var import_sisteransi = __toESM(require_src(), 1);
213480
213820
  var import_picocolors = __toESM(require_picocolors(), 1);
213481
213821
  import { stdin as j, stdout as M } from "node:process";
@@ -213922,7 +214262,7 @@ class RD extends x {
213922
214262
  }
213923
214263
  }
213924
214264
 
213925
- // ../../node_modules/@clack/prompts/dist/index.mjs
214265
+ // node_modules/@clack/prompts/dist/index.mjs
213926
214266
  var import_picocolors2 = __toESM(require_picocolors(), 1);
213927
214267
  var import_sisteransi2 = __toESM(require_src(), 1);
213928
214268
  import y2 from "node:process";
@@ -214175,11 +214515,11 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
214175
214515
  };
214176
214516
 
214177
214517
  // src/commands/auth.ts
214178
- var import_picocolors3 = __toESM(require_picocolors(), 1);
214179
- import { existsSync } from "fs";
214180
- import { readFile, writeFile, mkdir } from "fs/promises";
214181
- import { join } from "path";
214182
- 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";
214183
214523
  import { createServer } from "http";
214184
214524
  import { parse } from "url";
214185
214525
  import { randomBytes, createHash } from "crypto";
@@ -214187,11 +214527,18 @@ import { exec } from "child_process";
214187
214527
  import { promisify } from "util";
214188
214528
 
214189
214529
  // ../shared/dist/api/enact-api.js
214530
+ init_config();
214531
+
214190
214532
  class EnactApiClient {
214191
- constructor(baseUrl = "https://enact.tools", supabaseUrl = "https://xjnhhxwxovjifdxdwzih.supabase.co") {
214533
+ constructor(baseUrl, supabaseUrl) {
214192
214534
  this.baseUrl = baseUrl.replace(/\/$/, "");
214193
214535
  this.supabaseUrl = supabaseUrl.replace(/\/$/, "");
214194
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
+ }
214195
214542
  async makeRequest(endpoint, options = {}, token, tokenType = "jwt") {
214196
214543
  const url = endpoint.startsWith("http") ? endpoint : `${this.supabaseUrl}${endpoint}`;
214197
214544
  const headers = {
@@ -214473,7 +214820,7 @@ class EnactApiClient {
214473
214820
  };
214474
214821
  }
214475
214822
  }
214476
- var enactApi = new EnactApiClient;
214823
+ var enactApi = new EnactApiClient("https://enact.tools", "https://xjnhhxwxovjifdxdwzih.supabase.co");
214477
214824
 
214478
214825
  class EnactApiError extends Error {
214479
214826
  constructor(message, statusCode, endpoint) {
@@ -214484,14 +214831,17 @@ class EnactApiError extends Error {
214484
214831
  }
214485
214832
  }
214486
214833
  function createEnactApiClient(baseUrl, supabaseUrl) {
214487
- 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);
214488
214837
  }
214489
214838
  // src/commands/auth.ts
214839
+ init_utils();
214490
214840
  var execAsync = promisify(exec);
214491
- var CONFIG_DIR = join(homedir(), ".enact");
214492
- var AUTH_FILE = join(CONFIG_DIR, "auth.json");
214493
- var DEFAULT_SERVER = "https://enact.tools";
214841
+ var CONFIG_DIR3 = join5(homedir3(), ".enact");
214842
+ var AUTH_FILE = join5(CONFIG_DIR3, "auth.json");
214494
214843
  async function handleAuthCommand(args, options) {
214844
+ const defaultServer = await getFrontendUrl();
214495
214845
  if (options.help || !args[0]) {
214496
214846
  console.error(`
214497
214847
  Usage: enact auth <subcommand> [options]
@@ -214506,16 +214856,16 @@ Subcommands:
214506
214856
 
214507
214857
  Options:
214508
214858
  --help, -h Show this help message
214509
- --server <url> Specify the enact server URL (default: ${DEFAULT_SERVER})
214859
+ --server <url> Specify the enact server URL (default: ${defaultServer})
214510
214860
  --port <number> Local callback port for OAuth (default: 8080)
214511
214861
  `);
214512
214862
  return;
214513
214863
  }
214514
214864
  const subCommand = args[0];
214515
- const serverUrl = options.server || DEFAULT_SERVER;
214865
+ const serverUrl = options.server || defaultServer;
214516
214866
  const callbackPort = options.port || 8080;
214517
214867
  await ensureAuthConfig();
214518
- Ie(import_picocolors3.default.bgBlue(import_picocolors3.default.white(" Enact Authentication ")));
214868
+ Ie(import_picocolors6.default.bgBlue(import_picocolors6.default.white(" Enact Authentication ")));
214519
214869
  switch (subCommand) {
214520
214870
  case "login": {
214521
214871
  await handleLogin(serverUrl, callbackPort);
@@ -214534,7 +214884,7 @@ Options:
214534
214884
  break;
214535
214885
  }
214536
214886
  default:
214537
- Se(import_picocolors3.default.red(`✗ Unknown auth subcommand "${subCommand}"`));
214887
+ Se(import_picocolors6.default.red(`✗ Unknown auth subcommand "${subCommand}"`));
214538
214888
  return;
214539
214889
  }
214540
214890
  }
@@ -214546,7 +214896,7 @@ async function handleLogin(serverUrl, callbackPort) {
214546
214896
  message: "You are already authenticated. Continue with new login?"
214547
214897
  });
214548
214898
  if (!useExisting) {
214549
- Se(import_picocolors3.default.yellow("Login cancelled"));
214899
+ Se(import_picocolors6.default.yellow("Login cancelled"));
214550
214900
  return;
214551
214901
  }
214552
214902
  }
@@ -214568,14 +214918,14 @@ async function handleLogin(serverUrl, callbackPort) {
214568
214918
  try {
214569
214919
  server2 = await startCallbackServerWithFallback(callbackPort, serverUrl, codeVerifier, state);
214570
214920
  s.stop("OAuth server started");
214571
- } catch (error) {
214921
+ } catch (error2) {
214572
214922
  s.stop("OAuth server could not start, using manual mode");
214573
214923
  server2 = null;
214574
214924
  }
214575
214925
  Me(`Opening browser to: ${authUrl}`, "OAuth Login");
214576
214926
  try {
214577
214927
  await openBrowser(authUrl);
214578
- } catch (error) {
214928
+ } catch (error2) {
214579
214929
  Me(`Please open this URL in your browser: ${authUrl}`, "Manual Browser Open Required");
214580
214930
  }
214581
214931
  if (server2) {
@@ -214602,14 +214952,14 @@ async function handleLogin(serverUrl, callbackPort) {
214602
214952
  }
214603
214953
  });
214604
214954
  if (typeof authCode === "symbol") {
214605
- Se(import_picocolors3.default.yellow("Login cancelled"));
214955
+ Se(import_picocolors6.default.yellow("Login cancelled"));
214606
214956
  return;
214607
214957
  }
214608
214958
  await exchangeCodeForToken(authCode, redirectUri, codeVerifier, serverUrl);
214609
214959
  }
214610
- Se(import_picocolors3.default.green("✓ Successfully authenticated with Enact!"));
214611
- } catch (error) {
214612
- 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}`));
214613
214963
  } finally {
214614
214964
  process.exit(0);
214615
214965
  }
@@ -214623,13 +214973,13 @@ async function startCallbackServerWithFallback(port, serverUrl, codeVerifier, st
214623
214973
  const {
214624
214974
  code,
214625
214975
  state: returnedState,
214626
- error,
214976
+ error: error2,
214627
214977
  error_description
214628
214978
  } = parsedUrl.query;
214629
214979
  res.setHeader("Access-Control-Allow-Origin", "*");
214630
214980
  res.setHeader("Content-Type", "text/html");
214631
- if (error) {
214632
- const errorMsg = error_description || error;
214981
+ if (error2) {
214982
+ const errorMsg = error_description || error2;
214633
214983
  res.writeHead(400);
214634
214984
  res.end(`
214635
214985
  <html>
@@ -214688,19 +215038,19 @@ async function startCallbackServerWithFallback(port, serverUrl, codeVerifier, st
214688
215038
  `);
214689
215039
  server2.close();
214690
215040
  server2.emit("authComplete");
214691
- } catch (error2) {
214692
- console.error("Token exchange error:", error2);
215041
+ } catch (error3) {
215042
+ console.error("Token exchange error:", error3);
214693
215043
  res.writeHead(500);
214694
215044
  res.end(`
214695
215045
  <html>
214696
215046
  <body style="font-family: Arial, sans-serif; text-align: center; padding: 50px;">
214697
215047
  <h1 style="color: red;">❌ Authentication Failed</h1>
214698
- <p><strong>Error:</strong> ${error2.message}</p>
215048
+ <p><strong>Error:</strong> ${error3.message}</p>
214699
215049
  <p>You can close this window and check your terminal for more details.</p>
214700
215050
  </body>
214701
215051
  </html>
214702
215052
  `);
214703
- server2.emit("authError", error2);
215053
+ server2.emit("authError", error3);
214704
215054
  }
214705
215055
  } else {
214706
215056
  res.writeHead(404);
@@ -214719,11 +215069,11 @@ async function startCallbackServerWithFallback(port, serverUrl, codeVerifier, st
214719
215069
  console.error(`OAuth callback server listening on http://localhost:${port}`);
214720
215070
  resolve(server2);
214721
215071
  });
214722
- server2.on("error", (error) => {
214723
- if (error.code === "EADDRINUSE") {
215072
+ server2.on("error", (error2) => {
215073
+ if (error2.code === "EADDRINUSE") {
214724
215074
  reject(new Error(`Port ${port} is already in use`));
214725
215075
  } else {
214726
- reject(error);
215076
+ reject(error2);
214727
215077
  }
214728
215078
  });
214729
215079
  });
@@ -214752,11 +215102,11 @@ async function exchangeCodeForToken(code, redirectUri, codeVerifier, serverUrl)
214752
215102
  server: serverUrl
214753
215103
  });
214754
215104
  console.error("✓ Token stored successfully");
214755
- } catch (error) {
214756
- if (error instanceof EnactApiError) {
214757
- 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}`);
214758
215108
  }
214759
- throw error;
215109
+ throw error2;
214760
215110
  }
214761
215111
  }
214762
215112
  async function handleLogout() {
@@ -214770,45 +215120,45 @@ async function handleLogout() {
214770
215120
  message: "Are you sure you want to logout?"
214771
215121
  });
214772
215122
  if (!shouldLogout) {
214773
- Se(import_picocolors3.default.yellow("Logout cancelled"));
215123
+ Se(import_picocolors6.default.yellow("Logout cancelled"));
214774
215124
  return;
214775
215125
  }
214776
215126
  const s = Y2();
214777
215127
  s.start("Logging out...");
214778
215128
  await writeAuthConfig({});
214779
215129
  s.stop("Logged out successfully");
214780
- Se(import_picocolors3.default.green("✓ You have been logged out"));
215130
+ Se(import_picocolors6.default.green("✓ You have been logged out"));
214781
215131
  }
214782
215132
  async function handleStatus() {
214783
215133
  const currentAuth = await readAuthConfig();
214784
215134
  if (!currentAuth.token) {
214785
215135
  Me("Not authenticated", "Status");
214786
- Se(import_picocolors3.default.yellow('Run "enact auth login" to authenticate'));
215136
+ Se(import_picocolors6.default.yellow('Run "enact auth login" to authenticate'));
214787
215137
  return;
214788
215138
  }
214789
215139
  const isExpired = currentAuth.expiresAt && new Date(currentAuth.expiresAt) <= new Date;
214790
215140
  if (isExpired) {
214791
215141
  Me("Token has expired", "Status");
214792
- 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'));
214793
215143
  return;
214794
215144
  }
214795
215145
  const expiresIn = currentAuth.expiresAt ? Math.round((new Date(currentAuth.expiresAt).getTime() - Date.now()) / 1000 / 60 / 60) : "unknown";
214796
215146
  Me(`Authenticated
214797
215147
  Expires: ${currentAuth.expiresAt || "unknown"}
214798
215148
  Expires in: ${expiresIn} hours`, "Status");
214799
- Se(import_picocolors3.default.green("✓ Authentication valid"));
215149
+ Se(import_picocolors6.default.green("✓ Authentication valid"));
214800
215150
  }
214801
215151
  async function handleShowToken() {
214802
215152
  const currentAuth = await readAuthConfig();
214803
215153
  if (!currentAuth.token) {
214804
215154
  Me("Not authenticated", "Status");
214805
- Se(import_picocolors3.default.yellow('Run "enact auth login" to authenticate'));
215155
+ Se(import_picocolors6.default.yellow('Run "enact auth login" to authenticate'));
214806
215156
  return;
214807
215157
  }
214808
215158
  const isExpired = currentAuth.expiresAt && new Date(currentAuth.expiresAt) <= new Date;
214809
215159
  if (isExpired) {
214810
215160
  Me("Token has expired", "Status");
214811
- 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'));
214812
215162
  return;
214813
215163
  }
214814
215164
  const maskedToken = currentAuth.token.length > 12 ? `${currentAuth.token.slice(0, 8)}...${currentAuth.token.slice(-4)}` : currentAuth.token;
@@ -214843,23 +215193,23 @@ async function openBrowser(url) {
214843
215193
  await execAsync(command);
214844
215194
  }
214845
215195
  async function ensureAuthConfig() {
214846
- if (!existsSync(CONFIG_DIR)) {
214847
- await mkdir(CONFIG_DIR, { recursive: true });
215196
+ if (!existsSync3(CONFIG_DIR3)) {
215197
+ await mkdir2(CONFIG_DIR3, { recursive: true });
214848
215198
  }
214849
- if (!existsSync(AUTH_FILE)) {
215199
+ if (!existsSync3(AUTH_FILE)) {
214850
215200
  await writeAuthConfig({});
214851
215201
  }
214852
215202
  }
214853
215203
  async function readAuthConfig() {
214854
215204
  try {
214855
- const text = await readFile(AUTH_FILE, "utf8");
215205
+ const text = await readFile3(AUTH_FILE, "utf8");
214856
215206
  return JSON.parse(text);
214857
215207
  } catch (e2) {
214858
215208
  return {};
214859
215209
  }
214860
215210
  }
214861
- async function writeAuthConfig(config) {
214862
- 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");
214863
215213
  }
214864
215214
  async function getCurrentToken() {
214865
215215
  try {
@@ -214871,7 +215221,7 @@ async function getCurrentToken() {
214871
215221
  return null;
214872
215222
  }
214873
215223
  return auth.token;
214874
- } catch (error) {
215224
+ } catch (error2) {
214875
215225
  return null;
214876
215226
  }
214877
215227
  }
@@ -216058,6 +216408,23 @@ var MCP_CLIENTS = {
216058
216408
  }
216059
216409
  }
216060
216410
  };
216411
+ var MCP_SERVERS = {
216412
+ main: {
216413
+ name: "Enact MCP Server",
216414
+ description: "Main server for tool execution, search, and environment management",
216415
+ package: "@enactprotocol/mcp-server"
216416
+ },
216417
+ dev: {
216418
+ name: "Enact MCP Dev Server",
216419
+ description: "Development server for creating, testing, validating, and publishing tools",
216420
+ package: "@enactprotocol/mcp-dev-server"
216421
+ },
216422
+ both: {
216423
+ name: "Both Servers",
216424
+ description: "Install both main and development servers",
216425
+ package: "both"
216426
+ }
216427
+ };
216061
216428
  async function handleMcpCommand(args, options) {
216062
216429
  if (options.help || !args[0]) {
216063
216430
  console.error(`
@@ -216066,13 +216433,14 @@ Usage: enact mcp <subcommand> [options]
216066
216433
  Manages MCP (Model Context Protocol) client integrations.
216067
216434
 
216068
216435
  Subcommands:
216069
- install Install Enact MCP server to MCP clients
216436
+ install Install Enact MCP server(s) to MCP clients
216070
216437
  list List detected MCP clients
216071
216438
  status Show MCP integration status
216072
216439
 
216073
216440
  Options:
216074
216441
  --help, -h Show this help message
216075
216442
  --client <name> Target specific client (claude-desktop, claude-code, vscode, goose, gemini)
216443
+ --server <type> Choose server type (main, dev, both) - default: main
216076
216444
  `);
216077
216445
  return;
216078
216446
  }
@@ -216110,6 +216478,20 @@ Supported clients:
216110
216478
  return;
216111
216479
  }
216112
216480
  let targetClient = options.client;
216481
+ let serverType = options.server || "main";
216482
+ if (!MCP_SERVERS[serverType]) {
216483
+ console.error(import_picocolors11.default.red(`Invalid server type: ${serverType}. Valid options: main, dev, both`));
216484
+ process.exit(1);
216485
+ }
216486
+ if (!options.server) {
216487
+ serverType = await ve({
216488
+ message: "Which MCP server(s) would you like to install?",
216489
+ options: Object.entries(MCP_SERVERS).map(([key, config2]) => ({
216490
+ value: key,
216491
+ label: `${config2.name} - ${config2.description}`
216492
+ }))
216493
+ });
216494
+ }
216113
216495
  if (!targetClient) {
216114
216496
  if (detectedClients.length === 1) {
216115
216497
  targetClient = detectedClients[0].id;
@@ -216133,10 +216515,11 @@ Supported clients:
216133
216515
  console.error(import_picocolors11.default.red(`Client "${targetClient}" not found or not detected.`));
216134
216516
  process.exit(1);
216135
216517
  }
216136
- const isAlreadyInstalled = await checkMcpServerInstalled(selectedClient);
216518
+ const isAlreadyInstalled = await checkMcpServerInstalled(selectedClient, serverType);
216137
216519
  if (isAlreadyInstalled) {
216520
+ const serverConfig2 = MCP_SERVERS[serverType];
216138
216521
  const shouldReinstall = await ye({
216139
- message: `Enact MCP server is already installed in ${selectedClient.name}. Do you want to reinstall it?`
216522
+ message: `${serverConfig2.name} is already installed in ${selectedClient.name}. Do you want to reinstall it?`
216140
216523
  });
216141
216524
  if (!shouldReinstall) {
216142
216525
  Se("Installation cancelled.");
@@ -216144,11 +216527,14 @@ Supported clients:
216144
216527
  }
216145
216528
  }
216146
216529
  const s = Y2();
216147
- s.start("Installing Enact MCP server...");
216148
- await installMcpServer(selectedClient);
216149
- s.stop("✓ Enact MCP server installation process completed");
216150
- Me(import_picocolors11.default.green(`✓ Added 'enact' MCP server to ${selectedClient.name}
216151
- `) + import_picocolors11.default.cyan(`→ Please restart ${selectedClient.name} to enable the Enact MCP server
216530
+ const serverConfig = MCP_SERVERS[serverType];
216531
+ s.start(`Installing ${serverConfig.name}...`);
216532
+ await installMcpServer(selectedClient, serverType);
216533
+ s.stop(`✓ ${serverConfig.name} installation process completed`);
216534
+ const successMessage = serverType === "both" ? `✓ Added both 'enact' and 'enact-dev' MCP servers to ${selectedClient.name}
216535
+ ` : `✓ Added '${serverType === "main" ? "enact" : "enact-dev"}' MCP server to ${selectedClient.name}
216536
+ `;
216537
+ Me(import_picocolors11.default.green(successMessage) + import_picocolors11.default.cyan(`→ Please restart ${selectedClient.name} to enable the MCP server(s)
216152
216538
  `) + import_picocolors11.default.cyan(`→ Look for the MCP tools icon in the chat interface`), "Installation complete");
216153
216539
  Se("MCP server installation completed!");
216154
216540
  } catch (error2) {
@@ -216179,8 +216565,18 @@ async function handleStatusCommand() {
216179
216565
  return;
216180
216566
  }
216181
216567
  for (const client of detectedClients) {
216182
- const isInstalled = await checkMcpServerInstalled(client);
216183
- const status = isInstalled ? import_picocolors11.default.green("✓ Installed") : import_picocolors11.default.yellow("○ Not installed");
216568
+ const mainInstalled = await checkMcpServerInstalled(client, "main");
216569
+ const devInstalled = await checkMcpServerInstalled(client, "dev");
216570
+ let status = "";
216571
+ if (mainInstalled && devInstalled) {
216572
+ status = import_picocolors11.default.green("✓ Main + Dev servers");
216573
+ } else if (mainInstalled) {
216574
+ status = import_picocolors11.default.green("✓ Main server") + import_picocolors11.default.yellow(" (Dev server not installed)");
216575
+ } else if (devInstalled) {
216576
+ status = import_picocolors11.default.green("✓ Dev server") + import_picocolors11.default.yellow(" (Main server not installed)");
216577
+ } else {
216578
+ status = import_picocolors11.default.yellow("○ Not installed");
216579
+ }
216184
216580
  Me(`${status}
216185
216581
  Config: ${client.configPath}`, client.name);
216186
216582
  }
@@ -216222,10 +216618,9 @@ async function detectMcpClients() {
216222
216618
  }
216223
216619
  return detected;
216224
216620
  }
216225
- async function installMcpServer(client) {
216621
+ async function installMcpServer(client, serverType = "main") {
216226
216622
  if (client.id === "goose") {
216227
216623
  try {
216228
- const extensionName = "Enact Tools";
216229
216624
  const yaml = await Promise.resolve().then(() => __toESM(require_dist(), 1));
216230
216625
  const configPath2 = client.configPath;
216231
216626
  const configDir2 = join8(configPath2, "..");
@@ -216242,16 +216637,29 @@ async function installMcpServer(client) {
216242
216637
  if (!config3.extensions) {
216243
216638
  config3.extensions = {};
216244
216639
  }
216245
- config3.extensions.enact = {
216246
- name: "enact",
216247
- cmd: "npx",
216248
- args: ["-y", "@enactprotocol/mcp-server"],
216249
- enabled: true,
216250
- type: "stdio",
216251
- timeout: 300
216252
- };
216640
+ if (serverType === "main" || serverType === "both") {
216641
+ config3.extensions.enact = {
216642
+ name: "enact",
216643
+ cmd: "npx",
216644
+ args: ["-y", "@enactprotocol/mcp-server"],
216645
+ enabled: true,
216646
+ type: "stdio",
216647
+ timeout: 300
216648
+ };
216649
+ }
216650
+ if (serverType === "dev" || serverType === "both") {
216651
+ config3.extensions["enact-dev"] = {
216652
+ name: "enact-dev",
216653
+ cmd: "npx",
216654
+ args: ["-y", "@enactprotocol/mcp-dev-server"],
216655
+ enabled: true,
216656
+ type: "stdio",
216657
+ timeout: 300
216658
+ };
216659
+ }
216253
216660
  await writeFile6(configPath2, yaml.stringify(config3), "utf-8");
216254
- Me(import_picocolors11.default.green(`✓ Successfully added 'Enact Tools' extension to Goose configuration
216661
+ const serverConfig = MCP_SERVERS[serverType];
216662
+ Me(import_picocolors11.default.green(`✓ Successfully added '${serverConfig.name}' extension to Goose configuration
216255
216663
  `) + import_picocolors11.default.cyan(`→ The extension is now available in your Goose AI sessions
216256
216664
  `) + import_picocolors11.default.cyan(`→ Restart Goose if it's currently running`), "Installation complete");
216257
216665
  } catch (error2) {
@@ -216271,24 +216679,33 @@ async function installMcpServer(client) {
216271
216679
  console.warn(import_picocolors11.default.yellow(`Warning: Could not parse existing config at ${configPath}. Creating new config.`));
216272
216680
  }
216273
216681
  }
216274
- const mcpServerConfig = {
216275
- command: "npx",
216276
- args: ["-y", "@enactprotocol/mcp-server"]
216277
- };
216682
+ const serverConfigs = {};
216683
+ if (serverType === "main" || serverType === "both") {
216684
+ serverConfigs.enact = {
216685
+ command: "npx",
216686
+ args: ["-y", "@enactprotocol/mcp-server"]
216687
+ };
216688
+ }
216689
+ if (serverType === "dev" || serverType === "both") {
216690
+ serverConfigs["enact-dev"] = {
216691
+ command: "npx",
216692
+ args: ["-y", "@enactprotocol/mcp-dev-server"]
216693
+ };
216694
+ }
216278
216695
  if (client.id === "claude-desktop" || client.id === "claude-code" || client.id === "gemini") {
216279
216696
  if (!config2.mcpServers) {
216280
216697
  config2.mcpServers = {};
216281
216698
  }
216282
- config2.mcpServers.enact = mcpServerConfig;
216699
+ Object.assign(config2.mcpServers, serverConfigs);
216283
216700
  } else if (client.id === "vscode") {
216284
216701
  if (!config2["mcp.servers"]) {
216285
216702
  config2["mcp.servers"] = {};
216286
216703
  }
216287
- config2["mcp.servers"].enact = mcpServerConfig;
216704
+ Object.assign(config2["mcp.servers"], serverConfigs);
216288
216705
  }
216289
216706
  await writeFile6(configPath, JSON.stringify(config2, null, 2), "utf-8");
216290
216707
  }
216291
- async function checkMcpServerInstalled(client) {
216708
+ async function checkMcpServerInstalled(client, serverType = "main") {
216292
216709
  if (client.id === "goose") {
216293
216710
  try {
216294
216711
  const yaml = await Promise.resolve().then(() => __toESM(require_dist(), 1));
@@ -216297,7 +216714,14 @@ async function checkMcpServerInstalled(client) {
216297
216714
  }
216298
216715
  const configContent = await readFile6(client.configPath, "utf-8");
216299
216716
  const config2 = yaml.parse(configContent);
216300
- return config2?.extensions?.enact?.enabled === true;
216717
+ if (serverType === "main") {
216718
+ return config2?.extensions?.enact?.enabled === true;
216719
+ } else if (serverType === "dev") {
216720
+ return config2?.extensions?.["enact-dev"]?.enabled === true;
216721
+ } else if (serverType === "both") {
216722
+ return config2?.extensions?.enact?.enabled === true && config2?.extensions?.["enact-dev"]?.enabled === true;
216723
+ }
216724
+ return false;
216301
216725
  } catch (error2) {
216302
216726
  return false;
216303
216727
  }
@@ -216309,9 +216733,23 @@ async function checkMcpServerInstalled(client) {
216309
216733
  const configContent = await readFile6(client.configPath, "utf-8");
216310
216734
  const config2 = JSON.parse(configContent);
216311
216735
  if (client.id === "claude-desktop" || client.id === "claude-code" || client.id === "gemini") {
216312
- return config2.mcpServers && config2.mcpServers.enact;
216736
+ const servers = config2.mcpServers || {};
216737
+ if (serverType === "main") {
216738
+ return Boolean(servers.enact);
216739
+ } else if (serverType === "dev") {
216740
+ return Boolean(servers["enact-dev"]);
216741
+ } else if (serverType === "both") {
216742
+ return Boolean(servers.enact) && Boolean(servers["enact-dev"]);
216743
+ }
216313
216744
  } else if (client.id === "vscode") {
216314
- return config2["mcp.servers"] && config2["mcp.servers"].enact;
216745
+ const servers = config2["mcp.servers"] || {};
216746
+ if (serverType === "main") {
216747
+ return Boolean(servers.enact);
216748
+ } else if (serverType === "dev") {
216749
+ return Boolean(servers["enact-dev"]);
216750
+ } else if (serverType === "both") {
216751
+ return Boolean(servers.enact) && Boolean(servers["enact-dev"]);
216752
+ }
216315
216753
  }
216316
216754
  return false;
216317
216755
  } catch (error2) {
@@ -216321,6 +216759,7 @@ async function checkMcpServerInstalled(client) {
216321
216759
 
216322
216760
  // src/commands/config.ts
216323
216761
  var import_picocolors12 = __toESM(require_picocolors(), 1);
216762
+ init_utils();
216324
216763
  import fs from "fs/promises";
216325
216764
  import path from "path";
216326
216765
  import { existsSync as existsSync8 } from "fs";
@@ -216508,6 +216947,13 @@ function showConfigHelp() {
216508
216947
  console.log(" get <key> Get specific configuration value");
216509
216948
  console.log(" set <key> <value> Set configuration value");
216510
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");
216511
216957
  console.log(`
216512
216958
  Options:`);
216513
216959
  console.log(" --global Use global configuration (~/.enact-config.json)");
@@ -216528,6 +216974,160 @@ Examples:`);
216528
216974
  console.log(" enact config set daggerOptions.baseImage ubuntu:22.04");
216529
216975
  console.log(" enact config get executionProvider");
216530
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
+ }
216531
217131
  }
216532
217132
  async function handleConfigCommand(args, options) {
216533
217133
  if (options.help) {
@@ -216562,6 +217162,42 @@ async function handleConfigCommand(args, options) {
216562
217162
  case "reset":
216563
217163
  await resetConfig(global2);
216564
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;
216565
217201
  default:
216566
217202
  if (!subcommand) {
216567
217203
  await interactiveConfig(global2);
@@ -216803,7 +217439,7 @@ class DirectExecutionProvider extends ExecutionProvider {
216803
217439
  }
216804
217440
  if (verbose) {
216805
217441
  try {
216806
- const pc11 = require_picocolors();
217442
+ const pc11 = require_picocolors2();
216807
217443
  console.error(pc11.cyan(`
216808
217444
  \uD83D\uDE80 Executing command:`));
216809
217445
  console.error(pc11.white(command));
@@ -216897,7 +217533,7 @@ class DirectExecutionProvider extends ExecutionProvider {
216897
217533
  if (code === 0) {
216898
217534
  if (showSpinner || verbose) {
216899
217535
  try {
216900
- const pc11 = require_picocolors();
217536
+ const pc11 = require_picocolors2();
216901
217537
  console.error(pc11.green(`
216902
217538
  ✅ Tool executed successfully`));
216903
217539
  if (stdout.trim() && !streamOutput) {
@@ -216918,7 +217554,7 @@ class DirectExecutionProvider extends ExecutionProvider {
216918
217554
  } else {
216919
217555
  if (showSpinner || verbose) {
216920
217556
  try {
216921
- const pc11 = require_picocolors();
217557
+ const pc11 = require_picocolors2();
216922
217558
  console.error(pc11.red(`
216923
217559
  ❌ Tool execution failed (exit code: ${code})`));
216924
217560
  if (stderr.trim() && !streamOutput) {
@@ -216960,7 +217596,7 @@ class DirectExecutionProvider extends ExecutionProvider {
216960
217596
  }
216961
217597
  if (showSpinner || verbose) {
216962
217598
  try {
216963
- const pc11 = require_picocolors();
217599
+ const pc11 = require_picocolors2();
216964
217600
  console.error(pc11.red(`
216965
217601
  ❌ Failed to execute command: ${error2.message}`));
216966
217602
  } catch (e2) {
@@ -225677,7 +226313,7 @@ class DaggerExecutionProvider extends ExecutionProvider {
225677
226313
  if (verbose) {
225678
226314
  const containerImage = tool?.from || this.options.baseImage;
225679
226315
  try {
225680
- const pc11 = require_picocolors();
226316
+ const pc11 = require_picocolors2();
225681
226317
  console.error(pc11.cyan(`
225682
226318
  \uD83D\uDC33 Executing Enact command in Dagger container:`));
225683
226319
  console.error(pc11.white(substitutedCommand));
@@ -226083,37 +226719,6 @@ class DaggerExecutionProvider extends ExecutionProvider {
226083
226719
  process.exit(1);
226084
226720
  }
226085
226721
  }
226086
- forceCleanup() {
226087
- if (this.isShuttingDown)
226088
- return;
226089
- try {
226090
- logger_default.info("\uD83D\uDD04 Force cleaning up Dagger engines...");
226091
- const result = spawnSync("docker", [
226092
- "ps",
226093
- "--all",
226094
- "--filter",
226095
- "name=dagger-engine",
226096
- "--format",
226097
- "{{.Names}}"
226098
- ], {
226099
- encoding: "utf8",
226100
- timeout: 5000
226101
- });
226102
- if (result.stdout) {
226103
- const names = result.stdout.trim().split(`
226104
- `).filter((n) => n.trim());
226105
- if (names.length > 0) {
226106
- logger_default.info(`Found ${names.length} engine containers, force removing...`);
226107
- for (const name of names) {
226108
- spawnSync("docker", ["rm", "-f", name.trim()], { timeout: 3000 });
226109
- }
226110
- logger_default.info("✅ Force cleanup completed");
226111
- }
226112
- }
226113
- } catch (error2) {
226114
- logger_default.debug("Force cleanup failed (this is usually fine):", error2);
226115
- }
226116
- }
226117
226722
  getEngineStatus() {
226118
226723
  return {
226119
226724
  health: { ...this.engineHealth },
@@ -228517,7 +229122,7 @@ class KeyManager {
228517
229122
  static getAllTrustedPublicKeys() {
228518
229123
  try {
228519
229124
  this.ensureDirectories();
228520
- return fs5.readdirSync(this.TRUSTED_KEYS_DIR).filter((file) => file.endsWith("-public.pem")).map((file) => {
229125
+ return fs5.readdirSync(this.TRUSTED_KEYS_DIR).filter((file) => file.endsWith(".pem")).map((file) => {
228521
229126
  try {
228522
229127
  const publicKeyPem = fs5.readFileSync(path8.join(this.TRUSTED_KEYS_DIR, file), "utf8").trim();
228523
229128
  return CryptoUtils.pemToHex(publicKeyPem, "PUBLIC");
@@ -228847,6 +229452,8 @@ class SigningService {
228847
229452
  }
228848
229453
 
228849
229454
  // ../shared/dist/core/EnactCore.js
229455
+ init_config();
229456
+
228850
229457
  class EnactCore {
228851
229458
  constructor(options = {}) {
228852
229459
  this.options = {
@@ -228859,6 +229466,15 @@ class EnactCore {
228859
229466
  this.apiClient = new EnactApiClient(this.options.apiUrl, this.options.supabaseUrl);
228860
229467
  this.executionProvider = this.createExecutionProvider();
228861
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
+ }
228862
229478
  setAuthToken(token) {
228863
229479
  this.options.authToken = token;
228864
229480
  }
@@ -229045,7 +229661,6 @@ class EnactCore {
229045
229661
  }
229046
229662
  }
229047
229663
  async verifyTool(tool, dangerouslySkipVerification = false) {
229048
- console.log("=== VERIFY TOOL CALLED ===", tool.name, "skipVerification:", dangerouslySkipVerification);
229049
229664
  if (dangerouslySkipVerification) {
229050
229665
  logger_default.warn(`Skipping signature verification for tool: ${tool.name}`);
229051
229666
  return;
@@ -229054,9 +229669,6 @@ class EnactCore {
229054
229669
  if (!tool.signatures || tool.signatures.length === 0) {
229055
229670
  throw new Error(`Tool ${tool.name} does not have any signatures`);
229056
229671
  }
229057
- console.log("=== TOOL SIGNATURE DATA ===");
229058
- console.log("Tool signatures from database:", JSON.stringify(tool.signatures, null, 2));
229059
- console.log("Tool command:", tool.command);
229060
229672
  const documentForVerification = {
229061
229673
  command: tool.command
229062
229674
  };
@@ -229067,20 +229679,9 @@ class EnactCore {
229067
229679
  timestamp: new Date(tool.signatures[0].created).getTime()
229068
229680
  };
229069
229681
  const canonicalDoc = SigningService.getCanonicalDocument(documentForVerification, { includeFields: ["command"] });
229070
- console.log("=== SIGNATURE VERIFICATION DEBUG ===");
229071
- console.log("Original document for verification:", JSON.stringify(documentForVerification, null, 2));
229072
- console.log("Canonical document:", JSON.stringify(canonicalDoc, null, 2));
229073
229682
  const docString = JSON.stringify(canonicalDoc);
229074
229683
  const messageHash = CryptoUtils.hash(docString);
229075
- console.log("Document string:", docString);
229076
- console.log("Message hash:", messageHash);
229077
- console.log("Reference signature object:", JSON.stringify(referenceSignature, null, 2));
229078
229684
  const directVerify = CryptoUtils.verify(referenceSignature.publicKey, messageHash, referenceSignature.signature);
229079
- console.log("KEITH DEBUG - Direct crypto verification result:", directVerify, "publicKey:", referenceSignature.publicKey);
229080
- const trustedKeys = KeyManager.getAllTrustedPublicKeys();
229081
- console.log("Trusted keys:", trustedKeys);
229082
- console.log("Our referenceSignature.publicKey:", JSON.stringify(referenceSignature.publicKey));
229083
- console.log("Is our public key trusted?", trustedKeys.includes(referenceSignature.publicKey));
229084
229685
  const isValid = SigningService.verifyDocument(documentForVerification, referenceSignature, { includeFields: ["command"] });
229085
229686
  console.log("Final verification result:", isValid);
229086
229687
  if (!isValid) {
@@ -229427,7 +230028,7 @@ ${import_picocolors13.default.bold("EXAMPLES:")}
229427
230028
  author,
229428
230029
  format
229429
230030
  };
229430
- const apiClient = new EnactApiClient("https://enact.tools", "https://xjnhhxwxovjifdxdwzih.supabase.co");
230031
+ const apiClient = await EnactApiClient.create();
229431
230032
  const searchResults = await apiClient.searchTools(searchOptions);
229432
230033
  const results = [];
229433
230034
  for (const result of searchResults) {
@@ -229685,7 +230286,7 @@ Examples:
229685
230286
  toolDefinition = await loadLocalTool(toolIdentifier);
229686
230287
  spinner.stop("Local tool definition loaded");
229687
230288
  } else {
229688
- const apiClient = new EnactApiClient("https://enact.tools", "https://xjnhhxwxovjifdxdwzih.supabase.co");
230289
+ const apiClient = await EnactApiClient.create();
229689
230290
  toolDefinition = await apiClient.getTool(toolIdentifier);
229690
230291
  spinner.stop("Tool definition fetched");
229691
230292
  }
@@ -229913,7 +230514,7 @@ Environment variables:`));
229913
230514
  }
229914
230515
  if (!isLocalFile) {
229915
230516
  try {
229916
- const apiClient = new EnactApiClient("https://enact.tools", "https://xjnhhxwxovjifdxdwzih.supabase.co");
230517
+ const apiClient = await EnactApiClient.create();
229917
230518
  await apiClient.logToolUsage(toolIdentifier, {
229918
230519
  action: "execute",
229919
230520
  metadata: {
@@ -230016,7 +230617,7 @@ ${import_picocolors13.default.bold("EXAMPLES:")}
230016
230617
  Ie(import_picocolors13.default.bgBlue(import_picocolors13.default.black(" Getting Tool Info ")));
230017
230618
  const spinner = Y2();
230018
230619
  spinner.start(`Fetching ${toolName}...`);
230019
- const apiClient = new EnactApiClient("https://enact.tools", "https://xjnhhxwxovjifdxdwzih.supabase.co");
230620
+ const apiClient = await EnactApiClient.create();
230020
230621
  const toolDefinition = await apiClient.getTool(toolName);
230021
230622
  if (!toolDefinition) {
230022
230623
  spinner.stop("Tool not found");
@@ -230115,8 +230716,8 @@ function displayResultsTable(results) {
230115
230716
  console.error(`
230116
230717
  ` + import_picocolors13.default.bold("Search Results:"));
230117
230718
  console.error("═".repeat(100));
230118
- const nameWidth = 25;
230119
- const descWidth = 50;
230719
+ const nameWidth = 40;
230720
+ const descWidth = 45;
230120
230721
  const tagsWidth = 20;
230121
230722
  console.error(import_picocolors13.default.bold(import_picocolors13.default.cyan("NAME".padEnd(nameWidth))) + " │ " + import_picocolors13.default.bold(import_picocolors13.default.cyan("DESCRIPTION".padEnd(descWidth))) + " │ " + import_picocolors13.default.bold(import_picocolors13.default.cyan("TAGS".padEnd(tagsWidth))));
230122
230723
  console.error("─".repeat(nameWidth) + "─┼─" + "─".repeat(descWidth) + "─┼─" + "─".repeat(tagsWidth));
@@ -230587,7 +231188,8 @@ async function main() {
230587
231188
  case "mcp":
230588
231189
  await handleMcpCommand(commandArgs, {
230589
231190
  help: values.help,
230590
- client: values.client
231191
+ client: values.client,
231192
+ server: values.server
230591
231193
  });
230592
231194
  break;
230593
231195
  case "config":