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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -0
  3. package/dist/apiContracts.cjs +17 -0
  4. package/dist/apiContracts.cjs.map +1 -0
  5. package/dist/apiContracts.d.mts +53 -0
  6. package/dist/apiContracts.d.mts.map +1 -0
  7. package/dist/apiContracts.mjs +13 -0
  8. package/dist/apiContracts.mjs.map +1 -0
  9. package/dist/catalog.cjs +186 -0
  10. package/dist/catalog.cjs.map +1 -0
  11. package/dist/catalog.d.mts +66 -0
  12. package/dist/catalog.d.mts.map +1 -0
  13. package/dist/catalog.mjs +181 -0
  14. package/dist/catalog.mjs.map +1 -0
  15. package/dist/extensions/mcp-ui.mjs +31 -0
  16. package/dist/extensions/mcp-ui.mjs.map +1 -0
  17. package/dist/extensions/mcp.cjs +130 -0
  18. package/dist/extensions/mcp.cjs.map +1 -0
  19. package/dist/extensions/mcp.d.mts +5 -0
  20. package/dist/extensions/mcp.d.mts.map +1 -0
  21. package/dist/extensions/mcp.mjs +125 -0
  22. package/dist/extensions/mcp.mjs.map +1 -0
  23. package/dist/extensions/server.cjs +528 -0
  24. package/dist/extensions/server.cjs.map +1 -0
  25. package/dist/extensions/server.d.mts +5 -0
  26. package/dist/extensions/server.d.mts.map +1 -0
  27. package/dist/extensions/server.mjs +519 -0
  28. package/dist/extensions/server.mjs.map +1 -0
  29. package/dist/index.cjs +5 -0
  30. package/dist/index.d.mts +6 -0
  31. package/dist/index.d.mts.map +1 -0
  32. package/dist/index.mjs +2 -0
  33. package/dist/rolldown-runtime-VH7oDXx4.cjs +28 -0
  34. package/dist/skills-Ccvg1Hcz.mjs +8 -0
  35. package/dist/skills-Ccvg1Hcz.mjs.map +1 -0
  36. package/dist/skills-ComtgYb1.cjs +25 -0
  37. package/dist/skills-ComtgYb1.cjs.map +1 -0
  38. package/llms.txt +15 -0
  39. package/package.json +135 -0
  40. package/src/prompts/po-author-skill/SKILL.md +37 -0
  41. package/src/prompts/po-use-skill/SKILL.md +18 -0
