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.
- package/README.md +32 -23
- package/dist/_chunks/agent.mjs +2 -78
- package/dist/_chunks/agent.mjs.map +1 -1
- package/dist/_chunks/assemble.mjs +1 -18
- package/dist/_chunks/assemble.mjs.map +1 -1
- package/dist/_chunks/author-group.mjs +17 -0
- package/dist/_chunks/author-group.mjs.map +1 -0
- package/dist/_chunks/author.mjs +8 -24
- package/dist/_chunks/author.mjs.map +1 -1
- package/dist/_chunks/cache.mjs +1 -73
- package/dist/_chunks/cache.mjs.map +1 -1
- package/dist/_chunks/cache2.mjs +84 -17
- package/dist/_chunks/cache2.mjs.map +1 -1
- package/dist/_chunks/cli-helpers.mjs +3 -166
- package/dist/_chunks/cli-helpers.mjs.map +1 -1
- package/dist/_chunks/cli-helpers2.mjs +0 -11
- package/dist/_chunks/config.mjs +119 -54
- package/dist/_chunks/config.mjs.map +1 -1
- package/dist/_chunks/core.mjs +9 -0
- package/dist/_chunks/detect.mjs +29 -226
- package/dist/_chunks/detect.mjs.map +1 -1
- package/dist/_chunks/embedding-cache.mjs +0 -5
- package/dist/_chunks/embedding-cache2.mjs +2 -3
- package/dist/_chunks/formatting.mjs +0 -6
- package/dist/_chunks/formatting.mjs.map +1 -1
- package/dist/_chunks/index.d.mts +0 -10
- package/dist/_chunks/index.d.mts.map +1 -1
- package/dist/_chunks/index2.d.mts +3 -6
- package/dist/_chunks/index2.d.mts.map +1 -1
- package/dist/_chunks/index3.d.mts +81 -109
- package/dist/_chunks/index3.d.mts.map +1 -1
- package/dist/_chunks/install.mjs +85 -550
- package/dist/_chunks/install.mjs.map +1 -1
- package/dist/_chunks/install2.mjs +554 -0
- package/dist/_chunks/install2.mjs.map +1 -0
- package/dist/_chunks/libs/@sinclair/typebox.mjs +0 -444
- package/dist/_chunks/libs/@sinclair/typebox.mjs.map +1 -1
- package/dist/_chunks/list.mjs +0 -16
- package/dist/_chunks/list.mjs.map +1 -1
- package/dist/_chunks/lockfile.mjs +2 -10
- package/dist/_chunks/lockfile.mjs.map +1 -1
- package/dist/_chunks/markdown.mjs +0 -9
- package/dist/_chunks/markdown.mjs.map +1 -1
- package/dist/_chunks/package-json.mjs +0 -25
- package/dist/_chunks/package-json.mjs.map +1 -1
- package/dist/_chunks/package-registry.mjs +465 -0
- package/dist/_chunks/package-registry.mjs.map +1 -0
- package/dist/_chunks/pool2.mjs +0 -2
- package/dist/_chunks/pool2.mjs.map +1 -1
- package/dist/_chunks/prefix.mjs +108 -0
- package/dist/_chunks/prefix.mjs.map +1 -0
- package/dist/_chunks/prepare.mjs +14 -9
- package/dist/_chunks/prepare.mjs.map +1 -1
- package/dist/_chunks/prepare2.mjs +1 -19
- package/dist/_chunks/prepare2.mjs.map +1 -1
- package/dist/_chunks/prompts.mjs +6 -201
- package/dist/_chunks/prompts.mjs.map +1 -1
- package/dist/_chunks/retriv.mjs +23 -24
- package/dist/_chunks/retriv.mjs.map +1 -1
- package/dist/_chunks/rolldown-runtime.mjs +0 -2
- package/dist/_chunks/sanitize.mjs +0 -78
- package/dist/_chunks/sanitize.mjs.map +1 -1
- package/dist/_chunks/search-helpers.mjs +99 -0
- package/dist/_chunks/search-helpers.mjs.map +1 -0
- package/dist/_chunks/search-interactive.mjs +1 -18
- package/dist/_chunks/search-interactive.mjs.map +1 -1
- package/dist/_chunks/search.mjs +218 -19
- package/dist/_chunks/search.mjs.map +1 -0
- package/dist/_chunks/setup.mjs +0 -13
- package/dist/_chunks/setup.mjs.map +1 -1
- package/dist/_chunks/shared.mjs +1 -473
- package/dist/_chunks/shared.mjs.map +1 -1
- package/dist/_chunks/skills.mjs +3 -3
- package/dist/_chunks/skills.mjs.map +1 -1
- package/dist/_chunks/sources.mjs +1179 -1440
- package/dist/_chunks/sources.mjs.map +1 -1
- package/dist/_chunks/sync-registry.mjs +59 -0
- package/dist/_chunks/sync-registry.mjs.map +1 -0
- package/dist/_chunks/sync-shared.mjs +0 -16
- package/dist/_chunks/sync-shared2.mjs +10 -49
- package/dist/_chunks/sync-shared2.mjs.map +1 -1
- package/dist/_chunks/sync.mjs +209 -120
- package/dist/_chunks/sync.mjs.map +1 -1
- package/dist/_chunks/sync2.mjs +1 -21
- package/dist/_chunks/types.d.mts +0 -2
- package/dist/_chunks/types.d.mts.map +1 -1
- package/dist/_chunks/uninstall.mjs +3 -27
- package/dist/_chunks/uninstall.mjs.map +1 -1
- package/dist/_chunks/upload.mjs +152 -0
- package/dist/_chunks/upload.mjs.map +1 -0
- package/dist/_chunks/validate.mjs +1 -8
- package/dist/_chunks/validate.mjs.map +1 -1
- package/dist/_chunks/version.mjs +30 -0
- package/dist/_chunks/version.mjs.map +1 -0
- package/dist/_chunks/wizard.mjs +2 -3
- package/dist/_chunks/yaml.mjs +0 -21
- package/dist/_chunks/yaml.mjs.map +1 -1
- package/dist/agent/index.d.mts +0 -24
- package/dist/agent/index.d.mts.map +1 -1
- package/dist/agent/index.mjs +2 -9
- package/dist/cache/index.mjs +1 -3
- package/dist/cli-entry.mjs +0 -6
- package/dist/cli-entry.mjs.map +1 -1
- package/dist/cli.mjs +48 -33
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +2 -8
- package/dist/prepare.mjs +0 -12
- package/dist/prepare.mjs.map +1 -1
- package/dist/retriv/index.mjs +0 -2
- package/dist/retriv/worker.d.mts +0 -3
- package/dist/retriv/worker.d.mts.map +1 -1
- package/dist/retriv/worker.mjs +0 -2
- package/dist/retriv/worker.mjs.map +1 -1
- package/dist/sources/index.d.mts +2 -2
- package/dist/sources/index.mjs +3 -7
- package/dist/types.d.mts +1 -1
- package/package.json +20 -21
- package/dist/_chunks/search2.mjs +0 -319
- 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
|
[](https://npmjs.com/package/skilld)
|
|
4
4
|
[](https://npm.chart.dev/skilld)
|
|
5
|
-
[](https://github.com/
|
|
5
|
+
[](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 <
|
|
184
|
-
| `skilld update [pkg]`
|
|
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
|
|
194
|
-
| `skilld
|
|
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/
|
|
342
|
+
Licensed under the [MIT license](https://github.com/skilld-dev/skilld/blob/main/LICENSE).
|
package/dist/_chunks/agent.mjs
CHANGED
|
@@ -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 {
|
|
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
|