@agimon-ai/doompi-skill 0.0.1-alpha.9 → 0.0.1-alpha.91
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.
- package/README.md +3 -1
- package/dist/apiContracts.cjs +17 -0
- package/dist/apiContracts.cjs.map +1 -0
- package/dist/apiContracts.d.mts +53 -0
- package/dist/apiContracts.d.mts.map +1 -0
- package/dist/apiContracts.mjs +13 -0
- package/dist/apiContracts.mjs.map +1 -0
- package/dist/catalog.cjs +4 -1
- package/dist/catalog.d.mts +1 -1
- package/dist/catalog.mjs +2 -1
- package/dist/deferredSkills-BzhyXnJ4.mjs +176 -0
- package/dist/{adapters/deferredSkills.cjs.map → deferredSkills-BzhyXnJ4.mjs.map} +1 -1
- package/dist/deferredSkills-DF6UCAsk.cjs +195 -0
- package/dist/deferredSkills-DF6UCAsk.cjs.map +1 -0
- package/dist/extensions/mcp-ui.mjs +31 -0
- package/dist/extensions/mcp-ui.mjs.map +1 -0
- package/dist/extensions/mcp.cjs +130 -0
- package/dist/extensions/mcp.cjs.map +1 -0
- package/dist/extensions/mcp.d.mts +5 -0
- package/dist/extensions/mcp.d.mts.map +1 -0
- package/dist/extensions/mcp.mjs +125 -0
- package/dist/extensions/mcp.mjs.map +1 -0
- package/dist/extensions/pi.cjs +411 -1
- package/dist/extensions/pi.cjs.map +1 -0
- package/dist/extensions/pi.d.mts +5 -2
- package/dist/extensions/pi.d.mts.map +1 -0
- package/dist/extensions/pi.mjs +406 -1
- package/dist/extensions/pi.mjs.map +1 -0
- package/dist/extensions/server.cjs +367 -0
- package/dist/extensions/server.cjs.map +1 -0
- package/dist/extensions/server.d.mts +5 -0
- package/dist/extensions/server.d.mts.map +1 -0
- package/dist/extensions/server.mjs +359 -0
- package/dist/extensions/server.mjs.map +1 -0
- package/dist/{adapters/skillCatalog.d.cts → index-6I1f9Ola.d.mts} +12 -4
- package/dist/index-6I1f9Ola.d.mts.map +1 -0
- package/dist/index.cjs +11 -1
- package/dist/index.d.mts +60 -5
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +4 -1
- package/dist/rolldown-runtime-C0BPl7ul.cjs +43 -0
- package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
- package/dist/skillCatalog-DLuYFuS6.cjs +213 -0
- package/dist/skillCatalog-DLuYFuS6.cjs.map +1 -0
- package/dist/skillCatalog-DYpoSsdD.mjs +194 -0
- package/dist/skillCatalog-DYpoSsdD.mjs.map +1 -0
- package/dist/skillText-B8muK9HZ.mjs +17 -0
- package/dist/skillText-B8muK9HZ.mjs.map +1 -0
- package/dist/skillText-C5OuRtBY.cjs +22 -0
- package/dist/skillText-C5OuRtBY.cjs.map +1 -0
- package/dist/skills-CjL1THn-.cjs +61 -0
- package/dist/skills-CjL1THn-.cjs.map +1 -0
- package/dist/skills-DAabEcff.mjs +32 -0
- package/dist/skills-DAabEcff.mjs.map +1 -0
- package/dist/skillsOverlay-C-VBauyr.mjs +362 -0
- package/dist/skillsOverlay-C-VBauyr.mjs.map +1 -0
- package/dist/skillsOverlay-CYRvtxbp.cjs +375 -0
- package/dist/skillsOverlay-CYRvtxbp.cjs.map +1 -0
- package/package.json +70 -19
- package/src/prompts/doompi-author-skill/SKILL.md +6 -2
- package/dist/_virtual/_rolldown/runtime.cjs +0 -1
- package/dist/adapters/deferredSkills.cjs +0 -12
- package/dist/adapters/deferredSkills.mjs +0 -12
- package/dist/adapters/deferredSkills.mjs.map +0 -1
- package/dist/adapters/helpSkills.cjs +0 -2
- package/dist/adapters/helpSkills.cjs.map +0 -1
- package/dist/adapters/helpSkills.mjs +0 -2
- package/dist/adapters/helpSkills.mjs.map +0 -1
- package/dist/adapters/pi/extension.cjs +0 -2
- package/dist/adapters/pi/extension.cjs.map +0 -1
- package/dist/adapters/pi/extension.d.cts +0 -7
- package/dist/adapters/pi/extension.d.cts.map +0 -1
- package/dist/adapters/pi/extension.d.mts +0 -7
- package/dist/adapters/pi/extension.d.mts.map +0 -1
- package/dist/adapters/pi/extension.mjs +0 -2
- package/dist/adapters/pi/extension.mjs.map +0 -1
- package/dist/adapters/pi/skillReadiness.cjs +0 -4
- package/dist/adapters/pi/skillReadiness.cjs.map +0 -1
- package/dist/adapters/pi/skillReadiness.mjs +0 -4
- package/dist/adapters/pi/skillReadiness.mjs.map +0 -1
- package/dist/adapters/skillCatalog.cjs +0 -2
- package/dist/adapters/skillCatalog.cjs.map +0 -1
- package/dist/adapters/skillCatalog.d.cts.map +0 -1
- package/dist/adapters/skillCatalog.d.mts +0 -58
- package/dist/adapters/skillCatalog.d.mts.map +0 -1
- package/dist/adapters/skillCatalog.mjs +0 -2
- package/dist/adapters/skillCatalog.mjs.map +0 -1
- package/dist/catalog.d.cts +0 -2
- package/dist/commands/skillsCommand.cjs +0 -2
- package/dist/commands/skillsCommand.cjs.map +0 -1
- package/dist/commands/skillsCommand.mjs +0 -2
- package/dist/commands/skillsCommand.mjs.map +0 -1
- package/dist/extensions/pi.d.cts +0 -2
- package/dist/index.d.cts +0 -5
- package/dist/services/skillText.cjs +0 -2
- package/dist/services/skillText.cjs.map +0 -1
- package/dist/services/skillText.d.cts +0 -13
- package/dist/services/skillText.d.cts.map +0 -1
- package/dist/services/skillText.d.mts +0 -13
- package/dist/services/skillText.d.mts.map +0 -1
- package/dist/services/skillText.mjs +0 -2
- package/dist/services/skillText.mjs.map +0 -1
- package/dist/tui/skillsOverlay.cjs +0 -4
- package/dist/tui/skillsOverlay.cjs.map +0 -1
- package/dist/tui/skillsOverlay.d.cts +0 -18
- package/dist/tui/skillsOverlay.d.cts.map +0 -1
- package/dist/tui/skillsOverlay.d.mts +0 -18
- package/dist/tui/skillsOverlay.d.mts.map +0 -1
- package/dist/tui/skillsOverlay.mjs +0 -4
- package/dist/tui/skillsOverlay.mjs.map +0 -1
- package/dist/types/skills.cjs +0 -2
- package/dist/types/skills.cjs.map +0 -1
- package/dist/types/skills.d.cts +0 -32
- package/dist/types/skills.d.cts.map +0 -1
- package/dist/types/skills.d.mts +0 -32
- package/dist/types/skills.d.mts.map +0 -1
- package/dist/types/skills.mjs +0 -2
- package/dist/types/skills.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ 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-
|
|
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.
|
|
@@ -45,3 +45,5 @@ it. It is not selectable from `.doom/modes.yaml`.
|
|
|
45
45
|
## License
|
|
46
46
|
|
|
47
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
|
|
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;
|
package/dist/catalog.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
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{
|
|
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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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { defineMcpWidget } from "@agimon-ai/doompi-core/web";
|
|
2
|
+
import { McpToolFields, McpToolFrame, McpToolOutput } from "@agimon-ai/doompi-web-components";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
//#region src/extensions/workspaces/sessions/(frontend)/tool/load_skill.mcp.tsx
|
|
5
|
+
function LoadSkillMcpWidget(props) {
|
|
6
|
+
return /* @__PURE__ */ jsxs(McpToolFrame, {
|
|
7
|
+
...props,
|
|
8
|
+
title: "Load skill",
|
|
9
|
+
children: [/* @__PURE__ */ jsx(McpToolFields, { fields: [["Skill", props.args.name]] }), /* @__PURE__ */ jsx(McpToolOutput, { result: props.result })]
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
var load_skill_mcp_default = defineMcpWidget(LoadSkillMcpWidget);
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region src/extensions/workspaces/sessions/(frontend)/tool/search_skills.mcp.tsx
|
|
15
|
+
function SearchSkillsMcpWidget(props) {
|
|
16
|
+
return /* @__PURE__ */ jsxs(McpToolFrame, {
|
|
17
|
+
...props,
|
|
18
|
+
title: "Search skills",
|
|
19
|
+
children: [/* @__PURE__ */ jsx(McpToolFields, { fields: [["Query", props.args.query]] }), /* @__PURE__ */ jsx(McpToolOutput, { result: props.result })]
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region generated/mcp-ui.ts
|
|
24
|
+
const widgets = {
|
|
25
|
+
"@agimon-ai/doompi-skill/load_skill": load_skill_mcp_default,
|
|
26
|
+
"@agimon-ai/doompi-skill/search_skills": defineMcpWidget(SearchSkillsMcpWidget)
|
|
27
|
+
};
|
|
28
|
+
//#endregion
|
|
29
|
+
export { widgets };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=mcp-ui.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-ui.mjs","names":["Widget0","Widget1"],"sources":["../../src/extensions/workspaces/sessions/(frontend)/tool/load_skill.mcp.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/search_skills.mcp.tsx","../../generated/mcp-ui.ts"],"sourcesContent":["import { defineMcpWidget, type DoomMcpWidgetProps } from '@agimon-ai/doompi-core/web';\nimport { McpToolFrame, McpToolFields, McpToolOutput } from '@agimon-ai/doompi-web-components';\n\nfunction LoadSkillMcpWidget(props: DoomMcpWidgetProps) {\n return (\n <McpToolFrame {...props} title=\"Load skill\">\n <McpToolFields fields={[['Skill', props.args.name]]} />\n <McpToolOutput result={props.result} />\n </McpToolFrame>\n );\n}\n\nexport default defineMcpWidget(LoadSkillMcpWidget);\n","import { defineMcpWidget, type DoomMcpWidgetProps } from '@agimon-ai/doompi-core/web';\nimport { McpToolFrame, McpToolFields, McpToolOutput } from '@agimon-ai/doompi-web-components';\n\nfunction SearchSkillsMcpWidget(props: DoomMcpWidgetProps) {\n return (\n <McpToolFrame {...props} title=\"Search skills\">\n <McpToolFields fields={[['Query', props.args.query]]} />\n <McpToolOutput result={props.result} />\n </McpToolFrame>\n );\n}\n\nexport default defineMcpWidget(SearchSkillsMcpWidget);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport type { ComponentType } from 'react';\nimport type { DoomMcpWidgetProps } from '@agimon-ai/doompi-core/mcpWidget';\nimport Widget0 from \"../src/extensions/workspaces/sessions/(frontend)/tool/load_skill.mcp\";\nimport Widget1 from \"../src/extensions/workspaces/sessions/(frontend)/tool/search_skills.mcp\";\n\nexport const widgets: Readonly<Record<string, ComponentType<DoomMcpWidgetProps>>> = {\n \"@agimon-ai/doompi-skill/load_skill\": Widget0,\n \"@agimon-ai/doompi-skill/search_skills\": Widget1,\n};\n"],"mappings":";;;;AAGA,SAAS,mBAAmB,OAA2B;CACrD,OACE,qBAAC,cAAD;EAAc,GAAI;EAAO,OAAM;EAA/B,UAAA,CACE,oBAAC,eAAD,EAAe,QAAQ,CAAC,CAAC,SAAS,MAAM,KAAK,IAAI,CAAC,EAAI,CAAA,GACtD,oBAAC,eAAD,EAAe,QAAQ,MAAM,OAAS,CAAA,CAC1B;;AAElB;AAEA,IAAA,yBAAe,gBAAgB,kBAAkB;;;ACTjD,SAAS,sBAAsB,OAA2B;CACxD,OACE,qBAAC,cAAD;EAAc,GAAI;EAAO,OAAM;EAA/B,UAAA,CACE,oBAAC,eAAD,EAAe,QAAQ,CAAC,CAAC,SAAS,MAAM,KAAK,KAAK,CAAC,EAAI,CAAA,GACvD,oBAAC,eAAD,EAAe,QAAQ,MAAM,OAAS,CAAA,CAC1B;;AAElB;;;ACJA,MAAa,UAAuE;CAClF,sCAAsCA;CACtC,yCDIa,gBAAgB,qBCJYC;AAC3C"}
|