@cursor/july 0.1.100 → 0.1.101
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/dist/bin/agent-serve.js +3 -2
- package/dist/channels/deployments/deployments-channel.d.ts +41 -5
- package/dist/channels/deployments/deployments-channel.d.ts.map +1 -1
- package/dist/channels/deployments/deployments-channel.js +88 -8
- package/dist/channels/deployments/types.d.ts +4 -3
- package/dist/channels/deployments/types.d.ts.map +1 -1
- package/dist/channels/origin/defaults.d.ts +43 -0
- package/dist/channels/origin/defaults.d.ts.map +1 -0
- package/dist/channels/origin/defaults.js +111 -0
- package/dist/channels/origin/index.d.ts +2 -0
- package/dist/channels/origin/index.d.ts.map +1 -1
- package/dist/channels/origin/index.js +2 -0
- package/dist/channels/origin/origin-channel.d.ts +2 -1
- package/dist/channels/origin/origin-channel.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.js +24 -3
- package/dist/channels/origin/state.d.ts +32 -0
- package/dist/channels/origin/state.d.ts.map +1 -0
- package/dist/channels/origin/state.js +23 -0
- package/dist/channels/origin/types.d.ts +23 -1
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/api.d.ts.map +1 -1
- package/dist/channels/slack/api.js +2 -1
- package/dist/channels/slack/code-fences.d.ts +17 -0
- package/dist/channels/slack/code-fences.d.ts.map +1 -0
- package/dist/channels/slack/code-fences.js +168 -0
- package/dist/channels/slack/index.d.ts +1 -0
- package/dist/channels/slack/index.d.ts.map +1 -1
- package/dist/channels/slack/index.js +1 -0
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +11 -4
- package/dist/connections.d.ts +18 -2
- package/dist/connections.d.ts.map +1 -1
- package/dist/connections.js +18 -2
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.DZ1e0Ycq.js → app.BASO9Kih.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DbFXINq2.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.l8omwc6D.js → VPLocalSearchBox.DwkqxoE0.js} +1 -1
- package/dist/docs/assets/chunks/{theme.JVcD6gel.js → theme.CCil_13e.js} +2 -2
- package/dist/docs/assets/{reference_connections.md.BiGoBAk2.js → reference_connections.md.Di6jJAXF.js} +12 -2
- package/dist/docs/assets/{reference_connections.md.BiGoBAk2.lean.js → reference_connections.md.Di6jJAXF.lean.js} +1 -1
- package/dist/docs/assets/{reference_http-api.md.BEJx9XVj.js → reference_http-api.md.oySXBO8o.js} +1 -1
- package/dist/docs/building-with-agents.html +4 -4
- package/dist/docs/concepts.html +4 -4
- package/dist/docs/deployment.html +4 -4
- package/dist/docs/evals.html +4 -4
- package/dist/docs/guides/agent-to-agent.html +4 -4
- package/dist/docs/guides/cloud-runtime.html +4 -4
- package/dist/docs/guides/convert-automation.html +4 -4
- package/dist/docs/guides/github.html +4 -4
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +4 -4
- package/dist/docs/guides/opentelemetry.html +4 -4
- package/dist/docs/guides/slack.html +4 -4
- package/dist/docs/guides/webhooks.html +4 -4
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +4 -4
- package/dist/docs/index.html +4 -4
- package/dist/docs/llms-full.txt +32 -1
- package/dist/docs/quickstart.html +4 -4
- package/dist/docs/reference/agent-config.html +4 -4
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +4 -4
- package/dist/docs/reference/cli.html +4 -4
- package/dist/docs/reference/connections.html +16 -6
- package/dist/docs/reference/connections.md +31 -0
- package/dist/docs/reference/hooks.html +4 -4
- package/dist/docs/reference/http-api.html +6 -6
- package/dist/docs/reference/http-api.md +1 -1
- package/dist/docs/reference/instructions.html +4 -4
- package/dist/docs/reference/playground.html +4 -4
- package/dist/docs/reference/project-layout.html +4 -4
- package/dist/docs/reference/prompt.html +4 -4
- package/dist/docs/reference/schedules.html +4 -4
- package/dist/docs/reference/sessions.html +4 -4
- package/dist/docs/reference/skills.html +4 -4
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +4 -4
- package/dist/docs/scaffolding-agents.html +4 -4
- package/dist/docs/skills/ab.html +4 -4
- package/dist/docs/skills/create-agent.html +4 -4
- package/dist/docs/skills/debug.html +4 -4
- package/dist/docs/skills/evals.html +4 -4
- package/dist/docs/skills/framework-map.html +4 -4
- package/dist/docs/skills/github.html +4 -4
- package/dist/docs/skills/hillclimb.html +4 -4
- package/dist/docs/skills/index.html +4 -4
- package/dist/docs/skills/mcp-auth.html +4 -4
- package/dist/docs/skills/otel.html +4 -4
- package/dist/docs/skills/setup-slack.html +4 -4
- package/dist/docs/storage.html +4 -4
- package/dist/docs/templates/agentic-owners.html +4 -4
- package/dist/docs/templates/agents-md.html +4 -4
- package/dist/docs/templates/code-wiki.html +4 -4
- package/dist/docs/templates/demo.html +4 -4
- package/dist/docs/templates/pr-autofixer.html +4 -4
- package/dist/docs/templates/security-help.html +4 -4
- package/dist/docs/templates/security-reviewer.html +4 -4
- package/dist/docs/templates/triage.html +4 -4
- package/dist/docs/troubleshooting.html +4 -4
- package/dist/extensions/cursor-cloud-agents/extension.d.ts +55 -0
- package/dist/extensions/cursor-cloud-agents/extension.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/extension.js +64 -0
- package/dist/extensions/cursor-cloud-agents/lib/cloud.d.ts +30 -0
- package/dist/extensions/cursor-cloud-agents/lib/cloud.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/lib/cloud.js +45 -0
- package/dist/extensions/cursor-cloud-agents/lib/fleet.d.ts +25 -0
- package/dist/extensions/cursor-cloud-agents/lib/fleet.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/lib/fleet.js +85 -0
- package/dist/extensions/cursor-cloud-agents/lib/repos.d.ts +15 -0
- package/dist/extensions/cursor-cloud-agents/lib/repos.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/lib/repos.js +55 -0
- package/dist/extensions/cursor-cloud-agents/skills/handoff.md +27 -0
- package/dist/extensions/cursor-cloud-agents/tools/follow_up.d.ts +4 -0
- package/dist/extensions/cursor-cloud-agents/tools/follow_up.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/tools/follow_up.js +37 -0
- package/dist/extensions/cursor-cloud-agents/tools/launch.d.ts +4 -0
- package/dist/extensions/cursor-cloud-agents/tools/launch.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/tools/launch.js +83 -0
- package/dist/extensions/cursor-cloud-agents/tools/list.d.ts +4 -0
- package/dist/extensions/cursor-cloud-agents/tools/list.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/tools/list.js +36 -0
- package/dist/extensions/cursor-cloud-agents/tools/status.d.ts +4 -0
- package/dist/extensions/cursor-cloud-agents/tools/status.d.ts.map +1 -0
- package/dist/extensions/cursor-cloud-agents/tools/status.js +41 -0
- package/dist/extensions.d.ts +49 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/extensions.js +75 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/internal/advertise-tools.d.ts +4 -1
- package/dist/internal/advertise-tools.d.ts.map +1 -1
- package/dist/internal/advertise-tools.js +20 -1
- package/dist/internal/as-of.d.ts +18 -0
- package/dist/internal/as-of.d.ts.map +1 -1
- package/dist/internal/as-of.js +131 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +64 -19
- package/dist/internal/continuation-identity.d.ts.map +1 -1
- package/dist/internal/continuation-identity.js +3 -1
- package/dist/internal/cursor/hosted-deployment-secrets.d.ts +16 -0
- package/dist/internal/cursor/hosted-deployment-secrets.d.ts.map +1 -0
- package/dist/internal/cursor/hosted-deployment-secrets.js +61 -0
- package/dist/internal/cursor-deployment-relay.d.ts +15 -1
- package/dist/internal/cursor-deployment-relay.d.ts.map +1 -1
- package/dist/internal/cursor-deployment-relay.js +46 -7
- package/dist/internal/deploy-client.d.ts +23 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +54 -12
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +415 -120
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +5 -0
- package/dist/internal/framework-file-storage.d.ts +3 -3
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +34 -5
- package/dist/internal/hosted-delivery.d.ts +3 -1
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +19 -32
- package/dist/internal/hosted-execution-diag.d.ts +5 -0
- package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
- package/dist/internal/hosted-execution-diag.js +5 -0
- package/dist/internal/hosted-execution-flush.d.ts +46 -0
- package/dist/internal/hosted-execution-flush.d.ts.map +1 -0
- package/dist/internal/hosted-execution-flush.js +81 -0
- package/dist/internal/mcp-endpoint.js +1 -0
- package/dist/internal/mcp-host.d.ts +2 -1
- package/dist/internal/mcp-host.d.ts.map +1 -1
- package/dist/internal/mcp-host.js +35 -15
- package/dist/internal/review-comments.d.ts +1 -1
- package/dist/internal/review-comments.d.ts.map +1 -1
- package/dist/internal/review-comments.js +4 -4
- package/dist/internal/server.d.ts +3 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +79 -104
- package/dist/internal/session-engine.d.ts +9 -7
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +45 -34
- package/dist/internal/session-run-log.d.ts +2 -1
- package/dist/internal/session-run-log.d.ts.map +1 -1
- package/dist/internal/session-run-log.js +2 -1
- package/dist/internal/start-log-store.d.ts +60 -0
- package/dist/internal/start-log-store.d.ts.map +1 -0
- package/dist/internal/start-log-store.js +151 -0
- package/dist/internal/tool-policy.d.ts +8 -0
- package/dist/internal/tool-policy.d.ts.map +1 -1
- package/dist/internal/tool-policy.js +19 -7
- package/dist/playground/assets/{index-DVs98vPL.js → index-BnNN1-EK.js} +45 -45
- package/dist/playground/assets/index-DBQCwFp0.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/storage-protocol.d.ts +24 -0
- package/dist/storage-protocol.d.ts.map +1 -1
- package/dist/storage-protocol.js +33 -0
- package/dist/storage.d.ts +1 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +1 -1
- package/dist/types.d.ts +118 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +29 -1
- package/docs/reference/connections.md +31 -0
- package/docs/reference/http-api.md +1 -1
- package/package.json +18 -4
- package/src/bin/agent-serve.ts +11 -2
- package/src/channels/deployments/deployments-channel.ts +117 -8
- package/src/channels/deployments/types.ts +4 -3
- package/src/channels/origin/defaults.ts +143 -0
- package/src/channels/origin/index.ts +2 -0
- package/src/channels/origin/origin-channel.ts +37 -1
- package/src/channels/origin/state.ts +54 -0
- package/src/channels/origin/types.ts +24 -0
- package/src/channels/slack/api.ts +2 -1
- package/src/channels/slack/code-fences.ts +183 -0
- package/src/channels/slack/index.ts +1 -0
- package/src/channels/slack/live-delivery.ts +16 -13
- package/src/connections.ts +18 -1
- package/src/extensions/cursor-cloud-agents/extension.ts +118 -0
- package/src/extensions/cursor-cloud-agents/lib/cloud.ts +79 -0
- package/src/extensions/cursor-cloud-agents/lib/fleet.ts +109 -0
- package/src/extensions/cursor-cloud-agents/lib/repos.ts +81 -0
- package/src/extensions/cursor-cloud-agents/skills/handoff.md +27 -0
- package/src/extensions/cursor-cloud-agents/tools/follow_up.ts +29 -0
- package/src/extensions/cursor-cloud-agents/tools/launch.ts +84 -0
- package/src/extensions/cursor-cloud-agents/tools/list.ts +31 -0
- package/src/extensions/cursor-cloud-agents/tools/status.ts +39 -0
- package/src/extensions.ts +98 -0
- package/src/index.ts +2 -0
- package/src/internal/advertise-tools.ts +37 -12
- package/src/internal/as-of.ts +163 -0
- package/src/internal/cli-deploy.ts +86 -23
- package/src/internal/continuation-identity.ts +3 -1
- package/src/internal/cursor/hosted-deployment-secrets.ts +72 -0
- package/src/internal/cursor-deployment-relay.ts +65 -8
- package/src/internal/deploy-client.ts +73 -18
- package/src/internal/discovery.ts +470 -113
- package/src/internal/distribution.ts +5 -0
- package/src/internal/framework-file-storage.ts +39 -5
- package/src/internal/hosted-delivery.ts +38 -63
- package/src/internal/hosted-execution-diag.ts +6 -0
- package/src/internal/hosted-execution-flush.ts +142 -0
- package/src/internal/mcp-endpoint.ts +1 -0
- package/src/internal/mcp-host.ts +40 -14
- package/src/internal/review-comments.ts +5 -2
- package/src/internal/server.ts +81 -100
- package/src/internal/session-engine.ts +56 -28
- package/src/internal/session-run-log.ts +2 -1
- package/src/internal/start-log-store.ts +177 -0
- package/src/internal/tool-policy.ts +39 -9
- package/src/storage-protocol.ts +37 -0
- package/src/storage.ts +1 -0
- package/src/types.ts +172 -14
- package/dist/docs/assets/chunks/@localSearchIndexroot.j70vvPL4.js +0 -1
- package/dist/playground/assets/index-BszoQDc6.css +0 -1
- /package/dist/docs/assets/{reference_http-api.md.BEJx9XVj.lean.js → reference_http-api.md.oySXBO8o.lean.js} +0 -0
|
@@ -31,7 +31,7 @@ import { pathToFileURL } from "node:url";
|
|
|
31
31
|
import { resolveABMaxPlaygroundSessions } from "../ab.js";
|
|
32
32
|
import { resolveArtifactsMax } from "../artifacts.js";
|
|
33
33
|
import { httpChannel } from "../channels.js";
|
|
34
|
-
import { cursorAccountServersHasMixedWildcard, DEFAULT_MODEL, isInlineStdioConnection, isToolEffect, MAX_RUNNING_TURNS_LIMIT, normalizeConnectionEffects, normalizeCursorAccountServers, toPublicCloudInfo, } from "../types.js";
|
|
34
|
+
import { cursorAccountServersHasMixedWildcard, DEFAULT_MODEL, isInlineStdioConnection, isToolEffect, MAX_RUNNING_TURNS_LIMIT, normalizeConnectionEffects, normalizeConnectionTools, normalizeCursorAccountServers, toPublicCloudInfo, } from "../types.js";
|
|
35
35
|
import { registerAuthoredModuleLoaders } from "./authored-loaders.js";
|
|
36
36
|
import { normalizePositiveInt } from "./bounded-int.js";
|
|
37
37
|
import { getDefinitionKind } from "./brand.js";
|
|
@@ -310,6 +310,7 @@ function loadAgent(ctx, agentDir, options) {
|
|
|
310
310
|
}
|
|
311
311
|
const tools = yield loadTools(ctx, join(agentDir, "tools"));
|
|
312
312
|
const skills = yield loadSkills(ctx, join(agentDir, "skills"));
|
|
313
|
+
const extensions = yield appendExtensions(ctx, join(agentDir, "extensions"), tools, skills);
|
|
313
314
|
const connections = yield loadConnections(ctx, yield resolveMcpConnectionsDir(ctx, agentDir));
|
|
314
315
|
const hostConnections = yield loadHostConnections(ctx, agentDir, connections);
|
|
315
316
|
const seedFiles = yield loadSeedFiles(ctx, agentDir);
|
|
@@ -430,6 +431,7 @@ function loadAgent(ctx, agentDir, options) {
|
|
|
430
431
|
local }, (allowedTools === undefined ? {} : { allowedTools })), { hosting,
|
|
431
432
|
concurrency }), (architecture === undefined ? {} : { architecture })), { tools,
|
|
432
433
|
skills,
|
|
434
|
+
extensions,
|
|
433
435
|
connections,
|
|
434
436
|
hostConnections,
|
|
435
437
|
subagents,
|
|
@@ -662,17 +664,34 @@ function loadInstructionsModule(ctx, modulePath) {
|
|
|
662
664
|
// Tools
|
|
663
665
|
// ============================================================================
|
|
664
666
|
function loadTools(ctx, toolsDir) {
|
|
667
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
668
|
+
const tools = [];
|
|
669
|
+
for (const { name, path } of yield toolModuleEntries(ctx, toolsDir)) {
|
|
670
|
+
const definition = yield importDefault(ctx, path, "tool");
|
|
671
|
+
if (definition === undefined) {
|
|
672
|
+
continue;
|
|
673
|
+
}
|
|
674
|
+
const tool = compileTool(ctx, path, name, definition);
|
|
675
|
+
if (tool !== undefined) {
|
|
676
|
+
tools.push(tool);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
return tools;
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
/** The module files of a `tools/` directory whose filenames are valid tool names. */
|
|
683
|
+
function toolModuleEntries(ctx, toolsDir) {
|
|
665
684
|
return __awaiter(this, void 0, void 0, function* () {
|
|
666
685
|
if (!(yield isDirectory(toolsDir))) {
|
|
667
686
|
return [];
|
|
668
687
|
}
|
|
669
|
-
const
|
|
688
|
+
const entries = [];
|
|
670
689
|
for (const entry of yield sortedEntries(toolsDir)) {
|
|
671
|
-
const
|
|
690
|
+
const path = join(toolsDir, entry.name);
|
|
672
691
|
if (entry.isDirectory()) {
|
|
673
692
|
ctx.diagnostics.push({
|
|
674
693
|
severity: "warning",
|
|
675
|
-
path: displayPath(ctx,
|
|
694
|
+
path: displayPath(ctx, path),
|
|
676
695
|
message: "Nested tool directories are not supported; ignoring.",
|
|
677
696
|
});
|
|
678
697
|
continue;
|
|
@@ -681,94 +700,99 @@ function loadTools(ctx, toolsDir) {
|
|
|
681
700
|
continue;
|
|
682
701
|
}
|
|
683
702
|
const name = moduleStem(entry.name);
|
|
684
|
-
if (
|
|
685
|
-
|
|
686
|
-
severity: "error",
|
|
687
|
-
path: displayPath(ctx, entryPath),
|
|
688
|
-
message: `Tool name "${name}" must match ${NAME_PATTERN} (the filename becomes the tool name the model sees).`,
|
|
689
|
-
});
|
|
690
|
-
continue;
|
|
691
|
-
}
|
|
692
|
-
const definition = yield importDefault(ctx, entryPath, "tool");
|
|
693
|
-
if (definition === undefined) {
|
|
694
|
-
continue;
|
|
695
|
-
}
|
|
696
|
-
const tool = definition;
|
|
697
|
-
if (isBlank(tool.description)) {
|
|
698
|
-
ctx.diagnostics.push({
|
|
699
|
-
severity: "error",
|
|
700
|
-
path: displayPath(ctx, entryPath),
|
|
701
|
-
message: "Tools require a non-empty description.",
|
|
702
|
-
});
|
|
703
|
-
continue;
|
|
704
|
-
}
|
|
705
|
-
const execution = tool.execution === "agent" ? "agent" : "server";
|
|
706
|
-
const needsApprovalConfigured = tool.needsApproval === true || typeof tool.needsApproval === "function";
|
|
707
|
-
const effect = declaredEffect(tool);
|
|
708
|
-
if (execution === "agent") {
|
|
709
|
-
if (isBlank(tool.script)) {
|
|
710
|
-
ctx.diagnostics.push({
|
|
711
|
-
severity: "error",
|
|
712
|
-
path: displayPath(ctx, entryPath),
|
|
713
|
-
message: 'Tools with execution: "agent" require a non-empty `script` (shell body; JSON on stdin, result on stdout).',
|
|
714
|
-
});
|
|
715
|
-
continue;
|
|
716
|
-
}
|
|
717
|
-
if (typeof tool.execute === "function") {
|
|
718
|
-
ctx.diagnostics.push({
|
|
719
|
-
severity: "warning",
|
|
720
|
-
path: displayPath(ctx, entryPath),
|
|
721
|
-
message: '`execute` is ignored when execution is "agent"; the Cursor agent runs `script` instead.',
|
|
722
|
-
});
|
|
723
|
-
}
|
|
724
|
-
if (needsApprovalConfigured) {
|
|
725
|
-
ctx.diagnostics.push({
|
|
726
|
-
severity: "error",
|
|
727
|
-
path: displayPath(ctx, entryPath),
|
|
728
|
-
message: '`needsApproval` is only supported for execution: "server" tools (in-process).',
|
|
729
|
-
});
|
|
730
|
-
continue;
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
else if (typeof tool.execute !== "function") {
|
|
734
|
-
ctx.diagnostics.push({
|
|
735
|
-
severity: "error",
|
|
736
|
-
path: displayPath(ctx, entryPath),
|
|
737
|
-
message: 'Tools require an execute(input, ctx) function (or set execution: "agent" with a script).',
|
|
738
|
-
});
|
|
739
|
-
continue;
|
|
703
|
+
if (validateName(ctx, "tool", name, path)) {
|
|
704
|
+
entries.push({ name, path });
|
|
740
705
|
}
|
|
741
|
-
let inputSchema;
|
|
742
|
-
try {
|
|
743
|
-
inputSchema = toolInputJsonSchema(tool.inputSchema);
|
|
744
|
-
}
|
|
745
|
-
catch (error) {
|
|
746
|
-
ctx.diagnostics.push({
|
|
747
|
-
severity: "error",
|
|
748
|
-
path: displayPath(ctx, entryPath),
|
|
749
|
-
message: `Failed to convert inputSchema to JSON Schema: ${errorMessage(error)}`,
|
|
750
|
-
});
|
|
751
|
-
continue;
|
|
752
|
-
}
|
|
753
|
-
let outputSchema;
|
|
754
|
-
try {
|
|
755
|
-
outputSchema = toolOutputJsonSchema(tool.outputSchema);
|
|
756
|
-
}
|
|
757
|
-
catch (error) {
|
|
758
|
-
ctx.diagnostics.push({
|
|
759
|
-
severity: "error",
|
|
760
|
-
path: displayPath(ctx, entryPath),
|
|
761
|
-
message: `Failed to convert outputSchema to JSON Schema: ${errorMessage(error)}`,
|
|
762
|
-
});
|
|
763
|
-
continue;
|
|
764
|
-
}
|
|
765
|
-
tools.push(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ name, description: tool.description, inputSchema }, (outputSchema === undefined ? {} : { outputSchema })), { execution, needsApproval: needsApprovalConfigured }), (effect === undefined ? {} : { effect })), (execution === "agent" && tool.script !== undefined
|
|
766
|
-
? { script: tool.script }
|
|
767
|
-
: {})), { definition: tool }));
|
|
768
706
|
}
|
|
769
|
-
return
|
|
707
|
+
return entries;
|
|
770
708
|
});
|
|
771
709
|
}
|
|
710
|
+
/**
|
|
711
|
+
* Validate one tool definition against the tool contract and convert its
|
|
712
|
+
* schemas. Diagnostics point at `entryPath` (the authored file, or the
|
|
713
|
+
* extension mount that contributed the tool).
|
|
714
|
+
*/
|
|
715
|
+
function compileTool(ctx, entryPath, name, tool) {
|
|
716
|
+
if (isBlank(tool.description)) {
|
|
717
|
+
ctx.diagnostics.push({
|
|
718
|
+
severity: "error",
|
|
719
|
+
path: displayPath(ctx, entryPath),
|
|
720
|
+
message: "Tools require a non-empty description.",
|
|
721
|
+
});
|
|
722
|
+
return undefined;
|
|
723
|
+
}
|
|
724
|
+
const execution = tool.execution === "agent" ? "agent" : "server";
|
|
725
|
+
const needsApprovalConfigured = tool.needsApproval === true || typeof tool.needsApproval === "function";
|
|
726
|
+
const effect = declaredEffect(tool);
|
|
727
|
+
if (execution === "agent") {
|
|
728
|
+
if (isBlank(tool.script)) {
|
|
729
|
+
ctx.diagnostics.push({
|
|
730
|
+
severity: "error",
|
|
731
|
+
path: displayPath(ctx, entryPath),
|
|
732
|
+
message: 'Tools with execution: "agent" require a non-empty `script` (shell body; JSON on stdin, result on stdout).',
|
|
733
|
+
});
|
|
734
|
+
return undefined;
|
|
735
|
+
}
|
|
736
|
+
if (typeof tool.execute === "function") {
|
|
737
|
+
ctx.diagnostics.push({
|
|
738
|
+
severity: "warning",
|
|
739
|
+
path: displayPath(ctx, entryPath),
|
|
740
|
+
message: '`execute` is ignored when execution is "agent"; the Cursor agent runs `script` instead.',
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
if (needsApprovalConfigured) {
|
|
744
|
+
ctx.diagnostics.push({
|
|
745
|
+
severity: "error",
|
|
746
|
+
path: displayPath(ctx, entryPath),
|
|
747
|
+
message: '`needsApproval` is only supported for execution: "server" tools (in-process).',
|
|
748
|
+
});
|
|
749
|
+
return undefined;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
else if (typeof tool.execute !== "function") {
|
|
753
|
+
ctx.diagnostics.push({
|
|
754
|
+
severity: "error",
|
|
755
|
+
path: displayPath(ctx, entryPath),
|
|
756
|
+
message: 'Tools require an execute(input, ctx) function (or set execution: "agent" with a script).',
|
|
757
|
+
});
|
|
758
|
+
return undefined;
|
|
759
|
+
}
|
|
760
|
+
let inputSchema;
|
|
761
|
+
try {
|
|
762
|
+
inputSchema = toolInputJsonSchema(tool.inputSchema);
|
|
763
|
+
}
|
|
764
|
+
catch (error) {
|
|
765
|
+
ctx.diagnostics.push({
|
|
766
|
+
severity: "error",
|
|
767
|
+
path: displayPath(ctx, entryPath),
|
|
768
|
+
message: `Failed to convert inputSchema to JSON Schema: ${errorMessage(error)}`,
|
|
769
|
+
});
|
|
770
|
+
return undefined;
|
|
771
|
+
}
|
|
772
|
+
let outputSchema;
|
|
773
|
+
try {
|
|
774
|
+
outputSchema = toolOutputJsonSchema(tool.outputSchema);
|
|
775
|
+
}
|
|
776
|
+
catch (error) {
|
|
777
|
+
ctx.diagnostics.push({
|
|
778
|
+
severity: "error",
|
|
779
|
+
path: displayPath(ctx, entryPath),
|
|
780
|
+
message: `Failed to convert outputSchema to JSON Schema: ${errorMessage(error)}`,
|
|
781
|
+
});
|
|
782
|
+
return undefined;
|
|
783
|
+
}
|
|
784
|
+
return {
|
|
785
|
+
name,
|
|
786
|
+
description: tool.description,
|
|
787
|
+
inputSchema,
|
|
788
|
+
outputSchema,
|
|
789
|
+
execution,
|
|
790
|
+
needsApproval: needsApprovalConfigured,
|
|
791
|
+
effect,
|
|
792
|
+
script: execution === "agent" ? tool.script : undefined,
|
|
793
|
+
definition: tool,
|
|
794
|
+
};
|
|
795
|
+
}
|
|
772
796
|
/**
|
|
773
797
|
* Static view of a tool's `effect` for the manifest: the literal when it is
|
|
774
798
|
* one, `"dynamic"` for a per-call predicate, `undefined` when undeclared. A
|
|
@@ -788,7 +812,7 @@ function declaredEffect(tool) {
|
|
|
788
812
|
// ============================================================================
|
|
789
813
|
function loadSkills(ctx, skillsDir) {
|
|
790
814
|
return __awaiter(this, void 0, void 0, function* () {
|
|
791
|
-
var _a, _b
|
|
815
|
+
var _a, _b;
|
|
792
816
|
if (!(yield isDirectory(skillsDir))) {
|
|
793
817
|
return [];
|
|
794
818
|
}
|
|
@@ -807,7 +831,7 @@ function loadSkills(ctx, skillsDir) {
|
|
|
807
831
|
}
|
|
808
832
|
if (entry.name.endsWith(".md")) {
|
|
809
833
|
const name = entry.name.slice(0, -".md".length);
|
|
810
|
-
if (!
|
|
834
|
+
if (!validateName(ctx, "skill", name, entryPath)) {
|
|
811
835
|
continue;
|
|
812
836
|
}
|
|
813
837
|
const { data, body } = parseFrontmatter(yield readFile(entryPath, "utf8"));
|
|
@@ -821,27 +845,217 @@ function loadSkills(ctx, skillsDir) {
|
|
|
821
845
|
}
|
|
822
846
|
if (isModuleFile(entry.name)) {
|
|
823
847
|
const name = moduleStem(entry.name);
|
|
824
|
-
if (!
|
|
848
|
+
if (!validateName(ctx, "skill", name, entryPath)) {
|
|
825
849
|
continue;
|
|
826
850
|
}
|
|
827
851
|
const definition = yield importDefault(ctx, entryPath, "skill");
|
|
828
852
|
if (definition === undefined) {
|
|
829
853
|
continue;
|
|
830
854
|
}
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
855
|
+
skills.push(compileSkill(name, definition));
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
return skills;
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
/** A skill whose body and sibling files are in memory (`defineSkill`, extensions). */
|
|
862
|
+
function compileSkill(name, skill) {
|
|
863
|
+
var _a, _b, _c;
|
|
864
|
+
const files = {};
|
|
865
|
+
for (const [rel, contents] of Object.entries((_a = skill.files) !== null && _a !== void 0 ? _a : {})) {
|
|
866
|
+
files[rel] = { contents };
|
|
867
|
+
}
|
|
868
|
+
return {
|
|
869
|
+
name,
|
|
870
|
+
description: (_c = (_b = skill.description) !== null && _b !== void 0 ? _b : deriveSkillDescription(skill.markdown)) !== null && _c !== void 0 ? _c : SKILL_DESCRIPTION_FALLBACK(name),
|
|
871
|
+
markdown: skill.markdown.trim(),
|
|
872
|
+
files,
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
// ============================================================================
|
|
876
|
+
// Extensions (agent/extensions/<ns>.ts | agent/extensions/<ns>/extension.ts)
|
|
877
|
+
// ============================================================================
|
|
878
|
+
/**
|
|
879
|
+
* Mount every extension under `agent/extensions/` and append its tools and
|
|
880
|
+
* skills to the authored lists as `<ns>__<name>`, stamped with `extension`.
|
|
881
|
+
* The namespace is the mount's filename stem or directory name.
|
|
882
|
+
*/
|
|
883
|
+
function appendExtensions(ctx, extensionsDir, tools, skills) {
|
|
884
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
885
|
+
if (!(yield isDirectory(extensionsDir))) {
|
|
886
|
+
return [];
|
|
887
|
+
}
|
|
888
|
+
const extensions = [];
|
|
889
|
+
for (const entry of yield sortedEntries(extensionsDir)) {
|
|
890
|
+
const path = join(extensionsDir, entry.name);
|
|
891
|
+
const site = yield resolveMountSite(ctx, path, entry);
|
|
892
|
+
if (site === undefined) {
|
|
893
|
+
continue;
|
|
894
|
+
}
|
|
895
|
+
if (extensions.some((extension) => extension.name === site.ns)) {
|
|
896
|
+
ctx.diagnostics.push({
|
|
897
|
+
severity: "error",
|
|
898
|
+
path: displayPath(ctx, path),
|
|
899
|
+
message: `Extension "${site.ns}" is mounted twice (as a file and as a directory).`,
|
|
900
|
+
});
|
|
901
|
+
continue;
|
|
902
|
+
}
|
|
903
|
+
const mount = yield importDefault(ctx, site.mountPath, "extension");
|
|
904
|
+
if (mount === undefined) {
|
|
905
|
+
continue;
|
|
906
|
+
}
|
|
907
|
+
extensions.push(yield mountExtension(ctx, site, mount, tools, skills));
|
|
908
|
+
}
|
|
909
|
+
return extensions;
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
function resolveMountSite(ctx, path, entry) {
|
|
913
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
914
|
+
if (entry.isDirectory()) {
|
|
915
|
+
if (!validateName(ctx, "extension", entry.name, path)) {
|
|
916
|
+
return undefined;
|
|
917
|
+
}
|
|
918
|
+
const mountPath = yield findModuleFile(path, "extension");
|
|
919
|
+
if (mountPath === undefined) {
|
|
920
|
+
ctx.diagnostics.push({
|
|
921
|
+
severity: "error",
|
|
922
|
+
path: displayPath(ctx, path),
|
|
923
|
+
message: "A directory mount needs an extension.ts default-exporting the mount (`export default crm({ ... })`).",
|
|
924
|
+
});
|
|
925
|
+
return undefined;
|
|
926
|
+
}
|
|
927
|
+
return { ns: entry.name, mountPath, overlayDir: path };
|
|
928
|
+
}
|
|
929
|
+
if (!entry.isFile() || !isModuleFile(entry.name)) {
|
|
930
|
+
return undefined;
|
|
931
|
+
}
|
|
932
|
+
const ns = moduleStem(entry.name);
|
|
933
|
+
return validateName(ctx, "extension", ns, path)
|
|
934
|
+
? { ns, mountPath: path }
|
|
935
|
+
: undefined;
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* Read the extension's tree with the agent loaders, lay the mount's overlay
|
|
940
|
+
* on top (a same-named file replaces, `disableTool()` removes), then
|
|
941
|
+
* namespace what is left.
|
|
942
|
+
*/
|
|
943
|
+
function mountExtension(ctx, site, mount, tools, skills) {
|
|
944
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
945
|
+
const mounted = {
|
|
946
|
+
name: site.ns,
|
|
947
|
+
description: mount.extension.description,
|
|
948
|
+
tools: [],
|
|
949
|
+
skills: [],
|
|
950
|
+
};
|
|
951
|
+
const root = mount.extension.root;
|
|
952
|
+
if (!(yield isDirectory(root))) {
|
|
953
|
+
ctx.diagnostics.push({
|
|
954
|
+
severity: "error",
|
|
955
|
+
path: displayPath(ctx, site.mountPath),
|
|
956
|
+
message: `Extension "${site.ns}" declares root ${root}, which is not a directory. Pass \`import.meta.dirname\` from extension.ts.`,
|
|
957
|
+
});
|
|
958
|
+
return mounted;
|
|
959
|
+
}
|
|
960
|
+
yield warnUnsupportedExtensionSlots(ctx, root);
|
|
961
|
+
const contributedTools = new Map((yield loadTools(ctx, join(root, "tools"))).map((tool) => [tool.name, tool]));
|
|
962
|
+
const contributedSkills = new Map((yield loadSkills(ctx, join(root, "skills"))).map((skill) => [
|
|
963
|
+
skill.name,
|
|
964
|
+
skill,
|
|
965
|
+
]));
|
|
966
|
+
if (site.overlayDir !== undefined) {
|
|
967
|
+
const overlay = yield loadOverlayTools(ctx, join(site.overlayDir, "tools"));
|
|
968
|
+
for (const tool of overlay.tools) {
|
|
969
|
+
contributedTools.set(tool.name, tool);
|
|
970
|
+
}
|
|
971
|
+
for (const disabled of overlay.disabled) {
|
|
972
|
+
if (!contributedTools.delete(disabled.name)) {
|
|
973
|
+
ctx.diagnostics.push({
|
|
974
|
+
severity: "error",
|
|
975
|
+
path: displayPath(ctx, disabled.path),
|
|
976
|
+
message: `disableTool() targets "${disabled.name}", which extension "${site.ns}" does not contribute.`,
|
|
977
|
+
});
|
|
835
978
|
}
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
979
|
+
}
|
|
980
|
+
for (const skill of yield loadSkills(ctx, join(site.overlayDir, "skills"))) {
|
|
981
|
+
contributedSkills.set(skill.name, skill);
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
for (const [name, tool] of contributedTools) {
|
|
985
|
+
const composed = `${site.ns}__${name}`;
|
|
986
|
+
tools.push(Object.assign(Object.assign({}, tool), { name: composed, extension: site.ns }));
|
|
987
|
+
mounted.tools.push(composed);
|
|
988
|
+
}
|
|
989
|
+
for (const [name, skill] of contributedSkills) {
|
|
990
|
+
const composed = `${site.ns}__${name}`;
|
|
991
|
+
skills.push(Object.assign(Object.assign({}, skill), { name: composed, extension: site.ns }));
|
|
992
|
+
mounted.skills.push(composed);
|
|
993
|
+
}
|
|
994
|
+
return mounted;
|
|
995
|
+
});
|
|
996
|
+
}
|
|
997
|
+
/** A directory mount's `tools/`: replacements plus `disableTool()` markers. */
|
|
998
|
+
function loadOverlayTools(ctx, toolsDir) {
|
|
999
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1000
|
+
const tools = [];
|
|
1001
|
+
const disabled = [];
|
|
1002
|
+
for (const { name, path } of yield toolModuleEntries(ctx, toolsDir)) {
|
|
1003
|
+
let mod;
|
|
1004
|
+
try {
|
|
1005
|
+
mod = yield ctx.importModule(path);
|
|
1006
|
+
}
|
|
1007
|
+
catch (error) {
|
|
1008
|
+
ctx.diagnostics.push({
|
|
1009
|
+
severity: "error",
|
|
1010
|
+
path: displayPath(ctx, path),
|
|
1011
|
+
message: `Failed to load module: ${errorMessage(error)}`,
|
|
1012
|
+
});
|
|
1013
|
+
continue;
|
|
1014
|
+
}
|
|
1015
|
+
const kind = getDefinitionKind(mod.default);
|
|
1016
|
+
if (kind === "disabled-tool") {
|
|
1017
|
+
disabled.push({ name, path });
|
|
1018
|
+
continue;
|
|
1019
|
+
}
|
|
1020
|
+
if (kind !== "tool") {
|
|
1021
|
+
ctx.diagnostics.push({
|
|
1022
|
+
severity: "error",
|
|
1023
|
+
path: displayPath(ctx, path),
|
|
1024
|
+
message: "An override must default-export defineTool({ ... }) or disableTool().",
|
|
1025
|
+
});
|
|
1026
|
+
continue;
|
|
1027
|
+
}
|
|
1028
|
+
const tool = compileTool(ctx, path, name, mod.default);
|
|
1029
|
+
if (tool !== undefined) {
|
|
1030
|
+
tools.push(tool);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
return { tools, disabled };
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
1036
|
+
/** Slots an agent has that an extension tree may not contribute (yet). */
|
|
1037
|
+
function warnUnsupportedExtensionSlots(ctx, root) {
|
|
1038
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1039
|
+
const unsupported = [
|
|
1040
|
+
["instructions.md", "instructions"],
|
|
1041
|
+
["connections", "connections"],
|
|
1042
|
+
["mcp-connections", "MCP connections"],
|
|
1043
|
+
["hooks", "hooks"],
|
|
1044
|
+
["subagents", "subagents"],
|
|
1045
|
+
["channels", "channels"],
|
|
1046
|
+
["schedules", "schedules"],
|
|
1047
|
+
["extensions", "nested extensions"],
|
|
1048
|
+
];
|
|
1049
|
+
for (const [slot, label] of unsupported) {
|
|
1050
|
+
const path = join(root, slot);
|
|
1051
|
+
if ((yield isDirectory(path)) || (yield isFile(path))) {
|
|
1052
|
+
ctx.diagnostics.push({
|
|
1053
|
+
severity: "warning",
|
|
1054
|
+
path: displayPath(ctx, path),
|
|
1055
|
+
message: `Extension ${label} are not supported yet; only tools/ and skills/ are mounted. Ignoring.`,
|
|
841
1056
|
});
|
|
842
1057
|
}
|
|
843
1058
|
}
|
|
844
|
-
return skills;
|
|
845
1059
|
});
|
|
846
1060
|
}
|
|
847
1061
|
function loadPackagedSkill(ctx, skillDir, name) {
|
|
@@ -855,7 +1069,7 @@ function loadPackagedSkill(ctx, skillDir, name) {
|
|
|
855
1069
|
});
|
|
856
1070
|
return undefined;
|
|
857
1071
|
}
|
|
858
|
-
if (!
|
|
1072
|
+
if (!validateName(ctx, "skill", name, skillDir)) {
|
|
859
1073
|
return undefined;
|
|
860
1074
|
}
|
|
861
1075
|
const { data, body } = parseFrontmatter(yield readFile(skillMdPath, "utf8"));
|
|
@@ -923,6 +1137,22 @@ function parseConnectionEffects(effects) {
|
|
|
923
1137
|
}
|
|
924
1138
|
return { ok: true, value: normalizeConnectionEffects(parsed) };
|
|
925
1139
|
}
|
|
1140
|
+
function parseConnectionTools(tools) {
|
|
1141
|
+
if (tools === undefined) {
|
|
1142
|
+
return { ok: true, value: undefined };
|
|
1143
|
+
}
|
|
1144
|
+
if (!Array.isArray(tools) || tools.length === 0) {
|
|
1145
|
+
return { ok: false };
|
|
1146
|
+
}
|
|
1147
|
+
if (tools.some((name) => typeof name !== "string")) {
|
|
1148
|
+
return { ok: false };
|
|
1149
|
+
}
|
|
1150
|
+
const normalized = normalizeConnectionTools(tools);
|
|
1151
|
+
if (normalized.length === 0) {
|
|
1152
|
+
return { ok: false };
|
|
1153
|
+
}
|
|
1154
|
+
return { ok: true, value: normalized };
|
|
1155
|
+
}
|
|
926
1156
|
function connectionHasSpawnOrRemote(connection) {
|
|
927
1157
|
if ("cursorAccount" in connection && connection.cursorAccount === true) {
|
|
928
1158
|
return true;
|
|
@@ -956,16 +1186,29 @@ function connectionTransport(connection) {
|
|
|
956
1186
|
}
|
|
957
1187
|
return undefined;
|
|
958
1188
|
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
1189
|
+
/**
|
|
1190
|
+
* Filenames become the names the model sees. `__` is reserved: it joins an
|
|
1191
|
+
* extension's namespace to its contribution (`crm__search`).
|
|
1192
|
+
*/
|
|
1193
|
+
function validateName(ctx, kind, name, entryPath) {
|
|
1194
|
+
const label = { skill: "Skill", tool: "Tool", extension: "Extension" }[kind];
|
|
1195
|
+
if (!NAME_PATTERN.test(name)) {
|
|
1196
|
+
ctx.diagnostics.push({
|
|
1197
|
+
severity: "error",
|
|
1198
|
+
path: displayPath(ctx, entryPath),
|
|
1199
|
+
message: `${label} name "${name}" must match ${NAME_PATTERN}.`,
|
|
1200
|
+
});
|
|
1201
|
+
return false;
|
|
962
1202
|
}
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
1203
|
+
if (name.includes("__")) {
|
|
1204
|
+
ctx.diagnostics.push({
|
|
1205
|
+
severity: "error",
|
|
1206
|
+
path: displayPath(ctx, entryPath),
|
|
1207
|
+
message: `${label} name "${name}" may not contain "__"; it is reserved for extension contributions (\`<ns>__<name>\`).`,
|
|
1208
|
+
});
|
|
1209
|
+
return false;
|
|
1210
|
+
}
|
|
1211
|
+
return true;
|
|
969
1212
|
}
|
|
970
1213
|
/**
|
|
971
1214
|
* Advertise the first non-empty, non-code-fence line of the body, with any
|
|
@@ -1024,7 +1267,7 @@ function resolveMcpConnectionsDir(ctx, agentDir) {
|
|
|
1024
1267
|
function loadHostConnections(ctx, agentDir, modelConnections) {
|
|
1025
1268
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1026
1269
|
const hostDir = join(agentDir, "host-connections");
|
|
1027
|
-
const loaded = yield loadConnections(ctx, hostDir);
|
|
1270
|
+
const loaded = yield loadConnections(ctx, hostDir, "host");
|
|
1028
1271
|
const modelNames = new Set(modelConnections.map((connection) => connection.name));
|
|
1029
1272
|
const hostConnections = [];
|
|
1030
1273
|
for (const connection of loaded) {
|
|
@@ -1057,8 +1300,8 @@ function loadHostConnections(ctx, agentDir, modelConnections) {
|
|
|
1057
1300
|
return hostConnections;
|
|
1058
1301
|
});
|
|
1059
1302
|
}
|
|
1060
|
-
function loadConnections(
|
|
1061
|
-
return __awaiter(this,
|
|
1303
|
+
function loadConnections(ctx_1, connectionsDir_1) {
|
|
1304
|
+
return __awaiter(this, arguments, void 0, function* (ctx, connectionsDir, role = "model") {
|
|
1062
1305
|
if (!(yield isDirectory(connectionsDir))) {
|
|
1063
1306
|
return [];
|
|
1064
1307
|
}
|
|
@@ -1143,6 +1386,48 @@ function loadConnections(ctx, connectionsDir) {
|
|
|
1143
1386
|
});
|
|
1144
1387
|
continue;
|
|
1145
1388
|
}
|
|
1389
|
+
const parsedTools = isInlineStdioConnection(connection)
|
|
1390
|
+
? { ok: true, value: undefined }
|
|
1391
|
+
: parseConnectionTools(connection.tools);
|
|
1392
|
+
if (!parsedTools.ok) {
|
|
1393
|
+
ctx.diagnostics.push({
|
|
1394
|
+
severity: "error",
|
|
1395
|
+
path: displayPath(ctx, entryPath),
|
|
1396
|
+
message: "MCP connection `tools` allowlist must be a non-empty array of tool names.",
|
|
1397
|
+
});
|
|
1398
|
+
continue;
|
|
1399
|
+
}
|
|
1400
|
+
if (isInlineStdioConnection(connection) &&
|
|
1401
|
+
connection.disallowedTools !== undefined) {
|
|
1402
|
+
ctx.diagnostics.push({
|
|
1403
|
+
severity: "error",
|
|
1404
|
+
path: displayPath(ctx, entryPath),
|
|
1405
|
+
message: "MCP connection `disallowedTools` is not supported on inline `tools` connections — author only the tools you want.",
|
|
1406
|
+
});
|
|
1407
|
+
continue;
|
|
1408
|
+
}
|
|
1409
|
+
const parsedDisallowed = isInlineStdioConnection(connection)
|
|
1410
|
+
? { ok: true, value: undefined }
|
|
1411
|
+
: parseConnectionTools(connection.disallowedTools);
|
|
1412
|
+
if (!parsedDisallowed.ok) {
|
|
1413
|
+
ctx.diagnostics.push({
|
|
1414
|
+
severity: "error",
|
|
1415
|
+
path: displayPath(ctx, entryPath),
|
|
1416
|
+
message: "MCP connection `disallowedTools` must be a non-empty array of tool names.",
|
|
1417
|
+
});
|
|
1418
|
+
continue;
|
|
1419
|
+
}
|
|
1420
|
+
if ((parsedTools.value !== undefined ||
|
|
1421
|
+
parsedDisallowed.value !== undefined) &&
|
|
1422
|
+
role === "model" &&
|
|
1423
|
+
connection.advertiseTools !== true) {
|
|
1424
|
+
ctx.diagnostics.push({
|
|
1425
|
+
severity: "error",
|
|
1426
|
+
path: displayPath(ctx, entryPath),
|
|
1427
|
+
message: "MCP connection `tools` / `disallowedTools` filter advertised tools; set `advertiseTools: true` or drop the name list. Put the connection in `agent/host-connections/` to restrict `host.mcp` only.",
|
|
1428
|
+
});
|
|
1429
|
+
continue;
|
|
1430
|
+
}
|
|
1146
1431
|
if (connection.advertiseTools === true &&
|
|
1147
1432
|
isInlineStdioConnection(connection)) {
|
|
1148
1433
|
ctx.diagnostics.push({
|
|
@@ -1225,6 +1510,8 @@ function loadConnections(ctx, connectionsDir) {
|
|
|
1225
1510
|
auth: connection.auth,
|
|
1226
1511
|
advertiseTools: connection.advertiseTools,
|
|
1227
1512
|
effects: parsedEffects.value,
|
|
1513
|
+
tools: parsedTools.value,
|
|
1514
|
+
disallowedTools: parsedDisallowed.value,
|
|
1228
1515
|
});
|
|
1229
1516
|
}
|
|
1230
1517
|
return connections;
|
|
@@ -1324,6 +1611,7 @@ function warnUnsupportedSubagentSlots(ctx, subagentDir) {
|
|
|
1324
1611
|
const unsupported = [
|
|
1325
1612
|
["tools", "tools"],
|
|
1326
1613
|
["skills", "skills"],
|
|
1614
|
+
["extensions", "extensions"],
|
|
1327
1615
|
["mcp-connections", "MCP connections"],
|
|
1328
1616
|
["host-connections", "host MCP connections"],
|
|
1329
1617
|
["connections", "MCP connections"],
|
|
@@ -1354,13 +1642,16 @@ function appendBuiltinTools(ctx, agentDir, tools, config) {
|
|
|
1354
1642
|
return;
|
|
1355
1643
|
}
|
|
1356
1644
|
const agentPath = displayPath(ctx, join(agentDir, "agent.ts"));
|
|
1357
|
-
const authored = new Set(tools.map((tool) => tool.name));
|
|
1358
1645
|
for (const tool of builtin) {
|
|
1359
|
-
|
|
1646
|
+
const existing = tools.find((t) => t.name === tool.name);
|
|
1647
|
+
if (existing !== undefined) {
|
|
1648
|
+
const owner = existing.extension === undefined
|
|
1649
|
+
? "Authored"
|
|
1650
|
+
: `Extension "${existing.extension}"`;
|
|
1360
1651
|
ctx.diagnostics.push({
|
|
1361
1652
|
severity: "warning",
|
|
1362
1653
|
path: agentPath,
|
|
1363
|
-
message:
|
|
1654
|
+
message: `${owner} tool "${tool.name}" shadows the built-in tool of the same name; the built-in is skipped.`,
|
|
1364
1655
|
});
|
|
1365
1656
|
continue;
|
|
1366
1657
|
}
|
|
@@ -1875,7 +2166,7 @@ function loadSeedFiles(ctx, agentDir) {
|
|
|
1875
2166
|
// ============================================================================
|
|
1876
2167
|
export function projectInfo(project) {
|
|
1877
2168
|
var _a, _b, _c, _d;
|
|
1878
|
-
var _e;
|
|
2169
|
+
var _e, _f;
|
|
1879
2170
|
const agent = project.agent;
|
|
1880
2171
|
const httpRoutes = [
|
|
1881
2172
|
{ method: "POST", path: "/v1/session", url: "/v1/session" },
|
|
@@ -1922,11 +2213,13 @@ export function projectInfo(project) {
|
|
|
1922
2213
|
})), skills: agent.skills.map((skill) => ({
|
|
1923
2214
|
name: skill.name,
|
|
1924
2215
|
description: skill.description,
|
|
1925
|
-
})), connections: agent.connections.map((connection) => { var _a; return ({
|
|
2216
|
+
})), extensions: (_e = agent.extensions) !== null && _e !== void 0 ? _e : [], connections: agent.connections.map((connection) => { var _a; return ({
|
|
1926
2217
|
name: connection.name,
|
|
1927
2218
|
transport: connectionTransportLabel(connection.transport),
|
|
1928
2219
|
advertiseTools: connection.advertiseTools,
|
|
1929
2220
|
effects: connection.effects,
|
|
2221
|
+
tools: connection.tools,
|
|
2222
|
+
disallowedTools: connection.disallowedTools,
|
|
1930
2223
|
cursorAccountServers: "cursorAccount" in connection.transport
|
|
1931
2224
|
? ((_a = connection.transport.servers) !== null && _a !== void 0 ? _a : "*")
|
|
1932
2225
|
: undefined,
|
|
@@ -1993,7 +2286,7 @@ export function projectInfo(project) {
|
|
|
1993
2286
|
: { name: project.storage.name }, artifacts: project.artifacts === undefined
|
|
1994
2287
|
? undefined
|
|
1995
2288
|
: {
|
|
1996
|
-
kinds: Object.keys((
|
|
2289
|
+
kinds: Object.keys((_f = project.artifacts.kinds) !== null && _f !== void 0 ? _f : {}),
|
|
1997
2290
|
agentTool: project.artifacts.agentTool === true,
|
|
1998
2291
|
max: resolveArtifactsMax(project.artifacts),
|
|
1999
2292
|
}, otel: project.otel === undefined
|
|
@@ -2040,6 +2333,7 @@ const DEFINE_HELPER_NAME = {
|
|
|
2040
2333
|
instructions: "defineInstructions",
|
|
2041
2334
|
tool: "defineTool",
|
|
2042
2335
|
skill: "defineSkill",
|
|
2336
|
+
extension: "defineExtension",
|
|
2043
2337
|
connection: "defineConnection",
|
|
2044
2338
|
channel: "defineChannel",
|
|
2045
2339
|
"http-channel": "httpChannel",
|
|
@@ -2057,6 +2351,7 @@ function warnUnknownSlots(ctx, agentDir) {
|
|
|
2057
2351
|
"instructions",
|
|
2058
2352
|
"tools",
|
|
2059
2353
|
"skills",
|
|
2354
|
+
"extensions",
|
|
2060
2355
|
"mcp-connections",
|
|
2061
2356
|
"host-connections",
|
|
2062
2357
|
// Legacy slot name; resolveMcpConnectionsDir warns and still loads it.
|