@agimon-ai/doompi-skill 0.0.1-alpha.6 → 0.0.1-alpha.60

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 (118) hide show
  1. package/README.md +18 -10
  2. package/dist/apiContracts.cjs +17 -0
  3. package/dist/apiContracts.cjs.map +1 -0
  4. package/dist/apiContracts.d.mts +53 -0
  5. package/dist/apiContracts.d.mts.map +1 -0
  6. package/dist/apiContracts.mjs +13 -0
  7. package/dist/apiContracts.mjs.map +1 -0
  8. package/dist/catalog.cjs +4 -1
  9. package/dist/catalog.d.mts +1 -1
  10. package/dist/catalog.mjs +2 -1
  11. package/dist/deferredSkills-BzhyXnJ4.mjs +176 -0
  12. package/dist/{adapters/deferredSkills.cjs.map → deferredSkills-BzhyXnJ4.mjs.map} +1 -1
  13. package/dist/deferredSkills-DF6UCAsk.cjs +195 -0
  14. package/dist/deferredSkills-DF6UCAsk.cjs.map +1 -0
  15. package/dist/extensions/mcp.cjs +123 -0
  16. package/dist/extensions/mcp.cjs.map +1 -0
  17. package/dist/extensions/mcp.d.mts +5 -0
  18. package/dist/extensions/mcp.d.mts.map +1 -0
  19. package/dist/extensions/mcp.mjs +118 -0
  20. package/dist/extensions/mcp.mjs.map +1 -0
  21. package/dist/extensions/pi.cjs +401 -1
  22. package/dist/extensions/pi.cjs.map +1 -0
  23. package/dist/extensions/pi.d.mts +5 -2
  24. package/dist/extensions/pi.d.mts.map +1 -0
  25. package/dist/extensions/pi.mjs +396 -1
  26. package/dist/extensions/pi.mjs.map +1 -0
  27. package/dist/extensions/server.cjs +290 -0
  28. package/dist/extensions/server.cjs.map +1 -0
  29. package/dist/extensions/server.d.mts +5 -0
  30. package/dist/extensions/server.d.mts.map +1 -0
  31. package/dist/extensions/server.mjs +282 -0
  32. package/dist/extensions/server.mjs.map +1 -0
  33. package/dist/{adapters/skillCatalog.d.cts → index-6I1f9Ola.d.mts} +12 -4
  34. package/dist/index-6I1f9Ola.d.mts.map +1 -0
  35. package/dist/index.cjs +11 -1
  36. package/dist/index.d.mts +60 -5
  37. package/dist/index.d.mts.map +1 -0
  38. package/dist/index.mjs +4 -1
  39. package/dist/rolldown-runtime-C0BPl7ul.cjs +43 -0
  40. package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
  41. package/dist/skillCatalog-DLuYFuS6.cjs +213 -0
  42. package/dist/skillCatalog-DLuYFuS6.cjs.map +1 -0
  43. package/dist/skillCatalog-DYpoSsdD.mjs +194 -0
  44. package/dist/skillCatalog-DYpoSsdD.mjs.map +1 -0
  45. package/dist/skillText-B8muK9HZ.mjs +17 -0
  46. package/dist/skillText-B8muK9HZ.mjs.map +1 -0
  47. package/dist/skillText-C5OuRtBY.cjs +22 -0
  48. package/dist/skillText-C5OuRtBY.cjs.map +1 -0
  49. package/dist/skills-CjL1THn-.cjs +61 -0
  50. package/dist/skills-CjL1THn-.cjs.map +1 -0
  51. package/dist/skills-DAabEcff.mjs +32 -0
  52. package/dist/skills-DAabEcff.mjs.map +1 -0
  53. package/dist/skillsOverlay-C-VBauyr.mjs +362 -0
  54. package/dist/skillsOverlay-C-VBauyr.mjs.map +1 -0
  55. package/dist/skillsOverlay-CYRvtxbp.cjs +375 -0
  56. package/dist/skillsOverlay-CYRvtxbp.cjs.map +1 -0
  57. package/llms.txt +10 -2
  58. package/package.json +59 -18
  59. package/src/prompts/doompi-author-skill/SKILL.md +33 -0
  60. package/src/prompts/doompi-use-skill/SKILL.md +18 -0
  61. package/dist/_virtual/_rolldown/runtime.cjs +0 -1
  62. package/dist/adapters/deferredSkills.cjs +0 -12
  63. package/dist/adapters/deferredSkills.mjs +0 -12
  64. package/dist/adapters/deferredSkills.mjs.map +0 -1
  65. package/dist/adapters/helpSkills.cjs +0 -2
  66. package/dist/adapters/helpSkills.cjs.map +0 -1
  67. package/dist/adapters/helpSkills.mjs +0 -2
  68. package/dist/adapters/helpSkills.mjs.map +0 -1
  69. package/dist/adapters/pi/extension.cjs +0 -2
  70. package/dist/adapters/pi/extension.cjs.map +0 -1
  71. package/dist/adapters/pi/extension.d.cts +0 -7
  72. package/dist/adapters/pi/extension.d.cts.map +0 -1
  73. package/dist/adapters/pi/extension.d.mts +0 -7
  74. package/dist/adapters/pi/extension.d.mts.map +0 -1
  75. package/dist/adapters/pi/extension.mjs +0 -2
  76. package/dist/adapters/pi/extension.mjs.map +0 -1
  77. package/dist/adapters/pi/skillReadiness.cjs +0 -4
  78. package/dist/adapters/pi/skillReadiness.cjs.map +0 -1
  79. package/dist/adapters/pi/skillReadiness.mjs +0 -4
  80. package/dist/adapters/pi/skillReadiness.mjs.map +0 -1
  81. package/dist/adapters/skillCatalog.cjs +0 -2
  82. package/dist/adapters/skillCatalog.cjs.map +0 -1
  83. package/dist/adapters/skillCatalog.d.cts.map +0 -1
  84. package/dist/adapters/skillCatalog.d.mts +0 -58
  85. package/dist/adapters/skillCatalog.d.mts.map +0 -1
  86. package/dist/adapters/skillCatalog.mjs +0 -2
  87. package/dist/adapters/skillCatalog.mjs.map +0 -1
  88. package/dist/catalog.d.cts +0 -2
  89. package/dist/commands/skillsCommand.cjs +0 -2
  90. package/dist/commands/skillsCommand.cjs.map +0 -1
  91. package/dist/commands/skillsCommand.mjs +0 -2
  92. package/dist/commands/skillsCommand.mjs.map +0 -1
  93. package/dist/extensions/pi.d.cts +0 -2
  94. package/dist/index.d.cts +0 -5
  95. package/dist/services/skillText.cjs +0 -2
  96. package/dist/services/skillText.cjs.map +0 -1
  97. package/dist/services/skillText.d.cts +0 -13
  98. package/dist/services/skillText.d.cts.map +0 -1
  99. package/dist/services/skillText.d.mts +0 -13
  100. package/dist/services/skillText.d.mts.map +0 -1
  101. package/dist/services/skillText.mjs +0 -2
  102. package/dist/services/skillText.mjs.map +0 -1
  103. package/dist/tui/skillsOverlay.cjs +0 -4
  104. package/dist/tui/skillsOverlay.cjs.map +0 -1
  105. package/dist/tui/skillsOverlay.d.cts +0 -18
  106. package/dist/tui/skillsOverlay.d.cts.map +0 -1
  107. package/dist/tui/skillsOverlay.d.mts +0 -18
  108. package/dist/tui/skillsOverlay.d.mts.map +0 -1
  109. package/dist/tui/skillsOverlay.mjs +0 -4
  110. package/dist/tui/skillsOverlay.mjs.map +0 -1
  111. package/dist/types/skills.cjs +0 -2
  112. package/dist/types/skills.cjs.map +0 -1
  113. package/dist/types/skills.d.cts +0 -32
  114. package/dist/types/skills.d.cts.map +0 -1
  115. package/dist/types/skills.d.mts +0 -32
  116. package/dist/types/skills.d.mts.map +0 -1
  117. package/dist/types/skills.mjs +0 -2
  118. package/dist/types/skills.mjs.map +0 -1
