@frontmcp/sdk 1.0.0 → 1.0.2

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.
package/index.js CHANGED
@@ -3116,8 +3116,8 @@ var init_job_metadata = __esm({
3116
3116
  });
3117
3117
 
3118
3118
  // libs/sdk/src/common/metadata/workflow.metadata.ts
3119
- function isValidWebhookPath(path) {
3120
- return WEBHOOK_PATH_PATTERN.test(path);
3119
+ function isValidWebhookPath(path2) {
3120
+ return WEBHOOK_PATH_PATTERN.test(path2);
3121
3121
  }
3122
3122
  var import_zod34, workflowStepSchema, WEBHOOK_PATH_PATTERN, workflowWebhookConfigSchema, frontMcpWorkflowMetadataSchema;
3123
3123
  var init_workflow_metadata = __esm({
@@ -4390,8 +4390,8 @@ var init_sdk_errors = __esm({
4390
4390
  }
4391
4391
  };
4392
4392
  ConfigNotFoundError = class extends InternalMcpError {
4393
- constructor(path, triedPaths) {
4394
- const msg = triedPaths?.length ? `Config not found at "${path}". Tried: ${triedPaths.join(", ")}` : `Config not found at "${path}"`;
4393
+ constructor(path2, triedPaths) {
4394
+ const msg = triedPaths?.length ? `Config not found at "${path2}". Tried: ${triedPaths.join(", ")}` : `Config not found at "${path2}"`;
4395
4395
  super(msg, "CONFIG_NOT_FOUND");
4396
4396
  }
4397
4397
  };
@@ -4456,8 +4456,8 @@ var init_sdk_errors = __esm({
4456
4456
  }
4457
4457
  };
4458
4458
  AgentConfigKeyNotFoundError = class extends InternalMcpError {
4459
- constructor(path) {
4460
- super(`Agent config key not found: "${path}"`, "AGENT_CONFIG_KEY_NOT_FOUND");
4459
+ constructor(path2) {
4460
+ super(`Agent config key not found: "${path2}"`, "AGENT_CONFIG_KEY_NOT_FOUND");
4461
4461
  }
4462
4462
  };
4463
4463
  AgentToolExecutionError = class extends InternalMcpError {
@@ -4484,8 +4484,8 @@ var init_sdk_errors = __esm({
4484
4484
  }
4485
4485
  };
4486
4486
  RequiredConfigUndefinedError = class extends InternalMcpError {
4487
- constructor(path) {
4488
- super(`Required configuration path "${path}" is undefined`, "REQUIRED_CONFIG_UNDEFINED");
4487
+ constructor(path2) {
4488
+ super(`Required configuration path "${path2}" is undefined`, "REQUIRED_CONFIG_UNDEFINED");
4489
4489
  }
4490
4490
  };
4491
4491
  RegistryNotInitializedError = class extends InternalMcpError {
@@ -5665,8 +5665,8 @@ ${formattedErrors}`);
5665
5665
  constructor(config) {
5666
5666
  this.config = config;
5667
5667
  }
5668
- get(path, defaultValue) {
5669
- const keys = path.split(".");
5668
+ get(path2, defaultValue) {
5669
+ const keys = path2.split(".");
5670
5670
  let result = this.config;
5671
5671
  for (const key of keys) {
5672
5672
  if (result && typeof result === "object" && key in result) {
@@ -5687,18 +5687,18 @@ ${formattedErrors}`);
5687
5687
  * @example
5688
5688
  * config.getOrThrow('database.url') // string (throws if missing)
5689
5689
  */
5690
- getOrThrow(path) {
5691
- const value = this.get(path);
5690
+ getOrThrow(path2) {
5691
+ const value = this.get(path2);
5692
5692
  if (value === void 0) {
5693
- throw new ConfigMissingError(path);
5693
+ throw new ConfigMissingError(path2);
5694
5694
  }
5695
5695
  return value;
5696
5696
  }
5697
5697
  /**
5698
5698
  * Alias for getOrThrow.
5699
5699
  */
5700
- getRequired(path) {
5701
- return this.getOrThrow(path);
5700
+ getRequired(path2) {
5701
+ return this.getOrThrow(path2);
5702
5702
  }
5703
5703
  /**
5704
5704
  * Check if a configuration path exists and has a value.
@@ -5706,8 +5706,8 @@ ${formattedErrors}`);
5706
5706
  * @param path - Dot notation path (e.g., 'database.url')
5707
5707
  * @returns True if path exists and has a defined value
5708
5708
  */
5709
- has(path) {
5710
- const keys = path.split(".");
5709
+ has(path2) {
5710
+ const keys = path2.split(".");
5711
5711
  let result = this.config;
5712
5712
  for (const key of keys) {
5713
5713
  if (result && typeof result === "object" && key in result) {
@@ -5739,8 +5739,8 @@ ${formattedErrors}`);
5739
5739
  * @param defaultValue - Default value if not found or not a number
5740
5740
  * @returns Number value or NaN
5741
5741
  */
5742
- getNumber(path, defaultValue) {
5743
- const value = this.get(path);
5742
+ getNumber(path2, defaultValue) {
5743
+ const value = this.get(path2);
5744
5744
  if (value === void 0) {
5745
5745
  return defaultValue ?? NaN;
5746
5746
  }
@@ -5758,8 +5758,8 @@ ${formattedErrors}`);
5758
5758
  * @param defaultValue - Default value if not found
5759
5759
  * @returns Boolean value
5760
5760
  */
5761
- getBoolean(path, defaultValue) {
5762
- const value = this.get(path);
5761
+ getBoolean(path2, defaultValue) {
5762
+ const value = this.get(path2);
5763
5763
  if (value === void 0) {
5764
5764
  return defaultValue ?? false;
5765
5765
  }
@@ -6382,22 +6382,22 @@ var init_provider_registry = __esm({
6382
6382
  const WHITE = 0, GRAY = 1, BLACK = 2;
6383
6383
  const color = /* @__PURE__ */ new Map();
6384
6384
  const order = /* @__PURE__ */ new Set();
6385
- const path = [];
6385
+ const path2 = [];
6386
6386
  const dfs = (n) => {
6387
6387
  color.set(n, GRAY);
6388
- path.push(n);
6388
+ path2.push(n);
6389
6389
  for (const dep of this.graph.get(n) ?? []) {
6390
6390
  const c = color.get(dep) ?? WHITE;
6391
6391
  if (c === GRAY) {
6392
- const idx = path.findIndex((p) => p === dep);
6393
- const cycle = [...path.slice(idx), dep].map((t) => (0, import_di7.tokenName)(t)).join(" -> ");
6392
+ const idx = path2.findIndex((p) => p === dep);
6393
+ const cycle = [...path2.slice(idx), dep].map((t) => (0, import_di7.tokenName)(t)).join(" -> ");
6394
6394
  throw new DependencyCycleError(cycle);
6395
6395
  }
6396
6396
  if (c === WHITE) dfs(dep);
6397
6397
  }
6398
6398
  color.set(n, BLACK);
6399
6399
  order.add(n);
6400
- path.pop();
6400
+ path2.pop();
6401
6401
  };
6402
6402
  for (const n of this.graph.keys()) if ((color.get(n) ?? WHITE) === WHITE) dfs(n);
6403
6403
  this.order = order;
@@ -14902,7 +14902,59 @@ var init_skill_utils = __esm({
14902
14902
  function createSkillInstance(record, providers, owner) {
14903
14903
  return new SkillInstance(record, providers, owner);
14904
14904
  }
14905
- var import_utils34, SkillInstance;
14905
+ async function loadResourceWithManifestFallback(resourcePath, baseDir, skillName, resourceType, loader) {
14906
+ if (!resourcePath) return void 0;
14907
+ let dir = resourcePath.startsWith("/") ? resourcePath : baseDir ? (0, import_utils34.pathResolve)(baseDir, resourcePath) : void 0;
14908
+ if (dir) {
14909
+ try {
14910
+ return await loader(dir);
14911
+ } catch (err) {
14912
+ if (err.code !== "ENOENT") throw err;
14913
+ dir = await resolveResourceFromManifest(skillName, resourceType);
14914
+ if (dir) return await loader(dir);
14915
+ }
14916
+ } else {
14917
+ dir = await resolveResourceFromManifest(skillName, resourceType);
14918
+ if (dir) return await loader(dir);
14919
+ }
14920
+ return void 0;
14921
+ }
14922
+ async function resolveFromSkillManifest(skillName) {
14923
+ if (skillManifestCache === null) return void 0;
14924
+ if (skillManifestCache === void 0) {
14925
+ try {
14926
+ const mainDir2 = require.main?.filename ? (0, import_utils34.dirname)(require.main.filename) : process.cwd();
14927
+ const manifestPath = (0, import_utils34.pathJoin)(mainDir2, "_skills", "manifest.json");
14928
+ if (await (0, import_utils34.fileExists)(manifestPath)) {
14929
+ skillManifestCache = await (0, import_utils34.readJSON)(manifestPath);
14930
+ } else {
14931
+ skillManifestCache = null;
14932
+ return void 0;
14933
+ }
14934
+ } catch (err) {
14935
+ if (err.code === "ENOENT") {
14936
+ skillManifestCache = null;
14937
+ return void 0;
14938
+ }
14939
+ throw err;
14940
+ }
14941
+ }
14942
+ if (!skillManifestCache) return void 0;
14943
+ const entry = skillManifestCache[skillName];
14944
+ if (!entry?.instructions) return void 0;
14945
+ const mainDir = require.main?.filename ? (0, import_utils34.dirname)(require.main.filename) : process.cwd();
14946
+ return (0, import_utils34.pathResolve)(mainDir, entry.instructions);
14947
+ }
14948
+ async function resolveResourceFromManifest(skillName, resourceType) {
14949
+ await resolveFromSkillManifest(skillName);
14950
+ if (!skillManifestCache) return void 0;
14951
+ const entry = skillManifestCache[skillName];
14952
+ const relPath = entry?.[resourceType];
14953
+ if (!relPath) return void 0;
14954
+ const mainDir = require.main?.filename ? (0, import_utils34.dirname)(require.main.filename) : process.cwd();
14955
+ return (0, import_utils34.pathResolve)(mainDir, relPath);
14956
+ }
14957
+ var import_utils34, SkillInstance, skillManifestCache;
14906
14958
  var init_skill_instance = __esm({
14907
14959
  "libs/sdk/src/skill/skill.instance.ts"() {
14908
14960
  "use strict";
@@ -14964,7 +15016,20 @@ var init_skill_instance = __esm({
14964
15016
  } else if (this.record.kind === "VALUE" /* VALUE */ && this.record.callerDir) {
14965
15017
  basePath = this.record.callerDir;
14966
15018
  }
14967
- this.cachedInstructions = await loadInstructions(this.metadata.instructions, basePath);
15019
+ try {
15020
+ this.cachedInstructions = await loadInstructions(this.metadata.instructions, basePath);
15021
+ } catch (err) {
15022
+ if (err.code === "ENOENT") {
15023
+ const resolved = await resolveFromSkillManifest(this.metadata.name);
15024
+ if (resolved) {
15025
+ this.cachedInstructions = await loadInstructions({ file: resolved }, void 0);
15026
+ } else {
15027
+ throw err;
15028
+ }
15029
+ } else {
15030
+ throw err;
15031
+ }
15032
+ }
14968
15033
  return this.cachedInstructions;
14969
15034
  }
14970
15035
  /**
@@ -14989,22 +15054,20 @@ var init_skill_instance = __esm({
14989
15054
  }
14990
15055
  const instructions = await this.loadInstructions();
14991
15056
  const baseDir = this.getBaseDir();
14992
- const refsPath = this.metadata.resources?.references;
14993
- let resolvedRefs;
14994
- if (refsPath) {
14995
- const refsDir = refsPath.startsWith("/") ? refsPath : baseDir ? (0, import_utils34.pathResolve)(baseDir, refsPath) : void 0;
14996
- if (refsDir) {
14997
- resolvedRefs = await resolveReferences(refsDir);
14998
- }
14999
- }
15000
- const examplesPath = this.metadata.resources?.examples;
15001
- let resolvedExs;
15002
- if (examplesPath) {
15003
- const exDir = examplesPath.startsWith("/") ? examplesPath : baseDir ? (0, import_utils34.pathResolve)(baseDir, examplesPath) : void 0;
15004
- if (exDir) {
15005
- resolvedExs = await resolveExamples(exDir);
15006
- }
15007
- }
15057
+ const resolvedRefs = await loadResourceWithManifestFallback(
15058
+ this.metadata.resources?.references,
15059
+ baseDir,
15060
+ this.metadata.name,
15061
+ "references",
15062
+ resolveReferences
15063
+ );
15064
+ const resolvedExs = await loadResourceWithManifestFallback(
15065
+ this.metadata.resources?.examples,
15066
+ baseDir,
15067
+ this.metadata.name,
15068
+ "examples",
15069
+ resolveExamples
15070
+ );
15008
15071
  const baseContent = buildSkillContent(this.metadata, instructions, resolvedRefs, resolvedExs);
15009
15072
  this.cachedContent = {
15010
15073
  ...baseContent,
@@ -17936,8 +17999,8 @@ function generateEnvFallbacks(key, context) {
17936
17999
  ];
17937
18000
  }
17938
18001
  function resolveWithFallbacks(config, paths) {
17939
- for (const path of paths) {
17940
- const value = config.get(path);
18002
+ for (const path2 of paths) {
18003
+ const value = config.get(path2);
17941
18004
  if (value !== void 0) {
17942
18005
  return value;
17943
18006
  }
@@ -17946,31 +18009,31 @@ function resolveWithFallbacks(config, paths) {
17946
18009
  }
17947
18010
  function createContextResolver(config, context) {
17948
18011
  return {
17949
- get(path) {
17950
- const fallbacks = generateFallbacks(path, context);
18012
+ get(path2) {
18013
+ const fallbacks = generateFallbacks(path2, context);
17951
18014
  const value = resolveWithFallbacks(config, fallbacks);
17952
18015
  if (value === void 0) {
17953
- throw new ConfigNotFoundError(path, fallbacks);
18016
+ throw new ConfigNotFoundError(path2, fallbacks);
17954
18017
  }
17955
18018
  return value;
17956
18019
  },
17957
- tryGet(path) {
17958
- const fallbacks = generateFallbacks(path, context);
18020
+ tryGet(path2) {
18021
+ const fallbacks = generateFallbacks(path2, context);
17959
18022
  return resolveWithFallbacks(config, fallbacks);
17960
18023
  }
17961
18024
  };
17962
18025
  }
17963
18026
  function createDirectResolver(config) {
17964
18027
  return {
17965
- get(path) {
17966
- const value = config.get(path);
18028
+ get(path2) {
18029
+ const value = config.get(path2);
17967
18030
  if (value === void 0) {
17968
- throw new ConfigNotFoundError(path);
18031
+ throw new ConfigNotFoundError(path2);
17969
18032
  }
17970
18033
  return value;
17971
18034
  },
17972
- tryGet(path) {
17973
- return config.get(path);
18035
+ tryGet(path2) {
18036
+ return config.get(path2);
17974
18037
  }
17975
18038
  };
17976
18039
  }
@@ -17993,8 +18056,8 @@ function resolveWithConfigValue(withConfig2, configResolver, entityContext) {
17993
18056
  } else {
17994
18057
  paths = [withConfig2.configPath];
17995
18058
  }
17996
- for (const path of paths) {
17997
- const value = configResolver.tryGet(path);
18059
+ for (const path2 of paths) {
18060
+ const value = configResolver.tryGet(path2);
17998
18061
  if (value !== void 0) {
17999
18062
  return withConfig2.transform ? withConfig2.transform(value) : value;
18000
18063
  }
@@ -18231,11 +18294,11 @@ function populateProcessEnv(env, override = false) {
18231
18294
  function isSafeKey(key) {
18232
18295
  return !UNSAFE_KEYS.has(key);
18233
18296
  }
18234
- function pathToEnvKey(path) {
18235
- return path.toUpperCase().replace(/\./g, "_");
18297
+ function pathToEnvKey(path2) {
18298
+ return path2.toUpperCase().replace(/\./g, "_");
18236
18299
  }
18237
- function setNestedValue(obj, path, value) {
18238
- const keys = path.split(".");
18300
+ function setNestedValue(obj, path2, value) {
18301
+ const keys = path2.split(".");
18239
18302
  for (const key of keys) {
18240
18303
  if (!isSafeKey(key)) {
18241
18304
  return;
@@ -18258,8 +18321,8 @@ function setNestedValue(obj, path, value) {
18258
18321
  }
18259
18322
  current[finalKey] = value;
18260
18323
  }
18261
- function getNestedValue(obj, path) {
18262
- const keys = path.split(".");
18324
+ function getNestedValue(obj, path2) {
18325
+ const keys = path2.split(".");
18263
18326
  for (const key of keys) {
18264
18327
  if (!isSafeKey(key)) {
18265
18328
  return void 0;
@@ -18314,11 +18377,11 @@ function unwrapZodType(schema) {
18314
18377
  }
18315
18378
  function mapEnvToNestedConfig(env, paths) {
18316
18379
  const result = {};
18317
- for (const path of paths) {
18318
- const envKey = pathToEnvKey(path);
18380
+ for (const path2 of paths) {
18381
+ const envKey = pathToEnvKey(path2);
18319
18382
  const value = env[envKey];
18320
18383
  if (value !== void 0) {
18321
- setNestedValue(result, path, value);
18384
+ setNestedValue(result, path2, value);
18322
18385
  }
18323
18386
  }
18324
18387
  return result;
@@ -18870,8 +18933,8 @@ var init_flow_instance = __esm({
18870
18933
  this.stages = collectFlowHookMap(this.FlowClass);
18871
18934
  const { middleware } = this.metadata;
18872
18935
  if (middleware) {
18873
- const path = typeof middleware.path === "string" ? middleware.path : "";
18874
- server.registerMiddleware(path, async (request, response, next) => {
18936
+ const path2 = typeof middleware.path === "string" ? middleware.path : "";
18937
+ server.registerMiddleware(path2, async (request, response, next) => {
18875
18938
  const canActivate = await this.canActivate(request);
18876
18939
  if (!canActivate) return next();
18877
18940
  const contextStorage = this.getContextStorage();
@@ -19906,8 +19969,8 @@ var init_agent_instance = __esm({
19906
19969
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
19907
19970
  createConfigResolver(configService) {
19908
19971
  const config = configService.getAll();
19909
- const getNestedValue2 = (path) => {
19910
- const keys = path.split(".");
19972
+ const getNestedValue2 = (path2) => {
19973
+ const keys = path2.split(".");
19911
19974
  let current = config;
19912
19975
  for (const key of keys) {
19913
19976
  if (current && typeof current === "object" && key in current) {
@@ -19919,15 +19982,15 @@ var init_agent_instance = __esm({
19919
19982
  return current;
19920
19983
  };
19921
19984
  return {
19922
- get(path) {
19923
- const value = getNestedValue2(path);
19985
+ get(path2) {
19986
+ const value = getNestedValue2(path2);
19924
19987
  if (value === void 0) {
19925
- throw new AgentConfigKeyNotFoundError(path);
19988
+ throw new AgentConfigKeyNotFoundError(path2);
19926
19989
  }
19927
19990
  return value;
19928
19991
  },
19929
- tryGet(path) {
19930
- return getNestedValue2(path);
19992
+ tryGet(path2) {
19993
+ return getNestedValue2(path2);
19931
19994
  }
19932
19995
  };
19933
19996
  }
@@ -22912,21 +22975,21 @@ function getDefaultCacheDir() {
22912
22975
  return "";
22913
22976
  }
22914
22977
  try {
22915
- const path = require("node:path");
22978
+ const path2 = require("node:path");
22916
22979
  try {
22917
- const nodeModulesDir = path.join(process.cwd(), "node_modules");
22918
- const fs = require("node:fs");
22919
- if (fs.existsSync(nodeModulesDir)) {
22920
- return path.join(nodeModulesDir, ".cache", "frontmcp-esm");
22980
+ const nodeModulesDir = path2.join(process.cwd(), "node_modules");
22981
+ const fs2 = require("node:fs");
22982
+ if (fs2.existsSync(nodeModulesDir)) {
22983
+ return path2.join(nodeModulesDir, ".cache", "frontmcp-esm");
22921
22984
  }
22922
22985
  } catch {
22923
22986
  }
22924
22987
  try {
22925
- const os = require("node:os");
22926
- return path.join(os.homedir(), ".frontmcp", "esm-cache");
22988
+ const os2 = require("node:os");
22989
+ return path2.join(os2.homedir(), ".frontmcp", "esm-cache");
22927
22990
  } catch {
22928
22991
  }
22929
- return path.join(require("node:os").tmpdir?.() ?? "/tmp", ".frontmcp-esm-cache");
22992
+ return path2.join(require("node:os").tmpdir?.() ?? "/tmp", ".frontmcp-esm-cache");
22930
22993
  } catch {
22931
22994
  return "";
22932
22995
  }
@@ -22960,21 +23023,21 @@ var init_esm_cache = __esm({
22960
23023
  }
22961
23024
  if (!this.cacheDir) return void 0;
22962
23025
  try {
22963
- const path = require("node:path");
22964
- const { fileExists: fileExists6, readJSON } = require("@frontmcp/utils");
23026
+ const path2 = require("node:path");
23027
+ const { fileExists: fileExists8, readJSON: readJSON2 } = require("@frontmcp/utils");
22965
23028
  const entryDir = this.getEntryDir(packageName, version);
22966
- const metaPath = path.join(entryDir, "meta.json");
22967
- if (!await fileExists6(metaPath)) {
23029
+ const metaPath = path2.join(entryDir, "meta.json");
23030
+ if (!await fileExists8(metaPath)) {
22968
23031
  return void 0;
22969
23032
  }
22970
- const meta = await readJSON(metaPath);
23033
+ const meta = await readJSON2(metaPath);
22971
23034
  if (!meta) {
22972
23035
  return void 0;
22973
23036
  }
22974
23037
  if (Date.now() - meta.cachedAt > this.maxAgeMs) {
22975
23038
  return void 0;
22976
23039
  }
22977
- if (!await fileExists6(meta.bundlePath)) {
23040
+ if (!await fileExists8(meta.bundlePath)) {
22978
23041
  return void 0;
22979
23042
  }
22980
23043
  this.memoryStore.set(memKey, meta);
@@ -22994,12 +23057,12 @@ var init_esm_cache = __esm({
22994
23057
  let bundlePath = "";
22995
23058
  if (this.cacheDir) {
22996
23059
  try {
22997
- const path = require("node:path");
23060
+ const path2 = require("node:path");
22998
23061
  const { writeFile, ensureDir, writeJSON } = require("@frontmcp/utils");
22999
23062
  const entryDir = this.getEntryDir(packageName, version);
23000
23063
  await ensureDir(entryDir);
23001
23064
  const cachedBundle = toCachedBundle(bundleContent);
23002
- bundlePath = path.join(entryDir, cachedBundle.fileName);
23065
+ bundlePath = path2.join(entryDir, cachedBundle.fileName);
23003
23066
  await writeFile(bundlePath, cachedBundle.content);
23004
23067
  const diskEntry = {
23005
23068
  packageUrl,
@@ -23009,7 +23072,7 @@ var init_esm_cache = __esm({
23009
23072
  bundlePath,
23010
23073
  etag
23011
23074
  };
23012
- const metaPath = path.join(entryDir, "meta.json");
23075
+ const metaPath = path2.join(entryDir, "meta.json");
23013
23076
  await writeJSON(metaPath, diskEntry);
23014
23077
  } catch {
23015
23078
  }
@@ -23037,10 +23100,10 @@ var init_esm_cache = __esm({
23037
23100
  }
23038
23101
  if (!this.cacheDir) return;
23039
23102
  try {
23040
- const path = require("node:path");
23041
- const { fileExists: fileExists6, readJSON, rm } = require("@frontmcp/utils");
23103
+ const path2 = require("node:path");
23104
+ const { fileExists: fileExists8, readJSON: readJSON2, rm } = require("@frontmcp/utils");
23042
23105
  const { readdir: readdir2 } = require("@frontmcp/utils");
23043
- if (!await fileExists6(this.cacheDir)) {
23106
+ if (!await fileExists8(this.cacheDir)) {
23044
23107
  return;
23045
23108
  }
23046
23109
  let entries;
@@ -23050,11 +23113,11 @@ var init_esm_cache = __esm({
23050
23113
  return;
23051
23114
  }
23052
23115
  for (const dirEntry of entries) {
23053
- const metaPath = path.join(this.cacheDir, dirEntry, "meta.json");
23054
- if (await fileExists6(metaPath)) {
23055
- const meta = await readJSON(metaPath);
23116
+ const metaPath = path2.join(this.cacheDir, dirEntry, "meta.json");
23117
+ if (await fileExists8(metaPath)) {
23118
+ const meta = await readJSON2(metaPath);
23056
23119
  if (meta?.packageName === packageName) {
23057
- await rm(path.join(this.cacheDir, dirEntry), { recursive: true, force: true });
23120
+ await rm(path2.join(this.cacheDir, dirEntry), { recursive: true, force: true });
23058
23121
  }
23059
23122
  }
23060
23123
  }
@@ -23076,10 +23139,10 @@ var init_esm_cache = __esm({
23076
23139
  }
23077
23140
  if (!this.cacheDir) return removed;
23078
23141
  try {
23079
- const path = require("node:path");
23080
- const { fileExists: fileExists6, readJSON, rm } = require("@frontmcp/utils");
23142
+ const path2 = require("node:path");
23143
+ const { fileExists: fileExists8, readJSON: readJSON2, rm } = require("@frontmcp/utils");
23081
23144
  const { readdir: readdir2 } = require("@frontmcp/utils");
23082
- if (!await fileExists6(this.cacheDir)) {
23145
+ if (!await fileExists8(this.cacheDir)) {
23083
23146
  return removed;
23084
23147
  }
23085
23148
  let entries;
@@ -23089,11 +23152,11 @@ var init_esm_cache = __esm({
23089
23152
  return removed;
23090
23153
  }
23091
23154
  for (const dirEntry of entries) {
23092
- const metaPath = path.join(this.cacheDir, dirEntry, "meta.json");
23093
- if (await fileExists6(metaPath)) {
23094
- const meta = await readJSON(metaPath);
23155
+ const metaPath = path2.join(this.cacheDir, dirEntry, "meta.json");
23156
+ if (await fileExists8(metaPath)) {
23157
+ const meta = await readJSON2(metaPath);
23095
23158
  if (meta && now - meta.cachedAt > threshold) {
23096
- await rm(path.join(this.cacheDir, dirEntry), { recursive: true, force: true });
23159
+ await rm(path2.join(this.cacheDir, dirEntry), { recursive: true, force: true });
23097
23160
  removed++;
23098
23161
  }
23099
23162
  }
@@ -23116,9 +23179,9 @@ var init_esm_cache = __esm({
23116
23179
  * Get the cache directory for a specific package+version combination.
23117
23180
  */
23118
23181
  getEntryDir(packageName, version) {
23119
- const path = require("node:path");
23182
+ const path2 = require("node:path");
23120
23183
  const hash = (0, import_utils46.sha256Hex)(`${packageName}@${version}`);
23121
- return path.join(this.cacheDir, hash);
23184
+ return path2.join(this.cacheDir, hash);
23122
23185
  }
23123
23186
  };
23124
23187
  }
@@ -25636,8 +25699,8 @@ var init_oauth_authorize_flow = __esm({
25636
25699
  */
25637
25700
  formatZodErrors(error) {
25638
25701
  return error.issues.map((err) => {
25639
- const path = err.path.length > 0 ? `${err.path.join(".")}: ` : "";
25640
- return `${path}${err.message}`;
25702
+ const path2 = err.path.length > 0 ? `${err.path.join(".")}: ` : "";
25703
+ return `${path2}${err.message}`;
25641
25704
  });
25642
25705
  }
25643
25706
  /**
@@ -35080,8 +35143,8 @@ var init_skills_api_flow = __esm({
35080
35143
  const basePath = `${entryPrefix}${scopeBase}`;
35081
35144
  const apiPath = options.normalizedApi.path ?? "/skills";
35082
35145
  const fullPath = `${basePath}${apiPath}`;
35083
- const path = request.path;
35084
- return path === apiPath || path.startsWith(`${apiPath}/`) || path === fullPath || path.startsWith(`${fullPath}/`);
35146
+ const path2 = request.path;
35147
+ return path2 === apiPath || path2.startsWith(`${apiPath}/`) || path2 === fullPath || path2.startsWith(`${fullPath}/`);
35085
35148
  }
35086
35149
  async checkEnabled() {
35087
35150
  const skillsConfig = this.scope.metadata.skillsConfig;
@@ -35125,11 +35188,11 @@ var init_skills_api_flow = __esm({
35125
35188
  const apiPath = options.normalizedApi.path ?? "/skills";
35126
35189
  const fullPath = `${basePath}${apiPath}`;
35127
35190
  let skillId;
35128
- const path = request.path;
35129
- if (path.startsWith(`${fullPath}/`)) {
35130
- skillId = path.slice(fullPath.length + 1);
35131
- } else if (path.startsWith(`${apiPath}/`)) {
35132
- skillId = path.slice(apiPath.length + 1);
35191
+ const path2 = request.path;
35192
+ if (path2.startsWith(`${fullPath}/`)) {
35193
+ skillId = path2.slice(fullPath.length + 1);
35194
+ } else if (path2.startsWith(`${apiPath}/`)) {
35195
+ skillId = path2.slice(apiPath.length + 1);
35133
35196
  }
35134
35197
  const queryRaw = request.query?.["query"];
35135
35198
  const query = Array.isArray(queryRaw) ? queryRaw[0] : queryRaw;
@@ -36741,8 +36804,8 @@ function pathOf(req) {
36741
36804
  return String(raw).split("?")[0] || "/";
36742
36805
  }
36743
36806
  }
36744
- function isLegacySsePath(path) {
36745
- return path === "/sse" || path.endsWith("/sse");
36807
+ function isLegacySsePath(path2) {
36808
+ return path2 === "/sse" || path2.endsWith("/sse");
36746
36809
  }
36747
36810
  function tryDecodeTransportType(sessionId) {
36748
36811
  if (!sessionId) return;
@@ -36767,8 +36830,8 @@ function getQuerySessionId2(req) {
36767
36830
  function computeBitmap(req, cfg) {
36768
36831
  const method = req.method.toUpperCase();
36769
36832
  const accept = h(req, "accept");
36770
- const path = pathOf(req);
36771
- const postToMessage = method === "POST" && (path === "/message" || path.endsWith("/message"));
36833
+ const path2 = pathOf(req);
36834
+ const postToMessage = method === "POST" && (path2 === "/message" || path2.endsWith("/message"));
36772
36835
  const headerSessionId = h(req, "mcp-session-id");
36773
36836
  const querySessionId = postToMessage ? getQuerySessionId2(req) : void 0;
36774
36837
  const sessionId = headerSessionId ?? querySessionId;
@@ -36777,7 +36840,7 @@ function computeBitmap(req, cfg) {
36777
36840
  const acceptSSE = wantsSSE(accept);
36778
36841
  const acceptJSON = wantsJSON(accept) || !accept && cfg.tolerateMissingAccept;
36779
36842
  const init = method === "POST" && isInitialize(req.body);
36780
- const getToSsePath = method === "GET" && isLegacySsePath(path);
36843
+ const getToSsePath = method === "GET" && isLegacySsePath(path2);
36781
36844
  const channel = method === "POST" && postToMessage ? CH_POST_MESSAGE : getToSsePath && acceptSSE ? CH_GET_SSE_PATH : method === "GET" && acceptSSE ? CH_GET_SSE : method === "POST" && init && acceptSSE ? CH_POST_INIT_SSE : method === "POST" && init && acceptJSON ? CH_POST_INIT_JSON : method === "POST" && !init && acceptSSE ? CH_POST_SSE : method === "POST" && !init && acceptJSON ? CH_POST_JSON : CH_OTHER;
36782
36845
  let flags = 0;
36783
36846
  if (sessionId) flags |= B_HAS_SESSION;
@@ -44503,8 +44566,8 @@ var init_express_host_adapter = __esm({
44503
44566
  next();
44504
44567
  });
44505
44568
  }
44506
- registerRoute(method, path, handler) {
44507
- this.router[method.toLowerCase()](path, this.enhancedHandler(handler));
44569
+ registerRoute(method, path2, handler) {
44570
+ this.router[method.toLowerCase()](path2, this.enhancedHandler(handler));
44508
44571
  }
44509
44572
  registerMiddleware(entryPath, handler) {
44510
44573
  this.router.use(entryPath, handler);
@@ -44546,8 +44609,8 @@ var init_express_host_adapter = __esm({
44546
44609
  server.on("error", reject);
44547
44610
  server.listen(portOrSocketPath, () => {
44548
44611
  try {
44549
- const fs = require("node:fs");
44550
- fs.chmodSync(portOrSocketPath, 432);
44612
+ const fs2 = require("node:fs");
44613
+ fs2.chmodSync(portOrSocketPath, 432);
44551
44614
  } catch {
44552
44615
  }
44553
44616
  console.log(`MCP HTTP (Express) on unix://${portOrSocketPath}`);
@@ -44618,8 +44681,8 @@ var init_server_instance = __esm({
44618
44681
  registerMiddleware(entryPath, handler) {
44619
44682
  return this.host.registerMiddleware(entryPath, handler);
44620
44683
  }
44621
- registerRoute(method, path, handler) {
44622
- return this.host.registerRoute(method, path, handler);
44684
+ registerRoute(method, path2, handler) {
44685
+ return this.host.registerRoute(method, path2, handler);
44623
44686
  }
44624
44687
  enhancedHandler(handler) {
44625
44688
  return this.host.enhancedHandler(handler);
@@ -45017,6 +45080,37 @@ var direct_client_exports = {};
45017
45080
  __export(direct_client_exports, {
45018
45081
  DirectClientImpl: () => DirectClientImpl
45019
45082
  });
45083
+ function findFileFromRoot(root, relativePath) {
45084
+ const fs2 = require("fs");
45085
+ const path2 = require("path");
45086
+ const cleanRelative = relativePath.replace(/^\.\//, "");
45087
+ const searchDirs = ["src", "."];
45088
+ for (const srcDir of searchDirs) {
45089
+ const srcRoot = path2.join(root, srcDir);
45090
+ if (!fs2.existsSync(srcRoot)) continue;
45091
+ const found = walkForFile(srcRoot, cleanRelative, fs2, path2);
45092
+ if (found) return found;
45093
+ }
45094
+ return void 0;
45095
+ }
45096
+ function walkForFile(dir, targetRelative, fs2, path2, maxDepth = 10) {
45097
+ const candidate = path2.join(dir, targetRelative);
45098
+ if (fs2.existsSync(candidate)) {
45099
+ return { absolute: candidate, baseDir: dir };
45100
+ }
45101
+ if (maxDepth <= 0) return void 0;
45102
+ try {
45103
+ const entries = fs2.readdirSync(dir, { withFileTypes: true });
45104
+ for (const entry of entries) {
45105
+ if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules" && entry.name !== "dist") {
45106
+ const result = walkForFile(path2.join(dir, entry.name), targetRelative, fs2, path2, maxDepth - 1);
45107
+ if (result) return result;
45108
+ }
45109
+ }
45110
+ } catch {
45111
+ }
45112
+ return void 0;
45113
+ }
45020
45114
  var import_utils81, import_protocol44, DirectClientImpl;
45021
45115
  var init_direct_client = __esm({
45022
45116
  "libs/sdk/src/direct/direct-client.ts"() {
@@ -45042,6 +45136,8 @@ var init_direct_client = __esm({
45042
45136
  resourceUpdateHandlers = /* @__PURE__ */ new Set();
45043
45137
  // Generic notification handlers
45044
45138
  notificationHandlers = /* @__PURE__ */ new Set();
45139
+ // Scope reference for build-time operations (collectSkillAssets)
45140
+ scopeRef;
45045
45141
  constructor(mcpClient, sessionId, clientInfo, serverInfo, capabilities) {
45046
45142
  this.mcpClient = mcpClient;
45047
45143
  this.sessionId = sessionId;
@@ -45094,6 +45190,7 @@ var init_direct_client = __esm({
45094
45190
  }
45095
45191
  const client = new _DirectClientImpl(mcpClient, sessionId, clientInfo, serverInfo, serverCapabilities);
45096
45192
  client.closeServer = close;
45193
+ client.scopeRef = scope;
45097
45194
  await client.setupNotificationHandlers(mcpClient);
45098
45195
  return client;
45099
45196
  } catch (error) {
@@ -45397,6 +45494,52 @@ var init_direct_client = __esm({
45397
45494
  async getWorkflowStatus(runId) {
45398
45495
  return this.callToolAndParseJson("get-workflow-status", { runId });
45399
45496
  }
45497
+ // ─────────────────────────────────────────────────────────────────────────────
45498
+ // Build-Time Asset Collection
45499
+ // ─────────────────────────────────────────────────────────────────────────────
45500
+ async collectSkillAssets() {
45501
+ const scope = this.scopeRef;
45502
+ if (!scope?.skills) return { entries: [] };
45503
+ const skills = scope.skills.getSkills({ includeHidden: true });
45504
+ const entries = [];
45505
+ for (const skill of skills) {
45506
+ const baseDir = skill.getBaseDir?.();
45507
+ const meta = skill.metadata;
45508
+ const entry = {
45509
+ skillName: meta.name,
45510
+ baseDir
45511
+ };
45512
+ if (meta.instructions && typeof meta.instructions === "object" && "file" in meta.instructions) {
45513
+ const filePath = meta.instructions.file;
45514
+ const resolved = filePath.startsWith("/") ? filePath : baseDir ? (0, import_utils81.pathResolve)(baseDir, filePath) : void 0;
45515
+ if (resolved && await (0, import_utils81.fileExists)(resolved)) {
45516
+ entry.instructionFile = resolved;
45517
+ } else if (!filePath.startsWith("/")) {
45518
+ const fromCwd = findFileFromRoot(process.cwd(), filePath);
45519
+ if (fromCwd) {
45520
+ entry.instructionFile = fromCwd.absolute;
45521
+ entry.baseDir = fromCwd.baseDir;
45522
+ }
45523
+ }
45524
+ }
45525
+ const resources = skill.getResources?.();
45526
+ if (resources) {
45527
+ entry.resources = {};
45528
+ for (const key of ["references", "examples", "scripts", "assets"]) {
45529
+ const p = resources[key];
45530
+ if (p) {
45531
+ const base = entry.baseDir || baseDir;
45532
+ const resolved = p.startsWith("/") ? p : base ? (0, import_utils81.pathResolve)(base, p) : void 0;
45533
+ if (resolved && await (0, import_utils81.fileExists)(resolved)) {
45534
+ entry.resources[key] = resolved;
45535
+ }
45536
+ }
45537
+ }
45538
+ }
45539
+ entries.push(entry);
45540
+ }
45541
+ return { entries };
45542
+ }
45400
45543
  };
45401
45544
  }
45402
45545
  });
@@ -45766,6 +45909,102 @@ var init_direct = __esm({
45766
45909
  }
45767
45910
  });
45768
45911
 
45912
+ // libs/sdk/src/logger/instances/instance.file-logger.ts
45913
+ function stripAnsi(str) {
45914
+ return str.split(ESC).map((s) => s.replace(/\[[0-9;]*m/, "")).join("");
45915
+ }
45916
+ var path, fs, os, LOG_LEVEL_LABELS, ESC, DEFAULT_LOGS_MAX, FileLogTransportInstance;
45917
+ var init_instance_file_logger = __esm({
45918
+ "libs/sdk/src/logger/instances/instance.file-logger.ts"() {
45919
+ "use strict";
45920
+ init_common();
45921
+ path = __toESM(require("path"));
45922
+ fs = __toESM(require("fs"));
45923
+ os = __toESM(require("os"));
45924
+ LOG_LEVEL_LABELS = {
45925
+ [100 /* Off */]: "OFF",
45926
+ [0 /* Debug */]: "DEBUG",
45927
+ [1 /* Verbose */]: "VERBOSE",
45928
+ [2 /* Info */]: "INFO",
45929
+ [3 /* Warn */]: "WARN",
45930
+ [4 /* Error */]: "ERROR"
45931
+ };
45932
+ ESC = String.fromCharCode(27);
45933
+ DEFAULT_LOGS_MAX = 25;
45934
+ FileLogTransportInstance = class extends LogTransportInterface {
45935
+ fd;
45936
+ logDir;
45937
+ appName;
45938
+ constructor() {
45939
+ super();
45940
+ const rawAppName = process.env["FRONTMCP_APP_NAME"] || "frontmcp";
45941
+ const sanitized = rawAppName.replace(/[^a-zA-Z0-9._-]/g, "_");
45942
+ this.appName = sanitized.length > 0 ? sanitized : "frontmcp";
45943
+ this.logDir = process.env["FRONTMCP_LOG_DIR"] || path.join(process.env["FRONTMCP_HOME"] || path.join(os.homedir(), ".frontmcp"), "logs");
45944
+ const logsMax = parseInt(process.env["FRONTMCP_LOGS_MAX"] || "", 10);
45945
+ if (logsMax === 0) {
45946
+ this.fd = void 0;
45947
+ return;
45948
+ }
45949
+ try {
45950
+ fs.mkdirSync(this.logDir, { recursive: true });
45951
+ const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "_");
45952
+ const filePath = path.join(this.logDir, `${this.appName}-${ts}.log`);
45953
+ this.fd = fs.openSync(filePath, "a");
45954
+ this.rotate(isNaN(logsMax) ? DEFAULT_LOGS_MAX : logsMax);
45955
+ } catch {
45956
+ this.fd = void 0;
45957
+ }
45958
+ }
45959
+ /** Close the file descriptor. Call during shutdown to prevent handle leaks. */
45960
+ close() {
45961
+ if (this.fd !== void 0) {
45962
+ try {
45963
+ fs.closeSync(this.fd);
45964
+ } catch {
45965
+ }
45966
+ this.fd = void 0;
45967
+ }
45968
+ }
45969
+ log(rec) {
45970
+ if (this.fd === void 0) return;
45971
+ const ts = rec.timestamp.toISOString();
45972
+ const level = LOG_LEVEL_LABELS[rec.level] ?? "INFO";
45973
+ const prefix = rec.prefix ? ` [${rec.prefix}]` : "";
45974
+ const message = stripAnsi(String(rec.message));
45975
+ const line = `[${ts}] ${level}${prefix} ${message}
45976
+ `;
45977
+ try {
45978
+ fs.writeSync(this.fd, line);
45979
+ } catch {
45980
+ }
45981
+ }
45982
+ /** Remove oldest log files when count exceeds max (npm-style rotation). */
45983
+ rotate(maxFiles) {
45984
+ try {
45985
+ const prefix = `${this.appName}-`;
45986
+ const files = fs.readdirSync(this.logDir).filter((f) => f.startsWith(prefix) && f.endsWith(".log")).sort();
45987
+ const excess = files.length - maxFiles;
45988
+ if (excess <= 0) return;
45989
+ for (let i = 0; i < excess; i++) {
45990
+ try {
45991
+ fs.unlinkSync(path.join(this.logDir, files[i]));
45992
+ } catch {
45993
+ }
45994
+ }
45995
+ } catch {
45996
+ }
45997
+ }
45998
+ };
45999
+ FileLogTransportInstance = __decorateClass([
46000
+ FrontMcpLogTransport({
46001
+ name: "FileLogger",
46002
+ description: "Writes logs to a file for CLI mode diagnostics"
46003
+ })
46004
+ ], FileLogTransportInstance);
46005
+ }
46006
+ });
46007
+
45769
46008
  // libs/sdk/src/front-mcp/front-mcp.ts
45770
46009
  var front_mcp_exports = {};
45771
46010
  __export(front_mcp_exports, {
@@ -45782,6 +46021,7 @@ var init_front_mcp = __esm({
45782
46021
  init_logger_registry();
45783
46022
  init_direct();
45784
46023
  init_errors();
46024
+ init_instance_file_logger();
45785
46025
  import_utils83 = require("@frontmcp/utils");
45786
46026
  init_health2();
45787
46027
  FrontMcpInstance = class _FrontMcpInstance2 {
@@ -45923,6 +46163,20 @@ var init_front_mcp = __esm({
45923
46163
  static async createForCli(options) {
45924
46164
  const parsedConfig = parseFrontMcpConfigLite(options);
45925
46165
  parsedConfig["__cliMode"] = true;
46166
+ const verbose = process.env["FRONTMCP_CLI_VERBOSE"] === "1";
46167
+ if (parsedConfig.logging) {
46168
+ parsedConfig.logging.enableConsole = verbose;
46169
+ const transports = parsedConfig.logging.transports ?? [];
46170
+ if (!transports.includes(FileLogTransportInstance)) {
46171
+ transports.push(FileLogTransportInstance);
46172
+ }
46173
+ parsedConfig.logging.transports = transports;
46174
+ } else {
46175
+ parsedConfig["logging"] = {
46176
+ enableConsole: verbose,
46177
+ transports: [FileLogTransportInstance]
46178
+ };
46179
+ }
45926
46180
  const frontMcp = new _FrontMcpInstance2(parsedConfig);
45927
46181
  await frontMcp.ready;
45928
46182
  return frontMcp;
@@ -47139,9 +47393,9 @@ var init_flow_entry = __esm({
47139
47393
  scope;
47140
47394
  constructor(scope, record, token, metadata) {
47141
47395
  super(record, token, metadata);
47142
- const { path, method } = record.metadata.middleware ?? metadata?.middleware ?? {};
47396
+ const { path: path2, method } = record.metadata.middleware ?? metadata?.middleware ?? {};
47143
47397
  this.name = metadata?.name ?? record.metadata?.name;
47144
- this.path = path;
47398
+ this.path = path2;
47145
47399
  this.method = method;
47146
47400
  this.scope = scope;
47147
47401
  }
@@ -47737,8 +47991,8 @@ var init_base_config_provider = __esm({
47737
47991
  getAll() {
47738
47992
  return this.config;
47739
47993
  }
47740
- get(path, defaultValue) {
47741
- const keys = path.split(".");
47994
+ get(path2, defaultValue) {
47995
+ const keys = path2.split(".");
47742
47996
  let result = this.config;
47743
47997
  for (const key of keys) {
47744
47998
  if (result && typeof result === "object" && key in result) {
@@ -47756,8 +48010,8 @@ var init_base_config_provider = __esm({
47756
48010
  * config.has('vm.preset') // returns true
47757
48011
  * config.has('nonexistent.path') // returns false
47758
48012
  */
47759
- has(path) {
47760
- const keys = path.split(".");
48013
+ has(path2) {
48014
+ const keys = path2.split(".");
47761
48015
  let result = this.config;
47762
48016
  for (const key of keys) {
47763
48017
  if (result && typeof result === "object" && key in result) {
@@ -47773,8 +48027,8 @@ var init_base_config_provider = __esm({
47773
48027
  * @example
47774
48028
  * config.getOrDefault('vm.timeout', 5000)
47775
48029
  */
47776
- getOrDefault(path, defaultValue) {
47777
- const value = this.get(path);
48030
+ getOrDefault(path2, defaultValue) {
48031
+ const value = this.get(path2);
47778
48032
  return value !== void 0 ? value : defaultValue;
47779
48033
  }
47780
48034
  /**
@@ -47783,10 +48037,10 @@ var init_base_config_provider = __esm({
47783
48037
  * config.getRequired('vm.preset')
47784
48038
  * config.getOrThrow('vm.preset')
47785
48039
  */
47786
- getRequired(path) {
47787
- const value = this.get(path);
48040
+ getRequired(path2) {
48041
+ const value = this.get(path2);
47788
48042
  if (value === void 0) {
47789
- throw new RequiredConfigUndefinedError(path);
48043
+ throw new RequiredConfigUndefinedError(path2);
47790
48044
  }
47791
48045
  return value;
47792
48046
  }
@@ -47795,8 +48049,8 @@ var init_base_config_provider = __esm({
47795
48049
  * @example
47796
48050
  * config.getOrThrow('vm.preset')
47797
48051
  */
47798
- getOrThrow(path) {
47799
- return this.getRequired(path);
48052
+ getOrThrow(path2) {
48053
+ return this.getRequired(path2);
47800
48054
  }
47801
48055
  /**
47802
48056
  * Get a nested object at a path
@@ -47811,8 +48065,8 @@ var init_base_config_provider = __esm({
47811
48065
  * @example
47812
48066
  * config.matches('vm.preset', 'secure') // returns true/false
47813
48067
  */
47814
- matches(path, value) {
47815
- return this.get(path) === value;
48068
+ matches(path2, value) {
48069
+ return this.get(path2) === value;
47816
48070
  }
47817
48071
  /**
47818
48072
  * Get multiple values at once
@@ -47821,8 +48075,8 @@ var init_base_config_provider = __esm({
47821
48075
  */
47822
48076
  getMany(paths) {
47823
48077
  const result = {};
47824
- for (const path of paths) {
47825
- result[path] = this.get(path);
48078
+ for (const path2 of paths) {
48079
+ result[path2] = this.get(path2);
47826
48080
  }
47827
48081
  return result;
47828
48082
  }