@wrongstack/core 0.277.2 → 0.280.1

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 (83) hide show
  1. package/dist/{agent-bridge-BFJ2ODzI.d.ts → agent-bridge-DXC6QDJ4.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-BimKihiC.d.ts → agent-subagent-runner-PoqNKiR4.d.ts} +563 -471
  3. package/dist/{compactor-D3BGw26y.d.ts → compactor-U3agvUIG.d.ts} +1 -1
  4. package/dist/{config-DAOjriz9.d.ts → config-Cr3312zc.d.ts} +102 -4
  5. package/dist/coordination/index.d.ts +1087 -998
  6. package/dist/coordination/index.js +12235 -12052
  7. package/dist/coordination/index.js.map +1 -1
  8. package/dist/defaults/index.d.ts +31 -30
  9. package/dist/defaults/index.js +403 -189
  10. package/dist/defaults/index.js.map +1 -1
  11. package/dist/{brain-CCfuEOdp.d.ts → events-Bs2fmldo.d.ts} +117 -112
  12. package/dist/execution/index.d.ts +27 -19
  13. package/dist/execution/index.js +216 -63
  14. package/dist/execution/index.js.map +1 -1
  15. package/dist/execution/prompt-enhancer.d.ts +1 -1
  16. package/dist/execution/prompt-enhancer.js.map +1 -1
  17. package/dist/extension/index.d.ts +8 -7
  18. package/dist/{global-mailbox-Dr4cTKqL.d.ts → global-mailbox-Ct7IorLJ.d.ts} +84 -6
  19. package/dist/{goal-store-C1uH4srH.d.ts → goal-store-C4F6DjC0.d.ts} +1 -1
  20. package/dist/hq/index.d.ts +504 -7
  21. package/dist/hq/index.js +1069 -20
  22. package/dist/hq/index.js.map +1 -1
  23. package/dist/{index-DJXj-dcr.d.ts → index-kidebiDh.d.ts} +8 -5
  24. package/dist/{index-cMEmzCVN.d.ts → index-nP09-oP2.d.ts} +2 -2
  25. package/dist/index.d.ts +153 -76
  26. package/dist/index.js +5791 -3163
  27. package/dist/index.js.map +1 -1
  28. package/dist/infrastructure/index.d.ts +7 -6
  29. package/dist/kernel/index.d.ts +14 -13
  30. package/dist/kernel/index.js +31 -15
  31. package/dist/kernel/index.js.map +1 -1
  32. package/dist/{mailbox-types-DTl7bRH3.d.ts → mailbox-types-BGZWrYTJ.d.ts} +38 -0
  33. package/dist/{mcp-servers-CFb60-pH.d.ts → mcp-servers-D910X5_r.d.ts} +3 -3
  34. package/dist/models/index.d.ts +5 -5
  35. package/dist/models/index.js.map +1 -1
  36. package/dist/{models-registry-5Ufn7f2m.d.ts → models-registry-CLkoOcHk.d.ts} +1 -1
  37. package/dist/{multi-agent-coordinator-CcrcncvG.d.ts → multi-agent-coordinator-CieyUoEL.d.ts} +1 -1
  38. package/dist/{null-fleet-bus-C9KsYyrI.d.ts → null-fleet-bus-DkdmZJ_W.d.ts} +464 -464
  39. package/dist/observability/index.d.ts +3 -2
  40. package/dist/{path-resolver-CEeX9I7O.d.ts → path-resolver-XfZ9eLxG.d.ts} +3 -3
  41. package/dist/{permission-DbsGOA1C.d.ts → permission-Dx6dIqS2.d.ts} +2 -7
  42. package/dist/{permission-policy-BpEea3r7.d.ts → permission-policy-C8vJcnX5.d.ts} +2 -2
  43. package/dist/{pipeline-CEjBjzVA.d.ts → pipeline-BwAP21_4.d.ts} +9 -4
  44. package/dist/{provider-model-resolve-BpfXp3Jj.d.ts → provider-model-resolve-CwQNZWt_.d.ts} +3 -3
  45. package/dist/{provider-runner-CnOSr5BN.d.ts → provider-runner-CYHFImzV.d.ts} +3 -3
  46. package/dist/{retry-policy-Git9WF6d.d.ts → retry-policy-D4feSLk3.d.ts} +1 -1
  47. package/dist/sdd/index.d.ts +11 -10
  48. package/dist/sdd/index.js +2 -2
  49. package/dist/sdd/index.js.map +1 -1
  50. package/dist/secret-scrubber-3MHDDAtm.d.ts +6 -0
  51. package/dist/{secret-vault-DDSMHqIm.d.ts → secret-vault-CImt2XrR.d.ts} +1 -1
  52. package/dist/security/index.d.ts +6 -5
  53. package/dist/security/index.js.map +1 -1
  54. package/dist/{selector-Cq72C0Oy.d.ts → selector-Dy-MzKp1.d.ts} +1 -1
  55. package/dist/{session-event-bridge-DG94B3Bk.d.ts → session-event-bridge-CqdiGnfU.d.ts} +1 -1
  56. package/dist/{session-reader-BzT-iMQT.d.ts → session-reader-Hk0WbNm9.d.ts} +1 -1
  57. package/dist/{skill-DGIXCtdv.d.ts → skill-DHniprNl.d.ts} +15 -1
  58. package/dist/skills/index.d.ts +472 -26
  59. package/dist/skills/index.js +872 -129
  60. package/dist/skills/index.js.map +1 -1
  61. package/dist/storage/index.d.ts +27 -14
  62. package/dist/storage/index.js +264 -85
  63. package/dist/storage/index.js.map +1 -1
  64. package/dist/{strategy-compactor-Bt_ZH6R0.d.ts → strategy-compactor-CQwhbErd.d.ts} +32 -17
  65. package/dist/{todos-checkpoint-CH1pcua9.d.ts → todos-checkpoint-Bk2uP7Ex.d.ts} +6 -6
  66. package/dist/{context-DPlA6kid.d.ts → tool-BkOgs_KL.d.ts} +306 -286
  67. package/dist/{tool-executor-SVFq7IOR.d.ts → tool-executor-SiE1wlZo.d.ts} +9 -9
  68. package/dist/tools/index.d.ts +2 -2
  69. package/dist/tools/index.js.map +1 -1
  70. package/dist/types/index.d.ts +22 -21
  71. package/dist/types/index.js +7 -9
  72. package/dist/types/index.js.map +1 -1
  73. package/dist/utils/index.d.ts +30 -4
  74. package/dist/utils/index.js +50 -1
  75. package/dist/utils/index.js.map +1 -1
  76. package/dist/{worktree-manager-C4YIf1Fa.d.ts → worktree-manager-BjOFF6bt.d.ts} +1 -1
  77. package/dist/{wstack-paths-_NrRovdr.d.ts → wstack-paths-CMl_cYgq.d.ts} +8 -0
  78. package/package.json +1 -1
  79. package/skills/mailbox-bridge/SKILL.md +1 -0
  80. package/skills/plugin-author/SKILL.md +350 -0
  81. package/skills/sdd/SKILL.md +134 -134
  82. package/skills/skill-creator/SKILL.md +45 -7
  83. package/skills/wrongstack-mailbox/SKILL.md +40 -21
