@frontmcp/plugin-codecall 1.2.1 → 1.4.0

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/esm/index.mjs CHANGED
@@ -10,6 +10,7 @@ var __decorateClass = (decorators, target, key, kind) => {
10
10
  };
11
11
 
12
12
  // plugins/plugin-codecall/src/codecall.plugin.ts
13
+ import CachePlugin from "@frontmcp/plugin-cache";
13
14
  import {
14
15
  DynamicPlugin,
15
16
  FrontMcpLogger,
@@ -273,6 +274,104 @@ var DEFAULT_PLUGIN_OPTIONS = {
273
274
  };
274
275
  var codeCallPluginOptionsSchema = codeCallPluginOptionsObjectSchema.prefault(DEFAULT_PLUGIN_OPTIONS);
275
276
 
277
+ // plugins/plugin-codecall/src/providers/code-call.config.ts
278
+ import { Provider, ProviderScope, BaseConfig } from "@frontmcp/sdk";
279
+ var CodeCallConfig = class extends BaseConfig {
280
+ constructor(options = {}) {
281
+ const parsedConfig = codeCallPluginOptionsSchema.parse(options);
282
+ const resolvedVm = resolveVmOptions(parsedConfig.vm);
283
+ super({ ...parsedConfig, resolvedVm });
284
+ }
285
+ };
286
+ CodeCallConfig = __decorateClass([
287
+ Provider({
288
+ name: "codecall:config",
289
+ description: "CodeCall plugin configuration with validated defaults",
290
+ scope: ProviderScope.GLOBAL
291
+ })
292
+ ], CodeCallConfig);
293
+ function resolveVmOptions(vmOptions) {
294
+ const preset = vmOptions?.preset ?? "secure";
295
+ const base = presetDefaults(preset);
296
+ return {
297
+ ...base,
298
+ ...vmOptions,
299
+ disabledBuiltins: vmOptions?.disabledBuiltins ?? base.disabledBuiltins,
300
+ disabledGlobals: vmOptions?.disabledGlobals ?? base.disabledGlobals
301
+ };
302
+ }
303
+ function presetDefaults(preset) {
304
+ switch (preset) {
305
+ case "locked_down":
306
+ return {
307
+ preset,
308
+ timeoutMs: 2e3,
309
+ allowLoops: false,
310
+ allowConsole: false,
311
+ maxSteps: 2e3,
312
+ disabledBuiltins: ["eval", "Function", "AsyncFunction"],
313
+ disabledGlobals: [
314
+ "require",
315
+ "process",
316
+ "fetch",
317
+ "setTimeout",
318
+ "setInterval",
319
+ "setImmediate",
320
+ "global",
321
+ "globalThis"
322
+ ],
323
+ maxSanitizeDepth: 10,
324
+ maxSanitizeProperties: 1e3
325
+ };
326
+ case "balanced":
327
+ return {
328
+ preset,
329
+ timeoutMs: 5e3,
330
+ allowLoops: true,
331
+ allowConsole: true,
332
+ maxSteps: 1e4,
333
+ disabledBuiltins: ["eval", "Function", "AsyncFunction"],
334
+ disabledGlobals: ["require", "process", "fetch"],
335
+ maxSanitizeDepth: 50,
336
+ maxSanitizeProperties: 5e3
337
+ };
338
+ case "experimental":
339
+ return {
340
+ preset,
341
+ timeoutMs: 1e4,
342
+ allowLoops: true,
343
+ allowConsole: true,
344
+ maxSteps: 2e4,
345
+ disabledBuiltins: ["eval", "Function", "AsyncFunction"],
346
+ disabledGlobals: ["require", "process"],
347
+ maxSanitizeDepth: 100,
348
+ maxSanitizeProperties: 2e4
349
+ };
350
+ case "secure":
351
+ default:
352
+ return {
353
+ preset: "secure",
354
+ timeoutMs: 3500,
355
+ allowLoops: false,
356
+ allowConsole: true,
357
+ maxSteps: 5e3,
358
+ disabledBuiltins: ["eval", "Function", "AsyncFunction"],
359
+ disabledGlobals: [
360
+ "require",
361
+ "process",
362
+ "fetch",
363
+ "setTimeout",
364
+ "setInterval",
365
+ "setImmediate",
366
+ "global",
367
+ "globalThis"
368
+ ],
369
+ maxSanitizeDepth: 50,
370
+ maxSanitizeProperties: 2e3
371
+ };
372
+ }
373
+ }
374
+
276
375
  // plugins/plugin-codecall/src/services/tool-search.service.ts
277
376
  import { TFIDFVectoria, VectoriaDB } from "vectoriadb";
278
377
 
@@ -1179,8 +1278,8 @@ var ToolSearchService = class _ToolSearchService {
1179
1278
  };
1180
1279
 
1181
1280
  // plugins/plugin-codecall/src/services/enclave.service.ts
1182
- import { Provider, ProviderScope } from "@frontmcp/sdk";
1183
1281
  import { Enclave } from "@enclave-vm/core";
1282
+ import { Provider as Provider2, ProviderScope as ProviderScope2 } from "@frontmcp/sdk";
1184
1283
  var ScriptTooLargeError = class extends Error {
1185
1284
  code = "SCRIPT_TOO_LARGE";
1186
1285
  scriptLength;
@@ -1229,6 +1328,10 @@ var EnclaveService = class {
1229
1328
  maxResolvedSize: this.sidecarOptions.maxResolvedSize,
1230
1329
  allowComposites: this.sidecarOptions.allowComposites
1231
1330
  } : void 0;
1331
+ const RESERVED_GLOBALS = /* @__PURE__ */ new Set(["getTool", "mcpLog", "mcpNotify"]);
1332
+ const safeNamespaces = Object.fromEntries(
1333
+ Object.entries(environment.namespaces ?? {}).filter(([key]) => !RESERVED_GLOBALS.has(key))
1334
+ );
1232
1335
  const enclave = new Enclave({
1233
1336
  timeout: this.vmOptions.timeoutMs,
1234
1337
  maxToolCalls: this.vmOptions.maxSteps || 100,
@@ -1242,6 +1345,11 @@ var EnclaveService = class {
1242
1345
  // Allow functions in globals since we intentionally provide getTool, mcpLog, mcpNotify, and console
1243
1346
  allowFunctionsInGlobals: true,
1244
1347
  globals: {
1348
+ // Tool namespaces (e.g. `acme.getUser`) flow through here. Spread
1349
+ // FIRST so the runtime reserved globals below are guaranteed
1350
+ // last-wins. Reserved keys have already been stripped above —
1351
+ // belt-and-braces ordering makes the invariant locally obvious.
1352
+ ...safeNamespaces,
1245
1353
  // Provide getTool as a custom global
1246
1354
  getTool: environment.getTool,
1247
1355
  // Provide logging functions if available
@@ -1338,10 +1446,10 @@ var EnclaveService = class {
1338
1446
  }
1339
1447
  };
1340
1448
  EnclaveService = __decorateClass([
1341
- Provider({
1449
+ Provider2({
1342
1450
  name: "codecall:enclave",
1343
1451
  description: "Executes AgentScript code in a secure enclave",
1344
- scope: ProviderScope.GLOBAL
1452
+ scope: ProviderScope2.GLOBAL
1345
1453
  })
1346
1454
  ], EnclaveService);
1347
1455
 
@@ -1485,10 +1593,295 @@ SearchTool = __decorateClass([
1485
1593
  })
1486
1594
  ], SearchTool);
1487
1595
 
1488
- // plugins/plugin-codecall/src/tools/describe.tool.ts
1489
- import { toJSONSchema, z as z4, ZodType } from "@frontmcp/lazy-zod";
1596
+ // plugins/plugin-codecall/src/tools/search-skills.tool.ts
1490
1597
  import { Tool as Tool2, ToolContext as ToolContext2 } from "@frontmcp/sdk";
1491
1598
 
1599
+ // plugins/plugin-codecall/src/tools/search-skills.schema.ts
1600
+ import { z as z3 } from "@frontmcp/lazy-zod";
1601
+ var searchSkillsToolDescription = `Search for EXECUTABLE skills. Each result returns the skill's description, tags, and the openapi operation IDs it can call from within AgentScript.
1602
+
1603
+ DECOMPOSE complex requests into atomic queries. AVOID re-searching: use excludeSkillNames.
1604
+
1605
+ INPUT:
1606
+ - queries: string[] (required) - atomic skill descriptions, max 10
1607
+ - tags?: string[] - filter to skills carrying any of these tags
1608
+ - excludeSkillNames?: string[] - skip already-discovered skills
1609
+ - topK?: number (default 5) - results per query
1610
+ - minRelevanceScore?: number (default 0.1) - minimum match threshold
1611
+
1612
+ OUTPUT: Flat deduplicated executable skill list. Each entry includes the operationIds the skill is allowed to call (via the markdown harvester). The agent can use those operationIds directly in execute() AgentScript via the generated namespaces (e.g. acme.getOrder({...})).
1613
+
1614
+ FLOW: searchSkills \u2192 describe \u2192 execute`;
1615
+ var searchSkillsToolInputSchema = {
1616
+ queries: z3.array(z3.string().min(2).max(256)).min(1).max(10).describe("Atomic skill queries. Split complex requests into simple actions."),
1617
+ tags: z3.array(z3.string().min(1).max(64)).max(16).optional().describe("Filter to skills with any of these tags"),
1618
+ excludeSkillNames: z3.array(z3.string()).max(50).optional().describe("Skip already-known skill names"),
1619
+ topK: z3.number().int().positive().max(50).optional().default(5).describe("Results per query (default 5)"),
1620
+ minRelevanceScore: z3.number().min(0).max(1).optional().default(0.1).describe("Minimum relevance threshold (default 0.1)")
1621
+ };
1622
+ var referencedOperationSchema = z3.object({
1623
+ spec: z3.string().describe('OpenAPI spec id (e.g. "acme")'),
1624
+ operationId: z3.string().describe('OpenAPI operation id (e.g. "getOrder")')
1625
+ });
1626
+ var skillSearchHitSchema = z3.object({
1627
+ name: z3.string().describe("Skill name"),
1628
+ description: z3.string().describe("Short description of what the skill does"),
1629
+ tags: z3.array(z3.string()).describe("Tags carried by the skill"),
1630
+ /**
1631
+ * OpenAPI operations the skill is allowed to call. Inlined so the agent
1632
+ * can author AgentScript from a single search response.
1633
+ */
1634
+ operations: z3.array(referencedOperationSchema).describe("OpenAPI operations the skill can call"),
1635
+ /** Decorator-declared tools (for skills built the legacy way). */
1636
+ tools: z3.array(z3.string()).describe("Tool names the skill declares (if any)"),
1637
+ relevanceScore: z3.number().min(0).max(1).describe("Match score (0-1)"),
1638
+ matchedQueries: z3.array(z3.string()).describe("Which queries matched this skill"),
1639
+ source: z3.enum(["local", "external"]).describe("Where the skill was loaded from")
1640
+ });
1641
+ var searchSkillsToolOutputSchema = z3.object({
1642
+ skills: z3.array(skillSearchHitSchema).describe("Deduplicated executable skills, sorted by relevance"),
1643
+ warnings: z3.array(
1644
+ z3.object({
1645
+ type: z3.enum(["no_results", "low_relevance", "excluded_skill_not_found"]).describe("Warning type"),
1646
+ message: z3.string().describe("Warning message"),
1647
+ affectedSkills: z3.array(z3.string()).optional().describe("Affected skill names")
1648
+ })
1649
+ ).describe("Search warnings"),
1650
+ totalExecutableSkills: z3.number().int().nonnegative().describe("Total executable skills available")
1651
+ });
1652
+
1653
+ // plugins/plugin-codecall/src/tools/search-skills.tool.ts
1654
+ var SearchSkillsTool = class extends ToolContext2 {
1655
+ async execute(input) {
1656
+ const { queries, tags, excludeSkillNames = [], topK = 5, minRelevanceScore = 0.1 } = input;
1657
+ const skillRegistry = this.scope.skills;
1658
+ const executableSkills = skillRegistry.getExecutableSkills();
1659
+ const executableSet = new Set(executableSkills.map((s) => s.name));
1660
+ const totalExecutableSkills = executableSkills.length;
1661
+ const warnings = [];
1662
+ const nonExistentExcluded = excludeSkillNames.filter((n) => !executableSet.has(n));
1663
+ if (nonExistentExcluded.length > 0) {
1664
+ warnings.push({
1665
+ type: "excluded_skill_not_found",
1666
+ message: `Excluded skills not found: ${nonExistentExcluded.join(", ")}`,
1667
+ affectedSkills: nonExistentExcluded
1668
+ });
1669
+ }
1670
+ const matches = /* @__PURE__ */ new Map();
1671
+ let lowRelevanceCount = 0;
1672
+ const excludedSet = new Set(excludeSkillNames);
1673
+ const perQueryResults = await Promise.all(
1674
+ queries.map(
1675
+ (query) => skillRegistry.search(query, { topK, tags, minScore: minRelevanceScore }).then((results) => ({ query, results }))
1676
+ )
1677
+ );
1678
+ for (const { query, results } of perQueryResults) {
1679
+ for (const result of results) {
1680
+ const name = result.metadata.name;
1681
+ if (!executableSet.has(name)) continue;
1682
+ if (excludedSet.has(name)) continue;
1683
+ if (result.score < minRelevanceScore) {
1684
+ lowRelevanceCount++;
1685
+ continue;
1686
+ }
1687
+ const existing = matches.get(name);
1688
+ if (existing) {
1689
+ existing.matchedQueries.push(query);
1690
+ existing.relevanceScore = Math.max(existing.relevanceScore, result.score);
1691
+ } else {
1692
+ const ops = result.metadata.referencedOperations ?? [];
1693
+ const toolNames = (result.metadata.tools ?? []).map((t) => {
1694
+ if (typeof t === "string") return t;
1695
+ if (typeof t === "object" && t !== null && "name" in t) return t.name;
1696
+ return null;
1697
+ }).filter((n) => typeof n === "string");
1698
+ matches.set(name, {
1699
+ name,
1700
+ description: result.metadata.description,
1701
+ tags: result.metadata.tags ?? [],
1702
+ operations: ops.map((op) => ({ spec: op.spec, operationId: op.operationId })),
1703
+ tools: toolNames,
1704
+ relevanceScore: result.score,
1705
+ matchedQueries: [query],
1706
+ source: result.source
1707
+ });
1708
+ }
1709
+ }
1710
+ }
1711
+ const skills = Array.from(matches.values()).sort((a, b) => b.relevanceScore - a.relevanceScore);
1712
+ if (skills.length === 0) {
1713
+ warnings.push({
1714
+ type: "no_results",
1715
+ message: `No executable skills found for queries: ${queries.join(", ")}${tags?.length ? ` with tags: ${tags.join(", ")}` : ""}`
1716
+ });
1717
+ }
1718
+ if (lowRelevanceCount > 0 && skills.length > 0) {
1719
+ warnings.push({
1720
+ type: "low_relevance",
1721
+ message: `${lowRelevanceCount} result(s) filtered due to relevance below ${minRelevanceScore}`
1722
+ });
1723
+ }
1724
+ return { skills, warnings, totalExecutableSkills };
1725
+ }
1726
+ };
1727
+ SearchSkillsTool = __decorateClass([
1728
+ Tool2({
1729
+ name: "codecall:searchSkills",
1730
+ cache: {
1731
+ ttl: 60,
1732
+ slideWindow: false
1733
+ },
1734
+ codecall: {
1735
+ enabledInCodeCall: false,
1736
+ visibleInListTools: true
1737
+ },
1738
+ description: searchSkillsToolDescription,
1739
+ inputSchema: searchSkillsToolInputSchema,
1740
+ outputSchema: searchSkillsToolOutputSchema,
1741
+ annotations: {
1742
+ readOnlyHint: true,
1743
+ openWorldHint: true
1744
+ }
1745
+ })
1746
+ ], SearchSkillsTool);
1747
+
1748
+ // plugins/plugin-codecall/src/tools/search-knowledge.tool.ts
1749
+ import { Tool as Tool3, ToolContext as ToolContext3 } from "@frontmcp/sdk";
1750
+
1751
+ // plugins/plugin-codecall/src/tools/search-knowledge.schema.ts
1752
+ import { z as z4 } from "@frontmcp/lazy-zod";
1753
+ var searchKnowledgeToolDescription = `Search for KNOWLEDGE-ONLY skills \u2014 domain context the agent should read before deciding what to do. These skills have no tools and no openapi operation refs; they are pure prose / references / examples.
1754
+
1755
+ USE WHEN: the agent needs background to interpret a request, validate eligibility, or recall a procedure that isn't yet executable.
1756
+
1757
+ INPUT:
1758
+ - queries: string[] (required) - atomic context queries, max 10
1759
+ - tags?: string[] - filter to knowledge carrying any of these tags
1760
+ - excludeSkillNames?: string[] - skip already-loaded knowledge
1761
+ - topK?: number (default 5) - results per query
1762
+ - minRelevanceScore?: number (default 0.1) - minimum match threshold
1763
+
1764
+ OUTPUT: Deduplicated knowledge skill list with description + tags. To read the body, follow up with describe(skillName) or the skill:// resource URI.
1765
+
1766
+ FLOW: searchKnowledge \u2192 describe (for body) \u2192 continue with searchSkills`;
1767
+ var searchKnowledgeToolInputSchema = {
1768
+ queries: z4.array(z4.string().min(2).max(256)).min(1).max(10).describe("Atomic context queries."),
1769
+ tags: z4.array(z4.string().min(1).max(64)).max(16).optional().describe("Filter to skills with any of these tags"),
1770
+ excludeSkillNames: z4.array(z4.string()).max(50).optional().describe("Skip already-loaded knowledge skill names"),
1771
+ topK: z4.number().int().positive().max(50).optional().default(5).describe("Results per query (default 5)"),
1772
+ minRelevanceScore: z4.number().min(0).max(1).optional().default(0.1).describe("Minimum relevance threshold (default 0.1)")
1773
+ };
1774
+ var knowledgeHitSchema = z4.object({
1775
+ name: z4.string().describe("Skill name"),
1776
+ description: z4.string().describe("Short description of what the knowledge covers"),
1777
+ tags: z4.array(z4.string()).describe("Tags carried by the skill"),
1778
+ relevanceScore: z4.number().min(0).max(1).describe("Match score (0-1)"),
1779
+ matchedQueries: z4.array(z4.string()).describe("Which queries matched this knowledge"),
1780
+ source: z4.enum(["local", "external"]).describe("Where the skill was loaded from")
1781
+ });
1782
+ var searchKnowledgeToolOutputSchema = z4.object({
1783
+ knowledge: z4.array(knowledgeHitSchema).describe("Deduplicated knowledge skills, sorted by relevance"),
1784
+ warnings: z4.array(
1785
+ z4.object({
1786
+ type: z4.enum(["no_results", "low_relevance", "excluded_skill_not_found"]).describe("Warning type"),
1787
+ message: z4.string().describe("Warning message"),
1788
+ affectedSkills: z4.array(z4.string()).optional().describe("Affected skill names")
1789
+ })
1790
+ ).describe("Search warnings"),
1791
+ totalKnowledgeSkills: z4.number().int().nonnegative().describe("Total knowledge-only skills available")
1792
+ });
1793
+
1794
+ // plugins/plugin-codecall/src/tools/search-knowledge.tool.ts
1795
+ var SearchKnowledgeTool = class extends ToolContext3 {
1796
+ async execute(input) {
1797
+ const { queries, tags, excludeSkillNames = [], topK = 5, minRelevanceScore = 0.1 } = input;
1798
+ const skillRegistry = this.scope.skills;
1799
+ const knowledgeSkills = skillRegistry.getKnowledgeOnlySkills();
1800
+ const knowledgeSet = new Set(knowledgeSkills.map((s) => s.name));
1801
+ const totalKnowledgeSkills = knowledgeSkills.length;
1802
+ const warnings = [];
1803
+ const nonExistentExcluded = excludeSkillNames.filter((n) => !knowledgeSet.has(n));
1804
+ if (nonExistentExcluded.length > 0) {
1805
+ warnings.push({
1806
+ type: "excluded_skill_not_found",
1807
+ message: `Excluded knowledge skills not found: ${nonExistentExcluded.join(", ")}`,
1808
+ affectedSkills: nonExistentExcluded
1809
+ });
1810
+ }
1811
+ const matches = /* @__PURE__ */ new Map();
1812
+ let lowRelevanceCount = 0;
1813
+ const excludedSet = new Set(excludeSkillNames);
1814
+ const perQueryResults = await Promise.all(
1815
+ queries.map(
1816
+ (query) => skillRegistry.search(query, { topK, tags, minScore: minRelevanceScore }).then((results) => ({ query, results }))
1817
+ )
1818
+ );
1819
+ for (const { query, results } of perQueryResults) {
1820
+ for (const result of results) {
1821
+ const name = result.metadata.name;
1822
+ if (!knowledgeSet.has(name)) continue;
1823
+ if (excludedSet.has(name)) continue;
1824
+ if (result.score < minRelevanceScore) {
1825
+ lowRelevanceCount++;
1826
+ continue;
1827
+ }
1828
+ const existing = matches.get(name);
1829
+ if (existing) {
1830
+ existing.matchedQueries.push(query);
1831
+ existing.relevanceScore = Math.max(existing.relevanceScore, result.score);
1832
+ } else {
1833
+ matches.set(name, {
1834
+ name,
1835
+ description: result.metadata.description,
1836
+ tags: result.metadata.tags ?? [],
1837
+ relevanceScore: result.score,
1838
+ matchedQueries: [query],
1839
+ source: result.source
1840
+ });
1841
+ }
1842
+ }
1843
+ }
1844
+ const knowledge = Array.from(matches.values()).sort((a, b) => b.relevanceScore - a.relevanceScore);
1845
+ if (knowledge.length === 0) {
1846
+ warnings.push({
1847
+ type: "no_results",
1848
+ message: `No knowledge skills found for queries: ${queries.join(", ")}${tags?.length ? ` with tags: ${tags.join(", ")}` : ""}`
1849
+ });
1850
+ }
1851
+ if (lowRelevanceCount > 0 && knowledge.length > 0) {
1852
+ warnings.push({
1853
+ type: "low_relevance",
1854
+ message: `${lowRelevanceCount} result(s) filtered due to relevance below ${minRelevanceScore}`
1855
+ });
1856
+ }
1857
+ return { knowledge, warnings, totalKnowledgeSkills };
1858
+ }
1859
+ };
1860
+ SearchKnowledgeTool = __decorateClass([
1861
+ Tool3({
1862
+ name: "codecall:searchKnowledge",
1863
+ cache: {
1864
+ ttl: 60,
1865
+ slideWindow: false
1866
+ },
1867
+ codecall: {
1868
+ enabledInCodeCall: false,
1869
+ visibleInListTools: true
1870
+ },
1871
+ description: searchKnowledgeToolDescription,
1872
+ inputSchema: searchKnowledgeToolInputSchema,
1873
+ outputSchema: searchKnowledgeToolOutputSchema,
1874
+ annotations: {
1875
+ readOnlyHint: true,
1876
+ openWorldHint: true
1877
+ }
1878
+ })
1879
+ ], SearchKnowledgeTool);
1880
+
1881
+ // plugins/plugin-codecall/src/tools/describe.tool.ts
1882
+ import { toJSONSchema, z as z6, ZodType } from "@frontmcp/lazy-zod";
1883
+ import { Tool as Tool4, ToolContext as ToolContext4 } from "@frontmcp/sdk";
1884
+
1492
1885
  // plugins/plugin-codecall/src/errors/tool-call.errors.ts
1493
1886
  var TOOL_CALL_ERROR_CODES = {
1494
1887
  NOT_FOUND: "NOT_FOUND",
@@ -1567,6 +1960,70 @@ function assertNotSelfReference(toolName) {
1567
1960
  }
1568
1961
  }
1569
1962
 
1963
+ // plugins/plugin-codecall/src/utils/build-tool-namespaces.ts
1964
+ var IDENT_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
1965
+ var RESERVED_NAMESPACES = /* @__PURE__ */ new Set([
1966
+ "console",
1967
+ "Math",
1968
+ "JSON",
1969
+ "Object",
1970
+ "Array",
1971
+ "String",
1972
+ "Number",
1973
+ "Boolean",
1974
+ "Promise",
1975
+ "Symbol",
1976
+ "Map",
1977
+ "Set",
1978
+ "WeakMap",
1979
+ "WeakSet",
1980
+ "Date",
1981
+ "Error",
1982
+ "RegExp",
1983
+ "globalThis",
1984
+ "global",
1985
+ "window",
1986
+ "self",
1987
+ "undefined",
1988
+ "null",
1989
+ "true",
1990
+ "false",
1991
+ "callTool",
1992
+ "getTool",
1993
+ "mcpLog",
1994
+ "mcpNotify"
1995
+ ]);
1996
+ function buildToolNamespaces(tools, callTool) {
1997
+ const namespaces = {};
1998
+ const skipped = [];
1999
+ for (const tool of tools) {
2000
+ const name = tool?.name;
2001
+ if (typeof name !== "string" || name.length === 0) continue;
2002
+ const dot = name.indexOf(".");
2003
+ if (dot <= 0 || dot === name.length - 1) {
2004
+ skipped.push({ name, reason: "no-namespace-prefix" });
2005
+ continue;
2006
+ }
2007
+ const ns = name.slice(0, dot);
2008
+ const method = name.slice(dot + 1);
2009
+ if (!IDENT_RE.test(ns) || !IDENT_RE.test(method)) {
2010
+ skipped.push({ name, reason: "invalid-identifier" });
2011
+ continue;
2012
+ }
2013
+ if (RESERVED_NAMESPACES.has(ns)) {
2014
+ skipped.push({ name, reason: "reserved-namespace" });
2015
+ continue;
2016
+ }
2017
+ const bucket = namespaces[ns] ?? (namespaces[ns] = {});
2018
+ if (Object.prototype.hasOwnProperty.call(bucket, method)) {
2019
+ skipped.push({ name, reason: "duplicate-method" });
2020
+ continue;
2021
+ }
2022
+ bucket[method] = (input, options) => callTool(name, input, options);
2023
+ }
2024
+ return { namespaces, skipped };
2025
+ }
2026
+
1570
2027
  // plugins/plugin-codecall/src/utils/describe.utils.ts
1571
2028
  var INTENT_PATTERNS = {
1572
2029
  create: /^(create|add|new|insert|make|append|register|generate|produce|build|construct|provision|instantiate|define|compose|draft)/i,
@@ -1856,7 +2313,7 @@ function extractResultFromCallToolResult(mcpResult) {
1856
2313
  }
1857
2314
 
1858
2315
  // plugins/plugin-codecall/src/tools/describe.schema.ts
1859
- import { z as z3 } from "@frontmcp/lazy-zod";
2316
+ import { z as z5 } from "@frontmcp/lazy-zod";
1860
2317
  import { ToolAnnotationsSchema } from "@frontmcp/protocol";
1861
2318
  var describeToolDescription = `Get input/output schemas for tools from search results.
1862
2319
 
@@ -1866,7 +2323,7 @@ OUTPUT per tool: inputSchema (JSON Schema), outputSchema (JSON Schema), usageExa
1866
2323
  IMPORTANT: If notFound array is non-empty \u2192 re-search with corrected queries.
1867
2324
  FLOW: search \u2192 describe \u2192 execute/invoke`;
1868
2325
  var describeToolInputSchema = {
1869
- toolNames: z3.array(z3.string()).min(1).superRefine((toolNames, ctx) => {
2326
+ toolNames: z5.array(z5.string()).min(1).superRefine((toolNames, ctx) => {
1870
2327
  const seen = /* @__PURE__ */ new Set();
1871
2328
  const duplicates = /* @__PURE__ */ new Set();
1872
2329
  for (const name of toolNames) {
@@ -1877,7 +2334,7 @@ var describeToolInputSchema = {
1877
2334
  }
1878
2335
  if (duplicates.size > 0) {
1879
2336
  ctx.addIssue({
1880
- code: z3.ZodIssueCode.custom,
2337
+ code: z5.ZodIssueCode.custom,
1881
2338
  message: `Duplicate tool names are not allowed: ${Array.from(duplicates).join(", ")}`
1882
2339
  });
1883
2340
  }
@@ -1885,30 +2342,30 @@ var describeToolInputSchema = {
1885
2342
  'Array of unique tool names (from codecall:search results) to fetch their detailed schemas and usage examples. Example: ["users:list", "billing:getInvoice"]'
1886
2343
  )
1887
2344
  };
1888
- var describeToolOutputSchema = z3.object({
1889
- tools: z3.array(
1890
- z3.object({
1891
- name: z3.string().describe("Tool name to be used in callTool() within codecall:execute scripts"),
1892
- appId: z3.string().describe("The app ID this tool belongs to"),
1893
- description: z3.string().describe("Detailed description of what this tool does"),
1894
- inputSchema: z3.record(z3.string(), z3.unknown()).nullable().describe("JSON Schema object describing the tool input parameters"),
1895
- outputSchema: z3.record(z3.string(), z3.unknown()).nullable().describe("JSON Schema object describing the tool output structure"),
2345
+ var describeToolOutputSchema = z5.object({
2346
+ tools: z5.array(
2347
+ z5.object({
2348
+ name: z5.string().describe("Tool name to be used in callTool() within codecall:execute scripts"),
2349
+ appId: z5.string().describe("The app ID this tool belongs to"),
2350
+ description: z5.string().describe("Detailed description of what this tool does"),
2351
+ inputSchema: z5.record(z5.string(), z5.unknown()).nullable().describe("JSON Schema object describing the tool input parameters"),
2352
+ outputSchema: z5.record(z5.string(), z5.unknown()).nullable().describe("JSON Schema object describing the tool output structure"),
1896
2353
  annotations: ToolAnnotationsSchema.optional().describe("MCP tool annotations (metadata)"),
1897
- usageExamples: z3.array(
1898
- z3.object({
1899
- description: z3.string().describe("Description of what this example demonstrates"),
1900
- code: z3.string().describe(
2354
+ usageExamples: z5.array(
2355
+ z5.object({
2356
+ description: z5.string().describe("Description of what this example demonstrates"),
2357
+ code: z5.string().describe(
1901
2358
  'JavaScript code example showing how to call this tool using callTool(). Format: const result = await callTool("tool:name", { ...params });'
1902
2359
  )
1903
2360
  })
1904
2361
  ).max(5).describe("Up to 5 practical examples of how to use this tool in a codecall:execute script")
1905
2362
  })
1906
2363
  ).describe("Array of tool descriptions with schemas and usage examples"),
1907
- notFound: z3.array(z3.string()).optional().describe("Tool names that were requested but not found in the index. Check these for typos.")
2364
+ notFound: z5.array(z5.string()).optional().describe("Tool names that were requested but not found in the index. Check these for typos.")
1908
2365
  });
1909
2366
 
1910
2367
  // plugins/plugin-codecall/src/tools/describe.tool.ts
1911
- var DescribeTool = class extends ToolContext2 {
2368
+ var DescribeTool = class extends ToolContext4 {
1912
2369
  async execute(input) {
1913
2370
  const { toolNames } = input;
1914
2371
  const tools = [];
@@ -1928,7 +2385,7 @@ var DescribeTool = class extends ToolContext2 {
1928
2385
  }
1929
2386
  const appId = this.extractAppId(tool);
1930
2387
  const inputSchema = this.getInputSchema(tool);
1931
- const outputSchema = this.toJsonSchema(tool.outputSchema);
2388
+ const outputSchema = this.toJsonSchema(tool.rawOutputSchema ?? tool.outputSchema);
1932
2389
  const usageExamples = this.generateExamples(tool, inputSchema ?? void 0);
1933
2390
  tools.push({
1934
2391
  name: tool.name,
@@ -1959,7 +2416,7 @@ var DescribeTool = class extends ToolContext2 {
1959
2416
  try {
1960
2417
  const firstValue = Object.values(tool.inputSchema)[0];
1961
2418
  if (firstValue instanceof ZodType) {
1962
- return toJSONSchema(z4.object(tool.inputSchema));
2419
+ return toJSONSchema(z6.object(tool.inputSchema));
1963
2420
  }
1964
2421
  } catch {
1965
2422
  }
@@ -1991,7 +2448,7 @@ var DescribeTool = class extends ToolContext2 {
1991
2448
  const firstValue = Object.values(obj)[0];
1992
2449
  if (firstValue instanceof ZodType) {
1993
2450
  try {
1994
- return toJSONSchema(z4.object(obj));
2451
+ return toJSONSchema(z6.object(obj));
1995
2452
  } catch {
1996
2453
  return null;
1997
2454
  }
@@ -2054,7 +2511,7 @@ return result;`
2054
2511
  }
2055
2512
  };
2056
2513
  DescribeTool = __decorateClass([
2057
- Tool2({
2514
+ Tool4({
2058
2515
  name: "codecall:describe",
2059
2516
  cache: {
2060
2517
  ttl: 60,
@@ -2076,10 +2533,10 @@ DescribeTool = __decorateClass([
2076
2533
  ], DescribeTool);
2077
2534
 
2078
2535
  // plugins/plugin-codecall/src/tools/execute.tool.ts
2079
- import { Tool as Tool3, ToolContext as ToolContext3 } from "@frontmcp/sdk";
2536
+ import { Tool as Tool5, ToolContext as ToolContext5 } from "@frontmcp/sdk";
2080
2537
 
2081
2538
  // plugins/plugin-codecall/src/tools/execute.schema.ts
2082
- import { z as z5 } from "@frontmcp/lazy-zod";
2539
+ import { z as z7 } from "@frontmcp/lazy-zod";
2083
2540
  var MIN_EXECUTE_SCRIPT_LENGTH = 'return callTool("a",{})'.length;
2084
2541
  var executeToolDescription = `Execute AgentScript (safe JS subset) for multi-tool orchestration.
2085
2542
 
@@ -2103,72 +2560,72 @@ ERRORS: NOT_FOUND | VALIDATION | EXECUTION | TIMEOUT | ACCESS_DENIED
2103
2560
  STATUS: ok | syntax_error | illegal_access | runtime_error | tool_error | timeout
2104
2561
  LIMITS: 10K iter/loop, 30s timeout, 100 calls max`;
2105
2562
  var executeToolInputSchema = {
2106
- script: z5.string().min(MIN_EXECUTE_SCRIPT_LENGTH).max(100 * 1024).describe(
2563
+ script: z7.string().min(MIN_EXECUTE_SCRIPT_LENGTH).max(100 * 1024).describe(
2107
2564
  "JavaScript code to execute in the sandbox. Must return a value (implicitly or via explicit return). Use callTool(name, input) to invoke tools."
2108
2565
  ),
2109
- allowedTools: z5.array(z5.string()).optional().describe(
2566
+ allowedTools: z7.array(z7.string()).optional().describe(
2110
2567
  'Optional whitelist of tool names that can be called from this script. If not provided, all indexed tools are available. Example: ["users:list", "billing:getInvoice"]'
2111
2568
  )
2112
2569
  };
2113
- var syntaxErrorPayloadSchema = z5.object({
2114
- message: z5.string(),
2115
- location: z5.object({
2116
- line: z5.number(),
2117
- column: z5.number()
2570
+ var syntaxErrorPayloadSchema = z7.object({
2571
+ message: z7.string(),
2572
+ location: z7.object({
2573
+ line: z7.number(),
2574
+ column: z7.number()
2118
2575
  }).optional()
2119
2576
  });
2120
- var illegalAccessErrorPayloadSchema = z5.object({
2121
- message: z5.string(),
2122
- kind: z5.union([
2123
- z5.literal("IllegalBuiltinAccess"),
2124
- z5.literal("DisallowedGlobal"),
2125
- z5.string()
2577
+ var illegalAccessErrorPayloadSchema = z7.object({
2578
+ message: z7.string(),
2579
+ kind: z7.union([
2580
+ z7.literal("IllegalBuiltinAccess"),
2581
+ z7.literal("DisallowedGlobal"),
2582
+ z7.string()
2126
2583
  // same as your original type: 'A' | 'B' | string
2127
2584
  ])
2128
2585
  });
2129
- var runtimeErrorPayloadSchema = z5.object({
2130
- source: z5.literal("script"),
2131
- message: z5.string(),
2132
- name: z5.string().optional(),
2133
- stack: z5.string().optional()
2586
+ var runtimeErrorPayloadSchema = z7.object({
2587
+ source: z7.literal("script"),
2588
+ message: z7.string(),
2589
+ name: z7.string().optional(),
2590
+ stack: z7.string().optional()
2134
2591
  });
2135
- var toolErrorPayloadSchema = z5.object({
2136
- source: z5.literal("tool"),
2137
- toolName: z5.string(),
2138
- toolInput: z5.unknown(),
2139
- message: z5.string(),
2140
- code: z5.string().optional(),
2141
- details: z5.unknown().optional()
2592
+ var toolErrorPayloadSchema = z7.object({
2593
+ source: z7.literal("tool"),
2594
+ toolName: z7.string(),
2595
+ toolInput: z7.unknown(),
2596
+ message: z7.string(),
2597
+ code: z7.string().optional(),
2598
+ details: z7.unknown().optional()
2142
2599
  });
2143
- var timeoutErrorPayloadSchema = z5.object({
2144
- message: z5.string()
2600
+ var timeoutErrorPayloadSchema = z7.object({
2601
+ message: z7.string()
2145
2602
  });
2146
- var codeCallOkResultSchema = z5.object({
2147
- status: z5.literal("ok"),
2148
- result: z5.unknown(),
2149
- logs: z5.array(z5.string()).optional()
2603
+ var codeCallOkResultSchema = z7.object({
2604
+ status: z7.literal("ok"),
2605
+ result: z7.unknown(),
2606
+ logs: z7.array(z7.string()).optional()
2150
2607
  });
2151
- var codeCallSyntaxErrorResultSchema = z5.object({
2152
- status: z5.literal("syntax_error"),
2608
+ var codeCallSyntaxErrorResultSchema = z7.object({
2609
+ status: z7.literal("syntax_error"),
2153
2610
  error: syntaxErrorPayloadSchema
2154
2611
  });
2155
- var codeCallIllegalAccessResultSchema = z5.object({
2156
- status: z5.literal("illegal_access"),
2612
+ var codeCallIllegalAccessResultSchema = z7.object({
2613
+ status: z7.literal("illegal_access"),
2157
2614
  error: illegalAccessErrorPayloadSchema
2158
2615
  });
2159
- var codeCallRuntimeErrorResultSchema = z5.object({
2160
- status: z5.literal("runtime_error"),
2616
+ var codeCallRuntimeErrorResultSchema = z7.object({
2617
+ status: z7.literal("runtime_error"),
2161
2618
  error: runtimeErrorPayloadSchema
2162
2619
  });
2163
- var codeCallToolErrorResultSchema = z5.object({
2164
- status: z5.literal("tool_error"),
2620
+ var codeCallToolErrorResultSchema = z7.object({
2621
+ status: z7.literal("tool_error"),
2165
2622
  error: toolErrorPayloadSchema
2166
2623
  });
2167
- var codeCallTimeoutResultSchema = z5.object({
2168
- status: z5.literal("timeout"),
2624
+ var codeCallTimeoutResultSchema = z7.object({
2625
+ status: z7.literal("timeout"),
2169
2626
  error: timeoutErrorPayloadSchema
2170
2627
  });
2171
- var executeToolOutputSchema = z5.discriminatedUnion("status", [
2628
+ var executeToolOutputSchema = z7.discriminatedUnion("status", [
2172
2629
  codeCallOkResultSchema,
2173
2630
  codeCallSyntaxErrorResultSchema,
2174
2631
  codeCallIllegalAccessResultSchema,
@@ -2177,104 +2634,6 @@ var executeToolOutputSchema = z5.discriminatedUnion("status", [
2177
2634
  codeCallTimeoutResultSchema
2178
2635
  ]);
2179
2636
 
2180
- // plugins/plugin-codecall/src/providers/code-call.config.ts
2181
- import { Provider as Provider2, ProviderScope as ProviderScope2, BaseConfig } from "@frontmcp/sdk";
2182
- var CodeCallConfig = class extends BaseConfig {
2183
- constructor(options = {}) {
2184
- const parsedConfig = codeCallPluginOptionsSchema.parse(options);
2185
- const resolvedVm = resolveVmOptions(parsedConfig.vm);
2186
- super({ ...parsedConfig, resolvedVm });
2187
- }
2188
- };
2189
- CodeCallConfig = __decorateClass([
2190
- Provider2({
2191
- name: "codecall:config",
2192
- description: "CodeCall plugin configuration with validated defaults",
2193
- scope: ProviderScope2.GLOBAL
2194
- })
2195
- ], CodeCallConfig);
2196
- function resolveVmOptions(vmOptions) {
2197
- const preset = vmOptions?.preset ?? "secure";
2198
- const base = presetDefaults(preset);
2199
- return {
2200
- ...base,
2201
- ...vmOptions,
2202
- disabledBuiltins: vmOptions?.disabledBuiltins ?? base.disabledBuiltins,
2203
- disabledGlobals: vmOptions?.disabledGlobals ?? base.disabledGlobals
2204
- };
2205
- }
2206
- function presetDefaults(preset) {
2207
- switch (preset) {
2208
- case "locked_down":
2209
- return {
2210
- preset,
2211
- timeoutMs: 2e3,
2212
- allowLoops: false,
2213
- allowConsole: false,
2214
- maxSteps: 2e3,
2215
- disabledBuiltins: ["eval", "Function", "AsyncFunction"],
2216
- disabledGlobals: [
2217
- "require",
2218
- "process",
2219
- "fetch",
2220
- "setTimeout",
2221
- "setInterval",
2222
- "setImmediate",
2223
- "global",
2224
- "globalThis"
2225
- ],
2226
- maxSanitizeDepth: 10,
2227
- maxSanitizeProperties: 1e3
2228
- };
2229
- case "balanced":
2230
- return {
2231
- preset,
2232
- timeoutMs: 5e3,
2233
- allowLoops: true,
2234
- allowConsole: true,
2235
- maxSteps: 1e4,
2236
- disabledBuiltins: ["eval", "Function", "AsyncFunction"],
2237
- disabledGlobals: ["require", "process", "fetch"],
2238
- maxSanitizeDepth: 50,
2239
- maxSanitizeProperties: 5e3
2240
- };
2241
- case "experimental":
2242
- return {
2243
- preset,
2244
- timeoutMs: 1e4,
2245
- allowLoops: true,
2246
- allowConsole: true,
2247
- maxSteps: 2e4,
2248
- disabledBuiltins: ["eval", "Function", "AsyncFunction"],
2249
- disabledGlobals: ["require", "process"],
2250
- maxSanitizeDepth: 100,
2251
- maxSanitizeProperties: 2e4
2252
- };
2253
- case "secure":
2254
- default:
2255
- return {
2256
- preset: "secure",
2257
- timeoutMs: 3500,
2258
- allowLoops: false,
2259
- allowConsole: true,
2260
- maxSteps: 5e3,
2261
- disabledBuiltins: ["eval", "Function", "AsyncFunction"],
2262
- disabledGlobals: [
2263
- "require",
2264
- "process",
2265
- "fetch",
2266
- "setTimeout",
2267
- "setInterval",
2268
- "setImmediate",
2269
- "global",
2270
- "globalThis"
2271
- ],
2272
- maxSanitizeDepth: 50,
2273
- maxSanitizeProperties: 2e3
2274
- };
2275
- }
2276
- }
2277
-
2278
2637
  // plugins/plugin-codecall/src/tools/execute.tool.ts
2279
2638
  function getErrorCode(error) {
2280
2639
  if (!(error instanceof Error)) {
@@ -2291,7 +2650,7 @@ function getErrorCode(error) {
2291
2650
  }
2292
2651
  return TOOL_CALL_ERROR_CODES.EXECUTION;
2293
2652
  }
2294
- var ExecuteTool = class extends ToolContext3 {
2653
+ var ExecuteTool = class extends ToolContext5 {
2295
2654
  async execute(input) {
2296
2655
  const { script, allowedTools } = input;
2297
2656
  const allowedToolSet = allowedTools ? new Set(allowedTools) : null;
@@ -2363,6 +2722,22 @@ var ExecuteTool = class extends ToolContext3 {
2363
2722
  this.logger?.debug("Notification sent", { event, payload });
2364
2723
  }
2365
2724
  };
2725
+ try {
2726
+ const registeredTools = this.scope.tools.getTools(true);
2727
+ const { namespaces, skipped } = buildToolNamespaces(registeredTools, environment.callTool);
2728
+ environment.namespaces = namespaces;
2729
+ if (skipped.length > 0) {
2730
+ this.logger?.debug?.("codecall: tools skipped during namespace generation", {
2731
+ count: skipped.length,
2732
+ // Cap the debug payload so a huge skip list doesn't bloat logs.
2733
+ sample: skipped.slice(0, 25)
2734
+ });
2735
+ }
2736
+ } catch (error) {
2737
+ this.logger?.warn?.("codecall: failed to build tool namespaces", {
2738
+ error: error instanceof Error ? error.message : String(error)
2739
+ });
2740
+ }
2366
2741
  const enclaveService = this.get(EnclaveService);
2367
2742
  const config = this.get(CodeCallConfig);
2368
2743
  try {
@@ -2441,7 +2816,7 @@ var ExecuteTool = class extends ToolContext3 {
2441
2816
  }
2442
2817
  };
2443
2818
  ExecuteTool = __decorateClass([
2444
- Tool3({
2819
+ Tool5({
2445
2820
  name: "codecall:execute",
2446
2821
  cache: {
2447
2822
  ttl: 0,
@@ -2459,10 +2834,10 @@ ExecuteTool = __decorateClass([
2459
2834
  ], ExecuteTool);
2460
2835
 
2461
2836
  // plugins/plugin-codecall/src/tools/invoke.tool.ts
2462
- import { Tool as Tool4, ToolContext as ToolContext4 } from "@frontmcp/sdk";
2837
+ import { Tool as Tool6, ToolContext as ToolContext6 } from "@frontmcp/sdk";
2463
2838
 
2464
2839
  // plugins/plugin-codecall/src/tools/invoke.schema.ts
2465
- import { z as z6 } from "@frontmcp/lazy-zod";
2840
+ import { z as z8 } from "@frontmcp/lazy-zod";
2466
2841
  import { CallToolResultSchema } from "@frontmcp/protocol";
2467
2842
  var invokeToolDescription = `Call ONE tool directly. Returns standard MCP CallToolResult.
2468
2843
 
@@ -2475,10 +2850,10 @@ ERRORS: tool_not_found (\u2192 re-search) | validation_error | execution_error |
2475
2850
 
2476
2851
  FLOW: search \u2192 describe \u2192 invoke`;
2477
2852
  var invokeToolInputSchema = {
2478
- tool: z6.string().describe(
2853
+ tool: z8.string().describe(
2479
2854
  'The name of the tool to invoke (e.g., "users:getById", "billing:getInvoice"). Must be a tool you discovered via codecall:search.'
2480
2855
  ),
2481
- input: z6.record(z6.string(), z6.unknown()).describe(
2856
+ input: z8.record(z8.string(), z8.unknown()).describe(
2482
2857
  "The input parameters for the tool. Structure must match the tool's input schema (check codecall:describe for schema details)."
2483
2858
  )
2484
2859
  };
@@ -2491,7 +2866,7 @@ function buildErrorResult(message) {
2491
2866
  isError: true
2492
2867
  };
2493
2868
  }
2494
- var InvokeTool = class extends ToolContext4 {
2869
+ var InvokeTool = class extends ToolContext6 {
2495
2870
  async execute(input) {
2496
2871
  const { tool: toolName, input: toolInput } = input;
2497
2872
  if (isBlockedSelfReference(toolName)) {
@@ -2517,7 +2892,7 @@ var InvokeTool = class extends ToolContext4 {
2517
2892
  }
2518
2893
  };
2519
2894
  InvokeTool = __decorateClass([
2520
- Tool4({
2895
+ Tool6({
2521
2896
  name: "codecall:invoke",
2522
2897
  cache: {
2523
2898
  ttl: 0,
@@ -2535,7 +2910,6 @@ InvokeTool = __decorateClass([
2535
2910
  ], InvokeTool);
2536
2911
 
2537
2912
  // plugins/plugin-codecall/src/codecall.plugin.ts
2538
- import CachePlugin from "@frontmcp/plugin-cache";
2539
2913
  var CodeCallPlugin = class extends DynamicPlugin {
2540
2914
  options;
2541
2915
  cachedLogger;
@@ -2612,7 +2986,6 @@ var CodeCallPlugin = class extends DynamicPlugin {
2612
2986
  * @param mode - The current CodeCall mode
2613
2987
  * @returns true if tool should be visible
2614
2988
  */
2615
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- ToolEntry generics vary across call sites
2616
2989
  shouldShowInListTools(tool, mode) {
2617
2990
  if (this.isCodeCallTool(tool)) {
2618
2991
  return true;
@@ -2644,15 +3017,13 @@ var CodeCallPlugin = class extends DynamicPlugin {
2644
3017
  * Check if a tool is a CodeCall meta-tool.
2645
3018
  * CodeCall meta-tools always remain visible.
2646
3019
  */
2647
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2648
3020
  isCodeCallTool(tool) {
2649
3021
  const name = tool.name || tool.fullName;
2650
- return name.startsWith("codecall:");
3022
+ return typeof name === "string" && name.startsWith("codecall:");
2651
3023
  }
2652
3024
  /**
2653
3025
  * Extract CodeCall-specific metadata from a tool.
2654
3026
  */
2655
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2656
3027
  getCodeCallMetadata(tool) {
2657
3028
  return tool.metadata?.["codecall"];
2658
3029
  }
@@ -2666,7 +3037,7 @@ CodeCallPlugin = __decorateClass([
2666
3037
  description: "CodeCall plugin: AgentScript-based meta-tools for orchestrating MCP tools",
2667
3038
  providers: [],
2668
3039
  plugins: [CachePlugin],
2669
- tools: [SearchTool, DescribeTool, ExecuteTool, InvokeTool]
3040
+ tools: [SearchTool, SearchSkillsTool, SearchKnowledgeTool, DescribeTool, ExecuteTool, InvokeTool]
2670
3041
  })
2671
3042
  ], CodeCallPlugin);
2672
3043
  export {