@getbourdon/participants 0.5.5 → 0.6.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.
- package/dist/index.cjs +3595 -772
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +954 -5
- package/dist/index.d.ts +6 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/readers/claude-code.d.ts +21 -2
- package/dist/readers/claude-code.js +31 -1
- package/dist/readers/cursor.d.ts +23 -2
- package/dist/readers/cursor.js +33 -1
- package/dist/skill-index.d.ts +110 -0
- package/dist/skill-index.js +470 -0
- package/dist/skill-proposals.d.ts +212 -0
- package/dist/skill-proposals.js +757 -0
- package/dist/skill-shares.d.ts +128 -0
- package/dist/skill-shares.js +366 -0
- package/dist/skill-store.d.ts +186 -0
- package/dist/skill-store.js +750 -0
- package/dist/skills.d.ts +295 -0
- package/dist/skills.js +999 -0
- package/package.json +5 -4
package/dist/skills.d.ts
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill readers: advertise the local skills an agent can see in its L5
|
|
3
|
+
* manifest (plan 005, discovery side). Port of `participants/_skills.py`.
|
|
4
|
+
*
|
|
5
|
+
* A participant that knows where its agent keeps skills (a folder per skill
|
|
6
|
+
* holding a `SKILL.md` with `name` / `description` front matter) lists them as
|
|
7
|
+
* `SkillRef` rows: name, description and a content hash. Nothing is shared or
|
|
8
|
+
* promoted here; the body never enters the manifest.
|
|
9
|
+
*
|
|
10
|
+
* Two kinds of skill directory:
|
|
11
|
+
* - **The agent's own** (`~/.claude/skills`, `$CODEX_HOME/skills`,
|
|
12
|
+
* `~/.cursor/skills` and their project forms).
|
|
13
|
+
* - **The cross-agent store**, `~/.agents/skills` (and `<project>/.agents/skills`):
|
|
14
|
+
* a vendor-neutral directory no single agent owns. The cross-agent skills
|
|
15
|
+
* installer CLI keeps its installs there and records each one in
|
|
16
|
+
* `~/.agents/.skill-lock.json`; people also write skills there by hand. Refs
|
|
17
|
+
* from it carry `store: cross_agent`. Every skill-reading participant reads
|
|
18
|
+
* it with its own directories; a reader of several manifests collapses the
|
|
19
|
+
* copies (`collectAdvertisedSkills` in @getbourdon/federation).
|
|
20
|
+
*
|
|
21
|
+
* One skill, one ref per manifest: when an agent's own folder holds a skill
|
|
22
|
+
* that is also in the cross-agent store, the agent-folder ref is kept and
|
|
23
|
+
* records the store copy in `also_in` (`via: copy` for a copy with the same
|
|
24
|
+
* `content_sha256`, `via: link` for a link into the store); the store's own ref
|
|
25
|
+
* is then left out. A link counts only when it resolves to a direct child
|
|
26
|
+
* folder of the store at the same scope, and the skill is then read through
|
|
27
|
+
* the store's own path, never through the link. Any other link is skipped.
|
|
28
|
+
*
|
|
29
|
+
* Provenance (user-level store only): a skill with an entry in the installer
|
|
30
|
+
* lock carries `origin: {kind: installed, ...}`; one without carries
|
|
31
|
+
* `origin: {kind: authored}`. Nothing else is read from the lock, and a
|
|
32
|
+
* missing, linked, oversized or malformed lock never fails a scan.
|
|
33
|
+
*
|
|
34
|
+
* Scope: one skill at a time. By default a participant lists only the skills
|
|
35
|
+
* the person approved one by one with `bourdon skills share` (stored locally
|
|
36
|
+
* in `<library>/.skill-shares.json`, see skill-shares.ts), and only while the
|
|
37
|
+
* folder still hashes to the approved content; no other skill folder is read.
|
|
38
|
+
* `BOURDON_SKILLS_ADVERTISE` set to an on value lists every skill; an off
|
|
39
|
+
* value or an unrecognised one lists none, shared or not. A caller that builds
|
|
40
|
+
* a participant with explicit `skillSources` lists every skill in them
|
|
41
|
+
* ({@link skillsListingMode}). The directories: user-level skill directories,
|
|
42
|
+
* and a project's directories
|
|
43
|
+
* only when the project is named in `BOURDON_SKILL_PROJECTS` (absolute paths
|
|
44
|
+
* separated by the platform's path delimiter). Disallowed files are skipped
|
|
45
|
+
* and flagged, never fatal; no link is followed; no absolute path reaches the
|
|
46
|
+
* manifest (`path_hint` starts at a symbolic root); refs are emitted as
|
|
47
|
+
* `team`.
|
|
48
|
+
*/
|
|
49
|
+
import { type SkillOriginModel, type SkillRefModel } from "@getbourdon/l5";
|
|
50
|
+
/** Opt-in list of project roots whose skill directories may be indexed. */
|
|
51
|
+
export declare const SKILL_PROJECTS_ENV = "BOURDON_SKILL_PROJECTS";
|
|
52
|
+
/**
|
|
53
|
+
* The listing switch for every participant. Skill descriptions are free text
|
|
54
|
+
* and can name private projects, clients or infrastructure, so by default
|
|
55
|
+
* (unset or empty) only the skills approved one by one are listed. `1` /
|
|
56
|
+
* `true` / `yes` / `on` list every skill; `0` / `false` / `no` / `off` list
|
|
57
|
+
* none, approved or not, and so does any other value (fail closed): a typo
|
|
58
|
+
* never lists anything.
|
|
59
|
+
*/
|
|
60
|
+
export declare const SKILLS_ADVERTISE_ENV = "BOURDON_SKILLS_ADVERTISE";
|
|
61
|
+
/**
|
|
62
|
+
* Turns named participants off in every mode: agent ids separated by commas
|
|
63
|
+
* (or whitespace), e.g. `codex,cursor`. Matching ignores case.
|
|
64
|
+
*/
|
|
65
|
+
export declare const SKILLS_NO_ADVERTISE_ENV = "BOURDON_SKILLS_NO_ADVERTISE";
|
|
66
|
+
/** {@link skillsListingMode} results. */
|
|
67
|
+
export declare const LIST_ALL = "all";
|
|
68
|
+
export declare const LIST_APPROVED = "approved";
|
|
69
|
+
export declare const LIST_OFF = "off";
|
|
70
|
+
export type SkillsListingMode = typeof LIST_ALL | typeof LIST_APPROVED | typeof LIST_OFF;
|
|
71
|
+
/** Every advertised ref carries this visibility. */
|
|
72
|
+
export declare const SKILL_REF_VISIBILITY: "team";
|
|
73
|
+
/** The L5 schema bounds (`skills.maxItems` and the `SkillRef` fields). */
|
|
74
|
+
export declare const MAX_SKILL_REFS = 512;
|
|
75
|
+
export declare const MAX_SKIPPED_FILES = 32;
|
|
76
|
+
export declare const MAX_PATH_HINT_CHARS = 255;
|
|
77
|
+
export declare const MAX_PROJECT_NAME_CHARS = 128;
|
|
78
|
+
export declare const MAX_ORIGIN_SOURCE_CHARS = 255;
|
|
79
|
+
export declare const MAX_ORIGIN_URL_CHARS = 512;
|
|
80
|
+
export declare const MAX_ORIGIN_SOURCE_TYPE_CHARS = 32;
|
|
81
|
+
/** An installer lock larger than this is not read (origin is then omitted). */
|
|
82
|
+
export declare const MAX_LOCK_BYTES: number;
|
|
83
|
+
export declare const SCOPE_USER = "user";
|
|
84
|
+
export declare const SCOPE_PROJECT = "project";
|
|
85
|
+
/** Whose directory a skill folder sits in; `agent` is the default and never written. */
|
|
86
|
+
export declare const STORE_AGENT = "agent";
|
|
87
|
+
export declare const STORE_CROSS_AGENT = "cross_agent";
|
|
88
|
+
export declare const VIA_COPY = "copy";
|
|
89
|
+
export declare const VIA_LINK = "link";
|
|
90
|
+
export declare const ORIGIN_INSTALLED = "installed";
|
|
91
|
+
export declare const ORIGIN_AUTHORED = "authored";
|
|
92
|
+
/** The cross-agent installer's lock file, beside the user-level store. */
|
|
93
|
+
export declare const CROSS_AGENT_LOCK_NAME = ".skill-lock.json";
|
|
94
|
+
/**
|
|
95
|
+
* One directory a reader indexes, one skill per child folder. `label` is the
|
|
96
|
+
* symbolic form of `root` that `path_hint` starts with; it never contains an
|
|
97
|
+
* absolute path. `store` says whose directory it is; `lockFile` is the
|
|
98
|
+
* installer lock that records where the store's skills came from.
|
|
99
|
+
*/
|
|
100
|
+
export interface SkillSource {
|
|
101
|
+
root: string;
|
|
102
|
+
scope: string;
|
|
103
|
+
label: string;
|
|
104
|
+
project?: string | null;
|
|
105
|
+
store?: string;
|
|
106
|
+
lockFile?: string | null;
|
|
107
|
+
}
|
|
108
|
+
/** A skill (or a whole skills directory) that was not advertised, and why. */
|
|
109
|
+
export interface SkippedSkill {
|
|
110
|
+
pathHint: string;
|
|
111
|
+
scope: string;
|
|
112
|
+
reason: string;
|
|
113
|
+
project?: string | null;
|
|
114
|
+
}
|
|
115
|
+
export interface SkillScanReport {
|
|
116
|
+
refs: SkillRefModel[];
|
|
117
|
+
skipped: SkippedSkill[];
|
|
118
|
+
}
|
|
119
|
+
/** The home directory user-level skill directories are found under. */
|
|
120
|
+
export declare function userHome(): string;
|
|
121
|
+
/**
|
|
122
|
+
* Project roots opted in through {@link SKILL_PROJECTS_ENV}, in order. Only
|
|
123
|
+
* absolute paths count: a relative entry is ignored (and logged) rather than
|
|
124
|
+
* resolved against whatever directory the export happens to run in.
|
|
125
|
+
*/
|
|
126
|
+
export declare function skillProjects(): string[];
|
|
127
|
+
export interface SkillSourceOptions {
|
|
128
|
+
/** The home directory to use instead of {@link userHome}. */
|
|
129
|
+
home?: string;
|
|
130
|
+
/** Project roots instead of {@link skillProjects}. */
|
|
131
|
+
projects?: readonly string[];
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Claude Code: `<config dir>/skills` and, on opt-in, `<project>/.claude/skills`.
|
|
135
|
+
* The config directory is `CLAUDE_CONFIG_DIR` (Claude Code's own override),
|
|
136
|
+
* else `CLAUDE_HOME`, else `~/.claude`.
|
|
137
|
+
*/
|
|
138
|
+
export declare function claudeCodeSkillSources(options?: SkillSourceOptions): SkillSource[];
|
|
139
|
+
/**
|
|
140
|
+
* Codex: `$CODEX_HOME/skills`. `codexHome` is an explicit Codex home, if one
|
|
141
|
+
* was given; otherwise `CODEX_HOME`, else `~/.codex`. Codex keeps its bundled
|
|
142
|
+
* skills in a hidden `.system` folder there, which is not indexed. The mirror
|
|
143
|
+
* has no Codex participant yet; this is the source a Codex reader would use.
|
|
144
|
+
*/
|
|
145
|
+
export declare function codexSkillSources(options?: {
|
|
146
|
+
codexHome?: string | null;
|
|
147
|
+
home?: string;
|
|
148
|
+
}): SkillSource[];
|
|
149
|
+
/**
|
|
150
|
+
* Cursor: `~/.cursor/skills` and, on opt-in, `<project>/.cursor/skills`.
|
|
151
|
+
* `CURSOR_HOME` overrides `~/.cursor`. `~/.cursor/skills-cursor` holds
|
|
152
|
+
* Cursor's own built-in skills and is not indexed.
|
|
153
|
+
*/
|
|
154
|
+
export declare function cursorSkillSources(options?: SkillSourceOptions): SkillSource[];
|
|
155
|
+
/**
|
|
156
|
+
* The vendor-neutral store: `~/.agents/skills` and, on opt-in,
|
|
157
|
+
* `<project>/.agents/skills`. The user-level store comes with the installer
|
|
158
|
+
* lock for provenance; no lock is read for a project store.
|
|
159
|
+
*/
|
|
160
|
+
export declare function crossAgentSkillSources(options?: SkillSourceOptions): SkillSource[];
|
|
161
|
+
type LockEntry = Record<string, unknown>;
|
|
162
|
+
/**
|
|
163
|
+
* The `skills` table of the installer lock, keyed by skill name. An empty map
|
|
164
|
+
* when there is no lock (every store skill is then `authored`); `null` when a
|
|
165
|
+
* lock exists but cannot be trusted or parsed (a link, not a regular file, too
|
|
166
|
+
* large, not JSON, or without a `skills` mapping), in which case origin is left
|
|
167
|
+
* off rather than guessed.
|
|
168
|
+
*/
|
|
169
|
+
export declare function readInstallLock(path: string): Map<string, LockEntry> | null;
|
|
170
|
+
/**
|
|
171
|
+
* `installed` with the lock entry's sanitised source fields, else `authored`.
|
|
172
|
+
* Reads only `source`, `sourceType`, `sourceUrl` and `updatedAt`; a field
|
|
173
|
+
* that is missing, of the wrong type or fails its check is left out.
|
|
174
|
+
*/
|
|
175
|
+
export declare function originFromLockEntry(entry: LockEntry | null | undefined): SkillOriginModel;
|
|
176
|
+
/** Which child folders of a source to read: absent reads every one. */
|
|
177
|
+
export type SkillFolderFilter = (source: SkillSource, folderName: string) => boolean;
|
|
178
|
+
export interface ScanSkillSourcesOptions {
|
|
179
|
+
/**
|
|
180
|
+
* Limits the scan to the child folders it accepts; every other folder is
|
|
181
|
+
* passed over unread. A store folder that an accepted agent folder links to
|
|
182
|
+
* is read too, so the link resolves as in a full scan. An accepted agent
|
|
183
|
+
* folder that is a copy of a store folder the scan did not read carries no
|
|
184
|
+
* `also_in`.
|
|
185
|
+
*/
|
|
186
|
+
include?: SkillFolderFilter | null;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Index every source; one ref per skill, first occurrence of a name wins per
|
|
190
|
+
* store and scope. Cross-agent stores are scanned first so the agent's own
|
|
191
|
+
* folders can be matched against them (`also_in`). Refs come back with the
|
|
192
|
+
* agent's own folders first, in source order, then the cross-agent store
|
|
193
|
+
* skills that no advertised agent folder already represents.
|
|
194
|
+
*/
|
|
195
|
+
export declare function scanSkillSources(sources: Iterable<SkillSource>, options?: ScanSkillSourcesOptions): SkillScanReport;
|
|
196
|
+
/** A participant that advertises skills (plan 005). */
|
|
197
|
+
export interface SkillAdvertiser {
|
|
198
|
+
agentId: string;
|
|
199
|
+
exportSkills(): SkillRefModel[];
|
|
200
|
+
/**
|
|
201
|
+
* Whether the participant was built with explicit `skillSources`, which
|
|
202
|
+
* lists every skill in them ({@link skillsListingMode}). Absent = no.
|
|
203
|
+
*/
|
|
204
|
+
hasExplicitSkillSources?(): boolean;
|
|
205
|
+
/**
|
|
206
|
+
* The directories the reader indexes. When present, the default
|
|
207
|
+
* (approved-only) mode reads just the approved folders in them; without it
|
|
208
|
+
* the reader's own scan runs and only approved refs are kept.
|
|
209
|
+
*/
|
|
210
|
+
skillSources?(): SkillSource[];
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Which skills the participant `agentId` may list in its manifest.
|
|
214
|
+
*
|
|
215
|
+
* - {@link LIST_APPROVED}: {@link SKILLS_ADVERTISE_ENV} unset or empty: only
|
|
216
|
+
* the skills approved one by one (`bourdon skills share`) whose folder still
|
|
217
|
+
* hashes to the approved content.
|
|
218
|
+
* - {@link LIST_ALL}: an on value; or, while the variable is unset, a
|
|
219
|
+
* participant built with explicit `skillSources` (the caller chose what to
|
|
220
|
+
* index).
|
|
221
|
+
* - {@link LIST_OFF}: an off value, or any unrecognised one (fail closed):
|
|
222
|
+
* nothing is listed, approved or not.
|
|
223
|
+
*
|
|
224
|
+
* {@link SKILLS_NO_ADVERTISE_ENV} turns named participants off in every mode.
|
|
225
|
+
*/
|
|
226
|
+
export declare function skillsListingMode(agentId: string, options?: {
|
|
227
|
+
explicitSources?: boolean;
|
|
228
|
+
}): SkillsListingMode;
|
|
229
|
+
/**
|
|
230
|
+
* Whether the participant `agentId` lists every skill it can see: true only
|
|
231
|
+
* in {@link LIST_ALL} mode ({@link skillsListingMode}). In the default mode a
|
|
232
|
+
* participant lists only the skills shared one by one.
|
|
233
|
+
*/
|
|
234
|
+
export declare function skillsAdvertisingEnabled(agentId: string, options?: {
|
|
235
|
+
explicitSources?: boolean;
|
|
236
|
+
}): boolean;
|
|
237
|
+
/**
|
|
238
|
+
* The refs `participant`'s manifest carries, for `exportL5`.
|
|
239
|
+
*
|
|
240
|
+
* Follows {@link skillsListingMode}: nothing, and no skill directory read,
|
|
241
|
+
* when off; by default only the skills with a current approval, reading only
|
|
242
|
+
* their folders; every skill the reader sees when listing all. A participant
|
|
243
|
+
* built with explicit `skillSources` lists all unless turned off. A failure
|
|
244
|
+
* here never fails an export: skills are an addition to the manifest, not a
|
|
245
|
+
* reason to lose its memory rows. Private refs are dropped, as private
|
|
246
|
+
* entities are.
|
|
247
|
+
*/
|
|
248
|
+
export declare function advertisedSkills(participant: SkillAdvertiser): SkillRefModel[];
|
|
249
|
+
/**
|
|
250
|
+
* The default skill directories of a built-in skill-reading participant.
|
|
251
|
+
*
|
|
252
|
+
* The same directories the participant's own export reads (its user-level
|
|
253
|
+
* directory honouring its home override, the opted-in projects, and the
|
|
254
|
+
* cross-agent store). `null` for an agent with no skill reader here, so a skill
|
|
255
|
+
* it advertises can be listed but not proposed from this machine.
|
|
256
|
+
*/
|
|
257
|
+
export declare function skillSourcesForAgent(agentId: string): SkillSource[] | null;
|
|
258
|
+
/**
|
|
259
|
+
* The folder an advertised ref was scanned from, found through `sources` only.
|
|
260
|
+
*
|
|
261
|
+
* `ref` is a SkillRef as it sits in a manifest. Its `path_hint` is matched
|
|
262
|
+
* against each source's symbolic label (same scope and project), so the result
|
|
263
|
+
* is always one direct child of a directory the reader indexes; a path from
|
|
264
|
+
* anywhere else cannot be produced. A ref that is a link into the cross-agent
|
|
265
|
+
* store resolves to the store's own folder, as the reader read it. `null` when
|
|
266
|
+
* nothing matches.
|
|
267
|
+
*/
|
|
268
|
+
export declare function resolveAdvertisedFolder(sources: readonly SkillSource[], ref: Readonly<Record<string, unknown>>): string | null;
|
|
269
|
+
/** The built-in skill readers, in listing order. */
|
|
270
|
+
export declare const SKILL_READERS: readonly ["claude-code", "codex", "cursor"];
|
|
271
|
+
/**
|
|
272
|
+
* One skill folder a built-in reader sees, for `bourdon skills available|share`.
|
|
273
|
+
*
|
|
274
|
+
* `agent` is the reader that owns the folder, or `null` for a cross-agent
|
|
275
|
+
* store folder; `agents` names every reader that sees it. Local use only:
|
|
276
|
+
* `folder` is an absolute path and never leaves the terminal command that
|
|
277
|
+
* asked for it.
|
|
278
|
+
*/
|
|
279
|
+
export interface LocalSkill {
|
|
280
|
+
ref: SkillRefModel;
|
|
281
|
+
agent: string | null;
|
|
282
|
+
agents: string[];
|
|
283
|
+
folder: string;
|
|
284
|
+
/** `agent` or `cross_agent`. */
|
|
285
|
+
store: string;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Every skill folder the built-in readers see on this machine (each one is
|
|
289
|
+
* read). The same directories the readers' exports use: user-level, opted-in
|
|
290
|
+
* projects and the cross-agent store. One row per folder; a store folder seen
|
|
291
|
+
* by several readers is one row naming them all. `agent` keeps the folders
|
|
292
|
+
* that one reader sees.
|
|
293
|
+
*/
|
|
294
|
+
export declare function localSkills(agent?: string | null): LocalSkill[];
|
|
295
|
+
export {};
|