dsh-agent-skills 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +129 -0
  3. package/cordis.patch.yml +13 -0
  4. package/lib/client.js +15235 -0
  5. package/lib/client.js.map +7 -0
  6. package/lib/discovery.d.ts +9 -0
  7. package/lib/discovery.js +48 -0
  8. package/lib/discovery.js.map +1 -0
  9. package/lib/index.d.ts +35 -0
  10. package/lib/index.js +26 -0
  11. package/lib/index.js.map +1 -0
  12. package/lib/preset.d.ts +9 -0
  13. package/lib/preset.js +7 -0
  14. package/lib/preset.js.map +1 -0
  15. package/lib/provider.d.ts +53 -0
  16. package/lib/provider.js +295 -0
  17. package/lib/provider.js.map +1 -0
  18. package/lib/registry.d.ts +85 -0
  19. package/lib/registry.js +122 -0
  20. package/lib/registry.js.map +1 -0
  21. package/lib/runtime.d.ts +27 -0
  22. package/lib/runtime.js +162 -0
  23. package/lib/runtime.js.map +1 -0
  24. package/lib/scan.d.ts +29 -0
  25. package/lib/scan.js +156 -0
  26. package/lib/scan.js.map +1 -0
  27. package/lib/schemas.d.ts +112 -0
  28. package/lib/schemas.js +82 -0
  29. package/lib/schemas.js.map +1 -0
  30. package/lib/store.d.ts +26 -0
  31. package/lib/store.js +88 -0
  32. package/lib/store.js.map +1 -0
  33. package/lib/typert.d.ts +195 -0
  34. package/lib/typert.js +153 -0
  35. package/lib/typert.js.map +1 -0
  36. package/lib/types/client/AgentSkillsSection.d.ts +9 -0
  37. package/lib/types/client/index.d.ts +14 -0
  38. package/lib/types/client/locales.d.ts +86 -0
  39. package/lib/types/client/styles.d.ts +4 -0
  40. package/lib/types/client/typert-remote.d.ts +152 -0
  41. package/lib/types/client/types.d.ts +13 -0
  42. package/lib/types/schemas.d.ts +112 -0
  43. package/lib/views.d.ts +27 -0
  44. package/lib/views.js +218 -0
  45. package/lib/views.js.map +1 -0
  46. package/package.json +130 -0
  47. package/scripts/install-preset.mjs +49 -0
  48. package/scripts/uninstall-preset.mjs +22 -0
