@pleaseai/ask 0.1.0 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents.d.ts +2 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +73 -0
- package/dist/agents.js.map +1 -0
- package/dist/concurrency.d.ts +12 -0
- package/dist/concurrency.d.ts.map +1 -0
- package/dist/concurrency.js +33 -0
- package/dist/concurrency.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +28 -0
- package/dist/config.js.map +1 -0
- package/dist/ignore-files.d.ts +59 -0
- package/dist/ignore-files.d.ts.map +1 -0
- package/dist/ignore-files.js +205 -0
- package/dist/ignore-files.js.map +1 -0
- package/dist/index.d.ts +76 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +485 -0
- package/dist/index.js.map +1 -0
- package/dist/io.d.ts +55 -0
- package/dist/io.d.ts.map +1 -0
- package/dist/io.js +159 -0
- package/dist/io.js.map +1 -0
- package/dist/manifest/index.d.ts +26 -0
- package/dist/manifest/index.d.ts.map +1 -0
- package/dist/manifest/index.js +25 -0
- package/dist/manifest/index.js.map +1 -0
- package/dist/manifest/npm.d.ts +18 -0
- package/dist/manifest/npm.d.ts.map +1 -0
- package/dist/manifest/npm.js +155 -0
- package/dist/manifest/npm.js.map +1 -0
- package/dist/markers.d.ts +34 -0
- package/dist/markers.d.ts.map +1 -0
- package/dist/markers.js +82 -0
- package/dist/markers.js.map +1 -0
- package/dist/migrate-legacy.d.ts +24 -0
- package/dist/migrate-legacy.d.ts.map +1 -0
- package/dist/migrate-legacy.js +85 -0
- package/dist/migrate-legacy.js.map +1 -0
- package/dist/registry.d.ts +71 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +201 -0
- package/dist/registry.js.map +1 -0
- package/dist/resolvers/index.d.ts +32 -0
- package/dist/resolvers/index.d.ts.map +1 -0
- package/dist/resolvers/index.js +17 -0
- package/dist/resolvers/index.js.map +1 -0
- package/dist/resolvers/maven.d.ts +33 -0
- package/dist/resolvers/maven.d.ts.map +1 -0
- package/dist/resolvers/maven.js +187 -0
- package/dist/resolvers/maven.js.map +1 -0
- package/dist/resolvers/npm.d.ts +13 -0
- package/dist/resolvers/npm.d.ts.map +1 -0
- package/dist/resolvers/npm.js +67 -0
- package/dist/resolvers/npm.js.map +1 -0
- package/dist/resolvers/pub.d.ts +13 -0
- package/dist/resolvers/pub.d.ts.map +1 -0
- package/dist/resolvers/pub.js +50 -0
- package/dist/resolvers/pub.js.map +1 -0
- package/dist/resolvers/pypi.d.ts +12 -0
- package/dist/resolvers/pypi.d.ts.map +1 -0
- package/dist/resolvers/pypi.js +60 -0
- package/dist/resolvers/pypi.js.map +1 -0
- package/dist/resolvers/utils.d.ts +15 -0
- package/dist/resolvers/utils.d.ts.map +1 -0
- package/dist/resolvers/utils.js +26 -0
- package/dist/resolvers/utils.js.map +1 -0
- package/dist/schemas.d.ts +490 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +91 -0
- package/dist/schemas.js.map +1 -0
- package/dist/skill.d.ts +4 -0
- package/dist/skill.d.ts.map +1 -0
- package/dist/skill.js +53 -0
- package/dist/skill.js.map +1 -0
- package/dist/sources/github.d.ts +14 -0
- package/dist/sources/github.d.ts.map +1 -0
- package/dist/sources/github.js +114 -0
- package/dist/sources/github.js.map +1 -0
- package/dist/sources/index.d.ts +41 -0
- package/dist/sources/index.d.ts.map +1 -0
- package/dist/sources/index.js +14 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/sources/llms-txt.d.ts +5 -0
- package/dist/sources/llms-txt.d.ts.map +1 -0
- package/dist/sources/llms-txt.js +33 -0
- package/dist/sources/llms-txt.js.map +1 -0
- package/dist/sources/npm.d.ts +14 -0
- package/dist/sources/npm.d.ts.map +1 -0
- package/dist/sources/npm.js +113 -0
- package/dist/sources/npm.js.map +1 -0
- package/dist/sources/web.d.ts +13 -0
- package/dist/sources/web.d.ts.map +1 -0
- package/dist/sources/web.js +143 -0
- package/dist/sources/web.js.map +1 -0
- package/dist/storage.d.ts +11 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +76 -0
- package/dist/storage.js.map +1 -0
- package/package.json +9 -8
package/dist/index.js
ADDED
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import process from 'node:process';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
|
+
import { defineCommand, runMain } from 'citty';
|
|
6
|
+
import { consola } from 'consola';
|
|
7
|
+
import { generateAgentsMd } from './agents.js';
|
|
8
|
+
import { runWithConcurrency } from './concurrency.js';
|
|
9
|
+
import { addDocEntry, loadConfig, removeDocEntry, } from './config.js';
|
|
10
|
+
import { manageIgnoreFiles } from './ignore-files.js';
|
|
11
|
+
import { contentHash, getConfigPath, getLockPath, readLock, upsertLockEntry } from './io.js';
|
|
12
|
+
import { getReader } from './manifest/index.js';
|
|
13
|
+
import { migrateLegacyWorkspace } from './migrate-legacy.js';
|
|
14
|
+
import { fetchRegistryEntry, parseDocSpec, parseEcosystem, resolveFromRegistry } from './registry.js';
|
|
15
|
+
import { getResolver } from './resolvers/index.js';
|
|
16
|
+
import { generateSkill, removeSkill } from './skill.js';
|
|
17
|
+
import { getSource } from './sources/index.js';
|
|
18
|
+
import { listDocs, removeDocs, saveDocs } from './storage.js';
|
|
19
|
+
function buildLockEntry(config, result) {
|
|
20
|
+
const base = {
|
|
21
|
+
version: result.resolvedVersion,
|
|
22
|
+
fetchedAt: new Date().toISOString(),
|
|
23
|
+
fileCount: result.files.length,
|
|
24
|
+
contentHash: contentHash(result.files.map(f => ({ relpath: f.path, content: f.content }))),
|
|
25
|
+
};
|
|
26
|
+
const meta = result.meta ?? {};
|
|
27
|
+
switch (config.source) {
|
|
28
|
+
case 'github':
|
|
29
|
+
return {
|
|
30
|
+
...base,
|
|
31
|
+
source: 'github',
|
|
32
|
+
repo: config.repo,
|
|
33
|
+
ref: meta.ref ?? config.tag ?? config.branch ?? 'main',
|
|
34
|
+
...(meta.commit ? { commit: meta.commit } : {}),
|
|
35
|
+
};
|
|
36
|
+
case 'npm':
|
|
37
|
+
if (!meta.tarball) {
|
|
38
|
+
throw new Error(`npm source did not return a tarball URL for ${config.name}@${result.resolvedVersion}. `
|
|
39
|
+
+ 'Cannot record lockfile entry without it.');
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
...base,
|
|
43
|
+
source: 'npm',
|
|
44
|
+
tarball: meta.tarball,
|
|
45
|
+
...(meta.integrity ? { integrity: meta.integrity } : {}),
|
|
46
|
+
};
|
|
47
|
+
case 'web':
|
|
48
|
+
return {
|
|
49
|
+
...base,
|
|
50
|
+
source: 'web',
|
|
51
|
+
urls: meta.urls ?? config.urls,
|
|
52
|
+
};
|
|
53
|
+
case 'llms-txt':
|
|
54
|
+
return {
|
|
55
|
+
...base,
|
|
56
|
+
source: 'llms-txt',
|
|
57
|
+
url: (meta.urls ?? [])[0] ?? config.url,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Gate A: reject bare-name specs (`ask docs add next`).
|
|
63
|
+
*
|
|
64
|
+
* Bare names are ambiguous — they give the CLI no ecosystem hint and no
|
|
65
|
+
* explicit source, and silently auto-resolving them (which the old code did)
|
|
66
|
+
* can hand back wrong-looking docs. Instead we force the caller to either use
|
|
67
|
+
* an ecosystem prefix (`npm:next`) or the github shorthand (`owner/repo`).
|
|
68
|
+
*
|
|
69
|
+
* Returns an error message when the spec is ambiguous, or `null` when it is
|
|
70
|
+
* OK to proceed. `hasExplicitSource` lets the caller opt out of the check
|
|
71
|
+
* when `--source` is passed explicitly — an explicit source disambiguates.
|
|
72
|
+
*/
|
|
73
|
+
export function checkBareNameGate(input, parsedKind, hasExplicitSource) {
|
|
74
|
+
if (hasExplicitSource)
|
|
75
|
+
return null;
|
|
76
|
+
if (parsedKind !== 'name')
|
|
77
|
+
return null;
|
|
78
|
+
return (`Ambiguous spec '${input}'. Use one of:\n`
|
|
79
|
+
+ ` • npm:<name>[@version] (or pypi:, pub:, crates:, hex:, go:, maven:)\n`
|
|
80
|
+
+ ` • <owner>/<repo>[@ref] (direct GitHub)\n`
|
|
81
|
+
+ `Tip: the add-docs skill auto-resolves bare names from your project manifest.`);
|
|
82
|
+
}
|
|
83
|
+
export function runManifestGate(ecosystem, name, version, projectDir, opts, readerFactory = getReader) {
|
|
84
|
+
if (opts.noManifest)
|
|
85
|
+
return { kind: 'ok' };
|
|
86
|
+
if (version !== 'latest')
|
|
87
|
+
return { kind: 'ok' };
|
|
88
|
+
const reader = readerFactory(ecosystem);
|
|
89
|
+
const hit = reader?.readInstalledVersion(name, projectDir) ?? null;
|
|
90
|
+
if (!hit) {
|
|
91
|
+
if (opts.fromManifest) {
|
|
92
|
+
return {
|
|
93
|
+
kind: 'error',
|
|
94
|
+
message: `--from-manifest was set but no ${ecosystem} manifest entry found for '${name}'. `
|
|
95
|
+
+ `Ensure the package is listed in your lockfile or package.json.`,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return { kind: 'ok' };
|
|
99
|
+
}
|
|
100
|
+
return { kind: 'ok', version: hit.version, source: hit.source };
|
|
101
|
+
}
|
|
102
|
+
function parseSpec(spec) {
|
|
103
|
+
const lastAt = spec.lastIndexOf('@');
|
|
104
|
+
if (lastAt > 0) {
|
|
105
|
+
return {
|
|
106
|
+
name: spec.substring(0, lastAt),
|
|
107
|
+
version: spec.substring(lastAt + 1),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
return { name: spec, version: 'latest' };
|
|
111
|
+
}
|
|
112
|
+
function buildSourceConfig(name, version, opts) {
|
|
113
|
+
const base = { name, version };
|
|
114
|
+
switch (opts.source) {
|
|
115
|
+
case 'npm':
|
|
116
|
+
return {
|
|
117
|
+
...base,
|
|
118
|
+
source: 'npm',
|
|
119
|
+
docsPath: opts.docsPath,
|
|
120
|
+
};
|
|
121
|
+
case 'github':
|
|
122
|
+
if (!opts.repo) {
|
|
123
|
+
throw new Error('--repo is required for github source');
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
...base,
|
|
127
|
+
source: 'github',
|
|
128
|
+
repo: opts.repo,
|
|
129
|
+
branch: opts.branch,
|
|
130
|
+
tag: opts.tag,
|
|
131
|
+
docsPath: opts.docsPath,
|
|
132
|
+
};
|
|
133
|
+
case 'web':
|
|
134
|
+
if (!opts.url || opts.url.length === 0) {
|
|
135
|
+
throw new Error('--url is required for web source');
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
...base,
|
|
139
|
+
source: 'web',
|
|
140
|
+
urls: opts.url,
|
|
141
|
+
maxDepth: Number.parseInt(opts.maxDepth ?? '1', 10),
|
|
142
|
+
allowedPathPrefix: opts.pathPrefix,
|
|
143
|
+
};
|
|
144
|
+
case 'llms-txt':
|
|
145
|
+
if (!opts.url || opts.url.length === 0) {
|
|
146
|
+
throw new Error('--url is required for llms-txt source');
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
...base,
|
|
150
|
+
source: 'llms-txt',
|
|
151
|
+
url: opts.url[0],
|
|
152
|
+
};
|
|
153
|
+
default:
|
|
154
|
+
throw new Error(`Unknown source: ${opts.source}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const addCmd = defineCommand({
|
|
158
|
+
meta: { name: 'add', description: 'Download documentation for a library' },
|
|
159
|
+
args: {
|
|
160
|
+
'spec': { type: 'positional', description: 'Library spec (e.g. zod@3.22 or npm:next@canary)', required: true },
|
|
161
|
+
'source': { type: 'string', description: 'Source type: npm, github, web, llms-txt (auto-detected if omitted)', alias: ['s'] },
|
|
162
|
+
'repo': { type: 'string', description: 'GitHub repository (for github source)' },
|
|
163
|
+
'branch': { type: 'string', description: 'Git branch (for github source)' },
|
|
164
|
+
'tag': { type: 'string', description: 'Git tag (for github source)' },
|
|
165
|
+
'docsPath': { type: 'string', description: 'Path to docs within the package/repo' },
|
|
166
|
+
'url': { type: 'string', description: 'Documentation URL (for web source)' },
|
|
167
|
+
'maxDepth': { type: 'string', description: 'Max crawl depth for web source', default: '1' },
|
|
168
|
+
'pathPrefix': { type: 'string', description: 'URL path prefix filter for web source' },
|
|
169
|
+
'no-manifest': { type: 'boolean', description: 'Do not consult project manifest/lockfile for version resolution' },
|
|
170
|
+
'from-manifest': { type: 'boolean', description: 'Require manifest/lockfile to supply the version; error if absent' },
|
|
171
|
+
},
|
|
172
|
+
async run({ args }) {
|
|
173
|
+
const projectDir = process.cwd();
|
|
174
|
+
migrateLegacyWorkspace(projectDir);
|
|
175
|
+
let effectiveSpec = args.spec;
|
|
176
|
+
const parsed = parseDocSpec(effectiveSpec);
|
|
177
|
+
const { spec: cleanSpec } = parseEcosystem(effectiveSpec);
|
|
178
|
+
let sourceConfig;
|
|
179
|
+
// Gate A — reject bare-name specs (ambiguous, no ecosystem hint).
|
|
180
|
+
const gateAError = checkBareNameGate(effectiveSpec, parsed.kind, Boolean(args.source));
|
|
181
|
+
if (gateAError) {
|
|
182
|
+
consola.error(gateAError);
|
|
183
|
+
process.exit(1);
|
|
184
|
+
return; // unreachable
|
|
185
|
+
}
|
|
186
|
+
// Gate B — manifest-based version resolution. Only applies to ecosystem
|
|
187
|
+
// specs with no explicit version (`npm:next` / `pypi:fastapi`).
|
|
188
|
+
if (parsed.kind === 'ecosystem') {
|
|
189
|
+
const gateB = runManifestGate(parsed.ecosystem, parsed.name, parsed.version, projectDir, {
|
|
190
|
+
// citty exposes kebab-case flags under the original key as defined in args.
|
|
191
|
+
noManifest: Boolean(args['no-manifest']),
|
|
192
|
+
fromManifest: Boolean(args['from-manifest']),
|
|
193
|
+
});
|
|
194
|
+
if (gateB.kind === 'error') {
|
|
195
|
+
consola.error(gateB.message);
|
|
196
|
+
process.exit(1);
|
|
197
|
+
return; // unreachable
|
|
198
|
+
}
|
|
199
|
+
if (gateB.version) {
|
|
200
|
+
consola.info(`Using version ${gateB.version} from ${gateB.source}`);
|
|
201
|
+
// Mutation is intentional: the ecosystem resolver fallback at line ~365
|
|
202
|
+
// calls resolver.resolve(parsed.name, parsed.version) directly, so
|
|
203
|
+
// parsed.version must reflect the manifest override.
|
|
204
|
+
parsed.version = gateB.version;
|
|
205
|
+
// Also rebuild effectiveSpec so resolveFromRegistry (which re-parses
|
|
206
|
+
// from the raw spec string) picks up the override version.
|
|
207
|
+
effectiveSpec = `${parsed.ecosystem}:${parsed.name}@${gateB.version}`;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// github fast-path: `owner/repo[@ref]` — try registry for docsPath,
|
|
211
|
+
// then fall back to bare repo download.
|
|
212
|
+
// Only triggered when no explicit --source override was passed.
|
|
213
|
+
if (!args.source && parsed.kind === 'github') {
|
|
214
|
+
const { owner, repo, ref } = parsed;
|
|
215
|
+
const repoSpec = `${owner}/${repo}`;
|
|
216
|
+
const version = ref ?? 'latest';
|
|
217
|
+
const libName = `${owner}-${repo}`;
|
|
218
|
+
// Enrich with registry metadata (docsPath, strategies) when available
|
|
219
|
+
let docsPath = args.docsPath;
|
|
220
|
+
if (!docsPath) {
|
|
221
|
+
const entry = await fetchRegistryEntry(owner, repo);
|
|
222
|
+
if (entry) {
|
|
223
|
+
consola.info(`Found ${entry.name} in registry`);
|
|
224
|
+
docsPath = entry.docsPath;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
consola.start(`Downloading ${repoSpec}${ref ? `@${ref}` : ''} docs (source: github)...`);
|
|
228
|
+
sourceConfig = {
|
|
229
|
+
source: 'github',
|
|
230
|
+
name: libName,
|
|
231
|
+
version,
|
|
232
|
+
repo: repoSpec,
|
|
233
|
+
tag: ref,
|
|
234
|
+
docsPath,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
else if (args.source) {
|
|
238
|
+
// Explicit source — use manual config
|
|
239
|
+
const { name, version } = parseSpec(cleanSpec);
|
|
240
|
+
const urls = args.url ? [args.url] : undefined;
|
|
241
|
+
consola.start(`Downloading ${name}@${version} docs (source: ${args.source})...`);
|
|
242
|
+
sourceConfig = buildSourceConfig(name, version, {
|
|
243
|
+
source: args.source,
|
|
244
|
+
repo: args.repo,
|
|
245
|
+
branch: args.branch,
|
|
246
|
+
tag: args.tag,
|
|
247
|
+
docsPath: args.docsPath,
|
|
248
|
+
url: urls,
|
|
249
|
+
maxDepth: args.maxDepth,
|
|
250
|
+
pathPrefix: args.pathPrefix,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
// Auto-detect from registry
|
|
255
|
+
const resolved = await resolveFromRegistry(effectiveSpec, projectDir);
|
|
256
|
+
if (resolved) {
|
|
257
|
+
const { strategy } = resolved;
|
|
258
|
+
consola.start(`Downloading ${resolved.name}@${resolved.version} docs (source: ${strategy.source})...`);
|
|
259
|
+
sourceConfig = buildSourceConfig(resolved.name, resolved.version, {
|
|
260
|
+
source: strategy.source,
|
|
261
|
+
repo: strategy.repo,
|
|
262
|
+
docsPath: strategy.docsPath,
|
|
263
|
+
url: strategy.urls ?? (strategy.url ? [strategy.url] : undefined),
|
|
264
|
+
maxDepth: strategy.maxDepth?.toString(),
|
|
265
|
+
pathPrefix: strategy.allowedPathPrefix,
|
|
266
|
+
branch: strategy.branch,
|
|
267
|
+
tag: strategy.tag,
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
else if (parsed.kind === 'ecosystem') {
|
|
271
|
+
// Registry miss with ecosystem prefix → try ecosystem resolver
|
|
272
|
+
const resolver = getResolver(parsed.ecosystem);
|
|
273
|
+
if (!resolver) {
|
|
274
|
+
consola.error(`'${args.spec}' not found in registry and no resolver for '${parsed.ecosystem}'. `
|
|
275
|
+
+ `Use --source to specify manually.`);
|
|
276
|
+
process.exit(1);
|
|
277
|
+
return; // unreachable — hints TS that control flow ends
|
|
278
|
+
}
|
|
279
|
+
consola.info(`Registry miss — resolving via ${parsed.ecosystem} package metadata...`);
|
|
280
|
+
const resolveResult = await resolver.resolve(parsed.name, parsed.version);
|
|
281
|
+
consola.start(`Downloading ${parsed.name}@${resolveResult.resolvedVersion} docs (source: github via ${parsed.ecosystem} resolver)...`);
|
|
282
|
+
sourceConfig = {
|
|
283
|
+
source: 'github',
|
|
284
|
+
name: parsed.name,
|
|
285
|
+
version: resolveResult.resolvedVersion,
|
|
286
|
+
repo: resolveResult.repo,
|
|
287
|
+
tag: resolveResult.ref,
|
|
288
|
+
docsPath: args.docsPath,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
consola.error(`'${args.spec}' not found in registry. Use --source to specify manually.`);
|
|
293
|
+
process.exit(1);
|
|
294
|
+
return; // unreachable — hints TS that control flow ends
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
const source = getSource(sourceConfig.source);
|
|
298
|
+
const result = await source.fetch(sourceConfig);
|
|
299
|
+
const libName = sourceConfig.name;
|
|
300
|
+
consola.info(`Fetched ${result.files.length} doc files (resolved version: ${result.resolvedVersion})`);
|
|
301
|
+
const docsDir = saveDocs(projectDir, libName, result.resolvedVersion, result.files);
|
|
302
|
+
consola.info(`Docs saved to: ${docsDir}`);
|
|
303
|
+
const configEntry = { ...sourceConfig, version: result.resolvedVersion };
|
|
304
|
+
addDocEntry(projectDir, configEntry);
|
|
305
|
+
consola.info(`Config updated: ${path.relative(projectDir, getConfigPath(projectDir))}`);
|
|
306
|
+
const lockEntry = buildLockEntry(sourceConfig, result);
|
|
307
|
+
upsertLockEntry(projectDir, libName, lockEntry);
|
|
308
|
+
consola.info(`Lock updated: ${path.relative(projectDir, getLockPath(projectDir))}`);
|
|
309
|
+
const skillPath = generateSkill(projectDir, libName, result.resolvedVersion, result.files.map(f => f.path));
|
|
310
|
+
consola.info(`Skill created: ${skillPath}`);
|
|
311
|
+
const agentsPath = generateAgentsMd(projectDir);
|
|
312
|
+
consola.info(`AGENTS.md updated: ${agentsPath}`);
|
|
313
|
+
manageIgnoreFiles(projectDir, 'install');
|
|
314
|
+
consola.success(`Done! ${libName}@${result.resolvedVersion} docs are ready for AI agents.`);
|
|
315
|
+
},
|
|
316
|
+
});
|
|
317
|
+
/**
|
|
318
|
+
* Sync a single doc entry: fetch, diff, write. Never throws — failures are
|
|
319
|
+
* captured and returned as `status: 'failed'`. Logs the same lines that the
|
|
320
|
+
* legacy serial loop emitted, so user-facing output is unchanged.
|
|
321
|
+
*
|
|
322
|
+
* The internal write order (saveDocs → addDocEntry → upsertLockEntry →
|
|
323
|
+
* removeDocs(old) → generateSkill) is preserved verbatim from the previous
|
|
324
|
+
* implementation. See the inline comment below for the rationale.
|
|
325
|
+
*
|
|
326
|
+
* Safe to call from `runWithConcurrency` because:
|
|
327
|
+
* 1. Only `source.fetch()` is async (network I/O).
|
|
328
|
+
* 2. All disk writes (`addDocEntry`, `upsertLockEntry`, `saveDocs`,
|
|
329
|
+
* `removeDocs`, `generateSkill`) are fully synchronous fs operations
|
|
330
|
+
* with no `await` between read and write — Node's single-threaded event
|
|
331
|
+
* loop guarantees they execute atomically with respect to each other.
|
|
332
|
+
*/
|
|
333
|
+
async function syncEntry(projectDir, entry, lock) {
|
|
334
|
+
try {
|
|
335
|
+
consola.info(` ${entry.name} (${entry.source})...`);
|
|
336
|
+
const source = getSource(entry.source);
|
|
337
|
+
const result = await source.fetch(entry);
|
|
338
|
+
const newLockEntry = buildLockEntry(entry, result);
|
|
339
|
+
const previousLock = lock.entries[entry.name];
|
|
340
|
+
const changed = !previousLock
|
|
341
|
+
|| previousLock.contentHash !== newLockEntry.contentHash
|
|
342
|
+
|| previousLock.version !== newLockEntry.version;
|
|
343
|
+
if (!changed) {
|
|
344
|
+
consola.info(` -> unchanged (v${result.resolvedVersion})`);
|
|
345
|
+
return 'unchanged';
|
|
346
|
+
}
|
|
347
|
+
// Drift confirmed. Order is intentional: every write that can throw
|
|
348
|
+
// (saveDocs, addDocEntry/Zod, upsertLockEntry/Zod) happens BEFORE the
|
|
349
|
+
// destructive removeDocs of the old version. A mid-flow failure
|
|
350
|
+
// leaves both directories on disk and the config/lock pointing at
|
|
351
|
+
// the old version — recoverable on the next sync. Reversing this
|
|
352
|
+
// order would let a failed write leave config pointing at a deleted
|
|
353
|
+
// directory.
|
|
354
|
+
saveDocs(projectDir, entry.name, result.resolvedVersion, result.files);
|
|
355
|
+
addDocEntry(projectDir, { ...entry, version: result.resolvedVersion });
|
|
356
|
+
upsertLockEntry(projectDir, entry.name, newLockEntry);
|
|
357
|
+
if (previousLock && previousLock.version !== result.resolvedVersion) {
|
|
358
|
+
removeDocs(projectDir, entry.name, previousLock.version);
|
|
359
|
+
}
|
|
360
|
+
generateSkill(projectDir, entry.name, result.resolvedVersion, result.files.map(f => f.path));
|
|
361
|
+
const fromVersion = previousLock?.version ?? '(new)';
|
|
362
|
+
consola.success(` ⟳ ${fromVersion} → ${result.resolvedVersion} (${result.files.length} files)`);
|
|
363
|
+
return 'drifted';
|
|
364
|
+
}
|
|
365
|
+
catch (err) {
|
|
366
|
+
consola.error(` -> Error: ${err instanceof Error ? err.message : err}`);
|
|
367
|
+
return 'failed';
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
// Sources that are safe to fetch in parallel. `web` is intentionally excluded
|
|
371
|
+
// to remain polite toward upstream documentation servers (we don't know if
|
|
372
|
+
// multiple URLs hit the same host, and crawl bursts can trip rate limits).
|
|
373
|
+
const PARALLEL_SOURCES = new Set(['github', 'npm', 'llms-txt']);
|
|
374
|
+
const SYNC_CONCURRENCY = 5;
|
|
375
|
+
export async function runSync(projectDir, options = {}) {
|
|
376
|
+
migrateLegacyWorkspace(projectDir);
|
|
377
|
+
const config = loadConfig(projectDir);
|
|
378
|
+
const lock = readLock(projectDir);
|
|
379
|
+
if (config.docs.length === 0) {
|
|
380
|
+
consola.info('No docs configured in .ask/config.json');
|
|
381
|
+
return { drifted: 0, unchanged: 0, failed: 0 };
|
|
382
|
+
}
|
|
383
|
+
consola.start(`Syncing ${config.docs.length} library docs...`);
|
|
384
|
+
const fn = options.syncEntryFn ?? syncEntry;
|
|
385
|
+
const parallel = [];
|
|
386
|
+
const serial = [];
|
|
387
|
+
for (const entry of config.docs) {
|
|
388
|
+
if (PARALLEL_SOURCES.has(entry.source)) {
|
|
389
|
+
parallel.push(entry);
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
serial.push(entry);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
const parallelResults = await runWithConcurrency(parallel, SYNC_CONCURRENCY, entry => fn(projectDir, entry, lock));
|
|
396
|
+
const serialResults = [];
|
|
397
|
+
for (const entry of serial) {
|
|
398
|
+
serialResults.push(await fn(projectDir, entry, lock));
|
|
399
|
+
}
|
|
400
|
+
const counts = { drifted: 0, unchanged: 0, failed: 0 };
|
|
401
|
+
for (const status of [...parallelResults, ...serialResults]) {
|
|
402
|
+
counts[status]++;
|
|
403
|
+
}
|
|
404
|
+
if (!options.skipAgentsMd) {
|
|
405
|
+
generateAgentsMd(projectDir);
|
|
406
|
+
}
|
|
407
|
+
// `skipAgentsMd` is specifically about AGENTS.md regeneration; ignore
|
|
408
|
+
// file management always runs so that the project's lint/format/review
|
|
409
|
+
// tooling stays in sync with the current `.ask/docs/` state.
|
|
410
|
+
manageIgnoreFiles(projectDir, 'install');
|
|
411
|
+
consola.success(`Sync complete: ${counts.drifted} re-fetched, ${counts.unchanged} unchanged, ${counts.failed} failed. AGENTS.md updated.`);
|
|
412
|
+
return counts;
|
|
413
|
+
}
|
|
414
|
+
const syncCmd = defineCommand({
|
|
415
|
+
meta: { name: 'sync', description: 'Refresh docs from .ask/config.json, using .ask/ask.lock as the drift baseline' },
|
|
416
|
+
async run() {
|
|
417
|
+
await runSync(process.cwd());
|
|
418
|
+
},
|
|
419
|
+
});
|
|
420
|
+
const listCmd = defineCommand({
|
|
421
|
+
meta: { name: 'list', description: 'List downloaded documentation' },
|
|
422
|
+
run() {
|
|
423
|
+
const projectDir = process.cwd();
|
|
424
|
+
migrateLegacyWorkspace(projectDir);
|
|
425
|
+
const entries = listDocs(projectDir);
|
|
426
|
+
if (entries.length === 0) {
|
|
427
|
+
consola.info('No docs downloaded yet. Use `ask docs add` to get started.');
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
consola.info('Downloaded documentation:');
|
|
431
|
+
for (const { name, version, fileCount } of entries) {
|
|
432
|
+
consola.log(` ${name}@${version} (${fileCount} files)`);
|
|
433
|
+
}
|
|
434
|
+
},
|
|
435
|
+
});
|
|
436
|
+
const removeCmd = defineCommand({
|
|
437
|
+
meta: { name: 'remove', description: 'Remove downloaded documentation' },
|
|
438
|
+
args: {
|
|
439
|
+
spec: { type: 'positional', description: 'Library spec (e.g. zod or zod@3.22)', required: true },
|
|
440
|
+
},
|
|
441
|
+
run({ args }) {
|
|
442
|
+
const projectDir = process.cwd();
|
|
443
|
+
migrateLegacyWorkspace(projectDir);
|
|
444
|
+
const { name, version } = parseSpec(args.spec);
|
|
445
|
+
const hasExplicitVersion = args.spec.lastIndexOf('@') > 0;
|
|
446
|
+
const ver = hasExplicitVersion ? version : undefined;
|
|
447
|
+
removeDocs(projectDir, name, ver);
|
|
448
|
+
removeSkill(projectDir, name);
|
|
449
|
+
removeDocEntry(projectDir, name, ver);
|
|
450
|
+
generateAgentsMd(projectDir);
|
|
451
|
+
// If no docs remain, strip all ignore-file artifacts. Otherwise keep
|
|
452
|
+
// them in sync (e.g. a new root .prettierignore added since last add).
|
|
453
|
+
const remaining = listDocs(projectDir);
|
|
454
|
+
manageIgnoreFiles(projectDir, remaining.length === 0 ? 'remove' : 'install');
|
|
455
|
+
consola.success(`Removed docs for ${name}${ver ? `@${ver}` : ' (all versions)'}`);
|
|
456
|
+
},
|
|
457
|
+
});
|
|
458
|
+
const docsCmd = defineCommand({
|
|
459
|
+
meta: { name: 'docs', description: 'Manage library documentation' },
|
|
460
|
+
subCommands: {
|
|
461
|
+
add: addCmd,
|
|
462
|
+
sync: syncCmd,
|
|
463
|
+
list: listCmd,
|
|
464
|
+
remove: removeCmd,
|
|
465
|
+
},
|
|
466
|
+
});
|
|
467
|
+
const main = defineCommand({
|
|
468
|
+
meta: {
|
|
469
|
+
name: 'ask',
|
|
470
|
+
version: '0.1.0',
|
|
471
|
+
description: 'Agent Skills Kit - Download version-specific library docs for AI coding agents',
|
|
472
|
+
},
|
|
473
|
+
subCommands: {
|
|
474
|
+
docs: docsCmd,
|
|
475
|
+
},
|
|
476
|
+
});
|
|
477
|
+
// Only execute the CLI when this module is the program entry point.
|
|
478
|
+
// Tests import `runSync` from this file and must NOT trigger CLI execution.
|
|
479
|
+
// Use `pathToFileURL` for a cross-platform comparison: a naive
|
|
480
|
+
// `file://${process.argv[1]}` template breaks on Windows (backslash paths)
|
|
481
|
+
// and on POSIX paths containing spaces or unicode (no URL encoding).
|
|
482
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
483
|
+
runMain(main);
|
|
484
|
+
}
|
|
485
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/io.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Config, Lock, LockEntry } from './schemas.js';
|
|
2
|
+
/**
|
|
3
|
+
* Serialize a value to JSON with sorted keys, 2-space indent, and a trailing
|
|
4
|
+
* newline. Two calls with semantically equivalent input always produce the
|
|
5
|
+
* same byte string.
|
|
6
|
+
*/
|
|
7
|
+
export declare function sortedJSON(value: unknown): string;
|
|
8
|
+
/**
|
|
9
|
+
* Compute a deterministic content hash over a list of files.
|
|
10
|
+
* Files are sorted by relative path; each file contributes
|
|
11
|
+
* `<relpath>\0<bytes>\0` to the hash stream. The null separators prevent
|
|
12
|
+
* `path + content` ambiguity (e.g. "ab" + "cd" vs "a" + "bcd").
|
|
13
|
+
*
|
|
14
|
+
* Accepts either pre-encoded bytes or string content (the common case for
|
|
15
|
+
* DocFile records returned by source adapters).
|
|
16
|
+
*/
|
|
17
|
+
export interface HashableFile {
|
|
18
|
+
relpath: string;
|
|
19
|
+
bytes?: Uint8Array;
|
|
20
|
+
content?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function contentHash(files: HashableFile[]): string;
|
|
23
|
+
export declare function getAskDir(projectDir: string): string;
|
|
24
|
+
export declare function getConfigPath(projectDir: string): string;
|
|
25
|
+
export declare function getLockPath(projectDir: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Read and validate `.ask/config.json`. Returns the default empty config when
|
|
28
|
+
* the file does not exist. Throws on invalid contents.
|
|
29
|
+
*/
|
|
30
|
+
export declare function readConfig(projectDir: string): Config;
|
|
31
|
+
/**
|
|
32
|
+
* Validate, sort, and write `.ask/config.json`. Sorts `docs[]` by name.
|
|
33
|
+
* Throws (without writing) if the input fails Zod validation.
|
|
34
|
+
*/
|
|
35
|
+
export declare function writeConfig(projectDir: string, config: Config): void;
|
|
36
|
+
/**
|
|
37
|
+
* Read and validate `.ask/ask.lock`. Returns the default empty lock when the
|
|
38
|
+
* file does not exist. Throws on invalid contents.
|
|
39
|
+
*/
|
|
40
|
+
export declare function readLock(projectDir: string): Lock;
|
|
41
|
+
/**
|
|
42
|
+
* Validate, sort, and write `.ask/ask.lock`. Throws (without writing) if the
|
|
43
|
+
* input fails Zod validation.
|
|
44
|
+
*/
|
|
45
|
+
export declare function writeLock(projectDir: string, lock: Lock): void;
|
|
46
|
+
/**
|
|
47
|
+
* Upsert a single entry into `.ask/ask.lock`. Updates `generatedAt` only when
|
|
48
|
+
* the entry actually changes (so byte-stable on no-op re-runs).
|
|
49
|
+
*/
|
|
50
|
+
export declare function upsertLockEntry(projectDir: string, name: string, entry: LockEntry): void;
|
|
51
|
+
/**
|
|
52
|
+
* Remove one or more entries from the lock by name. No-op if absent.
|
|
53
|
+
*/
|
|
54
|
+
export declare function removeLockEntries(projectDir: string, names: string[]): void;
|
|
55
|
+
//# sourceMappingURL=io.d.ts.map
|
package/dist/io.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"io.d.ts","sourceRoot":"","sources":["../src/io.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAuB3D;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEjD;AAKD;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,MAAM,CAYzD;AAMD,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAiBrD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CASpE;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAqBjD;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAK9D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,SAAS,GACf,IAAI,CAeN;AAOD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EAAE,GACd,IAAI,CAaN"}
|