@@ -1,4 +1,4 @@
1
- import { M as Message } from './context-DPlA6kid.js';
1
+ import { M as Message } from './tool-BkOgs_KL.js';
2
2
 
3
3
  /**
4
4
  * Result of LLM-driven message importance analysis.
@@ -1,4 +1,4 @@
1
- import { S as SessionEvent, b as SessionWriter } from './context-DPlA6kid.js';
1
+ import { S as SessionEvent, b as SessionWriter } from './tool-BkOgs_KL.js';
2
2
 
3
3
  type AuditLevel = 'minimal' | 'standard' | 'full';
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { i as ContentBlock, S as SessionEvent, j as SessionMetadata, k as SessionStore } from './context-DPlA6kid.js';
1
+ import { i as ContentBlock, S as SessionEvent, j as SessionMetadata, k as SessionStore } from './tool-BkOgs_KL.js';
2
2
 
3
3
  type AttachmentKind = 'text' | 'image' | 'file';
4
4
  interface AttachmentMeta {
@@ -2,8 +2,20 @@ interface SkillManifest {
2
2
  name: string;
3
3
  description: string;
4
4
  version?: string | undefined;
5
+ /** agentskills.io optional frontmatter fields. */
6
+ license?: string | undefined;
7
+ compatibility?: string | undefined;
8
+ metadata?: Record<string, string> | undefined;
9
+ allowedTools?: string[] | undefined;
5
10
  path: string;
6
- source: 'project' | 'user' | 'bundled';
11
+ /**
12
+ * Discovery layer the skill came from. `claude-*`, `foreign`, and `extra` are
13
+ * read-only foreign sources (other coding agents' dirs, or
14
+ * `config.skills.extraDirs`); they are never written to by the skill installer.
15
+ */
16
+ source: 'project' | 'user' | 'bundled' | 'claude-project' | 'claude-user' | 'extra' | 'foreign';
17
+ /** For `foreign` sources: the originating tool id (codex, cursor, agents, …). */
18
+ originTool?: string | undefined;
7
19
  }
8
20
  /** Parsed skill entry for structured rendering in system prompt. */
