@agimon-ai/po-skill 0.0.0-alpha.13 → 0.0.0-alpha.15

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.
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  //#region src/schemas/apiContracts.ts
6
- /** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
6
+ /** This server plugin contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
7
7
  const apiContracts = (0, require("@agimon-ai/po-core/apiContracts").defineApiContract)({
8
8
  version: 1,
9
9
  http: [],
@@ -1 +1 @@
1
- {"version":3,"file":"apiContracts.cjs","names":["defineApiContract"],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract } from '@agimon-ai/po-core/apiContracts';\n\n/** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */\nexport const apiContracts = defineApiContract({ version: 1, http: [], sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":";;;;;;AAGA,MAAa,gBAAA,4CAAeA,CAAAA,CAAAA,kBAAAA,CAAkB;CAAE,SAAS;CAAG,MAAM,CAAC;CAAG,SAAS,CAAC;CAAG,SAAS,CAAC;AAAE,CAAC"}
1
+ {"version":3,"file":"apiContracts.cjs","names":["defineApiContract"],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract } from '@agimon-ai/po-core/apiContracts';\n\n/** This server plugin contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */\nexport const apiContracts = defineApiContract({ version: 1, http: [], sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":";;;;;;AAGA,MAAa,gBAAA,4CAAeA,CAAAA,CAAAA,kBAAAA,CAAkB;CAAE,SAAS;CAAG,MAAM,CAAC;CAAG,SAAS,CAAC;CAAG,SAAS,CAAC;AAAE,CAAC"}
@@ -1,5 +1,5 @@
1
1
  //#region src/schemas/apiContracts.d.ts
2
- /** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
2
+ /** This server plugin contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
3
3
  export declare const apiContracts: {
4
4
  version: 1;
5
5
  protocols?: Record<string, string> | undefined;
@@ -1,6 +1,6 @@
1
1
  import { defineApiContract } from "@agimon-ai/po-core/apiContracts";
2
2
  //#region src/schemas/apiContracts.ts
3
- /** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
3
+ /** This server plugin contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
4
4
  const apiContracts = defineApiContract({
5
5
  version: 1,
6
6
  http: [],
@@ -1 +1 @@
1
- {"version":3,"file":"apiContracts.mjs","names":[],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract } from '@agimon-ai/po-core/apiContracts';\n\n/** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */\nexport const apiContracts = defineApiContract({ version: 1, http: [], sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":";;;AAGA,MAAa,eAAe,kBAAkB;CAAE,SAAS;CAAG,MAAM,CAAC;CAAG,SAAS,CAAC;CAAG,SAAS,CAAC;AAAE,CAAC"}
1
+ {"version":3,"file":"apiContracts.mjs","names":[],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract } from '@agimon-ai/po-core/apiContracts';\n\n/** This server plugin contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */\nexport const apiContracts = defineApiContract({ version: 1, http: [], sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":";;;AAGA,MAAa,eAAe,kBAAkB;CAAE,SAAS;CAAG,MAAM,CAAC;CAAG,SAAS,CAAC;CAAG,SAAS,CAAC;AAAE,CAAC"}
@@ -5,7 +5,7 @@ Object.defineProperties(exports, {
5
5
  let _agimon_ai_po_core_mcpFacet = require("@agimon-ai/po-core/mcpFacet");
6
6
  let _agimon_ai_po_core_extensionFile = require("@agimon-ai/po-core/extensionFile");
7
7
  require("@agimon-ai/po-core/platform");
8
- let _agimon_ai_po_core_serverFacet = require("@agimon-ai/po-core/serverFacet");
8
+ let _agimon_ai_po_core_serverPlugin = require("@agimon-ai/po-core/serverPlugin");
9
9
  let typebox = require("typebox");
10
10
  //#region src/services/mcpSkills/index.ts
11
11
  const MCP_SKILLS_SERVICE = "po/discovered-mcp-skills";
@@ -22,14 +22,14 @@ var discovered_mcp_default = (0, _agimon_ai_po_core_extensionFile.defineRoutedCo
22
22
  var po_author_skill_mcp_default = (0, _agimon_ai_po_core_mcpFacet.defineMcpSkill)({
23
23
  name: "po-author-skill",
24
24
  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.",
25
- read: () => (0, _agimon_ai_po_core_serverFacet.readPackageResource)(require("url").pathToFileURL(__filename).href, "src/prompts/po-author-skill/SKILL.md")
25
+ read: () => (0, _agimon_ai_po_core_serverPlugin.readPackageResource)(require("url").pathToFileURL(__filename).href, "src/prompts/po-author-skill/SKILL.md")
26
26
  });
27
27
  //#endregion
28
28
  //#region src/extensions/workspaces/sessions/(backend)/skill/po-use-skill.mcp.ts
29
29
  var po_use_skill_mcp_default = (0, _agimon_ai_po_core_mcpFacet.defineMcpSkill)({
30
30
  name: "po-use-skill",
31
31
  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.",
32
- read: () => (0, _agimon_ai_po_core_serverFacet.readPackageResource)(require("url").pathToFileURL(__filename).href, "src/prompts/po-use-skill/SKILL.md")
32
+ read: () => (0, _agimon_ai_po_core_serverPlugin.readPackageResource)(require("url").pathToFileURL(__filename).href, "src/prompts/po-use-skill/SKILL.md")
33
33
  });
34
34
  //#endregion
35
35
  //#region src/schemas/mcpSkillTools.ts
@@ -1 +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 type { PoMcpPluginContext, PoMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport { BACKGROUND_CONTEXT, getOrThrow, withAbortSignal, type FileSystem } from '@agimon-ai/po-core/platform';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport type { ServerSkillGroup } from '../serverInventory';\n\nexport const MCP_SKILLS_SERVICE = 'po/discovered-mcp-skills';\n\nexport interface McpSkillProvider {\n list(context: PoMcpPluginContext): readonly PoMcpSkill[];\n}\n\n/** Explicit remote provider, never a projection of the local resource registry. */\nexport function mountMcpSkills(groups: readonly ServerSkillGroup[], fs: FileSystem, 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, PoMcpSkill>();\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 = getOrThrow(\n await fs.readTextFile(skill.filePath, withAbortSignal(readSignal, BACKGROUND_CONTEXT)),\n );\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: PoMcpPluginContext): readonly PoMcpSkill[] {\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 { PoHeadlessHostService, PoHeadlessTool } 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<PoHeadlessTool['execute']>[4]) {\n if (context.mcpSkills === undefined) throw new Error('Remote skill access is unavailable.');\n return context.mcpSkills;\n}\n\nexport function createSearchSkillsTool(): PoHeadlessTool<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<PoHeadlessHostService, 'readSkill'>,\n): PoHeadlessTool<typeof loadSkillParameters> {\n return {\n // web-plugin-tool-renderers: ignore load_skill (server session only, shown as a generic call)\n // PO_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(): PoHeadlessTool<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 PoMcpSessionPlugin } 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(): PoMcpSessionPlugin['skills'] { return [...many(skillDiscovered, context), at(skillPoAuthorSkill, context), at(skillPoUseSkill, context)]; },\n get tools(): PoMcpSessionPlugin['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 PoMcpSessionPlugin,\n});\n\nexport default mcp;\n"],"mappings":"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"}
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 type { PoMcpPluginContext, PoMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport { BACKGROUND_CONTEXT, getOrThrow, withAbortSignal, type FileSystem } from '@agimon-ai/po-core/platform';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport type { ServerSkillGroup } from '../serverInventory';\n\nexport const MCP_SKILLS_SERVICE = 'po/discovered-mcp-skills';\n\nexport interface McpSkillProvider {\n list(context: PoMcpPluginContext): readonly PoMcpSkill[];\n}\n\n/** Explicit remote provider, never a projection of the local resource registry. */\nexport function mountMcpSkills(groups: readonly ServerSkillGroup[], fs: FileSystem, 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, PoMcpSkill>();\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 = getOrThrow(\n await fs.readTextFile(skill.filePath, withAbortSignal(readSignal, BACKGROUND_CONTEXT)),\n );\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: PoMcpPluginContext): readonly PoMcpSkill[] {\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/serverPlugin';\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/serverPlugin';\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 { PoHeadlessHostService, PoHeadlessTool } 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<PoHeadlessTool['execute']>[4]) {\n if (context.mcpSkills === undefined) throw new Error('Remote skill access is unavailable.');\n return context.mcpSkills;\n}\n\nexport function createSearchSkillsTool(): PoHeadlessTool<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<PoHeadlessHostService, 'readSkill'>,\n): PoHeadlessTool<typeof loadSkillParameters> {\n return {\n // web-plugin-tool-renderers: ignore load_skill (server session only, shown as a generic call)\n // PO_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(): PoHeadlessTool<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 PoMcpSessionPlugin } 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(): PoMcpSessionPlugin['skills'] { return [...many(skillDiscovered, context), at(skillPoAuthorSkill, context), at(skillPoUseSkill, context)]; },\n get tools(): PoMcpSessionPlugin['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 PoMcpSessionPlugin,\n});\n\nexport default mcp;\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { defineMcpPlugin, defineMcpSkill, defineMcpTool } from "@agimon-ai/po-core/mcpFacet";
2
2
  import { defineRoutedContribution } from "@agimon-ai/po-core/extensionFile";
3
3
  import "@agimon-ai/po-core/platform";
4
- import { readPackageResource } from "@agimon-ai/po-core/serverFacet";
4
+ import { readPackageResource } from "@agimon-ai/po-core/serverPlugin";
5
5
  import { Type } from "typebox";
6
6
  //#region src/services/mcpSkills/index.ts
7
7
  const MCP_SKILLS_SERVICE = "po/discovered-mcp-skills";
@@ -1 +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 type { PoMcpPluginContext, PoMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport { BACKGROUND_CONTEXT, getOrThrow, withAbortSignal, type FileSystem } from '@agimon-ai/po-core/platform';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport type { ServerSkillGroup } from '../serverInventory';\n\nexport const MCP_SKILLS_SERVICE = 'po/discovered-mcp-skills';\n\nexport interface McpSkillProvider {\n list(context: PoMcpPluginContext): readonly PoMcpSkill[];\n}\n\n/** Explicit remote provider, never a projection of the local resource registry. */\nexport function mountMcpSkills(groups: readonly ServerSkillGroup[], fs: FileSystem, 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, PoMcpSkill>();\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 = getOrThrow(\n await fs.readTextFile(skill.filePath, withAbortSignal(readSignal, BACKGROUND_CONTEXT)),\n );\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: PoMcpPluginContext): readonly PoMcpSkill[] {\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 { PoHeadlessHostService, PoHeadlessTool } 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<PoHeadlessTool['execute']>[4]) {\n if (context.mcpSkills === undefined) throw new Error('Remote skill access is unavailable.');\n return context.mcpSkills;\n}\n\nexport function createSearchSkillsTool(): PoHeadlessTool<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<PoHeadlessHostService, 'readSkill'>,\n): PoHeadlessTool<typeof loadSkillParameters> {\n return {\n // web-plugin-tool-renderers: ignore load_skill (server session only, shown as a generic call)\n // PO_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(): PoHeadlessTool<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 PoMcpSessionPlugin } 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(): PoMcpSessionPlugin['skills'] { return [...many(skillDiscovered, context), at(skillPoAuthorSkill, context), at(skillPoUseSkill, context)]; },\n get tools(): PoMcpSessionPlugin['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 PoMcpSessionPlugin,\n});\n\nexport default mcp;\n"],"mappings":"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"}
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 type { PoMcpPluginContext, PoMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport { BACKGROUND_CONTEXT, getOrThrow, withAbortSignal, type FileSystem } from '@agimon-ai/po-core/platform';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport type { ServerSkillGroup } from '../serverInventory';\n\nexport const MCP_SKILLS_SERVICE = 'po/discovered-mcp-skills';\n\nexport interface McpSkillProvider {\n list(context: PoMcpPluginContext): readonly PoMcpSkill[];\n}\n\n/** Explicit remote provider, never a projection of the local resource registry. */\nexport function mountMcpSkills(groups: readonly ServerSkillGroup[], fs: FileSystem, 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, PoMcpSkill>();\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 = getOrThrow(\n await fs.readTextFile(skill.filePath, withAbortSignal(readSignal, BACKGROUND_CONTEXT)),\n );\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: PoMcpPluginContext): readonly PoMcpSkill[] {\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/serverPlugin';\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/serverPlugin';\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 { PoHeadlessHostService, PoHeadlessTool } 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<PoHeadlessTool['execute']>[4]) {\n if (context.mcpSkills === undefined) throw new Error('Remote skill access is unavailable.');\n return context.mcpSkills;\n}\n\nexport function createSearchSkillsTool(): PoHeadlessTool<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<PoHeadlessHostService, 'readSkill'>,\n): PoHeadlessTool<typeof loadSkillParameters> {\n return {\n // web-plugin-tool-renderers: ignore load_skill (server session only, shown as a generic call)\n // PO_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(): PoHeadlessTool<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 PoMcpSessionPlugin } 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(): PoMcpSessionPlugin['skills'] { return [...many(skillDiscovered, context), at(skillPoAuthorSkill, context), at(skillPoUseSkill, context)]; },\n get tools(): PoMcpSessionPlugin['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 PoMcpSessionPlugin,\n});\n\nexport default mcp;\n"],"mappings":"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"}
@@ -10,15 +10,23 @@ let _agimon_ai_po_config_domains = require("@agimon-ai/po-config/domains");
10
10
  let _agimon_ai_po_core_platform = require("@agimon-ai/po-core/platform");
11
11
  let _agimon_ai_po_domain_plugins = require("@agimon-ai/po-domain/plugins");
12
12
  let _earendil_works_pi_coding_agent = require("@earendil-works/pi-coding-agent");
13
- let _agimon_ai_po_core_serverFacet = require("@agimon-ai/po-core/serverFacet");
13
+ let _agimon_ai_po_core_serverPlugin = require("@agimon-ai/po-core/serverPlugin");
14
14
  let _agimon_ai_po_core_extensionFile = require("@agimon-ai/po-core/extensionFile");
15
- let typebox = require("typebox");
16
15
  let _agimon_ai_po_config_harnessState = require("@agimon-ai/po-config/harnessState");
16
+ let typebox = require("typebox");
17
17
  let _agimon_ai_po_domain_resources = require("@agimon-ai/po-domain/resources");
18
18
  let node_fs = require("node:fs");
19
19
  node_fs = require_rolldown_runtime.__toESM(node_fs, 1);
20
20
  let node_url = require("node:url");
21
21
  let node_worker_threads = require("node:worker_threads");
22
+ //#region src/constants/skillInventory.ts
23
+ /**
24
+ * How long sessions with the same inputs share one skill inventory instead of each reading the disk.
25
+ * ponytail: a skill added on disk reaches new sessions within this window, not at once; watch the
26
+ * skill roots if that lag matters.
27
+ */
28
+ const SKILL_INVENTORY_FRESH_MS = 6e4;
29
+ //#endregion
22
30
  //#region src/services/mcpSkills/index.ts
23
31
  const MCP_SKILLS_SERVICE = "po/discovered-mcp-skills";
24
32
  /** Explicit remote provider, never a projection of the local resource registry. */
@@ -85,6 +93,7 @@ function createSessionLoadSkillTool(host) {
85
93
  //#region src/services/deferredSkills/index.ts
86
94
  const PI_PACKAGE = "@earendil-works/pi-coding-agent";
87
95
  const PACKAGE_MANIFEST = "package.json";
96
+ const PI_SKILLS_MODULE = node_path.default.join("dist", "core", "skills.js");
88
97
  const SKILL_WORKER_SOURCE = `
89
98
  const { parentPort, workerData } = require('node:worker_threads');
90
99
  void (async () => {
@@ -112,6 +121,8 @@ function installedPiModuleUrl() {
112
121
  const manifest = JSON.parse(node_fs.default.readFileSync(manifestPath, "utf8"));
113
122
  if (typeof manifest.main === "string") {
114
123
  const entry = node_path.default.resolve(packageRoot, manifest.main);
124
+ const skills = node_path.default.join(packageRoot, PI_SKILLS_MODULE);
125
+ if (node_fs.default.existsSync(skills)) return (0, node_url.pathToFileURL)(skills).href;
115
126
  if (node_fs.default.existsSync(entry)) return (0, node_url.pathToFileURL)(entry).href;
116
127
  }
117
128
  } catch {}
@@ -281,7 +292,7 @@ function within(filePath, roots) {
281
292
  * Every skill the session could reach, grouped by what activates it.
282
293
  *
283
294
  * A cockpit `/domains` switch reconciles contributions rather than rebuilding
284
- * the facet: the session declaration is mounted once. So enumerating only the
295
+ * the server plugin: the session declaration is mounted once. So enumerating only the
285
296
  * launch selection would freeze the command list at whatever was selected when
286
297
  * the session host was built. Enumerating every domain up front and tagging
287
298
  * each group with its `when` lets the existing kernel refresh do the work, the
@@ -417,8 +428,17 @@ function createSkillCommands(inventory, catalog, groups) {
417
428
  }
418
429
  //#endregion
419
430
  //#region src/extensions/workspaces/sessions/(backend)/_lib/skillServer.ts
420
- async function createSkillServer(agent, fs, signal) {
421
- const { inventory, catalog, groups, mcpGroups, listed } = await discoverServerSkills(agent.context, fs, signal);
431
+ async function createSkillServer(agent, fs, signal, resources) {
432
+ const execution = agent.context;
433
+ const key = [
434
+ "inventory",
435
+ execution.repoRoot,
436
+ execution.cwd,
437
+ execution.environment.HOME ?? _agimon_ai_po_core_platform.nodeHost.homeDirectory(),
438
+ ...(0, _agimon_ai_po_config_harnessState.readHarnessState)(execution.environment).skillDirectories ?? [],
439
+ Math.floor(Date.now() / SKILL_INVENTORY_FRESH_MS)
440
+ ];
441
+ const { inventory, catalog, groups, mcpGroups, listed } = await resources.acquire(key, () => discoverServerSkills(execution, fs, new AbortController().signal));
422
442
  return {
423
443
  commands: createSkillCommands(inventory, catalog, groups),
424
444
  tools: [createSessionLoadSkillTool(agent)],
@@ -452,15 +472,15 @@ async function createSkillServer(agent, fs, signal) {
452
472
  }
453
473
  },
454
474
  kind: "skill",
455
- path: (0, _agimon_ai_po_core_serverFacet.packageResourcePath)(require("url").pathToFileURL(__filename).href, `src/prompts/${skill.name}/SKILL.md`),
456
- read: () => (0, _agimon_ai_po_core_serverFacet.readPackageResource)(require("url").pathToFileURL(__filename).href, `src/prompts/${skill.name}/SKILL.md`)
475
+ path: (0, _agimon_ai_po_core_serverPlugin.packageResourcePath)(require("url").pathToFileURL(__filename).href, `src/prompts/${skill.name}/SKILL.md`),
476
+ read: () => (0, _agimon_ai_po_core_serverPlugin.readPackageResource)(require("url").pathToFileURL(__filename).href, `src/prompts/${skill.name}/SKILL.md`)
457
477
  }))]
458
478
  };
459
479
  }
460
480
  //#endregion
461
481
  //#region src/extensions/workspaces/sessions/(backend)/root.server.ts
462
- var root_server_default = (0, _agimon_ai_po_core_extensionFile.defineRoot)(async ({ agent, context: root, signal }) => {
463
- const runtime = agent ? await createSkillServer(agent, (0, _agimon_ai_po_core_platform.requirePoFs)(root), signal) : {
482
+ var root_server_default = (0, _agimon_ai_po_core_extensionFile.defineRoot)(async ({ agent, context: root, signal, resources }) => {
483
+ const runtime = agent ? await createSkillServer(agent, (0, _agimon_ai_po_core_platform.requirePoFs)(root), signal, resources) : {
464
484
  commands: [],
465
485
  resources: []
466
486
  };
@@ -492,11 +512,12 @@ const via = (identity, value) => value === void 0 ? void 0 : {
492
512
  ...identity,
493
513
  ...value
494
514
  };
495
- const facet = (0, _agimon_ai_po_core_serverFacet.defineServerPlugin)({
515
+ const serverPlugin = (0, _agimon_ai_po_core_serverPlugin.defineServerPlugin)({
496
516
  name: "@agimon-ai/po-skill",
497
- providerOverrides: (0, _agimon_ai_po_core_serverFacet.composeServerProviderOverrides)(root_server_default),
517
+ providerOverrides: (0, _agimon_ai_po_core_serverPlugin.composeServerProviderOverrides)(root_server_default),
518
+ injects: (0, _agimon_ai_po_core_extensionFile.composeRootInjects)({ session: [root_server_default] }),
498
519
  session: async (context) => {
499
- const scopeSession = await root_server_default(context);
520
+ const scopeSession = await context.scopeRoot("session", root_server_default, context);
500
521
  const contextSession = {
501
522
  ...context,
502
523
  root: scopeSession.value
@@ -520,7 +541,7 @@ const facet = (0, _agimon_ai_po_core_serverFacet.defineServerPlugin)({
520
541
  }
521
542
  });
522
543
  //#endregion
523
- exports.default = facet;
524
- exports.facet = facet;
544
+ exports.default = serverPlugin;
545
+ exports.serverPlugin = serverPlugin;
525
546
 
526
547
  //# sourceMappingURL=server.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.cjs","names":["getOrThrow","withAbortSignal","BACKGROUND_CONTEXT","Type","fileURLToPath","path","fs","pathToFileURL","getAgentDir","loadSkills","Worker","stripFrontmatter","path","withAbortSignal","BACKGROUND_CONTEXT","readHarnessState","nodeHost","listDomainNamesAsync","materializePluginEntries","resolvePluginEntriesAsync","collectResources","discoverSkillsAsync","resolveSharedSkillsAsync","formatSkillsForPrompt","SKILL_COMMAND_PREFIX","SKILL_INVOCATION_PREFIX","SKILLS_COMMAND","getOrThrow","BACKGROUND_CONTEXT","packageResourcePath","readPackageResource","defineRoot","requirePoFs","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineServerPlugin","composeServerProviderOverrides","rootSession","composeRootHooks","commandSkills","resourceSkills","toolLoadSkill"],"sources":["../../src/services/mcpSkills/index.ts","../../src/schemas/mcpSkillTools.ts","../../src/services/mcpSkillTools/index.ts","../../src/services/deferredSkills/index.ts","../../src/services/serverInventory/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/skillCommands.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/skillServer.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/skills.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/skills.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/load_skill.server.ts","../../generated/server.ts"],"sourcesContent":["import type { PoMcpPluginContext, PoMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport { BACKGROUND_CONTEXT, getOrThrow, withAbortSignal, type FileSystem } from '@agimon-ai/po-core/platform';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport type { ServerSkillGroup } from '../serverInventory';\n\nexport const MCP_SKILLS_SERVICE = 'po/discovered-mcp-skills';\n\nexport interface McpSkillProvider {\n list(context: PoMcpPluginContext): readonly PoMcpSkill[];\n}\n\n/** Explicit remote provider, never a projection of the local resource registry. */\nexport function mountMcpSkills(groups: readonly ServerSkillGroup[], fs: FileSystem, 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, PoMcpSkill>();\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 = getOrThrow(\n await fs.readTextFile(skill.filePath, withAbortSignal(readSignal, BACKGROUND_CONTEXT)),\n );\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: PoMcpPluginContext): readonly PoMcpSkill[] {\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 { 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 { PoHeadlessHostService, PoHeadlessTool } 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<PoHeadlessTool['execute']>[4]) {\n if (context.mcpSkills === undefined) throw new Error('Remote skill access is unavailable.');\n return context.mcpSkills;\n}\n\nexport function createSearchSkillsTool(): PoHeadlessTool<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<PoHeadlessHostService, 'readSkill'>,\n): PoHeadlessTool<typeof loadSkillParameters> {\n return {\n // web-plugin-tool-renderers: ignore load_skill (server session only, shown as a generic call)\n // PO_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(): PoHeadlessTool<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 fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { Worker } from 'node:worker_threads';\n\nimport {\n type BuildSystemPromptOptions,\n formatSkillsForPrompt,\n getAgentDir,\n loadSkills,\n type Skill,\n stripFrontmatter,\n} from '@earendil-works/pi-coding-agent';\n\nimport type { DeferredSkillLoaderOptions, DeferredSkillSnapshot } from '../../types/skills';\n\nexport type { DeferredSkillLoaderOptions, DeferredSkillSnapshot } from '../../types/skills';\n\nconst PI_PACKAGE = '@earendil-works/pi-coding-agent';\nconst PACKAGE_MANIFEST = 'package.json';\nconst SKILL_WORKER_SOURCE = `\nconst { parentPort, workerData } = require('node:worker_threads');\nvoid (async () => {\n try {\n const { loadSkills } = await import(workerData.piModuleUrl);\n parentPort.postMessage({ ok: true, result: loadSkills(workerData.loadOptions) });\n } catch (error) {\n parentPort.postMessage({ ok: false, error: error instanceof Error ? error.message : String(error) });\n }\n})();\n`;\n\nfunction installedPiModuleUrl(): string {\n const anchors = [process.argv[1], fileURLToPath(import.meta.url), path.join(process.cwd(), PACKAGE_MANIFEST)];\n for (const anchor of anchors) {\n if (!anchor) continue;\n let directory = path.dirname(path.resolve(anchor));\n while (true) {\n const packageRoot = path.join(directory, 'node_modules', PI_PACKAGE);\n const manifestPath = path.join(packageRoot, PACKAGE_MANIFEST);\n try {\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as { main?: unknown };\n if (typeof manifest.main === 'string') {\n const entry = path.resolve(packageRoot, manifest.main);\n if (fs.existsSync(entry)) return pathToFileURL(entry).href;\n }\n } catch {\n // This anchor does not expose Pi at this level; continue up its module chain.\n }\n const parent = path.dirname(directory);\n if (parent === directory) break;\n directory = parent;\n }\n }\n throw new Error(`Cannot resolve ${PI_PACKAGE} from the Po or host module trees`);\n}\n\ninterface SkillWorkerResult {\n ok: boolean;\n result?: { skills: Skill[]; diagnostics: Array<{ path?: string; message: string }> };\n error?: string;\n}\n\n/**\n * One session's Po-selected skill inventory.\n *\n * Construction is deliberately cheap. `start()` schedules the synchronous Pi\n * walker after session_start returns, while `ready()` is the single promise the\n * first input awaits before Pi expands `/skill:name`.\n */\nexport class DeferredSkillLoader {\n readonly #options: DeferredSkillLoaderOptions;\n #promise: Promise<DeferredSkillSnapshot> | undefined;\n\n constructor(options: DeferredSkillLoaderOptions) {\n this.#options = options;\n }\n\n start(): Promise<DeferredSkillSnapshot> {\n if (this.#promise) return this.#promise;\n\n if (!this.#options.schedule && !this.#options.load) {\n this.#promise = this.#loadInWorker();\n return this.#promise;\n }\n\n const schedule = this.#options.schedule ?? ((load: () => void) => setImmediate(load));\n this.#promise = new Promise((resolve) => {\n const fail = (error: unknown): void => {\n resolve(this.#failure(error));\n };\n try {\n schedule(() => {\n try {\n resolve(this.#load());\n } catch (error) {\n fail(error);\n }\n });\n } catch (error) {\n fail(error);\n }\n });\n return this.#promise;\n }\n\n ready(): Promise<DeferredSkillSnapshot> {\n return this.start();\n }\n\n #loadOptions(): { cwd: string; agentDir: string; skillPaths: string[]; includeDefaults: boolean } {\n return {\n cwd: this.#options.cwd,\n agentDir: this.#options.agentDir ?? getAgentDir(),\n skillPaths: [...this.#options.skillPaths],\n includeDefaults: false,\n };\n }\n\n #snapshot(result: {\n skills: Skill[];\n diagnostics: Array<{ path?: string; message: string }>;\n }): DeferredSkillSnapshot {\n return {\n skills: result.skills,\n diagnostics: result.diagnostics.map(\n (diagnostic) => `${diagnostic.path ?? this.#options.cwd}: ${diagnostic.message}`,\n ),\n };\n }\n\n #failure(error: unknown): DeferredSkillSnapshot {\n return {\n skills: [],\n diagnostics: [`${this.#options.cwd}: ${error instanceof Error ? error.message : String(error)}`],\n };\n }\n\n #load(): DeferredSkillSnapshot {\n return this.#snapshot((this.#options.load ?? loadSkills)(this.#loadOptions()));\n }\n\n #loadInWorker(): Promise<DeferredSkillSnapshot> {\n return new Promise((resolve) => {\n let settled = false;\n const settle = (snapshot: DeferredSkillSnapshot): void => {\n if (settled) return;\n settled = true;\n resolve(snapshot);\n };\n let worker: Worker;\n try {\n worker = new Worker(SKILL_WORKER_SOURCE, {\n eval: true,\n workerData: {\n piModuleUrl: this.#options.piModuleUrl ?? installedPiModuleUrl(),\n loadOptions: this.#loadOptions(),\n },\n });\n } catch (error) {\n settle(this.#failure(error));\n return;\n }\n worker.unref();\n worker.once('message', (message: SkillWorkerResult) => {\n if (!message.ok || !message.result) {\n settle(this.#failure(message.error ?? 'Skill worker failed'));\n return;\n }\n settle(this.#snapshot(message.result));\n });\n worker.once('error', (error) => settle(this.#failure(error)));\n worker.once('exit', (code) => {\n if (code !== 0) settle(this.#failure(`Skill worker exited with code ${code}`));\n });\n });\n }\n}\n\n/** Appends only the inventory Pi would append for these deferred skills. */\nexport function buildPromptWithDeferredSkills(\n systemPrompt: string,\n options: BuildSystemPromptOptions,\n skills: Skill[],\n): string {\n if (options.selectedTools && !options.selectedTools.includes('read')) return systemPrompt;\n return `${systemPrompt}${formatSkillsForPrompt(skills)}`;\n}\n\n/** Expands a deferred `/skill:name` before Pi consults its synchronous inventory. */\nexport function expandDeferredSkillCommand(text: string, skills: readonly Skill[]): string {\n if (!text.startsWith('/skill:')) return text;\n const spaceIndex = text.indexOf(' ');\n const skillName = spaceIndex === -1 ? text.slice(7) : text.slice(7, spaceIndex);\n const skill = skills.find((candidate) => candidate.name === skillName);\n if (!skill) return text;\n\n try {\n const args = spaceIndex === -1 ? '' : text.slice(spaceIndex + 1).trim();\n const body = stripFrontmatter(fs.readFileSync(skill.filePath, 'utf8')).trim();\n const skillBlock = `<skill name=\"${skill.name}\" location=\"${skill.filePath}\">\\nReferences are relative to ${skill.baseDir}.\\n\\n${body}\\n</skill>`;\n return args ? `${skillBlock}\\n\\n${args}` : skillBlock;\n } catch {\n // Pi uses the same literal-text fallback if a skill disappears between\n // discovery and submission; the agent can still respond to the command.\n return text;\n }\n}\n","import path from 'node:path';\n\nimport {\n listDomainNamesAsync,\n resolvePluginEntriesAsync,\n resolveSharedSkillsAsync,\n type PluginEntry,\n} from '@agimon-ai/po-config/domains';\nimport { readHarnessState } from '@agimon-ai/po-config/harnessState';\nimport type { PoHeadlessExecutionContext } from '@agimon-ai/po-core/headless';\nimport { BACKGROUND_CONTEXT, nodeHost, withAbortSignal, type FileSystem } from '@agimon-ai/po-core/platform';\nimport { materializePluginEntries } from '@agimon-ai/po-domain/plugins';\nimport { collectResources, discoverSkillsAsync } from '@agimon-ai/po-domain/resources';\nimport { formatSkillsForPrompt } from '@earendil-works/pi-coding-agent';\n\nimport type { ServerSkillInventory } from '../../types/skills';\nimport { DeferredSkillLoader } from '../deferredSkills';\n\nexport type { ServerSkillGroup, ServerSkillInventory } from '../../types/skills';\n\ninterface SkillSource {\n readonly domain?: string;\n readonly paths: readonly string[];\n readonly mcpPaths: readonly string[];\n /** Advertised by this package rather than by po-domain. */\n readonly listed?: boolean;\n}\n\nconst LOCAL_ONLY_MCP_PACKAGES = new Set([\n '@agimon-ai/po-author',\n '@agimon-ai/po-git',\n '@agimon-ai/po-goal',\n '@agimon-ai/po-help',\n '@agimon-ai/po-loop',\n '@agimon-ai/po-user-feedback',\n '@agimon-ai/po-voice',\n '@agimon-ai/po-workflow',\n]);\n\ntype IoContext = Parameters<FileSystem['readTextFile']>[1];\n\nasync function isMcpSkillPlugin(fs: FileSystem, entry: PluginEntry, context: IoContext): Promise<boolean> {\n if (entry.source?.type === 'npm') return !LOCAL_ONLY_MCP_PACKAGES.has(entry.source.package);\n // A package manifest is optional for catalog plugins, but a present identity\n // that cannot be read or parsed must never make the plugin remotely eligible.\n const source = await fs.readTextFile(path.join(entry.directory, 'package.json'), context);\n if (!source.ok) return source.error.code === 'not_found';\n try {\n const manifest = JSON.parse(source.value) as unknown;\n if (typeof manifest !== 'object' || manifest === null || Array.isArray(manifest)) return false;\n const name = (manifest as { name?: unknown }).name;\n return typeof name === 'string' && name.length > 0 && name.trim() === name && !LOCAL_ONLY_MCP_PACKAGES.has(name);\n } catch {\n return false;\n }\n}\n\n/**\n * Whether a discovered skill came from one of these paths.\n *\n * A source holds exact SKILL.md files for plugin and shared skills, but a bare\n * directory for `.po/skills`, so membership is containment rather than\n * equality.\n */\nfunction within(filePath: string, roots: readonly string[]): boolean {\n const resolved = path.resolve(filePath);\n return roots.some((root) => {\n const base = path.resolve(root);\n return resolved === base || resolved.startsWith(`${base}${path.sep}`);\n });\n}\n/**\n * Every skill the session could reach, grouped by what activates it.\n *\n * A cockpit `/domains` switch reconciles contributions rather than rebuilding\n * the facet: the session declaration is mounted once. So enumerating only the\n * launch selection would freeze the command list at whatever was selected when\n * the session host was built. Enumerating every domain up front and tagging\n * each group with its `when` lets the existing kernel refresh do the work, the\n * same way domainServerResources registers per-domain skill resources.\n */\nexport async function discoverServerSkills(\n execution: PoHeadlessExecutionContext,\n fs: FileSystem,\n signal: AbortSignal,\n): Promise<ServerSkillInventory> {\n signal.throwIfAborted();\n const context = withAbortSignal(signal, BACKGROUND_CONTEXT);\n const state = readHarnessState(execution.environment);\n const home = execution.environment.HOME ?? nodeHost.homeDirectory();\n const repoSkills = path.join(execution.repoRoot, '.po', 'skills');\n const sources: SkillSource[] = [];\n const diagnostics: string[] = [];\n // A malformed domain is a configuration error in one domain, so it must not\n // remove every other domain's skills. Enumerating the whole manifest is new\n // exposure here: reading the launch selection could not fail this way.\n const domains: string[] = [];\n try {\n domains.push(...(await listDomainNamesAsync(fs, execution.repoRoot, context, home)));\n } catch (error) {\n diagnostics.push(`Domain skills are unavailable: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n // Domain-scoped plugin skills come first. The host keeps the first command\n // registered for a name, so this ordering reproduces the collector's rule\n // that a selected plugin outranks a shared fallback of the same name.\n for (const domain of domains) {\n signal.throwIfAborted();\n try {\n const plugins = await materializePluginEntries(\n await resolvePluginEntriesAsync(fs, execution.repoRoot, [domain], [], context, home),\n );\n const mcpPluginRoots = (\n await Promise.all(\n plugins.map(async (plugin) =>\n (await isMcpSkillPlugin(fs, plugin, context)) ? path.join(plugin.directory, 'skills') : undefined,\n ),\n )\n ).filter((root): root is string => root !== undefined);\n const collected = await collectResources(execution.repoRoot, plugins, {\n agents: false,\n mcp: false,\n sharedSkills: false,\n });\n try {\n if (collected.skillDirectories.length > 0) {\n const paths = [...collected.skillDirectories];\n sources.push({\n domain,\n paths,\n // Exact collected paths retain this domain's per-plugin skill subset.\n // A plugin root would also admit skills loaded for another domain.\n mcpPaths: paths.filter((skillPath) => within(skillPath, mcpPluginRoots)),\n });\n }\n } finally {\n await collected.cleanup();\n }\n } catch (error) {\n diagnostics.push(`Domain '${domain}': ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n // Shared .claude/skills are not owned by any one domain, and a domain can opt\n // out of them. `when` cannot express \"unless every selected domain opts out\",\n // but registering a copy per domain that keeps them says the same thing: the\n // group is active if any such domain is selected, which is exactly what\n // resolveSharedSkills computes.\n signal.throwIfAborted();\n const shared = await discoverSkillsAsync(execution.repoRoot, path.join(execution.repoRoot, '.claude', 'skills'));\n if (shared.length > 0) {\n const sharedPaths = shared.map((skill) => skill.path);\n for (const domain of domains) {\n if (await resolveSharedSkillsAsync(fs, execution.repoRoot, [domain], context, home)) {\n sources.push({ domain, paths: sharedPaths, mcpPaths: sharedPaths, listed: true });\n }\n }\n }\n\n // Repository-local skills belong to the repository, not to a selection.\n sources.push({ paths: [repoSkills], mcpPaths: [repoSkills], listed: true });\n\n signal.throwIfAborted();\n // One walk for every group. Pi drops a path it has already loaded, so the\n // loader gets the unique set and each group selects its own skills back out.\n const unique = [...new Set([...sources.flatMap((source) => source.paths), ...(state.skillDirectories ?? [])])];\n const inventory = await new DeferredSkillLoader({ cwd: execution.cwd, skillPaths: unique }).ready();\n signal.throwIfAborted();\n\n const groups = sources\n .map((source) => ({\n ...(source.domain === undefined ? {} : { domain: source.domain }),\n skills: inventory.skills.filter((skill) => within(skill.filePath, source.paths)),\n }))\n .filter((group) => group.skills.length > 0);\n const listed = sources\n .filter((source) => source.listed === true)\n .map((source) => ({\n ...(source.domain === undefined ? {} : { domain: source.domain }),\n skills: inventory.skills.filter((skill) => within(skill.filePath, source.paths)),\n }))\n .filter((group) => group.skills.length > 0);\n const mcpGroups = sources\n .map((source) => ({\n ...(source.domain === undefined ? {} : { domain: source.domain }),\n skills: inventory.skills.filter((skill) => within(skill.filePath, source.mcpPaths)),\n }))\n .filter((group) => group.skills.length > 0);\n\n // The catalog still describes the active selection rather than everything on\n // disk, because it is prompt text rather than a menu.\n const activeSkills = inventory.skills.filter((skill) =>\n within(skill.filePath, [...(state.skillDirectories ?? []), repoSkills]),\n );\n return {\n inventory: { skills: inventory.skills, diagnostics: [...inventory.diagnostics, ...diagnostics] },\n groups,\n mcpGroups,\n listed,\n catalog: formatSkillsForPrompt(activeSkills) || '(no discovered skills)',\n };\n}\n","import type { PoHeadlessCommand } from '@agimon-ai/po-core/headless';\nimport type { Skill } from '@earendil-works/pi-coding-agent';\n\nimport { expandDeferredSkillCommand, type DeferredSkillSnapshot } from '../../../../../services/deferredSkills';\nimport type { ServerSkillGroup } from '../../../../../services/serverInventory';\nimport { SKILL_COMMAND_PREFIX, SKILL_INVOCATION_PREFIX, SKILLS_COMMAND } from '../../../../../types/skills';\n\n/**\n * One command per skill, gated by whatever activates that skill.\n *\n * Expansion always reads the full inventory, not the group: a command is only\n * dispatchable while its condition holds, so by the time one runs its skill is\n * active, and looking it up in the union keeps one lookup table instead of one\n * per domain.\n */\nfunction skillCommand(skill: Skill, domain: string | undefined, inventory: DeferredSkillSnapshot): PoHeadlessCommand {\n return {\n ...(domain === undefined ? {} : { when: { domain } }),\n name: `${SKILL_COMMAND_PREFIX}${skill.name}`,\n description: skill.description,\n execute: async (args, execution) => {\n const text = `${SKILL_INVOCATION_PREFIX}${skill.name}${args ? ` ${args}` : ''}`;\n const expanded = expandDeferredSkillCommand(text, inventory.skills);\n if (expanded === text) throw new Error(`Skill '${skill.name}' is no longer readable.`);\n await execution.session.prompt(expanded);\n },\n };\n}\n\nexport function createSkillCommands(\n inventory: DeferredSkillSnapshot,\n catalog: string,\n groups: readonly ServerSkillGroup[],\n): readonly PoHeadlessCommand[] {\n return [\n {\n name: SKILLS_COMMAND,\n description: 'List discovered skills or invoke one by name.',\n async execute(args, execution) {\n const requested = args.trim();\n if (requested) {\n await execution.session.prompt(\n expandDeferredSkillCommand(`${SKILL_INVOCATION_PREFIX}${requested}`, inventory.skills),\n );\n return;\n }\n await execution.client.notify({\n title: 'Po skills',\n body: catalog,\n level: 'info',\n });\n },\n },\n ...groups.flatMap((group) => group.skills.map((skill) => skillCommand(skill, group.domain, inventory))),\n ];\n}\n","import type { PoHeadlessHostService } from '@agimon-ai/po-core/headless';\nimport { BACKGROUND_CONTEXT, getOrThrow, type FileSystem } from '@agimon-ai/po-core/platform';\nimport { type PoServerSessionPlugin, packageResourcePath, readPackageResource } from '@agimon-ai/po-core/serverFacet';\n\nimport { mountMcpSkills } from '../../../../../services/mcpSkills';\nimport { createSessionLoadSkillTool } from '../../../../../services/mcpSkillTools';\nimport { discoverServerSkills } from '../../../../../services/serverInventory';\nimport { createSkillCommands } from './skillCommands';\n\nexport async function createSkillServer(\n agent: PoHeadlessHostService,\n fs: FileSystem,\n signal: AbortSignal,\n): Promise<PoServerSessionPlugin> {\n const { inventory, catalog, groups, mcpGroups, listed } = await discoverServerSkills(agent.context, fs, signal);\n return {\n commands: createSkillCommands(inventory, catalog, groups),\n tools: [createSessionLoadSkillTool(agent)],\n services: [mountMcpSkills(mcpGroups, fs, signal)],\n resources: [\n // Each skill joins the prompt's one <available_skills> list, gated like the rest.\n ...listed.flatMap((group) =>\n group.skills.map((skill) => ({\n name: skill.name,\n description: skill.description,\n path: skill.filePath,\n kind: 'skill' as const,\n ...(group.domain === undefined\n ? {}\n : { when: { domain: group.domain, attribution: { kind: 'domain' as const, mode: group.domain } } }),\n read: async () => getOrThrow(await fs.readTextFile(skill.filePath, BACKGROUND_CONTEXT)),\n })),\n ),\n ...[\n {\n name: 'po-author-skill',\n description:\n 'Author and distribute Po agent skills. Use when creating a SKILL.md, contributing a runtime skill directory, or publishing activation-gated Help prompts and diagnostic tools.',\n },\n {\n name: 'po-use-skill',\n description:\n \"Use Po's skill catalog and deferred discovery. Diagnose missing or shadowed skills and invoke the narrowest available guidance.\",\n },\n ].map((skill) => ({\n ...skill,\n when: { state: { 'minor-mode': 'help' }, attribution: { kind: 'minor' as const, mode: 'help' } },\n kind: 'skill' as const,\n path: packageResourcePath(import.meta.url, `src/prompts/${skill.name}/SKILL.md`),\n read: () => readPackageResource(import.meta.url, `src/prompts/${skill.name}/SKILL.md`),\n })),\n ],\n };\n}\n","import { defineRoot } from '@agimon-ai/po-core/extensionFile';\nimport { requirePoFs } from '@agimon-ai/po-core/platform';\nimport type { PoServerPluginContext, PoServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\n\nimport { createSkillServer } from './_lib/skillServer';\n\nexport default defineRoot(async ({ agent, context: root, signal }: PoServerPluginContext) => {\n const runtime: PoServerSessionPlugin = agent\n ? await createSkillServer(agent, requirePoFs(root), signal)\n : { commands: [], resources: [] };\n return { value: runtime, services: runtime.services };\n});\n","import { defineRoutedContribution } from '@agimon-ai/po-core/extensionFile';\nimport type { WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { PoServerPluginContext, PoServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\n\nexport default defineRoutedContribution(\n (context: WithRoot<PoServerPluginContext, PoServerSessionPlugin>) => context.root.commands!,\n { cardinality: 'many' },\n);\n","import { defineRoutedContribution } from '@agimon-ai/po-core/extensionFile';\nimport type { WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { PoServerPluginContext, PoServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\n\nexport default defineRoutedContribution(\n (context: WithRoot<PoServerPluginContext, PoServerSessionPlugin>) => context.root.resources!,\n { cardinality: 'many' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { PoServerPluginContext, PoServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\n\n/** The session agent's skill loader; the Pi CLI keeps Pi's own skill handling. */\nexport default defineRoutedContribution(\n (context: WithRoot<PoServerPluginContext, PoServerSessionPlugin>) => context.root.tools?.[0],\n { cardinality: 'optional' },\n);\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineServerPlugin, type PoServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\nimport { composeServerProviderOverrides } from '@agimon-ai/po-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/po-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport commandSkills from '../src/extensions/workspaces/sessions/(backend)/command/skills.server';\nimport resourceSkills from '../src/extensions/workspaces/sessions/(backend)/resource/skills.server';\nimport toolLoadSkill from '../src/extensions/workspaces/sessions/(backend)/tool/load_skill.server';\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};\n/* v8 ignore next -- generated normalization branch */\nconst defined = <T>(values: readonly (T | undefined)[]): T[] =>\n values.filter((value): value is T => value !== undefined);\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/po-skill',\n providerOverrides: composeServerProviderOverrides(rootSession),\n session: async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get commands(): PoServerSessionPlugin['commands'] { return [...many(commandSkills, contextSession)]; },\n get resources(): PoServerSessionPlugin['resources'] { return [...many(resourceSkills, contextSession)]; },\n get tools(): PoServerSessionPlugin['tools'] { return defined([via({ name: 'load_skill' }, at(toolLoadSkill, contextSession))]); },\n services: [...(scopeSession.services ?? [])],\n get activities(): PoServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":"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"}
1
+ {"version":3,"file":"server.cjs","names":["getOrThrow","withAbortSignal","BACKGROUND_CONTEXT","Type","path","fileURLToPath","fs","pathToFileURL","getAgentDir","loadSkills","Worker","stripFrontmatter","path","withAbortSignal","BACKGROUND_CONTEXT","readHarnessState","nodeHost","listDomainNamesAsync","materializePluginEntries","resolvePluginEntriesAsync","collectResources","discoverSkillsAsync","resolveSharedSkillsAsync","formatSkillsForPrompt","SKILL_COMMAND_PREFIX","SKILL_INVOCATION_PREFIX","SKILLS_COMMAND","nodeHost","readHarnessState","getOrThrow","BACKGROUND_CONTEXT","packageResourcePath","readPackageResource","defineRoot","requirePoFs","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineServerPlugin","composeServerProviderOverrides","rootSession","composeRootInjects","composeRootHooks","commandSkills","resourceSkills","toolLoadSkill"],"sources":["../../src/constants/skillInventory.ts","../../src/services/mcpSkills/index.ts","../../src/schemas/mcpSkillTools.ts","../../src/services/mcpSkillTools/index.ts","../../src/services/deferredSkills/index.ts","../../src/services/serverInventory/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/skillCommands.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/skillServer.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/skills.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/skills.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/load_skill.server.ts","../../generated/server.ts"],"sourcesContent":["/**\n * How long sessions with the same inputs share one skill inventory instead of each reading the disk.\n * ponytail: a skill added on disk reaches new sessions within this window, not at once; watch the\n * skill roots if that lag matters.\n */\nexport const SKILL_INVENTORY_FRESH_MS = 60_000;\n","import type { PoMcpPluginContext, PoMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport { BACKGROUND_CONTEXT, getOrThrow, withAbortSignal, type FileSystem } from '@agimon-ai/po-core/platform';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport type { ServerSkillGroup } from '../serverInventory';\n\nexport const MCP_SKILLS_SERVICE = 'po/discovered-mcp-skills';\n\nexport interface McpSkillProvider {\n list(context: PoMcpPluginContext): readonly PoMcpSkill[];\n}\n\n/** Explicit remote provider, never a projection of the local resource registry. */\nexport function mountMcpSkills(groups: readonly ServerSkillGroup[], fs: FileSystem, 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, PoMcpSkill>();\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 = getOrThrow(\n await fs.readTextFile(skill.filePath, withAbortSignal(readSignal, BACKGROUND_CONTEXT)),\n );\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: PoMcpPluginContext): readonly PoMcpSkill[] {\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 { 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 { PoHeadlessHostService, PoHeadlessTool } 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<PoHeadlessTool['execute']>[4]) {\n if (context.mcpSkills === undefined) throw new Error('Remote skill access is unavailable.');\n return context.mcpSkills;\n}\n\nexport function createSearchSkillsTool(): PoHeadlessTool<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<PoHeadlessHostService, 'readSkill'>,\n): PoHeadlessTool<typeof loadSkillParameters> {\n return {\n // web-plugin-tool-renderers: ignore load_skill (server session only, shown as a generic call)\n // PO_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(): PoHeadlessTool<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 fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { Worker } from 'node:worker_threads';\n\nimport {\n type BuildSystemPromptOptions,\n formatSkillsForPrompt,\n getAgentDir,\n loadSkills,\n type Skill,\n stripFrontmatter,\n} from '@earendil-works/pi-coding-agent';\n\nimport type { DeferredSkillLoaderOptions, DeferredSkillSnapshot } from '../../types/skills';\n\nexport type { DeferredSkillLoaderOptions, DeferredSkillSnapshot } from '../../types/skills';\n\nconst PI_PACKAGE = '@earendil-works/pi-coding-agent';\nconst PACKAGE_MANIFEST = 'package.json';\n// A fresh worker takes ~240 ms to import Pi's main entry but ~20 ms for this module alone, and\n// every session spawns one. ponytail: not in Pi's exports map, so a Pi release that moves it\n// falls back to the main entry (slow, still correct); deferredSkills.test.ts pins the path.\nconst PI_SKILLS_MODULE = path.join('dist', 'core', 'skills.js');\nconst SKILL_WORKER_SOURCE = `\nconst { parentPort, workerData } = require('node:worker_threads');\nvoid (async () => {\n try {\n const { loadSkills } = await import(workerData.piModuleUrl);\n parentPort.postMessage({ ok: true, result: loadSkills(workerData.loadOptions) });\n } catch (error) {\n parentPort.postMessage({ ok: false, error: error instanceof Error ? error.message : String(error) });\n }\n})();\n`;\n\nfunction installedPiModuleUrl(): string {\n const anchors = [process.argv[1], fileURLToPath(import.meta.url), path.join(process.cwd(), PACKAGE_MANIFEST)];\n for (const anchor of anchors) {\n if (!anchor) continue;\n let directory = path.dirname(path.resolve(anchor));\n while (true) {\n const packageRoot = path.join(directory, 'node_modules', PI_PACKAGE);\n const manifestPath = path.join(packageRoot, PACKAGE_MANIFEST);\n try {\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as { main?: unknown };\n if (typeof manifest.main === 'string') {\n const entry = path.resolve(packageRoot, manifest.main);\n const skills = path.join(packageRoot, PI_SKILLS_MODULE);\n if (fs.existsSync(skills)) return pathToFileURL(skills).href;\n if (fs.existsSync(entry)) return pathToFileURL(entry).href;\n }\n } catch {\n // This anchor does not expose Pi at this level; continue up its module chain.\n }\n const parent = path.dirname(directory);\n if (parent === directory) break;\n directory = parent;\n }\n }\n throw new Error(`Cannot resolve ${PI_PACKAGE} from the Po or host module trees`);\n}\n\ninterface SkillWorkerResult {\n ok: boolean;\n result?: { skills: Skill[]; diagnostics: Array<{ path?: string; message: string }> };\n error?: string;\n}\n\n/**\n * One session's Po-selected skill inventory.\n *\n * Construction is deliberately cheap. `start()` schedules the synchronous Pi\n * walker after session_start returns, while `ready()` is the single promise the\n * first input awaits before Pi expands `/skill:name`.\n */\nexport class DeferredSkillLoader {\n readonly #options: DeferredSkillLoaderOptions;\n #promise: Promise<DeferredSkillSnapshot> | undefined;\n\n constructor(options: DeferredSkillLoaderOptions) {\n this.#options = options;\n }\n\n start(): Promise<DeferredSkillSnapshot> {\n if (this.#promise) return this.#promise;\n\n if (!this.#options.schedule && !this.#options.load) {\n this.#promise = this.#loadInWorker();\n return this.#promise;\n }\n\n const schedule = this.#options.schedule ?? ((load: () => void) => setImmediate(load));\n this.#promise = new Promise((resolve) => {\n const fail = (error: unknown): void => {\n resolve(this.#failure(error));\n };\n try {\n schedule(() => {\n try {\n resolve(this.#load());\n } catch (error) {\n fail(error);\n }\n });\n } catch (error) {\n fail(error);\n }\n });\n return this.#promise;\n }\n\n ready(): Promise<DeferredSkillSnapshot> {\n return this.start();\n }\n\n #loadOptions(): { cwd: string; agentDir: string; skillPaths: string[]; includeDefaults: boolean } {\n return {\n cwd: this.#options.cwd,\n agentDir: this.#options.agentDir ?? getAgentDir(),\n skillPaths: [...this.#options.skillPaths],\n includeDefaults: false,\n };\n }\n\n #snapshot(result: {\n skills: Skill[];\n diagnostics: Array<{ path?: string; message: string }>;\n }): DeferredSkillSnapshot {\n return {\n skills: result.skills,\n diagnostics: result.diagnostics.map(\n (diagnostic) => `${diagnostic.path ?? this.#options.cwd}: ${diagnostic.message}`,\n ),\n };\n }\n\n #failure(error: unknown): DeferredSkillSnapshot {\n return {\n skills: [],\n diagnostics: [`${this.#options.cwd}: ${error instanceof Error ? error.message : String(error)}`],\n };\n }\n\n #load(): DeferredSkillSnapshot {\n return this.#snapshot((this.#options.load ?? loadSkills)(this.#loadOptions()));\n }\n\n #loadInWorker(): Promise<DeferredSkillSnapshot> {\n return new Promise((resolve) => {\n let settled = false;\n const settle = (snapshot: DeferredSkillSnapshot): void => {\n if (settled) return;\n settled = true;\n resolve(snapshot);\n };\n let worker: Worker;\n try {\n worker = new Worker(SKILL_WORKER_SOURCE, {\n eval: true,\n workerData: {\n piModuleUrl: this.#options.piModuleUrl ?? installedPiModuleUrl(),\n loadOptions: this.#loadOptions(),\n },\n });\n } catch (error) {\n settle(this.#failure(error));\n return;\n }\n worker.unref();\n worker.once('message', (message: SkillWorkerResult) => {\n if (!message.ok || !message.result) {\n settle(this.#failure(message.error ?? 'Skill worker failed'));\n return;\n }\n settle(this.#snapshot(message.result));\n });\n worker.once('error', (error) => settle(this.#failure(error)));\n worker.once('exit', (code) => {\n if (code !== 0) settle(this.#failure(`Skill worker exited with code ${code}`));\n });\n });\n }\n}\n\n/** Appends only the inventory Pi would append for these deferred skills. */\nexport function buildPromptWithDeferredSkills(\n systemPrompt: string,\n options: BuildSystemPromptOptions,\n skills: Skill[],\n): string {\n if (options.selectedTools && !options.selectedTools.includes('read')) return systemPrompt;\n return `${systemPrompt}${formatSkillsForPrompt(skills)}`;\n}\n\n/** Expands a deferred `/skill:name` before Pi consults its synchronous inventory. */\nexport function expandDeferredSkillCommand(text: string, skills: readonly Skill[]): string {\n if (!text.startsWith('/skill:')) return text;\n const spaceIndex = text.indexOf(' ');\n const skillName = spaceIndex === -1 ? text.slice(7) : text.slice(7, spaceIndex);\n const skill = skills.find((candidate) => candidate.name === skillName);\n if (!skill) return text;\n\n try {\n const args = spaceIndex === -1 ? '' : text.slice(spaceIndex + 1).trim();\n const body = stripFrontmatter(fs.readFileSync(skill.filePath, 'utf8')).trim();\n const skillBlock = `<skill name=\"${skill.name}\" location=\"${skill.filePath}\">\\nReferences are relative to ${skill.baseDir}.\\n\\n${body}\\n</skill>`;\n return args ? `${skillBlock}\\n\\n${args}` : skillBlock;\n } catch {\n // Pi uses the same literal-text fallback if a skill disappears between\n // discovery and submission; the agent can still respond to the command.\n return text;\n }\n}\n","import path from 'node:path';\n\nimport {\n listDomainNamesAsync,\n resolvePluginEntriesAsync,\n resolveSharedSkillsAsync,\n type PluginEntry,\n} from '@agimon-ai/po-config/domains';\nimport { readHarnessState } from '@agimon-ai/po-config/harnessState';\nimport type { PoHeadlessExecutionContext } from '@agimon-ai/po-core/headless';\nimport { BACKGROUND_CONTEXT, nodeHost, withAbortSignal, type FileSystem } from '@agimon-ai/po-core/platform';\nimport { materializePluginEntries } from '@agimon-ai/po-domain/plugins';\nimport { collectResources, discoverSkillsAsync } from '@agimon-ai/po-domain/resources';\nimport { formatSkillsForPrompt } from '@earendil-works/pi-coding-agent';\n\nimport type { ServerSkillInventory } from '../../types/skills';\nimport { DeferredSkillLoader } from '../deferredSkills';\n\nexport type { ServerSkillGroup, ServerSkillInventory } from '../../types/skills';\n\ninterface SkillSource {\n readonly domain?: string;\n readonly paths: readonly string[];\n readonly mcpPaths: readonly string[];\n /** Advertised by this package rather than by po-domain. */\n readonly listed?: boolean;\n}\n\nconst LOCAL_ONLY_MCP_PACKAGES = new Set([\n '@agimon-ai/po-author',\n '@agimon-ai/po-git',\n '@agimon-ai/po-goal',\n '@agimon-ai/po-help',\n '@agimon-ai/po-loop',\n '@agimon-ai/po-user-feedback',\n '@agimon-ai/po-voice',\n '@agimon-ai/po-workflow',\n]);\n\ntype IoContext = Parameters<FileSystem['readTextFile']>[1];\n\nasync function isMcpSkillPlugin(fs: FileSystem, entry: PluginEntry, context: IoContext): Promise<boolean> {\n if (entry.source?.type === 'npm') return !LOCAL_ONLY_MCP_PACKAGES.has(entry.source.package);\n // A package manifest is optional for catalog plugins, but a present identity\n // that cannot be read or parsed must never make the plugin remotely eligible.\n const source = await fs.readTextFile(path.join(entry.directory, 'package.json'), context);\n if (!source.ok) return source.error.code === 'not_found';\n try {\n const manifest = JSON.parse(source.value) as unknown;\n if (typeof manifest !== 'object' || manifest === null || Array.isArray(manifest)) return false;\n const name = (manifest as { name?: unknown }).name;\n return typeof name === 'string' && name.length > 0 && name.trim() === name && !LOCAL_ONLY_MCP_PACKAGES.has(name);\n } catch {\n return false;\n }\n}\n\n/**\n * Whether a discovered skill came from one of these paths.\n *\n * A source holds exact SKILL.md files for plugin and shared skills, but a bare\n * directory for `.po/skills`, so membership is containment rather than\n * equality.\n */\nfunction within(filePath: string, roots: readonly string[]): boolean {\n const resolved = path.resolve(filePath);\n return roots.some((root) => {\n const base = path.resolve(root);\n return resolved === base || resolved.startsWith(`${base}${path.sep}`);\n });\n}\n/**\n * Every skill the session could reach, grouped by what activates it.\n *\n * A cockpit `/domains` switch reconciles contributions rather than rebuilding\n * the server plugin: the session declaration is mounted once. So enumerating only the\n * launch selection would freeze the command list at whatever was selected when\n * the session host was built. Enumerating every domain up front and tagging\n * each group with its `when` lets the existing kernel refresh do the work, the\n * same way domainServerResources registers per-domain skill resources.\n */\nexport async function discoverServerSkills(\n execution: PoHeadlessExecutionContext,\n fs: FileSystem,\n signal: AbortSignal,\n): Promise<ServerSkillInventory> {\n signal.throwIfAborted();\n const context = withAbortSignal(signal, BACKGROUND_CONTEXT);\n const state = readHarnessState(execution.environment);\n const home = execution.environment.HOME ?? nodeHost.homeDirectory();\n const repoSkills = path.join(execution.repoRoot, '.po', 'skills');\n const sources: SkillSource[] = [];\n const diagnostics: string[] = [];\n // A malformed domain is a configuration error in one domain, so it must not\n // remove every other domain's skills. Enumerating the whole manifest is new\n // exposure here: reading the launch selection could not fail this way.\n const domains: string[] = [];\n try {\n domains.push(...(await listDomainNamesAsync(fs, execution.repoRoot, context, home)));\n } catch (error) {\n diagnostics.push(`Domain skills are unavailable: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n // Domain-scoped plugin skills come first. The host keeps the first command\n // registered for a name, so this ordering reproduces the collector's rule\n // that a selected plugin outranks a shared fallback of the same name.\n for (const domain of domains) {\n signal.throwIfAborted();\n try {\n const plugins = await materializePluginEntries(\n await resolvePluginEntriesAsync(fs, execution.repoRoot, [domain], [], context, home),\n );\n const mcpPluginRoots = (\n await Promise.all(\n plugins.map(async (plugin) =>\n (await isMcpSkillPlugin(fs, plugin, context)) ? path.join(plugin.directory, 'skills') : undefined,\n ),\n )\n ).filter((root): root is string => root !== undefined);\n const collected = await collectResources(execution.repoRoot, plugins, {\n agents: false,\n mcp: false,\n sharedSkills: false,\n });\n try {\n if (collected.skillDirectories.length > 0) {\n const paths = [...collected.skillDirectories];\n sources.push({\n domain,\n paths,\n // Exact collected paths retain this domain's per-plugin skill subset.\n // A plugin root would also admit skills loaded for another domain.\n mcpPaths: paths.filter((skillPath) => within(skillPath, mcpPluginRoots)),\n });\n }\n } finally {\n await collected.cleanup();\n }\n } catch (error) {\n diagnostics.push(`Domain '${domain}': ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n // Shared .claude/skills are not owned by any one domain, and a domain can opt\n // out of them. `when` cannot express \"unless every selected domain opts out\",\n // but registering a copy per domain that keeps them says the same thing: the\n // group is active if any such domain is selected, which is exactly what\n // resolveSharedSkills computes.\n signal.throwIfAborted();\n const shared = await discoverSkillsAsync(execution.repoRoot, path.join(execution.repoRoot, '.claude', 'skills'));\n if (shared.length > 0) {\n const sharedPaths = shared.map((skill) => skill.path);\n for (const domain of domains) {\n if (await resolveSharedSkillsAsync(fs, execution.repoRoot, [domain], context, home)) {\n sources.push({ domain, paths: sharedPaths, mcpPaths: sharedPaths, listed: true });\n }\n }\n }\n\n // Repository-local skills belong to the repository, not to a selection.\n sources.push({ paths: [repoSkills], mcpPaths: [repoSkills], listed: true });\n\n signal.throwIfAborted();\n // One walk for every group. Pi drops a path it has already loaded, so the\n // loader gets the unique set and each group selects its own skills back out.\n const unique = [...new Set([...sources.flatMap((source) => source.paths), ...(state.skillDirectories ?? [])])];\n const inventory = await new DeferredSkillLoader({ cwd: execution.cwd, skillPaths: unique }).ready();\n signal.throwIfAborted();\n\n const groups = sources\n .map((source) => ({\n ...(source.domain === undefined ? {} : { domain: source.domain }),\n skills: inventory.skills.filter((skill) => within(skill.filePath, source.paths)),\n }))\n .filter((group) => group.skills.length > 0);\n const listed = sources\n .filter((source) => source.listed === true)\n .map((source) => ({\n ...(source.domain === undefined ? {} : { domain: source.domain }),\n skills: inventory.skills.filter((skill) => within(skill.filePath, source.paths)),\n }))\n .filter((group) => group.skills.length > 0);\n const mcpGroups = sources\n .map((source) => ({\n ...(source.domain === undefined ? {} : { domain: source.domain }),\n skills: inventory.skills.filter((skill) => within(skill.filePath, source.mcpPaths)),\n }))\n .filter((group) => group.skills.length > 0);\n\n // The catalog still describes the active selection rather than everything on\n // disk, because it is prompt text rather than a menu.\n const activeSkills = inventory.skills.filter((skill) =>\n within(skill.filePath, [...(state.skillDirectories ?? []), repoSkills]),\n );\n return {\n inventory: { skills: inventory.skills, diagnostics: [...inventory.diagnostics, ...diagnostics] },\n groups,\n mcpGroups,\n listed,\n catalog: formatSkillsForPrompt(activeSkills) || '(no discovered skills)',\n };\n}\n","import type { PoHeadlessCommand } from '@agimon-ai/po-core/headless';\nimport type { Skill } from '@earendil-works/pi-coding-agent';\n\nimport { expandDeferredSkillCommand, type DeferredSkillSnapshot } from '../../../../../services/deferredSkills';\nimport type { ServerSkillGroup } from '../../../../../services/serverInventory';\nimport { SKILL_COMMAND_PREFIX, SKILL_INVOCATION_PREFIX, SKILLS_COMMAND } from '../../../../../types/skills';\n\n/**\n * One command per skill, gated by whatever activates that skill.\n *\n * Expansion always reads the full inventory, not the group: a command is only\n * dispatchable while its condition holds, so by the time one runs its skill is\n * active, and looking it up in the union keeps one lookup table instead of one\n * per domain.\n */\nfunction skillCommand(skill: Skill, domain: string | undefined, inventory: DeferredSkillSnapshot): PoHeadlessCommand {\n return {\n ...(domain === undefined ? {} : { when: { domain } }),\n name: `${SKILL_COMMAND_PREFIX}${skill.name}`,\n description: skill.description,\n execute: async (args, execution) => {\n const text = `${SKILL_INVOCATION_PREFIX}${skill.name}${args ? ` ${args}` : ''}`;\n const expanded = expandDeferredSkillCommand(text, inventory.skills);\n if (expanded === text) throw new Error(`Skill '${skill.name}' is no longer readable.`);\n await execution.session.prompt(expanded);\n },\n };\n}\n\nexport function createSkillCommands(\n inventory: DeferredSkillSnapshot,\n catalog: string,\n groups: readonly ServerSkillGroup[],\n): readonly PoHeadlessCommand[] {\n return [\n {\n name: SKILLS_COMMAND,\n description: 'List discovered skills or invoke one by name.',\n async execute(args, execution) {\n const requested = args.trim();\n if (requested) {\n await execution.session.prompt(\n expandDeferredSkillCommand(`${SKILL_INVOCATION_PREFIX}${requested}`, inventory.skills),\n );\n return;\n }\n await execution.client.notify({\n title: 'Po skills',\n body: catalog,\n level: 'info',\n });\n },\n },\n ...groups.flatMap((group) => group.skills.map((skill) => skillCommand(skill, group.domain, inventory))),\n ];\n}\n","import { readHarnessState } from '@agimon-ai/po-config/harnessState';\nimport type { PoHeadlessHostService } from '@agimon-ai/po-core/headless';\nimport { BACKGROUND_CONTEXT, getOrThrow, nodeHost, type FileSystem } from '@agimon-ai/po-core/platform';\nimport {\n type PoServerResources,\n type PoServerSessionPlugin,\n packageResourcePath,\n readPackageResource,\n} from '@agimon-ai/po-core/serverPlugin';\n\nimport { SKILL_INVENTORY_FRESH_MS } from '../../../../../constants/skillInventory';\nimport { mountMcpSkills } from '../../../../../services/mcpSkills';\nimport { createSessionLoadSkillTool } from '../../../../../services/mcpSkillTools';\nimport { discoverServerSkills } from '../../../../../services/serverInventory';\nimport { createSkillCommands } from './skillCommands';\n\nexport async function createSkillServer(\n agent: PoHeadlessHostService,\n fs: FileSystem,\n signal: AbortSignal,\n resources: PoServerResources,\n): Promise<PoServerSessionPlugin> {\n const execution = agent.context;\n // Sessions with the same inputs share one discovery. The key holds every input discoverServerSkills\n // reads besides the disk, so equal keys give equal inventories, and the window bounds how old that\n // read of the disk can be.\n const key = [\n 'inventory',\n execution.repoRoot,\n execution.cwd,\n execution.environment.HOME ?? nodeHost.homeDirectory(),\n ...(readHarnessState(execution.environment).skillDirectories ?? []),\n Math.floor(Date.now() / SKILL_INVENTORY_FRESH_MS),\n ];\n const { inventory, catalog, groups, mcpGroups, listed } = await resources.acquire(key, () =>\n // Every session sharing the discovery waits on it, so none of their signals may abort it.\n discoverServerSkills(execution, fs, new AbortController().signal),\n );\n return {\n commands: createSkillCommands(inventory, catalog, groups),\n tools: [createSessionLoadSkillTool(agent)],\n services: [mountMcpSkills(mcpGroups, fs, signal)],\n resources: [\n // Each skill joins the prompt's one <available_skills> list, gated like the rest.\n ...listed.flatMap((group) =>\n group.skills.map((skill) => ({\n name: skill.name,\n description: skill.description,\n path: skill.filePath,\n kind: 'skill' as const,\n ...(group.domain === undefined\n ? {}\n : { when: { domain: group.domain, attribution: { kind: 'domain' as const, mode: group.domain } } }),\n read: async () => getOrThrow(await fs.readTextFile(skill.filePath, BACKGROUND_CONTEXT)),\n })),\n ),\n ...[\n {\n name: 'po-author-skill',\n description:\n 'Author and distribute Po agent skills. Use when creating a SKILL.md, contributing a runtime skill directory, or publishing activation-gated Help prompts and diagnostic tools.',\n },\n {\n name: 'po-use-skill',\n description:\n \"Use Po's skill catalog and deferred discovery. Diagnose missing or shadowed skills and invoke the narrowest available guidance.\",\n },\n ].map((skill) => ({\n ...skill,\n when: { state: { 'minor-mode': 'help' }, attribution: { kind: 'minor' as const, mode: 'help' } },\n kind: 'skill' as const,\n path: packageResourcePath(import.meta.url, `src/prompts/${skill.name}/SKILL.md`),\n read: () => readPackageResource(import.meta.url, `src/prompts/${skill.name}/SKILL.md`),\n })),\n ],\n };\n}\n","import { defineRoot } from '@agimon-ai/po-core/extensionFile';\nimport { requirePoFs } from '@agimon-ai/po-core/platform';\nimport type { PoServerPluginContext, PoServerSessionPlugin } from '@agimon-ai/po-core/serverPlugin';\n\nimport { createSkillServer } from './_lib/skillServer';\n\nexport default defineRoot(async ({ agent, context: root, signal, resources }: PoServerPluginContext) => {\n const runtime: PoServerSessionPlugin = agent\n ? await createSkillServer(agent, requirePoFs(root), signal, resources)\n : { commands: [], resources: [] };\n return { value: runtime, services: runtime.services };\n});\n","import { defineRoutedContribution } from '@agimon-ai/po-core/extensionFile';\nimport type { WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { PoServerPluginContext, PoServerSessionPlugin } from '@agimon-ai/po-core/serverPlugin';\n\nexport default defineRoutedContribution(\n (context: WithRoot<PoServerPluginContext, PoServerSessionPlugin>) => context.root.commands!,\n { cardinality: 'many' },\n);\n","import { defineRoutedContribution } from '@agimon-ai/po-core/extensionFile';\nimport type { WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { PoServerPluginContext, PoServerSessionPlugin } from '@agimon-ai/po-core/serverPlugin';\n\nexport default defineRoutedContribution(\n (context: WithRoot<PoServerPluginContext, PoServerSessionPlugin>) => context.root.resources!,\n { cardinality: 'many' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { PoServerPluginContext, PoServerSessionPlugin } from '@agimon-ai/po-core/serverPlugin';\n\n/** The session agent's skill loader; the Pi CLI keeps Pi's own skill handling. */\nexport default defineRoutedContribution(\n (context: WithRoot<PoServerPluginContext, PoServerSessionPlugin>) => context.root.tools?.[0],\n { cardinality: 'optional' },\n);\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineServerPlugin, type PoServerSessionPlugin } from '@agimon-ai/po-core/serverPlugin';\nimport { composeServerProviderOverrides } from '@agimon-ai/po-core/serverPlugin';\nimport { composeRootHooks, composeRootInjects } from '@agimon-ai/po-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport commandSkills from '../src/extensions/workspaces/sessions/(backend)/command/skills.server';\nimport resourceSkills from '../src/extensions/workspaces/sessions/(backend)/resource/skills.server';\nimport toolLoadSkill from '../src/extensions/workspaces/sessions/(backend)/tool/load_skill.server';\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};\n/* v8 ignore next -- generated normalization branch */\nconst defined = <T>(values: readonly (T | undefined)[]): T[] =>\n values.filter((value): value is T => value !== undefined);\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const serverPlugin = defineServerPlugin({\n name: '@agimon-ai/po-skill',\n providerOverrides: composeServerProviderOverrides(rootSession),\n injects: composeRootInjects({ session: [rootSession] }),\n session: async (context) => {\n const scopeSession = await context.scopeRoot('session', rootSession, context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get commands(): PoServerSessionPlugin['commands'] { return [...many(commandSkills, contextSession)]; },\n get resources(): PoServerSessionPlugin['resources'] { return [...many(resourceSkills, contextSession)]; },\n get tools(): PoServerSessionPlugin['tools'] { return defined([via({ name: 'load_skill' }, at(toolLoadSkill, contextSession))]); },\n services: [...(scopeSession.services ?? [])],\n get activities(): PoServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default serverPlugin;\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  //#region generated/server.d.ts
2
- export declare const facet: import("@agimon-ai/po-core/serverFacet").PoServerFacet;
2
+ export declare const serverPlugin: import("@agimon-ai/po-core/serverPlugin").PoServerPlugin;
3
3
  //#endregion
4
- export { facet as default };
4
+ export { serverPlugin as default };
5
5
  //# sourceMappingURL=server.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.mts","names":[],"sources":["../../generated/server.ts"],"mappings":";qBAwBa,gDAAK"}
1
+ {"version":3,"file":"server.d.mts","names":[],"sources":["../../generated/server.ts"],"mappings":";qBAwBa,wDAAY"}
@@ -4,14 +4,22 @@ import { listDomainNamesAsync, resolvePluginEntriesAsync, resolveSharedSkillsAsy
4
4
  import { BACKGROUND_CONTEXT, getOrThrow, nodeHost, requirePoFs, withAbortSignal } from "@agimon-ai/po-core/platform";
5
5
  import { materializePluginEntries } from "@agimon-ai/po-domain/plugins";
6
6
  import { formatSkillsForPrompt, getAgentDir, loadSkills, stripFrontmatter } from "@earendil-works/pi-coding-agent";
7
- import { composeServerProviderOverrides, defineServerPlugin, packageResourcePath, readPackageResource } from "@agimon-ai/po-core/serverFacet";
8
- import { composeRootHooks, defineRoot, defineRoutedContribution } from "@agimon-ai/po-core/extensionFile";
9
- import { Type } from "typebox";
7
+ import { composeServerProviderOverrides, defineServerPlugin, packageResourcePath, readPackageResource } from "@agimon-ai/po-core/serverPlugin";
8
+ import { composeRootHooks, composeRootInjects, defineRoot, defineRoutedContribution } from "@agimon-ai/po-core/extensionFile";
10
9
  import { readHarnessState } from "@agimon-ai/po-config/harnessState";
10
+ import { Type } from "typebox";
11
11
  import { collectResources, discoverSkillsAsync } from "@agimon-ai/po-domain/resources";
12
12
  import fs from "node:fs";
13
13
  import { fileURLToPath, pathToFileURL } from "node:url";
14
14
  import { Worker } from "node:worker_threads";
15
+ //#region src/constants/skillInventory.ts
16
+ /**
17
+ * How long sessions with the same inputs share one skill inventory instead of each reading the disk.
18
+ * ponytail: a skill added on disk reaches new sessions within this window, not at once; watch the
19
+ * skill roots if that lag matters.
20
+ */
21
+ const SKILL_INVENTORY_FRESH_MS = 6e4;
22
+ //#endregion
15
23
  //#region src/services/mcpSkills/index.ts
16
24
  const MCP_SKILLS_SERVICE = "po/discovered-mcp-skills";
17
25
  /** Explicit remote provider, never a projection of the local resource registry. */
@@ -78,6 +86,7 @@ function createSessionLoadSkillTool(host) {
78
86
  //#region src/services/deferredSkills/index.ts
79
87
  const PI_PACKAGE = "@earendil-works/pi-coding-agent";
80
88
  const PACKAGE_MANIFEST = "package.json";
89
+ const PI_SKILLS_MODULE = path.join("dist", "core", "skills.js");
81
90
  const SKILL_WORKER_SOURCE = `
82
91
  const { parentPort, workerData } = require('node:worker_threads');
83
92
  void (async () => {
@@ -105,6 +114,8 @@ function installedPiModuleUrl() {
105
114
  const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
106
115
  if (typeof manifest.main === "string") {
107
116
  const entry = path.resolve(packageRoot, manifest.main);
117
+ const skills = path.join(packageRoot, PI_SKILLS_MODULE);
118
+ if (fs.existsSync(skills)) return pathToFileURL(skills).href;
108
119
  if (fs.existsSync(entry)) return pathToFileURL(entry).href;
109
120
  }
110
121
  } catch {}
@@ -274,7 +285,7 @@ function within(filePath, roots) {
274
285
  * Every skill the session could reach, grouped by what activates it.
275
286
  *
276
287
  * A cockpit `/domains` switch reconciles contributions rather than rebuilding
277
- * the facet: the session declaration is mounted once. So enumerating only the
288
+ * the server plugin: the session declaration is mounted once. So enumerating only the
278
289
  * launch selection would freeze the command list at whatever was selected when
279
290
  * the session host was built. Enumerating every domain up front and tagging
280
291
  * each group with its `when` lets the existing kernel refresh do the work, the
@@ -410,8 +421,17 @@ function createSkillCommands(inventory, catalog, groups) {
410
421
  }
411
422
  //#endregion
412
423
  //#region src/extensions/workspaces/sessions/(backend)/_lib/skillServer.ts
413
- async function createSkillServer(agent, fs, signal) {
414
- const { inventory, catalog, groups, mcpGroups, listed } = await discoverServerSkills(agent.context, fs, signal);
424
+ async function createSkillServer(agent, fs, signal, resources) {
425
+ const execution = agent.context;
426
+ const key = [
427
+ "inventory",
428
+ execution.repoRoot,
429
+ execution.cwd,
430
+ execution.environment.HOME ?? nodeHost.homeDirectory(),
431
+ ...readHarnessState(execution.environment).skillDirectories ?? [],
432
+ Math.floor(Date.now() / SKILL_INVENTORY_FRESH_MS)
433
+ ];
434
+ const { inventory, catalog, groups, mcpGroups, listed } = await resources.acquire(key, () => discoverServerSkills(execution, fs, new AbortController().signal));
415
435
  return {
416
436
  commands: createSkillCommands(inventory, catalog, groups),
417
437
  tools: [createSessionLoadSkillTool(agent)],
@@ -452,8 +472,8 @@ async function createSkillServer(agent, fs, signal) {
452
472
  }
453
473
  //#endregion
454
474
  //#region src/extensions/workspaces/sessions/(backend)/root.server.ts
455
- var root_server_default = defineRoot(async ({ agent, context: root, signal }) => {
456
- const runtime = agent ? await createSkillServer(agent, requirePoFs(root), signal) : {
475
+ var root_server_default = defineRoot(async ({ agent, context: root, signal, resources }) => {
476
+ const runtime = agent ? await createSkillServer(agent, requirePoFs(root), signal, resources) : {
457
477
  commands: [],
458
478
  resources: []
459
479
  };
@@ -485,11 +505,12 @@ const via = (identity, value) => value === void 0 ? void 0 : {
485
505
  ...identity,
486
506
  ...value
487
507
  };
488
- const facet = defineServerPlugin({
508
+ const serverPlugin = defineServerPlugin({
489
509
  name: "@agimon-ai/po-skill",
490
510
  providerOverrides: composeServerProviderOverrides(root_server_default),
511
+ injects: composeRootInjects({ session: [root_server_default] }),
491
512
  session: async (context) => {
492
- const scopeSession = await root_server_default(context);
513
+ const scopeSession = await context.scopeRoot("session", root_server_default, context);
493
514
  const contextSession = {
494
515
  ...context,
495
516
  root: scopeSession.value
@@ -513,6 +534,6 @@ const facet = defineServerPlugin({
513
534
  }
514
535
  });
515
536
  //#endregion
516
- export { facet as default, facet };
537
+ export { serverPlugin as default, serverPlugin };
517
538
 
518
539
  //# sourceMappingURL=server.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.mjs","names":["rootSession","commandSkills","resourceSkills","toolLoadSkill"],"sources":["../../src/services/mcpSkills/index.ts","../../src/schemas/mcpSkillTools.ts","../../src/services/mcpSkillTools/index.ts","../../src/services/deferredSkills/index.ts","../../src/services/serverInventory/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/skillCommands.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/skillServer.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/skills.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/skills.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/load_skill.server.ts","../../generated/server.ts"],"sourcesContent":["import type { PoMcpPluginContext, PoMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport { BACKGROUND_CONTEXT, getOrThrow, withAbortSignal, type FileSystem } from '@agimon-ai/po-core/platform';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport type { ServerSkillGroup } from '../serverInventory';\n\nexport const MCP_SKILLS_SERVICE = 'po/discovered-mcp-skills';\n\nexport interface McpSkillProvider {\n list(context: PoMcpPluginContext): readonly PoMcpSkill[];\n}\n\n/** Explicit remote provider, never a projection of the local resource registry. */\nexport function mountMcpSkills(groups: readonly ServerSkillGroup[], fs: FileSystem, 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, PoMcpSkill>();\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 = getOrThrow(\n await fs.readTextFile(skill.filePath, withAbortSignal(readSignal, BACKGROUND_CONTEXT)),\n );\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: PoMcpPluginContext): readonly PoMcpSkill[] {\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 { 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 { PoHeadlessHostService, PoHeadlessTool } 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<PoHeadlessTool['execute']>[4]) {\n if (context.mcpSkills === undefined) throw new Error('Remote skill access is unavailable.');\n return context.mcpSkills;\n}\n\nexport function createSearchSkillsTool(): PoHeadlessTool<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<PoHeadlessHostService, 'readSkill'>,\n): PoHeadlessTool<typeof loadSkillParameters> {\n return {\n // web-plugin-tool-renderers: ignore load_skill (server session only, shown as a generic call)\n // PO_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(): PoHeadlessTool<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 fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { Worker } from 'node:worker_threads';\n\nimport {\n type BuildSystemPromptOptions,\n formatSkillsForPrompt,\n getAgentDir,\n loadSkills,\n type Skill,\n stripFrontmatter,\n} from '@earendil-works/pi-coding-agent';\n\nimport type { DeferredSkillLoaderOptions, DeferredSkillSnapshot } from '../../types/skills';\n\nexport type { DeferredSkillLoaderOptions, DeferredSkillSnapshot } from '../../types/skills';\n\nconst PI_PACKAGE = '@earendil-works/pi-coding-agent';\nconst PACKAGE_MANIFEST = 'package.json';\nconst SKILL_WORKER_SOURCE = `\nconst { parentPort, workerData } = require('node:worker_threads');\nvoid (async () => {\n try {\n const { loadSkills } = await import(workerData.piModuleUrl);\n parentPort.postMessage({ ok: true, result: loadSkills(workerData.loadOptions) });\n } catch (error) {\n parentPort.postMessage({ ok: false, error: error instanceof Error ? error.message : String(error) });\n }\n})();\n`;\n\nfunction installedPiModuleUrl(): string {\n const anchors = [process.argv[1], fileURLToPath(import.meta.url), path.join(process.cwd(), PACKAGE_MANIFEST)];\n for (const anchor of anchors) {\n if (!anchor) continue;\n let directory = path.dirname(path.resolve(anchor));\n while (true) {\n const packageRoot = path.join(directory, 'node_modules', PI_PACKAGE);\n const manifestPath = path.join(packageRoot, PACKAGE_MANIFEST);\n try {\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as { main?: unknown };\n if (typeof manifest.main === 'string') {\n const entry = path.resolve(packageRoot, manifest.main);\n if (fs.existsSync(entry)) return pathToFileURL(entry).href;\n }\n } catch {\n // This anchor does not expose Pi at this level; continue up its module chain.\n }\n const parent = path.dirname(directory);\n if (parent === directory) break;\n directory = parent;\n }\n }\n throw new Error(`Cannot resolve ${PI_PACKAGE} from the Po or host module trees`);\n}\n\ninterface SkillWorkerResult {\n ok: boolean;\n result?: { skills: Skill[]; diagnostics: Array<{ path?: string; message: string }> };\n error?: string;\n}\n\n/**\n * One session's Po-selected skill inventory.\n *\n * Construction is deliberately cheap. `start()` schedules the synchronous Pi\n * walker after session_start returns, while `ready()` is the single promise the\n * first input awaits before Pi expands `/skill:name`.\n */\nexport class DeferredSkillLoader {\n readonly #options: DeferredSkillLoaderOptions;\n #promise: Promise<DeferredSkillSnapshot> | undefined;\n\n constructor(options: DeferredSkillLoaderOptions) {\n this.#options = options;\n }\n\n start(): Promise<DeferredSkillSnapshot> {\n if (this.#promise) return this.#promise;\n\n if (!this.#options.schedule && !this.#options.load) {\n this.#promise = this.#loadInWorker();\n return this.#promise;\n }\n\n const schedule = this.#options.schedule ?? ((load: () => void) => setImmediate(load));\n this.#promise = new Promise((resolve) => {\n const fail = (error: unknown): void => {\n resolve(this.#failure(error));\n };\n try {\n schedule(() => {\n try {\n resolve(this.#load());\n } catch (error) {\n fail(error);\n }\n });\n } catch (error) {\n fail(error);\n }\n });\n return this.#promise;\n }\n\n ready(): Promise<DeferredSkillSnapshot> {\n return this.start();\n }\n\n #loadOptions(): { cwd: string; agentDir: string; skillPaths: string[]; includeDefaults: boolean } {\n return {\n cwd: this.#options.cwd,\n agentDir: this.#options.agentDir ?? getAgentDir(),\n skillPaths: [...this.#options.skillPaths],\n includeDefaults: false,\n };\n }\n\n #snapshot(result: {\n skills: Skill[];\n diagnostics: Array<{ path?: string; message: string }>;\n }): DeferredSkillSnapshot {\n return {\n skills: result.skills,\n diagnostics: result.diagnostics.map(\n (diagnostic) => `${diagnostic.path ?? this.#options.cwd}: ${diagnostic.message}`,\n ),\n };\n }\n\n #failure(error: unknown): DeferredSkillSnapshot {\n return {\n skills: [],\n diagnostics: [`${this.#options.cwd}: ${error instanceof Error ? error.message : String(error)}`],\n };\n }\n\n #load(): DeferredSkillSnapshot {\n return this.#snapshot((this.#options.load ?? loadSkills)(this.#loadOptions()));\n }\n\n #loadInWorker(): Promise<DeferredSkillSnapshot> {\n return new Promise((resolve) => {\n let settled = false;\n const settle = (snapshot: DeferredSkillSnapshot): void => {\n if (settled) return;\n settled = true;\n resolve(snapshot);\n };\n let worker: Worker;\n try {\n worker = new Worker(SKILL_WORKER_SOURCE, {\n eval: true,\n workerData: {\n piModuleUrl: this.#options.piModuleUrl ?? installedPiModuleUrl(),\n loadOptions: this.#loadOptions(),\n },\n });\n } catch (error) {\n settle(this.#failure(error));\n return;\n }\n worker.unref();\n worker.once('message', (message: SkillWorkerResult) => {\n if (!message.ok || !message.result) {\n settle(this.#failure(message.error ?? 'Skill worker failed'));\n return;\n }\n settle(this.#snapshot(message.result));\n });\n worker.once('error', (error) => settle(this.#failure(error)));\n worker.once('exit', (code) => {\n if (code !== 0) settle(this.#failure(`Skill worker exited with code ${code}`));\n });\n });\n }\n}\n\n/** Appends only the inventory Pi would append for these deferred skills. */\nexport function buildPromptWithDeferredSkills(\n systemPrompt: string,\n options: BuildSystemPromptOptions,\n skills: Skill[],\n): string {\n if (options.selectedTools && !options.selectedTools.includes('read')) return systemPrompt;\n return `${systemPrompt}${formatSkillsForPrompt(skills)}`;\n}\n\n/** Expands a deferred `/skill:name` before Pi consults its synchronous inventory. */\nexport function expandDeferredSkillCommand(text: string, skills: readonly Skill[]): string {\n if (!text.startsWith('/skill:')) return text;\n const spaceIndex = text.indexOf(' ');\n const skillName = spaceIndex === -1 ? text.slice(7) : text.slice(7, spaceIndex);\n const skill = skills.find((candidate) => candidate.name === skillName);\n if (!skill) return text;\n\n try {\n const args = spaceIndex === -1 ? '' : text.slice(spaceIndex + 1).trim();\n const body = stripFrontmatter(fs.readFileSync(skill.filePath, 'utf8')).trim();\n const skillBlock = `<skill name=\"${skill.name}\" location=\"${skill.filePath}\">\\nReferences are relative to ${skill.baseDir}.\\n\\n${body}\\n</skill>`;\n return args ? `${skillBlock}\\n\\n${args}` : skillBlock;\n } catch {\n // Pi uses the same literal-text fallback if a skill disappears between\n // discovery and submission; the agent can still respond to the command.\n return text;\n }\n}\n","import path from 'node:path';\n\nimport {\n listDomainNamesAsync,\n resolvePluginEntriesAsync,\n resolveSharedSkillsAsync,\n type PluginEntry,\n} from '@agimon-ai/po-config/domains';\nimport { readHarnessState } from '@agimon-ai/po-config/harnessState';\nimport type { PoHeadlessExecutionContext } from '@agimon-ai/po-core/headless';\nimport { BACKGROUND_CONTEXT, nodeHost, withAbortSignal, type FileSystem } from '@agimon-ai/po-core/platform';\nimport { materializePluginEntries } from '@agimon-ai/po-domain/plugins';\nimport { collectResources, discoverSkillsAsync } from '@agimon-ai/po-domain/resources';\nimport { formatSkillsForPrompt } from '@earendil-works/pi-coding-agent';\n\nimport type { ServerSkillInventory } from '../../types/skills';\nimport { DeferredSkillLoader } from '../deferredSkills';\n\nexport type { ServerSkillGroup, ServerSkillInventory } from '../../types/skills';\n\ninterface SkillSource {\n readonly domain?: string;\n readonly paths: readonly string[];\n readonly mcpPaths: readonly string[];\n /** Advertised by this package rather than by po-domain. */\n readonly listed?: boolean;\n}\n\nconst LOCAL_ONLY_MCP_PACKAGES = new Set([\n '@agimon-ai/po-author',\n '@agimon-ai/po-git',\n '@agimon-ai/po-goal',\n '@agimon-ai/po-help',\n '@agimon-ai/po-loop',\n '@agimon-ai/po-user-feedback',\n '@agimon-ai/po-voice',\n '@agimon-ai/po-workflow',\n]);\n\ntype IoContext = Parameters<FileSystem['readTextFile']>[1];\n\nasync function isMcpSkillPlugin(fs: FileSystem, entry: PluginEntry, context: IoContext): Promise<boolean> {\n if (entry.source?.type === 'npm') return !LOCAL_ONLY_MCP_PACKAGES.has(entry.source.package);\n // A package manifest is optional for catalog plugins, but a present identity\n // that cannot be read or parsed must never make the plugin remotely eligible.\n const source = await fs.readTextFile(path.join(entry.directory, 'package.json'), context);\n if (!source.ok) return source.error.code === 'not_found';\n try {\n const manifest = JSON.parse(source.value) as unknown;\n if (typeof manifest !== 'object' || manifest === null || Array.isArray(manifest)) return false;\n const name = (manifest as { name?: unknown }).name;\n return typeof name === 'string' && name.length > 0 && name.trim() === name && !LOCAL_ONLY_MCP_PACKAGES.has(name);\n } catch {\n return false;\n }\n}\n\n/**\n * Whether a discovered skill came from one of these paths.\n *\n * A source holds exact SKILL.md files for plugin and shared skills, but a bare\n * directory for `.po/skills`, so membership is containment rather than\n * equality.\n */\nfunction within(filePath: string, roots: readonly string[]): boolean {\n const resolved = path.resolve(filePath);\n return roots.some((root) => {\n const base = path.resolve(root);\n return resolved === base || resolved.startsWith(`${base}${path.sep}`);\n });\n}\n/**\n * Every skill the session could reach, grouped by what activates it.\n *\n * A cockpit `/domains` switch reconciles contributions rather than rebuilding\n * the facet: the session declaration is mounted once. So enumerating only the\n * launch selection would freeze the command list at whatever was selected when\n * the session host was built. Enumerating every domain up front and tagging\n * each group with its `when` lets the existing kernel refresh do the work, the\n * same way domainServerResources registers per-domain skill resources.\n */\nexport async function discoverServerSkills(\n execution: PoHeadlessExecutionContext,\n fs: FileSystem,\n signal: AbortSignal,\n): Promise<ServerSkillInventory> {\n signal.throwIfAborted();\n const context = withAbortSignal(signal, BACKGROUND_CONTEXT);\n const state = readHarnessState(execution.environment);\n const home = execution.environment.HOME ?? nodeHost.homeDirectory();\n const repoSkills = path.join(execution.repoRoot, '.po', 'skills');\n const sources: SkillSource[] = [];\n const diagnostics: string[] = [];\n // A malformed domain is a configuration error in one domain, so it must not\n // remove every other domain's skills. Enumerating the whole manifest is new\n // exposure here: reading the launch selection could not fail this way.\n const domains: string[] = [];\n try {\n domains.push(...(await listDomainNamesAsync(fs, execution.repoRoot, context, home)));\n } catch (error) {\n diagnostics.push(`Domain skills are unavailable: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n // Domain-scoped plugin skills come first. The host keeps the first command\n // registered for a name, so this ordering reproduces the collector's rule\n // that a selected plugin outranks a shared fallback of the same name.\n for (const domain of domains) {\n signal.throwIfAborted();\n try {\n const plugins = await materializePluginEntries(\n await resolvePluginEntriesAsync(fs, execution.repoRoot, [domain], [], context, home),\n );\n const mcpPluginRoots = (\n await Promise.all(\n plugins.map(async (plugin) =>\n (await isMcpSkillPlugin(fs, plugin, context)) ? path.join(plugin.directory, 'skills') : undefined,\n ),\n )\n ).filter((root): root is string => root !== undefined);\n const collected = await collectResources(execution.repoRoot, plugins, {\n agents: false,\n mcp: false,\n sharedSkills: false,\n });\n try {\n if (collected.skillDirectories.length > 0) {\n const paths = [...collected.skillDirectories];\n sources.push({\n domain,\n paths,\n // Exact collected paths retain this domain's per-plugin skill subset.\n // A plugin root would also admit skills loaded for another domain.\n mcpPaths: paths.filter((skillPath) => within(skillPath, mcpPluginRoots)),\n });\n }\n } finally {\n await collected.cleanup();\n }\n } catch (error) {\n diagnostics.push(`Domain '${domain}': ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n // Shared .claude/skills are not owned by any one domain, and a domain can opt\n // out of them. `when` cannot express \"unless every selected domain opts out\",\n // but registering a copy per domain that keeps them says the same thing: the\n // group is active if any such domain is selected, which is exactly what\n // resolveSharedSkills computes.\n signal.throwIfAborted();\n const shared = await discoverSkillsAsync(execution.repoRoot, path.join(execution.repoRoot, '.claude', 'skills'));\n if (shared.length > 0) {\n const sharedPaths = shared.map((skill) => skill.path);\n for (const domain of domains) {\n if (await resolveSharedSkillsAsync(fs, execution.repoRoot, [domain], context, home)) {\n sources.push({ domain, paths: sharedPaths, mcpPaths: sharedPaths, listed: true });\n }\n }\n }\n\n // Repository-local skills belong to the repository, not to a selection.\n sources.push({ paths: [repoSkills], mcpPaths: [repoSkills], listed: true });\n\n signal.throwIfAborted();\n // One walk for every group. Pi drops a path it has already loaded, so the\n // loader gets the unique set and each group selects its own skills back out.\n const unique = [...new Set([...sources.flatMap((source) => source.paths), ...(state.skillDirectories ?? [])])];\n const inventory = await new DeferredSkillLoader({ cwd: execution.cwd, skillPaths: unique }).ready();\n signal.throwIfAborted();\n\n const groups = sources\n .map((source) => ({\n ...(source.domain === undefined ? {} : { domain: source.domain }),\n skills: inventory.skills.filter((skill) => within(skill.filePath, source.paths)),\n }))\n .filter((group) => group.skills.length > 0);\n const listed = sources\n .filter((source) => source.listed === true)\n .map((source) => ({\n ...(source.domain === undefined ? {} : { domain: source.domain }),\n skills: inventory.skills.filter((skill) => within(skill.filePath, source.paths)),\n }))\n .filter((group) => group.skills.length > 0);\n const mcpGroups = sources\n .map((source) => ({\n ...(source.domain === undefined ? {} : { domain: source.domain }),\n skills: inventory.skills.filter((skill) => within(skill.filePath, source.mcpPaths)),\n }))\n .filter((group) => group.skills.length > 0);\n\n // The catalog still describes the active selection rather than everything on\n // disk, because it is prompt text rather than a menu.\n const activeSkills = inventory.skills.filter((skill) =>\n within(skill.filePath, [...(state.skillDirectories ?? []), repoSkills]),\n );\n return {\n inventory: { skills: inventory.skills, diagnostics: [...inventory.diagnostics, ...diagnostics] },\n groups,\n mcpGroups,\n listed,\n catalog: formatSkillsForPrompt(activeSkills) || '(no discovered skills)',\n };\n}\n","import type { PoHeadlessCommand } from '@agimon-ai/po-core/headless';\nimport type { Skill } from '@earendil-works/pi-coding-agent';\n\nimport { expandDeferredSkillCommand, type DeferredSkillSnapshot } from '../../../../../services/deferredSkills';\nimport type { ServerSkillGroup } from '../../../../../services/serverInventory';\nimport { SKILL_COMMAND_PREFIX, SKILL_INVOCATION_PREFIX, SKILLS_COMMAND } from '../../../../../types/skills';\n\n/**\n * One command per skill, gated by whatever activates that skill.\n *\n * Expansion always reads the full inventory, not the group: a command is only\n * dispatchable while its condition holds, so by the time one runs its skill is\n * active, and looking it up in the union keeps one lookup table instead of one\n * per domain.\n */\nfunction skillCommand(skill: Skill, domain: string | undefined, inventory: DeferredSkillSnapshot): PoHeadlessCommand {\n return {\n ...(domain === undefined ? {} : { when: { domain } }),\n name: `${SKILL_COMMAND_PREFIX}${skill.name}`,\n description: skill.description,\n execute: async (args, execution) => {\n const text = `${SKILL_INVOCATION_PREFIX}${skill.name}${args ? ` ${args}` : ''}`;\n const expanded = expandDeferredSkillCommand(text, inventory.skills);\n if (expanded === text) throw new Error(`Skill '${skill.name}' is no longer readable.`);\n await execution.session.prompt(expanded);\n },\n };\n}\n\nexport function createSkillCommands(\n inventory: DeferredSkillSnapshot,\n catalog: string,\n groups: readonly ServerSkillGroup[],\n): readonly PoHeadlessCommand[] {\n return [\n {\n name: SKILLS_COMMAND,\n description: 'List discovered skills or invoke one by name.',\n async execute(args, execution) {\n const requested = args.trim();\n if (requested) {\n await execution.session.prompt(\n expandDeferredSkillCommand(`${SKILL_INVOCATION_PREFIX}${requested}`, inventory.skills),\n );\n return;\n }\n await execution.client.notify({\n title: 'Po skills',\n body: catalog,\n level: 'info',\n });\n },\n },\n ...groups.flatMap((group) => group.skills.map((skill) => skillCommand(skill, group.domain, inventory))),\n ];\n}\n","import type { PoHeadlessHostService } from '@agimon-ai/po-core/headless';\nimport { BACKGROUND_CONTEXT, getOrThrow, type FileSystem } from '@agimon-ai/po-core/platform';\nimport { type PoServerSessionPlugin, packageResourcePath, readPackageResource } from '@agimon-ai/po-core/serverFacet';\n\nimport { mountMcpSkills } from '../../../../../services/mcpSkills';\nimport { createSessionLoadSkillTool } from '../../../../../services/mcpSkillTools';\nimport { discoverServerSkills } from '../../../../../services/serverInventory';\nimport { createSkillCommands } from './skillCommands';\n\nexport async function createSkillServer(\n agent: PoHeadlessHostService,\n fs: FileSystem,\n signal: AbortSignal,\n): Promise<PoServerSessionPlugin> {\n const { inventory, catalog, groups, mcpGroups, listed } = await discoverServerSkills(agent.context, fs, signal);\n return {\n commands: createSkillCommands(inventory, catalog, groups),\n tools: [createSessionLoadSkillTool(agent)],\n services: [mountMcpSkills(mcpGroups, fs, signal)],\n resources: [\n // Each skill joins the prompt's one <available_skills> list, gated like the rest.\n ...listed.flatMap((group) =>\n group.skills.map((skill) => ({\n name: skill.name,\n description: skill.description,\n path: skill.filePath,\n kind: 'skill' as const,\n ...(group.domain === undefined\n ? {}\n : { when: { domain: group.domain, attribution: { kind: 'domain' as const, mode: group.domain } } }),\n read: async () => getOrThrow(await fs.readTextFile(skill.filePath, BACKGROUND_CONTEXT)),\n })),\n ),\n ...[\n {\n name: 'po-author-skill',\n description:\n 'Author and distribute Po agent skills. Use when creating a SKILL.md, contributing a runtime skill directory, or publishing activation-gated Help prompts and diagnostic tools.',\n },\n {\n name: 'po-use-skill',\n description:\n \"Use Po's skill catalog and deferred discovery. Diagnose missing or shadowed skills and invoke the narrowest available guidance.\",\n },\n ].map((skill) => ({\n ...skill,\n when: { state: { 'minor-mode': 'help' }, attribution: { kind: 'minor' as const, mode: 'help' } },\n kind: 'skill' as const,\n path: packageResourcePath(import.meta.url, `src/prompts/${skill.name}/SKILL.md`),\n read: () => readPackageResource(import.meta.url, `src/prompts/${skill.name}/SKILL.md`),\n })),\n ],\n };\n}\n","import { defineRoot } from '@agimon-ai/po-core/extensionFile';\nimport { requirePoFs } from '@agimon-ai/po-core/platform';\nimport type { PoServerPluginContext, PoServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\n\nimport { createSkillServer } from './_lib/skillServer';\n\nexport default defineRoot(async ({ agent, context: root, signal }: PoServerPluginContext) => {\n const runtime: PoServerSessionPlugin = agent\n ? await createSkillServer(agent, requirePoFs(root), signal)\n : { commands: [], resources: [] };\n return { value: runtime, services: runtime.services };\n});\n","import { defineRoutedContribution } from '@agimon-ai/po-core/extensionFile';\nimport type { WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { PoServerPluginContext, PoServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\n\nexport default defineRoutedContribution(\n (context: WithRoot<PoServerPluginContext, PoServerSessionPlugin>) => context.root.commands!,\n { cardinality: 'many' },\n);\n","import { defineRoutedContribution } from '@agimon-ai/po-core/extensionFile';\nimport type { WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { PoServerPluginContext, PoServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\n\nexport default defineRoutedContribution(\n (context: WithRoot<PoServerPluginContext, PoServerSessionPlugin>) => context.root.resources!,\n { cardinality: 'many' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { PoServerPluginContext, PoServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\n\n/** The session agent's skill loader; the Pi CLI keeps Pi's own skill handling. */\nexport default defineRoutedContribution(\n (context: WithRoot<PoServerPluginContext, PoServerSessionPlugin>) => context.root.tools?.[0],\n { cardinality: 'optional' },\n);\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineServerPlugin, type PoServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\nimport { composeServerProviderOverrides } from '@agimon-ai/po-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/po-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport commandSkills from '../src/extensions/workspaces/sessions/(backend)/command/skills.server';\nimport resourceSkills from '../src/extensions/workspaces/sessions/(backend)/resource/skills.server';\nimport toolLoadSkill from '../src/extensions/workspaces/sessions/(backend)/tool/load_skill.server';\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};\n/* v8 ignore next -- generated normalization branch */\nconst defined = <T>(values: readonly (T | undefined)[]): T[] =>\n values.filter((value): value is T => value !== undefined);\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/po-skill',\n providerOverrides: composeServerProviderOverrides(rootSession),\n session: async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get commands(): PoServerSessionPlugin['commands'] { return [...many(commandSkills, contextSession)]; },\n get resources(): PoServerSessionPlugin['resources'] { return [...many(resourceSkills, contextSession)]; },\n get tools(): PoServerSessionPlugin['tools'] { return defined([via({ name: 'load_skill' }, at(toolLoadSkill, contextSession))]); },\n services: [...(scopeSession.services ?? [])],\n get activities(): PoServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":"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"}
1
+ {"version":3,"file":"server.mjs","names":["rootSession","commandSkills","resourceSkills","toolLoadSkill"],"sources":["../../src/constants/skillInventory.ts","../../src/services/mcpSkills/index.ts","../../src/schemas/mcpSkillTools.ts","../../src/services/mcpSkillTools/index.ts","../../src/services/deferredSkills/index.ts","../../src/services/serverInventory/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/skillCommands.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/skillServer.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/skills.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/skills.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/load_skill.server.ts","../../generated/server.ts"],"sourcesContent":["/**\n * How long sessions with the same inputs share one skill inventory instead of each reading the disk.\n * ponytail: a skill added on disk reaches new sessions within this window, not at once; watch the\n * skill roots if that lag matters.\n */\nexport const SKILL_INVENTORY_FRESH_MS = 60_000;\n","import type { PoMcpPluginContext, PoMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport { BACKGROUND_CONTEXT, getOrThrow, withAbortSignal, type FileSystem } from '@agimon-ai/po-core/platform';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport type { ServerSkillGroup } from '../serverInventory';\n\nexport const MCP_SKILLS_SERVICE = 'po/discovered-mcp-skills';\n\nexport interface McpSkillProvider {\n list(context: PoMcpPluginContext): readonly PoMcpSkill[];\n}\n\n/** Explicit remote provider, never a projection of the local resource registry. */\nexport function mountMcpSkills(groups: readonly ServerSkillGroup[], fs: FileSystem, 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, PoMcpSkill>();\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 = getOrThrow(\n await fs.readTextFile(skill.filePath, withAbortSignal(readSignal, BACKGROUND_CONTEXT)),\n );\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: PoMcpPluginContext): readonly PoMcpSkill[] {\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 { 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 { PoHeadlessHostService, PoHeadlessTool } 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<PoHeadlessTool['execute']>[4]) {\n if (context.mcpSkills === undefined) throw new Error('Remote skill access is unavailable.');\n return context.mcpSkills;\n}\n\nexport function createSearchSkillsTool(): PoHeadlessTool<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<PoHeadlessHostService, 'readSkill'>,\n): PoHeadlessTool<typeof loadSkillParameters> {\n return {\n // web-plugin-tool-renderers: ignore load_skill (server session only, shown as a generic call)\n // PO_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(): PoHeadlessTool<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 fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { Worker } from 'node:worker_threads';\n\nimport {\n type BuildSystemPromptOptions,\n formatSkillsForPrompt,\n getAgentDir,\n loadSkills,\n type Skill,\n stripFrontmatter,\n} from '@earendil-works/pi-coding-agent';\n\nimport type { DeferredSkillLoaderOptions, DeferredSkillSnapshot } from '../../types/skills';\n\nexport type { DeferredSkillLoaderOptions, DeferredSkillSnapshot } from '../../types/skills';\n\nconst PI_PACKAGE = '@earendil-works/pi-coding-agent';\nconst PACKAGE_MANIFEST = 'package.json';\n// A fresh worker takes ~240 ms to import Pi's main entry but ~20 ms for this module alone, and\n// every session spawns one. ponytail: not in Pi's exports map, so a Pi release that moves it\n// falls back to the main entry (slow, still correct); deferredSkills.test.ts pins the path.\nconst PI_SKILLS_MODULE = path.join('dist', 'core', 'skills.js');\nconst SKILL_WORKER_SOURCE = `\nconst { parentPort, workerData } = require('node:worker_threads');\nvoid (async () => {\n try {\n const { loadSkills } = await import(workerData.piModuleUrl);\n parentPort.postMessage({ ok: true, result: loadSkills(workerData.loadOptions) });\n } catch (error) {\n parentPort.postMessage({ ok: false, error: error instanceof Error ? error.message : String(error) });\n }\n})();\n`;\n\nfunction installedPiModuleUrl(): string {\n const anchors = [process.argv[1], fileURLToPath(import.meta.url), path.join(process.cwd(), PACKAGE_MANIFEST)];\n for (const anchor of anchors) {\n if (!anchor) continue;\n let directory = path.dirname(path.resolve(anchor));\n while (true) {\n const packageRoot = path.join(directory, 'node_modules', PI_PACKAGE);\n const manifestPath = path.join(packageRoot, PACKAGE_MANIFEST);\n try {\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as { main?: unknown };\n if (typeof manifest.main === 'string') {\n const entry = path.resolve(packageRoot, manifest.main);\n const skills = path.join(packageRoot, PI_SKILLS_MODULE);\n if (fs.existsSync(skills)) return pathToFileURL(skills).href;\n if (fs.existsSync(entry)) return pathToFileURL(entry).href;\n }\n } catch {\n // This anchor does not expose Pi at this level; continue up its module chain.\n }\n const parent = path.dirname(directory);\n if (parent === directory) break;\n directory = parent;\n }\n }\n throw new Error(`Cannot resolve ${PI_PACKAGE} from the Po or host module trees`);\n}\n\ninterface SkillWorkerResult {\n ok: boolean;\n result?: { skills: Skill[]; diagnostics: Array<{ path?: string; message: string }> };\n error?: string;\n}\n\n/**\n * One session's Po-selected skill inventory.\n *\n * Construction is deliberately cheap. `start()` schedules the synchronous Pi\n * walker after session_start returns, while `ready()` is the single promise the\n * first input awaits before Pi expands `/skill:name`.\n */\nexport class DeferredSkillLoader {\n readonly #options: DeferredSkillLoaderOptions;\n #promise: Promise<DeferredSkillSnapshot> | undefined;\n\n constructor(options: DeferredSkillLoaderOptions) {\n this.#options = options;\n }\n\n start(): Promise<DeferredSkillSnapshot> {\n if (this.#promise) return this.#promise;\n\n if (!this.#options.schedule && !this.#options.load) {\n this.#promise = this.#loadInWorker();\n return this.#promise;\n }\n\n const schedule = this.#options.schedule ?? ((load: () => void) => setImmediate(load));\n this.#promise = new Promise((resolve) => {\n const fail = (error: unknown): void => {\n resolve(this.#failure(error));\n };\n try {\n schedule(() => {\n try {\n resolve(this.#load());\n } catch (error) {\n fail(error);\n }\n });\n } catch (error) {\n fail(error);\n }\n });\n return this.#promise;\n }\n\n ready(): Promise<DeferredSkillSnapshot> {\n return this.start();\n }\n\n #loadOptions(): { cwd: string; agentDir: string; skillPaths: string[]; includeDefaults: boolean } {\n return {\n cwd: this.#options.cwd,\n agentDir: this.#options.agentDir ?? getAgentDir(),\n skillPaths: [...this.#options.skillPaths],\n includeDefaults: false,\n };\n }\n\n #snapshot(result: {\n skills: Skill[];\n diagnostics: Array<{ path?: string; message: string }>;\n }): DeferredSkillSnapshot {\n return {\n skills: result.skills,\n diagnostics: result.diagnostics.map(\n (diagnostic) => `${diagnostic.path ?? this.#options.cwd}: ${diagnostic.message}`,\n ),\n };\n }\n\n #failure(error: unknown): DeferredSkillSnapshot {\n return {\n skills: [],\n diagnostics: [`${this.#options.cwd}: ${error instanceof Error ? error.message : String(error)}`],\n };\n }\n\n #load(): DeferredSkillSnapshot {\n return this.#snapshot((this.#options.load ?? loadSkills)(this.#loadOptions()));\n }\n\n #loadInWorker(): Promise<DeferredSkillSnapshot> {\n return new Promise((resolve) => {\n let settled = false;\n const settle = (snapshot: DeferredSkillSnapshot): void => {\n if (settled) return;\n settled = true;\n resolve(snapshot);\n };\n let worker: Worker;\n try {\n worker = new Worker(SKILL_WORKER_SOURCE, {\n eval: true,\n workerData: {\n piModuleUrl: this.#options.piModuleUrl ?? installedPiModuleUrl(),\n loadOptions: this.#loadOptions(),\n },\n });\n } catch (error) {\n settle(this.#failure(error));\n return;\n }\n worker.unref();\n worker.once('message', (message: SkillWorkerResult) => {\n if (!message.ok || !message.result) {\n settle(this.#failure(message.error ?? 'Skill worker failed'));\n return;\n }\n settle(this.#snapshot(message.result));\n });\n worker.once('error', (error) => settle(this.#failure(error)));\n worker.once('exit', (code) => {\n if (code !== 0) settle(this.#failure(`Skill worker exited with code ${code}`));\n });\n });\n }\n}\n\n/** Appends only the inventory Pi would append for these deferred skills. */\nexport function buildPromptWithDeferredSkills(\n systemPrompt: string,\n options: BuildSystemPromptOptions,\n skills: Skill[],\n): string {\n if (options.selectedTools && !options.selectedTools.includes('read')) return systemPrompt;\n return `${systemPrompt}${formatSkillsForPrompt(skills)}`;\n}\n\n/** Expands a deferred `/skill:name` before Pi consults its synchronous inventory. */\nexport function expandDeferredSkillCommand(text: string, skills: readonly Skill[]): string {\n if (!text.startsWith('/skill:')) return text;\n const spaceIndex = text.indexOf(' ');\n const skillName = spaceIndex === -1 ? text.slice(7) : text.slice(7, spaceIndex);\n const skill = skills.find((candidate) => candidate.name === skillName);\n if (!skill) return text;\n\n try {\n const args = spaceIndex === -1 ? '' : text.slice(spaceIndex + 1).trim();\n const body = stripFrontmatter(fs.readFileSync(skill.filePath, 'utf8')).trim();\n const skillBlock = `<skill name=\"${skill.name}\" location=\"${skill.filePath}\">\\nReferences are relative to ${skill.baseDir}.\\n\\n${body}\\n</skill>`;\n return args ? `${skillBlock}\\n\\n${args}` : skillBlock;\n } catch {\n // Pi uses the same literal-text fallback if a skill disappears between\n // discovery and submission; the agent can still respond to the command.\n return text;\n }\n}\n","import path from 'node:path';\n\nimport {\n listDomainNamesAsync,\n resolvePluginEntriesAsync,\n resolveSharedSkillsAsync,\n type PluginEntry,\n} from '@agimon-ai/po-config/domains';\nimport { readHarnessState } from '@agimon-ai/po-config/harnessState';\nimport type { PoHeadlessExecutionContext } from '@agimon-ai/po-core/headless';\nimport { BACKGROUND_CONTEXT, nodeHost, withAbortSignal, type FileSystem } from '@agimon-ai/po-core/platform';\nimport { materializePluginEntries } from '@agimon-ai/po-domain/plugins';\nimport { collectResources, discoverSkillsAsync } from '@agimon-ai/po-domain/resources';\nimport { formatSkillsForPrompt } from '@earendil-works/pi-coding-agent';\n\nimport type { ServerSkillInventory } from '../../types/skills';\nimport { DeferredSkillLoader } from '../deferredSkills';\n\nexport type { ServerSkillGroup, ServerSkillInventory } from '../../types/skills';\n\ninterface SkillSource {\n readonly domain?: string;\n readonly paths: readonly string[];\n readonly mcpPaths: readonly string[];\n /** Advertised by this package rather than by po-domain. */\n readonly listed?: boolean;\n}\n\nconst LOCAL_ONLY_MCP_PACKAGES = new Set([\n '@agimon-ai/po-author',\n '@agimon-ai/po-git',\n '@agimon-ai/po-goal',\n '@agimon-ai/po-help',\n '@agimon-ai/po-loop',\n '@agimon-ai/po-user-feedback',\n '@agimon-ai/po-voice',\n '@agimon-ai/po-workflow',\n]);\n\ntype IoContext = Parameters<FileSystem['readTextFile']>[1];\n\nasync function isMcpSkillPlugin(fs: FileSystem, entry: PluginEntry, context: IoContext): Promise<boolean> {\n if (entry.source?.type === 'npm') return !LOCAL_ONLY_MCP_PACKAGES.has(entry.source.package);\n // A package manifest is optional for catalog plugins, but a present identity\n // that cannot be read or parsed must never make the plugin remotely eligible.\n const source = await fs.readTextFile(path.join(entry.directory, 'package.json'), context);\n if (!source.ok) return source.error.code === 'not_found';\n try {\n const manifest = JSON.parse(source.value) as unknown;\n if (typeof manifest !== 'object' || manifest === null || Array.isArray(manifest)) return false;\n const name = (manifest as { name?: unknown }).name;\n return typeof name === 'string' && name.length > 0 && name.trim() === name && !LOCAL_ONLY_MCP_PACKAGES.has(name);\n } catch {\n return false;\n }\n}\n\n/**\n * Whether a discovered skill came from one of these paths.\n *\n * A source holds exact SKILL.md files for plugin and shared skills, but a bare\n * directory for `.po/skills`, so membership is containment rather than\n * equality.\n */\nfunction within(filePath: string, roots: readonly string[]): boolean {\n const resolved = path.resolve(filePath);\n return roots.some((root) => {\n const base = path.resolve(root);\n return resolved === base || resolved.startsWith(`${base}${path.sep}`);\n });\n}\n/**\n * Every skill the session could reach, grouped by what activates it.\n *\n * A cockpit `/domains` switch reconciles contributions rather than rebuilding\n * the server plugin: the session declaration is mounted once. So enumerating only the\n * launch selection would freeze the command list at whatever was selected when\n * the session host was built. Enumerating every domain up front and tagging\n * each group with its `when` lets the existing kernel refresh do the work, the\n * same way domainServerResources registers per-domain skill resources.\n */\nexport async function discoverServerSkills(\n execution: PoHeadlessExecutionContext,\n fs: FileSystem,\n signal: AbortSignal,\n): Promise<ServerSkillInventory> {\n signal.throwIfAborted();\n const context = withAbortSignal(signal, BACKGROUND_CONTEXT);\n const state = readHarnessState(execution.environment);\n const home = execution.environment.HOME ?? nodeHost.homeDirectory();\n const repoSkills = path.join(execution.repoRoot, '.po', 'skills');\n const sources: SkillSource[] = [];\n const diagnostics: string[] = [];\n // A malformed domain is a configuration error in one domain, so it must not\n // remove every other domain's skills. Enumerating the whole manifest is new\n // exposure here: reading the launch selection could not fail this way.\n const domains: string[] = [];\n try {\n domains.push(...(await listDomainNamesAsync(fs, execution.repoRoot, context, home)));\n } catch (error) {\n diagnostics.push(`Domain skills are unavailable: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n // Domain-scoped plugin skills come first. The host keeps the first command\n // registered for a name, so this ordering reproduces the collector's rule\n // that a selected plugin outranks a shared fallback of the same name.\n for (const domain of domains) {\n signal.throwIfAborted();\n try {\n const plugins = await materializePluginEntries(\n await resolvePluginEntriesAsync(fs, execution.repoRoot, [domain], [], context, home),\n );\n const mcpPluginRoots = (\n await Promise.all(\n plugins.map(async (plugin) =>\n (await isMcpSkillPlugin(fs, plugin, context)) ? path.join(plugin.directory, 'skills') : undefined,\n ),\n )\n ).filter((root): root is string => root !== undefined);\n const collected = await collectResources(execution.repoRoot, plugins, {\n agents: false,\n mcp: false,\n sharedSkills: false,\n });\n try {\n if (collected.skillDirectories.length > 0) {\n const paths = [...collected.skillDirectories];\n sources.push({\n domain,\n paths,\n // Exact collected paths retain this domain's per-plugin skill subset.\n // A plugin root would also admit skills loaded for another domain.\n mcpPaths: paths.filter((skillPath) => within(skillPath, mcpPluginRoots)),\n });\n }\n } finally {\n await collected.cleanup();\n }\n } catch (error) {\n diagnostics.push(`Domain '${domain}': ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n // Shared .claude/skills are not owned by any one domain, and a domain can opt\n // out of them. `when` cannot express \"unless every selected domain opts out\",\n // but registering a copy per domain that keeps them says the same thing: the\n // group is active if any such domain is selected, which is exactly what\n // resolveSharedSkills computes.\n signal.throwIfAborted();\n const shared = await discoverSkillsAsync(execution.repoRoot, path.join(execution.repoRoot, '.claude', 'skills'));\n if (shared.length > 0) {\n const sharedPaths = shared.map((skill) => skill.path);\n for (const domain of domains) {\n if (await resolveSharedSkillsAsync(fs, execution.repoRoot, [domain], context, home)) {\n sources.push({ domain, paths: sharedPaths, mcpPaths: sharedPaths, listed: true });\n }\n }\n }\n\n // Repository-local skills belong to the repository, not to a selection.\n sources.push({ paths: [repoSkills], mcpPaths: [repoSkills], listed: true });\n\n signal.throwIfAborted();\n // One walk for every group. Pi drops a path it has already loaded, so the\n // loader gets the unique set and each group selects its own skills back out.\n const unique = [...new Set([...sources.flatMap((source) => source.paths), ...(state.skillDirectories ?? [])])];\n const inventory = await new DeferredSkillLoader({ cwd: execution.cwd, skillPaths: unique }).ready();\n signal.throwIfAborted();\n\n const groups = sources\n .map((source) => ({\n ...(source.domain === undefined ? {} : { domain: source.domain }),\n skills: inventory.skills.filter((skill) => within(skill.filePath, source.paths)),\n }))\n .filter((group) => group.skills.length > 0);\n const listed = sources\n .filter((source) => source.listed === true)\n .map((source) => ({\n ...(source.domain === undefined ? {} : { domain: source.domain }),\n skills: inventory.skills.filter((skill) => within(skill.filePath, source.paths)),\n }))\n .filter((group) => group.skills.length > 0);\n const mcpGroups = sources\n .map((source) => ({\n ...(source.domain === undefined ? {} : { domain: source.domain }),\n skills: inventory.skills.filter((skill) => within(skill.filePath, source.mcpPaths)),\n }))\n .filter((group) => group.skills.length > 0);\n\n // The catalog still describes the active selection rather than everything on\n // disk, because it is prompt text rather than a menu.\n const activeSkills = inventory.skills.filter((skill) =>\n within(skill.filePath, [...(state.skillDirectories ?? []), repoSkills]),\n );\n return {\n inventory: { skills: inventory.skills, diagnostics: [...inventory.diagnostics, ...diagnostics] },\n groups,\n mcpGroups,\n listed,\n catalog: formatSkillsForPrompt(activeSkills) || '(no discovered skills)',\n };\n}\n","import type { PoHeadlessCommand } from '@agimon-ai/po-core/headless';\nimport type { Skill } from '@earendil-works/pi-coding-agent';\n\nimport { expandDeferredSkillCommand, type DeferredSkillSnapshot } from '../../../../../services/deferredSkills';\nimport type { ServerSkillGroup } from '../../../../../services/serverInventory';\nimport { SKILL_COMMAND_PREFIX, SKILL_INVOCATION_PREFIX, SKILLS_COMMAND } from '../../../../../types/skills';\n\n/**\n * One command per skill, gated by whatever activates that skill.\n *\n * Expansion always reads the full inventory, not the group: a command is only\n * dispatchable while its condition holds, so by the time one runs its skill is\n * active, and looking it up in the union keeps one lookup table instead of one\n * per domain.\n */\nfunction skillCommand(skill: Skill, domain: string | undefined, inventory: DeferredSkillSnapshot): PoHeadlessCommand {\n return {\n ...(domain === undefined ? {} : { when: { domain } }),\n name: `${SKILL_COMMAND_PREFIX}${skill.name}`,\n description: skill.description,\n execute: async (args, execution) => {\n const text = `${SKILL_INVOCATION_PREFIX}${skill.name}${args ? ` ${args}` : ''}`;\n const expanded = expandDeferredSkillCommand(text, inventory.skills);\n if (expanded === text) throw new Error(`Skill '${skill.name}' is no longer readable.`);\n await execution.session.prompt(expanded);\n },\n };\n}\n\nexport function createSkillCommands(\n inventory: DeferredSkillSnapshot,\n catalog: string,\n groups: readonly ServerSkillGroup[],\n): readonly PoHeadlessCommand[] {\n return [\n {\n name: SKILLS_COMMAND,\n description: 'List discovered skills or invoke one by name.',\n async execute(args, execution) {\n const requested = args.trim();\n if (requested) {\n await execution.session.prompt(\n expandDeferredSkillCommand(`${SKILL_INVOCATION_PREFIX}${requested}`, inventory.skills),\n );\n return;\n }\n await execution.client.notify({\n title: 'Po skills',\n body: catalog,\n level: 'info',\n });\n },\n },\n ...groups.flatMap((group) => group.skills.map((skill) => skillCommand(skill, group.domain, inventory))),\n ];\n}\n","import { readHarnessState } from '@agimon-ai/po-config/harnessState';\nimport type { PoHeadlessHostService } from '@agimon-ai/po-core/headless';\nimport { BACKGROUND_CONTEXT, getOrThrow, nodeHost, type FileSystem } from '@agimon-ai/po-core/platform';\nimport {\n type PoServerResources,\n type PoServerSessionPlugin,\n packageResourcePath,\n readPackageResource,\n} from '@agimon-ai/po-core/serverPlugin';\n\nimport { SKILL_INVENTORY_FRESH_MS } from '../../../../../constants/skillInventory';\nimport { mountMcpSkills } from '../../../../../services/mcpSkills';\nimport { createSessionLoadSkillTool } from '../../../../../services/mcpSkillTools';\nimport { discoverServerSkills } from '../../../../../services/serverInventory';\nimport { createSkillCommands } from './skillCommands';\n\nexport async function createSkillServer(\n agent: PoHeadlessHostService,\n fs: FileSystem,\n signal: AbortSignal,\n resources: PoServerResources,\n): Promise<PoServerSessionPlugin> {\n const execution = agent.context;\n // Sessions with the same inputs share one discovery. The key holds every input discoverServerSkills\n // reads besides the disk, so equal keys give equal inventories, and the window bounds how old that\n // read of the disk can be.\n const key = [\n 'inventory',\n execution.repoRoot,\n execution.cwd,\n execution.environment.HOME ?? nodeHost.homeDirectory(),\n ...(readHarnessState(execution.environment).skillDirectories ?? []),\n Math.floor(Date.now() / SKILL_INVENTORY_FRESH_MS),\n ];\n const { inventory, catalog, groups, mcpGroups, listed } = await resources.acquire(key, () =>\n // Every session sharing the discovery waits on it, so none of their signals may abort it.\n discoverServerSkills(execution, fs, new AbortController().signal),\n );\n return {\n commands: createSkillCommands(inventory, catalog, groups),\n tools: [createSessionLoadSkillTool(agent)],\n services: [mountMcpSkills(mcpGroups, fs, signal)],\n resources: [\n // Each skill joins the prompt's one <available_skills> list, gated like the rest.\n ...listed.flatMap((group) =>\n group.skills.map((skill) => ({\n name: skill.name,\n description: skill.description,\n path: skill.filePath,\n kind: 'skill' as const,\n ...(group.domain === undefined\n ? {}\n : { when: { domain: group.domain, attribution: { kind: 'domain' as const, mode: group.domain } } }),\n read: async () => getOrThrow(await fs.readTextFile(skill.filePath, BACKGROUND_CONTEXT)),\n })),\n ),\n ...[\n {\n name: 'po-author-skill',\n description:\n 'Author and distribute Po agent skills. Use when creating a SKILL.md, contributing a runtime skill directory, or publishing activation-gated Help prompts and diagnostic tools.',\n },\n {\n name: 'po-use-skill',\n description:\n \"Use Po's skill catalog and deferred discovery. Diagnose missing or shadowed skills and invoke the narrowest available guidance.\",\n },\n ].map((skill) => ({\n ...skill,\n when: { state: { 'minor-mode': 'help' }, attribution: { kind: 'minor' as const, mode: 'help' } },\n kind: 'skill' as const,\n path: packageResourcePath(import.meta.url, `src/prompts/${skill.name}/SKILL.md`),\n read: () => readPackageResource(import.meta.url, `src/prompts/${skill.name}/SKILL.md`),\n })),\n ],\n };\n}\n","import { defineRoot } from '@agimon-ai/po-core/extensionFile';\nimport { requirePoFs } from '@agimon-ai/po-core/platform';\nimport type { PoServerPluginContext, PoServerSessionPlugin } from '@agimon-ai/po-core/serverPlugin';\n\nimport { createSkillServer } from './_lib/skillServer';\n\nexport default defineRoot(async ({ agent, context: root, signal, resources }: PoServerPluginContext) => {\n const runtime: PoServerSessionPlugin = agent\n ? await createSkillServer(agent, requirePoFs(root), signal, resources)\n : { commands: [], resources: [] };\n return { value: runtime, services: runtime.services };\n});\n","import { defineRoutedContribution } from '@agimon-ai/po-core/extensionFile';\nimport type { WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { PoServerPluginContext, PoServerSessionPlugin } from '@agimon-ai/po-core/serverPlugin';\n\nexport default defineRoutedContribution(\n (context: WithRoot<PoServerPluginContext, PoServerSessionPlugin>) => context.root.commands!,\n { cardinality: 'many' },\n);\n","import { defineRoutedContribution } from '@agimon-ai/po-core/extensionFile';\nimport type { WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { PoServerPluginContext, PoServerSessionPlugin } from '@agimon-ai/po-core/serverPlugin';\n\nexport default defineRoutedContribution(\n (context: WithRoot<PoServerPluginContext, PoServerSessionPlugin>) => context.root.resources!,\n { cardinality: 'many' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { PoServerPluginContext, PoServerSessionPlugin } from '@agimon-ai/po-core/serverPlugin';\n\n/** The session agent's skill loader; the Pi CLI keeps Pi's own skill handling. */\nexport default defineRoutedContribution(\n (context: WithRoot<PoServerPluginContext, PoServerSessionPlugin>) => context.root.tools?.[0],\n { cardinality: 'optional' },\n);\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineServerPlugin, type PoServerSessionPlugin } from '@agimon-ai/po-core/serverPlugin';\nimport { composeServerProviderOverrides } from '@agimon-ai/po-core/serverPlugin';\nimport { composeRootHooks, composeRootInjects } from '@agimon-ai/po-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport commandSkills from '../src/extensions/workspaces/sessions/(backend)/command/skills.server';\nimport resourceSkills from '../src/extensions/workspaces/sessions/(backend)/resource/skills.server';\nimport toolLoadSkill from '../src/extensions/workspaces/sessions/(backend)/tool/load_skill.server';\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};\n/* v8 ignore next -- generated normalization branch */\nconst defined = <T>(values: readonly (T | undefined)[]): T[] =>\n values.filter((value): value is T => value !== undefined);\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const serverPlugin = defineServerPlugin({\n name: '@agimon-ai/po-skill',\n providerOverrides: composeServerProviderOverrides(rootSession),\n injects: composeRootInjects({ session: [rootSession] }),\n session: async (context) => {\n const scopeSession = await context.scopeRoot('session', rootSession, context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get commands(): PoServerSessionPlugin['commands'] { return [...many(commandSkills, contextSession)]; },\n get resources(): PoServerSessionPlugin['resources'] { return [...many(resourceSkills, contextSession)]; },\n get tools(): PoServerSessionPlugin['tools'] { return defined([via({ name: 'load_skill' }, at(toolLoadSkill, contextSession))]); },\n services: [...(scopeSession.services ?? [])],\n get activities(): PoServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default serverPlugin;\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/po-skill",
3
- "version": "0.0.0-alpha.13",
3
+ "version": "0.0.0-alpha.15",
4
4
  "description": "Session skill catalogue, deferred skill discovery, and the skill browser for Po.",
5
5
  "keywords": [
6
6
  "agent-skills",
@@ -65,19 +65,19 @@
65
65
  "access": "public"
66
66
  },
67
67
  "dependencies": {
68
- "@agimon-ai/po-config": "0.0.0-alpha.13",
69
- "@agimon-ai/po-core": "0.0.0-alpha.13",
70
- "@agimon-ai/po-domain": "0.0.0-alpha.13",
71
- "@agimon-ai/po-telemetry": "0.0.0-alpha.13",
72
- "@agimon-ai/po-web-components": "0.0.0-alpha.13",
73
- "@deepseek-ai/cordis": "4.0.4",
68
+ "@agimon-ai/po-config": "0.0.0-alpha.15",
69
+ "@agimon-ai/po-core": "0.0.0-alpha.15",
70
+ "@agimon-ai/po-domain": "0.0.0-alpha.15",
71
+ "@agimon-ai/po-telemetry": "0.0.0-alpha.15",
72
+ "@agimon-ai/po-web-components": "0.0.0-alpha.15",
73
+ "@deepseek-ai/cordis": "4.0.5",
74
74
  "gpt-tokenizer": "4.0.0",
75
75
  "typebox": "1.3.37"
76
76
  },
77
77
  "devDependencies": {
78
- "@agimon-ai/po-build": "0.0.0-alpha.13",
79
- "@agimon-ai/vibe-lint-plugin-po-extension": "0.0.0-alpha.13",
80
- "@deepseek-ai/cordis": "4.0.4",
78
+ "@agimon-ai/po-build": "0.0.0-alpha.15",
79
+ "@agimon-ai/vibe-lint-plugin-po-extension": "0.0.0-alpha.15",
80
+ "@deepseek-ai/cordis": "4.0.5",
81
81
  "@earendil-works/pi-coding-agent": "1.3.0",
82
82
  "@types/node": "26.6.5",
83
83
  "@types/react": "19.3.0",