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