@@ -0,0 +1,528 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ const require_rolldown_runtime = require("../rolldown-runtime-VH7oDXx4.cjs");
6
+ const require_skills = require("../skills-ComtgYb1.cjs");
7
+ let node_fs = require("node:fs");
8
+ node_fs = require_rolldown_runtime.__toESM(node_fs, 1);
9
+ let node_path = require("node:path");
10
+ node_path = require_rolldown_runtime.__toESM(node_path, 1);
11
+ let _agimon_ai_po_config_domains = require("@agimon-ai/po-config/domains");
12
+ let _agimon_ai_po_domain_plugins = require("@agimon-ai/po-domain/plugins");
13
+ let _earendil_works_pi_coding_agent = require("@earendil-works/pi-coding-agent");
14
+ let _agimon_ai_po_core_serverFacet = require("@agimon-ai/po-core/serverFacet");
15
+ let _agimon_ai_po_core_extensionFile = require("@agimon-ai/po-core/extensionFile");
16
+ let node_fs_promises = require("node:fs/promises");
17
+ let typebox = require("typebox");
18
+ let node_os = require("node:os");
19
+ node_os = require_rolldown_runtime.__toESM(node_os, 1);
20
+ let _agimon_ai_po_config_harnessState = require("@agimon-ai/po-config/harnessState");
21
+ let _agimon_ai_po_domain_resources = require("@agimon-ai/po-domain/resources");
22
+ let node_url = require("node:url");
23
+ let node_worker_threads = require("node:worker_threads");
24
+ //#region src/services/mcpSkills/index.ts
25
+ const MCP_SKILLS_SERVICE = "doom/discovered-mcp-skills";
26
+ /** Explicit remote provider, never a projection of the local resource registry. */
27
+ function mountMcpSkills(groups, signal) {
28
+ return (context) => {
29
+ context.provide(MCP_SKILLS_SERVICE, { list(remote) {
30
+ signal.throwIfAborted();
31
+ remote.signal.throwIfAborted();
32
+ const domains = remote.selection.read().domains;
33
+ const skills = /* @__PURE__ */ new Map();
34
+ for (const group of groups) {
35
+ if (group.domain !== void 0 && !domains.includes(group.domain)) continue;
36
+ for (const skill of group.skills) {
37
+ if (skills.has(skill.name)) continue;
38
+ skills.set(skill.name, {
39
+ name: skill.name,
40
+ description: skill.description,
41
+ async read() {
42
+ const readSignal = AbortSignal.any([signal, remote.signal]);
43
+ readSignal.throwIfAborted();
44
+ const text = await (0, node_fs_promises.readFile)(skill.filePath, {
45
+ encoding: "utf8",
46
+ signal: readSignal
47
+ });
48
+ readSignal.throwIfAborted();
49
+ return text;
50
+ }
51
+ });
52
+ }
53
+ }
54
+ return [...skills.values()];
55
+ } });
56
+ };
57
+ }
58
+ typebox.Type.Object({ query: typebox.Type.Optional(typebox.Type.String()) });
59
+ const loadSkillParameters = typebox.Type.Object({ name: typebox.Type.String() });
60
+ //#endregion
61
+ //#region src/services/mcpSkillTools/index.ts
62
+ function text(text) {
63
+ return { content: [{
64
+ type: "text",
65
+ text
66
+ }] };
67
+ }
68
+ /**
69
+ * The session agent's way into a skill. Its skills are listed in the prompt, which Po
70
+ * controls, so it needs no search; a remote agent's prompt is not ours, hence the pair above.
71
+ */
72
+ function createSessionLoadSkillTool(host) {
73
+ return {
74
+ name: "load_skill",
75
+ label: "Load skill",
76
+ description: "Load the full instructions of a skill from the available skills list by exact name.",
77
+ parameters: loadSkillParameters,
78
+ executionMode: "parallel",
79
+ async execute(_toolCallId, { name }) {
80
+ const body = host.readSkill(name);
81
+ if (body === void 0) return {
82
+ ...text(`No skill named ${name} is available in this session.`),
83
+ isError: true
84
+ };
85
+ return text(body);
86
+ }
87
+ };
88
+ }
89
+ //#endregion
90
+ //#region src/services/deferredSkills/index.ts
91
+ const PI_PACKAGE = "@earendil-works/pi-coding-agent";
92
+ const PACKAGE_MANIFEST = "package.json";
93
+ const SKILL_WORKER_SOURCE = `
94
+ const { parentPort, workerData } = require('node:worker_threads');
95
+ void (async () => {
96
+ try {
97
+ const { loadSkills } = await import(workerData.piModuleUrl);
98
+ parentPort.postMessage({ ok: true, result: loadSkills(workerData.loadOptions) });
99
+ } catch (error) {
100
+ parentPort.postMessage({ ok: false, error: error instanceof Error ? error.message : String(error) });
101
+ }
102
+ })();
103
+ `;
104
+ function installedPiModuleUrl() {
105
+ const anchors = [
106
+ process.argv[1],
107
+ (0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href),
108
+ node_path.default.join(process.cwd(), PACKAGE_MANIFEST)
109
+ ];
110
+ for (const anchor of anchors) {
111
+ if (!anchor) continue;
112
+ let directory = node_path.default.dirname(node_path.default.resolve(anchor));
113
+ while (true) {
114
+ const packageRoot = node_path.default.join(directory, "node_modules", PI_PACKAGE);
115
+ const manifestPath = node_path.default.join(packageRoot, PACKAGE_MANIFEST);
116
+ try {
117
+ const manifest = JSON.parse(node_fs.default.readFileSync(manifestPath, "utf8"));
118
+ if (typeof manifest.main === "string") {
119
+ const entry = node_path.default.resolve(packageRoot, manifest.main);
120
+ if (node_fs.default.existsSync(entry)) return (0, node_url.pathToFileURL)(entry).href;
121
+ }
122
+ } catch {}
123
+ const parent = node_path.default.dirname(directory);
124
+ if (parent === directory) break;
125
+ directory = parent;
126
+ }
127
+ }
128
+ throw new Error(`Cannot resolve ${PI_PACKAGE} from the Po or host module trees`);
129
+ }
130
+ /**
131
+ * One session's Doom-selected skill inventory.
132
+ *
133
+ * Construction is deliberately cheap. `start()` schedules the synchronous Pi
134
+ * walker after session_start returns, while `ready()` is the single promise the
135
+ * first input awaits before Pi expands `/skill:name`.
136
+ */
137
+ var DeferredSkillLoader = class {
138
+ #options;
139
+ #promise;
140
+ constructor(options) {
141
+ this.#options = options;
142
+ }
143
+ start() {
144
+ if (this.#promise) return this.#promise;
145
+ if (!this.#options.schedule && !this.#options.load) {
146
+ this.#promise = this.#loadInWorker();
147
+ return this.#promise;
148
+ }
149
+ const schedule = this.#options.schedule ?? ((load) => setImmediate(load));
150
+ this.#promise = new Promise((resolve) => {
151
+ const fail = (error) => {
152
+ resolve(this.#failure(error));
153
+ };
154
+ try {
155
+ schedule(() => {
156
+ try {
157
+ resolve(this.#load());
158
+ } catch (error) {
159
+ fail(error);
160
+ }
161
+ });
162
+ } catch (error) {
163
+ fail(error);
164
+ }
165
+ });
166
+ return this.#promise;
167
+ }
168
+ ready() {
169
+ return this.start();
170
+ }
171
+ #loadOptions() {
172
+ return {
173
+ cwd: this.#options.cwd,
174
+ agentDir: this.#options.agentDir ?? (0, _earendil_works_pi_coding_agent.getAgentDir)(),
175
+ skillPaths: [...this.#options.skillPaths],
176
+ includeDefaults: false
177
+ };
178
+ }
179
+ #snapshot(result) {
180
+ return {
181
+ skills: result.skills,
182
+ diagnostics: result.diagnostics.map((diagnostic) => `${diagnostic.path ?? this.#options.cwd}: ${diagnostic.message}`)
183
+ };
184
+ }
185
+ #failure(error) {
186
+ return {
187
+ skills: [],
188
+ diagnostics: [`${this.#options.cwd}: ${error instanceof Error ? error.message : String(error)}`]
189
+ };
190
+ }
191
+ #load() {
192
+ return this.#snapshot((this.#options.load ?? _earendil_works_pi_coding_agent.loadSkills)(this.#loadOptions()));
193
+ }
194
+ #loadInWorker() {
195
+ return new Promise((resolve) => {
196
+ let settled = false;
197
+ const settle = (snapshot) => {
198
+ if (settled) return;
199
+ settled = true;
200
+ resolve(snapshot);
201
+ };
202
+ let worker;
203
+ try {
204
+ worker = new node_worker_threads.Worker(SKILL_WORKER_SOURCE, {
205
+ eval: true,
206
+ workerData: {
207
+ piModuleUrl: this.#options.piModuleUrl ?? installedPiModuleUrl(),
208
+ loadOptions: this.#loadOptions()
209
+ }
210
+ });
211
+ } catch (error) {
212
+ settle(this.#failure(error));
213
+ return;
214
+ }
215
+ worker.unref();
216
+ worker.once("message", (message) => {
217
+ if (!message.ok || !message.result) {
218
+ settle(this.#failure(message.error ?? "Skill worker failed"));
219
+ return;
220
+ }
221
+ settle(this.#snapshot(message.result));
222
+ });
223
+ worker.once("error", (error) => settle(this.#failure(error)));
224
+ worker.once("exit", (code) => {
225
+ if (code !== 0) settle(this.#failure(`Skill worker exited with code ${code}`));
226
+ });
227
+ });
228
+ }
229
+ };
230
+ /** Expands a deferred `/skill:name` before Pi consults its synchronous inventory. */
231
+ function expandDeferredSkillCommand(text, skills) {
232
+ if (!text.startsWith("/skill:")) return text;
233
+ const spaceIndex = text.indexOf(" ");
234
+ const skillName = spaceIndex === -1 ? text.slice(7) : text.slice(7, spaceIndex);
235
+ const skill = skills.find((candidate) => candidate.name === skillName);
236
+ if (!skill) return text;
237
+ try {
238
+ const args = spaceIndex === -1 ? "" : text.slice(spaceIndex + 1).trim();
239
+ const body = (0, _earendil_works_pi_coding_agent.stripFrontmatter)(node_fs.default.readFileSync(skill.filePath, "utf8")).trim();
240
+ const skillBlock = `<skill name="${skill.name}" location="${skill.filePath}">\nReferences are relative to ${skill.baseDir}.\n\n${body}\n</skill>`;
241
+ return args ? `${skillBlock}\n\n${args}` : skillBlock;
242
+ } catch {
243
+ return text;
244
+ }
245
+ }
246
+ //#endregion
247
+ //#region src/services/serverInventory/index.ts
248
+ const LOCAL_ONLY_MCP_PACKAGES = /* @__PURE__ */ new Set([
249
+ "@agimon-ai/po-author",
250
+ "@agimon-ai/po-git",
251
+ "@agimon-ai/po-goal",
252
+ "@agimon-ai/po-help",
253
+ "@agimon-ai/po-loop",
254
+ "@agimon-ai/po-user-feedback",
255
+ "@agimon-ai/po-voice",
256
+ "@agimon-ai/po-workflow"
257
+ ]);
258
+ async function isMcpSkillPlugin(entry) {
259
+ if (entry.source?.type === "npm") return !LOCAL_ONLY_MCP_PACKAGES.has(entry.source.package);
260
+ try {
261
+ const manifest = JSON.parse(await (0, node_fs_promises.readFile)(node_path.default.join(entry.directory, "package.json"), "utf8"));
262
+ if (typeof manifest !== "object" || manifest === null || Array.isArray(manifest)) return false;
263
+ const name = manifest.name;
264
+ return typeof name === "string" && name.length > 0 && name.trim() === name && !LOCAL_ONLY_MCP_PACKAGES.has(name);
265
+ } catch (error) {
266
+ return error.code === "ENOENT";
267
+ }
268
+ }
269
+ /**
270
+ * Whether a discovered skill came from one of these paths.
271
+ *
272
+ * A source holds exact SKILL.md files for plugin and shared skills, but a bare
273
+ * directory for `.po/skills`, so membership is containment rather than
274
+ * equality.
275
+ */
276
+ function within(filePath, roots) {
277
+ const resolved = node_path.default.resolve(filePath);
278
+ return roots.some((root) => {
279
+ const base = node_path.default.resolve(root);
280
+ return resolved === base || resolved.startsWith(`${base}${node_path.default.sep}`);
281
+ });
282
+ }
283
+ /**
284
+ * Every skill the session could reach, grouped by what activates it.
285
+ *
286
+ * A cockpit `/domains` switch reconciles contributions rather than rebuilding
287
+ * the facet: the session declaration is mounted once. So enumerating only the
288
+ * launch selection would freeze the command list at whatever was selected when
289
+ * the session host was built. Enumerating every domain up front and tagging
290
+ * each group with its `when` lets the existing kernel refresh do the work, the
291
+ * same way domainServerResources registers per-domain skill resources.
292
+ */
293
+ async function discoverServerSkills(execution, signal) {
294
+ signal.throwIfAborted();
295
+ const state = (0, _agimon_ai_po_config_harnessState.readHarnessState)(execution.environment);
296
+ const home = execution.environment.HOME ?? node_os.default.homedir();
297
+ const repoSkills = node_path.default.join(execution.repoRoot, ".po", "skills");
298
+ const sources = [];
299
+ const diagnostics = [];
300
+ const domains = [];
301
+ try {
302
+ domains.push(...(0, _agimon_ai_po_config_domains.listDomainNames)(execution.repoRoot, home));
303
+ } catch (error) {
304
+ diagnostics.push(`Domain skills are unavailable: ${error instanceof Error ? error.message : String(error)}`);
305
+ }
306
+ for (const domain of domains) {
307
+ signal.throwIfAborted();
308
+ try {
309
+ const plugins = await (0, _agimon_ai_po_domain_plugins.materializePluginEntries)((0, _agimon_ai_po_config_domains.resolvePluginEntries)(execution.repoRoot, [domain], [], home));
310
+ const mcpPluginRoots = (await Promise.all(plugins.map(async (plugin) => await isMcpSkillPlugin(plugin) ? node_path.default.join(plugin.directory, "skills") : void 0))).filter((root) => root !== void 0);
311
+ const collected = await (0, _agimon_ai_po_domain_resources.collectResources)(execution.repoRoot, plugins, {
312
+ agents: false,
313
+ mcp: false,
314
+ sharedSkills: false
315
+ });
316
+ try {
317
+ if (collected.skillDirectories.length > 0) {
318
+ const paths = [...collected.skillDirectories];
319
+ sources.push({
320
+ domain,
321
+ paths,
322
+ mcpPaths: paths.filter((skillPath) => within(skillPath, mcpPluginRoots))
323
+ });
324
+ }
325
+ } finally {
326
+ await collected.cleanup();
327
+ }
328
+ } catch (error) {
329
+ diagnostics.push(`Domain '${domain}': ${error instanceof Error ? error.message : String(error)}`);
330
+ }
331
+ }
332
+ signal.throwIfAborted();
333
+ const shared = await (0, _agimon_ai_po_domain_resources.discoverSkillsAsync)(execution.repoRoot, node_path.default.join(execution.repoRoot, ".claude", "skills"));
334
+ if (shared.length > 0) {
335
+ const sharedPaths = shared.map((skill) => skill.path);
336
+ for (const domain of domains) if ((0, _agimon_ai_po_config_domains.resolveSharedSkills)(execution.repoRoot, [domain], home)) sources.push({
337
+ domain,
338
+ paths: sharedPaths,
339
+ mcpPaths: sharedPaths,
340
+ listed: true
341
+ });
342
+ }
343
+ sources.push({
344
+ paths: [repoSkills],
345
+ mcpPaths: [repoSkills],
346
+ listed: true
347
+ });
348
+ signal.throwIfAborted();
349
+ const unique = [.../* @__PURE__ */ new Set([...sources.flatMap((source) => source.paths), ...state.skillDirectories ?? []])];
350
+ const inventory = await new DeferredSkillLoader({
351
+ cwd: execution.cwd,
352
+ skillPaths: unique
353
+ }).ready();
354
+ signal.throwIfAborted();
355
+ const groups = sources.map((source) => ({
356
+ ...source.domain === void 0 ? {} : { domain: source.domain },
357
+ skills: inventory.skills.filter((skill) => within(skill.filePath, source.paths))
358
+ })).filter((group) => group.skills.length > 0);
359
+ const listed = sources.filter((source) => source.listed === true).map((source) => ({
360
+ ...source.domain === void 0 ? {} : { domain: source.domain },
361
+ skills: inventory.skills.filter((skill) => within(skill.filePath, source.paths))
362
+ })).filter((group) => group.skills.length > 0);
363
+ const mcpGroups = sources.map((source) => ({
364
+ ...source.domain === void 0 ? {} : { domain: source.domain },
365
+ skills: inventory.skills.filter((skill) => within(skill.filePath, source.mcpPaths))
366
+ })).filter((group) => group.skills.length > 0);
367
+ const activeSkills = inventory.skills.filter((skill) => within(skill.filePath, [...state.skillDirectories ?? [], repoSkills]));
368
+ return {
369
+ inventory: {
370
+ skills: inventory.skills,
371
+ diagnostics: [...inventory.diagnostics, ...diagnostics]
372
+ },
373
+ groups,
374
+ mcpGroups,
375
+ listed,
376
+ catalog: (0, _earendil_works_pi_coding_agent.formatSkillsForPrompt)(activeSkills) || "(no discovered skills)"
377
+ };
378
+ }
379
+ //#endregion
380
+ //#region src/extensions/workspaces/sessions/(backend)/_lib/skillCommands.ts
381
+ /**
382
+ * One command per skill, gated by whatever activates that skill.
383
+ *
384
+ * Expansion always reads the full inventory, not the group: a command is only
385
+ * dispatchable while its condition holds, so by the time one runs its skill is
386
+ * active, and looking it up in the union keeps one lookup table instead of one
387
+ * per domain.
388
+ */
389
+ function skillCommand(skill, domain, inventory) {
390
+ return {
391
+ ...domain === void 0 ? {} : { when: { domain } },
392
+ name: `${require_skills.SKILL_COMMAND_PREFIX}${skill.name}`,
393
+ description: skill.description,
394
+ execute: async (args, execution) => {
395
+ const text = `${require_skills.SKILL_INVOCATION_PREFIX}${skill.name}${args ? ` ${args}` : ""}`;
396
+ const expanded = expandDeferredSkillCommand(text, inventory.skills);
397
+ if (expanded === text) throw new Error(`Skill '${skill.name}' is no longer readable.`);
398
+ await execution.session.prompt(expanded);
399
+ }
400
+ };
401
+ }
402
+ function createSkillCommands(inventory, catalog, groups) {
403
+ return [{
404
+ name: require_skills.SKILLS_COMMAND,
405
+ description: "List discovered skills or invoke one by name.",
406
+ async execute(args, execution) {
407
+ const requested = args.trim();
408
+ if (requested) {
409
+ await execution.session.prompt(expandDeferredSkillCommand(`${require_skills.SKILL_INVOCATION_PREFIX}${requested}`, inventory.skills));
410
+ return;
411
+ }
412
+ await execution.client.notify({
413
+ title: "Po skills",
414
+ body: catalog,
415
+ level: "info"
416
+ });
417
+ }
418
+ }, ...groups.flatMap((group) => group.skills.map((skill) => skillCommand(skill, group.domain, inventory)))];
419
+ }
420
+ //#endregion
421
+ //#region src/extensions/workspaces/sessions/(backend)/_lib/skillServer.ts
422
+ async function createSkillServer(agent, signal) {
423
+ const { inventory, catalog, groups, mcpGroups, listed } = await discoverServerSkills(agent.context, signal);
424
+ return {
425
+ commands: createSkillCommands(inventory, catalog, groups),
426
+ tools: [createSessionLoadSkillTool(agent)],
427
+ services: [mountMcpSkills(mcpGroups, signal)],
428
+ resources: [...listed.flatMap((group) => group.skills.map((skill) => ({
429
+ name: skill.name,
430
+ description: skill.description,
431
+ path: skill.filePath,
432
+ kind: "skill",
433
+ ...group.domain === void 0 ? {} : { when: {
434
+ domain: group.domain,
435
+ attribution: {
436
+ kind: "domain",
437
+ mode: group.domain
438
+ }
439
+ } },
440
+ read: () => (0, node_fs_promises.readFile)(skill.filePath, "utf8")
441
+ }))), ...[{
442
+ name: "po-author-skill",
443
+ description: "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."
444
+ }, {
445
+ name: "po-use-skill",
446
+ description: "Use Po's skill catalog and deferred discovery. Diagnose missing or shadowed skills and invoke the narrowest available guidance."
447
+ }].map((skill) => ({
448
+ ...skill,
449
+ when: {
450
+ state: { "minor-mode": "help" },
451
+ attribution: {
452
+ kind: "minor",
453
+ mode: "help"
454
+ }
455
+ },
456
+ kind: "skill",
457
+ path: (0, _agimon_ai_po_core_serverFacet.packageResourcePath)(require("url").pathToFileURL(__filename).href, `src/prompts/${skill.name}/SKILL.md`),
458
+ read: () => (0, _agimon_ai_po_core_serverFacet.readPackageResource)(require("url").pathToFileURL(__filename).href, `src/prompts/${skill.name}/SKILL.md`)
459
+ }))]
460
+ };
461
+ }
462
+ //#endregion
463
+ //#region src/extensions/workspaces/sessions/(backend)/root.server.ts
464
+ var root_server_default = (0, _agimon_ai_po_core_extensionFile.defineRoot)(async ({ agent, signal }) => {
465
+ const runtime = agent ? await createSkillServer(agent, signal) : {
466
+ commands: [],
467
+ resources: []
468
+ };
469
+ return {
470
+ value: runtime,
471
+ services: runtime.services
472
+ };
473
+ });
474
+ //#endregion
475
+ //#region src/extensions/workspaces/sessions/(backend)/command/skills.server.ts
476
+ var skills_server_default$1 = (0, _agimon_ai_po_core_extensionFile.defineRoutedContribution)((context) => context.root.commands, { cardinality: "many" });
477
+ //#endregion
478
+ //#region src/extensions/workspaces/sessions/(backend)/resource/skills.server.ts
479
+ var skills_server_default = (0, _agimon_ai_po_core_extensionFile.defineRoutedContribution)((context) => context.root.resources, { cardinality: "many" });
480
+ //#endregion
481
+ //#region src/extensions/workspaces/sessions/(backend)/tool/load_skill.server.ts
482
+ /** The session agent's skill loader; the Pi CLI keeps Pi's own skill handling. */
483
+ var load_skill_server_default = (0, _agimon_ai_po_core_extensionFile.defineRoutedContribution)((context) => context.root.tools?.[0], { cardinality: "optional" });
484
+ //#endregion
485
+ //#region generated/server.ts
486
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
487
+ const many = (value, context) => {
488
+ const resolved = typeof value === "function" ? value(context) : value;
489
+ return Array.isArray(resolved) ? resolved : [resolved];
490
+ };
491
+ /* v8 ignore next -- generated normalization branch */
492
+ const defined = (values) => values.filter((value) => value !== void 0);
493
+ const via = (identity, value) => value === void 0 ? void 0 : {
494
+ ...identity,
495
+ ...value
496
+ };
497
+ const facet = (0, _agimon_ai_po_core_serverFacet.defineServerPlugin)({
498
+ name: "@agimon-ai/po-skill",
499
+ providerOverrides: (0, _agimon_ai_po_core_serverFacet.composeServerProviderOverrides)(root_server_default),
500
+ session: async (context) => {
501
+ const scopeSession = await root_server_default(context);
502
+ const contextSession = {
503
+ ...context,
504
+ root: scopeSession.value
505
+ };
506
+ return {
507
+ ...(0, _agimon_ai_po_core_extensionFile.composeRootHooks)(scopeSession),
508
+ get commands() {
509
+ return [...many(skills_server_default$1, contextSession)];
510
+ },
511
+ get resources() {
512
+ return [...many(skills_server_default, contextSession)];
513
+ },
514
+ get tools() {
515
+ return defined([via({ name: "load_skill" }, at(load_skill_server_default, contextSession))]);
516
+ },
517
+ services: [...scopeSession.services ?? []],
518
+ get activities() {
519
+ return [...scopeSession.activities ?? []];
520
+ }
521
+ };
522
+ }
523
+ });
524
+ //#endregion
525
+ exports.default = facet;
526
+ exports.facet = facet;
527
+
528
+ //# sourceMappingURL=server.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.cjs","names":["readFile","Type","fileURLToPath","path","fs","pathToFileURL","getAgentDir","loadSkills","Worker","stripFrontmatter","readFile","path","readHarnessState","os","listDomainNames","materializePluginEntries","resolvePluginEntries","collectResources","discoverSkillsAsync","resolveSharedSkills","formatSkillsForPrompt","SKILL_COMMAND_PREFIX","SKILL_INVOCATION_PREFIX","SKILLS_COMMAND","readFile","packageResourcePath","readPackageResource","defineRoot","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineServerPlugin","composeServerProviderOverrides","rootSession","composeRootHooks","commandSkills","resourceSkills","toolLoadSkill"],"sources":["../../src/services/mcpSkills/index.ts","../../src/schemas/mcpSkillTools.ts","../../src/services/mcpSkillTools/index.ts","../../src/services/deferredSkills/index.ts","../../src/services/serverInventory/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/skillCommands.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/skillServer.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/skills.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/skills.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/load_skill.server.ts","../../generated/server.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\n\nimport type { DoomMcpPluginContext, DoomMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport type { ServerSkillGroup } from '../serverInventory';\n\nexport const MCP_SKILLS_SERVICE = 'doom/discovered-mcp-skills';\n\nexport interface McpSkillProvider {\n list(context: DoomMcpPluginContext): readonly DoomMcpSkill[];\n}\n\n/** Explicit remote provider, never a projection of the local resource registry. */\nexport function mountMcpSkills(groups: readonly ServerSkillGroup[], signal: AbortSignal) {\n return (context: Context): void => {\n context.provide(MCP_SKILLS_SERVICE, {\n list(remote) {\n signal.throwIfAborted();\n remote.signal.throwIfAborted();\n const domains = remote.selection.read().domains;\n const skills = new Map<string, DoomMcpSkill>();\n for (const group of groups) {\n if (group.domain !== undefined && !domains.includes(group.domain)) continue;\n for (const skill of group.skills) {\n // Match command precedence, including shared copies across domains.\n if (skills.has(skill.name)) continue;\n skills.set(skill.name, {\n name: skill.name,\n description: skill.description,\n async read() {\n const readSignal = AbortSignal.any([signal, remote.signal]);\n readSignal.throwIfAborted();\n const text = await readFile(skill.filePath, { encoding: 'utf8', signal: readSignal });\n readSignal.throwIfAborted();\n return text;\n },\n });\n }\n }\n return [...skills.values()];\n },\n } satisfies McpSkillProvider);\n };\n}\n\nexport function bindMcpSkills(context: DoomMcpPluginContext): readonly DoomMcpSkill[] {\n const provider = context.services.get<McpSkillProvider>(MCP_SKILLS_SERVICE);\n if (!provider) throw new Error('Discovered MCP skills are unavailable.');\n return provider.list(context);\n}\n","import { Type } from 'typebox';\n\nexport const searchSkillsParameters = Type.Object({ query: Type.Optional(Type.String()) });\nexport const loadSkillParameters = Type.Object({ name: Type.String() });\n","import type { DoomHeadlessHostService, DoomHeadlessTool } from '@agimon-ai/po-core/headless';\n\nimport { loadSkillParameters, searchSkillsParameters } from '../../schemas/mcpSkillTools';\n\nfunction text(text: string) {\n return { content: [{ type: 'text' as const, text }] };\n}\n\nfunction skills(context: Parameters<DoomHeadlessTool['execute']>[4]) {\n if (context.mcpSkills === undefined) throw new Error('Remote skill access is unavailable.');\n return context.mcpSkills;\n}\n\nexport function createSearchSkillsTool(): DoomHeadlessTool<typeof searchSkillsParameters> {\n return {\n // web-plugin-tool-renderers: ignore search_skills (remote MCP only)\n name: 'search_skills',\n label: 'Search skills',\n description: 'Discover repository and active-domain skills available to this remote connection.',\n parameters: searchSkillsParameters,\n annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },\n async execute(_toolCallId, { query }, _signal, _onUpdate, context) {\n const needle = query?.trim().toLocaleLowerCase();\n const available = await skills(context).list();\n const matches =\n needle === undefined || needle === ''\n ? available\n : available.filter(({ name, description }) => `${name}\\n${description}`.toLocaleLowerCase().includes(needle));\n return { ...text(JSON.stringify(matches)), structuredContent: { skills: matches } };\n },\n };\n}\n\n/**\n * The session agent's way into a skill. Its skills are listed in the prompt, which Po\n * controls, so it needs no search; a remote agent's prompt is not ours, hence the pair above.\n */\nexport function createSessionLoadSkillTool(\n host: Pick<DoomHeadlessHostService, 'readSkill'>,\n): DoomHeadlessTool<typeof loadSkillParameters> {\n return {\n // web-plugin-tool-renderers: ignore load_skill (server session only, shown as a generic call)\n // DOOM_LOAD_SKILL_TOOL, spelled out so the renderer rule can read it.\n name: 'load_skill',\n label: 'Load skill',\n description: 'Load the full instructions of a skill from the available skills list by exact name.',\n parameters: loadSkillParameters,\n executionMode: 'parallel',\n async execute(_toolCallId, { name }) {\n const body = host.readSkill(name);\n if (body === undefined) return { ...text(`No skill named ${name} is available in this session.`), isError: true };\n return text(body);\n },\n };\n}\n\nexport function createLoadSkillTool(): DoomHeadlessTool<typeof loadSkillParameters> {\n return {\n // web-plugin-tool-renderers: ignore load_skill (remote MCP only)\n name: 'load_skill',\n label: 'Load skill',\n description: 'Load the full Markdown instructions for an available remote skill by exact name.',\n parameters: loadSkillParameters,\n annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },\n async execute(_toolCallId, { name }, _signal, _onUpdate, context) {\n return text(await skills(context).read(name));\n },\n };\n}\n","import 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\nexport interface DeferredSkillSnapshot {\n skills: Skill[];\n diagnostics: string[];\n}\n\nconst PI_PACKAGE = '@earendil-works/pi-coding-agent';\nconst PACKAGE_MANIFEST = 'package.json';\nconst SKILL_WORKER_SOURCE = `\nconst { parentPort, workerData } = require('node:worker_threads');\nvoid (async () => {\n try {\n const { loadSkills } = await import(workerData.piModuleUrl);\n parentPort.postMessage({ ok: true, result: loadSkills(workerData.loadOptions) });\n } catch (error) {\n parentPort.postMessage({ ok: false, error: error instanceof Error ? error.message : String(error) });\n }\n})();\n`;\n\nfunction installedPiModuleUrl(): string {\n const anchors = [process.argv[1], fileURLToPath(import.meta.url), path.join(process.cwd(), PACKAGE_MANIFEST)];\n for (const anchor of anchors) {\n if (!anchor) continue;\n let directory = path.dirname(path.resolve(anchor));\n while (true) {\n const packageRoot = path.join(directory, 'node_modules', PI_PACKAGE);\n const manifestPath = path.join(packageRoot, PACKAGE_MANIFEST);\n try {\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as { main?: unknown };\n if (typeof manifest.main === 'string') {\n const entry = path.resolve(packageRoot, manifest.main);\n if (fs.existsSync(entry)) return pathToFileURL(entry).href;\n }\n } catch {\n // This anchor does not expose Pi at this level; continue up its module chain.\n }\n const parent = path.dirname(directory);\n if (parent === directory) break;\n directory = parent;\n }\n }\n throw new Error(`Cannot resolve ${PI_PACKAGE} from the Po or host module trees`);\n}\n\ninterface SkillWorkerResult {\n ok: boolean;\n result?: { skills: Skill[]; diagnostics: Array<{ path?: string; message: string }> };\n error?: string;\n}\n\nexport interface DeferredSkillLoaderOptions {\n cwd: string;\n skillPaths: readonly string[];\n agentDir?: string;\n piModuleUrl?: string;\n schedule?: (load: () => void) => void;\n load?: (options: { cwd: string; agentDir: string; skillPaths: string[]; includeDefaults: boolean }) => {\n skills: Skill[];\n diagnostics: Array<{ path?: string; message: string }>;\n };\n}\n\n/**\n * One session's Doom-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 { readFile } from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport {\n listDomainNames,\n resolvePluginEntries,\n resolveSharedSkills,\n type PluginEntry,\n} from '@agimon-ai/po-config/domains';\nimport { readHarnessState } from '@agimon-ai/po-config/harnessState';\nimport type { DoomHeadlessExecutionContext } from '@agimon-ai/po-core/headless';\nimport { materializePluginEntries } from '@agimon-ai/po-domain/plugins';\nimport { collectResources, discoverSkillsAsync } from '@agimon-ai/po-domain/resources';\nimport { formatSkillsForPrompt, type Skill } from '@earendil-works/pi-coding-agent';\n\nimport { DeferredSkillLoader, type DeferredSkillSnapshot } from '../deferredSkills';\n\n/** Skills and the domain whose selection activates them, or always-on when absent. */\nexport interface ServerSkillGroup {\n readonly domain?: string;\n readonly skills: readonly Skill[];\n}\n\nexport interface ServerSkillInventory {\n /** Every skill any selection can reach, so an activated command can still expand. */\n readonly inventory: DeferredSkillSnapshot;\n readonly groups: readonly ServerSkillGroup[];\n readonly mcpGroups: readonly ServerSkillGroup[];\n /**\n * The shared and repository skills this package advertises itself. Domain plugin skills are\n * left out: po-domain already contributes each one, and listing them twice was noise.\n */\n readonly listed: readonly ServerSkillGroup[];\n readonly catalog: string;\n}\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\nasync function isMcpSkillPlugin(entry: PluginEntry): Promise<boolean> {\n if (entry.source?.type === 'npm') return !LOCAL_ONLY_MCP_PACKAGES.has(entry.source.package);\n try {\n const manifest = JSON.parse(await readFile(path.join(entry.directory, 'package.json'), 'utf8')) 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 (error) {\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 return (error as NodeJS.ErrnoException).code === 'ENOENT';\n }\n}\n\n/**\n * Whether a discovered skill came from one of these paths.\n *\n * A source holds exact SKILL.md files for plugin and shared skills, but a bare\n * directory for `.po/skills`, so membership is containment rather than\n * equality.\n */\nfunction within(filePath: string, roots: readonly string[]): boolean {\n const resolved = path.resolve(filePath);\n return roots.some((root) => {\n const base = path.resolve(root);\n return resolved === base || resolved.startsWith(`${base}${path.sep}`);\n });\n}\n/**\n * Every skill the session could reach, grouped by what activates it.\n *\n * A cockpit `/domains` switch reconciles contributions rather than rebuilding\n * the facet: the session declaration is mounted once. So enumerating only the\n * launch selection would freeze the command list at whatever was selected when\n * the session host was built. Enumerating every domain up front and tagging\n * each group with its `when` lets the existing kernel refresh do the work, the\n * same way domainServerResources registers per-domain skill resources.\n */\nexport async function discoverServerSkills(\n execution: DoomHeadlessExecutionContext,\n signal: AbortSignal,\n): Promise<ServerSkillInventory> {\n signal.throwIfAborted();\n const state = readHarnessState(execution.environment);\n const home = execution.environment.HOME ?? os.homedir();\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(...listDomainNames(execution.repoRoot, 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(resolvePluginEntries(execution.repoRoot, [domain], [], home));\n const mcpPluginRoots = (\n await Promise.all(\n plugins.map(async (plugin) =>\n (await isMcpSkillPlugin(plugin)) ? 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 (resolveSharedSkills(execution.repoRoot, [domain], 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 { DoomHeadlessCommand } 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): DoomHeadlessCommand {\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 DoomHeadlessCommand[] {\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 { readFile } from 'node:fs/promises';\n\nimport type { DoomHeadlessHostService } from '@agimon-ai/po-core/headless';\nimport { type DoomServerSessionPlugin, packageResourcePath, readPackageResource } from '@agimon-ai/po-core/serverFacet';\n\nimport { mountMcpSkills } from '../../../../../services/mcpSkills';\nimport { createSessionLoadSkillTool } from '../../../../../services/mcpSkillTools';\nimport { discoverServerSkills } from '../../../../../services/serverInventory';\nimport { createSkillCommands } from './skillCommands';\n\nexport async function createSkillServer(\n agent: DoomHeadlessHostService,\n signal: AbortSignal,\n): Promise<DoomServerSessionPlugin> {\n const { inventory, catalog, groups, mcpGroups, listed } = await discoverServerSkills(agent.context, signal);\n return {\n commands: createSkillCommands(inventory, catalog, groups),\n tools: [createSessionLoadSkillTool(agent)],\n services: [mountMcpSkills(mcpGroups, 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: () => readFile(skill.filePath, 'utf8'),\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 type { DoomServerPluginContext, DoomServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\n\nimport { createSkillServer } from './_lib/skillServer';\n\nexport default defineRoot(async ({ agent, signal }: DoomServerPluginContext) => {\n const runtime: DoomServerSessionPlugin = agent\n ? await createSkillServer(agent, signal)\n : { commands: [], resources: [] };\n return { value: runtime, services: runtime.services };\n});\n","import { defineRoutedContribution } from '@agimon-ai/po-core/extensionFile';\nimport type { WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { DoomServerPluginContext, DoomServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\n\nexport default defineRoutedContribution(\n (context: WithRoot<DoomServerPluginContext, DoomServerSessionPlugin>) => 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 { DoomServerPluginContext, DoomServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\n\nexport default defineRoutedContribution(\n (context: WithRoot<DoomServerPluginContext, DoomServerSessionPlugin>) => context.root.resources!,\n { cardinality: 'many' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { DoomServerPluginContext, DoomServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\n\n/** The session agent's skill loader; the Pi CLI keeps Pi's own skill handling. */\nexport default defineRoutedContribution(\n (context: WithRoot<DoomServerPluginContext, DoomServerSessionPlugin>) => context.root.tools?.[0],\n { cardinality: 'optional' },\n);\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\nimport { composeServerProviderOverrides } from '@agimon-ai/po-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/po-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport commandSkills from '../src/extensions/workspaces/sessions/(backend)/command/skills.server';\nimport resourceSkills from '../src/extensions/workspaces/sessions/(backend)/resource/skills.server';\nimport toolLoadSkill from '../src/extensions/workspaces/sessions/(backend)/tool/load_skill.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\ntype ManyFactory<T, C> = (context: C) => T | readonly T[];\nconst many = <T, C>(value: T | readonly T[] | ManyFactory<T, C>, context: C): readonly T[] => {\n const resolved = typeof value === 'function' ? (value as ManyFactory<T, C>)(context) : value;\n return Array.isArray(resolved) ? resolved : [resolved as T];\n};\n/* v8 ignore next -- generated normalization branch */\nconst defined = <T>(values: readonly (T | undefined)[]): T[] =>\n values.filter((value): value is T => value !== undefined);\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/po-skill',\n providerOverrides: composeServerProviderOverrides(rootSession),\n session: async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get commands(): DoomServerSessionPlugin['commands'] { return [...many(commandSkills, contextSession)]; },\n get resources(): DoomServerSessionPlugin['resources'] { return [...many(resourceSkills, contextSession)]; },\n get tools(): DoomServerSessionPlugin['tools'] { return defined([via({ name: 'load_skill' }, at(toolLoadSkill, contextSession))]); },\n services: [...(scopeSession.services ?? [])],\n get activities(): DoomServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ //#region generated/server.d.ts
2
+ export declare const facet: import("@agimon-ai/po-core/serverFacet").DoomServerFacet;
3
+ //#endregion
4
+ export { facet as default };
5
+ //# sourceMappingURL=server.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.mts","names":[],"sources":["../../generated/server.ts"],"mappings":";qBAwBa,gDAAK"}