@frontmcp/plugin-codecall 1.8.7 → 1.9.1-rc.1
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/codecall.plugin.d.ts +22 -0
- package/codecall.plugin.d.ts.map +1 -1
- package/codecall.types.d.ts +3 -0
- package/codecall.types.d.ts.map +1 -1
- package/esm/index.mjs +296 -255
- package/esm/package.json +7 -7
- package/index.js +400 -362
- package/package.json +7 -7
- package/security/codecall-dispatch.d.ts +13 -0
- package/security/codecall-dispatch.d.ts.map +1 -0
- package/security/index.d.ts +1 -0
- package/security/index.d.ts.map +1 -1
- package/tools/execute.tool.d.ts.map +1 -1
- package/tools/invoke.tool.d.ts +1 -1
- package/tools/invoke.tool.d.ts.map +1 -1
- package/tools/search.tool.d.ts +1 -1
- package/tools/search.tool.d.ts.map +1 -1
package/index.js
CHANGED
|
@@ -56,7 +56,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
56
56
|
|
|
57
57
|
// plugins/plugin-codecall/src/codecall.plugin.ts
|
|
58
58
|
var import_plugin_cache = __toESM(require("@frontmcp/plugin-cache"));
|
|
59
|
-
var
|
|
59
|
+
var import_sdk11 = require("@frontmcp/sdk");
|
|
60
60
|
|
|
61
61
|
// plugins/plugin-codecall/src/codecall.types.ts
|
|
62
62
|
var import_lazy_zod = require("@frontmcp/lazy-zod");
|
|
@@ -411,8 +411,186 @@ function presetDefaults(preset) {
|
|
|
411
411
|
}
|
|
412
412
|
}
|
|
413
413
|
|
|
414
|
-
// plugins/plugin-codecall/src/
|
|
414
|
+
// plugins/plugin-codecall/src/security/codecall-dispatch.ts
|
|
415
415
|
var import_sdk2 = require("@frontmcp/sdk");
|
|
416
|
+
var CODECALL_DISPATCH = /* @__PURE__ */ Symbol("frontmcp.codecall.dispatch");
|
|
417
|
+
function asCodeCallDispatch(ctx) {
|
|
418
|
+
return Object.defineProperty(ctx, CODECALL_DISPATCH, { value: true, enumerable: false });
|
|
419
|
+
}
|
|
420
|
+
function isInProcessDispatch(ctx) {
|
|
421
|
+
if ((0, import_sdk2.getRunningTool)()) return true;
|
|
422
|
+
if (typeof ctx !== "object" || ctx === null) return false;
|
|
423
|
+
const marks = ctx;
|
|
424
|
+
return marks[CODECALL_DISPATCH] === true || marks.internalCall === true;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// plugins/plugin-codecall/src/security/codecall-tool-policy.ts
|
|
428
|
+
var BLOCKED_NAMESPACE_PATTERNS = Object.freeze([/^system:/, /^internal:/, /^__/]);
|
|
429
|
+
function isOfferedToCaller(availableWhen, surface) {
|
|
430
|
+
const offered = availableWhen?.surface;
|
|
431
|
+
return offered === void 0 || surface === void 0 || offered.includes(surface);
|
|
432
|
+
}
|
|
433
|
+
var ALLOWED = { allowed: true };
|
|
434
|
+
function deny(reason) {
|
|
435
|
+
return { allowed: false, reason };
|
|
436
|
+
}
|
|
437
|
+
function codeCallAppIdOf(scope, entry) {
|
|
438
|
+
const lineage = scope?.tools?.lineageOf?.(entry) ?? [];
|
|
439
|
+
const owners = entry.owner ? [...lineage, entry.owner] : lineage;
|
|
440
|
+
return owners.find((owner) => owner.kind === "app")?.id;
|
|
441
|
+
}
|
|
442
|
+
function toCodeCallPolicyTool(entry, requestedName, scope) {
|
|
443
|
+
const { metadata } = entry;
|
|
444
|
+
return {
|
|
445
|
+
name: entry.name || entry.fullName,
|
|
446
|
+
fullName: entry.fullName,
|
|
447
|
+
aliases: requestedName ? [requestedName] : void 0,
|
|
448
|
+
appId: codeCallAppIdOf(scope, entry),
|
|
449
|
+
description: metadata?.description,
|
|
450
|
+
tags: metadata?.tags,
|
|
451
|
+
// `internal` tools refuse every external tools/call, CodeCall's included, so no surface may offer them.
|
|
452
|
+
hidden: metadata?.hideFromDiscovery === true || metadata?.visibility === "hidden" || metadata?.visibility === "internal",
|
|
453
|
+
codecall: metadata?.codecall,
|
|
454
|
+
annotations: metadata?.annotations,
|
|
455
|
+
metadata
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
function isPlainData(value) {
|
|
459
|
+
if (Array.isArray(value)) return true;
|
|
460
|
+
const proto = Object.getPrototypeOf(value);
|
|
461
|
+
return proto === Object.prototype || proto === null;
|
|
462
|
+
}
|
|
463
|
+
function readOnlyCopy(value, copies) {
|
|
464
|
+
if (typeof value !== "object" || value === null || !isPlainData(value)) return value;
|
|
465
|
+
const existing = copies.get(value);
|
|
466
|
+
if (existing !== void 0) return existing;
|
|
467
|
+
const copy = Array.isArray(value) ? [] : Object.create(Object.getPrototypeOf(value));
|
|
468
|
+
copies.set(value, copy);
|
|
469
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
470
|
+
if (!Object.prototype.propertyIsEnumerable.call(value, key)) continue;
|
|
471
|
+
Object.defineProperty(copy, key, {
|
|
472
|
+
value: readOnlyCopy(Reflect.get(value, key), copies),
|
|
473
|
+
enumerable: true,
|
|
474
|
+
writable: true,
|
|
475
|
+
configurable: true
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
return Object.freeze(copy);
|
|
479
|
+
}
|
|
480
|
+
function toToolFilterInfo(tool) {
|
|
481
|
+
const copies = /* @__PURE__ */ new WeakMap();
|
|
482
|
+
const annotations = readOnlyCopy(tool.annotations, copies);
|
|
483
|
+
const metadata = tool.metadata ? readOnlyCopy({ ...tool.metadata, ...annotations ? { annotations: tool.annotations } : {} }, copies) : void 0;
|
|
484
|
+
return {
|
|
485
|
+
name: tool.name,
|
|
486
|
+
fullName: tool.fullName,
|
|
487
|
+
appId: tool.appId,
|
|
488
|
+
source: tool.codecall?.source,
|
|
489
|
+
description: tool.description,
|
|
490
|
+
tags: readOnlyCopy(tool.codecall?.tags ?? tool.tags, copies),
|
|
491
|
+
annotations,
|
|
492
|
+
metadata
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
function ownNamesOf(tool) {
|
|
496
|
+
return [tool.name, tool.fullName].filter((candidate) => !!candidate);
|
|
497
|
+
}
|
|
498
|
+
function checkCodeCallToolPolicy(tool, config) {
|
|
499
|
+
const { name } = tool;
|
|
500
|
+
const spellings = [...ownNamesOf(tool), ...tool.aliases ?? []];
|
|
501
|
+
if (spellings.some((candidate) => candidate.startsWith("codecall:"))) {
|
|
502
|
+
return deny("CodeCall meta-tools are not callable from CodeCall");
|
|
503
|
+
}
|
|
504
|
+
for (const candidate of spellings) {
|
|
505
|
+
if (BLOCKED_NAMESPACE_PATTERNS.some((pattern) => pattern.test(candidate))) {
|
|
506
|
+
return deny(`Tool "${candidate}" is in a namespace CodeCall never calls`);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
if (tool.hidden === true) {
|
|
510
|
+
return deny(`Tool "${name}" is hidden from discovery`);
|
|
511
|
+
}
|
|
512
|
+
const enabled = tool.codecall?.enabledInCodeCall;
|
|
513
|
+
switch (config.mode) {
|
|
514
|
+
case "codecall_only":
|
|
515
|
+
case "metadata_driven":
|
|
516
|
+
if (enabled === false) {
|
|
517
|
+
return deny(`Tool "${name}" sets enabledInCodeCall: false`);
|
|
518
|
+
}
|
|
519
|
+
break;
|
|
520
|
+
case "codecall_opt_in":
|
|
521
|
+
if (enabled !== true) {
|
|
522
|
+
return deny(`Tool "${name}" has not opted in to CodeCall`);
|
|
523
|
+
}
|
|
524
|
+
break;
|
|
525
|
+
default:
|
|
526
|
+
return deny(`Unknown CodeCall mode: ${String(config.mode)}`);
|
|
527
|
+
}
|
|
528
|
+
if (config.includeTools && !config.includeTools(toToolFilterInfo(tool))) {
|
|
529
|
+
return deny(`Tool "${name}" is excluded by the includeTools filter`);
|
|
530
|
+
}
|
|
531
|
+
return ALLOWED;
|
|
532
|
+
}
|
|
533
|
+
function denyUnknownTool(name) {
|
|
534
|
+
return deny(`Tool "${name}" is not available through CodeCall`);
|
|
535
|
+
}
|
|
536
|
+
function resolveCodeCallTool(scope, name) {
|
|
537
|
+
const typedScope = scope;
|
|
538
|
+
const alias = /[-_]/.test(name) ? name.includes("_") ? name.replace(/_/g, "-") : name.replace(/-/g, "_") : void 0;
|
|
539
|
+
const candidates = alias ? [name, alias] : [name];
|
|
540
|
+
const matches = (entry) => candidates.includes(entry.fullName) || candidates.includes(entry.name);
|
|
541
|
+
const local = typedScope.tools?.getTools(true)?.find(matches);
|
|
542
|
+
if (local) return local;
|
|
543
|
+
const registries = typedScope.providers?.getRegistries?.("AppRegistry") ?? [];
|
|
544
|
+
for (const registry of registries) {
|
|
545
|
+
for (const app of registry.getApps()) {
|
|
546
|
+
if (!app.isRemote) continue;
|
|
547
|
+
const remote = app.tools.getTools(true).find(matches);
|
|
548
|
+
if (remote) return remote;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
return void 0;
|
|
552
|
+
}
|
|
553
|
+
function checkDirectCallPolicy(tool, directCalls) {
|
|
554
|
+
if (!directCalls) return ALLOWED;
|
|
555
|
+
if (directCalls.enabled === false) {
|
|
556
|
+
return deny("Direct tool invocation is disabled");
|
|
557
|
+
}
|
|
558
|
+
const { allowedTools } = directCalls;
|
|
559
|
+
if (allowedTools && !ownNamesOf(tool).some((ownName) => allowedTools.includes(ownName))) {
|
|
560
|
+
return deny(`Tool "${tool.name}" is not in the direct-call allowlist`);
|
|
561
|
+
}
|
|
562
|
+
if (directCalls.filter && !directCalls.filter(toToolFilterInfo(tool))) {
|
|
563
|
+
return deny(`Tool "${tool.name}" is excluded by the directCalls filter`);
|
|
564
|
+
}
|
|
565
|
+
return ALLOWED;
|
|
566
|
+
}
|
|
567
|
+
function readCodeCallPolicyConfig(config) {
|
|
568
|
+
return {
|
|
569
|
+
// An absent mode means an unparsed/partial config, not a hostile one: fall back to the
|
|
570
|
+
// schema's own documented default rather than denying every call. An unrecognised mode
|
|
571
|
+
// still fails closed inside the policy's switch.
|
|
572
|
+
mode: config.get("mode") ?? "codecall_only",
|
|
573
|
+
includeTools: config.get("includeTools")
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
function checkCodeCallToolAccess(scope, config, name, options = {}) {
|
|
577
|
+
const entry = resolveCodeCallTool(scope, name);
|
|
578
|
+
if (!entry) return denyUnknownTool(name);
|
|
579
|
+
if (!isOfferedToCaller(entry.metadata?.availableWhen, options.surface)) {
|
|
580
|
+
return deny(`Tool "${name}" is not offered on the caller's surface "${options.surface}"`);
|
|
581
|
+
}
|
|
582
|
+
const policyTool = toCodeCallPolicyTool(entry, name, scope);
|
|
583
|
+
const baseDecision = checkCodeCallToolPolicy(policyTool, readCodeCallPolicyConfig(config));
|
|
584
|
+
if (!baseDecision.allowed) return baseDecision;
|
|
585
|
+
if (options.directCall) {
|
|
586
|
+
const directDecision = checkDirectCallPolicy(
|
|
587
|
+
policyTool,
|
|
588
|
+
config.get("directCalls")
|
|
589
|
+
);
|
|
590
|
+
if (!directDecision.allowed) return directDecision;
|
|
591
|
+
}
|
|
592
|
+
return { allowed: true, entry };
|
|
593
|
+
}
|
|
416
594
|
|
|
417
595
|
// plugins/plugin-codecall/src/utils/client-error-message.ts
|
|
418
596
|
var EMBEDDED_STACK_FRAME_RE = /\n[ \t]*at\s[^\n]*/g;
|
|
@@ -452,7 +630,85 @@ function redactAbsolutePaths(text) {
|
|
|
452
630
|
return result + redactPaths(text.slice(last));
|
|
453
631
|
}
|
|
454
632
|
|
|
633
|
+
// plugins/plugin-codecall/src/errors/tool-call.errors.ts
|
|
634
|
+
var TOOL_CALL_ERROR_CODES = {
|
|
635
|
+
NOT_FOUND: "NOT_FOUND",
|
|
636
|
+
VALIDATION: "VALIDATION",
|
|
637
|
+
EXECUTION: "EXECUTION",
|
|
638
|
+
TIMEOUT: "TIMEOUT",
|
|
639
|
+
ACCESS_DENIED: "ACCESS_DENIED",
|
|
640
|
+
SELF_REFERENCE: "SELF_REFERENCE"
|
|
641
|
+
};
|
|
642
|
+
function createToolCallError(code, toolName, rawMessage) {
|
|
643
|
+
const sanitizedMessage = getSanitizedMessage(code, toolName, rawMessage);
|
|
644
|
+
return Object.freeze({
|
|
645
|
+
code,
|
|
646
|
+
message: sanitizedMessage,
|
|
647
|
+
toolName
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
function getSanitizedMessage(code, toolName, rawMessage) {
|
|
651
|
+
switch (code) {
|
|
652
|
+
case TOOL_CALL_ERROR_CODES.NOT_FOUND:
|
|
653
|
+
return `Tool "${toolName}" was not found`;
|
|
654
|
+
case TOOL_CALL_ERROR_CODES.VALIDATION:
|
|
655
|
+
return rawMessage ? sanitizeValidationMessage(rawMessage) : `Input validation failed for tool "${toolName}"`;
|
|
656
|
+
case TOOL_CALL_ERROR_CODES.EXECUTION:
|
|
657
|
+
return `Tool "${toolName}" execution failed`;
|
|
658
|
+
case TOOL_CALL_ERROR_CODES.TIMEOUT:
|
|
659
|
+
return `Tool "${toolName}" execution timed out`;
|
|
660
|
+
case TOOL_CALL_ERROR_CODES.ACCESS_DENIED:
|
|
661
|
+
return `Access denied for tool "${toolName}"`;
|
|
662
|
+
case TOOL_CALL_ERROR_CODES.SELF_REFERENCE:
|
|
663
|
+
return `Cannot call CodeCall tools from within AgentScript`;
|
|
664
|
+
default:
|
|
665
|
+
return `An error occurred while calling "${toolName}"`;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
function sanitizeValidationMessage(message) {
|
|
669
|
+
let sanitized = toClientErrorMessage(message);
|
|
670
|
+
sanitized = sanitized.replace(/\bat line \d+/gi, "");
|
|
671
|
+
sanitized = sanitized.replace(/\bline \d+/gi, "");
|
|
672
|
+
sanitized = sanitized.replace(/:\d+:\d+/g, "");
|
|
673
|
+
if (sanitized.length > 200) {
|
|
674
|
+
sanitized = sanitized.substring(0, 200) + "...";
|
|
675
|
+
}
|
|
676
|
+
return sanitized.trim();
|
|
677
|
+
}
|
|
678
|
+
var SelfReferenceError = class extends Error {
|
|
679
|
+
code = TOOL_CALL_ERROR_CODES.SELF_REFERENCE;
|
|
680
|
+
toolName;
|
|
681
|
+
constructor(toolName) {
|
|
682
|
+
super(`Self-reference attack: Attempted to call CodeCall tool "${toolName}" from within AgentScript`);
|
|
683
|
+
this.name = "SelfReferenceError";
|
|
684
|
+
this.toolName = toolName;
|
|
685
|
+
Object.freeze(this);
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
|
|
689
|
+
// plugins/plugin-codecall/src/security/self-reference-guard.ts
|
|
690
|
+
var CODECALL_TOOL_PREFIX = "codecall:";
|
|
691
|
+
var BLOCKED_CODECALL_TOOLS = Object.freeze(
|
|
692
|
+
/* @__PURE__ */ new Set(["codecall:search", "codecall:describe", "codecall:execute", "codecall:invoke"])
|
|
693
|
+
);
|
|
694
|
+
function isBlockedSelfReference(toolName) {
|
|
695
|
+
const normalizedName = toolName.toLowerCase().trim();
|
|
696
|
+
if (normalizedName.startsWith(CODECALL_TOOL_PREFIX)) {
|
|
697
|
+
return true;
|
|
698
|
+
}
|
|
699
|
+
if (BLOCKED_CODECALL_TOOLS.has(toolName)) {
|
|
700
|
+
return true;
|
|
701
|
+
}
|
|
702
|
+
return false;
|
|
703
|
+
}
|
|
704
|
+
function assertNotSelfReference(toolName) {
|
|
705
|
+
if (isBlockedSelfReference(toolName)) {
|
|
706
|
+
throw new SelfReferenceError(toolName);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
|
|
455
710
|
// plugins/plugin-codecall/src/services/audit-logger.service.ts
|
|
711
|
+
var import_sdk3 = require("@frontmcp/sdk");
|
|
456
712
|
var AUDIT_EVENT_TYPES = {
|
|
457
713
|
/** Script execution started */
|
|
458
714
|
EXECUTION_START: "codecall:execution:start",
|
|
@@ -664,256 +920,88 @@ var AuditLoggerService = class {
|
|
|
664
920
|
durationMs,
|
|
665
921
|
data: {
|
|
666
922
|
queryLength: query.length,
|
|
667
|
-
resultCount
|
|
668
|
-
}
|
|
669
|
-
});
|
|
670
|
-
}
|
|
671
|
-
/**
|
|
672
|
-
* Log describe operation.
|
|
673
|
-
*/
|
|
674
|
-
logDescribe(executionId, toolNames, durationMs) {
|
|
675
|
-
this.emit({
|
|
676
|
-
type: AUDIT_EVENT_TYPES.DESCRIBE_PERFORMED,
|
|
677
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
678
|
-
executionId,
|
|
679
|
-
durationMs,
|
|
680
|
-
data: {
|
|
681
|
-
toolCount: toolNames.length,
|
|
682
|
-
toolNames: toolNames.slice(0, 10)
|
|
683
|
-
// Limit to first 10 for audit
|
|
684
|
-
}
|
|
685
|
-
});
|
|
686
|
-
}
|
|
687
|
-
/**
|
|
688
|
-
* Log invoke operation.
|
|
689
|
-
*/
|
|
690
|
-
logInvoke(executionId, toolName, success, durationMs) {
|
|
691
|
-
this.emit({
|
|
692
|
-
type: AUDIT_EVENT_TYPES.INVOKE_PERFORMED,
|
|
693
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
694
|
-
executionId,
|
|
695
|
-
durationMs,
|
|
696
|
-
data: {
|
|
697
|
-
toolName,
|
|
698
|
-
success
|
|
699
|
-
}
|
|
700
|
-
});
|
|
701
|
-
}
|
|
702
|
-
/**
|
|
703
|
-
* Emit an audit event to all listeners.
|
|
704
|
-
*/
|
|
705
|
-
emit(event) {
|
|
706
|
-
const frozenEvent = Object.freeze({ ...event, data: Object.freeze({ ...event.data }) });
|
|
707
|
-
for (const listener of this.listeners) {
|
|
708
|
-
try {
|
|
709
|
-
listener(frozenEvent);
|
|
710
|
-
} catch {
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
/**
|
|
715
|
-
* Create a simple hash of the script for identification.
|
|
716
|
-
* Uses a fast, non-cryptographic hash for performance.
|
|
717
|
-
*/
|
|
718
|
-
hashScript(script) {
|
|
719
|
-
let hash = 0;
|
|
720
|
-
for (let i = 0; i < script.length; i++) {
|
|
721
|
-
const char = script.charCodeAt(i);
|
|
722
|
-
hash = (hash << 5) - hash + char;
|
|
723
|
-
hash = hash & hash;
|
|
724
|
-
}
|
|
725
|
-
return `sh_${(hash >>> 0).toString(16).padStart(8, "0")}`;
|
|
726
|
-
}
|
|
727
|
-
/**
|
|
728
|
-
* Sanitize error messages to remove sensitive information.
|
|
729
|
-
*/
|
|
730
|
-
sanitizeError(error) {
|
|
731
|
-
if (!error) return "Unknown error";
|
|
732
|
-
let sanitized = toClientErrorMessage(error);
|
|
733
|
-
sanitized = sanitized.replace(/:\d+:\d+/g, "");
|
|
734
|
-
if (sanitized.length > 200) {
|
|
735
|
-
sanitized = sanitized.substring(0, 200) + "...";
|
|
736
|
-
}
|
|
737
|
-
return sanitized.trim();
|
|
738
|
-
}
|
|
739
|
-
};
|
|
740
|
-
AuditLoggerService = __decorateClass([
|
|
741
|
-
(0, import_sdk2.Provider)({
|
|
742
|
-
name: "codecall:audit-logger",
|
|
743
|
-
scope: import_sdk2.ProviderScope.GLOBAL
|
|
744
|
-
})
|
|
745
|
-
], AuditLoggerService);
|
|
746
|
-
|
|
747
|
-
// plugins/plugin-codecall/src/services/tool-search.service.ts
|
|
748
|
-
var import_vectoriadb = require("vectoriadb");
|
|
749
|
-
|
|
750
|
-
// plugins/plugin-codecall/src/security/codecall-tool-policy.ts
|
|
751
|
-
var BLOCKED_NAMESPACE_PATTERNS = Object.freeze([/^system:/, /^internal:/, /^__/]);
|
|
752
|
-
function isOfferedToCaller(availableWhen, surface) {
|
|
753
|
-
const offered = availableWhen?.surface;
|
|
754
|
-
return offered === void 0 || surface === void 0 || offered.includes(surface);
|
|
755
|
-
}
|
|
756
|
-
var ALLOWED = { allowed: true };
|
|
757
|
-
function deny(reason) {
|
|
758
|
-
return { allowed: false, reason };
|
|
759
|
-
}
|
|
760
|
-
function codeCallAppIdOf(scope, entry) {
|
|
761
|
-
const lineage = scope?.tools?.lineageOf?.(entry) ?? [];
|
|
762
|
-
const owners = entry.owner ? [...lineage, entry.owner] : lineage;
|
|
763
|
-
return owners.find((owner) => owner.kind === "app")?.id;
|
|
764
|
-
}
|
|
765
|
-
function toCodeCallPolicyTool(entry, requestedName, scope) {
|
|
766
|
-
const { metadata } = entry;
|
|
767
|
-
return {
|
|
768
|
-
name: entry.name || entry.fullName,
|
|
769
|
-
fullName: entry.fullName,
|
|
770
|
-
aliases: requestedName ? [requestedName] : void 0,
|
|
771
|
-
appId: codeCallAppIdOf(scope, entry),
|
|
772
|
-
description: metadata?.description,
|
|
773
|
-
tags: metadata?.tags,
|
|
774
|
-
// `internal` tools refuse every external tools/call, CodeCall's included, so no surface may offer them.
|
|
775
|
-
hidden: metadata?.hideFromDiscovery === true || metadata?.visibility === "hidden" || metadata?.visibility === "internal",
|
|
776
|
-
codecall: metadata?.codecall,
|
|
777
|
-
annotations: metadata?.annotations,
|
|
778
|
-
metadata
|
|
779
|
-
};
|
|
780
|
-
}
|
|
781
|
-
function isPlainData(value) {
|
|
782
|
-
if (Array.isArray(value)) return true;
|
|
783
|
-
const proto = Object.getPrototypeOf(value);
|
|
784
|
-
return proto === Object.prototype || proto === null;
|
|
785
|
-
}
|
|
786
|
-
function readOnlyCopy(value, copies) {
|
|
787
|
-
if (typeof value !== "object" || value === null || !isPlainData(value)) return value;
|
|
788
|
-
const existing = copies.get(value);
|
|
789
|
-
if (existing !== void 0) return existing;
|
|
790
|
-
const copy = Array.isArray(value) ? [] : Object.create(Object.getPrototypeOf(value));
|
|
791
|
-
copies.set(value, copy);
|
|
792
|
-
for (const key of Reflect.ownKeys(value)) {
|
|
793
|
-
if (!Object.prototype.propertyIsEnumerable.call(value, key)) continue;
|
|
794
|
-
Object.defineProperty(copy, key, {
|
|
795
|
-
value: readOnlyCopy(Reflect.get(value, key), copies),
|
|
796
|
-
enumerable: true,
|
|
797
|
-
writable: true,
|
|
798
|
-
configurable: true
|
|
799
|
-
});
|
|
800
|
-
}
|
|
801
|
-
return Object.freeze(copy);
|
|
802
|
-
}
|
|
803
|
-
function toToolFilterInfo(tool) {
|
|
804
|
-
const copies = /* @__PURE__ */ new WeakMap();
|
|
805
|
-
const annotations = readOnlyCopy(tool.annotations, copies);
|
|
806
|
-
const metadata = tool.metadata ? readOnlyCopy({ ...tool.metadata, ...annotations ? { annotations: tool.annotations } : {} }, copies) : void 0;
|
|
807
|
-
return {
|
|
808
|
-
name: tool.name,
|
|
809
|
-
fullName: tool.fullName,
|
|
810
|
-
appId: tool.appId,
|
|
811
|
-
source: tool.codecall?.source,
|
|
812
|
-
description: tool.description,
|
|
813
|
-
tags: readOnlyCopy(tool.codecall?.tags ?? tool.tags, copies),
|
|
814
|
-
annotations,
|
|
815
|
-
metadata
|
|
816
|
-
};
|
|
817
|
-
}
|
|
818
|
-
function ownNamesOf(tool) {
|
|
819
|
-
return [tool.name, tool.fullName].filter((candidate) => !!candidate);
|
|
820
|
-
}
|
|
821
|
-
function checkCodeCallToolPolicy(tool, config) {
|
|
822
|
-
const { name } = tool;
|
|
823
|
-
const spellings = [...ownNamesOf(tool), ...tool.aliases ?? []];
|
|
824
|
-
if (spellings.some((candidate) => candidate.startsWith("codecall:"))) {
|
|
825
|
-
return deny("CodeCall meta-tools are not callable from CodeCall");
|
|
826
|
-
}
|
|
827
|
-
for (const candidate of spellings) {
|
|
828
|
-
if (BLOCKED_NAMESPACE_PATTERNS.some((pattern) => pattern.test(candidate))) {
|
|
829
|
-
return deny(`Tool "${candidate}" is in a namespace CodeCall never calls`);
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
if (tool.hidden === true) {
|
|
833
|
-
return deny(`Tool "${name}" is hidden from discovery`);
|
|
834
|
-
}
|
|
835
|
-
const enabled = tool.codecall?.enabledInCodeCall;
|
|
836
|
-
switch (config.mode) {
|
|
837
|
-
case "codecall_only":
|
|
838
|
-
case "metadata_driven":
|
|
839
|
-
if (enabled === false) {
|
|
840
|
-
return deny(`Tool "${name}" sets enabledInCodeCall: false`);
|
|
841
|
-
}
|
|
842
|
-
break;
|
|
843
|
-
case "codecall_opt_in":
|
|
844
|
-
if (enabled !== true) {
|
|
845
|
-
return deny(`Tool "${name}" has not opted in to CodeCall`);
|
|
923
|
+
resultCount
|
|
846
924
|
}
|
|
847
|
-
|
|
848
|
-
default:
|
|
849
|
-
return deny(`Unknown CodeCall mode: ${String(config.mode)}`);
|
|
850
|
-
}
|
|
851
|
-
if (config.includeTools && !config.includeTools(toToolFilterInfo(tool))) {
|
|
852
|
-
return deny(`Tool "${name}" is excluded by the includeTools filter`);
|
|
853
|
-
}
|
|
854
|
-
return ALLOWED;
|
|
855
|
-
}
|
|
856
|
-
function denyUnknownTool(name) {
|
|
857
|
-
return deny(`Tool "${name}" is not available through CodeCall`);
|
|
858
|
-
}
|
|
859
|
-
function resolveCodeCallTool(scope, name) {
|
|
860
|
-
const typedScope = scope;
|
|
861
|
-
const alias = /[-_]/.test(name) ? name.includes("_") ? name.replace(/_/g, "-") : name.replace(/-/g, "_") : void 0;
|
|
862
|
-
const candidates = alias ? [name, alias] : [name];
|
|
863
|
-
const matches = (entry) => candidates.includes(entry.fullName) || candidates.includes(entry.name);
|
|
864
|
-
const local = typedScope.tools?.getTools(true)?.find(matches);
|
|
865
|
-
if (local) return local;
|
|
866
|
-
const registries = typedScope.providers?.getRegistries?.("AppRegistry") ?? [];
|
|
867
|
-
for (const registry of registries) {
|
|
868
|
-
for (const app of registry.getApps()) {
|
|
869
|
-
if (!app.isRemote) continue;
|
|
870
|
-
const remote = app.tools.getTools(true).find(matches);
|
|
871
|
-
if (remote) return remote;
|
|
872
|
-
}
|
|
925
|
+
});
|
|
873
926
|
}
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
927
|
+
/**
|
|
928
|
+
* Log describe operation.
|
|
929
|
+
*/
|
|
930
|
+
logDescribe(executionId, toolNames, durationMs) {
|
|
931
|
+
this.emit({
|
|
932
|
+
type: AUDIT_EVENT_TYPES.DESCRIBE_PERFORMED,
|
|
933
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
934
|
+
executionId,
|
|
935
|
+
durationMs,
|
|
936
|
+
data: {
|
|
937
|
+
toolCount: toolNames.length,
|
|
938
|
+
toolNames: toolNames.slice(0, 10)
|
|
939
|
+
// Limit to first 10 for audit
|
|
940
|
+
}
|
|
941
|
+
});
|
|
880
942
|
}
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
943
|
+
/**
|
|
944
|
+
* Log invoke operation.
|
|
945
|
+
*/
|
|
946
|
+
logInvoke(executionId, toolName, success, durationMs) {
|
|
947
|
+
this.emit({
|
|
948
|
+
type: AUDIT_EVENT_TYPES.INVOKE_PERFORMED,
|
|
949
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
950
|
+
executionId,
|
|
951
|
+
durationMs,
|
|
952
|
+
data: {
|
|
953
|
+
toolName,
|
|
954
|
+
success
|
|
955
|
+
}
|
|
956
|
+
});
|
|
884
957
|
}
|
|
885
|
-
|
|
886
|
-
|
|
958
|
+
/**
|
|
959
|
+
* Emit an audit event to all listeners.
|
|
960
|
+
*/
|
|
961
|
+
emit(event) {
|
|
962
|
+
const frozenEvent = Object.freeze({ ...event, data: Object.freeze({ ...event.data }) });
|
|
963
|
+
for (const listener of this.listeners) {
|
|
964
|
+
try {
|
|
965
|
+
listener(frozenEvent);
|
|
966
|
+
} catch {
|
|
967
|
+
}
|
|
968
|
+
}
|
|
887
969
|
}
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
const entry = resolveCodeCallTool(scope, name);
|
|
901
|
-
if (!entry) return denyUnknownTool(name);
|
|
902
|
-
if (!isOfferedToCaller(entry.metadata?.availableWhen, options.surface)) {
|
|
903
|
-
return deny(`Tool "${name}" is not offered on the caller's surface "${options.surface}"`);
|
|
970
|
+
/**
|
|
971
|
+
* Create a simple hash of the script for identification.
|
|
972
|
+
* Uses a fast, non-cryptographic hash for performance.
|
|
973
|
+
*/
|
|
974
|
+
hashScript(script) {
|
|
975
|
+
let hash = 0;
|
|
976
|
+
for (let i = 0; i < script.length; i++) {
|
|
977
|
+
const char = script.charCodeAt(i);
|
|
978
|
+
hash = (hash << 5) - hash + char;
|
|
979
|
+
hash = hash & hash;
|
|
980
|
+
}
|
|
981
|
+
return `sh_${(hash >>> 0).toString(16).padStart(8, "0")}`;
|
|
904
982
|
}
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
)
|
|
913
|
-
|
|
983
|
+
/**
|
|
984
|
+
* Sanitize error messages to remove sensitive information.
|
|
985
|
+
*/
|
|
986
|
+
sanitizeError(error) {
|
|
987
|
+
if (!error) return "Unknown error";
|
|
988
|
+
let sanitized = toClientErrorMessage(error);
|
|
989
|
+
sanitized = sanitized.replace(/:\d+:\d+/g, "");
|
|
990
|
+
if (sanitized.length > 200) {
|
|
991
|
+
sanitized = sanitized.substring(0, 200) + "...";
|
|
992
|
+
}
|
|
993
|
+
return sanitized.trim();
|
|
914
994
|
}
|
|
915
|
-
|
|
916
|
-
|
|
995
|
+
};
|
|
996
|
+
AuditLoggerService = __decorateClass([
|
|
997
|
+
(0, import_sdk3.Provider)({
|
|
998
|
+
name: "codecall:audit-logger",
|
|
999
|
+
scope: import_sdk3.ProviderScope.GLOBAL
|
|
1000
|
+
})
|
|
1001
|
+
], AuditLoggerService);
|
|
1002
|
+
|
|
1003
|
+
// plugins/plugin-codecall/src/services/tool-search.service.ts
|
|
1004
|
+
var import_vectoriadb = require("vectoriadb");
|
|
917
1005
|
|
|
918
1006
|
// plugins/plugin-codecall/src/services/synonym-expansion.service.ts
|
|
919
1007
|
var DEFAULT_SYNONYM_GROUPS = [
|
|
@@ -1773,7 +1861,7 @@ var ToolSearchService = class _ToolSearchService {
|
|
|
1773
1861
|
|
|
1774
1862
|
// plugins/plugin-codecall/src/services/enclave.service.ts
|
|
1775
1863
|
var import_core = require("@enclave-vm/core");
|
|
1776
|
-
var
|
|
1864
|
+
var import_sdk4 = require("@frontmcp/sdk");
|
|
1777
1865
|
|
|
1778
1866
|
// plugins/plugin-codecall/src/utils/build-tool-namespaces.ts
|
|
1779
1867
|
var IDENT_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
@@ -2224,10 +2312,10 @@ var EnclaveService = class {
|
|
|
2224
2312
|
}
|
|
2225
2313
|
};
|
|
2226
2314
|
EnclaveService = __decorateClass([
|
|
2227
|
-
(0,
|
|
2315
|
+
(0, import_sdk4.Provider)({
|
|
2228
2316
|
name: "codecall:enclave",
|
|
2229
2317
|
description: "Executes AgentScript code in a secure enclave",
|
|
2230
|
-
scope:
|
|
2318
|
+
scope: import_sdk4.ProviderScope.GLOBAL
|
|
2231
2319
|
})
|
|
2232
2320
|
], EnclaveService);
|
|
2233
2321
|
function createEnclave(options) {
|
|
@@ -2242,7 +2330,7 @@ function createEnclave(options) {
|
|
|
2242
2330
|
}
|
|
2243
2331
|
|
|
2244
2332
|
// plugins/plugin-codecall/src/tools/search.tool.ts
|
|
2245
|
-
var
|
|
2333
|
+
var import_sdk5 = require("@frontmcp/sdk");
|
|
2246
2334
|
|
|
2247
2335
|
// plugins/plugin-codecall/src/tools/search.schema.ts
|
|
2248
2336
|
var import_lazy_zod2 = require("@frontmcp/lazy-zod");
|
|
@@ -2292,7 +2380,7 @@ var searchToolOutputSchema = import_lazy_zod2.z.object({
|
|
|
2292
2380
|
});
|
|
2293
2381
|
|
|
2294
2382
|
// plugins/plugin-codecall/src/tools/search.tool.ts
|
|
2295
|
-
var SearchTool = class extends
|
|
2383
|
+
var SearchTool = class extends import_sdk5.ToolContext {
|
|
2296
2384
|
async execute(input) {
|
|
2297
2385
|
const { queries, appIds, excludeToolNames = [], topK = 5, minRelevanceScore = 0.3 } = input;
|
|
2298
2386
|
const searchService = this.get(ToolSearchService);
|
|
@@ -2300,7 +2388,7 @@ var SearchTool = class extends import_sdk4.ToolContext {
|
|
|
2300
2388
|
const audit = this.tryGet(AuditLoggerService);
|
|
2301
2389
|
const executionId = audit ? audit.generateExecutionId() : "";
|
|
2302
2390
|
const startedAt = Date.now();
|
|
2303
|
-
const surface = (0,
|
|
2391
|
+
const surface = (0, import_sdk5.getCallSurface)();
|
|
2304
2392
|
const nonExistentExcludedTools = excludeToolNames.filter(
|
|
2305
2393
|
(toolName) => !searchService.hasTool(toolName, surface)
|
|
2306
2394
|
);
|
|
@@ -2368,7 +2456,7 @@ var SearchTool = class extends import_sdk4.ToolContext {
|
|
|
2368
2456
|
}
|
|
2369
2457
|
};
|
|
2370
2458
|
SearchTool = __decorateClass([
|
|
2371
|
-
(0,
|
|
2459
|
+
(0, import_sdk5.Tool)({
|
|
2372
2460
|
name: "codecall:search",
|
|
2373
2461
|
cache: {
|
|
2374
2462
|
ttl: 60,
|
|
@@ -2390,7 +2478,7 @@ SearchTool = __decorateClass([
|
|
|
2390
2478
|
], SearchTool);
|
|
2391
2479
|
|
|
2392
2480
|
// plugins/plugin-codecall/src/tools/search-skills.tool.ts
|
|
2393
|
-
var
|
|
2481
|
+
var import_sdk6 = require("@frontmcp/sdk");
|
|
2394
2482
|
|
|
2395
2483
|
// plugins/plugin-codecall/src/tools/search-skills.schema.ts
|
|
2396
2484
|
var import_lazy_zod3 = require("@frontmcp/lazy-zod");
|
|
@@ -2447,11 +2535,11 @@ var searchSkillsToolOutputSchema = import_lazy_zod3.z.object({
|
|
|
2447
2535
|
});
|
|
2448
2536
|
|
|
2449
2537
|
// plugins/plugin-codecall/src/tools/search-skills.tool.ts
|
|
2450
|
-
var SearchSkillsTool = class extends
|
|
2538
|
+
var SearchSkillsTool = class extends import_sdk6.ToolContext {
|
|
2451
2539
|
async execute(input) {
|
|
2452
2540
|
const { queries, tags, excludeSkillNames = [], topK = 5, minRelevanceScore = 0.1 } = input;
|
|
2453
2541
|
const skillRegistry = this.scope.skills;
|
|
2454
|
-
const executableSkills = await (0,
|
|
2542
|
+
const executableSkills = await (0, import_sdk6.filterServableSkills)(this.scope, skillRegistry.getExecutableSkills());
|
|
2455
2543
|
const executableSet = new Set(executableSkills.map((s) => s.name));
|
|
2456
2544
|
const totalExecutableSkills = executableSkills.length;
|
|
2457
2545
|
const warnings = [];
|
|
@@ -2521,7 +2609,7 @@ var SearchSkillsTool = class extends import_sdk5.ToolContext {
|
|
|
2521
2609
|
}
|
|
2522
2610
|
};
|
|
2523
2611
|
SearchSkillsTool = __decorateClass([
|
|
2524
|
-
(0,
|
|
2612
|
+
(0, import_sdk6.Tool)({
|
|
2525
2613
|
name: "codecall:searchSkills",
|
|
2526
2614
|
cache: {
|
|
2527
2615
|
ttl: 60,
|
|
@@ -2542,7 +2630,7 @@ SearchSkillsTool = __decorateClass([
|
|
|
2542
2630
|
], SearchSkillsTool);
|
|
2543
2631
|
|
|
2544
2632
|
// plugins/plugin-codecall/src/tools/search-knowledge.tool.ts
|
|
2545
|
-
var
|
|
2633
|
+
var import_sdk7 = require("@frontmcp/sdk");
|
|
2546
2634
|
|
|
2547
2635
|
// plugins/plugin-codecall/src/tools/search-knowledge.schema.ts
|
|
2548
2636
|
var import_lazy_zod4 = require("@frontmcp/lazy-zod");
|
|
@@ -2588,11 +2676,11 @@ var searchKnowledgeToolOutputSchema = import_lazy_zod4.z.object({
|
|
|
2588
2676
|
});
|
|
2589
2677
|
|
|
2590
2678
|
// plugins/plugin-codecall/src/tools/search-knowledge.tool.ts
|
|
2591
|
-
var SearchKnowledgeTool = class extends
|
|
2679
|
+
var SearchKnowledgeTool = class extends import_sdk7.ToolContext {
|
|
2592
2680
|
async execute(input) {
|
|
2593
2681
|
const { queries, tags, excludeSkillNames = [], topK = 5, minRelevanceScore = 0.1 } = input;
|
|
2594
2682
|
const skillRegistry = this.scope.skills;
|
|
2595
|
-
const knowledgeSkills = await (0,
|
|
2683
|
+
const knowledgeSkills = await (0, import_sdk7.filterServableSkills)(this.scope, skillRegistry.getKnowledgeOnlySkills());
|
|
2596
2684
|
const knowledgeSet = new Set(knowledgeSkills.map((s) => s.name));
|
|
2597
2685
|
const totalKnowledgeSkills = knowledgeSkills.length;
|
|
2598
2686
|
const warnings = [];
|
|
@@ -2654,7 +2742,7 @@ var SearchKnowledgeTool = class extends import_sdk6.ToolContext {
|
|
|
2654
2742
|
}
|
|
2655
2743
|
};
|
|
2656
2744
|
SearchKnowledgeTool = __decorateClass([
|
|
2657
|
-
(0,
|
|
2745
|
+
(0, import_sdk7.Tool)({
|
|
2658
2746
|
name: "codecall:searchKnowledge",
|
|
2659
2747
|
cache: {
|
|
2660
2748
|
ttl: 60,
|
|
@@ -2676,84 +2764,7 @@ SearchKnowledgeTool = __decorateClass([
|
|
|
2676
2764
|
|
|
2677
2765
|
// plugins/plugin-codecall/src/tools/describe.tool.ts
|
|
2678
2766
|
var import_lazy_zod6 = require("@frontmcp/lazy-zod");
|
|
2679
|
-
var
|
|
2680
|
-
|
|
2681
|
-
// plugins/plugin-codecall/src/errors/tool-call.errors.ts
|
|
2682
|
-
var TOOL_CALL_ERROR_CODES = {
|
|
2683
|
-
NOT_FOUND: "NOT_FOUND",
|
|
2684
|
-
VALIDATION: "VALIDATION",
|
|
2685
|
-
EXECUTION: "EXECUTION",
|
|
2686
|
-
TIMEOUT: "TIMEOUT",
|
|
2687
|
-
ACCESS_DENIED: "ACCESS_DENIED",
|
|
2688
|
-
SELF_REFERENCE: "SELF_REFERENCE"
|
|
2689
|
-
};
|
|
2690
|
-
function createToolCallError(code, toolName, rawMessage) {
|
|
2691
|
-
const sanitizedMessage = getSanitizedMessage(code, toolName, rawMessage);
|
|
2692
|
-
return Object.freeze({
|
|
2693
|
-
code,
|
|
2694
|
-
message: sanitizedMessage,
|
|
2695
|
-
toolName
|
|
2696
|
-
});
|
|
2697
|
-
}
|
|
2698
|
-
function getSanitizedMessage(code, toolName, rawMessage) {
|
|
2699
|
-
switch (code) {
|
|
2700
|
-
case TOOL_CALL_ERROR_CODES.NOT_FOUND:
|
|
2701
|
-
return `Tool "${toolName}" was not found`;
|
|
2702
|
-
case TOOL_CALL_ERROR_CODES.VALIDATION:
|
|
2703
|
-
return rawMessage ? sanitizeValidationMessage(rawMessage) : `Input validation failed for tool "${toolName}"`;
|
|
2704
|
-
case TOOL_CALL_ERROR_CODES.EXECUTION:
|
|
2705
|
-
return `Tool "${toolName}" execution failed`;
|
|
2706
|
-
case TOOL_CALL_ERROR_CODES.TIMEOUT:
|
|
2707
|
-
return `Tool "${toolName}" execution timed out`;
|
|
2708
|
-
case TOOL_CALL_ERROR_CODES.ACCESS_DENIED:
|
|
2709
|
-
return `Access denied for tool "${toolName}"`;
|
|
2710
|
-
case TOOL_CALL_ERROR_CODES.SELF_REFERENCE:
|
|
2711
|
-
return `Cannot call CodeCall tools from within AgentScript`;
|
|
2712
|
-
default:
|
|
2713
|
-
return `An error occurred while calling "${toolName}"`;
|
|
2714
|
-
}
|
|
2715
|
-
}
|
|
2716
|
-
function sanitizeValidationMessage(message) {
|
|
2717
|
-
let sanitized = toClientErrorMessage(message);
|
|
2718
|
-
sanitized = sanitized.replace(/\bat line \d+/gi, "");
|
|
2719
|
-
sanitized = sanitized.replace(/\bline \d+/gi, "");
|
|
2720
|
-
sanitized = sanitized.replace(/:\d+:\d+/g, "");
|
|
2721
|
-
if (sanitized.length > 200) {
|
|
2722
|
-
sanitized = sanitized.substring(0, 200) + "...";
|
|
2723
|
-
}
|
|
2724
|
-
return sanitized.trim();
|
|
2725
|
-
}
|
|
2726
|
-
var SelfReferenceError = class extends Error {
|
|
2727
|
-
code = TOOL_CALL_ERROR_CODES.SELF_REFERENCE;
|
|
2728
|
-
toolName;
|
|
2729
|
-
constructor(toolName) {
|
|
2730
|
-
super(`Self-reference attack: Attempted to call CodeCall tool "${toolName}" from within AgentScript`);
|
|
2731
|
-
this.name = "SelfReferenceError";
|
|
2732
|
-
this.toolName = toolName;
|
|
2733
|
-
Object.freeze(this);
|
|
2734
|
-
}
|
|
2735
|
-
};
|
|
2736
|
-
|
|
2737
|
-
// plugins/plugin-codecall/src/security/self-reference-guard.ts
|
|
2738
|
-
var CODECALL_TOOL_PREFIX = "codecall:";
|
|
2739
|
-
var BLOCKED_CODECALL_TOOLS = Object.freeze(
|
|
2740
|
-
/* @__PURE__ */ new Set(["codecall:search", "codecall:describe", "codecall:execute", "codecall:invoke"])
|
|
2741
|
-
);
|
|
2742
|
-
function isBlockedSelfReference(toolName) {
|
|
2743
|
-
const normalizedName = toolName.toLowerCase().trim();
|
|
2744
|
-
if (normalizedName.startsWith(CODECALL_TOOL_PREFIX)) {
|
|
2745
|
-
return true;
|
|
2746
|
-
}
|
|
2747
|
-
if (BLOCKED_CODECALL_TOOLS.has(toolName)) {
|
|
2748
|
-
return true;
|
|
2749
|
-
}
|
|
2750
|
-
return false;
|
|
2751
|
-
}
|
|
2752
|
-
function assertNotSelfReference(toolName) {
|
|
2753
|
-
if (isBlockedSelfReference(toolName)) {
|
|
2754
|
-
throw new SelfReferenceError(toolName);
|
|
2755
|
-
}
|
|
2756
|
-
}
|
|
2767
|
+
var import_sdk8 = require("@frontmcp/sdk");
|
|
2757
2768
|
|
|
2758
2769
|
// plugins/plugin-codecall/src/utils/describe.utils.ts
|
|
2759
2770
|
var INTENT_PATTERNS = {
|
|
@@ -3215,7 +3226,7 @@ var describeToolOutputSchema = import_lazy_zod5.z.object({
|
|
|
3215
3226
|
});
|
|
3216
3227
|
|
|
3217
3228
|
// plugins/plugin-codecall/src/tools/describe.tool.ts
|
|
3218
|
-
var DescribeTool = class extends
|
|
3229
|
+
var DescribeTool = class extends import_sdk8.ToolContext {
|
|
3219
3230
|
async execute(input) {
|
|
3220
3231
|
const { toolNames } = input;
|
|
3221
3232
|
const audit = this.tryGet(AuditLoggerService);
|
|
@@ -3224,7 +3235,7 @@ var DescribeTool = class extends import_sdk7.ToolContext {
|
|
|
3224
3235
|
const tools = [];
|
|
3225
3236
|
const notFound = [];
|
|
3226
3237
|
const config = this.get(CodeCallConfig);
|
|
3227
|
-
const surface = (0,
|
|
3238
|
+
const surface = (0, import_sdk8.getCallSurface)();
|
|
3228
3239
|
for (const toolName of toolNames) {
|
|
3229
3240
|
if (isBlockedSelfReference(toolName)) {
|
|
3230
3241
|
notFound.push(toolName);
|
|
@@ -3368,7 +3379,7 @@ return result;`
|
|
|
3368
3379
|
}
|
|
3369
3380
|
};
|
|
3370
3381
|
DescribeTool = __decorateClass([
|
|
3371
|
-
(0,
|
|
3382
|
+
(0, import_sdk8.Tool)({
|
|
3372
3383
|
name: "codecall:describe",
|
|
3373
3384
|
cache: {
|
|
3374
3385
|
ttl: 60,
|
|
@@ -3390,7 +3401,7 @@ DescribeTool = __decorateClass([
|
|
|
3390
3401
|
], DescribeTool);
|
|
3391
3402
|
|
|
3392
3403
|
// plugins/plugin-codecall/src/tools/execute.tool.ts
|
|
3393
|
-
var
|
|
3404
|
+
var import_sdk9 = require("@frontmcp/sdk");
|
|
3394
3405
|
|
|
3395
3406
|
// plugins/plugin-codecall/src/tools/execute.schema.ts
|
|
3396
3407
|
var import_lazy_zod7 = require("@frontmcp/lazy-zod");
|
|
@@ -3513,7 +3524,7 @@ function getErrorCode(error) {
|
|
|
3513
3524
|
}
|
|
3514
3525
|
return TOOL_CALL_ERROR_CODES.EXECUTION;
|
|
3515
3526
|
}
|
|
3516
|
-
var ExecuteTool = class extends
|
|
3527
|
+
var ExecuteTool = class extends import_sdk9.ToolContext {
|
|
3517
3528
|
/**
|
|
3518
3529
|
* Resolve the server-side CodeCall policy for a tool name (GHSA-6w3j-82v5-6qrr).
|
|
3519
3530
|
*
|
|
@@ -3527,7 +3538,7 @@ var ExecuteTool = class extends import_sdk8.ToolContext {
|
|
|
3527
3538
|
}
|
|
3528
3539
|
async execute(input) {
|
|
3529
3540
|
const { script, allowedTools } = input;
|
|
3530
|
-
const callerSurface = (0,
|
|
3541
|
+
const callerSurface = (0, import_sdk9.getCallSurface)();
|
|
3531
3542
|
const audit = this.tryGet(AuditLoggerService);
|
|
3532
3543
|
const executionId = audit ? audit.generateExecutionId() : "";
|
|
3533
3544
|
const callDepth = 1;
|
|
@@ -3568,10 +3579,10 @@ var ExecuteTool = class extends import_sdk8.ToolContext {
|
|
|
3568
3579
|
arguments: toolInput
|
|
3569
3580
|
}
|
|
3570
3581
|
};
|
|
3571
|
-
const ctx = {
|
|
3582
|
+
const ctx = asCodeCallDispatch({
|
|
3572
3583
|
authInfo: this.authInfo,
|
|
3573
3584
|
surface: callerSurface
|
|
3574
|
-
};
|
|
3585
|
+
});
|
|
3575
3586
|
const mcpResult = await this.scope.runFlow("tools:call-tool", { request, ctx });
|
|
3576
3587
|
if (!mcpResult) {
|
|
3577
3588
|
audit?.logToolCallFailure(
|
|
@@ -3750,7 +3761,7 @@ var ExecuteTool = class extends import_sdk8.ToolContext {
|
|
|
3750
3761
|
}
|
|
3751
3762
|
};
|
|
3752
3763
|
ExecuteTool = __decorateClass([
|
|
3753
|
-
(0,
|
|
3764
|
+
(0, import_sdk9.Tool)({
|
|
3754
3765
|
name: "codecall:execute",
|
|
3755
3766
|
cache: {
|
|
3756
3767
|
ttl: 0,
|
|
@@ -3768,7 +3779,7 @@ ExecuteTool = __decorateClass([
|
|
|
3768
3779
|
], ExecuteTool);
|
|
3769
3780
|
|
|
3770
3781
|
// plugins/plugin-codecall/src/tools/invoke.tool.ts
|
|
3771
|
-
var
|
|
3782
|
+
var import_sdk10 = require("@frontmcp/sdk");
|
|
3772
3783
|
|
|
3773
3784
|
// plugins/plugin-codecall/src/tools/invoke.schema.ts
|
|
3774
3785
|
var import_lazy_zod8 = require("@frontmcp/lazy-zod");
|
|
@@ -3800,7 +3811,7 @@ function buildErrorResult(message) {
|
|
|
3800
3811
|
isError: true
|
|
3801
3812
|
};
|
|
3802
3813
|
}
|
|
3803
|
-
var InvokeTool = class extends
|
|
3814
|
+
var InvokeTool = class extends import_sdk10.ToolContext {
|
|
3804
3815
|
async execute(input) {
|
|
3805
3816
|
const { tool: toolName, input: toolInput } = input;
|
|
3806
3817
|
const audit = this.tryGet(AuditLoggerService);
|
|
@@ -3812,7 +3823,7 @@ var InvokeTool = class extends import_sdk9.ToolContext {
|
|
|
3812
3823
|
`Tool "${toolName}" cannot be invoked directly. CodeCall tools are internal and not accessible via codecall:invoke.`
|
|
3813
3824
|
);
|
|
3814
3825
|
}
|
|
3815
|
-
const surface = (0,
|
|
3826
|
+
const surface = (0, import_sdk10.getCallSurface)();
|
|
3816
3827
|
const decision = checkCodeCallToolAccess(this.scope, this.get(CodeCallConfig), toolName, {
|
|
3817
3828
|
directCall: true,
|
|
3818
3829
|
surface
|
|
@@ -3828,10 +3839,10 @@ var InvokeTool = class extends import_sdk9.ToolContext {
|
|
|
3828
3839
|
arguments: toolInput
|
|
3829
3840
|
}
|
|
3830
3841
|
};
|
|
3831
|
-
const ctx = {
|
|
3842
|
+
const ctx = asCodeCallDispatch({
|
|
3832
3843
|
authInfo: this.authInfo,
|
|
3833
3844
|
surface
|
|
3834
|
-
};
|
|
3845
|
+
});
|
|
3835
3846
|
const result = await this.scope.runFlow("tools:call-tool", { request, ctx });
|
|
3836
3847
|
if (!result) {
|
|
3837
3848
|
audit?.logInvoke(executionId, toolName, false, Date.now() - startedAt);
|
|
@@ -3842,7 +3853,7 @@ var InvokeTool = class extends import_sdk9.ToolContext {
|
|
|
3842
3853
|
}
|
|
3843
3854
|
};
|
|
3844
3855
|
InvokeTool = __decorateClass([
|
|
3845
|
-
(0,
|
|
3856
|
+
(0, import_sdk10.Tool)({
|
|
3846
3857
|
name: "codecall:invoke",
|
|
3847
3858
|
cache: {
|
|
3848
3859
|
ttl: 0,
|
|
@@ -3864,12 +3875,16 @@ function auditLogFields(event) {
|
|
|
3864
3875
|
const { executionId, durationMs, data } = event;
|
|
3865
3876
|
return durationMs === void 0 ? { executionId, ...data } : { executionId, durationMs, ...data };
|
|
3866
3877
|
}
|
|
3867
|
-
|
|
3878
|
+
function callContextOf(flowCtx) {
|
|
3879
|
+
const rawInput = flowCtx.rawInput;
|
|
3880
|
+
return typeof rawInput === "object" && rawInput !== null ? rawInput.ctx : void 0;
|
|
3881
|
+
}
|
|
3882
|
+
var CodeCallPlugin = class extends import_sdk11.DynamicPlugin {
|
|
3868
3883
|
options;
|
|
3869
3884
|
cachedLogger;
|
|
3870
3885
|
getLogger() {
|
|
3871
3886
|
if (!this.cachedLogger) {
|
|
3872
|
-
this.cachedLogger = this.get(
|
|
3887
|
+
this.cachedLogger = this.get(import_sdk11.FrontMcpLogger).child("CodeCall");
|
|
3873
3888
|
}
|
|
3874
3889
|
return this.cachedLogger;
|
|
3875
3890
|
}
|
|
@@ -3905,7 +3920,7 @@ var CodeCallPlugin = class extends import_sdk10.DynamicPlugin {
|
|
|
3905
3920
|
// per-request would grow the listener Set for the life of the process.
|
|
3906
3921
|
name: "codecall:audit-logger",
|
|
3907
3922
|
provide: AuditLoggerService,
|
|
3908
|
-
inject: () => [
|
|
3923
|
+
inject: () => [import_sdk11.ScopeEntry],
|
|
3909
3924
|
useFactory: (scope) => {
|
|
3910
3925
|
const audit = new AuditLoggerService();
|
|
3911
3926
|
const logger = scope.logger.child("codecall:audit");
|
|
@@ -3916,7 +3931,7 @@ var CodeCallPlugin = class extends import_sdk10.DynamicPlugin {
|
|
|
3916
3931
|
{
|
|
3917
3932
|
name: "codecall:tool-search",
|
|
3918
3933
|
provide: ToolSearchService,
|
|
3919
|
-
inject: () => [
|
|
3934
|
+
inject: () => [import_sdk11.ScopeEntry],
|
|
3920
3935
|
useFactory: async (scope) => {
|
|
3921
3936
|
return new ToolSearchService(
|
|
3922
3937
|
{
|
|
@@ -3939,12 +3954,32 @@ var CodeCallPlugin = class extends import_sdk10.DynamicPlugin {
|
|
|
3939
3954
|
logger.verbose("adjustListTools: no tools to filter, returning early");
|
|
3940
3955
|
return;
|
|
3941
3956
|
}
|
|
3942
|
-
const
|
|
3943
|
-
|
|
3944
|
-
|
|
3957
|
+
const scope = this.tryGetScope();
|
|
3958
|
+
const filteredTools = resolvedTools.filter(
|
|
3959
|
+
({ tool }) => !this.judges(scope, { tool }) || this.shouldShowInListTools(tool, this.options.mode)
|
|
3960
|
+
);
|
|
3945
3961
|
logger.verbose("adjustListTools: tools after filter", { count: filteredTools.length });
|
|
3946
3962
|
flowCtx.state.set("resolvedTools", filteredTools);
|
|
3947
3963
|
}
|
|
3964
|
+
async refuseDirectCallOfHiddenTool(flowCtx) {
|
|
3965
|
+
const { tool } = flowCtx.state;
|
|
3966
|
+
if (!tool || tool.owner?.kind === "scope") return;
|
|
3967
|
+
if (this.shouldShowInListTools(tool, this.options.mode)) return;
|
|
3968
|
+
if (isInProcessDispatch(callContextOf(flowCtx))) return;
|
|
3969
|
+
this.getLogger().verbose("refused a direct tools/call of a tool CodeCall hides", { tool: tool.fullName });
|
|
3970
|
+
throw new import_sdk11.ToolNotFoundError(flowCtx.state.input?.name ?? tool.name);
|
|
3971
|
+
}
|
|
3972
|
+
/** Whether this instance's direct-call gate runs for the tool, so the listing hides only what that gate refuses. */
|
|
3973
|
+
judges(scope, entry) {
|
|
3974
|
+
return !scope?.hooks || (0, import_sdk11.isEntryGatedBy)(scope, entry, this);
|
|
3975
|
+
}
|
|
3976
|
+
tryGetScope() {
|
|
3977
|
+
try {
|
|
3978
|
+
return this.get(import_sdk11.ScopeEntry);
|
|
3979
|
+
} catch {
|
|
3980
|
+
return void 0;
|
|
3981
|
+
}
|
|
3982
|
+
}
|
|
3948
3983
|
/**
|
|
3949
3984
|
* Determine if a tool should be visible in list_tools based on mode.
|
|
3950
3985
|
*
|
|
@@ -3998,10 +4033,13 @@ var CodeCallPlugin = class extends import_sdk10.DynamicPlugin {
|
|
|
3998
4033
|
}
|
|
3999
4034
|
};
|
|
4000
4035
|
__decorateClass([
|
|
4001
|
-
|
|
4036
|
+
import_sdk11.ListToolsHook.Did("resolveConflicts", { priority: 1e3 })
|
|
4002
4037
|
], CodeCallPlugin.prototype, "adjustListTools", 1);
|
|
4038
|
+
__decorateClass([
|
|
4039
|
+
import_sdk11.ToolHook.Did("findTool", { priority: 10, appliesTo: "uncovered-apps" })
|
|
4040
|
+
], CodeCallPlugin.prototype, "refuseDirectCallOfHiddenTool", 1);
|
|
4003
4041
|
CodeCallPlugin = __decorateClass([
|
|
4004
|
-
(0,
|
|
4042
|
+
(0, import_sdk11.Plugin)({
|
|
4005
4043
|
name: "codecall",
|
|
4006
4044
|
description: "CodeCall plugin: AgentScript-based meta-tools for orchestrating MCP tools",
|
|
4007
4045
|
providers: [],
|