@agimon-ai/po-skill 0.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -0
  3. package/dist/apiContracts.cjs +17 -0
  4. package/dist/apiContracts.cjs.map +1 -0
  5. package/dist/apiContracts.d.mts +53 -0
  6. package/dist/apiContracts.d.mts.map +1 -0
  7. package/dist/apiContracts.mjs +13 -0
  8. package/dist/apiContracts.mjs.map +1 -0
  9. package/dist/catalog.cjs +186 -0
  10. package/dist/catalog.cjs.map +1 -0
  11. package/dist/catalog.d.mts +66 -0
  12. package/dist/catalog.d.mts.map +1 -0
  13. package/dist/catalog.mjs +181 -0
  14. package/dist/catalog.mjs.map +1 -0
  15. package/dist/extensions/mcp-ui.mjs +31 -0
  16. package/dist/extensions/mcp-ui.mjs.map +1 -0
  17. package/dist/extensions/mcp.cjs +130 -0
  18. package/dist/extensions/mcp.cjs.map +1 -0
  19. package/dist/extensions/mcp.d.mts +5 -0
  20. package/dist/extensions/mcp.d.mts.map +1 -0
  21. package/dist/extensions/mcp.mjs +125 -0
  22. package/dist/extensions/mcp.mjs.map +1 -0
  23. package/dist/extensions/server.cjs +528 -0
  24. package/dist/extensions/server.cjs.map +1 -0
  25. package/dist/extensions/server.d.mts +5 -0
  26. package/dist/extensions/server.d.mts.map +1 -0
  27. package/dist/extensions/server.mjs +519 -0
  28. package/dist/extensions/server.mjs.map +1 -0
  29. package/dist/index.cjs +5 -0
  30. package/dist/index.d.mts +6 -0
  31. package/dist/index.d.mts.map +1 -0
  32. package/dist/index.mjs +2 -0
  33. package/dist/rolldown-runtime-VH7oDXx4.cjs +28 -0
  34. package/dist/skills-Ccvg1Hcz.mjs +8 -0
  35. package/dist/skills-Ccvg1Hcz.mjs.map +1 -0
  36. package/dist/skills-ComtgYb1.cjs +25 -0
  37. package/dist/skills-ComtgYb1.cjs.map +1 -0
  38. package/llms.txt +15 -0
  39. package/package.json +135 -0
  40. package/src/prompts/po-author-skill/SKILL.md +37 -0
  41. package/src/prompts/po-use-skill/SKILL.md +18 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.mjs","names":[],"sources":["../src/services/skillCatalog/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { listDomainNames, type PluginSkillDiscovery, resolvePluginEntries } from '@agimon-ai/po-config/domains';\nimport type { SkillSourceContribution } from '@agimon-ai/po-core/skills';\nimport { materializePluginEntries } from '@agimon-ai/po-domain/plugins';\nimport { formatSkillsForPrompt, loadSkillsFromDir, type Skill } from '@earendil-works/pi-coding-agent';\n\nconst SKILLS_DIRECTORY = 'skills';\nconst SHARED_SKILLS_OWNER = '.claude/skills';\n\nexport type SkillGroupKey = 'extensions' | 'help' | 'plugins' | 'default';\n\nexport interface SkillEntry {\n name: string;\n description: string;\n filePath: string;\n baseDir: string;\n group: SkillGroupKey;\n /** Package name for an extension, plugin directory name, or `.claude/skills`. */\n owner: string;\n modelInvocable: boolean;\n /**\n * What removing this skill would save from the `<available_skills>` block.\n *\n * Marginal rather than proportional: the block has fixed framing that no\n * single skill pays for, so the useful figure is what actually goes away.\n * Bodies are excluded because they load on demand and are not a resting cost.\n */\n promptTokens?: number;\n}\n\nexport interface SkillOwnerNode {\n owner: string;\n skills: SkillEntry[];\n}\n\nexport interface SkillGroup {\n key: SkillGroupKey;\n label: string;\n owners: SkillOwnerNode[];\n}\n\nexport interface SkillCatalog {\n groups: SkillGroup[];\n skillCount: number;\n /** Tokens the `<available_skills>` prompt block costs on every request. */\n promptTokens: number;\n /** Tokens every loaded SKILL.md costs in full, if all of them were read. */\n bodyTokens: number;\n /** Frontmatter and read failures, surfaced instead of thrown. */\n diagnostics: string[];\n}\n\nexport interface SkillCatalogOptions {\n repoRoot: string;\n /** Exact files the current selection resolved to, from `HarnessState.skillDirectories`. */\n activeSkillDirectories: readonly string[];\n extensionSources: readonly SkillSourceContribution[];\n /** Activation-gated wrappers already accepted by the merged active-skill view. */\n helpSkills?: readonly Skill[];\n /** Bounded Help activation and collision diagnostics. */\n helpDiagnostics?: readonly string[];\n}\n\n/**\n * The tokenizer, loaded on first use rather than at import.\n *\n * `gpt-tokenizer` carries its whole vocabulary and costs about a tenth of a\n * second to load. This module is reachable from the skills extension, which Pi\n * loads at session start, so a top-level import would charge every session for\n * a surface most of them never open.\n */\nlet tokenizer: Promise<typeof import('gpt-tokenizer')> | undefined;\n\nexport async function counter(): Promise<(text: string) => number> {\n tokenizer ??= import('gpt-tokenizer');\n return (await tokenizer).countTokens;\n}\n\n/**\n * Matches a directory against the active set.\n *\n * A domain that lists a plugin subset puts individual skill directories in the\n * set rather than the plugin's `skills` root, so containment has to be checked\n * both ways: the set may hold an ancestor of the directory, or a descendant of\n * it.\n */\nfunction createActiveMatcher(directories: readonly string[]): (directory: string) => boolean {\n const active = directories.map((directory) => path.resolve(directory));\n return (directory) => {\n const resolved = path.resolve(directory);\n return active.some(\n (entry) =>\n entry === resolved || entry.startsWith(`${resolved}${path.sep}`) || resolved.startsWith(`${entry}${path.sep}`),\n );\n };\n}\n\nfunction collect(\n directory: string,\n group: SkillGroupKey,\n owner: string,\n isActive: (directory: string) => boolean,\n loaded: Skill[],\n diagnostics: string[],\n discovery: PluginSkillDiscovery = 'recursive',\n): SkillEntry[] {\n const result = loadSkillsFromDir({ dir: directory, source: owner });\n for (const diagnostic of result.diagnostics) {\n diagnostics.push(`${diagnostic.path ?? directory}: ${diagnostic.message}`);\n }\n // Checked per skill, not per root: a subset domain selects some of a plugin's\n // skills and leaves the rest on disk, unloaded and therefore not listed.\n const root = path.resolve(directory);\n const kept = result.skills.filter((skill) => {\n const skillDirectory = path.dirname(skill.filePath);\n if (discovery === 'direct-children' && path.dirname(skillDirectory) !== root) return false;\n return isActive(skillDirectory);\n });\n // Kept in their loaded form as well, because the prompt-block cost is measured\n // by handing them back to Pi's own formatter.\n loaded.push(...kept);\n return kept\n .map((skill) => ({\n name: skill.name,\n description: skill.description,\n filePath: skill.filePath,\n baseDir: skill.baseDir,\n group,\n owner,\n modelInvocable: !skill.disableModelInvocation,\n }))\n .sort((left, right) => left.name.localeCompare(right.name));\n}\n\nfunction sortOwners(owners: SkillOwnerNode[]): SkillOwnerNode[] {\n return owners.sort((left, right) => left.owner.localeCompare(right.owner));\n}\n\nfunction collectHelpSkills(skills: readonly Skill[], loaded: Skill[], diagnostics: string[]): SkillOwnerNode[] {\n const occupiedNames = new Set(loaded.map((skill) => skill.name));\n const owners = new Map<string, SkillEntry[]>();\n const candidates = [...skills].sort(\n (left, right) =>\n left.sourceInfo.source.localeCompare(right.sourceInfo.source) ||\n left.name.localeCompare(right.name) ||\n left.filePath.localeCompare(right.filePath),\n );\n for (const skill of candidates) {\n if (occupiedNames.has(skill.name)) {\n diagnostics.push(\n `Help ${skill.sourceInfo.source} [HELP_SKILL_COLLISION]: '${skill.name}' was ignored because a normal skill wins.`,\n );\n continue;\n }\n occupiedNames.add(skill.name);\n loaded.push(skill);\n const owner = skill.sourceInfo.source;\n const entries = owners.get(owner) ?? [];\n entries.push({\n name: skill.name,\n description: skill.description,\n filePath: skill.filePath,\n baseDir: skill.baseDir,\n group: 'help',\n owner,\n modelInvocable: !skill.disableModelInvocation,\n });\n owners.set(owner, entries);\n }\n return sortOwners(\n [...owners.entries()].map(([owner, entries]) => ({\n owner,\n skills: entries.sort((left, right) => left.name.localeCompare(right.name)),\n })),\n );\n}\n\n/**\n * Every skill this session actually loaded, grouped by where it comes from,\n * priced in tokens.\n *\n * Discovery runs over `loadSkillsFromDir` from Pi rather than the harness's own\n * walker so the listing matches what Pi would load, including its ignore-file\n * handling; the same skills are then handed to Pi's `formatSkillsForPrompt` so\n * the always-on figure is the real prompt block rather than a reconstruction of\n * it.\n */\nexport async function buildSkillCatalog(options: SkillCatalogOptions): Promise<SkillCatalog> {\n const { repoRoot } = options;\n const isActive = createActiveMatcher(options.activeSkillDirectories);\n const diagnostics: string[] = [...(options.helpDiagnostics ?? [])];\n const loaded: Skill[] = [];\n\n const extensionOwners: SkillOwnerNode[] = [];\n for (const entry of options.extensionSources) {\n const skills = entry.directories.flatMap((directory) =>\n collect(directory, 'extensions', entry.source, () => true, loaded, diagnostics),\n );\n if (skills.length > 0) extensionOwners.push({ owner: entry.source, skills });\n }\n\n const pluginOwners: SkillOwnerNode[] = [];\n const domainPlugins = await materializePluginEntries(resolvePluginEntries(repoRoot, listDomainNames(repoRoot), []));\n for (const entry of domainPlugins) {\n const directory = path.join(entry.directory, SKILLS_DIRECTORY);\n if (!fs.existsSync(directory)) continue;\n const owner = path.basename(entry.directory);\n const skills = collect(directory, 'plugins', owner, isActive, loaded, diagnostics, entry.skillDiscovery);\n if (skills.length > 0) pluginOwners.push({ owner, skills });\n }\n\n const sharedDirectory = path.join(repoRoot, '.claude', SKILLS_DIRECTORY);\n const sharedSkills = collect(sharedDirectory, 'default', SHARED_SKILLS_OWNER, isActive, loaded, diagnostics);\n const defaultOwners = sharedSkills.length > 0 ? [{ owner: SHARED_SKILLS_OWNER, skills: sharedSkills }] : [];\n const helpOwners = collectHelpSkills(options.helpSkills ?? [], loaded, diagnostics);\n\n const groups: SkillGroup[] = [\n { key: 'extensions', label: 'extensions', owners: sortOwners(extensionOwners) },\n { key: 'help', label: 'Help', owners: helpOwners },\n { key: 'plugins', label: 'plugins', owners: sortOwners(pluginOwners) },\n { key: 'default', label: 'default', owners: defaultOwners },\n ];\n\n const countTokens = await counter();\n const prompt = formatSkillsForPrompt(loaded);\n const framingTokens = countTokens(formatSkillsForPrompt([]));\n const marginal = new Map<string, number>();\n for (const skill of loaded) {\n marginal.set(skill.name, Math.max(0, countTokens(formatSkillsForPrompt([skill])) - framingTokens));\n }\n for (const group of groups) {\n for (const owner of group.owners) {\n for (const skill of owner.skills) {\n const tokens = marginal.get(skill.name);\n if (tokens !== undefined) skill.promptTokens = tokens;\n }\n }\n }\n let bodyTokens = 0;\n for (const skill of loaded) {\n try {\n bodyTokens += countTokens(fs.readFileSync(skill.filePath, 'utf8'));\n } catch (error) {\n diagnostics.push(`${skill.filePath}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n return {\n groups,\n skillCount: loaded.length,\n promptTokens: prompt ? countTokens(prompt) : 0,\n bodyTokens,\n diagnostics,\n };\n}\n\n/** The skills a name resolves to, used to decide what `enter` can invoke. */\nexport function findSkill(catalog: SkillCatalog, name: string): SkillEntry | undefined {\n for (const group of catalog.groups) {\n for (const owner of group.owners) {\n const match = owner.skills.find((skill) => skill.name === name);\n if (match) return match;\n }\n }\n return undefined;\n}\n"],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { defineMcpWidget } from "@agimon-ai/po-core/web";
2
+ import { McpToolFields, McpToolFrame, McpToolOutput } from "@agimon-ai/po-web-components";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ //#region src/extensions/workspaces/sessions/(frontend)/tool/load_skill.mcp.tsx
5
+ function LoadSkillMcpWidget(props) {
6
+ return /* @__PURE__ */ jsxs(McpToolFrame, {
7
+ ...props,
8
+ title: "Load skill",
9
+ children: [/* @__PURE__ */ jsx(McpToolFields, { fields: [["Skill", props.args.name]] }), /* @__PURE__ */ jsx(McpToolOutput, { result: props.result })]
10
+ });
11
+ }
12
+ var load_skill_mcp_default = defineMcpWidget(LoadSkillMcpWidget);
13
+ //#endregion
14
+ //#region src/extensions/workspaces/sessions/(frontend)/tool/search_skills.mcp.tsx
15
+ function SearchSkillsMcpWidget(props) {
16
+ return /* @__PURE__ */ jsxs(McpToolFrame, {
17
+ ...props,
18
+ title: "Search skills",
19
+ children: [/* @__PURE__ */ jsx(McpToolFields, { fields: [["Query", props.args.query]] }), /* @__PURE__ */ jsx(McpToolOutput, { result: props.result })]
20
+ });
21
+ }
22
+ //#endregion
23
+ //#region generated/mcp-ui.ts
24
+ const widgets = {
25
+ "@agimon-ai/po-skill/load_skill": load_skill_mcp_default,
26
+ "@agimon-ai/po-skill/search_skills": defineMcpWidget(SearchSkillsMcpWidget)
27
+ };
28
+ //#endregion
29
+ export { widgets };
30
+
31
+ //# sourceMappingURL=mcp-ui.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-ui.mjs","names":["Widget0","Widget1"],"sources":["../../src/extensions/workspaces/sessions/(frontend)/tool/load_skill.mcp.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/search_skills.mcp.tsx","../../generated/mcp-ui.ts"],"sourcesContent":["import { defineMcpWidget, type DoomMcpWidgetProps } from '@agimon-ai/po-core/web';\nimport { McpToolFrame, McpToolFields, McpToolOutput } from '@agimon-ai/po-web-components';\n\nfunction LoadSkillMcpWidget(props: DoomMcpWidgetProps) {\n return (\n <McpToolFrame {...props} title=\"Load skill\">\n <McpToolFields fields={[['Skill', props.args.name]]} />\n <McpToolOutput result={props.result} />\n </McpToolFrame>\n );\n}\n\nexport default defineMcpWidget(LoadSkillMcpWidget);\n","import { defineMcpWidget, type DoomMcpWidgetProps } from '@agimon-ai/po-core/web';\nimport { McpToolFrame, McpToolFields, McpToolOutput } from '@agimon-ai/po-web-components';\n\nfunction SearchSkillsMcpWidget(props: DoomMcpWidgetProps) {\n return (\n <McpToolFrame {...props} title=\"Search skills\">\n <McpToolFields fields={[['Query', props.args.query]]} />\n <McpToolOutput result={props.result} />\n </McpToolFrame>\n );\n}\n\nexport default defineMcpWidget(SearchSkillsMcpWidget);\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport type { ComponentType } from 'react';\nimport type { DoomMcpWidgetProps } from '@agimon-ai/po-core/mcpWidget';\nimport Widget0 from \"../src/extensions/workspaces/sessions/(frontend)/tool/load_skill.mcp\";\nimport Widget1 from \"../src/extensions/workspaces/sessions/(frontend)/tool/search_skills.mcp\";\n\nexport const widgets: Readonly<Record<string, ComponentType<DoomMcpWidgetProps>>> = {\n \"@agimon-ai/po-skill/load_skill\": Widget0,\n \"@agimon-ai/po-skill/search_skills\": Widget1,\n};\n"],"mappings":";;;;AAGA,SAAS,mBAAmB,OAA2B;CACrD,OACE,qBAAC,cAAD;EAAc,GAAI;EAAO,OAAM;EAA/B,UAAA,CACE,oBAAC,eAAD,EAAe,QAAQ,CAAC,CAAC,SAAS,MAAM,KAAK,IAAI,CAAC,EAAI,CAAA,GACtD,oBAAC,eAAD,EAAe,QAAQ,MAAM,OAAS,CAAA,CAC1B;;AAElB;AAEA,IAAA,yBAAe,gBAAgB,kBAAkB;;;ACTjD,SAAS,sBAAsB,OAA2B;CACxD,OACE,qBAAC,cAAD;EAAc,GAAI;EAAO,OAAM;EAA/B,UAAA,CACE,oBAAC,eAAD,EAAe,QAAQ,CAAC,CAAC,SAAS,MAAM,KAAK,KAAK,CAAC,EAAI,CAAA,GACvD,oBAAC,eAAD,EAAe,QAAQ,MAAM,OAAS,CAAA,CAC1B;;AAElB;;;ACJA,MAAa,UAAuE;CAClF,kCAAkCA;CAClC,qCDIa,gBAAgB,qBCJQC;AACvC"}
@@ -0,0 +1,130 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ let _agimon_ai_po_core_mcpFacet = require("@agimon-ai/po-core/mcpFacet");
6
+ let _agimon_ai_po_core_extensionFile = require("@agimon-ai/po-core/extensionFile");
7
+ let _agimon_ai_po_core_serverFacet = require("@agimon-ai/po-core/serverFacet");
8
+ let typebox = require("typebox");
9
+ //#region src/services/mcpSkills/index.ts
10
+ const MCP_SKILLS_SERVICE = "doom/discovered-mcp-skills";
11
+ function bindMcpSkills(context) {
12
+ const provider = context.services.get(MCP_SKILLS_SERVICE);
13
+ if (!provider) throw new Error("Discovered MCP skills are unavailable.");
14
+ return provider.list(context);
15
+ }
16
+ //#endregion
17
+ //#region src/extensions/workspaces/sessions/(backend)/skill/discovered.mcp.ts
18
+ var discovered_mcp_default = (0, _agimon_ai_po_core_extensionFile.defineRoutedContribution)(bindMcpSkills, { cardinality: "many" });
19
+ //#endregion
20
+ //#region src/extensions/workspaces/sessions/(backend)/skill/po-author-skill.mcp.ts
21
+ var po_author_skill_mcp_default = (0, _agimon_ai_po_core_mcpFacet.defineMcpSkill)({
22
+ name: "po-author-skill",
23
+ description: "Author and distribute Po agent skills. Use when creating a SKILL.md, adding supporting references or scripts, contributing a runtime skill directory through Cordis, or publishing activation-gated Help prompts from a Po package.",
24
+ read: () => (0, _agimon_ai_po_core_serverFacet.readPackageResource)(require("url").pathToFileURL(__filename).href, "src/prompts/po-author-skill/SKILL.md")
25
+ });
26
+ //#endregion
27
+ //#region src/extensions/workspaces/sessions/(backend)/skill/po-use-skill.mcp.ts
28
+ var po_use_skill_mcp_default = (0, _agimon_ai_po_core_mcpFacet.defineMcpSkill)({
29
+ name: "po-use-skill",
30
+ description: "Use Po's skill catalog and deferred discovery. Use when browsing available skills, invoking /skill:name, understanding Help and extension-owned skill groups, or diagnosing why a skill is absent or shadowed.",
31
+ read: () => (0, _agimon_ai_po_core_serverFacet.readPackageResource)(require("url").pathToFileURL(__filename).href, "src/prompts/po-use-skill/SKILL.md")
32
+ });
33
+ //#endregion
34
+ //#region src/schemas/mcpSkillTools.ts
35
+ const searchSkillsParameters = typebox.Type.Object({ query: typebox.Type.Optional(typebox.Type.String()) });
36
+ const loadSkillParameters = typebox.Type.Object({ name: typebox.Type.String() });
37
+ //#endregion
38
+ //#region src/services/mcpSkillTools/index.ts
39
+ function text(text) {
40
+ return { content: [{
41
+ type: "text",
42
+ text
43
+ }] };
44
+ }
45
+ function skills(context) {
46
+ if (context.mcpSkills === void 0) throw new Error("Remote skill access is unavailable.");
47
+ return context.mcpSkills;
48
+ }
49
+ function createSearchSkillsTool() {
50
+ return {
51
+ name: "search_skills",
52
+ label: "Search skills",
53
+ description: "Discover repository and active-domain skills available to this remote connection.",
54
+ parameters: searchSkillsParameters,
55
+ annotations: {
56
+ readOnlyHint: true,
57
+ destructiveHint: false,
58
+ openWorldHint: false
59
+ },
60
+ async execute(_toolCallId, { query }, _signal, _onUpdate, context) {
61
+ const needle = query?.trim().toLocaleLowerCase();
62
+ const available = await skills(context).list();
63
+ const matches = needle === void 0 || needle === "" ? available : available.filter(({ name, description }) => `${name}\n${description}`.toLocaleLowerCase().includes(needle));
64
+ return {
65
+ ...text(JSON.stringify(matches)),
66
+ structuredContent: { skills: matches }
67
+ };
68
+ }
69
+ };
70
+ }
71
+ function createLoadSkillTool() {
72
+ return {
73
+ name: "load_skill",
74
+ label: "Load skill",
75
+ description: "Load the full Markdown instructions for an available remote skill by exact name.",
76
+ parameters: loadSkillParameters,
77
+ annotations: {
78
+ readOnlyHint: true,
79
+ destructiveHint: false,
80
+ openWorldHint: false
81
+ },
82
+ async execute(_toolCallId, { name }, _signal, _onUpdate, context) {
83
+ return text(await skills(context).read(name));
84
+ }
85
+ };
86
+ }
87
+ //#endregion
88
+ //#region src/extensions/workspaces/sessions/(backend)/tool/load_skill.mcp.ts
89
+ var load_skill_mcp_default = (0, _agimon_ai_po_core_mcpFacet.defineMcpTool)(createLoadSkillTool());
90
+ //#endregion
91
+ //#region src/extensions/workspaces/sessions/(backend)/tool/search_skills.mcp.ts
92
+ var search_skills_mcp_default = (0, _agimon_ai_po_core_mcpFacet.defineMcpTool)(createSearchSkillsTool());
93
+ //#endregion
94
+ //#region generated/mcp.ts
95
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
96
+ const many = (value, context) => {
97
+ const resolved = typeof value === "function" ? value(context) : value;
98
+ return Array.isArray(resolved) ? resolved : [resolved];
99
+ };
100
+ const via = (identity, value) => value === void 0 ? void 0 : {
101
+ ...identity,
102
+ ...value
103
+ };
104
+ const withWidget = (key, value) => value === void 0 ? value : {
105
+ ...value,
106
+ _meta: {
107
+ ...value._meta,
108
+ ["po/widget"]: key
109
+ }
110
+ };
111
+ const mcp = (0, _agimon_ai_po_core_mcpFacet.defineMcpPlugin)({
112
+ name: "@agimon-ai/po-skill",
113
+ session: (context) => ({
114
+ get skills() {
115
+ return [
116
+ ...many(discovered_mcp_default, context),
117
+ at(po_author_skill_mcp_default, context),
118
+ at(po_use_skill_mcp_default, context)
119
+ ];
120
+ },
121
+ get tools() {
122
+ return [withWidget("@agimon-ai/po-skill/load_skill", via({ name: "load_skill" }, at(load_skill_mcp_default, context))), withWidget("@agimon-ai/po-skill/search_skills", via({ name: "search_skills" }, at(search_skills_mcp_default, context)))];
123
+ }
124
+ })
125
+ });
126
+ //#endregion
127
+ exports.default = mcp;
128
+ exports.mcp = mcp;
129
+
130
+ //# sourceMappingURL=mcp.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.cjs","names":["defineRoutedContribution","defineMcpSkill","readPackageResource","defineMcpSkill","readPackageResource","Type","defineMcpTool","defineMcpTool","defineMcpPlugin","skillDiscovered","skillPoAuthorSkill","skillPoUseSkill","toolLoadSkill","toolSearchSkills"],"sources":["../../src/services/mcpSkills/index.ts","../../src/extensions/workspaces/sessions/(backend)/skill/discovered.mcp.ts","../../src/extensions/workspaces/sessions/(backend)/skill/po-author-skill.mcp.ts","../../src/extensions/workspaces/sessions/(backend)/skill/po-use-skill.mcp.ts","../../src/schemas/mcpSkillTools.ts","../../src/services/mcpSkillTools/index.ts","../../src/extensions/workspaces/sessions/(backend)/tool/load_skill.mcp.ts","../../src/extensions/workspaces/sessions/(backend)/tool/search_skills.mcp.ts","../../generated/mcp.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\n\nimport type { DoomMcpPluginContext, DoomMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport type { ServerSkillGroup } from '../serverInventory';\n\nexport const MCP_SKILLS_SERVICE = 'doom/discovered-mcp-skills';\n\nexport interface McpSkillProvider {\n list(context: DoomMcpPluginContext): readonly DoomMcpSkill[];\n}\n\n/** Explicit remote provider, never a projection of the local resource registry. */\nexport function mountMcpSkills(groups: readonly ServerSkillGroup[], signal: AbortSignal) {\n return (context: Context): void => {\n context.provide(MCP_SKILLS_SERVICE, {\n list(remote) {\n signal.throwIfAborted();\n remote.signal.throwIfAborted();\n const domains = remote.selection.read().domains;\n const skills = new Map<string, DoomMcpSkill>();\n for (const group of groups) {\n if (group.domain !== undefined && !domains.includes(group.domain)) continue;\n for (const skill of group.skills) {\n // Match command precedence, including shared copies across domains.\n if (skills.has(skill.name)) continue;\n skills.set(skill.name, {\n name: skill.name,\n description: skill.description,\n async read() {\n const readSignal = AbortSignal.any([signal, remote.signal]);\n readSignal.throwIfAborted();\n const text = await readFile(skill.filePath, { encoding: 'utf8', signal: readSignal });\n readSignal.throwIfAborted();\n return text;\n },\n });\n }\n }\n return [...skills.values()];\n },\n } satisfies McpSkillProvider);\n };\n}\n\nexport function bindMcpSkills(context: DoomMcpPluginContext): readonly DoomMcpSkill[] {\n const provider = context.services.get<McpSkillProvider>(MCP_SKILLS_SERVICE);\n if (!provider) throw new Error('Discovered MCP skills are unavailable.');\n return provider.list(context);\n}\n","import { defineRoutedContribution } from '@agimon-ai/po-core/extensionFile';\n\nimport { bindMcpSkills } from '../../../../../services/mcpSkills';\n\nexport default defineRoutedContribution(bindMcpSkills, { cardinality: 'many' });\n","import { defineMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport { readPackageResource } from '@agimon-ai/po-core/serverFacet';\n\nexport default defineMcpSkill({\n name: 'po-author-skill',\n description:\n 'Author and distribute Po agent skills. Use when creating a SKILL.md, adding supporting references or scripts, contributing a runtime skill directory through Cordis, or publishing activation-gated Help prompts from a Po package.',\n read: () => readPackageResource(import.meta.url, 'src/prompts/po-author-skill/SKILL.md'),\n});\n","import { defineMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport { readPackageResource } from '@agimon-ai/po-core/serverFacet';\n\nexport default defineMcpSkill({\n name: 'po-use-skill',\n description:\n \"Use Po's skill catalog and deferred discovery. Use when browsing available skills, invoking /skill:name, understanding Help and extension-owned skill groups, or diagnosing why a skill is absent or shadowed.\",\n read: () => readPackageResource(import.meta.url, 'src/prompts/po-use-skill/SKILL.md'),\n});\n","import { Type } from 'typebox';\n\nexport const searchSkillsParameters = Type.Object({ query: Type.Optional(Type.String()) });\nexport const loadSkillParameters = Type.Object({ name: Type.String() });\n","import type { DoomHeadlessHostService, DoomHeadlessTool } from '@agimon-ai/po-core/headless';\n\nimport { loadSkillParameters, searchSkillsParameters } from '../../schemas/mcpSkillTools';\n\nfunction text(text: string) {\n return { content: [{ type: 'text' as const, text }] };\n}\n\nfunction skills(context: Parameters<DoomHeadlessTool['execute']>[4]) {\n if (context.mcpSkills === undefined) throw new Error('Remote skill access is unavailable.');\n return context.mcpSkills;\n}\n\nexport function createSearchSkillsTool(): DoomHeadlessTool<typeof searchSkillsParameters> {\n return {\n // web-plugin-tool-renderers: ignore search_skills (remote MCP only)\n name: 'search_skills',\n label: 'Search skills',\n description: 'Discover repository and active-domain skills available to this remote connection.',\n parameters: searchSkillsParameters,\n annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },\n async execute(_toolCallId, { query }, _signal, _onUpdate, context) {\n const needle = query?.trim().toLocaleLowerCase();\n const available = await skills(context).list();\n const matches =\n needle === undefined || needle === ''\n ? available\n : available.filter(({ name, description }) => `${name}\\n${description}`.toLocaleLowerCase().includes(needle));\n return { ...text(JSON.stringify(matches)), structuredContent: { skills: matches } };\n },\n };\n}\n\n/**\n * The session agent's way into a skill. Its skills are listed in the prompt, which Po\n * controls, so it needs no search; a remote agent's prompt is not ours, hence the pair above.\n */\nexport function createSessionLoadSkillTool(\n host: Pick<DoomHeadlessHostService, 'readSkill'>,\n): DoomHeadlessTool<typeof loadSkillParameters> {\n return {\n // web-plugin-tool-renderers: ignore load_skill (server session only, shown as a generic call)\n // DOOM_LOAD_SKILL_TOOL, spelled out so the renderer rule can read it.\n name: 'load_skill',\n label: 'Load skill',\n description: 'Load the full instructions of a skill from the available skills list by exact name.',\n parameters: loadSkillParameters,\n executionMode: 'parallel',\n async execute(_toolCallId, { name }) {\n const body = host.readSkill(name);\n if (body === undefined) return { ...text(`No skill named ${name} is available in this session.`), isError: true };\n return text(body);\n },\n };\n}\n\nexport function createLoadSkillTool(): DoomHeadlessTool<typeof loadSkillParameters> {\n return {\n // web-plugin-tool-renderers: ignore load_skill (remote MCP only)\n name: 'load_skill',\n label: 'Load skill',\n description: 'Load the full Markdown instructions for an available remote skill by exact name.',\n parameters: loadSkillParameters,\n annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },\n async execute(_toolCallId, { name }, _signal, _onUpdate, context) {\n return text(await skills(context).read(name));\n },\n };\n}\n","import { defineMcpTool } from '@agimon-ai/po-core/mcpFacet';\n\nimport { createLoadSkillTool } from '../../../../../services/mcpSkillTools';\n\nexport default defineMcpTool(createLoadSkillTool());\n","import { defineMcpTool } from '@agimon-ai/po-core/mcpFacet';\n\nimport { createSearchSkillsTool } from '../../../../../services/mcpSkillTools';\n\nexport default defineMcpTool(createSearchSkillsTool());\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineMcpPlugin, type DoomMcpSessionPlugin } from '@agimon-ai/po-core/mcpFacet';\n\nimport skillDiscovered from '../src/extensions/workspaces/sessions/(backend)/skill/discovered.mcp';\nimport skillPoAuthorSkill from '../src/extensions/workspaces/sessions/(backend)/skill/po-author-skill.mcp';\nimport skillPoUseSkill from '../src/extensions/workspaces/sessions/(backend)/skill/po-use-skill.mcp';\nimport toolLoadSkill from '../src/extensions/workspaces/sessions/(backend)/tool/load_skill.mcp';\nimport toolSearchSkills from '../src/extensions/workspaces/sessions/(backend)/tool/search_skills.mcp';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\ntype ManyFactory<T, C> = (context: C) => T | readonly T[];\nconst many = <T, C>(value: T | readonly T[] | ManyFactory<T, C>, context: C): readonly T[] => {\n const resolved = typeof value === 'function' ? (value as ManyFactory<T, C>)(context) : value;\n return Array.isArray(resolved) ? resolved : [resolved as T];\n};\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nconst withWidget = <T>(key: string, value: T): T => value === undefined ? value : ({\n ...value, _meta: { ...(value as { _meta?: object })._meta, [\"po/widget\"]: key },\n});\n\nexport const mcp = defineMcpPlugin({\n name: '@agimon-ai/po-skill',\n session: (context) => ({\n get skills(): DoomMcpSessionPlugin['skills'] { return [...many(skillDiscovered, context), at(skillPoAuthorSkill, context), at(skillPoUseSkill, context)]; },\n get tools(): DoomMcpSessionPlugin['tools'] { return [withWidget(\"@agimon-ai/po-skill/load_skill\", via({ name: 'load_skill' }, at(toolLoadSkill, context))), withWidget(\"@agimon-ai/po-skill/search_skills\", via({ name: 'search_skills' }, at(toolSearchSkills, context)))]; },\n }) satisfies DoomMcpSessionPlugin,\n});\n\nexport default mcp;\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ //#region generated/mcp.d.ts
2
+ export declare const mcp: import("@agimon-ai/po-core/mcpFacet").DoomMcpPluginDefinition;
3
+ //#endregion
4
+ export { mcp as default };
5
+ //# sourceMappingURL=mcp.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.mts","names":[],"sources":["../../generated/mcp.ts"],"mappings":";qBAwBa,2CAAG"}
@@ -0,0 +1,125 @@
1
+ import { defineMcpPlugin, defineMcpSkill, defineMcpTool } from "@agimon-ai/po-core/mcpFacet";
2
+ import { defineRoutedContribution } from "@agimon-ai/po-core/extensionFile";
3
+ import { readPackageResource } from "@agimon-ai/po-core/serverFacet";
4
+ import { Type } from "typebox";
5
+ //#region src/services/mcpSkills/index.ts
6
+ const MCP_SKILLS_SERVICE = "doom/discovered-mcp-skills";
7
+ function bindMcpSkills(context) {
8
+ const provider = context.services.get(MCP_SKILLS_SERVICE);
9
+ if (!provider) throw new Error("Discovered MCP skills are unavailable.");
10
+ return provider.list(context);
11
+ }
12
+ //#endregion
13
+ //#region src/extensions/workspaces/sessions/(backend)/skill/discovered.mcp.ts
14
+ var discovered_mcp_default = defineRoutedContribution(bindMcpSkills, { cardinality: "many" });
15
+ //#endregion
16
+ //#region src/extensions/workspaces/sessions/(backend)/skill/po-author-skill.mcp.ts
17
+ var po_author_skill_mcp_default = defineMcpSkill({
18
+ name: "po-author-skill",
19
+ description: "Author and distribute Po agent skills. Use when creating a SKILL.md, adding supporting references or scripts, contributing a runtime skill directory through Cordis, or publishing activation-gated Help prompts from a Po package.",
20
+ read: () => readPackageResource(import.meta.url, "src/prompts/po-author-skill/SKILL.md")
21
+ });
22
+ //#endregion
23
+ //#region src/extensions/workspaces/sessions/(backend)/skill/po-use-skill.mcp.ts
24
+ var po_use_skill_mcp_default = defineMcpSkill({
25
+ name: "po-use-skill",
26
+ description: "Use Po's skill catalog and deferred discovery. Use when browsing available skills, invoking /skill:name, understanding Help and extension-owned skill groups, or diagnosing why a skill is absent or shadowed.",
27
+ read: () => readPackageResource(import.meta.url, "src/prompts/po-use-skill/SKILL.md")
28
+ });
29
+ //#endregion
30
+ //#region src/schemas/mcpSkillTools.ts
31
+ const searchSkillsParameters = Type.Object({ query: Type.Optional(Type.String()) });
32
+ const loadSkillParameters = Type.Object({ name: Type.String() });
33
+ //#endregion
34
+ //#region src/services/mcpSkillTools/index.ts
35
+ function text(text) {
36
+ return { content: [{
37
+ type: "text",
38
+ text
39
+ }] };
40
+ }
41
+ function skills(context) {
42
+ if (context.mcpSkills === void 0) throw new Error("Remote skill access is unavailable.");
43
+ return context.mcpSkills;
44
+ }
45
+ function createSearchSkillsTool() {
46
+ return {
47
+ name: "search_skills",
48
+ label: "Search skills",
49
+ description: "Discover repository and active-domain skills available to this remote connection.",
50
+ parameters: searchSkillsParameters,
51
+ annotations: {
52
+ readOnlyHint: true,
53
+ destructiveHint: false,
54
+ openWorldHint: false
55
+ },
56
+ async execute(_toolCallId, { query }, _signal, _onUpdate, context) {
57
+ const needle = query?.trim().toLocaleLowerCase();
58
+ const available = await skills(context).list();
59
+ const matches = needle === void 0 || needle === "" ? available : available.filter(({ name, description }) => `${name}\n${description}`.toLocaleLowerCase().includes(needle));
60
+ return {
61
+ ...text(JSON.stringify(matches)),
62
+ structuredContent: { skills: matches }
63
+ };
64
+ }
65
+ };
66
+ }
67
+ function createLoadSkillTool() {
68
+ return {
69
+ name: "load_skill",
70
+ label: "Load skill",
71
+ description: "Load the full Markdown instructions for an available remote skill by exact name.",
72
+ parameters: loadSkillParameters,
73
+ annotations: {
74
+ readOnlyHint: true,
75
+ destructiveHint: false,
76
+ openWorldHint: false
77
+ },
78
+ async execute(_toolCallId, { name }, _signal, _onUpdate, context) {
79
+ return text(await skills(context).read(name));
80
+ }
81
+ };
82
+ }
83
+ //#endregion
84
+ //#region src/extensions/workspaces/sessions/(backend)/tool/load_skill.mcp.ts
85
+ var load_skill_mcp_default = defineMcpTool(createLoadSkillTool());
86
+ //#endregion
87
+ //#region src/extensions/workspaces/sessions/(backend)/tool/search_skills.mcp.ts
88
+ var search_skills_mcp_default = defineMcpTool(createSearchSkillsTool());
89
+ //#endregion
90
+ //#region generated/mcp.ts
91
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
92
+ const many = (value, context) => {
93
+ const resolved = typeof value === "function" ? value(context) : value;
94
+ return Array.isArray(resolved) ? resolved : [resolved];
95
+ };
96
+ const via = (identity, value) => value === void 0 ? void 0 : {
97
+ ...identity,
98
+ ...value
99
+ };
100
+ const withWidget = (key, value) => value === void 0 ? value : {
101
+ ...value,
102
+ _meta: {
103
+ ...value._meta,
104
+ ["po/widget"]: key
105
+ }
106
+ };
107
+ const mcp = defineMcpPlugin({
108
+ name: "@agimon-ai/po-skill",
109
+ session: (context) => ({
110
+ get skills() {
111
+ return [
112
+ ...many(discovered_mcp_default, context),
113
+ at(po_author_skill_mcp_default, context),
114
+ at(po_use_skill_mcp_default, context)
115
+ ];
116
+ },
117
+ get tools() {
118
+ return [withWidget("@agimon-ai/po-skill/load_skill", via({ name: "load_skill" }, at(load_skill_mcp_default, context))), withWidget("@agimon-ai/po-skill/search_skills", via({ name: "search_skills" }, at(search_skills_mcp_default, context)))];
119
+ }
120
+ })
121
+ });
122
+ //#endregion
123
+ export { mcp as default, mcp };
124
+
125
+ //# sourceMappingURL=mcp.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.mjs","names":["skillDiscovered","skillPoAuthorSkill","skillPoUseSkill","toolLoadSkill","toolSearchSkills"],"sources":["../../src/services/mcpSkills/index.ts","../../src/extensions/workspaces/sessions/(backend)/skill/discovered.mcp.ts","../../src/extensions/workspaces/sessions/(backend)/skill/po-author-skill.mcp.ts","../../src/extensions/workspaces/sessions/(backend)/skill/po-use-skill.mcp.ts","../../src/schemas/mcpSkillTools.ts","../../src/services/mcpSkillTools/index.ts","../../src/extensions/workspaces/sessions/(backend)/tool/load_skill.mcp.ts","../../src/extensions/workspaces/sessions/(backend)/tool/search_skills.mcp.ts","../../generated/mcp.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\n\nimport type { DoomMcpPluginContext, DoomMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport type { ServerSkillGroup } from '../serverInventory';\n\nexport const MCP_SKILLS_SERVICE = 'doom/discovered-mcp-skills';\n\nexport interface McpSkillProvider {\n list(context: DoomMcpPluginContext): readonly DoomMcpSkill[];\n}\n\n/** Explicit remote provider, never a projection of the local resource registry. */\nexport function mountMcpSkills(groups: readonly ServerSkillGroup[], signal: AbortSignal) {\n return (context: Context): void => {\n context.provide(MCP_SKILLS_SERVICE, {\n list(remote) {\n signal.throwIfAborted();\n remote.signal.throwIfAborted();\n const domains = remote.selection.read().domains;\n const skills = new Map<string, DoomMcpSkill>();\n for (const group of groups) {\n if (group.domain !== undefined && !domains.includes(group.domain)) continue;\n for (const skill of group.skills) {\n // Match command precedence, including shared copies across domains.\n if (skills.has(skill.name)) continue;\n skills.set(skill.name, {\n name: skill.name,\n description: skill.description,\n async read() {\n const readSignal = AbortSignal.any([signal, remote.signal]);\n readSignal.throwIfAborted();\n const text = await readFile(skill.filePath, { encoding: 'utf8', signal: readSignal });\n readSignal.throwIfAborted();\n return text;\n },\n });\n }\n }\n return [...skills.values()];\n },\n } satisfies McpSkillProvider);\n };\n}\n\nexport function bindMcpSkills(context: DoomMcpPluginContext): readonly DoomMcpSkill[] {\n const provider = context.services.get<McpSkillProvider>(MCP_SKILLS_SERVICE);\n if (!provider) throw new Error('Discovered MCP skills are unavailable.');\n return provider.list(context);\n}\n","import { defineRoutedContribution } from '@agimon-ai/po-core/extensionFile';\n\nimport { bindMcpSkills } from '../../../../../services/mcpSkills';\n\nexport default defineRoutedContribution(bindMcpSkills, { cardinality: 'many' });\n","import { defineMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport { readPackageResource } from '@agimon-ai/po-core/serverFacet';\n\nexport default defineMcpSkill({\n name: 'po-author-skill',\n description:\n 'Author and distribute Po agent skills. Use when creating a SKILL.md, adding supporting references or scripts, contributing a runtime skill directory through Cordis, or publishing activation-gated Help prompts from a Po package.',\n read: () => readPackageResource(import.meta.url, 'src/prompts/po-author-skill/SKILL.md'),\n});\n","import { defineMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport { readPackageResource } from '@agimon-ai/po-core/serverFacet';\n\nexport default defineMcpSkill({\n name: 'po-use-skill',\n description:\n \"Use Po's skill catalog and deferred discovery. Use when browsing available skills, invoking /skill:name, understanding Help and extension-owned skill groups, or diagnosing why a skill is absent or shadowed.\",\n read: () => readPackageResource(import.meta.url, 'src/prompts/po-use-skill/SKILL.md'),\n});\n","import { Type } from 'typebox';\n\nexport const searchSkillsParameters = Type.Object({ query: Type.Optional(Type.String()) });\nexport const loadSkillParameters = Type.Object({ name: Type.String() });\n","import type { DoomHeadlessHostService, DoomHeadlessTool } from '@agimon-ai/po-core/headless';\n\nimport { loadSkillParameters, searchSkillsParameters } from '../../schemas/mcpSkillTools';\n\nfunction text(text: string) {\n return { content: [{ type: 'text' as const, text }] };\n}\n\nfunction skills(context: Parameters<DoomHeadlessTool['execute']>[4]) {\n if (context.mcpSkills === undefined) throw new Error('Remote skill access is unavailable.');\n return context.mcpSkills;\n}\n\nexport function createSearchSkillsTool(): DoomHeadlessTool<typeof searchSkillsParameters> {\n return {\n // web-plugin-tool-renderers: ignore search_skills (remote MCP only)\n name: 'search_skills',\n label: 'Search skills',\n description: 'Discover repository and active-domain skills available to this remote connection.',\n parameters: searchSkillsParameters,\n annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },\n async execute(_toolCallId, { query }, _signal, _onUpdate, context) {\n const needle = query?.trim().toLocaleLowerCase();\n const available = await skills(context).list();\n const matches =\n needle === undefined || needle === ''\n ? available\n : available.filter(({ name, description }) => `${name}\\n${description}`.toLocaleLowerCase().includes(needle));\n return { ...text(JSON.stringify(matches)), structuredContent: { skills: matches } };\n },\n };\n}\n\n/**\n * The session agent's way into a skill. Its skills are listed in the prompt, which Po\n * controls, so it needs no search; a remote agent's prompt is not ours, hence the pair above.\n */\nexport function createSessionLoadSkillTool(\n host: Pick<DoomHeadlessHostService, 'readSkill'>,\n): DoomHeadlessTool<typeof loadSkillParameters> {\n return {\n // web-plugin-tool-renderers: ignore load_skill (server session only, shown as a generic call)\n // DOOM_LOAD_SKILL_TOOL, spelled out so the renderer rule can read it.\n name: 'load_skill',\n label: 'Load skill',\n description: 'Load the full instructions of a skill from the available skills list by exact name.',\n parameters: loadSkillParameters,\n executionMode: 'parallel',\n async execute(_toolCallId, { name }) {\n const body = host.readSkill(name);\n if (body === undefined) return { ...text(`No skill named ${name} is available in this session.`), isError: true };\n return text(body);\n },\n };\n}\n\nexport function createLoadSkillTool(): DoomHeadlessTool<typeof loadSkillParameters> {\n return {\n // web-plugin-tool-renderers: ignore load_skill (remote MCP only)\n name: 'load_skill',\n label: 'Load skill',\n description: 'Load the full Markdown instructions for an available remote skill by exact name.',\n parameters: loadSkillParameters,\n annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },\n async execute(_toolCallId, { name }, _signal, _onUpdate, context) {\n return text(await skills(context).read(name));\n },\n };\n}\n","import { defineMcpTool } from '@agimon-ai/po-core/mcpFacet';\n\nimport { createLoadSkillTool } from '../../../../../services/mcpSkillTools';\n\nexport default defineMcpTool(createLoadSkillTool());\n","import { defineMcpTool } from '@agimon-ai/po-core/mcpFacet';\n\nimport { createSearchSkillsTool } from '../../../../../services/mcpSkillTools';\n\nexport default defineMcpTool(createSearchSkillsTool());\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineMcpPlugin, type DoomMcpSessionPlugin } from '@agimon-ai/po-core/mcpFacet';\n\nimport skillDiscovered from '../src/extensions/workspaces/sessions/(backend)/skill/discovered.mcp';\nimport skillPoAuthorSkill from '../src/extensions/workspaces/sessions/(backend)/skill/po-author-skill.mcp';\nimport skillPoUseSkill from '../src/extensions/workspaces/sessions/(backend)/skill/po-use-skill.mcp';\nimport toolLoadSkill from '../src/extensions/workspaces/sessions/(backend)/tool/load_skill.mcp';\nimport toolSearchSkills from '../src/extensions/workspaces/sessions/(backend)/tool/search_skills.mcp';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\ntype ManyFactory<T, C> = (context: C) => T | readonly T[];\nconst many = <T, C>(value: T | readonly T[] | ManyFactory<T, C>, context: C): readonly T[] => {\n const resolved = typeof value === 'function' ? (value as ManyFactory<T, C>)(context) : value;\n return Array.isArray(resolved) ? resolved : [resolved as T];\n};\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nconst withWidget = <T>(key: string, value: T): T => value === undefined ? value : ({\n ...value, _meta: { ...(value as { _meta?: object })._meta, [\"po/widget\"]: key },\n});\n\nexport const mcp = defineMcpPlugin({\n name: '@agimon-ai/po-skill',\n session: (context) => ({\n get skills(): DoomMcpSessionPlugin['skills'] { return [...many(skillDiscovered, context), at(skillPoAuthorSkill, context), at(skillPoUseSkill, context)]; },\n get tools(): DoomMcpSessionPlugin['tools'] { return [withWidget(\"@agimon-ai/po-skill/load_skill\", via({ name: 'load_skill' }, at(toolLoadSkill, context))), withWidget(\"@agimon-ai/po-skill/search_skills\", via({ name: 'search_skills' }, at(toolSearchSkills, context)))]; },\n }) satisfies DoomMcpSessionPlugin,\n});\n\nexport default mcp;\n"],"mappings":"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"}