9
21
  interface SkillEntry {
@@ -13,6 +25,8 @@ interface SkillEntry {
13
25
  /** Comma-separated scope items */
14
26
  scope: string[];
15
27
  source: SkillManifest['source'];
28
+ /** For `foreign` sources: the originating tool id. */
29
+ originTool?: string | undefined;
16
30
  path: string;
17
31
  }
18
32
  interface SkillLoader {
@@ -1,4 +1,226 @@
1
- import { S as SkillLoader } from '../skill-DGIXCtdv.js';
1
+ import { b as SkillEntry, S as SkillLoader } from '../skill-DHniprNl.js';
2
+
3
+ /**
4
+ * Well-known foreign coding-agent skill directories. All follow the
5
+ * agentskills.io `SKILL.md` format, so the same loader reads them — this just
6
+ * tells it WHERE each agent keeps them.
7
+ *
8
+ * Claude is handled separately by the loader (`claude-project` / `claude-user`
9
+ * sources); this list covers the OTHER agents. Every tool here stores skills
10
+ * under `~/.<tool>/skills` (+ `<project>/.<tool>/skills`).
11
+ *
12
+ * Dirs that don't exist are skipped gracefully, so listing many is cheap.
13
+ *
14
+ * NOTE: Cursor previously used a non-standard `skills-cursor` subdir. As of the
15
+ * 2026-07 alignment with the broader skills.sh / antfu-skills-cli / vercel-labs
16
+ * ecosystem, Cursor uses the standard `skills` subdir like everyone else.
17
+ * (`skills-cursor` was WrongStack-only and meant real Cursor skills were never
18
+ * discovered — see docs/skills.md.)
19
+ */
20
+ interface ForeignSkillTool {
21
+ /** Tool id — also the directory name segment (`~/.<id>/…`). */
22
+ id: string;
23
+ /** Skills subdirectory name under `~/.<id>/`. */
24
+ subdir: string;
25
+ }
26
+ declare const FOREIGN_SKILL_TOOLS: readonly ForeignSkillTool[];
27
+ /** Result of resolving a `foreignSources` config option. */
28
+ interface ResolvedForeignTools {
29
+ /** Tool ids that will be scanned (subset of {@link FOREIGN_SKILL_TOOLS}). */
30
+ ids: string[];
31
+ /** Tool ids the user asked for that aren't known — likely typos (e.g. `corser`). */
32
+ unknownIds: string[];
33
+ }
34
+ /**
35
+ * Resolve the `config.skills.foreignSources` option into the list of tool ids
36
+ * to scan. Kept for backward compatibility (returns only `ids`).
37
+ * - `false` → none
38
+ * - `string[]` → only those ids (unknown ids silently dropped — see
39
+ * {@link resolveForeignToolIdsWithWarnings} to surface them)
40
+ * - `true` / `undefined` → all well-known tools
41
+ */
42
+ declare function resolveForeignToolIds(opt: boolean | string[] | undefined): string[];
43
+ /**
44
+ * Like {@link resolveForeignToolIds}, but also returns tool ids the caller asked
45
+ * for that don't match any known agent. Callers that want to warn the user
46
+ * about a likely typo (e.g. `foreignSources: ["corser"]`) should prefer this.
47
+ *
48
+ * - `false` → none
49
+ * - `string[]` → known ids included, unknown ones returned in `unknownIds`
50
+ * - `true` / `undefined` → all well-known tools (no unknowns possible)
51
+ */
52
+ declare function resolveForeignToolIdsWithWarnings(opt: boolean | string[] | undefined): ResolvedForeignTools;
53
+ /**
54
+ * Security tier bucket for a registry skill's `securityScore` (0–100).
55
+ * Mirrors the ags (agentskill-sh/ags) thresholds: skills below 30 need
56
+ * explicit confirmation before install.
57
+ */
58
+ type SkillSecurityTier = 'low' | 'medium' | 'high';
59
+ /** Classify a 0–100 security score into a tier. 0/undefined → unknown → `low`. */
60
+ declare function securityScoreToTier(score: number | undefined | null): SkillSecurityTier;
61
+
62
+ /**
63
+ * Shared SKILL.md frontmatter parser + agentskills.io name validation.
64
+ *
65
+ * The SKILL.md format (https://agentskills.io/specification) is YAML
66
+ * frontmatter between `---` markers followed by a Markdown body. This parser is
67
+ * intentionally minimal — it handles the fields skills actually use, with YAML
68
+ * block scalars (`|` / `>`) for multi-line values and an indented map for
69
+ * `metadata`. It is NOT a general YAML parser; skill files are trusted markdown.
70
+ */
71
+ interface ParsedSkillFrontmatter {
72
+ name?: string | undefined;
73
+ description?: string | undefined;
74
+ /** WrongStack extension; informational only. */
75
+ version?: string | undefined;
76
+ license?: string | undefined;
77
+ compatibility?: string | undefined;
78
+ metadata?: Record<string, string> | undefined;
79
+ /** `allowed-tools` (spec, experimental) → split on whitespace. */
80
+ allowedTools?: string[] | undefined;
81
+ }
82
+ /**
83
+ * Parse the YAML frontmatter block from a raw SKILL.md file. Returns `{}` when
84
+ * there is no (or unclosed) frontmatter — callers treat that as "skip".
85
+ *
86
+ * Line endings are normalized first: CRLF (and lone CR) would otherwise leave a
87
+ * trailing `\r` on each line, and since `.` / `$` don't match `\r`, the
88
+ * `key: value` regex would fail on every line and silently drop the whole
89
+ * frontmatter. Real skill files are frequently CRLF (Windows / some editors).
90
+ */
91
+ declare function parseSkillFrontmatter(raw: string): ParsedSkillFrontmatter;
92
+ /** Strip leading YAML frontmatter (`---\n…\n---`) from a SKILL.md file. */
93
+ declare function stripFrontmatter(raw: string): string;
94
+ /** True when `name` matches the agentskills.io name format (chars + length only). */
95
+ declare function isValidSkillNameFormat(name: string): boolean;
96
+ /**
97
+ * Validate a skill `name` against the agentskills.io spec:
98
+ * 1-64 chars; lowercase letters, digits, and single hyphens only; no
99
+ * leading/trailing/consecutive hyphens. Pass the parent directory name to also
100
+ * enforce the "name must match the parent directory" rule.
101
+ *
102
+ * Returns a list of human-readable violations (empty = valid).
103
+ */
104
+ declare function validateSkillName(name: string, parentDirName?: string): string[];
105
+
106
+ interface ParsedRef {
107
+ owner: string;
108
+ repo: string;
109
+ ref: string;
110
+ }
111
+ /**
112
+ * Parse a skill reference string.
113
+ * Formats: `user/repo` (default ref: main), `user/repo@ref`
114
+ */
115
+ declare function parseSkillRef(input: string): ParsedRef;
116
+ interface DownloadResult {
117
+ /** Temp directory containing the extracted repo. Caller must clean up. */
118
+ tempDir: string;
119
+ }
120
+ /**
121
+ * Download and extract a GitHub repository tarball.
122
+ *
123
+ * Auth: reads `WRONGSTACK_GITHUB_TOKEN` / `GITHUB_TOKEN` / `GH_TOKEN` (in that
124
+ * order). Without a token only public repos work; with one, private repos the
125
+ * token can read also work, and the API rate limit is the authenticated
126
+ * (much higher) limit instead of the anonymous 60/hour.
127
+ *
128
+ * Returns the path to a temp directory with the extracted contents. The caller
129
+ * must remove it (the installer does this in a `finally`).
130
+ */
131
+ declare function downloadGitHubTarball(parsed: ParsedRef): Promise<DownloadResult>;
132
+
133
+ /**
134
+ * Centralized skill system limits.
135
+ *
136
+ * Before this file existed, the magic numbers below were scattered across five
137
+ * modules (`skill-installer`, `github-fetcher`, `skill` tool, system-prompt
138
+ * builder, skill-loader), sometimes duplicated (e.g. per-skill body cap was
139
+ * defined independently in the builder and the tool). Centralizing them here
140
+ * keeps the budget model coherent — change one, change everywhere — and makes
141
+ * the trade-offs visible in one place.
142
+ *
143
+ * Values are frozen at their pre-centralization defaults so this is a pure
144
+ * refactor (no behavior change).
145
+ */
146
+ declare const SKILL_LIMITS: {
147
+ /**
148
+ * Per-skill body cap when injecting a full skill body into the system prompt
149
+ * (eager mode), and when returning a skill body from the `skill` tool.
150
+ * ~4k tokens. Oversized bodies are truncated at a paragraph boundary.
151
+ *
152
+ * Consumers: `system-prompt-builder.capSkillBody`, `skill` tool body return.
153
+ */
154
+ readonly MAX_SKILL_BODY_CHARS: 16000;
155
+ /**
156
+ * Per-resource cap when the `skill` tool loads a bundled file
157
+ * (`scripts/`, `references/`, `assets/`). ~8k tokens.
158
+ *
159
+ * Consumer: `skill` tool `loadResource`.
160
+ */
161
+ readonly MAX_RESOURCE_CHARS: 32000;
162
+ /**
163
+ * Maximum number of bundled resource paths the `skill` tool lists in one
164
+ * response. Caps a pathological skill (huge `assets/` tree) from blowing up
165
+ * the tool result.
166
+ *
167
+ * Consumer: `skill` tool resource listing.
168
+ */
169
+ readonly MAX_LISTED_RESOURCES: 100;
170
+ /**
171
+ * Max size of a single installed skill file (SKILL.md or a bundled resource).
172
+ * Guards against a malicious registry skill shipping a multi-MB blob that
173
+ * then flows into the prompt. 100KB.
174
+ *
175
+ * Consumer: `SkillInstaller.install` / `importFromDir`.
176
+ */
177
+ readonly MAX_SKILL_FILE_SIZE: number;
178
+ /**
179
+ * Max size of a GitHub tarball downloaded by the skill installer. Guards
180
+ * against a repo accidentally (or maliciously) shipping a giant tarball that
181
+ * would be extracted into a temp dir. 50MB.
182
+ *
183
+ * Consumer: `downloadGitHubTarball`.
184
+ */
185
+ readonly MAX_TARBALL_SIZE: number;
186
+ /**
187
+ * Default total char budget for skill bodies injected in eager mode when
188
+ * `config.skills.eagerMaxChars` is unset. ~6k tokens. Skills are injected
189
+ * highest-priority first; once the budget is exhausted the remaining skills
190
+ * are listed as a manifest the agent loads via the `skill` tool. Set very
191
+ * high to effectively disable budgeting.
192
+ *
193
+ * Consumer: `DefaultSystemPromptBuilder.buildMemoryAndSkills` (default for
194
+ * `skillEagerMaxChars`).
195
+ */
196
+ readonly EAGER_DEFAULT_MAX_CHARS: 24000;
197
+ /**
198
+ * Auto-compact body limits (the token-saving fallback used when a skill has
199
+ * no hand-crafted `SKILL.save.md`). The Overview and Rules sections are
200
+ * extracted and trimmed to these char budgets, then the total is capped.
201
+ *
202
+ * Consumer: `DefaultSkillLoader.compactSkillBody`.
203
+ */
204
+ readonly COMPACT_OVERVIEW_MAX: 200;
205
+ readonly COMPACT_RULES_MAX: 350;
206
+ readonly COMPACT_TOTAL_MAX: 450;
207
+ /**
208
+ * Max length of a skill name (agentskills.io spec). Enforced by the
209
+ * frontmatter validator's format regex plus this length bound.
210
+ *
211
+ * Consumer: `isValidSkillNameFormat`.
212
+ */
213
+ readonly SKILL_NAME_MAX_LEN: 64;
214
+ /**
215
+ * Soft line limit for a SKILL.md body, per the bundled `skill-creator` rule.
216
+ * Not enforced in code (a skill can exceed it) — surfaced by `/skill-gen
217
+ * validate` and the `skill-creator` skill as guidance to move deep material
218
+ * into `references/`.
219
+ *
220
+ * Consumer: `skill-creator` skill, `/skill-gen validate` advisory.
221
+ */
222
+ readonly SKILL_BODY_LINE_LIMIT: 500;
223
+ };
2
224
 
3
225
  interface InstalledSkillEntry {
4
226
  name: string;
@@ -14,6 +236,15 @@ interface InstalledSkillEntry {
14
236
  installedAt: string;
15
237
  /** List of files that were installed (relative to skill dir) */
16
238
  files: string[];
239
+ /**
240
+ * When the install was resolved through a registry (e.g. `skills.sh`), the
241
+ * adapter id + registry id that mapped to the GitHub `source`. Absent for
242
+ * direct `user/repo` installs.
243
+ */
244
+ registryFrom?: {
245
+ adapterId: string;
246
+ registryId: string;
247
+ } | undefined;
17
248
  }
18
249
  interface ManifestData {
19
250
  skills: InstalledSkillEntry[];
@@ -33,6 +264,200 @@ declare class SkillManifestStore {
33
264
  invalidateCache(): void;
34
265
  }
35
266
 
267
+ /**
268
+ * Skill registry adapter contract.
269
+ *
270
+ * A registry is a searchable catalog of skills that resolves to a concrete
271
+ * install target (a GitHub `user/repo[@ref]`). Two adapters ship out of the
272
+ * box:
273
+ *
274
+ * - `githubDirectAdapter` — no search; `user/repo` is typed directly. This
275
+ * is the original pre-registry install path.
276
+ * - `skillsShAdapter` — searches the skills.sh marketplace
277
+ * (https://skills.sh/api/skills), which indexes
278
+ * 34k+ skills from 2.8k+ repos and computes a
279
+ * per-skill security score (0–100).
280
+ *
281
+ * The adapter layer keeps the installer registry-agnostic: it asks each
282
+ * adapter to resolve a `<adapterId>:<registryId>` ref to a `user/repo@ref`
283
+ * and reuses the existing GitHub tarball path. New registries (an internal
284
+ * company hub, ags, …) are added by implementing this interface and passing
285
+ * them to the `SkillInstaller`.
286
+ */
287
+ /**
288
+ * One hit from a registry search. Fields are optional where the underlying
289
+ * registry doesn't guarantee them — every adapter normalizes to this shape.
290
+ */
291
+ interface RegistrySkillSummary {
292
+ /** Registry-native id (used as `<adapterId>:<id>` in `/skill-install`). */
293
+ id: string;
294
+ /** Skill name (kebab-case, as it will appear once installed). */
295
+ name: string;
296
+ /** Short description / trigger line. */
297
+ description: string;
298
+ /** Author / owner (often the GitHub owner). */
299
+ author?: string | undefined;
300
+ /** Install count, if the registry reports it. */
301
+ installs?: number | undefined;
302
+ /** Star count, if the registry reports it. */
303
+ stars?: number | undefined;
304
+ /**
305
+ * Security score 0–100 (skills.sh computes this; ags uses the same scale).
306
+ * Lower = riskier. Below 30 the install command prompts for confirmation.
307
+ */
308
+ securityScore?: number | undefined;
309
+ /** ISO timestamp of the skill's last update, if known. */
310
+ updatedAt?: string | undefined;
311
+ /**
312
+ * The `user/repo[@ref]` the installer passes to `downloadGitHubTarball`.
313
+ * Always present for real registry hits — it's the whole point of resolving.
314
+ */
315
+ installRef: string;
316
+ }
317
+ interface RegistrySearchOptions {
318
+ /** 1-indexed page (default 1). */
319
+ page?: number | undefined;
320
+ /** Page size (default 20; registries may cap this). */
321
+ pageSize?: number | undefined;
322
+ }
323
+ interface RegistrySearchResult {
324
+ /** Which adapter produced these results. */
325
+ adapterId: string;
326
+ results: RegistrySkillSummary[];
327
+ /** True when the registry indicates more pages exist. */
328
+ hasMore?: boolean | undefined;
329
+ }
330
+ /**
331
+ * A searchable skill catalog that resolves to a GitHub install target.
332
+ *
333
+ * `search` is optional in spirit (the github-direct adapter doesn't search),
334
+ * but the interface requires it so callers can fan out uniformly — adapters
335
+ * that can't search simply return `[]`.
336
+ */
337
+ interface SkillRegistryAdapter {
338
+ /** Stable id used in `<adapterId>:<registryId>` refs (e.g. `'skills.sh'`). */
339
+ readonly id: string;
340
+ /** Human label for UI (e.g. `'skills.sh'`). */
341
+ readonly displayName: string;
342
+ /** Search the catalog. Return `[]` if the adapter doesn't support search. */
343
+ search(query: string, opts?: RegistrySearchOptions): Promise<RegistrySearchResult>;
344
+ /**
345
+ * Resolve a registry-native id to a `user/repo[@ref]` install ref. Should
346
+ * validate the id shape and throw on an id this adapter can't resolve.
347
+ */
348
+ resolveInstallRef(registryId: string): string;
349
+ }
350
+
351
+ /**
352
+ * GitHub-direct registry adapter.
353
+ *
354
+ * This is the original pre-registry install path wrapped in the adapter
355
+ * interface: the user types `user/repo[@ref]` directly. It does NOT search
356
+ * (GitHub code search is a separate API with its own auth/rate-limit story and
357
+ * isn't a skill catalog), so `search()` returns an empty result. Its job is
358
+ * solely to make `user/repo` flow through the same `<adapterId>:<registryId>`
359
+ * resolution as the skills.sh adapter — except here the "registry id" IS the
360
+ * install ref already.
361
+ *
362
+ * Registered as the fallback adapter so `/skill-install user/repo` keeps
363
+ * working unchanged when no `<adapterId>:` prefix is given.
364
+ */
365
+
366
+ declare const githubDirectAdapter: SkillRegistryAdapter;
367
+
368
+ /** Default skills.sh base URL. Override via `config.skills.registryUrl`. */
369
+ declare const DEFAULT_SKILLS_SH_URL = "https://skills.sh";
370
+ /** Injectable fetcher (mirrors the `prompt-installer` JsonFetcher pattern). */
371
+ type SkillsShFetcher = (url: string) => Promise<unknown>;
372
+ interface SkillsShAdapterOptions {
373
+ /** Base URL (no trailing slash). Defaults to {@link DEFAULT_SKILLS_SH_URL}. */
374
+ baseUrl?: string | undefined;
375
+ /** Injectable fetcher for tests. */
376
+ fetcher?: SkillsShFetcher | undefined;
377
+ }
378
+ declare function createSkillsShAdapter(opts?: SkillsShAdapterOptions): SkillRegistryAdapter;
379
+
380
+ /** Result of validating a proposed skill name. */
381
+ interface SkillNameValidation {
382
+ /** Whether the name is valid kebab-case AND free of collisions. */
383
+ ok: boolean;
384
+ /** Format violations (empty when the name is valid kebab-case). */
385
+ formatViolations: string[];
386
+ /** Existing skills with the same name (empty when there's no collision). */
387
+ conflicts: SkillEntry[];
388
+ }
389
+ /**
390
+ * Validate a proposed skill name: format (kebab-case, ≤64 chars) plus collision
391
+ * check against every skill the loader can see (project, user, foreign,
392
+ * bundled). A collision isn't fatal — project skills intentionally shadow
393
+ * lower layers — so `ok` is true when the only collision is with a foreign or
394
+ * bundled skill (intended shadowing), but `conflicts` is still populated so the
395
+ * user can decide. A collision with another project or user skill of the same
396
+ * name does fail (`ok: false`), since that would silently overwrite it.
397
+ */
398
+ declare function validateSkillNameAvailable(name: string, loader?: SkillLoader): Promise<SkillNameValidation>;
399
+ interface SkillSkeletonOptions {
400
+ name: string;
401
+ description: string;
402
+ /** Trigger keywords for the `Triggers:` line. */
403
+ triggerKeywords?: string[] | undefined;
404
+ /** Optional version (default `1.0.0`). */
405
+ version?: string | undefined;
406
+ }
407
+ /**
408
+ * Generate a SKILL.md body (with frontmatter) following the agentskills.io
409
+ * format and the `skill-creator` skill's recommended skeleton. Deterministic:
410
+ * the same inputs always produce the same output, and the result round-trips
411
+ * through `parseSkillFrontmatter` (so what we write is what the loader reads).
412
+ *
413
+ * The body is a skeleton — the user fills in Rules/Patterns/etc. The
414
+ * `skill-creator` skill is the right tool for the open-ended authoring; this
415
+ * is the scaffold.
416
+ */
417
+ declare function generateSkillSkeleton(opts: SkillSkeletonOptions): string;
418
+ /** Result of extracting a skill draft from a free-form prompt. */
419
+ interface ExtractedSkillDraft {
420
+ /** Suggested name (kebab-case) derived from the prompt, or empty. */
421
+ suggestedName: string;
422
+ /** Description (first paragraph of the prompt). */
423
+ description: string;
424
+ /** Remaining prompt text, used as the skill body. */
425
+ body: string;
426
+ /** Trigger keywords extracted from the prompt. */
427
+ triggerKeywords: string[];
428
+ }
429
+ /**
430
+ * Heuristically extract a skill draft from a free-form prompt. No LLM — just
431
+ * light structure detection:
432
+ * - First non-empty paragraph → `description`.
433
+ * - A `# heading` or the first line → suggested kebab-case `suggestedName`.
434
+ * - Remaining text → `body`.
435
+ * - Quoted tokens and the heading words → `triggerKeywords`.
436
+ *
437
+ * The output is a starting point the user (or the skill-creator wizard) refines.
438
+ */
439
+ declare function extractSkillFromPrompt(prompt: string): ExtractedSkillDraft;
440
+ /**
441
+ * Open a file in the user's editor (`$VISUAL` → `$EDITOR` → platform default).
442
+ * Detached + unref'd so the editor outlives the WrongStack process. Throws a
443
+ * `WrongStackError` when no editor can be resolved.
444
+ */
445
+ declare function openInEditor(filePath: string, env?: NodeJS.ProcessEnv): Promise<void>;
446
+ /**
447
+ * Write a skeleton skill to `<skillsDir>/<name>/SKILL.md`. Returns the written
448
+ * path. Used by `/skill-gen skeleton` and `/skill-gen from-prompt`. Refuses to
449
+ * overwrite an existing SKILL.md unless `overwrite` is set — a guard against
450
+ * clobbering a hand-edited skill.
451
+ */
452
+ declare function writeSkeletonSkill(skillsDir: string, body: string, opts?: {
453
+ overwrite?: boolean | undefined;
454
+ }): Promise<string>;
455
+ /** Soft length advisory for a SKILL.md body (the `skill-creator` 500-line rule). */
456
+ declare function bodyLineAdvisory(body: string): {
457
+ lines: number;
458
+ over: boolean;
459
+ };
460
+
36
461
  interface SkillInstallerOptions {
37
462
  /** Path to the manifest file (~/.wrongstack/installed-skills.json) */
38
463
  manifestPath: string;
@@ -45,7 +470,14 @@ interface SkillInstallerOptions {
45
470
  /** Skill loader — cache will be invalidated after mutations */
46
471
  skillLoader?: SkillLoader | undefined;
47
472
  /** Logger for status messages */
48
- log?: (((msg: string) => void)) | undefined;
473
+ log?: ((msg: string) => void) | undefined;
474
+ /**
475
+ * Skill registries used to resolve `<adapterId>:<registryId>` refs and to
476
+ * serve `/skill-search`. Defaults to `[githubDirectAdapter]` (the original
477
+ * direct `user/repo` install path). Add a skills.sh adapter to enable
478
+ * searching the marketplace and installing registry hits by id.
479
+ */
480
+ registryAdapters?: SkillRegistryAdapter[] | undefined;
49
481
  }
50
482
  interface InstallResult {
51
483
  name: string;
@@ -70,14 +502,36 @@ interface UpdateResult {
70
502
  declare class SkillInstaller {
71
503
  private readonly opts;
72
504
  private readonly manifest;
505
+ private readonly adapters;
73
506
  constructor(opts: SkillInstallerOptions);
74
507
  /**
75
- * Install skills from a GitHub repository.
76
- * Supports both single-skill repos (SKILL.md at root) and multi-skill repos (skills/ subdirectory).
508
+ * Install skills from a skill reference.
509
+ *
510
+ * Accepts two ref formats:
511
+ * - `user/repo[@ref]` — direct GitHub install (original path)
512
+ * - `<adapterId>:<registryId>` — registry-resolved (e.g.
513
+ * `skills.sh:owner/repo@v1`); the
514
+ * adapter resolves it to a `user/repo`
515
+ * ref and the install proceeds as above.
516
+ *
517
+ * Supports both single-skill repos (SKILL.md at root) and multi-skill repos
518
+ * (skills/ subdirectory). The manifest records the GitHub source as
519
+ * `github:owner/repo` (so `/skill-update` keeps working) plus the originating
520
+ * registry in `registryFrom` when the install came through a registry.
77
521
  */
78
522
  install(refInput: string, opts?: {
79
523
  global?: boolean | undefined;
80
524
  }): Promise<InstallResult[]>;
525
+ /**
526
+ * Import skills from a local directory (e.g. `.claude/skills`) into the
527
+ * project or user skills dir, optionally as symlinks. Used by `/skill-import`
528
+ * to take ownership of foreign skills so they can be edited/committed.
529
+ * Each direct subdirectory containing a valid `SKILL.md` is copied verbatim.
530
+ */
531
+ importFromDir(srcDir: string, opts?: {
532
+ global?: boolean | undefined;
533
+ link?: boolean | undefined;
534
+ }): Promise<InstallResult[]>;
81
535
  /**
82
536
  * Update installed skills.
83
537
  * - No args: update all
@@ -97,6 +551,13 @@ declare class SkillInstaller {
97
551
  * List all installed skills from the manifest.
98
552
  */
99
553
  listInstalled(): Promise<InstalledSkillEntry[]>;
554
+ /**
555
+ * Search across all configured registry adapters. Results from each adapter
556
+ * are merged (deduplicated by `installRef`, adapters earlier in the list win
557
+ * conflicts). Adapters that don't support search (e.g. github-direct)
558
+ * contribute nothing.
559
+ */
560
+ search(query: string, opts?: RegistrySearchOptions): Promise<RegistrySearchResult[]>;
100
561
  /**
101
562
  * Detect skills in an extracted repository.
102
563
  * Returns an array of detected skills with their files.
@@ -110,27 +571,12 @@ declare class SkillInstaller {
110
571
  * Invalidate the skill loader's cache so newly installed skills appear.
111
572
  */
112
573
  private invalidateLoaderCache;
574
+ /**
575
+ * Resolve an install ref, dispatching registry-prefixed refs to the matching
576
+ * adapter. Returns the concrete `user/repo[@ref]` install ref plus provenance
577
+ * (which adapter resolved it, if any).
578
+ */
579
+ private resolveRef;
113
580
  }
114
581
 
115
- interface ParsedRef {
116
- owner: string;
117
- repo: string;
118
- ref: string;
119
- }
120
- /**
121
- * Parse a skill reference string.
122
- * Formats: `user/repo` (default ref: main), `user/repo@ref`
123
- */
124
- declare function parseSkillRef(input: string): ParsedRef;
125
- interface DownloadResult {
126
- /** Temp directory containing the extracted repo. Caller must clean up. */
127
- tempDir: string;
128
- }
129
- /**
130
- * Download and extract a GitHub repository tarball.
131
- * Uses the public GitHub API — no auth token required for public repos.
132
- * Returns the path to a temp directory with the extracted contents.
133
- */
134
- declare function downloadGitHubTarball(parsed: ParsedRef): Promise<DownloadResult>;
135
-
136
- export { type DownloadResult, type InstallResult, type InstalledSkillEntry, type ManifestData, type ParsedRef, SkillInstaller, type SkillInstallerOptions, SkillManifestStore, type UpdateResult, downloadGitHubTarball, parseSkillRef };
582
+ export { DEFAULT_SKILLS_SH_URL, type DownloadResult, type ExtractedSkillDraft, FOREIGN_SKILL_TOOLS, type ForeignSkillTool, type InstallResult, type InstalledSkillEntry, type ManifestData, type ParsedRef, type ParsedSkillFrontmatter, type RegistrySearchOptions, type RegistrySearchResult, type RegistrySkillSummary, type ResolvedForeignTools, SKILL_LIMITS, SkillInstaller, type SkillInstallerOptions, SkillManifestStore, type SkillNameValidation, type SkillRegistryAdapter, type SkillSecurityTier, type SkillSkeletonOptions, type UpdateResult, bodyLineAdvisory, createSkillsShAdapter, downloadGitHubTarball, extractSkillFromPrompt, generateSkillSkeleton, githubDirectAdapter, isValidSkillNameFormat, openInEditor, parseSkillFrontmatter, parseSkillRef, resolveForeignToolIds, resolveForeignToolIdsWithWarnings, securityScoreToTier, stripFrontmatter, validateSkillName, validateSkillNameAvailable, writeSkeletonSkill };