@@ -0,0 +1,9 @@
1
+ /** Well-known skill roots of other AI coding agents (relative to home). */
2
+ export declare const AGENT_SKILL_DIRS: ReadonlyArray<readonly [id: string, rel: string]>;
3
+ /** Whether a directory exists and is a directory. */
4
+ export declare function directoryExists(path: string): Promise<boolean>;
5
+ /**
6
+ * Discover agent skill directories that exist on this machine, home-expanded.
7
+ * @returns absolute paths, existing only.
8
+ */
9
+ export declare function discoverAgentSkillDirs(home?: string): Promise<string[]>;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Auto-discovery of other AI coding agents' skill directories. On first run
3
+ * (and on every scan) any of the well-known homes that actually exists is
4
+ * offered as a scan source, so skills from Claude Code, Codex, Gemini CLI,
5
+ * Cursor, Qoder, Continue, Roo, Cline and Kilo flow into the catalog without
6
+ * any manual setup.
7
+ *
8
+ * @module dsh-agent-skills/discovery
9
+ */
10
+ import { homedir } from "node:os";
11
+ import { access } from "node:fs/promises";
12
+ import { join } from "node:path";
13
+ /** Well-known skill roots of other AI coding agents (relative to home). */
14
+ export const AGENT_SKILL_DIRS = [
15
+ ["claude", join(".claude", "skills")],
16
+ ["codex", join(".codex", "skills")],
17
+ ["gemini", join(".gemini", "skills")],
18
+ ["cursor", join(".cursor", "skills")],
19
+ ["qoder", join(".qoder", "skills")],
20
+ ["continue", join(".continue", "skills")],
21
+ ["roo", join(".roo", "skills")],
22
+ ["cline", join(".cline", "skills")],
23
+ ["kilo", join(".kilo", "skills")]
24
+ ];
25
+ /** Whether a directory exists and is a directory. */
26
+ export async function directoryExists(path) {
27
+ try {
28
+ const info = await access(path);
29
+ return true;
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
35
+ /**
36
+ * Discover agent skill directories that exist on this machine, home-expanded.
37
+ * @returns absolute paths, existing only.
38
+ */
39
+ export async function discoverAgentSkillDirs(home = homedir()) {
40
+ const found = [];
41
+ for (const [, rel] of AGENT_SKILL_DIRS) {
42
+ const path = join(home, rel);
43
+ if (await directoryExists(path))
44
+ found.push(path);
45
+ }
46
+ return found;
47
+ }
48
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,2EAA2E;AAC3E,MAAM,CAAC,MAAM,gBAAgB,GAAsD;IACjF,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IACzC,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC/B,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;CAClC,CAAC;AAEF,qDAAqD;AACrD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY;IAChD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,IAAI,GAAG,OAAO,EAAE;IAC3D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,gBAAgB,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC7B,IAAI,MAAM,eAAe,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * dsh-agent-skills — host entry.
3
+ *
4
+ * The same package is mounted in two planes:
5
+ *
6
+ * 1. HOST row (web profile bundle, id `agent-skills`): the settings-page
7
+ * service. It owns the durable store (custom scan dirs + toggles), exposes
8
+ * the `agentSkills` typert namespace for the browser half, and publishes
9
+ * catalog invalidations so toggles reach the model on the next agent step.
10
+ *
11
+ * 2. PRESET row (appended to the shipped agent presets by
12
+ * scripts/install-preset.mjs): registers the `agent-skills` provider into
13
+ * the preset layer of the skill registry, where it re-emits every
14
+ * candidate with the user's enable/disable policy and scans the custom
15
+ * directories. The preset layer outranks the global layer, which is what
16
+ * lets the toggles shadow the preset's own skill-filesystem provider.
17
+ *
18
+ * @module dsh-agent-skills
19
+ */
20
+ import type { Context } from "@deepseek-ai/cordis";
21
+ /** Stable cordis plugin name. */
22
+ export declare const name = "agent-skills";
23
+ /** The skill registry is required in both planes. */
24
+ export declare const inject: string[];
25
+ /**
26
+ * Mount the plugin. Both planes register the skill provider:
27
+ * - the HOST row registers into the global layer (covers host-level
28
+ * compositions such as the headless profile, where skill-filesystem is a
29
+ * host row);
30
+ * - a PRESET row registers into its preset layer, which outranks the
31
+ * global layer for agent-visible skills (the web profile's arrangement).
32
+ * The host row additionally provides the settings-page service and the
33
+ * `agentSkills` typert namespace.
34
+ */
35
+ export declare function apply(ctx: Context): Promise<void>;
package/lib/index.js ADDED
@@ -0,0 +1,26 @@
1
+ import { scopeOf } from "@deepseek-ai/dsh-scope";
2
+ import { AgentSkillsRuntime } from "./runtime.js";
3
+ import { createAgentSkillsProvider } from "./provider.js";
4
+ /** Stable cordis plugin name. */
5
+ export const name = "agent-skills";
6
+ /** The skill registry is required in both planes. */
7
+ export const inject = ["skills"];
8
+ /**
9
+ * Mount the plugin. Both planes register the skill provider:
10
+ * - the HOST row registers into the global layer (covers host-level
11
+ * compositions such as the headless profile, where skill-filesystem is a
12
+ * host row);
13
+ * - a PRESET row registers into its preset layer, which outranks the
14
+ * global layer for agent-visible skills (the web profile's arrangement).
15
+ * The host row additionally provides the settings-page service and the
16
+ * `agentSkills` typert namespace.
17
+ */
18
+ export async function apply(ctx) {
19
+ const scope = scopeOf(ctx);
20
+ ctx.skills.registerProvider((control) => createAgentSkillsProvider(ctx, control));
21
+ if (scope === undefined) {
22
+ // Host plane: settings-page service + typert namespace.
23
+ new AgentSkillsRuntime(ctx);
24
+ }
25
+ }
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAE1D,iCAAiC;AACjC,MAAM,CAAC,MAAM,IAAI,GAAG,cAAc,CAAC;AAEnC,qDAAqD;AACrD,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC;AAEjC;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,GAAY;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,yBAAyB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IAClF,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,wDAAwD;QACxD,IAAI,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Preset-only entry point. It contributes the provider to the preset's
3
+ * scoped skill layer and deliberately does not construct host services such
4
+ * as `agentSkills`.
5
+ */
6
+ import type { Context } from "@deepseek-ai/cordis";
7
+ export declare const name = "agent-skills-preset";
8
+ export declare const inject: string[];
9
+ export declare function apply(ctx: Context): void;
package/lib/preset.js ADDED
@@ -0,0 +1,7 @@
1
+ import { createAgentSkillsProvider } from "./provider.js";
2
+ export const name = "agent-skills-preset";
3
+ export const inject = ["skills"];
4
+ export function apply(ctx) {
5
+ ctx.skills.registerProvider((control) => createAgentSkillsProvider(ctx, control));
6
+ }
7
+ //# sourceMappingURL=preset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preset.js","sourceRoot":"","sources":["../src/preset.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAE1D,MAAM,CAAC,MAAM,IAAI,GAAG,qBAAqB,CAAC;AAC1C,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC;AAEjC,MAAM,UAAU,KAAK,CAAC,GAAY;IAChC,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,yBAAyB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;AACpF,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The per-agent-preset skill provider. Registered by the preset-scoped half
3
+ * of this plugin into the preset layer of the skill registry — the layer
4
+ * that outranks the global layer for agent-visible skills.
5
+ *
6
+ * Responsibilities:
7
+ * - re-emit every candidate from the layers' other providers (the preset's
8
+ * own skill-filesystem, global providers, runtime registrations) at
9
+ * rank - 1, so this provider's copies win the per-name dedupe and can
10
+ * carry the user's enable/disable policy;
11
+ * - discover user-configured custom scan directories itself;
12
+ * - delegate `get()` to the original provider / file so skill bodies are
13
+ * always loaded by the same code that owns them.
14
+ *
15
+ * @module dsh-agent-skills/provider
16
+ */
17
+ import type { Context } from "@deepseek-ai/cordis";
18
+ import type { SkillCandidate, SkillProvider, SkillProviderControl } from "@deepseek-ai/dsh-skill";
19
+ import { type AgentSkillsState } from "./store.js";
20
+ /** The provider name this plugin registers (never "runtime"). */
21
+ export declare const PROVIDER_NAME = "agent-skills";
22
+ export interface RootPolicy {
23
+ /** Absolute root path. */
24
+ path: string;
25
+ /** True when the root is disabled by the user. */
26
+ disabled: boolean;
27
+ }
28
+ export interface StateReader {
29
+ read(): Promise<AgentSkillsState>;
30
+ }
31
+ export declare function stateReaderOf(): StateReader;
32
+ /** Longest matching root wins; returns undefined when no root covers the path. */
33
+ export declare function rootFor(path: string | undefined, roots: RootPolicy[]): RootPolicy | undefined;
34
+ /** Builtin roots resolved from the environment (mirrors dsh-skill-filesystem). */
35
+ export declare function builtinRoots(dshHome?: string): Promise<RootPolicy[]>;
36
+ /** Origins of an emitted candidate, attached for `get()` delegation. */
37
+ interface Origin {
38
+ kind: "provider" | "runtime" | "custom";
39
+ provider?: SkillProvider;
40
+ candidate?: SkillCandidate;
41
+ }
42
+ export declare function originOf(candidate: SkillCandidate): Origin | undefined;
43
+ /**
44
+ * Create the preset-scope provider. Watchers on the user's custom directories
45
+ * invalidate the registry cache on file changes so the catalog follows disk
46
+ * edits without a restart.
47
+ */
48
+ export declare function createAgentSkillsProvider(ctx: Context, control: SkillProviderControl, stateReader?: StateReader): SkillProvider;
49
+ /** Find this plugin's provider in any scoped layer (the preset instance). */
50
+ export declare function findPresetProvider(skills: unknown): {
51
+ provider: SkillProvider;
52
+ } | undefined;
53
+ export {};
@@ -0,0 +1,295 @@
1
+ import { scopeOf } from "@deepseek-ai/dsh-scope";
2
+ import { readState, stateFilePath } from "./store.js";
3
+ import { collectAllLayers, dedupeWinners, registryOf, RANK } from "./registry.js";
4
+ import { scanRoot } from "./scan.js";
5
+ import { resolveDshHome } from "@deepseek-ai/dsh-home-paths";
6
+ import { watch } from "node:fs";
7
+ import { resolve } from "node:path";
8
+ /** The provider name this plugin registers (never "runtime"). */
9
+ export const PROVIDER_NAME = "agent-skills";
10
+ export function stateReaderOf() {
11
+ let cached;
12
+ return {
13
+ async read() {
14
+ const { stat } = await import("node:fs/promises");
15
+ const file = stateFilePath();
16
+ let mtimeMs = 0;
17
+ try {
18
+ mtimeMs = (await stat(file)).mtimeMs;
19
+ }
20
+ catch {
21
+ /* missing file counts as the empty state */
22
+ }
23
+ if (cached !== undefined && cached.mtimeMs === mtimeMs)
24
+ return cached.state;
25
+ const state = await readState();
26
+ cached = { mtimeMs, state };
27
+ return state;
28
+ }
29
+ };
30
+ }
31
+ /** Longest matching root wins; returns undefined when no root covers the path. */
32
+ export function rootFor(path, roots) {
33
+ if (path === undefined)
34
+ return undefined;
35
+ let best;
36
+ for (const root of roots) {
37
+ if (path === root.path || path.startsWith(root.path.endsWith("/") ? root.path : root.path + "/")) {
38
+ if (best === undefined || root.path.length > best.path.length)
39
+ best = root;
40
+ }
41
+ }
42
+ return best;
43
+ }
44
+ /** Builtin roots resolved from the environment (mirrors dsh-skill-filesystem). */
45
+ export async function builtinRoots(dshHome = resolveDshHome()) {
46
+ const { homedir } = await import("node:os");
47
+ const roots = [];
48
+ roots.push({ path: resolve(dshHome, "skills"), disabled: false });
49
+ const agentsHome = process.env.DSH_AGENTS_HOME ?? resolve(homedir(), ".agents");
50
+ roots.push({ path: resolve(agentsHome, "skills"), disabled: false });
51
+ if (process.env.DSH_BUNDLED_SKILL_DIR !== undefined && process.env.DSH_BUNDLED_SKILL_DIR !== "") {
52
+ roots.push({ path: resolve(process.env.DSH_BUNDLED_SKILL_DIR), disabled: false });
53
+ }
54
+ return roots;
55
+ }
56
+ const origins = new WeakMap();
57
+ export function originOf(candidate) {
58
+ return origins.get(candidate);
59
+ }
60
+ function emit(candidate, origin, rank) {
61
+ const emitted = {
62
+ ...candidate,
63
+ rank,
64
+ provider: PROVIDER_NAME
65
+ };
66
+ origins.set(emitted, origin);
67
+ return emitted;
68
+ }
69
+ /** Custom-dir candidates (rank 300) from the current state. */
70
+ async function customCandidates(state, logger) {
71
+ const candidates = [];
72
+ const roots = [];
73
+ let localOrder = 0;
74
+ for (const dir of state.dirs) {
75
+ const path = resolve(dir.path);
76
+ roots.push({ path, disabled: dir.enabled === false });
77
+ const scanned = await scanRoot(path, logger);
78
+ for (const skill of scanned.skills) {
79
+ candidates.push(emit({
80
+ name: skill.name,
81
+ description: skill.description,
82
+ ...(skill.whenToUse !== undefined ? { whenToUse: skill.whenToUse } : {}),
83
+ invocation: { modelInvocable: skill.modelInvocable, userInvocable: skill.userInvocable },
84
+ source: "custom",
85
+ provider: PROVIDER_NAME,
86
+ rank: RANK.custom,
87
+ locator: { path: skill.path, directory: skill.directory },
88
+ ...(skill.metadata !== undefined ? { metadata: skill.metadata } : {}),
89
+ resourceBase: { kind: "directory", path: skill.directory },
90
+ path: skill.path
91
+ }, { kind: "custom" }, RANK.custom - 1));
92
+ localOrder += 1;
93
+ }
94
+ }
95
+ return { candidates, roots };
96
+ }
97
+ /** Scan the built-in user roots when no filesystem provider is mounted yet. */
98
+ async function builtinCandidates(roots, logger) {
99
+ const candidates = [];
100
+ for (const root of roots) {
101
+ const scanned = await scanRoot(root.path, logger);
102
+ const source = root.path.endsWith("/skills") && root.path.includes("/.agents/")
103
+ ? "user-agents"
104
+ : root.path.endsWith("/skills") && root.path.includes("/.dsh/")
105
+ ? "user-dsh"
106
+ : "bundled";
107
+ const rank = source === "user-agents" ? RANK.userAgents : source === "user-dsh" ? RANK.userDsh : RANK.bundled;
108
+ for (const skill of scanned.skills) {
109
+ candidates.push(emit({
110
+ name: skill.name,
111
+ description: skill.description,
112
+ ...(skill.whenToUse !== undefined ? { whenToUse: skill.whenToUse } : {}),
113
+ invocation: { modelInvocable: skill.modelInvocable, userInvocable: skill.userInvocable },
114
+ source,
115
+ provider: PROVIDER_NAME,
116
+ rank,
117
+ locator: { path: skill.path, directory: skill.directory },
118
+ resourceBase: { kind: "directory", path: skill.directory },
119
+ path: skill.path,
120
+ ...(skill.metadata !== undefined ? { metadata: skill.metadata } : {})
121
+ }, { kind: "custom" }, rank - 1));
122
+ }
123
+ }
124
+ return candidates;
125
+ }
126
+ /**
127
+ * Create the preset-scope provider. Watchers on the user's custom directories
128
+ * invalidate the registry cache on file changes so the catalog follows disk
129
+ * edits without a restart.
130
+ */
131
+ export function createAgentSkillsProvider(ctx, control, stateReader = stateReaderOf()) {
132
+ const logger = ctx.logger;
133
+ const scope = scopeOf(ctx);
134
+ const watchers = new Map();
135
+ let invalidateQueued = false;
136
+ const queueInvalidate = () => {
137
+ if (invalidateQueued)
138
+ return;
139
+ invalidateQueued = true;
140
+ queueMicrotask(() => {
141
+ invalidateQueued = false;
142
+ control.invalidate();
143
+ });
144
+ };
145
+ const startWatchers = async () => {
146
+ const state = await stateReader.read();
147
+ for (const dir of state.dirs) {
148
+ const path = resolve(dir.path);
149
+ if (watchers.has(path))
150
+ continue;
151
+ try {
152
+ const watcher = watch(path, { recursive: true }, (_event, filename) => {
153
+ if (filename === null || typeof filename !== "string")
154
+ return;
155
+ if (!filename.endsWith(".md"))
156
+ return;
157
+ queueInvalidate();
158
+ });
159
+ watchers.set(path, watcher);
160
+ }
161
+ catch {
162
+ /* recursive watching unsupported or the dir is gone — rescan covers it */
163
+ }
164
+ }
165
+ };
166
+ void startWatchers();
167
+ control.signal.addEventListener("abort", () => {
168
+ for (const watcher of watchers.values()) {
169
+ try {
170
+ watcher.close();
171
+ }
172
+ catch {
173
+ /* already closed */
174
+ }
175
+ }
176
+ watchers.clear();
177
+ }, { once: true });
178
+ return {
179
+ name: PROVIDER_NAME,
180
+ async list(options) {
181
+ const state = await stateReader.read();
182
+ const registry = registryOf(ctx.skills);
183
+ const myLayer = scope === undefined ? registry.layers.global : registry.layers.scoped.get(scope);
184
+ void myLayer; // self is skipped by name below, layer lookup only needed for structure
185
+ const inner = await collectAllLayers(registry, options, logger, PROVIDER_NAME);
186
+ const custom = await customCandidates(state, logger);
187
+ const builtins = await builtinRoots();
188
+ const builtin = await builtinCandidates(builtins, logger);
189
+ const roots = [...custom.roots, ...builtins];
190
+ const disabledDirs = new Set(state.disabledDirs);
191
+ const disabledSkills = new Set(state.disabledSkills);
192
+ const policy = roots.map((root) => ({
193
+ path: root.path,
194
+ disabled: root.disabled || disabledDirs.has(root.path)
195
+ }));
196
+ const winners = dedupeWinners(inner.entries);
197
+ const emitted = winners.map((entry) => {
198
+ const dir = rootFor(entry.candidate.resourceBase?.kind === "directory" ? entry.candidate.resourceBase.path : entry.candidate.path, policy);
199
+ const disabled = disabledSkills.has(entry.candidate.name) || (dir !== undefined && dir.disabled);
200
+ const invocation = entry.candidate.invocation ?? { modelInvocable: true, userInvocable: true };
201
+ const origin = entry.provider === undefined
202
+ ? { kind: "runtime" }
203
+ : { kind: "provider", provider: entry.provider, candidate: entry.candidate };
204
+ return emit({
205
+ ...entry.candidate,
206
+ invocation: disabled ? { modelInvocable: false, userInvocable: false } : invocation,
207
+ provider: PROVIDER_NAME
208
+ }, origin, entry.candidate.rank - 1);
209
+ });
210
+ // Custom candidates flow through the same policy (a disabled custom dir
211
+ // hides its skills; an explicitly disabled skill wins over the dir flag).
212
+ for (const candidate of custom.candidates) {
213
+ const dir = rootFor(candidate.resourceBase?.kind === "directory" ? candidate.resourceBase.path : candidate.path, policy);
214
+ const disabled = disabledSkills.has(candidate.name) || (dir !== undefined && dir.disabled);
215
+ if (disabled) {
216
+ emitted.push({ ...candidate, invocation: { modelInvocable: false, userInvocable: false } });
217
+ }
218
+ else {
219
+ emitted.push(candidate);
220
+ }
221
+ }
222
+ // The host settings service can be ready before the preset's filesystem
223
+ // provider. Keep the page and the next model step useful during that
224
+ // window by scanning the same built-in roots directly. When the official
225
+ // provider is present its candidates have the same rank and the wrapper
226
+ // above wins the duplicate deterministically.
227
+ for (const candidate of builtin) {
228
+ const dir = rootFor(candidate.resourceBase?.kind === "directory" ? candidate.resourceBase.path : candidate.path, policy);
229
+ const disabled = disabledSkills.has(candidate.name) || (dir !== undefined && dir.disabled);
230
+ if (disabled)
231
+ emitted.push({ ...candidate, invocation: { modelInvocable: false, userInvocable: false } });
232
+ else
233
+ emitted.push(candidate);
234
+ }
235
+ const unique = dedupeWinners(emitted.map((candidate, localOrder) => ({
236
+ candidate,
237
+ provider: undefined,
238
+ providerOrder: 0,
239
+ localOrder
240
+ }))).map((entry) => entry.candidate);
241
+ return {
242
+ candidates: unique,
243
+ complete: inner.complete
244
+ };
245
+ },
246
+ async get(candidate, options) {
247
+ const origin = origins.get(candidate);
248
+ if (origin === undefined)
249
+ return undefined;
250
+ if (origin.kind === "provider" && origin.provider !== undefined && origin.candidate !== undefined) {
251
+ const definition = await origin.provider.get(origin.candidate, options);
252
+ if (definition === undefined)
253
+ return undefined;
254
+ return definition;
255
+ }
256
+ if (origin.kind === "runtime") {
257
+ const locator = candidate.locator;
258
+ return locator;
259
+ }
260
+ if (origin.kind === "custom") {
261
+ const locator = candidate;
262
+ if (locator.locator?.path === undefined)
263
+ return undefined;
264
+ const { parseSkillFile } = await import("./scan.js");
265
+ const parsed = await parseSkillFile(locator.locator.path, logger);
266
+ if (parsed === undefined)
267
+ return undefined;
268
+ return {
269
+ name: parsed.name,
270
+ description: parsed.description,
271
+ ...(parsed.whenToUse !== undefined ? { whenToUse: parsed.whenToUse } : {}),
272
+ invocation: { modelInvocable: parsed.modelInvocable, userInvocable: parsed.userInvocable },
273
+ source: candidate.source,
274
+ provider: PROVIDER_NAME,
275
+ resourceBase: { kind: "directory", path: parsed.directory },
276
+ path: parsed.path,
277
+ ...(parsed.metadata !== undefined ? { metadata: parsed.metadata } : {}),
278
+ content: parsed.content
279
+ };
280
+ }
281
+ return undefined;
282
+ }
283
+ };
284
+ }
285
+ /** Find this plugin's provider in any scoped layer (the preset instance). */
286
+ export function findPresetProvider(skills) {
287
+ const registry = registryOf(skills);
288
+ for (const layer of registry.layers.scoped.values()) {
289
+ const found = layer.providers.get(PROVIDER_NAME);
290
+ if (found !== undefined)
291
+ return found;
292
+ }
293
+ return undefined;
294
+ }
295
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Internal access to the skill registry's layered provider tables.
3
+ *
4
+ * The official types keep `SkillRegistry.layers` private; this module is the
5
+ * single place that reaches through (cast to a structural shape), reads
6
+ * provider candidates, and triggers catalog invalidation. Everything here is
7
+ * read-only except `invalidateSkillCache`, which is exactly what the
8
+ * "重新扫描" button and every toggle need to republish the model catalog.
9
+ *
10
+ * @module dsh-agent-skills/registry
11
+ */
12
+ import type { SkillCandidate, SkillDefinition, SkillLookupOptions, SkillProvider } from "@deepseek-ai/dsh-skill";
13
+ /** Structural view of one registry layer (the compiled class shape). */
14
+ export interface LayerShape {
15
+ providers: {
16
+ get(name: string): {
17
+ provider: SkillProvider;
18
+ order: number;
19
+ } | undefined;
20
+ values(): IterableIterator<{
21
+ provider: SkillProvider;
22
+ order: number;
23
+ }>;
24
+ };
25
+ runtime: Map<string, SkillDefinition>;
26
+ }
27
+ /** Structural view of the SkillRegistry service. */
28
+ export interface RegistryShape {
29
+ layers: {
30
+ global: LayerShape;
31
+ scoped: Map<unknown, LayerShape>;
32
+ };
33
+ invalidateCache(): void;
34
+ }
35
+ /** Cast a `ctx.skills` service to the structural shape. */
36
+ export declare function registryOf(skills: unknown): RegistryShape;
37
+ /** One collected candidate plus its origin, mirroring the registry's internal entry. */
38
+ export interface CandidateEntry {
39
+ candidate: SkillCandidate;
40
+ /** Original provider for `get()` delegation; undefined for runtime entries. */
41
+ provider: SkillProvider | undefined;
42
+ /** Original provider registration order (tie-break for equal ranks). */
43
+ providerOrder: number;
44
+ /** Per-provider emission order (tie-break). */
45
+ localOrder: number;
46
+ }
47
+ /** Skill rank constants mirroring @deepseek-ai/dsh-skill-filesystem. */
48
+ export declare const RANK: {
49
+ readonly projectDsh: 100;
50
+ readonly projectAgents: 200;
51
+ readonly runtime: 250;
52
+ readonly custom: 300;
53
+ readonly userDsh: 400;
54
+ readonly userAgents: 500;
55
+ readonly bundled: 600;
56
+ };
57
+ /** The runtime provider name (reserved by the skill registry). */
58
+ export declare const RUNTIME_PROVIDER_NAME = "runtime";
59
+ /** Normalize one provider observation into candidates + completeness. */
60
+ export declare function normalizeObservation(output: unknown, providerName: string): {
61
+ candidates: readonly SkillCandidate[];
62
+ complete: boolean;
63
+ };
64
+ /**
65
+ * Collect candidates from one layer: runtime entries first (rank 250), then
66
+ * each provider in registration order. A provider that throws is skipped and
67
+ * marks the observation incomplete (mirrors the registry's own resilience).
68
+ */
69
+ export declare function collectLayer(layer: LayerShape, options: SkillLookupOptions, logger: {
70
+ warn(message: string): void;
71
+ }, excludeProvider?: string): Promise<{
72
+ entries: CandidateEntry[];
73
+ complete: boolean;
74
+ }>;
75
+ /** Collect candidates from the global layer and every scoped layer. */
76
+ export declare function collectAllLayers(registry: RegistryShape, options: SkillLookupOptions, logger: {
77
+ warn(message: string): void;
78
+ }, excludeProvider?: string): Promise<{
79
+ entries: CandidateEntry[];
80
+ complete: boolean;
81
+ }>;
82
+ /** First-wins dedupe after rank/providerOrder/localOrder sort (registry semantics). */
83
+ export declare function dedupeWinners(entries: CandidateEntry[]): CandidateEntry[];
84
+ /** Force the registry to re-collect on the next `list()`/snapshot. */
85
+ export declare function invalidateSkillCache(skills: unknown): void;