skilld 1.5.5 → 1.7.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 (120) hide show
  1. package/README.md +32 -23
  2. package/dist/_chunks/agent.mjs +2 -78
  3. package/dist/_chunks/agent.mjs.map +1 -1
  4. package/dist/_chunks/assemble.mjs +1 -18
  5. package/dist/_chunks/assemble.mjs.map +1 -1
  6. package/dist/_chunks/author-group.mjs +17 -0
  7. package/dist/_chunks/author-group.mjs.map +1 -0
  8. package/dist/_chunks/author.mjs +8 -24
  9. package/dist/_chunks/author.mjs.map +1 -1
  10. package/dist/_chunks/cache.mjs +1 -73
  11. package/dist/_chunks/cache.mjs.map +1 -1
  12. package/dist/_chunks/cache2.mjs +84 -17
  13. package/dist/_chunks/cache2.mjs.map +1 -1
  14. package/dist/_chunks/cli-helpers.mjs +3 -166
  15. package/dist/_chunks/cli-helpers.mjs.map +1 -1
  16. package/dist/_chunks/cli-helpers2.mjs +0 -11
  17. package/dist/_chunks/config.mjs +119 -54
  18. package/dist/_chunks/config.mjs.map +1 -1
  19. package/dist/_chunks/core.mjs +9 -0
  20. package/dist/_chunks/detect.mjs +29 -226
  21. package/dist/_chunks/detect.mjs.map +1 -1
  22. package/dist/_chunks/embedding-cache.mjs +0 -5
  23. package/dist/_chunks/embedding-cache2.mjs +2 -3
  24. package/dist/_chunks/formatting.mjs +0 -6
  25. package/dist/_chunks/formatting.mjs.map +1 -1
  26. package/dist/_chunks/index.d.mts +0 -10
  27. package/dist/_chunks/index.d.mts.map +1 -1
  28. package/dist/_chunks/index2.d.mts +3 -6
  29. package/dist/_chunks/index2.d.mts.map +1 -1
  30. package/dist/_chunks/index3.d.mts +81 -109
  31. package/dist/_chunks/index3.d.mts.map +1 -1
  32. package/dist/_chunks/install.mjs +85 -550
  33. package/dist/_chunks/install.mjs.map +1 -1
  34. package/dist/_chunks/install2.mjs +554 -0
  35. package/dist/_chunks/install2.mjs.map +1 -0
  36. package/dist/_chunks/libs/@sinclair/typebox.mjs +0 -444
  37. package/dist/_chunks/libs/@sinclair/typebox.mjs.map +1 -1
  38. package/dist/_chunks/list.mjs +0 -16
  39. package/dist/_chunks/list.mjs.map +1 -1
  40. package/dist/_chunks/lockfile.mjs +2 -10
  41. package/dist/_chunks/lockfile.mjs.map +1 -1
  42. package/dist/_chunks/markdown.mjs +0 -9
  43. package/dist/_chunks/markdown.mjs.map +1 -1
  44. package/dist/_chunks/package-json.mjs +0 -25
  45. package/dist/_chunks/package-json.mjs.map +1 -1
  46. package/dist/_chunks/package-registry.mjs +465 -0
  47. package/dist/_chunks/package-registry.mjs.map +1 -0
  48. package/dist/_chunks/pool2.mjs +0 -2
  49. package/dist/_chunks/pool2.mjs.map +1 -1
  50. package/dist/_chunks/prefix.mjs +108 -0
  51. package/dist/_chunks/prefix.mjs.map +1 -0
  52. package/dist/_chunks/prepare.mjs +14 -9
  53. package/dist/_chunks/prepare.mjs.map +1 -1
  54. package/dist/_chunks/prepare2.mjs +1 -19
  55. package/dist/_chunks/prepare2.mjs.map +1 -1
  56. package/dist/_chunks/prompts.mjs +6 -201
  57. package/dist/_chunks/prompts.mjs.map +1 -1
  58. package/dist/_chunks/retriv.mjs +23 -24
  59. package/dist/_chunks/retriv.mjs.map +1 -1
  60. package/dist/_chunks/rolldown-runtime.mjs +0 -2
  61. package/dist/_chunks/sanitize.mjs +0 -78
  62. package/dist/_chunks/sanitize.mjs.map +1 -1
  63. package/dist/_chunks/search-helpers.mjs +99 -0
  64. package/dist/_chunks/search-helpers.mjs.map +1 -0
  65. package/dist/_chunks/search-interactive.mjs +1 -18
  66. package/dist/_chunks/search-interactive.mjs.map +1 -1
  67. package/dist/_chunks/search.mjs +218 -19
  68. package/dist/_chunks/search.mjs.map +1 -0
  69. package/dist/_chunks/setup.mjs +0 -13
  70. package/dist/_chunks/setup.mjs.map +1 -1
  71. package/dist/_chunks/shared.mjs +1 -473
  72. package/dist/_chunks/shared.mjs.map +1 -1
  73. package/dist/_chunks/skills.mjs +3 -3
  74. package/dist/_chunks/skills.mjs.map +1 -1
  75. package/dist/_chunks/sources.mjs +1179 -1440
  76. package/dist/_chunks/sources.mjs.map +1 -1
  77. package/dist/_chunks/sync-registry.mjs +59 -0
  78. package/dist/_chunks/sync-registry.mjs.map +1 -0
  79. package/dist/_chunks/sync-shared.mjs +0 -16
  80. package/dist/_chunks/sync-shared2.mjs +10 -49
  81. package/dist/_chunks/sync-shared2.mjs.map +1 -1
  82. package/dist/_chunks/sync.mjs +209 -120
  83. package/dist/_chunks/sync.mjs.map +1 -1
  84. package/dist/_chunks/sync2.mjs +1 -21
  85. package/dist/_chunks/types.d.mts +0 -2
  86. package/dist/_chunks/types.d.mts.map +1 -1
  87. package/dist/_chunks/uninstall.mjs +3 -27
  88. package/dist/_chunks/uninstall.mjs.map +1 -1
  89. package/dist/_chunks/upload.mjs +152 -0
  90. package/dist/_chunks/upload.mjs.map +1 -0
  91. package/dist/_chunks/validate.mjs +1 -8
  92. package/dist/_chunks/validate.mjs.map +1 -1
  93. package/dist/_chunks/version.mjs +30 -0
  94. package/dist/_chunks/version.mjs.map +1 -0
  95. package/dist/_chunks/wizard.mjs +2 -3
  96. package/dist/_chunks/yaml.mjs +0 -21
  97. package/dist/_chunks/yaml.mjs.map +1 -1
  98. package/dist/agent/index.d.mts +0 -24
  99. package/dist/agent/index.d.mts.map +1 -1
  100. package/dist/agent/index.mjs +2 -9
  101. package/dist/cache/index.mjs +1 -3
  102. package/dist/cli-entry.mjs +0 -6
  103. package/dist/cli-entry.mjs.map +1 -1
  104. package/dist/cli.mjs +48 -33
  105. package/dist/cli.mjs.map +1 -1
  106. package/dist/index.d.mts +1 -1
  107. package/dist/index.mjs +2 -8
  108. package/dist/prepare.mjs +0 -12
  109. package/dist/prepare.mjs.map +1 -1
  110. package/dist/retriv/index.mjs +0 -2
  111. package/dist/retriv/worker.d.mts +0 -3
  112. package/dist/retriv/worker.d.mts.map +1 -1
  113. package/dist/retriv/worker.mjs +0 -2
  114. package/dist/retriv/worker.mjs.map +1 -1
  115. package/dist/sources/index.d.mts +2 -2
  116. package/dist/sources/index.mjs +3 -7
  117. package/dist/types.d.mts +1 -1
  118. package/package.json +20 -21
  119. package/dist/_chunks/search2.mjs +0 -319
  120. package/dist/_chunks/search2.mjs.map +0 -1
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
- <h1>skilld</h1>
1
+ <h1><a href="https://skilld.dev"><img src=".github/logos/logo-mark.svg" alt="" width="28" height="28" valign="middle"></a> skilld</h1>
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/skilld?color=yellow)](https://npmjs.com/package/skilld)
4
4
  [![npm downloads](https://img.shields.io/npm/dm/skilld?color=yellow)](https://npm.chart.dev/skilld)
5
- [![license](https://img.shields.io/npm/l/skilld?color=yellow)](https://github.com/harlan-zw/skilld/blob/main/LICENSE)
5
+ [![license](https://img.shields.io/npm/l/skilld?color=yellow)](https://github.com/skilld-dev/skilld/blob/main/LICENSE)
6
6
 
7
7
  > Generate AI agent skills from your NPM dependencies.
8
8
 
@@ -51,7 +51,7 @@ __Requires Node 22.6.0 or higher.__
51
51
  Or add a specific package directly:
52
52
 
53
53
  ```bash
54
- npx -y skilld add vue
54
+ npx -y skilld add npm:vue
55
55
  ```
56
56
 
57
57
  If you need to re-configure skilld, just run `npx -y skilld config` to update your agent, model, or preferences.
@@ -59,10 +59,10 @@ If you need to re-configure skilld, just run `npx -y skilld config` to update yo
59
59
  **No agent CLI?** No problem - choose "No agent" when prompted. You get a base skill immediately, plus portable prompts you can run in any LLM:
60
60
 
61
61
  ```bash
62
- npx -y skilld add vue
62
+ npx -y skilld add npm:vue
63
63
  # Choose "No agent" -> base skill + prompts exported
64
64
  # Paste prompts into ChatGPT/Claude web, save outputs, then:
65
- npx -y skilld assemble
65
+ npx -y skilld author assemble
66
66
  ```
67
67
 
68
68
  ### Tips
@@ -143,8 +143,14 @@ Yes. Add `skilld prepare` to your prepare script. It restores references, auto-i
143
143
  # Interactive mode - auto-discover from package.json
144
144
  skilld
145
145
 
146
- # Add skills for specific package(s)
147
- skilld add vue nuxt pinia
146
+ # Add skills for specific package(s) — npm: prefix for registry packages
147
+ skilld add npm:vue npm:nuxt npm:pinia
148
+
149
+ # Add a pre-authored skill from a GitHub repo
150
+ skilld add gh:vercel-labs/agent-skills
151
+
152
+ # Add a skill for a Rust crate (crates.io)
153
+ skilld add crate:serde
148
154
 
149
155
  # Update outdated skills
150
156
  skilld update
@@ -156,13 +162,13 @@ skilld search "error" -p nuxt --filter '{"type":"issue"}'
156
162
  skilld search --guide -p nuxt
157
163
 
158
164
  # Target a specific agent
159
- skilld add react --agent cursor
165
+ skilld add npm:react --agent cursor
160
166
 
161
167
  # Install globally to ~/.claude/skills
162
- skilld add zod --global
168
+ skilld add npm:zod --global
163
169
 
164
170
  # Skip prompts
165
- skilld add drizzle-orm --yes
171
+ skilld add npm:drizzle-orm --yes
166
172
 
167
173
  # Check skill info
168
174
  skilld info
@@ -180,8 +186,8 @@ skilld config
180
186
  | Command | Description |
181
187
  |---------|-------------|
182
188
  | `skilld` | Interactive wizard (first run) or status menu (existing skills) |
183
- | `skilld add <pkg...>` | Add skills for package(s), space or comma-separated |
184
- | `skilld update [pkg]` | Update outdated skills (all or specific) |
189
+ | `skilld add <source...>` | Add skills. Sources: `npm:<pkg>`, `crate:<name>`, `gh:<owner/repo>`, or bare names (deprecated) |
190
+ | `skilld update [pkg]` | Update outdated skills (all or specific) |
185
191
  | `skilld search [query]` | Search indexed docs (`-p` package, `--filter` JSON, `--limit`, `--guide`) |
186
192
  | `skilld list` | List installed skills (`--json` for machine-readable output) |
187
193
  | `skilld info` | Show skill info and config |
@@ -190,15 +196,18 @@ skilld config
190
196
  | `skilld remove` | Remove installed skills |
191
197
  | `skilld uninstall` | Remove all skilld data |
192
198
  | `skilld cache` | Cache management (clean expired LLM cache entries) |
193
- | `skilld eject <pkg>` | Eject skill as portable directory (no symlinks) |
194
- | `skilld assemble [dir]` | Merge LLM output files back into SKILL.md (auto-discovers) |
199
+ | `skilld author package <pkg>` | Generate a portable package skill from docs |
200
+ | `skilld author publish` | Publish skills to skilld.dev |
201
+ | `skilld author eject <pkg>` | Eject skill as portable directory (no symlinks) |
202
+ | `skilld author validate <file>`| Validate a skill section |
203
+ | `skilld author assemble [dir]` | Merge LLM output files back into SKILL.md (auto-discovers) |
195
204
 
196
205
  ### Works Without an Agent CLI
197
206
 
198
207
  No Claude, Gemini, or Codex CLI? Choose "No agent" when prompted. You get a base skill immediately, plus portable prompts you can run in any LLM to enhance it:
199
208
 
200
209
  ```bash
201
- skilld add vue
210
+ skilld add npm:vue
202
211
  # Choose "No agent" -> installs to .claude/skills/vue-skilld/
203
212
 
204
213
  # What you get:
@@ -208,23 +217,23 @@ skilld add vue
208
217
 
209
218
  # Run each PROMPT_*.md in ChatGPT/Claude web/any LLM
210
219
  # Save outputs as _BEST_PRACTICES.md, _API_CHANGES.md, then:
211
- skilld assemble
220
+ skilld author assemble
212
221
  ```
213
222
 
214
- `skilld assemble` auto-discovers skills with pending output files. `skilld update` re-exports prompts for outdated packages.
223
+ `skilld author assemble` auto-discovers skills with pending output files. `skilld update` re-exports prompts for outdated packages.
215
224
 
216
225
  ### Eject
217
226
 
218
227
  Export a skill as a portable, self-contained directory for sharing via git repos:
219
228
 
220
229
  ```bash
221
- skilld eject vue # Default skill directory
222
- skilld eject vue --name vue # Custom directory name
223
- skilld eject vue --out ./skills/ # Custom path
224
- skilld eject vue --from 2025-07-01 # Only recent releases/issues
230
+ skilld author eject vue # Default skill directory
231
+ skilld author eject vue --name vue # Custom directory name
232
+ skilld author eject vue --out ./skills/ # Custom path
233
+ skilld author eject vue --from 2025-07-01 # Only recent releases/issues
225
234
  ```
226
235
 
227
- Share via `skilld add owner/repo` - consumers get fully functional skills with no LLM cost.
236
+ Share via `skilld add gh:owner/repo` - consumers get fully functional skills with no LLM cost.
228
237
 
229
238
  ### CLI Options
230
239
 
@@ -330,4 +339,4 @@ DO_NOT_TRACK=1
330
339
 
331
340
  ## License
332
341
 
333
- Licensed under the [MIT license](https://github.com/harlan-zw/skilld/blob/main/LICENSE).
342
+ Licensed under the [MIT license](https://github.com/skilld-dev/skilld/blob/main/LICENSE).
@@ -3,7 +3,8 @@ import { n as sanitizeMarkdown } from "./sanitize.mjs";
3
3
  import { h as writeSections, m as readCachedSection } from "./cache.mjs";
4
4
  import { i as resolveSkilldCommand } from "./shared.mjs";
5
5
  import { a as targets, t as detectInstalledAgents } from "./detect.mjs";
6
- import { c as SECTION_OUTPUT_FILES, f as getSectionValidator, l as buildAllSectionPrompts, m as wrapSection, s as SECTION_MERGE_ORDER } from "./prompts.mjs";
6
+ import { i as buildAllSectionPrompts, l as wrapSection, n as SECTION_MERGE_ORDER, r as SECTION_OUTPUT_FILES, s as getSectionValidator } from "./prompts.mjs";
7
+ import "./install.mjs";
7
8
  import { t as Type } from "./libs/@sinclair/typebox.mjs";
8
9
  import { homedir } from "node:os";
9
10
  import { dirname, join } from "pathe";
@@ -20,7 +21,6 @@ import { getEnvApiKey, getModel, getModels, getProviders, streamSimple } from "@
20
21
  import { getOAuthApiKey, getOAuthProvider, getOAuthProviders } from "@mariozechner/pi-ai/oauth";
21
22
  import { readFile } from "node:fs/promises";
22
23
  import { parseSync } from "oxc-parser";
23
- //#region src/agent/clis/claude.ts
24
24
  var claude_exports = /* @__PURE__ */ __exportAll({
25
25
  agentId: () => agentId$2,
26
26
  buildArgs: () => buildArgs$2,
@@ -73,16 +73,6 @@ function buildArgs$2(model, skillDir, symlinkDirs) {
73
73
  "--no-session-persistence"
74
74
  ];
75
75
  }
76
- /**
77
- * Parse claude stream-json events
78
- *
79
- * Event types:
80
- * - stream_event/content_block_delta/text_delta → token streaming
81
- * - stream_event/content_block_start/tool_use → tool invocation starting
82
- * - assistant message with tool_use content → tool name + input
83
- * - assistant message with text content → full text (non-streaming fallback)
84
- * - result → usage, cost, turns
85
- */
86
76
  function parseLine$2(line) {
87
77
  try {
88
78
  const obj = JSON.parse(line);
@@ -126,8 +116,6 @@ function parseLine$2(line) {
126
116
  } catch {}
127
117
  return {};
128
118
  }
129
- //#endregion
130
- //#region src/agent/clis/codex.ts
131
119
  var codex_exports = /* @__PURE__ */ __exportAll({
132
120
  agentId: () => agentId$1,
133
121
  buildArgs: () => buildArgs$1,
@@ -201,8 +189,6 @@ function parseLine$1(line) {
201
189
  } catch {}
202
190
  return {};
203
191
  }
204
- //#endregion
205
- //#region src/agent/clis/gemini.ts
206
192
  var gemini_exports = /* @__PURE__ */ __exportAll({
207
193
  agentId: () => agentId,
208
194
  buildArgs: () => buildArgs,
@@ -238,7 +224,6 @@ function buildArgs(model, skillDir, symlinkDirs) {
238
224
  ...symlinkDirs.flatMap((d) => ["--include-directories", d])
239
225
  ];
240
226
  }
241
- /** Parse gemini stream-json events — turn level (full message per event) */
242
227
  function parseLine(line) {
243
228
  try {
244
229
  const obj = JSON.parse(line);
@@ -271,12 +256,9 @@ function parseLine(line) {
271
256
  } catch {}
272
257
  return {};
273
258
  }
274
- //#endregion
275
- //#region src/agent/clis/pi-ai.ts
276
259
  function isPiAiModel(model) {
277
260
  return model.startsWith("pi:");
278
261
  }
279
- /** Parse a pi:provider/model-id string → { provider, modelId } */
280
262
  function parsePiAiModelId(model) {
281
263
  if (!model.startsWith("pi:")) return null;
282
264
  const rest = model.slice(3);
@@ -294,9 +276,7 @@ const BLOCKED_OAUTH_PROVIDERS = new Set([
294
276
  "anthropic",
295
277
  "openai-codex"
296
278
  ]);
297
- /** pi coding agent stores auth here; env var can override */
298
279
  const PI_AGENT_AUTH_PATH = join(process.env.PI_CODING_AGENT_DIR || join(homedir(), ".pi", "agent"), "auth.json");
299
- /** skilld's own auth file — used when user logs in via skilld */
300
280
  const SKILLD_AUTH_PATH = join(homedir(), ".skilld", "pi-ai-auth.json");
301
281
  function readAuthFile(path) {
302
282
  if (!existsSync(path)) return {};
@@ -306,7 +286,6 @@ function readAuthFile(path) {
306
286
  return {};
307
287
  }
308
288
  }
309
- /** Load auth from pi coding agent first (~/.pi/agent/auth.json), then skilld's own */
310
289
  function loadAuth() {
311
290
  const piAuth = readAuthFile(PI_AGENT_AUTH_PATH);
312
291
  return {
@@ -314,7 +293,6 @@ function loadAuth() {
314
293
  ...piAuth
315
294
  };
316
295
  }
317
- /** Save auth to skilld's own file — never writes to pi agent's auth */
318
296
  function saveAuth(auth) {
319
297
  mkdirSync(join(homedir(), ".skilld"), {
320
298
  recursive: true,
@@ -322,16 +300,10 @@ function saveAuth(auth) {
322
300
  });
323
301
  writeFileSync(SKILLD_AUTH_PATH, JSON.stringify(auth, null, 2), { mode: 384 });
324
302
  }
325
- /**
326
- * Overrides for model-provider → OAuth-provider mapping.
327
- * Most providers share the same ID in both systems (auto-matched).
328
- * Only list exceptions where the IDs diverge.
329
- */
330
303
  const OAUTH_PROVIDER_OVERRIDES = {
331
304
  google: "google-gemini-cli",
332
305
  openai: "openai-codex"
333
306
  };
334
- /** Resolve model provider ID → OAuth provider ID (returns null for blocked providers) */
335
307
  function resolveOAuthProviderId(modelProvider) {
336
308
  const oauthId = OAUTH_PROVIDER_OVERRIDES[modelProvider] ?? modelProvider;
337
309
  if (BLOCKED_OAUTH_PROVIDERS.has(oauthId)) return null;
@@ -339,7 +311,6 @@ function resolveOAuthProviderId(modelProvider) {
339
311
  if (new Set(getOAuthProviders().map((p) => p.id)).has(modelProvider)) return modelProvider;
340
312
  return null;
341
313
  }
342
- /** Resolve API key for a provider — checks env vars first, then OAuth credentials */
343
314
  async function resolveApiKey(provider) {
344
315
  const envKey = getEnvApiKey(provider);
345
316
  if (envKey) return envKey;
@@ -357,7 +328,6 @@ async function resolveApiKey(provider) {
357
328
  saveAuth(skilldAuth);
358
329
  return result.apiKey;
359
330
  }
360
- /** Get available OAuth providers for login (excludes blocked providers) */
361
331
  function getOAuthProviderList() {
362
332
  const auth = loadAuth();
363
333
  return getOAuthProviders().filter((p) => !BLOCKED_OAUTH_PROVIDERS.has(p.id)).map((p) => ({
@@ -366,7 +336,6 @@ function getOAuthProviderList() {
366
336
  loggedIn: !!auth[p.id]
367
337
  }));
368
338
  }
369
- /** Run OAuth login for a provider, saving credentials to ~/.skilld/ */
370
339
  async function loginOAuthProvider(providerId, callbacks) {
371
340
  const provider = getOAuthProvider(providerId);
372
341
  if (!provider) return false;
@@ -383,14 +352,12 @@ async function loginOAuthProvider(providerId, callbacks) {
383
352
  saveAuth(auth);
384
353
  return true;
385
354
  }
386
- /** Remove OAuth credentials for a provider */
387
355
  function logoutOAuthProvider(providerId) {
388
356
  const auth = loadAuth();
389
357
  delete auth[providerId];
390
358
  saveAuth(auth);
391
359
  }
392
360
  const MIN_CONTEXT_WINDOW = 32e3;
393
- /** Legacy model patterns — old generations that clutter the model list */
394
361
  const LEGACY_MODEL_PATTERNS = [
395
362
  /^claude-3-/,
396
363
  /^claude-3\.5-/,
@@ -407,13 +374,11 @@ const LEGACY_MODEL_PATTERNS = [
407
374
  function isLegacyModel(modelId) {
408
375
  return LEGACY_MODEL_PATTERNS.some((p) => p.test(modelId));
409
376
  }
410
- /** Preferred model per provider for auto-selection (cheapest reliable option) */
411
377
  const RECOMMENDED_MODELS = {
412
378
  anthropic: /haiku/,
413
379
  google: /flash/,
414
380
  openai: /gpt-4\.1-mini/
415
381
  };
416
- /** Get all pi-ai models for providers with auth configured */
417
382
  function getAvailablePiAiModels() {
418
383
  const providers = getProviders();
419
384
  const auth = loadAuth();
@@ -491,13 +456,11 @@ const SAFE_COMMANDS = new Set([
491
456
  "find"
492
457
  ]);
493
458
  const SHELL_META_RE = /[;&|`$()<>]/;
494
- /** Resolve a path safely within skilldDir, blocking traversal */
495
459
  function resolveSandboxedPath(p, skilldDir) {
496
460
  const resolved = resolve$1(skilldDir, String(p).replace(/^\.\/\.skilld\//, "./").replace(/^\.skilld\//, "./").replace(/^\.\//, ""));
497
461
  if (!resolved.startsWith(`${skilldDir}/`) && resolved !== skilldDir) throw new Error(`Path traversal blocked: ${p}`);
498
462
  return resolved;
499
463
  }
500
- /** Match a file path against a glob pattern using simple segment matching (no regex from user input) */
501
464
  function globMatch(filePath, pattern) {
502
465
  const segments = pattern.split("**");
503
466
  if (segments.length === 1) {
@@ -541,7 +504,6 @@ function globMatch(filePath, pattern) {
541
504
  }
542
505
  return true;
543
506
  }
544
- /** Execute a tool call against the .skilld/ directory */
545
507
  function executeTool(toolCall, skilldDir) {
546
508
  const args = toolCall.arguments;
547
509
  switch (toolCall.name) {
@@ -588,7 +550,6 @@ function executeTool(toolCall, skilldDir) {
588
550
  default: return `Unknown tool: ${toolCall.name}`;
589
551
  }
590
552
  }
591
- /** Optimize a single section using pi-ai agentic API with tool use */
592
553
  async function optimizeSectionPiAi(opts) {
593
554
  const parsed = parsePiAiModelId(opts.model);
594
555
  if (!parsed) throw new Error(`Invalid pi-ai model ID: ${opts.model}. Expected format: pi:provider/model-id`);
@@ -702,8 +663,6 @@ async function optimizeSectionPiAi(opts) {
702
663
  cost: totalCost
703
664
  };
704
665
  }
705
- //#endregion
706
- //#region src/agent/clis/index.ts
707
666
  const TOOL_VERBS = {
708
667
  Read: "Reading",
709
668
  Glob: "Searching",
@@ -717,11 +676,9 @@ const TOOL_VERBS = {
717
676
  search_file_content: "Searching",
718
677
  run_shell_command: "Running"
719
678
  };
720
- /** Create a progress callback that emits one line per tool call, Claude Code style */
721
679
  function createToolProgress(log) {
722
680
  let lastMsg = "";
723
681
  let repeatCount = 0;
724
- /** Per-section timestamp of last "Writing..." emission — throttles text_delta spam */
725
682
  const lastTextEmit = /* @__PURE__ */ new Map();
726
683
  const TEXT_THROTTLE_MS = 2e3;
727
684
  function emit(msg) {
@@ -786,7 +743,6 @@ const CLI_PARSE_LINE = {
786
743
  gemini: parseLine,
787
744
  codex: parseLine$1
788
745
  };
789
- /** Map CLI agent IDs to their LLM provider name (not the agent/tool name) */
790
746
  const CLI_PROVIDER_NAMES = {
791
747
  "claude-code": "Anthropic",
792
748
  "gemini-cli": "Google",
@@ -869,7 +825,6 @@ async function getAvailableModels() {
869
825
  });
870
826
  return [...cliModels, ...piAiEntries];
871
827
  }
872
- /** Resolve symlinks in .skilld/ to get real paths for --add-dir */
873
828
  function resolveReferenceDirs(skillDir) {
874
829
  const refsDir = join(skillDir, ".skilld");
875
830
  if (!existsSync(refsDir)) return [];
@@ -882,7 +837,6 @@ function resolveReferenceDirs(skillDir) {
882
837
  return [...resolved, ...parents];
883
838
  }
884
839
  const CACHE_DIR = join(homedir(), ".skilld", "llm-cache");
885
- /** Strip absolute paths from prompt so the hash is project-independent */
886
840
  function normalizePromptForHash(prompt) {
887
841
  return prompt.replace(/\/[^\s`]*\.(?:claude|codex|gemini)\/skills\/[^\s/`]+/g, "<SKILL_DIR>");
888
842
  }
@@ -971,7 +925,6 @@ async function optimizeSectionViaPiAi(opts) {
971
925
  };
972
926
  }
973
927
  }
974
- /** Spawn a single CLI process for one section, or call pi-ai directly */
975
928
  function optimizeSection(opts) {
976
929
  const { section, prompt, outputFile, skillDir, model, onProgress, timeout, debug, preExistingFiles } = opts;
977
930
  if (isPiAiModel(model)) return optimizeSectionViaPiAi({
@@ -1342,37 +1295,31 @@ async function optimizeDocs(opts) {
1342
1295
  debugLogsDir
1343
1296
  };
1344
1297
  }
1345
- /** Check if an error string indicates a rate limit (429) */
1346
1298
  function isRateLimitError(error) {
1347
1299
  if (!error) return false;
1348
1300
  return /\b429\b/.test(error) || /rate.?limit/i.test(error) || /exhausted.*capacity/i.test(error) || /quota.*reset/i.test(error);
1349
1301
  }
1350
- /** Parse delay hint from rate limit error (e.g. "reset after 5s" → 5). Returns undefined if not a rate limit. */
1351
1302
  function parseRateLimitDelay(error) {
1352
1303
  if (!error || !isRateLimitError(error)) return void 0;
1353
1304
  const match = error.match(/reset\s+after\s+(\d+)s/i);
1354
1305
  return match ? Number(match[1]) : 10;
1355
1306
  }
1356
- /** Extract error string from a PromiseSettledResult */
1357
1307
  function getRetryError(result) {
1358
1308
  if (result.status === "rejected") return String(result.reason);
1359
1309
  return result.value.error;
1360
1310
  }
1361
- /** Shorten absolute paths for display: /home/user/project/.claude/skills/vue/SKILL.md → .claude/.../SKILL.md */
1362
1311
  function shortenPath(p) {
1363
1312
  const refIdx = p.indexOf(".skilld/");
1364
1313
  if (refIdx !== -1) return p.slice(refIdx + 8);
1365
1314
  const parts = p.split("/");
1366
1315
  return parts.length > 2 ? `.../${parts.slice(-2).join("/")}` : p;
1367
1316
  }
1368
- /** Replace absolute paths in a command string with shortened versions */
1369
1317
  function shortenCommand(cmd) {
1370
1318
  return cmd.replace(/\/[^\s"']+/g, (match) => {
1371
1319
  if (match.includes(".claude/") || match.includes(".skilld/") || match.includes("node_modules/")) return `.../${match.split("/").slice(-2).join("/")}`;
1372
1320
  return match;
1373
1321
  });
1374
1322
  }
1375
- /** Clean a single section's LLM output: strip markdown fences, frontmatter, sanitize */
1376
1323
  function cleanSectionOutput(content) {
1377
1324
  let cleaned = content.trim();
1378
1325
  const wrapMatch = cleaned.match(/^```(?:markdown|md)?[^\S\n]*\n([\s\S]+)\n```[^\S\n]*$/);
@@ -1408,8 +1355,6 @@ function cleanSectionOutput(content) {
1408
1355
  if (!/^##\s/m.test(cleaned) && !/^- (?:BREAKING|DEPRECATED|NEW): /m.test(cleaned) && !/\[source\]/.test(cleaned)) return "";
1409
1356
  return cleaned;
1410
1357
  }
1411
- //#endregion
1412
- //#region src/agent/detect-presets.ts
1413
1358
  const NUXT_CONFIG_FILES = [
1414
1359
  "nuxt.config.ts",
1415
1360
  "nuxt.config.js",
@@ -1431,10 +1376,6 @@ async function findNuxtConfig(cwd) {
1431
1376
  }
1432
1377
  return null;
1433
1378
  }
1434
- /**
1435
- * Walk AST node to find all string values inside a `modules` array property.
1436
- * Handles: defineNuxtConfig({ modules: [...] }) and export default { modules: [...] }
1437
- */
1438
1379
  function extractModuleStrings(node) {
1439
1380
  if (!node || typeof node !== "object") return [];
1440
1381
  if (node.type === "Property" && !node.computed && node.key?.type === "Identifier" && node.key.name === "modules" && node.value?.type === "ArrayExpression") return node.value.elements.filter((el) => el?.type === "Literal" && typeof el.value === "string").map((el) => el.value);
@@ -1447,9 +1388,6 @@ function extractModuleStrings(node) {
1447
1388
  }
1448
1389
  return results;
1449
1390
  }
1450
- /**
1451
- * Detect Nuxt modules from nuxt.config.{ts,js,mjs}
1452
- */
1453
1391
  async function detectNuxtModules(cwd) {
1454
1392
  const config = await findNuxtConfig(cwd);
1455
1393
  if (!config) return [];
@@ -1474,18 +1412,9 @@ async function detectNuxtModules(cwd) {
1474
1412
  }
1475
1413
  return packages;
1476
1414
  }
1477
- /**
1478
- * Run all preset detectors and merge results
1479
- */
1480
1415
  async function detectPresetPackages(cwd) {
1481
1416
  return detectNuxtModules(cwd);
1482
1417
  }
1483
- //#endregion
1484
- //#region src/agent/detect-imports.ts
1485
- /**
1486
- * Detect directly-used npm packages by scanning source files
1487
- * Uses mlly for proper ES module parsing + tinyglobby for file discovery
1488
- */
1489
1418
  const PATTERNS = ["**/*.{ts,js,vue,mjs,cjs,tsx,jsx,mts,cts}"];
1490
1419
  const IGNORE = [
1491
1420
  "**/node_modules/**",
@@ -1499,10 +1428,6 @@ function addPackage(counts, specifier) {
1499
1428
  const name = specifier.startsWith("@") ? specifier.split("/").slice(0, 2).join("/") : specifier.split("/")[0];
1500
1429
  if (!isNodeBuiltin(name)) counts.set(name, (counts.get(name) || 0) + 1);
1501
1430
  }
1502
- /**
1503
- * Scan source files to detect all directly-imported npm packages
1504
- * Async with gitignore support for proper spinner animation
1505
- */
1506
1431
  async function detectImportedPackages(cwd = process.cwd()) {
1507
1432
  try {
1508
1433
  const counts = /* @__PURE__ */ new Map();
@@ -1587,7 +1512,6 @@ function isNodeBuiltin(pkg) {
1587
1512
  const base = pkg.startsWith("node:") ? pkg.slice(5) : pkg;
1588
1513
  return NODE_BUILTINS.has(base.split("/")[0]);
1589
1514
  }
1590
- //#endregion
1591
1515
  export { getModelLabel as a, getOAuthProviderList as c, getAvailableModels as i, loginOAuthProvider as l, cleanSectionOutput as n, getModelName as o, createToolProgress as r, optimizeDocs as s, detectImportedPackages as t, logoutOAuthProvider as u };
1592
1516
 
1593
1517
  //# sourceMappingURL=agent.mjs.map