package/README.md CHANGED
@@ -1,19 +1,19 @@
1
1
  # @agimon-ai/doompi-skill
2
2
 
3
- The session skill catalogue for [DoomPi](https://www.npmjs.com/package/@agimon-ai/doompi).
3
+ The session skill catalog for [DoomPi](https://www.npmjs.com/package/@agimon-ai/doompi).
4
4
 
5
5
  Pi loads skills from the directories it is given at startup. DoomPi adds two things on top: skills
6
- that are discovered lazily rather than loaded eagerly, and a registry other extensions publish their
7
- own skill directories to.
6
+ that are discovered lazily rather than loaded eagerly, and a registry where other extensions
7
+ publish their own skill directories.
8
8
 
9
9
  ## What it registers
10
10
 
11
- | Surface | Behaviour |
12
- | -------------------- | ------------------------------------------------------------------------------------------------ |
13
- | `/skills` | a fullscreen browser over everything this session loaded and everything another domain would add |
14
- | `SPC e s` | the leader binding for the same browser |
15
- | `input` hook | expands `/skill:<name>` for a skill that was discovered but not loaded |
16
- | `before_agent_start` | appends discovered skills to the system prompt, and surfaces discovery diagnostics once |
11
+ | Surface | Behavior |
12
+ | -------------------- | -------------------------------------------------------------------------------------------------- |
13
+ | `/skills` | a fullscreen browser over everything this session loaded and everything any other domain would add |
14
+ | `SPC e s` | the leader binding for the same browser |
15
+ | `input` hook | expands `/skill:<name>` for a skill that was discovered but not loaded |
16
+ | `before_agent_start` | appends discovered skills to the system prompt, and surfaces discovery diagnostics once |
17
17
 
18
18
  ## Deferred discovery
19
19
 
@@ -26,11 +26,17 @@ diagnostics.
26
26
  ## Contributing skill directories
27
27
 
28
28
  The package provides the session-owned `doom/skill-sources` Cordis service from
29
- `@agimon-ai/doompi-extension-contracts/skills`. Extensions register their directories inside
29
+ `@agimon-ai/doompi-core/skills`. Extensions register their directories inside
30
30
  `ctx.inject([DOOM_SKILL_SOURCES_SERVICE], ...)`; the returned handle is disposed automatically when
31
31
  either the contributor or provider unloads. Contributions are keyed by source, so a replacement
32
32
  generation takes the previous package slot without doubling it.
33
33
 
34
+ ## Help guidance
35
+
36
+ While the Help minor mode is active, this package contributes `doompi-author-skill` for creating
37
+ and distributing skills and `doompi-use-skill` for browsing, invoking, and diagnosing them. Both
38
+ prompts are published under `src/prompts` and routed through this package's [`llms.txt`](./llms.txt).
39
+
34
40
  ## Installation
35
41
 
36
42
  DoomPi depends on this package and activates it as fixed host core, so a DoomPi install already has
@@ -39,3 +45,5 @@ it. It is not selectable from `.doom/modes.yaml`.
39
45
  ## License
40
46
 
41
47
  MIT
48
+
49
+ Plugin entries live in `src/extensions`, host events and commands in routed surfaces, and catalog and discovery logic in named `src/services` folders. `src/exports` contains public helpers and types. Pi declares owned service bindings and native events. Its `onStop` invalidates pending discovery generations; final disposal releases the Help view. The server awaits its async declaration factory to discover named skill commands before registration and startup.
@@ -0,0 +1,17 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ //#region src/schemas/apiContracts.ts
6
+ /** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
7
+ const apiContracts = (0, require("@agimon-ai/doompi-core/apiContracts").defineApiContract)({
8
+ version: 1,
9
+ http: [],
10
+ sockets: [],
11
+ dynamic: []
12
+ });
13
+ //#endregion
14
+ exports.apiContracts = apiContracts;
15
+ exports.default = apiContracts;
16
+
17
+ //# sourceMappingURL=apiContracts.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiContracts.cjs","names":["defineApiContract"],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract } from '@agimon-ai/doompi-core/apiContracts';\n\n/** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */\nexport const apiContracts = defineApiContract({ version: 1, http: [], sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":";;;;;;AAGA,MAAa,gBAAA,gDAAeA,CAAAA,CAAAA,kBAAAA,CAAkB;CAAE,SAAS;CAAG,MAAM,CAAC;CAAG,SAAS,CAAC;CAAG,SAAS,CAAC;AAAE,CAAC"}
@@ -0,0 +1,53 @@
1
+ //#region src/schemas/apiContracts.d.ts
2
+ /** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
3
+ export declare const apiContracts: {
4
+ version: 1;
5
+ protocols?: Record<string, string> | undefined;
6
+ schemas?: Record<string, boolean | object> | undefined;
7
+ http: {
8
+ id: string;
9
+ scope: "global" | "session" | "workspace";
10
+ basePath?: string | undefined;
11
+ path: string;
12
+ method: "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT";
13
+ description: string;
14
+ availability?: string | undefined;
15
+ authentication: "device" | "none" | "owner";
16
+ parameters?: {
17
+ name: string;
18
+ in: "header" | "path" | "query";
19
+ required: boolean;
20
+ schema: boolean | object;
21
+ }[] | undefined;
22
+ body?: {
23
+ contentType: string;
24
+ contentTypes?: string[] | undefined;
25
+ required: boolean;
26
+ schema: boolean | object;
27
+ } | undefined;
28
+ responses: Record<string, {
29
+ description: string;
30
+ contentType?: string | undefined;
31
+ schema?: boolean | object | undefined;
32
+ events?: Record<string, boolean | object> | undefined;
33
+ }>;
34
+ }[];
35
+ sockets: {
36
+ id: string;
37
+ scope: "global" | "session" | "workspace";
38
+ description: string;
39
+ availability?: string | undefined;
40
+ service: string;
41
+ member: string;
42
+ direction: "client-to-server" | "server-to-client";
43
+ kind: "channel" | "method" | "state";
44
+ input: boolean | object;
45
+ output?: boolean | object | undefined;
46
+ errors?: boolean | object | undefined;
47
+ }[];
48
+ dynamic: string[];
49
+ gaps?: string[] | undefined;
50
+ };
51
+ //#endregion
52
+ export { apiContracts as default };
53
+ //# sourceMappingURL=apiContracts.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiContracts.d.mts","names":[],"sources":["../src/schemas/apiContracts.ts"],"mappings":";;qBAGa"}
@@ -0,0 +1,13 @@
1
+ import { defineApiContract } from "@agimon-ai/doompi-core/apiContracts";
2
+ //#region src/schemas/apiContracts.ts
3
+ /** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
4
+ const apiContracts = defineApiContract({
5
+ version: 1,
6
+ http: [],
7
+ sockets: [],
8
+ dynamic: []
9
+ });
10
+ //#endregion
11
+ export { apiContracts, apiContracts as default };
12
+
13
+ //# sourceMappingURL=apiContracts.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiContracts.mjs","names":[],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract } from '@agimon-ai/doompi-core/apiContracts';\n\n/** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */\nexport const apiContracts = defineApiContract({ version: 1, http: [], sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":";;;AAGA,MAAa,eAAe,kBAAkB;CAAE,SAAS;CAAG,MAAM,CAAC;CAAG,SAAS,CAAC;CAAG,SAAS,CAAC;AAAE,CAAC"}
package/dist/catalog.cjs CHANGED
@@ -1 +1,4 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/skillCatalog.cjs");exports.buildSkillCatalog=e.buildSkillCatalog,exports.counter=e.counter;
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_skillCatalog = require("./skillCatalog-DLuYFuS6.cjs");
3
+ exports.buildSkillCatalog = require_skillCatalog.buildSkillCatalog;
4
+ exports.counter = require_skillCatalog.counter;
@@ -1,2 +1,2 @@
1
- import { SkillCatalog, SkillCatalogOptions, SkillEntry, SkillGroup, SkillOwnerNode, buildSkillCatalog, counter } from "./adapters/skillCatalog.mjs";
1
+ import { a as SkillOwnerNode, i as SkillGroup, n as SkillCatalogOptions, o as buildSkillCatalog, r as SkillEntry, s as counter, t as SkillCatalog } from "./index-6I1f9Ola.mjs";
2
2
  export { type SkillCatalog, type SkillCatalogOptions, type SkillEntry, type SkillGroup, type SkillOwnerNode, buildSkillCatalog, counter };
package/dist/catalog.mjs CHANGED
@@ -1 +1,2 @@
1
- import{buildSkillCatalog as e,counter as t}from"./adapters/skillCatalog.mjs";export{e as buildSkillCatalog,t as counter};
1
+ import { n as counter, t as buildSkillCatalog } from "./skillCatalog-DYpoSsdD.mjs";
2
+ export { buildSkillCatalog, counter };
@@ -0,0 +1,176 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { formatSkillsForPrompt, getAgentDir, loadSkills, stripFrontmatter } from "@earendil-works/pi-coding-agent";
5
+ import { fileURLToPath, pathToFileURL } from "node:url";
6
+ import { Worker } from "node:worker_threads";
7
+ //#region src/services/deferredSkills/index.ts
8
+ var deferredSkills_exports = /* @__PURE__ */ __exportAll({
9
+ DeferredSkillLoader: () => DeferredSkillLoader,
10
+ buildPromptWithDeferredSkills: () => buildPromptWithDeferredSkills,
11
+ expandDeferredSkillCommand: () => expandDeferredSkillCommand
12
+ });
13
+ const PI_PACKAGE = "@earendil-works/pi-coding-agent";
14
+ const PACKAGE_MANIFEST = "package.json";
15
+ const SKILL_WORKER_SOURCE = `
16
+ const { parentPort, workerData } = require('node:worker_threads');
17
+ void (async () => {
18
+ try {
19
+ const { loadSkills } = await import(workerData.piModuleUrl);
20
+ parentPort.postMessage({ ok: true, result: loadSkills(workerData.loadOptions) });
21
+ } catch (error) {
22
+ parentPort.postMessage({ ok: false, error: error instanceof Error ? error.message : String(error) });
23
+ }
24
+ })();
25
+ `;
26
+ function installedPiModuleUrl() {
27
+ const anchors = [
28
+ process.argv[1],
29
+ fileURLToPath(import.meta.url),
30
+ path.join(process.cwd(), PACKAGE_MANIFEST)
31
+ ];
32
+ for (const anchor of anchors) {
33
+ if (!anchor) continue;
34
+ let directory = path.dirname(path.resolve(anchor));
35
+ while (true) {
36
+ const packageRoot = path.join(directory, "node_modules", PI_PACKAGE);
37
+ const manifestPath = path.join(packageRoot, PACKAGE_MANIFEST);
38
+ try {
39
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
40
+ if (typeof manifest.main === "string") {
41
+ const entry = path.resolve(packageRoot, manifest.main);
42
+ if (fs.existsSync(entry)) return pathToFileURL(entry).href;
43
+ }
44
+ } catch {}
45
+ const parent = path.dirname(directory);
46
+ if (parent === directory) break;
47
+ directory = parent;
48
+ }
49
+ }
50
+ throw new Error(`Cannot resolve ${PI_PACKAGE} from the DoomPi or host module trees`);
51
+ }
52
+ /**
53
+ * One session's Doom-selected skill inventory.
54
+ *
55
+ * Construction is deliberately cheap. `start()` schedules the synchronous Pi
56
+ * walker after session_start returns, while `ready()` is the single promise the
57
+ * first input awaits before Pi expands `/skill:name`.
58
+ */
59
+ var DeferredSkillLoader = class {
60
+ #options;
61
+ #promise;
62
+ constructor(options) {
63
+ this.#options = options;
64
+ }
65
+ start() {
66
+ if (this.#promise) return this.#promise;
67
+ if (!this.#options.schedule && !this.#options.load) {
68
+ this.#promise = this.#loadInWorker();
69
+ return this.#promise;
70
+ }
71
+ const schedule = this.#options.schedule ?? ((load) => setImmediate(load));
72
+ this.#promise = new Promise((resolve) => {
73
+ const fail = (error) => {
74
+ resolve(this.#failure(error));
75
+ };
76
+ try {
77
+ schedule(() => {
78
+ try {
79
+ resolve(this.#load());
80
+ } catch (error) {
81
+ fail(error);
82
+ }
83
+ });
84
+ } catch (error) {
85
+ fail(error);
86
+ }
87
+ });
88
+ return this.#promise;
89
+ }
90
+ ready() {
91
+ return this.start();
92
+ }
93
+ #loadOptions() {
94
+ return {
95
+ cwd: this.#options.cwd,
96
+ agentDir: this.#options.agentDir ?? getAgentDir(),
97
+ skillPaths: [...this.#options.skillPaths],
98
+ includeDefaults: false
99
+ };
100
+ }
101
+ #snapshot(result) {
102
+ return {
103
+ skills: result.skills,
104
+ diagnostics: result.diagnostics.map((diagnostic) => `${diagnostic.path ?? this.#options.cwd}: ${diagnostic.message}`)
105
+ };
106
+ }
107
+ #failure(error) {
108
+ return {
109
+ skills: [],
110
+ diagnostics: [`${this.#options.cwd}: ${error instanceof Error ? error.message : String(error)}`]
111
+ };
112
+ }
113
+ #load() {
114
+ return this.#snapshot((this.#options.load ?? loadSkills)(this.#loadOptions()));
115
+ }
116
+ #loadInWorker() {
117
+ return new Promise((resolve) => {
118
+ let settled = false;
119
+ const settle = (snapshot) => {
120
+ if (settled) return;
121
+ settled = true;
122
+ resolve(snapshot);
123
+ };
124
+ let worker;
125
+ try {
126
+ worker = new Worker(SKILL_WORKER_SOURCE, {
127
+ eval: true,
128
+ workerData: {
129
+ piModuleUrl: this.#options.piModuleUrl ?? installedPiModuleUrl(),
130
+ loadOptions: this.#loadOptions()
131
+ }
132
+ });
133
+ } catch (error) {
134
+ settle(this.#failure(error));
135
+ return;
136
+ }
137
+ worker.unref();
138
+ worker.once("message", (message) => {
139
+ if (!message.ok || !message.result) {
140
+ settle(this.#failure(message.error ?? "Skill worker failed"));
141
+ return;
142
+ }
143
+ settle(this.#snapshot(message.result));
144
+ });
145
+ worker.once("error", (error) => settle(this.#failure(error)));
146
+ worker.once("exit", (code) => {
147
+ if (code !== 0) settle(this.#failure(`Skill worker exited with code ${code}`));
148
+ });
149
+ });
150
+ }
151
+ };
152
+ /** Appends only the inventory Pi would append for these deferred skills. */
153
+ function buildPromptWithDeferredSkills(systemPrompt, options, skills) {
154
+ if (options.selectedTools && !options.selectedTools.includes("read")) return systemPrompt;
155
+ return `${systemPrompt}${formatSkillsForPrompt(skills)}`;
156
+ }
157
+ /** Expands a deferred `/skill:name` before Pi consults its synchronous inventory. */
158
+ function expandDeferredSkillCommand(text, skills) {
159
+ if (!text.startsWith("/skill:")) return text;
160
+ const spaceIndex = text.indexOf(" ");
161
+ const skillName = spaceIndex === -1 ? text.slice(7) : text.slice(7, spaceIndex);
162
+ const skill = skills.find((candidate) => candidate.name === skillName);
163
+ if (!skill) return text;
164
+ try {
165
+ const args = spaceIndex === -1 ? "" : text.slice(spaceIndex + 1).trim();
166
+ const body = stripFrontmatter(fs.readFileSync(skill.filePath, "utf8")).trim();
167
+ const skillBlock = `<skill name="${skill.name}" location="${skill.filePath}">\nReferences are relative to ${skill.baseDir}.\n\n${body}\n</skill>`;
168
+ return args ? `${skillBlock}\n\n${args}` : skillBlock;
169
+ } catch {
170
+ return text;
171
+ }
172
+ }
173
+ //#endregion
174
+ export { deferredSkills_exports as n, expandDeferredSkillCommand as r, DeferredSkillLoader as t };
175
+
176
+ //# sourceMappingURL=deferredSkills-BzhyXnJ4.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"deferredSkills.cjs","names":["fileURLToPath","path","fs","pathToFileURL","#options","#promise","#loadInWorker","#failure","#load","getAgentDir","#snapshot","loadSkills","#loadOptions","Worker","formatSkillsForPrompt","stripFrontmatter"],"sources":["../../src/adapters/deferredSkills.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { Worker } from 'node:worker_threads';\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 DoomPi 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"],"mappings":"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"}
1
+ {"version":3,"file":"deferredSkills-BzhyXnJ4.mjs","names":[],"sources":["../src/services/deferredSkills/index.ts"],"sourcesContent":["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 DoomPi 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"],"mappings":"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"}
@@ -0,0 +1,195 @@
1
+ const require_rolldown_runtime = require("./rolldown-runtime-C0BPl7ul.cjs");
2
+ let node_fs = require("node:fs");
3
+ node_fs = require_rolldown_runtime.__toESM(node_fs, 1);
4
+ let node_path = require("node:path");
5
+ node_path = require_rolldown_runtime.__toESM(node_path, 1);
6
+ let _earendil_works_pi_coding_agent = require("@earendil-works/pi-coding-agent");
7
+ let node_url = require("node:url");
8
+ let node_worker_threads = require("node:worker_threads");
9
+ //#region src/services/deferredSkills/index.ts
10
+ var deferredSkills_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
11
+ DeferredSkillLoader: () => DeferredSkillLoader,
12
+ buildPromptWithDeferredSkills: () => buildPromptWithDeferredSkills,
13
+ expandDeferredSkillCommand: () => expandDeferredSkillCommand
14
+ });
15
+ const PI_PACKAGE = "@earendil-works/pi-coding-agent";
16
+ const PACKAGE_MANIFEST = "package.json";
17
+ const SKILL_WORKER_SOURCE = `
18
+ const { parentPort, workerData } = require('node:worker_threads');
19
+ void (async () => {
20
+ try {
21
+ const { loadSkills } = await import(workerData.piModuleUrl);
22
+ parentPort.postMessage({ ok: true, result: loadSkills(workerData.loadOptions) });
23
+ } catch (error) {
24
+ parentPort.postMessage({ ok: false, error: error instanceof Error ? error.message : String(error) });
25
+ }
26
+ })();
27
+ `;
28
+ function installedPiModuleUrl() {
29
+ const anchors = [
30
+ process.argv[1],
31
+ (0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href),
32
+ node_path.default.join(process.cwd(), PACKAGE_MANIFEST)
33
+ ];
34
+ for (const anchor of anchors) {
35
+ if (!anchor) continue;
36
+ let directory = node_path.default.dirname(node_path.default.resolve(anchor));
37
+ while (true) {
38
+ const packageRoot = node_path.default.join(directory, "node_modules", PI_PACKAGE);
39
+ const manifestPath = node_path.default.join(packageRoot, PACKAGE_MANIFEST);
40
+ try {
41
+ const manifest = JSON.parse(node_fs.default.readFileSync(manifestPath, "utf8"));
42
+ if (typeof manifest.main === "string") {
43
+ const entry = node_path.default.resolve(packageRoot, manifest.main);
44
+ if (node_fs.default.existsSync(entry)) return (0, node_url.pathToFileURL)(entry).href;
45
+ }
46
+ } catch {}
47
+ const parent = node_path.default.dirname(directory);
48
+ if (parent === directory) break;
49
+ directory = parent;
50
+ }
51
+ }
52
+ throw new Error(`Cannot resolve ${PI_PACKAGE} from the DoomPi or host module trees`);
53
+ }
54
+ /**
55
+ * One session's Doom-selected skill inventory.
56
+ *
57
+ * Construction is deliberately cheap. `start()` schedules the synchronous Pi
58
+ * walker after session_start returns, while `ready()` is the single promise the
59
+ * first input awaits before Pi expands `/skill:name`.
60
+ */
61
+ var DeferredSkillLoader = class {
62
+ #options;
63
+ #promise;
64
+ constructor(options) {
65
+ this.#options = options;
66
+ }
67
+ start() {
68
+ if (this.#promise) return this.#promise;
69
+ if (!this.#options.schedule && !this.#options.load) {
70
+ this.#promise = this.#loadInWorker();
71
+ return this.#promise;
72
+ }
73
+ const schedule = this.#options.schedule ?? ((load) => setImmediate(load));
74
+ this.#promise = new Promise((resolve) => {
75
+ const fail = (error) => {
76
+ resolve(this.#failure(error));
77
+ };
78
+ try {
79
+ schedule(() => {
80
+ try {
81
+ resolve(this.#load());
82
+ } catch (error) {
83
+ fail(error);
84
+ }
85
+ });
86
+ } catch (error) {
87
+ fail(error);
88
+ }
89
+ });
90
+ return this.#promise;
91
+ }
92
+ ready() {
93
+ return this.start();
94
+ }
95
+ #loadOptions() {
96
+ return {
97
+ cwd: this.#options.cwd,
98
+ agentDir: this.#options.agentDir ?? (0, _earendil_works_pi_coding_agent.getAgentDir)(),
99
+ skillPaths: [...this.#options.skillPaths],
100
+ includeDefaults: false
101
+ };
102
+ }
103
+ #snapshot(result) {
104
+ return {
105
+ skills: result.skills,
106
+ diagnostics: result.diagnostics.map((diagnostic) => `${diagnostic.path ?? this.#options.cwd}: ${diagnostic.message}`)
107
+ };
108
+ }
109
+ #failure(error) {
110
+ return {
111
+ skills: [],
112
+ diagnostics: [`${this.#options.cwd}: ${error instanceof Error ? error.message : String(error)}`]
113
+ };
114
+ }
115
+ #load() {
116
+ return this.#snapshot((this.#options.load ?? _earendil_works_pi_coding_agent.loadSkills)(this.#loadOptions()));
117
+ }
118
+ #loadInWorker() {
119
+ return new Promise((resolve) => {
120
+ let settled = false;
121
+ const settle = (snapshot) => {
122
+ if (settled) return;
123
+ settled = true;
124
+ resolve(snapshot);
125
+ };
126
+ let worker;
127
+ try {
128
+ worker = new node_worker_threads.Worker(SKILL_WORKER_SOURCE, {
129
+ eval: true,
130
+ workerData: {
131
+ piModuleUrl: this.#options.piModuleUrl ?? installedPiModuleUrl(),
132
+ loadOptions: this.#loadOptions()
133
+ }
134
+ });
135
+ } catch (error) {
136
+ settle(this.#failure(error));
137
+ return;
138
+ }
139
+ worker.unref();
140
+ worker.once("message", (message) => {
141
+ if (!message.ok || !message.result) {
142
+ settle(this.#failure(message.error ?? "Skill worker failed"));
143
+ return;
144
+ }
145
+ settle(this.#snapshot(message.result));
146
+ });
147
+ worker.once("error", (error) => settle(this.#failure(error)));
148
+ worker.once("exit", (code) => {
149
+ if (code !== 0) settle(this.#failure(`Skill worker exited with code ${code}`));
150
+ });
151
+ });
152
+ }
153
+ };
154
+ /** Appends only the inventory Pi would append for these deferred skills. */
155
+ function buildPromptWithDeferredSkills(systemPrompt, options, skills) {
156
+ if (options.selectedTools && !options.selectedTools.includes("read")) return systemPrompt;
157
+ return `${systemPrompt}${(0, _earendil_works_pi_coding_agent.formatSkillsForPrompt)(skills)}`;
158
+ }
159
+ /** Expands a deferred `/skill:name` before Pi consults its synchronous inventory. */
160
+ function expandDeferredSkillCommand(text, skills) {
161
+ if (!text.startsWith("/skill:")) return text;
162
+ const spaceIndex = text.indexOf(" ");
163
+ const skillName = spaceIndex === -1 ? text.slice(7) : text.slice(7, spaceIndex);
164
+ const skill = skills.find((candidate) => candidate.name === skillName);
165
+ if (!skill) return text;
166
+ try {
167
+ const args = spaceIndex === -1 ? "" : text.slice(spaceIndex + 1).trim();
168
+ const body = (0, _earendil_works_pi_coding_agent.stripFrontmatter)(node_fs.default.readFileSync(skill.filePath, "utf8")).trim();
169
+ const skillBlock = `<skill name="${skill.name}" location="${skill.filePath}">\nReferences are relative to ${skill.baseDir}.\n\n${body}\n</skill>`;
170
+ return args ? `${skillBlock}\n\n${args}` : skillBlock;
171
+ } catch {
172
+ return text;
173
+ }
174
+ }
175
+ //#endregion
176
+ Object.defineProperty(exports, "DeferredSkillLoader", {
177
+ enumerable: true,
178
+ get: function() {
179
+ return DeferredSkillLoader;
180
+ }
181
+ });
182
+ Object.defineProperty(exports, "deferredSkills_exports", {
183
+ enumerable: true,
184
+ get: function() {
185
+ return deferredSkills_exports;
186
+ }
187
+ });
188
+ Object.defineProperty(exports, "expandDeferredSkillCommand", {
189
+ enumerable: true,
190
+ get: function() {
191
+ return expandDeferredSkillCommand;
192
+ }
193
+ });
194
+
195
+ //# sourceMappingURL=deferredSkills-DF6UCAsk.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deferredSkills-DF6UCAsk.cjs","names":["fileURLToPath","path","fs","pathToFileURL","getAgentDir","loadSkills","Worker","formatSkillsForPrompt","stripFrontmatter"],"sources":["../src/services/deferredSkills/index.ts"],"sourcesContent":["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 DoomPi 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"],"mappings":"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"}