@frontmcp/sdk 1.8.1 → 1.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/common/metadata/front-mcp.metadata.d.ts +15 -0
- package/common/metadata/front-mcp.metadata.d.ts.map +1 -1
- package/common/metadata/tool-ui.metadata.d.ts +1 -0
- package/common/metadata/tool-ui.metadata.d.ts.map +1 -1
- package/completion/flows/complete.flow.d.ts +9 -2
- package/completion/flows/complete.flow.d.ts.map +1 -1
- package/context/frontmcp-context.d.ts +2 -0
- package/context/frontmcp-context.d.ts.map +1 -1
- package/esm/index.mjs +445 -250
- package/flows/resolved-entries.d.ts +9 -0
- package/flows/resolved-entries.d.ts.map +1 -0
- package/front-mcp/front-mcp.d.ts.map +1 -1
- package/index.d.ts +2 -2
- package/index.d.ts.map +1 -1
- package/index.js +441 -249
- package/package.json +10 -10
- package/plugin/plugin.registry.d.ts +2 -0
- package/plugin/plugin.registry.d.ts.map +1 -1
- package/prompt/flows/get-prompt.flow.d.ts.map +1 -1
- package/prompt/prompt.registry.d.ts +1 -0
- package/prompt/prompt.registry.d.ts.map +1 -1
- package/provider/provider.registry.d.ts +6 -1
- package/provider/provider.registry.d.ts.map +1 -1
- package/resource/flows/read-resource.flow.d.ts.map +1 -1
- package/resource/resource.registry.d.ts +1 -0
- package/resource/resource.registry.d.ts.map +1 -1
- package/scope/scope.instance.d.ts.map +1 -1
- package/skill/flows/http/skills-api.flow.d.ts +0 -6
- package/skill/flows/http/skills-api.flow.d.ts.map +1 -1
- package/skill/flows/load-skill.flow.d.ts +0 -7
- package/skill/flows/load-skill.flow.d.ts.map +1 -1
- package/skill/flows/search-skills.flow.d.ts +0 -13
- package/skill/flows/search-skills.flow.d.ts.map +1 -1
- package/skill/index.d.ts +2 -2
- package/skill/index.d.ts.map +1 -1
- package/skill/sep-2640/sep-2640.per-skill.d.ts.map +1 -1
- package/skill/skill-authorities.helper.d.ts +0 -20
- package/skill/skill-authorities.helper.d.ts.map +1 -1
- package/skill/skill-entry.resolver.d.ts +27 -0
- package/skill/skill-entry.resolver.d.ts.map +1 -0
- package/skill/skill-filter.helper.d.ts +15 -6
- package/skill/skill-filter.helper.d.ts.map +1 -1
- package/skill/skill-instructions.helper.d.ts +30 -0
- package/skill/skill-instructions.helper.d.ts.map +1 -1
- package/tool/flows/call-tool.flow.d.ts.map +1 -1
- package/tool/tool.registry.d.ts +1 -1
- package/tool/tool.registry.d.ts.map +1 -1
- package/tool/ui/ui-shared.d.ts +12 -1
- package/tool/ui/ui-shared.d.ts.map +1 -1
- package/transport/adapters/transport.local.adapter.d.ts +0 -9
- package/transport/adapters/transport.local.adapter.d.ts.map +1 -1
- package/transport/mcp-20260728/dispatcher.d.ts +3 -2
- package/transport/mcp-20260728/dispatcher.d.ts.map +1 -1
- package/transport/mcp-handlers/mcp-handlers.types.d.ts +9 -9
- package/transport/mcp-handlers/mcp-handlers.types.d.ts.map +1 -1
- package/transport/mcp-handlers/skills-list-request.handler.d.ts.map +1 -1
- package/transport/mcp-handlers/skills-load-request.handler.d.ts.map +1 -1
- package/transport/mcp-handlers/skills-search-request.handler.d.ts.map +1 -1
- package/utils/lineage.utils.d.ts +11 -0
- package/utils/lineage.utils.d.ts.map +1 -1
package/esm/index.mjs
CHANGED
|
@@ -3204,7 +3204,8 @@ var init_front_mcp_metadata = __esm({
|
|
|
3204
3204
|
extApps: extAppsOptionsSchema.optional(),
|
|
3205
3205
|
sqlite: sqliteOptionsSchema.optional(),
|
|
3206
3206
|
ui: z25.object({
|
|
3207
|
-
cdnOverrides: z25.record(z25.string(), z25.string()).optional()
|
|
3207
|
+
cdnOverrides: z25.record(z25.string(), z25.string()).optional(),
|
|
3208
|
+
escapeStringResults: z25.boolean().optional()
|
|
3208
3209
|
}).optional(),
|
|
3209
3210
|
/**
|
|
3210
3211
|
* Output-validation policy applied after entry-level Zod parsing succeeds.
|
|
@@ -9666,7 +9667,7 @@ function initializeRequestHandler({
|
|
|
9666
9667
|
const requestedVersion = request.params.protocolVersion;
|
|
9667
9668
|
const protocolVersion = SUPPORTED_PROTOCOL_VERSIONS.includes(requestedVersion) ? requestedVersion : LATEST_PROTOCOL_VERSION;
|
|
9668
9669
|
const configuredInfo = scope.metadata?.info ?? { name: "FrontMcpServer", version: "0.0.1" };
|
|
9669
|
-
const composed = composeInstructions?.();
|
|
9670
|
+
const composed = await composeInstructions?.(ctx);
|
|
9670
9671
|
const instructions = composed !== void 0 ? composed : serverOptions.instructions;
|
|
9671
9672
|
const result = {
|
|
9672
9673
|
capabilities: serverOptions.capabilities ?? {},
|
|
@@ -9972,31 +9973,49 @@ async function filterSkillsByAuthorities(scope, skills, authInfo) {
|
|
|
9972
9973
|
);
|
|
9973
9974
|
return skills.filter((_, i) => grants[i]);
|
|
9974
9975
|
}
|
|
9975
|
-
async function filterSkillMetadataByAuthorities(scope, registry, results, authInfo) {
|
|
9976
|
-
const engine = scope.authoritiesEngine;
|
|
9977
|
-
const ctxBuilder = scope.authoritiesContextBuilder;
|
|
9978
|
-
if (!engine || !ctxBuilder) return [...results];
|
|
9979
|
-
const normalized = normalizeAuthInfoForAuthorities(authInfo);
|
|
9980
|
-
const grants = await Promise.all(
|
|
9981
|
-
results.map(async (r) => {
|
|
9982
|
-
const id = r.metadata.id ?? r.metadata.name;
|
|
9983
|
-
const entry = registry.findByName(id) ?? registry.getSkills(true).find((s) => (s.metadata.id ?? s.name) === id || s.metadata.name === id);
|
|
9984
|
-
if (!entry) return true;
|
|
9985
|
-
const authorities = getSkillAuthorities(entry);
|
|
9986
|
-
if (!authorities) return true;
|
|
9987
|
-
const evalCtx = ctxBuilder.build(normalized);
|
|
9988
|
-
const result = await engine.evaluate(authorities, evalCtx);
|
|
9989
|
-
return result.granted;
|
|
9990
|
-
})
|
|
9991
|
-
);
|
|
9992
|
-
return results.filter((_, i) => grants[i]);
|
|
9993
|
-
}
|
|
9994
9976
|
var init_skill_authorities_helper = __esm({
|
|
9995
9977
|
"libs/sdk/src/skill/skill-authorities.helper.ts"() {
|
|
9996
9978
|
"use strict";
|
|
9997
9979
|
}
|
|
9998
9980
|
});
|
|
9999
9981
|
|
|
9982
|
+
// libs/sdk/src/skill/skill-entry.resolver.ts
|
|
9983
|
+
function skillResultId(result) {
|
|
9984
|
+
return result.metadata.id ?? result.metadata.name;
|
|
9985
|
+
}
|
|
9986
|
+
function createSkillEntryResolver(registry) {
|
|
9987
|
+
let fallback;
|
|
9988
|
+
const fallbackEntry = (id) => {
|
|
9989
|
+
if (!fallback) {
|
|
9990
|
+
const skills = registry.getSkills(true);
|
|
9991
|
+
fallback = /* @__PURE__ */ new Map();
|
|
9992
|
+
for (const skill of skills) {
|
|
9993
|
+
const skillId = skill.metadata.id ?? skill.name;
|
|
9994
|
+
if (!fallback.has(skillId)) fallback.set(skillId, skill);
|
|
9995
|
+
}
|
|
9996
|
+
for (const skill of skills) {
|
|
9997
|
+
if (!fallback.has(skill.metadata.name)) fallback.set(skill.metadata.name, skill);
|
|
9998
|
+
}
|
|
9999
|
+
}
|
|
10000
|
+
return fallback.get(id);
|
|
10001
|
+
};
|
|
10002
|
+
const lookup = (id) => registry.findByName(id) ?? // Qualified names always carry an owner prefix, so plain ids skip that scan.
|
|
10003
|
+
(id.includes(":") ? registry.findByQualifiedName(id) : void 0) ?? fallbackEntry(id);
|
|
10004
|
+
return (...ids) => {
|
|
10005
|
+
for (const id of ids) {
|
|
10006
|
+
if (!id) continue;
|
|
10007
|
+
const entry = lookup(id);
|
|
10008
|
+
if (entry) return entry;
|
|
10009
|
+
}
|
|
10010
|
+
return void 0;
|
|
10011
|
+
};
|
|
10012
|
+
}
|
|
10013
|
+
var init_skill_entry_resolver = __esm({
|
|
10014
|
+
"libs/sdk/src/skill/skill-entry.resolver.ts"() {
|
|
10015
|
+
"use strict";
|
|
10016
|
+
}
|
|
10017
|
+
});
|
|
10018
|
+
|
|
10000
10019
|
// libs/sdk/src/skill/skill-filter.helper.ts
|
|
10001
10020
|
async function filterServableSkills(scope, skills, ctx) {
|
|
10002
10021
|
if (skills.length === 0) return [];
|
|
@@ -10008,21 +10027,22 @@ async function isSkillServable(scope, skill, ctx) {
|
|
|
10008
10027
|
const servable = await filterServableSkills(scope, [skill], ctx);
|
|
10009
10028
|
return servable.length === 1;
|
|
10010
10029
|
}
|
|
10011
|
-
async function
|
|
10012
|
-
const
|
|
10013
|
-
const
|
|
10014
|
-
const
|
|
10030
|
+
async function filterDiscoverableSkillResults(scope, registry, results, caller = {}) {
|
|
10031
|
+
const resolve = createSkillEntryResolver(registry);
|
|
10032
|
+
const entries = results.map((result) => resolve(skillResultId(result)));
|
|
10033
|
+
const registered = [...new Set(entries.filter((entry) => entry !== void 0))];
|
|
10034
|
+
const authorized = await filterSkillsByAuthorities(scope, registered, caller.authInfo ?? {});
|
|
10035
|
+
const servable = new Set(await filterServableSkills(scope, authorized, caller.ctx));
|
|
10015
10036
|
return results.filter((_, index) => {
|
|
10016
10037
|
const entry = entries[index];
|
|
10017
10038
|
return entry === void 0 || servable.has(entry);
|
|
10018
10039
|
});
|
|
10019
10040
|
}
|
|
10020
|
-
function findSkillEntry(registry, id) {
|
|
10021
|
-
return registry.findByName(id) ?? registry.getSkills(true).find((skill) => (skill.metadata.id ?? skill.name) === id || skill.metadata.name === id);
|
|
10022
|
-
}
|
|
10023
10041
|
var init_skill_filter_helper = __esm({
|
|
10024
10042
|
"libs/sdk/src/skill/skill-filter.helper.ts"() {
|
|
10025
10043
|
"use strict";
|
|
10044
|
+
init_skill_authorities_helper();
|
|
10045
|
+
init_skill_entry_resolver();
|
|
10026
10046
|
}
|
|
10027
10047
|
});
|
|
10028
10048
|
|
|
@@ -10052,8 +10072,7 @@ function skillsListRequestHandler({
|
|
|
10052
10072
|
});
|
|
10053
10073
|
const authInfo = ctx?.authInfo ?? {};
|
|
10054
10074
|
const wrapped = listResult.skills.map((metadata) => ({ metadata }));
|
|
10055
|
-
const
|
|
10056
|
-
const visible = await filterServableSkillResults(scope, skillRegistry, authVisible, ctx);
|
|
10075
|
+
const visible = await filterDiscoverableSkillResults(scope, skillRegistry, wrapped, { authInfo, ctx });
|
|
10057
10076
|
const removed = listResult.skills.length - visible.length;
|
|
10058
10077
|
const skills = visible.map(({ metadata: s }) => ({
|
|
10059
10078
|
id: s.id ?? s.name,
|
|
@@ -10077,7 +10096,6 @@ var init_skills_list_request_handler = __esm({
|
|
|
10077
10096
|
"libs/sdk/src/transport/mcp-handlers/skills-list-request.handler.ts"() {
|
|
10078
10097
|
"use strict";
|
|
10079
10098
|
init_errors();
|
|
10080
|
-
init_skill_authorities_helper();
|
|
10081
10099
|
init_skill_filter_helper();
|
|
10082
10100
|
init_skills_mcp_types();
|
|
10083
10101
|
}
|
|
@@ -10489,10 +10507,10 @@ async function loadInstructions(source, basePath) {
|
|
|
10489
10507
|
}
|
|
10490
10508
|
throw new InvalidInstructionSourceError();
|
|
10491
10509
|
}
|
|
10492
|
-
function buildSkillContent(metadata, instructions,
|
|
10510
|
+
function buildSkillContent(metadata, instructions, resolvedReferences2, resolvedExamples) {
|
|
10493
10511
|
let finalInstructions = instructions;
|
|
10494
|
-
if (
|
|
10495
|
-
finalInstructions += buildReferencesTable(
|
|
10512
|
+
if (resolvedReferences2 && resolvedReferences2.length > 0) {
|
|
10513
|
+
finalInstructions += buildReferencesTable(resolvedReferences2);
|
|
10496
10514
|
}
|
|
10497
10515
|
if (resolvedExamples && resolvedExamples.length > 0) {
|
|
10498
10516
|
finalInstructions += buildExamplesTable(resolvedExamples);
|
|
@@ -10510,7 +10528,7 @@ function buildSkillContent(metadata, instructions, resolvedReferences, resolvedE
|
|
|
10510
10528
|
specMetadata: metadata.specMetadata,
|
|
10511
10529
|
allowedTools: metadata.allowedTools,
|
|
10512
10530
|
resources: metadata.resources,
|
|
10513
|
-
resolvedReferences,
|
|
10531
|
+
resolvedReferences: resolvedReferences2,
|
|
10514
10532
|
resolvedExamples
|
|
10515
10533
|
};
|
|
10516
10534
|
}
|
|
@@ -10777,13 +10795,14 @@ function skillsLoadRequestHandler({
|
|
|
10777
10795
|
toolsByName.set(tool.name, tool);
|
|
10778
10796
|
}
|
|
10779
10797
|
}
|
|
10798
|
+
const resolveEntry = createSkillEntryResolver(skillRegistry);
|
|
10780
10799
|
for (const skillId of skillIds) {
|
|
10781
10800
|
const loadResult = await skillRegistry.loadSkill(skillId);
|
|
10782
10801
|
if (!loadResult) {
|
|
10783
10802
|
warnings.push(`Skill "${skillId}" not found`);
|
|
10784
10803
|
continue;
|
|
10785
10804
|
}
|
|
10786
|
-
const entry =
|
|
10805
|
+
const entry = resolveEntry(skillId, loadResult.skill.id);
|
|
10787
10806
|
if (entry) {
|
|
10788
10807
|
if (!await isSkillServable(scope, entry, ctx)) {
|
|
10789
10808
|
warnings.push(`Skill "${skillId}" not found`);
|
|
@@ -10862,6 +10881,7 @@ var init_skills_load_request_handler = __esm({
|
|
|
10862
10881
|
"use strict";
|
|
10863
10882
|
init_errors();
|
|
10864
10883
|
init_skill_authorities_helper();
|
|
10884
|
+
init_skill_entry_resolver();
|
|
10865
10885
|
init_skill_filter_helper();
|
|
10866
10886
|
init_skill_http_utils();
|
|
10867
10887
|
init_skill_utils();
|
|
@@ -10896,13 +10916,10 @@ function skillsSearchRequestHandler({
|
|
|
10896
10916
|
return visibility === "mcp" || visibility === "both";
|
|
10897
10917
|
});
|
|
10898
10918
|
const authInfo = ctx?.authInfo ?? {};
|
|
10899
|
-
const
|
|
10900
|
-
|
|
10901
|
-
|
|
10902
|
-
|
|
10903
|
-
authInfo
|
|
10904
|
-
);
|
|
10905
|
-
const servableResults = await filterServableSkillResults(scope, skillRegistry, authVisibleResults, ctx);
|
|
10919
|
+
const servableResults = await filterDiscoverableSkillResults(scope, skillRegistry, mcpVisibleResults, {
|
|
10920
|
+
authInfo,
|
|
10921
|
+
ctx
|
|
10922
|
+
});
|
|
10906
10923
|
const skills = servableResults.map((r) => {
|
|
10907
10924
|
const toolNames = extractToolNames(r.metadata);
|
|
10908
10925
|
return {
|
|
@@ -10936,7 +10953,6 @@ var init_skills_search_request_handler = __esm({
|
|
|
10936
10953
|
"use strict";
|
|
10937
10954
|
init_skill_metadata();
|
|
10938
10955
|
init_errors();
|
|
10939
|
-
init_skill_authorities_helper();
|
|
10940
10956
|
init_skill_filter_helper();
|
|
10941
10957
|
init_skills_mcp_types();
|
|
10942
10958
|
}
|
|
@@ -13123,6 +13139,15 @@ var init_metrics2 = __esm({
|
|
|
13123
13139
|
}
|
|
13124
13140
|
});
|
|
13125
13141
|
|
|
13142
|
+
// libs/sdk/src/transport/transport.types.ts
|
|
13143
|
+
var STATELESS_SESSION_ID;
|
|
13144
|
+
var init_transport_types = __esm({
|
|
13145
|
+
"libs/sdk/src/transport/transport.types.ts"() {
|
|
13146
|
+
"use strict";
|
|
13147
|
+
STATELESS_SESSION_ID = "__stateless__";
|
|
13148
|
+
}
|
|
13149
|
+
});
|
|
13150
|
+
|
|
13126
13151
|
// libs/sdk/src/context/trace-context.ts
|
|
13127
13152
|
import { randomUUID as randomUUID7 } from "@frontmcp/utils";
|
|
13128
13153
|
function parseTraceContext(headers) {
|
|
@@ -13238,6 +13263,7 @@ var init_frontmcp_context = __esm({
|
|
|
13238
13263
|
"libs/sdk/src/context/frontmcp-context.ts"() {
|
|
13239
13264
|
"use strict";
|
|
13240
13265
|
init_mcp_error();
|
|
13266
|
+
init_transport_types();
|
|
13241
13267
|
init_trace_context();
|
|
13242
13268
|
PRE_RESOLVED_ELICIT_KEY = /* @__PURE__ */ Symbol.for("frontmcp:pre-resolved-elicit");
|
|
13243
13269
|
MRTR_EXCHANGE_KEY = /* @__PURE__ */ Symbol.for("frontmcp:mrtr-exchange");
|
|
@@ -13339,6 +13365,12 @@ var init_frontmcp_context = __esm({
|
|
|
13339
13365
|
updateAuthInfo(authInfo) {
|
|
13340
13366
|
this._authInfo = { ...this._authInfo, ...authInfo };
|
|
13341
13367
|
}
|
|
13368
|
+
/** `sessionId` when the server verified it; undefined for stateless and per-request placeholder ids. */
|
|
13369
|
+
get verifiedSessionId() {
|
|
13370
|
+
if (this.sessionId === STATELESS_SESSION_ID) return void 0;
|
|
13371
|
+
const verified = this._authInfo.sessionId ?? this._authInfo.extra?.["sessionId"];
|
|
13372
|
+
return verified === this.sessionId ? this.sessionId : void 0;
|
|
13373
|
+
}
|
|
13342
13374
|
/**
|
|
13343
13375
|
* The client's self-reported identity, sent with this request (MCP 2026-07-28 `_meta`).
|
|
13344
13376
|
* Session-based clients report it once at initialize instead; see the notification service.
|
|
@@ -17496,9 +17528,24 @@ function appOwnerIdOf(lineage, owner) {
|
|
|
17496
17528
|
const owners = owner ? [...lineage, owner] : lineage;
|
|
17497
17529
|
return owners.find((candidate) => candidate.kind === "app")?.id;
|
|
17498
17530
|
}
|
|
17531
|
+
var EntryLineageIndex;
|
|
17499
17532
|
var init_lineage_utils = __esm({
|
|
17500
17533
|
"libs/sdk/src/utils/lineage.utils.ts"() {
|
|
17501
17534
|
"use strict";
|
|
17535
|
+
EntryLineageIndex = class {
|
|
17536
|
+
lineages = /* @__PURE__ */ new Map();
|
|
17537
|
+
/** Replace the index with these rows; an entry held by several rows keeps the first row's lineage. */
|
|
17538
|
+
rebuild(rows) {
|
|
17539
|
+
this.lineages.clear();
|
|
17540
|
+
for (const row of rows) {
|
|
17541
|
+
if (!this.lineages.has(row.instance)) this.lineages.set(row.instance, row.lineage);
|
|
17542
|
+
}
|
|
17543
|
+
}
|
|
17544
|
+
/** Owner lineage (root → leaf) of an entry, or undefined when no row holds it. */
|
|
17545
|
+
lineageOf(entry) {
|
|
17546
|
+
return this.lineages.get(entry);
|
|
17547
|
+
}
|
|
17548
|
+
};
|
|
17502
17549
|
}
|
|
17503
17550
|
});
|
|
17504
17551
|
|
|
@@ -17531,6 +17578,28 @@ var init_remote_capabilities_utils = __esm({
|
|
|
17531
17578
|
}
|
|
17532
17579
|
});
|
|
17533
17580
|
|
|
17581
|
+
// libs/sdk/src/flows/resolved-entries.ts
|
|
17582
|
+
var ResolvedEntries;
|
|
17583
|
+
var init_resolved_entries = __esm({
|
|
17584
|
+
"libs/sdk/src/flows/resolved-entries.ts"() {
|
|
17585
|
+
"use strict";
|
|
17586
|
+
ResolvedEntries = class {
|
|
17587
|
+
byInput = /* @__PURE__ */ new WeakMap();
|
|
17588
|
+
/** Keep the entry resolved for this run's raw input and lookup key. */
|
|
17589
|
+
remember(rawInput, key, entry) {
|
|
17590
|
+
if (typeof rawInput === "object" && rawInput !== null) this.byInput.set(rawInput, { key, entry });
|
|
17591
|
+
}
|
|
17592
|
+
/** The entry kept for this run when it was resolved from the same key; undefined otherwise. */
|
|
17593
|
+
take(rawInput, key) {
|
|
17594
|
+
if (typeof rawInput !== "object" || rawInput === null) return void 0;
|
|
17595
|
+
const resolved = this.byInput.get(rawInput);
|
|
17596
|
+
this.byInput.delete(rawInput);
|
|
17597
|
+
return resolved?.key === key ? resolved.entry : void 0;
|
|
17598
|
+
}
|
|
17599
|
+
};
|
|
17600
|
+
}
|
|
17601
|
+
});
|
|
17602
|
+
|
|
17534
17603
|
// libs/sdk/src/provider/flow-context-providers.ts
|
|
17535
17604
|
var FlowContextProviders;
|
|
17536
17605
|
var init_flow_context_providers = __esm({
|
|
@@ -17569,13 +17638,14 @@ var init_flow_context_providers = __esm({
|
|
|
17569
17638
|
import { AuthorityDeniedError as AuthorityDeniedError3, resolveRequiredScopes as resolveRequiredScopes2 } from "@frontmcp/auth";
|
|
17570
17639
|
import { z as z49 } from "@frontmcp/lazy-zod";
|
|
17571
17640
|
import { GetPromptRequestSchema as GetPromptRequestSchema2, GetPromptResultSchema } from "@frontmcp/protocol";
|
|
17572
|
-
var inputSchema5, outputSchema5, stateSchema5, plan5, name5, Stage5, GetPromptFlow;
|
|
17641
|
+
var inputSchema5, outputSchema5, stateSchema5, plan5, name5, Stage5, resolvedPrompts, GetPromptFlow;
|
|
17573
17642
|
var init_get_prompt_flow = __esm({
|
|
17574
17643
|
"libs/sdk/src/prompt/flows/get-prompt.flow.ts"() {
|
|
17575
17644
|
"use strict";
|
|
17576
17645
|
init_remote_capabilities_utils();
|
|
17577
17646
|
init_common();
|
|
17578
17647
|
init_errors();
|
|
17648
|
+
init_resolved_entries();
|
|
17579
17649
|
init_hooks_utils();
|
|
17580
17650
|
init_flow_context_providers();
|
|
17581
17651
|
init_lineage_utils();
|
|
@@ -17611,17 +17681,19 @@ var init_get_prompt_flow = __esm({
|
|
|
17611
17681
|
};
|
|
17612
17682
|
name5 = "prompts:get-prompt";
|
|
17613
17683
|
({ Stage: Stage5 } = FlowHooksOf(name5));
|
|
17684
|
+
resolvedPrompts = new ResolvedEntries();
|
|
17614
17685
|
GetPromptFlow = class extends FlowBase {
|
|
17615
17686
|
static async resolveHookOwnerId(rawInput, scope) {
|
|
17616
|
-
const
|
|
17617
|
-
if (
|
|
17618
|
-
|
|
17619
|
-
let prompt = findPrompt();
|
|
17687
|
+
const promptName = rawInput?.request?.params?.name;
|
|
17688
|
+
if (typeof promptName !== "string") return void 0;
|
|
17689
|
+
let prompt = scope.prompts.findByName(promptName);
|
|
17620
17690
|
if (!prompt) {
|
|
17621
17691
|
await loadRemoteAppCapabilities(scope);
|
|
17622
|
-
prompt =
|
|
17692
|
+
prompt = scope.prompts.findByName(promptName);
|
|
17623
17693
|
}
|
|
17624
|
-
|
|
17694
|
+
if (!prompt) return void 0;
|
|
17695
|
+
resolvedPrompts.remember(rawInput, promptName, prompt);
|
|
17696
|
+
return appOwnerIdOf(scope.prompts.lineageOf(prompt) ?? [], prompt.owner);
|
|
17625
17697
|
}
|
|
17626
17698
|
logger = this.scopeLogger.child("GetPromptFlow");
|
|
17627
17699
|
async parseInput() {
|
|
@@ -17685,7 +17757,7 @@ var init_get_prompt_flow = __esm({
|
|
|
17685
17757
|
this.logger.verbose("findPrompt:start");
|
|
17686
17758
|
const { name: name44 } = this.state.required.input;
|
|
17687
17759
|
this.logger.info(`findPrompt: looking for prompt with name "${name44}"`);
|
|
17688
|
-
const prompt = this.scope.prompts.findByName(name44);
|
|
17760
|
+
const prompt = resolvedPrompts.take(this.rawInput, name44) ?? this.scope.prompts.findByName(name44);
|
|
17689
17761
|
if (!prompt) {
|
|
17690
17762
|
this.logger.warn(`findPrompt: prompt "${name44}" not found`);
|
|
17691
17763
|
throw new PromptNotFoundError(name44);
|
|
@@ -17741,14 +17813,8 @@ var init_get_prompt_flow = __esm({
|
|
|
17741
17813
|
const parsedArgs = prompt.parseArguments(input.arguments);
|
|
17742
17814
|
this.state.set("parsedArgs", parsedArgs);
|
|
17743
17815
|
const sessionKey = authInfo?.sessionId ?? "anonymous";
|
|
17744
|
-
const promptViews = await prompt.providers.buildViews(sessionKey, new Map(this.deps));
|
|
17745
|
-
const
|
|
17746
|
-
for (const [token, instance] of promptViews.context) {
|
|
17747
|
-
if (!mergedContextDeps.has(token)) {
|
|
17748
|
-
mergedContextDeps.set(token, instance);
|
|
17749
|
-
}
|
|
17750
|
-
}
|
|
17751
|
-
const contextProviders = new FlowContextProviders(prompt.providers, mergedContextDeps);
|
|
17816
|
+
const promptViews = await prompt.providers.buildViews(sessionKey, new Map(this.deps), this.scope.providers);
|
|
17817
|
+
const contextProviders = new FlowContextProviders(prompt.providers, promptViews.context);
|
|
17752
17818
|
const context = prompt.create(parsedArgs, { ...ctx, contextProviders });
|
|
17753
17819
|
this.appendContextHooks(hooksBoundTo(this.scope.hooks.getClsHooks(prompt.record.provide), context));
|
|
17754
17820
|
context.mark("createPromptContext");
|
|
@@ -18369,6 +18435,8 @@ var init_prompt_registry = __esm({
|
|
|
18369
18435
|
// "ownerKey:name" -> row
|
|
18370
18436
|
byOwner = /* @__PURE__ */ new Map();
|
|
18371
18437
|
// ownerKey -> rows
|
|
18438
|
+
lineages = new EntryLineageIndex();
|
|
18439
|
+
// instance -> first row's lineage
|
|
18372
18440
|
// version + emitter
|
|
18373
18441
|
version = 0;
|
|
18374
18442
|
emitter = new PromptEmitter();
|
|
@@ -18552,7 +18620,7 @@ var init_prompt_registry = __esm({
|
|
|
18552
18620
|
}
|
|
18553
18621
|
/** Owner lineage (root → leaf) of a prompt this registry holds, or undefined when it holds none. */
|
|
18554
18622
|
lineageOf(entry) {
|
|
18555
|
-
return this.
|
|
18623
|
+
return this.lineages.lineageOf(entry);
|
|
18556
18624
|
}
|
|
18557
18625
|
/** List instances by owner path (e.g. "app:Portal/plugin:Okta") */
|
|
18558
18626
|
listByOwner(ownerPath) {
|
|
@@ -18565,6 +18633,7 @@ var init_prompt_registry = __esm({
|
|
|
18565
18633
|
this.byName.clear();
|
|
18566
18634
|
this.byOwnerAndName.clear();
|
|
18567
18635
|
this.byOwner.clear();
|
|
18636
|
+
this.lineages.rebuild(effective);
|
|
18568
18637
|
for (const r of effective) {
|
|
18569
18638
|
this.byQualifiedId.set(r.qualifiedId, r);
|
|
18570
18639
|
const listByName = this.byName.get(r.baseName) ?? [];
|
|
@@ -18830,7 +18899,11 @@ var init_resource_record = __esm({
|
|
|
18830
18899
|
});
|
|
18831
18900
|
|
|
18832
18901
|
// libs/sdk/src/tool/ui/ui-shared.ts
|
|
18833
|
-
import {
|
|
18902
|
+
import {
|
|
18903
|
+
MCP_APPS_MIME_TYPE,
|
|
18904
|
+
renderToolTemplate,
|
|
18905
|
+
detectUIType as uipackDetectUIType
|
|
18906
|
+
} from "@frontmcp/uipack/adapters";
|
|
18834
18907
|
function extractSizing(uiConfig) {
|
|
18835
18908
|
if (!uiConfig) return void 0;
|
|
18836
18909
|
const sizing = {};
|
|
@@ -18891,8 +18964,18 @@ var init_ui_shared = __esm({
|
|
|
18891
18964
|
manifests = /* @__PURE__ */ new Map();
|
|
18892
18965
|
resourceMeta = /* @__PURE__ */ new Map();
|
|
18893
18966
|
resolver;
|
|
18894
|
-
|
|
18967
|
+
options;
|
|
18968
|
+
constructor(resolver, options = {}) {
|
|
18895
18969
|
this.resolver = resolver;
|
|
18970
|
+
this.options = options;
|
|
18971
|
+
}
|
|
18972
|
+
/** Tool-level `ui.escapeStringResults` wins over the server-wide default. */
|
|
18973
|
+
stringResultOptions(uiConfig) {
|
|
18974
|
+
const toolSetting = uiConfig?.["escapeStringResults"];
|
|
18975
|
+
return {
|
|
18976
|
+
escapeStringResults: typeof toolSetting === "boolean" ? toolSetting : this.options.escapeStringResults,
|
|
18977
|
+
logger: this.options.logger
|
|
18978
|
+
};
|
|
18896
18979
|
}
|
|
18897
18980
|
getStaticWidget(name44) {
|
|
18898
18981
|
return this.widgets.get(name44);
|
|
@@ -18931,7 +19014,8 @@ var init_ui_shared = __esm({
|
|
|
18931
19014
|
template,
|
|
18932
19015
|
resolver: this.resolver,
|
|
18933
19016
|
resourceMode,
|
|
18934
|
-
sizing: extractSizing(uiConfig)
|
|
19017
|
+
sizing: extractSizing(uiConfig),
|
|
19018
|
+
...this.stringResultOptions(uiConfig)
|
|
18935
19019
|
});
|
|
18936
19020
|
this.widgets.set(toolName, result.html);
|
|
18937
19021
|
this.manifests.set(toolName, {
|
|
@@ -19008,7 +19092,8 @@ var init_ui_shared = __esm({
|
|
|
19008
19092
|
platformType,
|
|
19009
19093
|
resolver: this.resolver,
|
|
19010
19094
|
resourceMode,
|
|
19011
|
-
sizing: extractSizing(uiConfig)
|
|
19095
|
+
sizing: extractSizing(uiConfig),
|
|
19096
|
+
...this.stringResultOptions(uiConfig)
|
|
19012
19097
|
});
|
|
19013
19098
|
return { meta: result.meta };
|
|
19014
19099
|
}
|
|
@@ -19268,13 +19353,14 @@ import { AuthorityDeniedError as AuthorityDeniedError4, resolveRequiredScopes as
|
|
|
19268
19353
|
import { z as z51 } from "@frontmcp/lazy-zod";
|
|
19269
19354
|
import { ReadResourceRequestSchema as ReadResourceRequestSchema2, ReadResourceResultSchema } from "@frontmcp/protocol";
|
|
19270
19355
|
import { randomBytes as randomBytes2 } from "@frontmcp/utils";
|
|
19271
|
-
var inputSchema7, outputSchema7, stateSchema7, plan7, name7, Stage7, ReadResourceFlow;
|
|
19356
|
+
var inputSchema7, outputSchema7, stateSchema7, plan7, name7, Stage7, resolvedResources, ReadResourceFlow;
|
|
19272
19357
|
var init_read_resource_flow = __esm({
|
|
19273
19358
|
"libs/sdk/src/resource/flows/read-resource.flow.ts"() {
|
|
19274
19359
|
"use strict";
|
|
19275
19360
|
init_remote_capabilities_utils();
|
|
19276
19361
|
init_common();
|
|
19277
19362
|
init_errors();
|
|
19363
|
+
init_resolved_entries();
|
|
19278
19364
|
init_hooks_utils();
|
|
19279
19365
|
init_flow_context_providers();
|
|
19280
19366
|
init_ui();
|
|
@@ -19316,17 +19402,19 @@ var init_read_resource_flow = __esm({
|
|
|
19316
19402
|
};
|
|
19317
19403
|
name7 = "resources:read-resource";
|
|
19318
19404
|
({ Stage: Stage7 } = FlowHooksOf(name7));
|
|
19405
|
+
resolvedResources = new ResolvedEntries();
|
|
19319
19406
|
ReadResourceFlow = class extends FlowBase {
|
|
19320
19407
|
static async resolveHookOwnerId(rawInput, scope) {
|
|
19321
|
-
const
|
|
19322
|
-
if (
|
|
19323
|
-
|
|
19324
|
-
|
|
19325
|
-
if (!resource) {
|
|
19408
|
+
const uri = rawInput?.request?.params?.uri;
|
|
19409
|
+
if (typeof uri !== "string") return void 0;
|
|
19410
|
+
let match = scope.resources.findResourceForUri(uri);
|
|
19411
|
+
if (!match) {
|
|
19326
19412
|
await loadRemoteAppCapabilities(scope);
|
|
19327
|
-
|
|
19413
|
+
match = scope.resources.findResourceForUri(uri);
|
|
19328
19414
|
}
|
|
19329
|
-
|
|
19415
|
+
if (!match) return void 0;
|
|
19416
|
+
resolvedResources.remember(rawInput, uri, match);
|
|
19417
|
+
return appOwnerIdOf(scope.resources.lineageOf(match.instance) ?? [], match.instance.owner);
|
|
19330
19418
|
}
|
|
19331
19419
|
logger = this.scopeLogger.child("ReadResourceFlow");
|
|
19332
19420
|
async parseInput() {
|
|
@@ -19411,7 +19499,7 @@ var init_read_resource_flow = __esm({
|
|
|
19411
19499
|
return;
|
|
19412
19500
|
}
|
|
19413
19501
|
}
|
|
19414
|
-
const match = this.scope.resources.findResourceForUri(uri);
|
|
19502
|
+
const match = resolvedResources.take(this.rawInput, uri) ?? this.scope.resources.findResourceForUri(uri);
|
|
19415
19503
|
if (!match) {
|
|
19416
19504
|
this.logger.warn(`findResource: resource for URI "${uri}" not found`);
|
|
19417
19505
|
throw new ResourceNotFoundError(uri);
|
|
@@ -19471,14 +19559,8 @@ var init_read_resource_flow = __esm({
|
|
|
19471
19559
|
const { resource, input, params } = this.state.required;
|
|
19472
19560
|
try {
|
|
19473
19561
|
const sessionKey = this.state.sessionId ?? ctx.authInfo?.sessionId ?? `req-${Date.now()}-${Buffer.from(randomBytes2(16)).toString("hex")}`;
|
|
19474
|
-
const resourceViews = await resource.providers.buildViews(sessionKey, new Map(this.deps));
|
|
19475
|
-
const
|
|
19476
|
-
for (const [token, instance] of resourceViews.context) {
|
|
19477
|
-
if (!mergedContextDeps.has(token)) {
|
|
19478
|
-
mergedContextDeps.set(token, instance);
|
|
19479
|
-
}
|
|
19480
|
-
}
|
|
19481
|
-
const contextProviders = new FlowContextProviders(resource.providers, mergedContextDeps);
|
|
19562
|
+
const resourceViews = await resource.providers.buildViews(sessionKey, new Map(this.deps), this.scope.providers);
|
|
19563
|
+
const contextProviders = new FlowContextProviders(resource.providers, resourceViews.context);
|
|
19482
19564
|
const context = resource.create(input.uri, params, { ...ctx, contextProviders });
|
|
19483
19565
|
this.appendContextHooks(hooksBoundTo(this.scope.hooks.getClsHooks(resource.record.provide), context));
|
|
19484
19566
|
context.mark("createResourceContext");
|
|
@@ -20727,6 +20809,8 @@ var init_resource_registry = __esm({
|
|
|
20727
20809
|
// "ownerKey:name" -> row
|
|
20728
20810
|
byOwner = /* @__PURE__ */ new Map();
|
|
20729
20811
|
// ownerKey -> rows
|
|
20812
|
+
lineages = new EntryLineageIndex();
|
|
20813
|
+
// instance -> first row's lineage
|
|
20730
20814
|
// version + emitter
|
|
20731
20815
|
version = 0;
|
|
20732
20816
|
emitter = new ResourceEmitter();
|
|
@@ -20939,7 +21023,7 @@ var init_resource_registry = __esm({
|
|
|
20939
21023
|
}
|
|
20940
21024
|
/** Owner lineage (root → leaf) of a resource this registry holds, or undefined when it holds none. */
|
|
20941
21025
|
lineageOf(entry) {
|
|
20942
|
-
return this.
|
|
21026
|
+
return this.lineages.lineageOf(entry);
|
|
20943
21027
|
}
|
|
20944
21028
|
/** List instances by owner path (e.g. "app:Portal/plugin:Okta") */
|
|
20945
21029
|
listByOwner(ownerPath) {
|
|
@@ -20954,6 +21038,7 @@ var init_resource_registry = __esm({
|
|
|
20954
21038
|
this.byUriTemplate.clear();
|
|
20955
21039
|
this.byOwnerAndName.clear();
|
|
20956
21040
|
this.byOwner.clear();
|
|
21041
|
+
this.lineages.rebuild(effective);
|
|
20957
21042
|
for (const r of effective) {
|
|
20958
21043
|
this.byQualifiedId.set(r.qualifiedId, r);
|
|
20959
21044
|
const listByName = this.byName.get(r.baseName) ?? [];
|
|
@@ -21561,7 +21646,7 @@ function linkedAbortController(signal) {
|
|
|
21561
21646
|
else signal?.addEventListener("abort", () => controller.abort(signal.reason), { once: true });
|
|
21562
21647
|
return controller;
|
|
21563
21648
|
}
|
|
21564
|
-
var inputSchema13, outputSchema12, stateSchema12, plan12, name12, Stage12, CallToolFlow;
|
|
21649
|
+
var inputSchema13, outputSchema12, stateSchema12, plan12, name12, Stage12, resolvedTools, CallToolFlow;
|
|
21565
21650
|
var init_call_tool_flow = __esm({
|
|
21566
21651
|
"libs/sdk/src/tool/flows/call-tool.flow.ts"() {
|
|
21567
21652
|
"use strict";
|
|
@@ -21572,6 +21657,7 @@ var init_call_tool_flow = __esm({
|
|
|
21572
21657
|
init_tool_metadata();
|
|
21573
21658
|
init_helpers();
|
|
21574
21659
|
init_errors();
|
|
21660
|
+
init_resolved_entries();
|
|
21575
21661
|
init_hooks_utils();
|
|
21576
21662
|
init_flow_context_providers();
|
|
21577
21663
|
init_task_id();
|
|
@@ -21646,6 +21732,7 @@ var init_call_tool_flow = __esm({
|
|
|
21646
21732
|
};
|
|
21647
21733
|
name12 = "tools:call-tool";
|
|
21648
21734
|
({ Stage: Stage12 } = FlowHooksOf(name12));
|
|
21735
|
+
resolvedTools = new ResolvedEntries();
|
|
21649
21736
|
CallToolFlow = class extends FlowBase {
|
|
21650
21737
|
static async resolveHookOwnerId(rawInput, scope) {
|
|
21651
21738
|
const toolName = rawInput?.request?.params?.name;
|
|
@@ -21655,7 +21742,9 @@ var init_call_tool_flow = __esm({
|
|
|
21655
21742
|
await loadRemoteAppCapabilities(scope);
|
|
21656
21743
|
tool = lookupTool(scope, toolName);
|
|
21657
21744
|
}
|
|
21658
|
-
|
|
21745
|
+
if (!tool) return void 0;
|
|
21746
|
+
resolvedTools.remember(rawInput, toolName, tool);
|
|
21747
|
+
return hookOwnerIdOf(scope.tools.lineageOf(tool) ?? [], tool.owner);
|
|
21659
21748
|
}
|
|
21660
21749
|
logger = this.scopeLogger.child("CallToolFlow");
|
|
21661
21750
|
async parseInput() {
|
|
@@ -21698,7 +21787,7 @@ var init_call_tool_flow = __esm({
|
|
|
21698
21787
|
async findTool() {
|
|
21699
21788
|
this.logger.verbose("findTool:start");
|
|
21700
21789
|
const { name: name44 } = this.state.required.input;
|
|
21701
|
-
const tool = lookupTool(this.scope, name44);
|
|
21790
|
+
const tool = resolvedTools.take(this.rawInput, name44) ?? lookupTool(this.scope, name44);
|
|
21702
21791
|
if (tool && tool.fullName !== name44 && tool.name !== name44) {
|
|
21703
21792
|
const [, alias] = toolNameCandidates(name44);
|
|
21704
21793
|
this.logger.warn(
|
|
@@ -22001,14 +22090,8 @@ var init_call_tool_flow = __esm({
|
|
|
22001
22090
|
const progressToken = this.state.progressToken;
|
|
22002
22091
|
try {
|
|
22003
22092
|
const sessionKey = authInfo?.sessionId ?? "anonymous";
|
|
22004
|
-
const toolViews = await tool.providers.buildViews(sessionKey, new Map(this.deps));
|
|
22005
|
-
const
|
|
22006
|
-
for (const [token, instance] of toolViews.context) {
|
|
22007
|
-
if (!mergedContextDeps.has(token)) {
|
|
22008
|
-
mergedContextDeps.set(token, instance);
|
|
22009
|
-
}
|
|
22010
|
-
}
|
|
22011
|
-
const contextProviders = new FlowContextProviders(tool.providers, mergedContextDeps);
|
|
22093
|
+
const toolViews = await tool.providers.buildViews(sessionKey, new Map(this.deps), this.scope.providers);
|
|
22094
|
+
const contextProviders = new FlowContextProviders(tool.providers, toolViews.context);
|
|
22012
22095
|
const executionAbort = linkedAbortController(ctx.signal);
|
|
22013
22096
|
this.state.set("executionAbort", executionAbort);
|
|
22014
22097
|
const context = tool.create(input.arguments, {
|
|
@@ -23079,8 +23162,8 @@ var init_tool_registry = __esm({
|
|
|
23079
23162
|
// "providerId:name" -> row (best-effort)
|
|
23080
23163
|
byOwner = /* @__PURE__ */ new Map();
|
|
23081
23164
|
// ownerKey -> rows
|
|
23082
|
-
|
|
23083
|
-
// instance -> first row
|
|
23165
|
+
lineages = new EntryLineageIndex();
|
|
23166
|
+
// instance -> first row's lineage
|
|
23084
23167
|
// version + emitter
|
|
23085
23168
|
version = 0;
|
|
23086
23169
|
emitter = new ToolEmitter();
|
|
@@ -23300,10 +23383,9 @@ var init_tool_registry = __esm({
|
|
|
23300
23383
|
this.byOwnerAndName.clear();
|
|
23301
23384
|
this.byProviderAndName.clear();
|
|
23302
23385
|
this.byOwner.clear();
|
|
23303
|
-
this.
|
|
23386
|
+
this.lineages.rebuild(effective);
|
|
23304
23387
|
for (const r of effective) {
|
|
23305
23388
|
this.byQualifiedId.set(r.qualifiedId, r);
|
|
23306
|
-
if (!this.byInstance.has(r.instance)) this.byInstance.set(r.instance, r);
|
|
23307
23389
|
const listByName = this.byName.get(r.baseName) ?? [];
|
|
23308
23390
|
listByName.push(r);
|
|
23309
23391
|
this.byName.set(r.baseName, listByName);
|
|
@@ -23325,7 +23407,7 @@ var init_tool_registry = __esm({
|
|
|
23325
23407
|
}
|
|
23326
23408
|
/** Owner lineage (root → leaf) of a tool this registry holds, or undefined when it holds none. */
|
|
23327
23409
|
lineageOf(entry) {
|
|
23328
|
-
return this.
|
|
23410
|
+
return this.lineages.lineageOf(entry);
|
|
23329
23411
|
}
|
|
23330
23412
|
/** List instances by owner path (e.g. "app:Portal/plugin:Okta") */
|
|
23331
23413
|
listByOwner(ownerPath) {
|
|
@@ -28315,6 +28397,10 @@ var init_plugin_registry = __esm({
|
|
|
28315
28397
|
const providers = new ProviderRegistry(rec.metadata.providers ?? [], this.providers);
|
|
28316
28398
|
await providers.ready;
|
|
28317
28399
|
const providerHooks = normalizeHooksFromProviders(providers);
|
|
28400
|
+
const { pluginInstance, dynamicProviders } = await this.instantiatePlugin(rec, deps);
|
|
28401
|
+
if (dynamicProviders) {
|
|
28402
|
+
await providers.addDynamicProviders(dynamicProviders);
|
|
28403
|
+
}
|
|
28318
28404
|
const pluginOwner = {
|
|
28319
28405
|
kind: "plugin",
|
|
28320
28406
|
id: rec.metadata.name,
|
|
@@ -28346,32 +28432,6 @@ var init_plugin_registry = __esm({
|
|
|
28346
28432
|
return providers.getProviderInfo(token2.provide);
|
|
28347
28433
|
});
|
|
28348
28434
|
this.providers.mergeFromRegistry(providers, exported);
|
|
28349
|
-
const depsTokens = [...deps];
|
|
28350
|
-
const depsInstances = await Promise.all(depsTokens.map((t) => this.providers.resolveBootstrapDep(t)));
|
|
28351
|
-
let pluginInstance;
|
|
28352
|
-
let optionDerivedProviders = [];
|
|
28353
|
-
if (rec.kind === "CLASS" /* CLASS */) {
|
|
28354
|
-
const klass = rec.useClass;
|
|
28355
|
-
pluginInstance = new klass(...depsInstances);
|
|
28356
|
-
} else if (rec.kind === "CLASS_TOKEN" /* CLASS_TOKEN */) {
|
|
28357
|
-
const klass = rec.provide;
|
|
28358
|
-
pluginInstance = new klass(...depsInstances);
|
|
28359
|
-
} else if (rec.kind === "FACTORY" /* FACTORY */) {
|
|
28360
|
-
const factoryDeps = [...rec.inject()];
|
|
28361
|
-
const args = [];
|
|
28362
|
-
for (const d of factoryDeps) args.push(await this.providers.resolveBootstrapDep(d));
|
|
28363
|
-
const produced = rec.useFactory(...args);
|
|
28364
|
-
if (isDynamicPluginClass(rec.provide) && !(produced instanceof rec.provide)) {
|
|
28365
|
-
pluginInstance = new rec.provide(produced);
|
|
28366
|
-
optionDerivedProviders = collectDynamicProviders(rec.provide, produced);
|
|
28367
|
-
} else {
|
|
28368
|
-
pluginInstance = produced;
|
|
28369
|
-
}
|
|
28370
|
-
} else if (rec.kind === "VALUE" /* VALUE */) {
|
|
28371
|
-
pluginInstance = rec.useValue;
|
|
28372
|
-
} else {
|
|
28373
|
-
throw new InvalidRegistryKindError("plugin", rec.kind);
|
|
28374
|
-
}
|
|
28375
28435
|
const pluginScope = rec.metadata.scope ?? "app";
|
|
28376
28436
|
if (this.scopeInfo?.isStandaloneApp && pluginScope === "server") {
|
|
28377
28437
|
throw new InvalidPluginScopeError(
|
|
@@ -28405,9 +28465,7 @@ var init_plugin_registry = __esm({
|
|
|
28405
28465
|
if (contextExtensions && contextExtensions.length > 0) {
|
|
28406
28466
|
installContextExtensions(rec.metadata.name, contextExtensions);
|
|
28407
28467
|
}
|
|
28408
|
-
const dynamicProviders = optionDerivedProviders.length > 0 ? dedupePluginProviders([...optionDerivedProviders, ...rec.providers ?? []]) : rec.providers;
|
|
28409
28468
|
if (dynamicProviders) {
|
|
28410
|
-
await providers.addDynamicProviders(dynamicProviders);
|
|
28411
28469
|
const normalized = dynamicProviders.map((p) => normalizeProvider(p));
|
|
28412
28470
|
const singletons = providers.getAllSingletons();
|
|
28413
28471
|
const exported2 = normalized.map((def) => ({
|
|
@@ -28430,6 +28488,39 @@ var init_plugin_registry = __esm({
|
|
|
28430
28488
|
);
|
|
28431
28489
|
}
|
|
28432
28490
|
}
|
|
28491
|
+
/** Builds the plugin instance and the providers it contributes; a factory's options exist only once it has run. */
|
|
28492
|
+
async instantiatePlugin(rec, deps) {
|
|
28493
|
+
const depsInstances = await Promise.all([...deps].map((t) => this.providers.resolveBootstrapDep(t)));
|
|
28494
|
+
switch (rec.kind) {
|
|
28495
|
+
case "CLASS" /* CLASS */:
|
|
28496
|
+
return {
|
|
28497
|
+
pluginInstance: new rec.useClass(...depsInstances),
|
|
28498
|
+
dynamicProviders: rec.providers
|
|
28499
|
+
};
|
|
28500
|
+
case "CLASS_TOKEN" /* CLASS_TOKEN */:
|
|
28501
|
+
return {
|
|
28502
|
+
pluginInstance: new rec.provide(...depsInstances),
|
|
28503
|
+
dynamicProviders: rec.providers
|
|
28504
|
+
};
|
|
28505
|
+
case "VALUE" /* VALUE */:
|
|
28506
|
+
return { pluginInstance: rec.useValue, dynamicProviders: rec.providers };
|
|
28507
|
+
case "FACTORY" /* FACTORY */: {
|
|
28508
|
+
const args = [];
|
|
28509
|
+
for (const d of rec.inject()) args.push(await this.providers.resolveBootstrapDep(d));
|
|
28510
|
+
const produced = rec.useFactory(...args);
|
|
28511
|
+
if (isDynamicPluginClass(rec.provide) && !(produced instanceof rec.provide)) {
|
|
28512
|
+
const optionDerived = collectDynamicProviders(rec.provide, produced);
|
|
28513
|
+
return {
|
|
28514
|
+
pluginInstance: new rec.provide(produced),
|
|
28515
|
+
dynamicProviders: optionDerived.length > 0 ? dedupePluginProviders([...optionDerived, ...rec.providers ?? []]) : rec.providers
|
|
28516
|
+
};
|
|
28517
|
+
}
|
|
28518
|
+
return { pluginInstance: produced, dynamicProviders: rec.providers };
|
|
28519
|
+
}
|
|
28520
|
+
default:
|
|
28521
|
+
throw new InvalidRegistryKindError("plugin", rec.kind);
|
|
28522
|
+
}
|
|
28523
|
+
}
|
|
28433
28524
|
};
|
|
28434
28525
|
}
|
|
28435
28526
|
});
|
|
@@ -31462,12 +31553,13 @@ async function dispatch20260728(options) {
|
|
|
31462
31553
|
return outcome.kind === "result" ? { kind: "result", result: decorate(outcome.result) } : outcome;
|
|
31463
31554
|
}
|
|
31464
31555
|
if (method === "server/discover") {
|
|
31556
|
+
const instructions = await composeInstructions?.({ authInfo });
|
|
31465
31557
|
return {
|
|
31466
31558
|
kind: "result",
|
|
31467
|
-
result: decorate(buildDiscoverResult(scope,
|
|
31559
|
+
result: decorate(buildDiscoverResult(scope, instructions))
|
|
31468
31560
|
};
|
|
31469
31561
|
}
|
|
31470
|
-
const serverOptions = buildScopedServerOptions(scope
|
|
31562
|
+
const serverOptions = buildScopedServerOptions(scope);
|
|
31471
31563
|
const handlers = createMcpHandlers({ scope, serverOptions, composeInstructions });
|
|
31472
31564
|
const handler = handlers.find((entry) => methodOfSchema(entry.requestSchema) === method);
|
|
31473
31565
|
if (!handler) {
|
|
@@ -43696,13 +43788,24 @@ function findCompletionReference(scope, ref) {
|
|
|
43696
43788
|
if (ref.type === "ref/prompt") return { prompt: scope.prompts.findByName(ref.name) };
|
|
43697
43789
|
return { resource: scope.resources.findResourceForUri(ref.uri)?.instance };
|
|
43698
43790
|
}
|
|
43699
|
-
|
|
43791
|
+
function referenceKeyOf(ref) {
|
|
43792
|
+
return ref.type === "ref/prompt" ? `prompt:${ref.name}` : `resource:${ref.uri}`;
|
|
43793
|
+
}
|
|
43794
|
+
function isWidgetToolNameCompletion(ref, argumentName) {
|
|
43795
|
+
return ref.type === "ref/resource" && ref.uri.startsWith("ui://widget/") && argumentName === "toolName";
|
|
43796
|
+
}
|
|
43797
|
+
function isListedTool(tool, listedNames) {
|
|
43798
|
+
const baseName = tool.metadata.id ?? tool.metadata.name;
|
|
43799
|
+
return listedNames.has(baseName) || listedNames.has(`${tool.owner.id}:${baseName}`);
|
|
43800
|
+
}
|
|
43801
|
+
var inputSchema29, outputSchema27, PromptRefSchema, ResourceRefSchema, CompletionRefSchema, stateSchema27, plan27, name28, Stage28, resolvedReferences, MAX_TOOL_LIST_PAGES, CompleteFlow;
|
|
43700
43802
|
var init_complete_flow = __esm({
|
|
43701
43803
|
"libs/sdk/src/completion/flows/complete.flow.ts"() {
|
|
43702
43804
|
"use strict";
|
|
43703
43805
|
init_remote_capabilities_utils();
|
|
43704
43806
|
init_common();
|
|
43705
43807
|
init_errors();
|
|
43808
|
+
init_resolved_entries();
|
|
43706
43809
|
init_ui();
|
|
43707
43810
|
init_lineage_utils();
|
|
43708
43811
|
inputSchema29 = z79.object({
|
|
@@ -43718,8 +43821,9 @@ var init_complete_flow = __esm({
|
|
|
43718
43821
|
type: z79.literal("ref/resource"),
|
|
43719
43822
|
uri: z79.string()
|
|
43720
43823
|
});
|
|
43824
|
+
CompletionRefSchema = z79.discriminatedUnion("type", [PromptRefSchema, ResourceRefSchema]);
|
|
43721
43825
|
stateSchema27 = z79.object({
|
|
43722
|
-
ref:
|
|
43826
|
+
ref: CompletionRefSchema,
|
|
43723
43827
|
argument: z79.object({
|
|
43724
43828
|
name: z79.string(),
|
|
43725
43829
|
value: z79.string()
|
|
@@ -43727,25 +43831,33 @@ var init_complete_flow = __esm({
|
|
|
43727
43831
|
// z.any() used because PromptEntry and ResourceEntry are complex abstract class types
|
|
43728
43832
|
prompt: z79.any().optional(),
|
|
43729
43833
|
resource: z79.any().optional(),
|
|
43834
|
+
widgetTools: z79.array(z79.instanceof(ToolEntry)).optional(),
|
|
43730
43835
|
output: outputSchema27
|
|
43731
43836
|
});
|
|
43732
43837
|
plan27 = {
|
|
43733
|
-
pre: ["parseInput", "findReference"],
|
|
43838
|
+
pre: ["parseInput", "findReference", "findWidgetTools"],
|
|
43734
43839
|
execute: ["complete"],
|
|
43735
43840
|
finalize: ["finalize"]
|
|
43736
43841
|
};
|
|
43737
43842
|
name28 = "completion:complete";
|
|
43738
43843
|
({ Stage: Stage28 } = FlowHooksOf(name28));
|
|
43844
|
+
resolvedReferences = new ResolvedEntries();
|
|
43845
|
+
MAX_TOOL_LIST_PAGES = 1e3;
|
|
43739
43846
|
CompleteFlow = class extends FlowBase {
|
|
43740
43847
|
static async resolveHookOwnerId(rawInput, scope) {
|
|
43741
|
-
const parsed =
|
|
43848
|
+
const parsed = CompletionRefSchema.safeParse(
|
|
43849
|
+
rawInput?.request?.params?.ref
|
|
43850
|
+
);
|
|
43742
43851
|
if (!parsed.success) return void 0;
|
|
43743
|
-
const
|
|
43744
|
-
let
|
|
43745
|
-
if (!prompt && !resource) {
|
|
43852
|
+
const ref = parsed.data;
|
|
43853
|
+
let reference = findCompletionReference(scope, ref);
|
|
43854
|
+
if (!reference.prompt && !reference.resource) {
|
|
43746
43855
|
await loadRemoteAppCapabilities(scope);
|
|
43747
|
-
|
|
43856
|
+
reference = findCompletionReference(scope, ref);
|
|
43748
43857
|
}
|
|
43858
|
+
const { prompt, resource } = reference;
|
|
43859
|
+
if (!prompt && !resource) return void 0;
|
|
43860
|
+
resolvedReferences.remember(rawInput, referenceKeyOf(ref), reference);
|
|
43749
43861
|
if (prompt) return appOwnerIdOf(scope.prompts.lineageOf(prompt) ?? [], prompt.owner);
|
|
43750
43862
|
return resource ? appOwnerIdOf(scope.resources.lineageOf(resource) ?? [], resource.owner) : void 0;
|
|
43751
43863
|
}
|
|
@@ -43782,10 +43894,43 @@ var init_complete_flow = __esm({
|
|
|
43782
43894
|
}
|
|
43783
43895
|
async findReference() {
|
|
43784
43896
|
this.logger.verbose("findReference:start");
|
|
43785
|
-
const {
|
|
43897
|
+
const { ref } = this.state.required;
|
|
43898
|
+
const { prompt, resource } = resolvedReferences.take(this.rawInput, referenceKeyOf(ref)) ?? findCompletionReference(this.scope, ref);
|
|
43786
43899
|
this.state.set({ prompt, resource });
|
|
43787
43900
|
this.logger.verbose("findReference:done");
|
|
43788
43901
|
}
|
|
43902
|
+
async findWidgetTools() {
|
|
43903
|
+
const { ref, argument } = this.state.required;
|
|
43904
|
+
if (!isWidgetToolNameCompletion(ref, argument.name)) return;
|
|
43905
|
+
this.logger.verbose("findWidgetTools:start");
|
|
43906
|
+
const uiTools = this.scope.tools.getTools().filter((tool) => hasUIConfig(tool.metadata));
|
|
43907
|
+
const listedNames = uiTools.length > 0 ? await this.listToolNames() : /* @__PURE__ */ new Set();
|
|
43908
|
+
this.state.set(
|
|
43909
|
+
"widgetTools",
|
|
43910
|
+
uiTools.filter((tool) => isListedTool(tool, listedNames))
|
|
43911
|
+
);
|
|
43912
|
+
this.logger.verbose("findWidgetTools:done");
|
|
43913
|
+
}
|
|
43914
|
+
/** Every tool name `tools/list` returns this caller, across all pages; none when listing fails. */
|
|
43915
|
+
async listToolNames() {
|
|
43916
|
+
const names = /* @__PURE__ */ new Set();
|
|
43917
|
+
let cursor;
|
|
43918
|
+
try {
|
|
43919
|
+
for (let page = 0; page < MAX_TOOL_LIST_PAGES; page++) {
|
|
43920
|
+
const { tools, nextCursor } = await this.scope.runFlowForOutput("tools:list-tools", {
|
|
43921
|
+
request: { method: "tools/list", params: cursor ? { cursor } : {} },
|
|
43922
|
+
ctx: this.input.ctx
|
|
43923
|
+
});
|
|
43924
|
+
for (const tool of tools) names.add(tool.name);
|
|
43925
|
+
if (!nextCursor) break;
|
|
43926
|
+
cursor = nextCursor;
|
|
43927
|
+
}
|
|
43928
|
+
} catch (e) {
|
|
43929
|
+
this.logger.warn(`findWidgetTools: tools/list failed, offering no tool names: ${e}`);
|
|
43930
|
+
names.clear();
|
|
43931
|
+
}
|
|
43932
|
+
return names;
|
|
43933
|
+
}
|
|
43789
43934
|
async complete() {
|
|
43790
43935
|
this.logger.verbose("complete:start");
|
|
43791
43936
|
const { ref, argument } = this.state.required;
|
|
@@ -43823,9 +43968,8 @@ var init_complete_flow = __esm({
|
|
|
43823
43968
|
this.logger.debug(
|
|
43824
43969
|
`complete: resource completion for URI "${uri}" argument "${argName}" with value "${argValue}"`
|
|
43825
43970
|
);
|
|
43826
|
-
if (
|
|
43827
|
-
const
|
|
43828
|
-
const toolNames = toolsWithUI.map((t) => t.metadata.id ?? t.metadata.name);
|
|
43971
|
+
if (isWidgetToolNameCompletion(ref, argName)) {
|
|
43972
|
+
const toolNames = (this.state.widgetTools ?? []).map((t) => t.metadata.id ?? t.metadata.name);
|
|
43829
43973
|
const prefix = argValue.toLowerCase();
|
|
43830
43974
|
values = toolNames.filter((name44) => name44.toLowerCase().startsWith(prefix));
|
|
43831
43975
|
total = values.length;
|
|
@@ -43869,6 +44013,9 @@ var init_complete_flow = __esm({
|
|
|
43869
44013
|
__decorateClass([
|
|
43870
44014
|
Stage28("findReference")
|
|
43871
44015
|
], CompleteFlow.prototype, "findReference", 1);
|
|
44016
|
+
__decorateClass([
|
|
44017
|
+
Stage28("findWidgetTools")
|
|
44018
|
+
], CompleteFlow.prototype, "findWidgetTools", 1);
|
|
43872
44019
|
__decorateClass([
|
|
43873
44020
|
Stage28("complete")
|
|
43874
44021
|
], CompleteFlow.prototype, "complete", 1);
|
|
@@ -49484,7 +49631,6 @@ var init_search_skills_flow = __esm({
|
|
|
49484
49631
|
"use strict";
|
|
49485
49632
|
init_common();
|
|
49486
49633
|
init_errors();
|
|
49487
|
-
init_skill_authorities_helper();
|
|
49488
49634
|
init_skill_filter_helper();
|
|
49489
49635
|
TELEMETRY_ACCESSOR_TOKEN = /* @__PURE__ */ Symbol.for("frontmcp:observability:telemetry-accessor");
|
|
49490
49636
|
inputSchema33 = z95.object({
|
|
@@ -49592,8 +49738,10 @@ var init_search_skills_flow = __esm({
|
|
|
49592
49738
|
const visibility = result.metadata.visibility ?? "both";
|
|
49593
49739
|
return visibility === "mcp" || visibility === "both";
|
|
49594
49740
|
});
|
|
49595
|
-
const
|
|
49596
|
-
const
|
|
49741
|
+
const registry = this.scope.skills;
|
|
49742
|
+
const ctx = this.rawInput["ctx"];
|
|
49743
|
+
const authInfo = ctx?.["authInfo"] ?? {};
|
|
49744
|
+
const servableResults = registry ? await filterDiscoverableSkillResults(this.scope, registry, mcpVisibleResults, { authInfo }) : mcpVisibleResults;
|
|
49597
49745
|
const skills = servableResults.map((result) => ({
|
|
49598
49746
|
id: result.metadata.id ?? result.metadata.name,
|
|
49599
49747
|
name: result.metadata.name,
|
|
@@ -49629,25 +49777,6 @@ var init_search_skills_flow = __esm({
|
|
|
49629
49777
|
this.respond(output);
|
|
49630
49778
|
this.logger.verbose("finalize:done");
|
|
49631
49779
|
}
|
|
49632
|
-
/**
|
|
49633
|
-
* Remove search results the caller is not authorized to discover.
|
|
49634
|
-
*
|
|
49635
|
-
* Search-result metadata is projected from `SkillContent` and does NOT carry
|
|
49636
|
-
* the `authorities` field, so we resolve the live skill entry (by id/name)
|
|
49637
|
-
* to read its declared authorities, then evaluate via the scope's engine.
|
|
49638
|
-
* No-op when no authorities engine is configured; results unchanged.
|
|
49639
|
-
*
|
|
49640
|
-
* Evaluated WITHOUT request input — `fromInput`/ReBAC-by-input policies can't
|
|
49641
|
-
* be evaluated at search time and will be treated as a denial. Use
|
|
49642
|
-
* role/permission/claims-based authorities for discoverable skills.
|
|
49643
|
-
*/
|
|
49644
|
-
async filterResultsByAuthorities(results) {
|
|
49645
|
-
const registry = this.scope.skills;
|
|
49646
|
-
if (!registry) return results;
|
|
49647
|
-
const ctx = this.rawInput["ctx"];
|
|
49648
|
-
const authInfo = ctx?.["authInfo"] ?? {};
|
|
49649
|
-
return filterSkillMetadataByAuthorities(this.scope, registry, results, authInfo);
|
|
49650
|
-
}
|
|
49651
49780
|
};
|
|
49652
49781
|
__decorateClass([
|
|
49653
49782
|
Stage32("parseInput")
|
|
@@ -49679,6 +49808,7 @@ var init_load_skill_flow = __esm({
|
|
|
49679
49808
|
init_common();
|
|
49680
49809
|
init_errors();
|
|
49681
49810
|
init_skill_authorities_helper();
|
|
49811
|
+
init_skill_entry_resolver();
|
|
49682
49812
|
init_skill_filter_helper();
|
|
49683
49813
|
init_skill_http_utils();
|
|
49684
49814
|
init_skill_utils();
|
|
@@ -49780,13 +49910,14 @@ var init_load_skill_flow = __esm({
|
|
|
49780
49910
|
const ctx = this.rawInput["ctx"];
|
|
49781
49911
|
const authInfo = ctx?.["authInfo"] ?? {};
|
|
49782
49912
|
const loadResults = [];
|
|
49913
|
+
const resolveEntry = createSkillEntryResolver(skillRegistry);
|
|
49783
49914
|
for (const skillId of skillIds) {
|
|
49784
49915
|
const result = await skillRegistry.loadSkill(skillId);
|
|
49785
49916
|
if (!result) {
|
|
49786
49917
|
warnings.push(`Skill "${skillId}" not found`);
|
|
49787
49918
|
continue;
|
|
49788
49919
|
}
|
|
49789
|
-
const entry =
|
|
49920
|
+
const entry = resolveEntry(skillId, result.skill.id);
|
|
49790
49921
|
if (entry) {
|
|
49791
49922
|
if (!await isSkillServable(this.scope, entry)) {
|
|
49792
49923
|
warnings.push(`Skill "${skillId}" not found`);
|
|
@@ -49799,17 +49930,6 @@ var init_load_skill_flow = __esm({
|
|
|
49799
49930
|
this.state.set({ loadResults, warnings });
|
|
49800
49931
|
this.logger.verbose("loadSkills:done", { loaded: loadResults.length, notFound: warnings.length });
|
|
49801
49932
|
}
|
|
49802
|
-
/**
|
|
49803
|
-
* Resolve the registered skill entry that backs a loaded skill, so its
|
|
49804
|
-
* `authorities` metadata can be evaluated. Matches by the requested id, the
|
|
49805
|
-
* resolved content id, and finally by display name — covering id/name/
|
|
49806
|
-
* qualified-name lookups the registry's `loadSkill` accepts.
|
|
49807
|
-
*/
|
|
49808
|
-
findSkillEntry(requestedId, resolvedId) {
|
|
49809
|
-
const registry = this.scope.skills;
|
|
49810
|
-
if (!registry) return void 0;
|
|
49811
|
-
return registry.findByName(requestedId) ?? registry.findByQualifiedName(requestedId) ?? registry.findByName(resolvedId) ?? registry.getSkills(true).find((s) => (s.metadata.id ?? s.name) === resolvedId || s.metadata.name === resolvedId);
|
|
49812
|
-
}
|
|
49813
49933
|
async activateSessions() {
|
|
49814
49934
|
this.logger.verbose("activateSessions:start");
|
|
49815
49935
|
const { activateSession, policyMode, loadResults } = this.state.required;
|
|
@@ -50805,6 +50925,7 @@ var init_skills_api_flow = __esm({
|
|
|
50805
50925
|
init_skills_http();
|
|
50806
50926
|
init_auth3();
|
|
50807
50927
|
init_skill_authorities_helper();
|
|
50928
|
+
init_skill_entry_resolver();
|
|
50808
50929
|
init_skill_filter_helper();
|
|
50809
50930
|
init_skill_http_utils();
|
|
50810
50931
|
init_skill_utils();
|
|
@@ -50989,7 +51110,7 @@ var init_skills_api_flow = __esm({
|
|
|
50989
51110
|
return;
|
|
50990
51111
|
}
|
|
50991
51112
|
const { skill, availableTools, missingTools, isComplete, warning } = loadResult;
|
|
50992
|
-
const skillEntry = skillRegistry
|
|
51113
|
+
const skillEntry = createSkillEntryResolver(skillRegistry)(skillId, skill.id);
|
|
50993
51114
|
if (skillEntry) {
|
|
50994
51115
|
if (!await isSkillServable(this.scope, skillEntry)) {
|
|
50995
51116
|
respondNotFound();
|
|
@@ -51082,8 +51203,9 @@ var init_skills_api_flow = __esm({
|
|
|
51082
51203
|
const visibility = r.metadata.visibility ?? "both";
|
|
51083
51204
|
return visibility !== "mcp";
|
|
51084
51205
|
});
|
|
51085
|
-
filteredResults = await this.
|
|
51086
|
-
|
|
51206
|
+
filteredResults = await filterDiscoverableSkillResults(this.scope, skillRegistry, filteredResults, {
|
|
51207
|
+
authInfo: this.httpAuthInfo()
|
|
51208
|
+
});
|
|
51087
51209
|
if (options.category) {
|
|
51088
51210
|
filteredResults = filteredResults.filter((r) => r.metadata.category === options.category);
|
|
51089
51211
|
}
|
|
@@ -51158,14 +51280,6 @@ var init_skills_api_flow = __esm({
|
|
|
51158
51280
|
const user = request?.authSession?.user;
|
|
51159
51281
|
return user ? { user } : {};
|
|
51160
51282
|
}
|
|
51161
|
-
/**
|
|
51162
|
-
* Filter search results (whose projected metadata lacks `authorities`) down
|
|
51163
|
-
* to skills the caller can discover, by resolving the live skill entry to
|
|
51164
|
-
* read its declared authorities. No-op when no engine is configured.
|
|
51165
|
-
*/
|
|
51166
|
-
async filterHttpResultsByAuthorities(results, skillRegistry) {
|
|
51167
|
-
return filterSkillMetadataByAuthorities(this.scope, skillRegistry, results, this.httpAuthInfo());
|
|
51168
|
-
}
|
|
51169
51283
|
async handleListSkills(options, skillRegistry) {
|
|
51170
51284
|
const allSkills = skillRegistry.getSkills({ includeHidden: false, visibility: "http" });
|
|
51171
51285
|
let filteredSkills = await filterServableSkills(
|
|
@@ -53944,6 +54058,7 @@ function buildPerSkillResourceRecord(scope, skill, opts = {}) {
|
|
|
53944
54058
|
}
|
|
53945
54059
|
async function registerPerSkillResources(options) {
|
|
53946
54060
|
const { scope, resourceRegistry, skills, logger, resolveLastModified } = options;
|
|
54061
|
+
const registered = [];
|
|
53947
54062
|
for (const skill of skills) {
|
|
53948
54063
|
let lastModified;
|
|
53949
54064
|
if (resolveLastModified) {
|
|
@@ -53958,6 +54073,11 @@ async function registerPerSkillResources(options) {
|
|
|
53958
54073
|
try {
|
|
53959
54074
|
const record = buildPerSkillResourceRecord(scope, skill, { lastModified });
|
|
53960
54075
|
resourceRegistry.registerDynamicResource(record);
|
|
54076
|
+
registered.push({
|
|
54077
|
+
skillPath: skill.getSkillPath(),
|
|
54078
|
+
metadata: record.metadata,
|
|
54079
|
+
extensionKeys: Object.keys(skillExtensionMetadata(skill))
|
|
54080
|
+
});
|
|
53961
54081
|
logger.verbose(`Registered SEP-2640 per-skill resource: ${record.metadata.uri}`);
|
|
53962
54082
|
} catch (err) {
|
|
53963
54083
|
logger.warn(
|
|
@@ -53965,6 +54085,32 @@ async function registerPerSkillResources(options) {
|
|
|
53965
54085
|
);
|
|
53966
54086
|
}
|
|
53967
54087
|
}
|
|
54088
|
+
if (registered.length > 0) {
|
|
54089
|
+
scope.skills?.subscribe({ immediate: false }, () => {
|
|
54090
|
+
const served = servedSkillsByPath(scope);
|
|
54091
|
+
for (const resource of registered) {
|
|
54092
|
+
const skill = served.get(resource.skillPath);
|
|
54093
|
+
if (skill) refreshFromSkill(resource, skill);
|
|
54094
|
+
}
|
|
54095
|
+
});
|
|
54096
|
+
}
|
|
54097
|
+
}
|
|
54098
|
+
function servedSkillsByPath(scope) {
|
|
54099
|
+
const served = /* @__PURE__ */ new Map();
|
|
54100
|
+
for (const skill of getSepVisibleSkills(scope)) {
|
|
54101
|
+
const skillPath = skill.getSkillPath();
|
|
54102
|
+
if (!served.has(skillPath)) served.set(skillPath, skill);
|
|
54103
|
+
}
|
|
54104
|
+
return served;
|
|
54105
|
+
}
|
|
54106
|
+
function refreshFromSkill(resource, skill) {
|
|
54107
|
+
const extensions = skillExtensionMetadata(skill);
|
|
54108
|
+
for (const key of resource.extensionKeys) {
|
|
54109
|
+
if (!(key in extensions)) Reflect.deleteProperty(resource.metadata, key);
|
|
54110
|
+
}
|
|
54111
|
+
Object.assign(resource.metadata, extensions);
|
|
54112
|
+
resource.metadata["description"] = skill.metadata.description;
|
|
54113
|
+
resource.extensionKeys = Object.keys(extensions);
|
|
53968
54114
|
}
|
|
53969
54115
|
var init_sep_2640_per_skill = __esm({
|
|
53970
54116
|
"libs/sdk/src/skill/sep-2640/sep-2640.per-skill.ts"() {
|
|
@@ -55273,15 +55419,6 @@ var init_handle_sse_flow = __esm({
|
|
|
55273
55419
|
}
|
|
55274
55420
|
});
|
|
55275
55421
|
|
|
55276
|
-
// libs/sdk/src/transport/transport.types.ts
|
|
55277
|
-
var STATELESS_SESSION_ID;
|
|
55278
|
-
var init_transport_types = __esm({
|
|
55279
|
-
"libs/sdk/src/transport/transport.types.ts"() {
|
|
55280
|
-
"use strict";
|
|
55281
|
-
STATELESS_SESSION_ID = "__stateless__";
|
|
55282
|
-
}
|
|
55283
|
-
});
|
|
55284
|
-
|
|
55285
55422
|
// libs/sdk/src/transport/flows/handle.stateless-http.flow.ts
|
|
55286
55423
|
import { z as z104 } from "@frontmcp/lazy-zod";
|
|
55287
55424
|
import { RequestSchema } from "@frontmcp/protocol";
|
|
@@ -56650,8 +56787,7 @@ function sanitizeName(raw) {
|
|
|
56650
56787
|
return s.length > MAX_SKILL_NAME_CHARS ? `${s.slice(0, MAX_SKILL_NAME_CHARS)}\u2026` : s;
|
|
56651
56788
|
}
|
|
56652
56789
|
function buildSkillsCatalogSummary(skillRegistry, options = {}) {
|
|
56653
|
-
|
|
56654
|
-
const skills = skillRegistry.getSkills({ visibility: "mcp" });
|
|
56790
|
+
const skills = options.skills ?? skillRegistry?.getSkills({ visibility: "mcp" }) ?? [];
|
|
56655
56791
|
if (skills.length === 0) return "";
|
|
56656
56792
|
const pointers = options.mcpResources === false ? METHOD_POINTERS : RESOURCE_POINTERS;
|
|
56657
56793
|
const lines = [pointers.header, ""];
|
|
@@ -56692,7 +56828,10 @@ function composeInitializeInstructions(options) {
|
|
|
56692
56828
|
if (policy === "off") {
|
|
56693
56829
|
return joinSections([user, channel2]);
|
|
56694
56830
|
}
|
|
56695
|
-
const catalog = buildSkillsCatalogSummary(options.skillRegistry, {
|
|
56831
|
+
const catalog = buildSkillsCatalogSummary(options.skillRegistry, {
|
|
56832
|
+
mcpResources: options.mcpResources,
|
|
56833
|
+
skills: options.skills
|
|
56834
|
+
});
|
|
56696
56835
|
if (policy === "prepend") {
|
|
56697
56836
|
return joinSections([catalog, channel2, user]);
|
|
56698
56837
|
}
|
|
@@ -56703,6 +56842,60 @@ function buildChannelInstructions(channels) {
|
|
|
56703
56842
|
const hasTwoWay = channels.getChannelInstances().some((ch) => ch.twoWay);
|
|
56704
56843
|
return hasTwoWay ? "Events arrive as <channel> tags. Reply with the channel-reply tool." : "Events arrive as <channel> tags.";
|
|
56705
56844
|
}
|
|
56845
|
+
async function composeCallerInstructions(scope, options = {}) {
|
|
56846
|
+
const skillsConfig = scope.metadata.skillsConfig;
|
|
56847
|
+
const composeOptions = {
|
|
56848
|
+
userInstructions: scope.metadata.instructions,
|
|
56849
|
+
channelInstructions: buildChannelInstructions(scope.channels),
|
|
56850
|
+
skillRegistry: scope.skills,
|
|
56851
|
+
policy: skillsConfig?.injectInstructions,
|
|
56852
|
+
mcpResources: skillsConfig?.mcpResources
|
|
56853
|
+
};
|
|
56854
|
+
const withUriHints = options.skillUriHints === true && skillUriHintsEnabled(scope);
|
|
56855
|
+
const listsSkills = withUriHints || includesSkillCatalog(composeOptions);
|
|
56856
|
+
let skills = [];
|
|
56857
|
+
if (listsSkills) {
|
|
56858
|
+
try {
|
|
56859
|
+
skills = await skillsVisibleTo(scope, options.ctx);
|
|
56860
|
+
} catch (error) {
|
|
56861
|
+
scope.logger.warn("initialize instructions: left the skills out, the skills:filter flow failed", {
|
|
56862
|
+
error: error instanceof Error ? error.message : String(error)
|
|
56863
|
+
});
|
|
56864
|
+
}
|
|
56865
|
+
}
|
|
56866
|
+
const composed = composeInitializeInstructions({ ...composeOptions, skills });
|
|
56867
|
+
const uriHints = withUriHints ? buildSkillUriHints(skills, scope.skills?.getSep2640InstructionUris?.() ?? []) : "";
|
|
56868
|
+
return [composed, uriHints].filter((section) => section.length > 0).join("\n\n---\n\n");
|
|
56869
|
+
}
|
|
56870
|
+
function buildSkillUriHints(skills, extraUris = []) {
|
|
56871
|
+
if (skills.length === 0) return "";
|
|
56872
|
+
const lines = ["Available skills (load via resources/read):"];
|
|
56873
|
+
for (const skill of skills) {
|
|
56874
|
+
lines.push(`- skill://${skill.getSkillPath()}/SKILL.md \u2014 ${skill.metadata.description}`);
|
|
56875
|
+
}
|
|
56876
|
+
for (const extra of extraUris) {
|
|
56877
|
+
lines.push(`- ${extra}`);
|
|
56878
|
+
}
|
|
56879
|
+
return lines.join("\n");
|
|
56880
|
+
}
|
|
56881
|
+
function skillUriHintsEnabled(scope) {
|
|
56882
|
+
const skillsConfig = scope.metadata.skillsConfig;
|
|
56883
|
+
if (!skillsConfig?.sep2640InInstructions || skillsConfig.mcpResources === false) return false;
|
|
56884
|
+
const serverInstructions = (scope.metadata.instructions ?? "").trim();
|
|
56885
|
+
return !(skillsConfig.injectInstructions === "replace" && serverInstructions.length > 0);
|
|
56886
|
+
}
|
|
56887
|
+
function includesSkillCatalog(options) {
|
|
56888
|
+
const policy = options.policy ?? DEFAULT_POLICY;
|
|
56889
|
+
if (policy === "off") return false;
|
|
56890
|
+
return !(policy === "replace" && (options.userInstructions ?? "").trim().length > 0);
|
|
56891
|
+
}
|
|
56892
|
+
async function skillsVisibleTo(scope, ctx) {
|
|
56893
|
+
const visible = scope.skills?.getSkills({ visibility: "mcp" }) ?? [];
|
|
56894
|
+
if (visible.length === 0) return [];
|
|
56895
|
+
const authInfo = ctx?.authInfo ?? {};
|
|
56896
|
+
const authorized = await filterSkillsByAuthorities(scope, visible, authInfo);
|
|
56897
|
+
return filterServableSkills(scope, authorized, ctx);
|
|
56898
|
+
}
|
|
56706
56899
|
function joinSections(sections) {
|
|
56707
56900
|
return sections.map((s) => (s ?? "").trim()).filter((s) => s.length > 0).join("\n\n---\n\n");
|
|
56708
56901
|
}
|
|
@@ -56711,6 +56904,8 @@ var init_skill_instructions_helper = __esm({
|
|
|
56711
56904
|
"libs/sdk/src/skill/skill-instructions.helper.ts"() {
|
|
56712
56905
|
"use strict";
|
|
56713
56906
|
init_sep_2640_constants();
|
|
56907
|
+
init_skill_authorities_helper();
|
|
56908
|
+
init_skill_filter_helper();
|
|
56714
56909
|
DEFAULT_POLICY = "append";
|
|
56715
56910
|
MAX_SKILL_CATALOG_CHARS = 16e3;
|
|
56716
56911
|
TRUNCATION_FOOTER_RESERVE = 160;
|
|
@@ -56843,18 +57038,8 @@ var init_transport_local_adapter = __esm({
|
|
|
56843
57038
|
const elicitationCapability = this.scope.metadata.elicitation?.enabled ? { elicitation: {} } : {};
|
|
56844
57039
|
const channelCapabilities = this.scope.channels?.getCapabilities() ?? {};
|
|
56845
57040
|
const skillsCapabilities = this.scope.skills?.getCapabilities() ?? {};
|
|
56846
|
-
const composeInstructions = () => {
|
|
56847
|
-
|
|
56848
|
-
userInstructions: this.scope.metadata.instructions,
|
|
56849
|
-
channelInstructions: buildChannelInstructions(this.scope.channels),
|
|
56850
|
-
skillRegistry: this.scope.skills,
|
|
56851
|
-
policy: this.scope.metadata.skillsConfig?.injectInstructions,
|
|
56852
|
-
mcpResources: this.scope.metadata.skillsConfig?.mcpResources
|
|
56853
|
-
});
|
|
56854
|
-
const sep2640Hints = this.buildSkillInstructionHints();
|
|
56855
|
-
return [composed, sep2640Hints].filter((s) => s.length > 0).join("\n\n---\n\n");
|
|
56856
|
-
};
|
|
56857
|
-
const instructions = composeInstructions();
|
|
57041
|
+
const composeInstructions = (caller) => composeCallerInstructions(this.scope, { ctx: caller, skillUriHints: true });
|
|
57042
|
+
const instructions = "";
|
|
56858
57043
|
const mergedCapabilities = mergeExperimental([
|
|
56859
57044
|
remoteCapabilities,
|
|
56860
57045
|
// Pre-advertise for remote apps (may be overwritten by local)
|
|
@@ -57104,34 +57289,6 @@ var init_transport_local_adapter = __esm({
|
|
|
57104
57289
|
const appObj = app;
|
|
57105
57290
|
return "urlType" in appObj && appObj["standalone"] !== true;
|
|
57106
57291
|
}
|
|
57107
|
-
/**
|
|
57108
|
-
* SEP-2640 §Discovery — opt-in `instructions` text listing each
|
|
57109
|
-
* MCP-visible skill's `skill://` URI. Returns an empty string unless
|
|
57110
|
-
* `skillsConfig.sep2640InInstructions` is true and the `skill://`
|
|
57111
|
-
* resources are served (`skillsConfig.mcpResources` is not false). Also
|
|
57112
|
-
* empty under `injectInstructions: 'replace'` with non-empty server
|
|
57113
|
-
* instructions, which must then be sent alone.
|
|
57114
|
-
*/
|
|
57115
|
-
buildSkillInstructionHints() {
|
|
57116
|
-
const skillRegistry = this.scope.skills;
|
|
57117
|
-
if (!skillRegistry?.hasAny()) return "";
|
|
57118
|
-
const skillsConfig = this.scope.metadata?.skillsConfig;
|
|
57119
|
-
if (!skillsConfig?.sep2640InInstructions || skillsConfig.mcpResources === false) return "";
|
|
57120
|
-
const serverInstructions = (this.scope.metadata.instructions ?? "").trim();
|
|
57121
|
-
if (skillsConfig.injectInstructions === "replace" && serverInstructions.length > 0) return "";
|
|
57122
|
-
const visible = skillRegistry.getSkills({ visibility: "mcp" });
|
|
57123
|
-
if (visible.length === 0) return "";
|
|
57124
|
-
const lines = ["Available skills (load via resources/read):"];
|
|
57125
|
-
for (const skill of visible) {
|
|
57126
|
-
const uri = `skill://${skill.getSkillPath()}/SKILL.md`;
|
|
57127
|
-
lines.push(`- ${uri} \u2014 ${skill.metadata.description}`);
|
|
57128
|
-
}
|
|
57129
|
-
const extras = skillRegistry.getSep2640InstructionUris?.() ?? [];
|
|
57130
|
-
for (const extra of extras) {
|
|
57131
|
-
lines.push(`- ${extra}`);
|
|
57132
|
-
}
|
|
57133
|
-
return lines.join("\n");
|
|
57134
|
-
}
|
|
57135
57292
|
/**
|
|
57136
57293
|
* Build capabilities that should be pre-advertised for remote apps.
|
|
57137
57294
|
* Remote apps load their tools/resources/prompts asynchronously after connection,
|
|
@@ -59782,7 +59939,10 @@ var init_scope_instance = __esm({
|
|
|
59782
59939
|
this.logger.verbose("Created UI resolver with CDN overrides", { overrides: Object.keys(cdnOverrides) });
|
|
59783
59940
|
}
|
|
59784
59941
|
}
|
|
59785
|
-
this.toolUIRegistry = new ToolUIRegistry(uiResolver
|
|
59942
|
+
this.toolUIRegistry = new ToolUIRegistry(uiResolver, {
|
|
59943
|
+
escapeStringResults: this.metadata.ui?.escapeStringResults,
|
|
59944
|
+
logger: this.logger
|
|
59945
|
+
});
|
|
59786
59946
|
if (!this.cliMode) {
|
|
59787
59947
|
await this.compileUIWidgets();
|
|
59788
59948
|
}
|
|
@@ -61283,26 +61443,37 @@ var init_provider_registry = __esm({
|
|
|
61283
61443
|
*
|
|
61284
61444
|
* @param sessionKey - Unique context/session identifier for CONTEXT-scoped providers
|
|
61285
61445
|
* @param contextProviders - Optional pre-built CONTEXT-scoped providers (e.g., FrontMcpContext)
|
|
61446
|
+
* @param contextSource - The ancestor registry whose views built `contextProviders`. Tokens this registry's
|
|
61447
|
+
* hierarchy defines below it are resolved from their own nearest definition instead of the pre-built instance,
|
|
61448
|
+
* so an app's plugin providers are not shadowed by the definition another app merged into the scope.
|
|
61286
61449
|
* @returns ProviderViews with global and context provider maps (session/request as aliases)
|
|
61287
61450
|
*/
|
|
61288
|
-
async buildViews(sessionKey, contextProviders) {
|
|
61451
|
+
async buildViews(sessionKey, contextProviders, contextSource) {
|
|
61289
61452
|
validateSessionId(sessionKey);
|
|
61290
61453
|
const global = this.getAllSingletons();
|
|
61291
61454
|
let sessionProviders;
|
|
61455
|
+
const ownDefs = (contextSource && this.defsBelow(contextSource)) ?? /* @__PURE__ */ new Map();
|
|
61292
61456
|
if (this.sessionCacheEnabled) {
|
|
61293
61457
|
let cached = this.sessionStores.get(sessionKey);
|
|
61294
61458
|
if (!cached) {
|
|
61295
|
-
cached = { providers: /* @__PURE__ */ new Map(), lastAccess: Date.now() };
|
|
61459
|
+
cached = { providers: /* @__PURE__ */ new Map(), bySource: /* @__PURE__ */ new Map(), lastAccess: Date.now() };
|
|
61296
61460
|
this.sessionStores.set(sessionKey, cached);
|
|
61297
61461
|
} else {
|
|
61298
61462
|
cached.lastAccess = Date.now();
|
|
61299
61463
|
}
|
|
61300
61464
|
sessionProviders = cached.providers;
|
|
61465
|
+
if (contextSource && ownDefs.size > 0) {
|
|
61466
|
+
sessionProviders = cached.bySource.get(contextSource);
|
|
61467
|
+
if (!sessionProviders) {
|
|
61468
|
+
sessionProviders = /* @__PURE__ */ new Map();
|
|
61469
|
+
cached.bySource.set(contextSource, sessionProviders);
|
|
61470
|
+
}
|
|
61471
|
+
}
|
|
61301
61472
|
}
|
|
61302
61473
|
const requestTokens = requestScopedTokens(contextProviders);
|
|
61303
61474
|
const contextStore = new Map(sessionProviders ?? []);
|
|
61304
61475
|
for (const [token, instance] of contextProviders ?? []) {
|
|
61305
|
-
contextStore.set(token, instance);
|
|
61476
|
+
if (!ownDefs.has(token)) contextStore.set(token, instance);
|
|
61306
61477
|
}
|
|
61307
61478
|
for (const token of this.order) {
|
|
61308
61479
|
const rec = this.defs.get(token);
|
|
@@ -61317,6 +61488,18 @@ var init_provider_registry = __esm({
|
|
|
61317
61488
|
if (contextStore.has(token)) continue;
|
|
61318
61489
|
await this.buildIntoStoreWithViews(token, rec, contextStore, sessionKey, contextStore, global);
|
|
61319
61490
|
}
|
|
61491
|
+
for (const [token, { registry, rec }] of ownDefs) {
|
|
61492
|
+
if (registry === this || contextStore.has(token)) continue;
|
|
61493
|
+
if (registry.getProviderScope(rec) !== ProviderScope8.CONTEXT) continue;
|
|
61494
|
+
await registry.buildIntoStoreWithViews(
|
|
61495
|
+
token,
|
|
61496
|
+
rec,
|
|
61497
|
+
contextStore,
|
|
61498
|
+
sessionKey,
|
|
61499
|
+
contextStore,
|
|
61500
|
+
registry.getAllSingletons()
|
|
61501
|
+
);
|
|
61502
|
+
}
|
|
61320
61503
|
if (sessionProviders) {
|
|
61321
61504
|
for (const [token, instance] of contextStore) {
|
|
61322
61505
|
if (!sessionProviders.has(token) && !this.dependsOnAny(token, requestTokens)) {
|
|
@@ -61329,6 +61512,14 @@ var init_provider_registry = __esm({
|
|
|
61329
61512
|
context: contextStore
|
|
61330
61513
|
};
|
|
61331
61514
|
}
|
|
61515
|
+
/** Nearest definition of each token declared between this registry and `ancestor`; undefined when `ancestor` is not above it. */
|
|
61516
|
+
defsBelow(ancestor) {
|
|
61517
|
+
if (this === ancestor) return /* @__PURE__ */ new Map();
|
|
61518
|
+
const owned = this.parentProviders?.defsBelow(ancestor);
|
|
61519
|
+
if (!owned) return void 0;
|
|
61520
|
+
for (const [token, rec] of this.defs) owned.set(token, { registry: this, rec });
|
|
61521
|
+
return owned;
|
|
61522
|
+
}
|
|
61332
61523
|
dependsOnAny(token, targets, visited = /* @__PURE__ */ new Set()) {
|
|
61333
61524
|
if (targets.has(token)) return true;
|
|
61334
61525
|
if (visited.has(token)) return false;
|
|
@@ -61414,6 +61605,15 @@ var init_provider_registry = __esm({
|
|
|
61414
61605
|
if (v !== void 0) return v;
|
|
61415
61606
|
throw new ProviderNotInstantiatedError(tokenName18(token), "GLOBAL", "parent");
|
|
61416
61607
|
}
|
|
61608
|
+
await up.registry.buildIntoStoreWithViews(
|
|
61609
|
+
token,
|
|
61610
|
+
up.rec,
|
|
61611
|
+
contextStore,
|
|
61612
|
+
scopeKey,
|
|
61613
|
+
contextStore,
|
|
61614
|
+
up.registry.getAllSingletons()
|
|
61615
|
+
);
|
|
61616
|
+
return contextStore.get(token);
|
|
61417
61617
|
}
|
|
61418
61618
|
throw new ProviderDependencyError(`Cannot resolve dependency ${tokenName18(token)} from views`);
|
|
61419
61619
|
}
|
|
@@ -63077,14 +63277,8 @@ var init_front_mcp = __esm({
|
|
|
63077
63277
|
prompts: { listChanged: true }
|
|
63078
63278
|
} : {};
|
|
63079
63279
|
const channelCapabilities = scope.channels?.getCapabilities() ?? {};
|
|
63080
|
-
const composeInstructions = () =>
|
|
63081
|
-
|
|
63082
|
-
channelInstructions: buildChannelInstructions(scope.channels),
|
|
63083
|
-
skillRegistry: scope.skills,
|
|
63084
|
-
policy: scope.metadata.skillsConfig?.injectInstructions,
|
|
63085
|
-
mcpResources: scope.metadata.skillsConfig?.mcpResources
|
|
63086
|
-
});
|
|
63087
|
-
const instructions = composeInstructions();
|
|
63280
|
+
const composeInstructions = (caller) => composeCallerInstructions(scope, { ctx: caller });
|
|
63281
|
+
const instructions = "";
|
|
63088
63282
|
const serverOptions = {
|
|
63089
63283
|
instructions,
|
|
63090
63284
|
capabilities: {
|
|
@@ -66064,6 +66258,7 @@ export {
|
|
|
66064
66258
|
channelsConfigSchema,
|
|
66065
66259
|
clearCreateCache,
|
|
66066
66260
|
compareVersions,
|
|
66261
|
+
composeCallerInstructions,
|
|
66067
66262
|
composeInitializeInstructions,
|
|
66068
66263
|
computeIssuer,
|
|
66069
66264
|
computeResource,
|