@agimon-ai/po-skill 0.0.0-alpha.24 → 0.0.0-alpha.25

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.
@@ -404,10 +404,17 @@ function skillCommand(skill, domain, inventory) {
404
404
  const text = `${require_skills.SKILL_INVOCATION_PREFIX}${skill.name}${args ? ` ${args}` : ""}`;
405
405
  const expanded = expandDeferredSkillCommand(text, inventory.skills);
406
406
  if (expanded === text) throw new Error(`Skill '${skill.name}' is no longer readable.`);
407
- await execution.session.prompt(expanded);
407
+ await admit(execution.session, expanded);
408
408
  }
409
409
  };
410
410
  }
411
+ /**
412
+ * The dispatching prompt acks when this command returns, so awaiting the whole
413
+ * turn (session.prompt) kept the composer draft until the run ended.
414
+ */
415
+ function admit(session, text) {
416
+ return session.admitPrompt ? session.admitPrompt(text, "prompt", "operator") : session.prompt(text);
417
+ }
411
418
  function createSkillCommands(inventory, catalog, groups) {
412
419
  return [{
413
420
  name: require_skills.SKILLS_COMMAND,
@@ -415,7 +422,7 @@ function createSkillCommands(inventory, catalog, groups) {
415
422
  async execute(args, execution) {
416
423
  const requested = args.trim();
417
424
  if (requested) {
418
- await execution.session.prompt(expandDeferredSkillCommand(`${require_skills.SKILL_INVOCATION_PREFIX}${requested}`, inventory.skills));
425
+ await admit(execution.session, expandDeferredSkillCommand(`${require_skills.SKILL_INVOCATION_PREFIX}${requested}`, inventory.skills));
419
426
  return;
420
427
  }
421
428
  await execution.client.notify({
@@ -1 +1 @@
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
+ {"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 admit(execution.session, expanded);\n },\n };\n}\n\n/**\n * The dispatching prompt acks when this command returns, so awaiting the whole\n * turn (session.prompt) kept the composer draft until the run ended.\n */\nfunction admit(session: Parameters<PoHeadlessCommand['execute']>[1]['session'], text: string): Promise<void> {\n return session.admitPrompt ? session.admitPrompt(text, 'prompt', 'operator') : session.prompt(text);\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 admit(\n execution.session,\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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"}
@@ -397,10 +397,17 @@ function skillCommand(skill, domain, inventory) {
397
397
  const text = `${SKILL_INVOCATION_PREFIX}${skill.name}${args ? ` ${args}` : ""}`;
398
398
  const expanded = expandDeferredSkillCommand(text, inventory.skills);
399
399
  if (expanded === text) throw new Error(`Skill '${skill.name}' is no longer readable.`);
400
- await execution.session.prompt(expanded);
400
+ await admit(execution.session, expanded);
401
401
  }
402
402
  };
403
403
  }
404
+ /**
405
+ * The dispatching prompt acks when this command returns, so awaiting the whole
406
+ * turn (session.prompt) kept the composer draft until the run ended.
407
+ */
408
+ function admit(session, text) {
409
+ return session.admitPrompt ? session.admitPrompt(text, "prompt", "operator") : session.prompt(text);
410
+ }
404
411
  function createSkillCommands(inventory, catalog, groups) {
405
412
  return [{
406
413
  name: SKILLS_COMMAND,
@@ -408,7 +415,7 @@ function createSkillCommands(inventory, catalog, groups) {
408
415
  async execute(args, execution) {
409
416
  const requested = args.trim();
410
417
  if (requested) {
411
- await execution.session.prompt(expandDeferredSkillCommand(`${SKILL_INVOCATION_PREFIX}${requested}`, inventory.skills));
418
+ await admit(execution.session, expandDeferredSkillCommand(`${SKILL_INVOCATION_PREFIX}${requested}`, inventory.skills));
412
419
  return;
413
420
  }
414
421
  await execution.client.notify({
@@ -1 +1 @@
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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"}
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 admit(execution.session, expanded);\n },\n };\n}\n\n/**\n * The dispatching prompt acks when this command returns, so awaiting the whole\n * turn (session.prompt) kept the composer draft until the run ended.\n */\nfunction admit(session: Parameters<PoHeadlessCommand['execute']>[1]['session'], text: string): Promise<void> {\n return session.admitPrompt ? session.admitPrompt(text, 'prompt', 'operator') : session.prompt(text);\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 admit(\n execution.session,\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":";;;;;;;;;;;;;;;;;;;;AAKA,MAAa,2BAA2B;;;ACCxC,MAAa,qBAAqB;;AAOlC,SAAgB,eAAe,QAAqC,IAAgB,QAAqB;CACvG,QAAQ,YAA2B;EACjC,QAAQ,QAAQ,oBAAoB,EAClC,KAAK,QAAQ;GACX,OAAO,eAAe;GACtB,OAAO,OAAO,eAAe;GAC7B,MAAM,UAAU,OAAO,UAAU,KAAK,CAAC,CAAC;GACxC,MAAM,yBAAS,IAAI,IAAwB;GAC3C,KAAK,MAAM,SAAS,QAAQ;IAC1B,IAAI,MAAM,WAAW,KAAA,KAAa,CAAC,QAAQ,SAAS,MAAM,MAAM,GAAG;IACnE,KAAK,MAAM,SAAS,MAAM,QAAQ;KAEhC,IAAI,OAAO,IAAI,MAAM,IAAI,GAAG;KAC5B,OAAO,IAAI,MAAM,MAAM;MACrB,MAAM,MAAM;MACZ,aAAa,MAAM;MACnB,MAAM,OAAO;OACX,MAAM,aAAa,YAAY,IAAI,CAAC,QAAQ,OAAO,MAAM,CAAC;OAC1D,WAAW,eAAe;OAC1B,MAAM,OAAO,WACX,MAAM,GAAG,aAAa,MAAM,UAAU,gBAAgB,YAAY,kBAAkB,CAAC,CACvF;OACA,WAAW,eAAe;OAC1B,OAAO;MACT;KACF,CAAC;IACH;GACF;GACA,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC;EAC5B,EACF,CAA4B;CAC9B;AACF;AC3CsC,KAAK,OAAO,EAAE,OAAO,KAAK,SAAS,KAAK,OAAO,CAAC,EAAE,CAAC;AACzF,MAAa,sBAAsB,KAAK,OAAO,EAAE,MAAM,KAAK,OAAO,EAAE,CAAC;;;ACCtE,SAAS,KAAK,MAAc;CAC1B,OAAO,EAAE,SAAS,CAAC;EAAE,MAAM;EAAiB;CAAK,CAAC,EAAE;AACtD;;;;;AA+BA,SAAgB,2BACd,MAC4C;CAC5C,OAAO;EAGL,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY;EACZ,eAAe;EACf,MAAM,QAAQ,aAAa,EAAE,QAAQ;GACnC,MAAM,OAAO,KAAK,UAAU,IAAI;GAChC,IAAI,SAAS,KAAA,GAAW,OAAO;IAAE,GAAG,KAAK,kBAAkB,KAAK,+BAA+B;IAAG,SAAS;GAAK;GAChH,OAAO,KAAK,IAAI;EAClB;CACF;AACF;;;ACpCA,MAAM,aAAa;AACnB,MAAM,mBAAmB;AAIzB,MAAM,mBAAmB,KAAK,KAAK,QAAQ,QAAQ,WAAW;AAC9D,MAAM,sBAAsB;;;;;;;;;;;AAY5B,SAAS,uBAA+B;CACtC,MAAM,UAAU;EAAC,QAAQ,KAAK;EAAI,cAAc,YAAY,GAAG;EAAG,KAAK,KAAK,QAAQ,IAAI,GAAG,gBAAgB;CAAC;CAC5G,KAAK,MAAM,UAAU,SAAS;EAC5B,IAAI,CAAC,QAAQ;EACb,IAAI,YAAY,KAAK,QAAQ,KAAK,QAAQ,MAAM,CAAC;EACjD,OAAO,MAAM;GACX,MAAM,cAAc,KAAK,KAAK,WAAW,gBAAgB,UAAU;GACnE,MAAM,eAAe,KAAK,KAAK,aAAa,gBAAgB;GAC5D,IAAI;IACF,MAAM,WAAW,KAAK,MAAM,GAAG,aAAa,cAAc,MAAM,CAAC;IACjE,IAAI,OAAO,SAAS,SAAS,UAAU;KACrC,MAAM,QAAQ,KAAK,QAAQ,aAAa,SAAS,IAAI;KACrD,MAAM,SAAS,KAAK,KAAK,aAAa,gBAAgB;KACtD,IAAI,GAAG,WAAW,MAAM,GAAG,OAAO,cAAc,MAAM,CAAC,CAAC;KACxD,IAAI,GAAG,WAAW,KAAK,GAAG,OAAO,cAAc,KAAK,CAAC,CAAC;IACxD;GACF,QAAQ,CAER;GACA,MAAM,SAAS,KAAK,QAAQ,SAAS;GACrC,IAAI,WAAW,WAAW;GAC1B,YAAY;EACd;CACF;CACA,MAAM,IAAI,MAAM,kBAAkB,WAAW,kCAAkC;AACjF;;;;;;;;AAeA,IAAa,sBAAb,MAAiC;CAC/B;CACA;CAEA,YAAY,SAAqC;EAC/C,KAAK,WAAW;CAClB;CAEA,QAAwC;EACtC,IAAI,KAAK,UAAU,OAAO,KAAK;EAE/B,IAAI,CAAC,KAAK,SAAS,YAAY,CAAC,KAAK,SAAS,MAAM;GAClD,KAAK,WAAW,KAAK,cAAc;GACnC,OAAO,KAAK;EACd;EAEA,MAAM,WAAW,KAAK,SAAS,cAAc,SAAqB,aAAa,IAAI;EACnF,KAAK,WAAW,IAAI,SAAS,YAAY;GACvC,MAAM,QAAQ,UAAyB;IACrC,QAAQ,KAAK,SAAS,KAAK,CAAC;GAC9B;GACA,IAAI;IACF,eAAe;KACb,IAAI;MACF,QAAQ,KAAK,MAAM,CAAC;KACtB,SAAS,OAAO;MACd,KAAK,KAAK;KACZ;IACF,CAAC;GACH,SAAS,OAAO;IACd,KAAK,KAAK;GACZ;EACF,CAAC;EACD,OAAO,KAAK;CACd;CAEA,QAAwC;EACtC,OAAO,KAAK,MAAM;CACpB;CAEA,eAAkG;EAChG,OAAO;GACL,KAAK,KAAK,SAAS;GACnB,UAAU,KAAK,SAAS,YAAY,YAAY;GAChD,YAAY,CAAC,GAAG,KAAK,SAAS,UAAU;GACxC,iBAAiB;EACnB;CACF;CAEA,UAAU,QAGgB;EACxB,OAAO;GACL,QAAQ,OAAO;GACf,aAAa,OAAO,YAAY,KAC7B,eAAe,GAAG,WAAW,QAAQ,KAAK,SAAS,IAAI,IAAI,WAAW,SACzE;EACF;CACF;CAEA,SAAS,OAAuC;EAC9C,OAAO;GACL,QAAQ,CAAC;GACT,aAAa,CAAC,GAAG,KAAK,SAAS,IAAI,IAAI,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG;EACjG;CACF;CAEA,QAA+B;EAC7B,OAAO,KAAK,WAAW,KAAK,SAAS,QAAQ,WAAA,CAAY,KAAK,aAAa,CAAC,CAAC;CAC/E;CAEA,gBAAgD;EAC9C,OAAO,IAAI,SAAS,YAAY;GAC9B,IAAI,UAAU;GACd,MAAM,UAAU,aAA0C;IACxD,IAAI,SAAS;IACb,UAAU;IACV,QAAQ,QAAQ;GAClB;GACA,IAAI;GACJ,IAAI;IACF,SAAS,IAAI,OAAO,qBAAqB;KACvC,MAAM;KACN,YAAY;MACV,aAAa,KAAK,SAAS,eAAe,qBAAqB;MAC/D,aAAa,KAAK,aAAa;KACjC;IACF,CAAC;GACH,SAAS,OAAO;IACd,OAAO,KAAK,SAAS,KAAK,CAAC;IAC3B;GACF;GACA,OAAO,MAAM;GACb,OAAO,KAAK,YAAY,YAA+B;IACrD,IAAI,CAAC,QAAQ,MAAM,CAAC,QAAQ,QAAQ;KAClC,OAAO,KAAK,SAAS,QAAQ,SAAS,qBAAqB,CAAC;KAC5D;IACF;IACA,OAAO,KAAK,UAAU,QAAQ,MAAM,CAAC;GACvC,CAAC;GACD,OAAO,KAAK,UAAU,UAAU,OAAO,KAAK,SAAS,KAAK,CAAC,CAAC;GAC5D,OAAO,KAAK,SAAS,SAAS;IAC5B,IAAI,SAAS,GAAG,OAAO,KAAK,SAAS,iCAAiC,MAAM,CAAC;GAC/E,CAAC;EACH,CAAC;CACH;AACF;;AAaA,SAAgB,2BAA2B,MAAc,QAAkC;CACzF,IAAI,CAAC,KAAK,WAAW,SAAS,GAAG,OAAO;CACxC,MAAM,aAAa,KAAK,QAAQ,GAAG;CACnC,MAAM,YAAY,eAAe,KAAK,KAAK,MAAM,CAAC,IAAI,KAAK,MAAM,GAAG,UAAU;CAC9E,MAAM,QAAQ,OAAO,MAAM,cAAc,UAAU,SAAS,SAAS;CACrE,IAAI,CAAC,OAAO,OAAO;CAEnB,IAAI;EACF,MAAM,OAAO,eAAe,KAAK,KAAK,KAAK,MAAM,aAAa,CAAC,CAAC,CAAC,KAAK;EACtE,MAAM,OAAO,iBAAiB,GAAG,aAAa,MAAM,UAAU,MAAM,CAAC,CAAC,CAAC,KAAK;EAC5E,MAAM,aAAa,gBAAgB,MAAM,KAAK,cAAc,MAAM,SAAS,iCAAiC,MAAM,QAAQ,OAAO,KAAK;EACtI,OAAO,OAAO,GAAG,WAAW,MAAM,SAAS;CAC7C,QAAQ;EAGN,OAAO;CACT;AACF;;;ACzLA,MAAM,0CAA0B,IAAI,IAAI;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAID,eAAe,iBAAiB,IAAgB,OAAoB,SAAsC;CACxG,IAAI,MAAM,QAAQ,SAAS,OAAO,OAAO,CAAC,wBAAwB,IAAI,MAAM,OAAO,OAAO;CAG1F,MAAM,SAAS,MAAM,GAAG,aAAa,KAAK,KAAK,MAAM,WAAW,cAAc,GAAG,OAAO;CACxF,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,MAAM,SAAS;CAC7C,IAAI;EACF,MAAM,WAAW,KAAK,MAAM,OAAO,KAAK;EACxC,IAAI,OAAO,aAAa,YAAY,aAAa,QAAQ,MAAM,QAAQ,QAAQ,GAAG,OAAO;EACzF,MAAM,OAAQ,SAAgC;EAC9C,OAAO,OAAO,SAAS,YAAY,KAAK,SAAS,KAAK,KAAK,KAAK,MAAM,QAAQ,CAAC,wBAAwB,IAAI,IAAI;CACjH,QAAQ;EACN,OAAO;CACT;AACF;;;;;;;;AASA,SAAS,OAAO,UAAkB,OAAmC;CACnE,MAAM,WAAW,KAAK,QAAQ,QAAQ;CACtC,OAAO,MAAM,MAAM,SAAS;EAC1B,MAAM,OAAO,KAAK,QAAQ,IAAI;EAC9B,OAAO,aAAa,QAAQ,SAAS,WAAW,GAAG,OAAO,KAAK,KAAK;CACtE,CAAC;AACH;;;;;;;;;;;AAWA,eAAsB,qBACpB,WACA,IACA,QAC+B;CAC/B,OAAO,eAAe;CACtB,MAAM,UAAU,gBAAgB,QAAQ,kBAAkB;CAC1D,MAAM,QAAQ,iBAAiB,UAAU,WAAW;CACpD,MAAM,OAAO,UAAU,YAAY,QAAQ,SAAS,cAAc;CAClE,MAAM,aAAa,KAAK,KAAK,UAAU,UAAU,OAAO,QAAQ;CAChE,MAAM,UAAyB,CAAC;CAChC,MAAM,cAAwB,CAAC;CAI/B,MAAM,UAAoB,CAAC;CAC3B,IAAI;EACF,QAAQ,KAAK,GAAI,MAAM,qBAAqB,IAAI,UAAU,UAAU,SAAS,IAAI,CAAE;CACrF,SAAS,OAAO;EACd,YAAY,KAAK,kCAAkC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG;CAC7G;CAKA,KAAK,MAAM,UAAU,SAAS;EAC5B,OAAO,eAAe;EACtB,IAAI;GACF,MAAM,UAAU,MAAM,yBACpB,MAAM,0BAA0B,IAAI,UAAU,UAAU,CAAC,MAAM,GAAG,CAAC,GAAG,SAAS,IAAI,CACrF;GACA,MAAM,kBACJ,MAAM,QAAQ,IACZ,QAAQ,IAAI,OAAO,WAChB,MAAM,iBAAiB,IAAI,QAAQ,OAAO,IAAK,KAAK,KAAK,OAAO,WAAW,QAAQ,IAAI,KAAA,CAC1F,CACF,EAAA,CACA,QAAQ,SAAyB,SAAS,KAAA,CAAS;GACrD,MAAM,YAAY,MAAM,iBAAiB,UAAU,UAAU,SAAS;IACpE,QAAQ;IACR,KAAK;IACL,cAAc;GAChB,CAAC;GACD,IAAI;IACF,IAAI,UAAU,iBAAiB,SAAS,GAAG;KACzC,MAAM,QAAQ,CAAC,GAAG,UAAU,gBAAgB;KAC5C,QAAQ,KAAK;MACX;MACA;MAGA,UAAU,MAAM,QAAQ,cAAc,OAAO,WAAW,cAAc,CAAC;KACzE,CAAC;IACH;GACF,UAAU;IACR,MAAM,UAAU,QAAQ;GAC1B;EACF,SAAS,OAAO;GACd,YAAY,KAAK,WAAW,OAAO,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG;EAClG;CACF;CAOA,OAAO,eAAe;CACtB,MAAM,SAAS,MAAM,oBAAoB,UAAU,UAAU,KAAK,KAAK,UAAU,UAAU,WAAW,QAAQ,CAAC;CAC/G,IAAI,OAAO,SAAS,GAAG;EACrB,MAAM,cAAc,OAAO,KAAK,UAAU,MAAM,IAAI;EACpD,KAAK,MAAM,UAAU,SACnB,IAAI,MAAM,yBAAyB,IAAI,UAAU,UAAU,CAAC,MAAM,GAAG,SAAS,IAAI,GAChF,QAAQ,KAAK;GAAE;GAAQ,OAAO;GAAa,UAAU;GAAa,QAAQ;EAAK,CAAC;CAGtF;CAGA,QAAQ,KAAK;EAAE,OAAO,CAAC,UAAU;EAAG,UAAU,CAAC,UAAU;EAAG,QAAQ;CAAK,CAAC;CAE1E,OAAO,eAAe;CAGtB,MAAM,SAAS,CAAC,mBAAG,IAAI,IAAI,CAAC,GAAG,QAAQ,SAAS,WAAW,OAAO,KAAK,GAAG,GAAI,MAAM,oBAAoB,CAAC,CAAE,CAAC,CAAC;CAC7G,MAAM,YAAY,MAAM,IAAI,oBAAoB;EAAE,KAAK,UAAU;EAAK,YAAY;CAAO,CAAC,CAAC,CAAC,MAAM;CAClG,OAAO,eAAe;CAEtB,MAAM,SAAS,QACZ,KAAK,YAAY;EAChB,GAAI,OAAO,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,OAAO,OAAO;EAC/D,QAAQ,UAAU,OAAO,QAAQ,UAAU,OAAO,MAAM,UAAU,OAAO,KAAK,CAAC;CACjF,EAAE,CAAC,CACF,QAAQ,UAAU,MAAM,OAAO,SAAS,CAAC;CAC5C,MAAM,SAAS,QACZ,QAAQ,WAAW,OAAO,WAAW,IAAI,CAAC,CAC1C,KAAK,YAAY;EAChB,GAAI,OAAO,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,OAAO,OAAO;EAC/D,QAAQ,UAAU,OAAO,QAAQ,UAAU,OAAO,MAAM,UAAU,OAAO,KAAK,CAAC;CACjF,EAAE,CAAC,CACF,QAAQ,UAAU,MAAM,OAAO,SAAS,CAAC;CAC5C,MAAM,YAAY,QACf,KAAK,YAAY;EAChB,GAAI,OAAO,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,OAAO,OAAO;EAC/D,QAAQ,UAAU,OAAO,QAAQ,UAAU,OAAO,MAAM,UAAU,OAAO,QAAQ,CAAC;CACpF,EAAE,CAAC,CACF,QAAQ,UAAU,MAAM,OAAO,SAAS,CAAC;CAI5C,MAAM,eAAe,UAAU,OAAO,QAAQ,UAC5C,OAAO,MAAM,UAAU,CAAC,GAAI,MAAM,oBAAoB,CAAC,GAAI,UAAU,CAAC,CACxE;CACA,OAAO;EACL,WAAW;GAAE,QAAQ,UAAU;GAAQ,aAAa,CAAC,GAAG,UAAU,aAAa,GAAG,WAAW;EAAE;EAC/F;EACA;EACA;EACA,SAAS,sBAAsB,YAAY,KAAK;CAClD;AACF;;;;;;;;;;;AC1LA,SAAS,aAAa,OAAc,QAA4B,WAAqD;CACnH,OAAO;EACL,GAAI,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;EACnD,MAAM,GAAG,uBAAuB,MAAM;EACtC,aAAa,MAAM;EACnB,SAAS,OAAO,MAAM,cAAc;GAClC,MAAM,OAAO,GAAG,0BAA0B,MAAM,OAAO,OAAO,IAAI,SAAS;GAC3E,MAAM,WAAW,2BAA2B,MAAM,UAAU,MAAM;GAClE,IAAI,aAAa,MAAM,MAAM,IAAI,MAAM,UAAU,MAAM,KAAK,yBAAyB;GACrF,MAAM,MAAM,UAAU,SAAS,QAAQ;EACzC;CACF;AACF;;;;;AAMA,SAAS,MAAM,SAAiE,MAA6B;CAC3G,OAAO,QAAQ,cAAc,QAAQ,YAAY,MAAM,UAAU,UAAU,IAAI,QAAQ,OAAO,IAAI;AACpG;AACA,SAAgB,oBACd,WACA,SACA,QAC8B;CAC9B,OAAO,CACL;EACE,MAAM;EACN,aAAa;EACb,MAAM,QAAQ,MAAM,WAAW;GAC7B,MAAM,YAAY,KAAK,KAAK;GAC5B,IAAI,WAAW;IACb,MAAM,MACJ,UAAU,SACV,2BAA2B,GAAG,0BAA0B,aAAa,UAAU,MAAM,CACvF;IACA;GACF;GACA,MAAM,UAAU,OAAO,OAAO;IAC5B,OAAO;IACP,MAAM;IACN,OAAO;GACT,CAAC;EACH;CACF,GACA,GAAG,OAAO,SAAS,UAAU,MAAM,OAAO,KAAK,UAAU,aAAa,OAAO,MAAM,QAAQ,SAAS,CAAC,CAAC,CACxG;AACF;;;AC/CA,eAAsB,kBACpB,OACA,IACA,QACA,WACgC;CAChC,MAAM,YAAY,MAAM;CAIxB,MAAM,MAAM;EACV;EACA,UAAU;EACV,UAAU;EACV,UAAU,YAAY,QAAQ,SAAS,cAAc;EACrD,GAAI,iBAAiB,UAAU,WAAW,CAAC,CAAC,oBAAoB,CAAC;EACjE,KAAK,MAAM,KAAK,IAAI,IAAI,wBAAwB;CAClD;CACA,MAAM,EAAE,WAAW,SAAS,QAAQ,WAAW,WAAW,MAAM,UAAU,QAAQ,WAEhF,qBAAqB,WAAW,IAAI,IAAI,gBAAgB,CAAC,CAAC,MAAM,CAClE;CACA,OAAO;EACL,UAAU,oBAAoB,WAAW,SAAS,MAAM;EACxD,OAAO,CAAC,2BAA2B,KAAK,CAAC;EACzC,UAAU,CAAC,eAAe,WAAW,IAAI,MAAM,CAAC;EAChD,WAAW,CAET,GAAG,OAAO,SAAS,UACjB,MAAM,OAAO,KAAK,WAAW;GAC3B,MAAM,MAAM;GACZ,aAAa,MAAM;GACnB,MAAM,MAAM;GACZ,MAAM;GACN,GAAI,MAAM,WAAW,KAAA,IACjB,CAAC,IACD,EAAE,MAAM;IAAE,QAAQ,MAAM;IAAQ,aAAa;KAAE,MAAM;KAAmB,MAAM,MAAM;IAAO;GAAE,EAAE;GACnG,MAAM,YAAY,WAAW,MAAM,GAAG,aAAa,MAAM,UAAU,kBAAkB,CAAC;EACxF,EAAE,CACJ,GACA,GAAG,CACD;GACE,MAAM;GACN,aACE;EACJ,GACA;GACE,MAAM;GACN,aACE;EACJ,CACF,CAAC,CAAC,KAAK,WAAW;GAChB,GAAG;GACH,MAAM;IAAE,OAAO,EAAE,cAAc,OAAO;IAAG,aAAa;KAAE,MAAM;KAAkB,MAAM;IAAO;GAAE;GAC/F,MAAM;GACN,MAAM,oBAAoB,YAAY,KAAK,eAAe,MAAM,KAAK,UAAU;GAC/E,YAAY,oBAAoB,YAAY,KAAK,eAAe,MAAM,KAAK,UAAU;EACvF,EAAE,CACJ;CACF;AACF;;;ACtEA,IAAA,sBAAe,WAAW,OAAO,EAAE,OAAO,SAAS,MAAM,QAAQ,gBAAuC;CACtG,MAAM,UAAiC,QACnC,MAAM,kBAAkB,OAAO,YAAY,IAAI,GAAG,QAAQ,SAAS,IACnE;EAAE,UAAU,CAAC;EAAG,WAAW,CAAC;CAAE;CAClC,OAAO;EAAE,OAAO;EAAS,UAAU,QAAQ;CAAS;AACtD,CAAC;;;ACPD,IAAA,0BAAe,0BACZ,YAAoE,QAAQ,KAAK,UAClF,EAAE,aAAa,OAAO,CACxB;;;ACHA,IAAA,wBAAe,0BACZ,YAAoE,QAAQ,KAAK,WAClF,EAAE,aAAa,OAAO,CACxB;;;;ACHA,IAAA,4BAAe,0BACZ,YAAoE,QAAQ,KAAK,QAAQ,IAC1F,EAAE,aAAa,WAAW,CAC5B;;;ACIA,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AAEpE,MAAM,QAAc,OAA6C,YAA6B;CAC5F,MAAM,WAAW,OAAO,UAAU,aAAc,MAA4B,OAAO,IAAI;CACvF,OAAO,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC,QAAa;AAC5D;;AAEA,MAAM,WAAc,WAClB,OAAO,QAAQ,UAAsB,UAAU,KAAA,CAAS;AAC1D,MAAM,OAAU,UAAmC,UAChD,UAAU,KAAA,IAAY,KAAA,IAAY;CAAE,GAAG;CAAU,GAAI;AAAiB;AAEzE,MAAa,eAAe,mBAAmB;CAC7C,MAAM;CACN,mBAAmB,+BAA+BA,mBAAW;CAC7D,SAAS,mBAAmB,EAAE,SAAS,CAACA,mBAAW,EAAE,CAAC;CACtD,SAAS,OAAO,YAAY;EAC1B,MAAM,eAAe,MAAM,QAAQ,UAAU,WAAWA,qBAAa,OAAO;EAC5E,MAAM,iBAAiB;GAAE,GAAG;GAAS,MAAM,aAAa;EAAM;EAC9D,OAAO;GACL,GAAG,iBAAiB,YAAY;GAChC,IAAI,WAA8C;IAAE,OAAO,CAAC,GAAG,KAAKC,yBAAe,cAAc,CAAC;GAAG;GACrG,IAAI,YAAgD;IAAE,OAAO,CAAC,GAAG,KAAKC,uBAAgB,cAAc,CAAC;GAAG;GACxG,IAAI,QAAwC;IAAE,OAAO,QAAQ,CAAC,IAAI,EAAE,MAAM,aAAa,GAAG,GAAGC,2BAAe,cAAc,CAAC,CAAC,CAAC;GAAG;GAChI,UAAU,CAAC,GAAI,aAAa,YAAY,CAAC,CAAE;GAC3C,IAAI,aAAkD;IAAE,OAAO,CAAC,GAAI,aAAa,cAAc,CAAC,CAAE;GAAG;EACvG;CACF;AACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/po-skill",
3
- "version": "0.0.0-alpha.24",
3
+ "version": "0.0.0-alpha.25",
4
4
  "description": "Session skill catalogue, deferred skill discovery, and the skill browser for Po.",
5
5
  "keywords": [
6
6
  "agent-skills",
@@ -65,18 +65,18 @@
65
65
  "access": "public"
66
66
  },
67
67
  "dependencies": {
68
- "@agimon-ai/po-config": "0.0.0-alpha.24",
69
- "@agimon-ai/po-core": "0.0.0-alpha.24",
70
- "@agimon-ai/po-domain": "0.0.0-alpha.24",
71
- "@agimon-ai/po-telemetry": "0.0.0-alpha.24",
72
- "@agimon-ai/po-web-components": "0.0.0-alpha.24",
68
+ "@agimon-ai/po-config": "0.0.0-alpha.25",
69
+ "@agimon-ai/po-core": "0.0.0-alpha.25",
70
+ "@agimon-ai/po-domain": "0.0.0-alpha.25",
71
+ "@agimon-ai/po-telemetry": "0.0.0-alpha.25",
72
+ "@agimon-ai/po-web-components": "0.0.0-alpha.25",
73
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.24",
79
- "@agimon-ai/vibe-lint-plugin-po-extension": "0.0.0-alpha.24",
78
+ "@agimon-ai/po-build": "0.0.0-alpha.25",
79
+ "@agimon-ai/vibe-lint-plugin-po-extension": "0.0.0-alpha.25",
80
80
  "@deepseek-ai/cordis": "4.0.5",
81
81
  "@earendil-works/pi-coding-agent": "1.3.0",
82
82
  "@types/node": "26.6.5",