@pleaseai/ask 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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 +2 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +2 -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
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { consola } from 'consola';
|
|
2
|
+
import { maxSatisfying, validRange } from 'semver';
|
|
3
|
+
import { parseRepoUrl } from './utils.js';
|
|
4
|
+
const RE_SEMVER_RANGE_CHARS = /[~^>=<|]/g;
|
|
5
|
+
/**
|
|
6
|
+
* Resolve an npm package to a GitHub repo + git tag.
|
|
7
|
+
*
|
|
8
|
+
* 1. Fetch `https://registry.npmjs.org/<name>`
|
|
9
|
+
* 2. Resolve version: dist-tag → exact, semver range → best match, exact → passthrough
|
|
10
|
+
* 3. Extract `repository.url` → `owner/repo`
|
|
11
|
+
* 4. Return `v{version}` as the git ref
|
|
12
|
+
*/
|
|
13
|
+
export class NpmResolver {
|
|
14
|
+
async resolve(name, version) {
|
|
15
|
+
const url = `https://registry.npmjs.org/${name}`;
|
|
16
|
+
const response = await fetch(url);
|
|
17
|
+
if (!response.ok) {
|
|
18
|
+
throw new Error(`npm registry returned ${response.status} for ${name}`);
|
|
19
|
+
}
|
|
20
|
+
const meta = await response.json();
|
|
21
|
+
const distTags = meta['dist-tags'] ?? {};
|
|
22
|
+
const allVersions = meta.versions ? Object.keys(meta.versions) : [];
|
|
23
|
+
// Resolve version: dist-tag → semver range → exact
|
|
24
|
+
let resolvedVersion;
|
|
25
|
+
if (distTags[version]) {
|
|
26
|
+
// dist-tag (e.g. 'latest', 'canary')
|
|
27
|
+
resolvedVersion = distTags[version];
|
|
28
|
+
}
|
|
29
|
+
else if (validRange(version) && version !== version.replace(RE_SEMVER_RANGE_CHARS, '')) {
|
|
30
|
+
// Semver range (e.g. '^15', '~3.22', '>=18.0.0')
|
|
31
|
+
const best = maxSatisfying(allVersions, version);
|
|
32
|
+
if (!best) {
|
|
33
|
+
throw new Error(`No version matching '${version}' found for npm package '${name}'. `
|
|
34
|
+
+ `Available dist-tags: ${Object.keys(distTags).join(', ')}`);
|
|
35
|
+
}
|
|
36
|
+
resolvedVersion = best;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
// Exact version string
|
|
40
|
+
resolvedVersion = version;
|
|
41
|
+
}
|
|
42
|
+
// Verify the resolved version exists
|
|
43
|
+
if (allVersions.length > 0 && !allVersions.includes(resolvedVersion)) {
|
|
44
|
+
throw new Error(`Version '${resolvedVersion}' not found for npm package '${name}'. `
|
|
45
|
+
+ `Available dist-tags: ${Object.keys(distTags).join(', ')}`);
|
|
46
|
+
}
|
|
47
|
+
// Extract repository URL
|
|
48
|
+
const repoField = meta.repository;
|
|
49
|
+
const repoUrl = typeof repoField === 'string'
|
|
50
|
+
? repoField
|
|
51
|
+
: repoField?.url;
|
|
52
|
+
const repo = parseRepoUrl(repoUrl);
|
|
53
|
+
if (!repo) {
|
|
54
|
+
throw new Error(`Cannot resolve GitHub repository for npm package '${name}'. `
|
|
55
|
+
+ `The 'repository' field is missing or not a GitHub URL. `
|
|
56
|
+
+ `Use 'owner/repo' format instead: ask docs add owner/repo`);
|
|
57
|
+
}
|
|
58
|
+
consola.debug(`npm: ${name}@${version} → ${repo}@${resolvedVersion}`);
|
|
59
|
+
return {
|
|
60
|
+
repo,
|
|
61
|
+
ref: `v${resolvedVersion}`,
|
|
62
|
+
fallbackRefs: [resolvedVersion],
|
|
63
|
+
resolvedVersion,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=npm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npm.js","sourceRoot":"","sources":["../../src/resolvers/npm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { EcosystemResolver, ResolveResult } from './index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve a pub.dev package to a GitHub repo + git tag.
|
|
4
|
+
*
|
|
5
|
+
* 1. Fetch `https://pub.dev/api/packages/<name>`
|
|
6
|
+
* 2. If version is explicit, verify it exists
|
|
7
|
+
* 3. Extract `latest.pubspec.repository` → `owner/repo`
|
|
8
|
+
* 4. Use the version as the git ref
|
|
9
|
+
*/
|
|
10
|
+
export declare class PubResolver implements EcosystemResolver {
|
|
11
|
+
resolve(name: string, version: string): Promise<ResolveResult>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=pub.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pub.d.ts","sourceRoot":"","sources":["../../src/resolvers/pub.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAkBlE;;;;;;;GAOG;AACH,qBAAa,WAAY,YAAW,iBAAiB;IAC7C,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;CA8CrE"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { consola } from 'consola';
|
|
2
|
+
import { parseRepoUrl } from './utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* Resolve a pub.dev package to a GitHub repo + git tag.
|
|
5
|
+
*
|
|
6
|
+
* 1. Fetch `https://pub.dev/api/packages/<name>`
|
|
7
|
+
* 2. If version is explicit, verify it exists
|
|
8
|
+
* 3. Extract `latest.pubspec.repository` → `owner/repo`
|
|
9
|
+
* 4. Use the version as the git ref
|
|
10
|
+
*/
|
|
11
|
+
export class PubResolver {
|
|
12
|
+
async resolve(name, version) {
|
|
13
|
+
const url = `https://pub.dev/api/packages/${name}`;
|
|
14
|
+
const response = await fetch(url);
|
|
15
|
+
if (!response.ok) {
|
|
16
|
+
throw new Error(`pub.dev returned ${response.status} for ${name}`);
|
|
17
|
+
}
|
|
18
|
+
const meta = await response.json();
|
|
19
|
+
const latestVersion = meta.latest.version;
|
|
20
|
+
let resolvedVersion;
|
|
21
|
+
if (version === 'latest') {
|
|
22
|
+
resolvedVersion = latestVersion;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
// Verify the requested version exists
|
|
26
|
+
const allVersions = meta.versions?.map(v => v.version) ?? [];
|
|
27
|
+
if (allVersions.length > 0 && !allVersions.includes(version)) {
|
|
28
|
+
throw new Error(`Version '${version}' not found for pub package '${name}'. `
|
|
29
|
+
+ `Latest version: ${latestVersion}`);
|
|
30
|
+
}
|
|
31
|
+
resolvedVersion = version;
|
|
32
|
+
}
|
|
33
|
+
// Extract repository URL
|
|
34
|
+
const repoUrl = meta.latest.pubspec.repository ?? meta.latest.pubspec.homepage;
|
|
35
|
+
const repo = parseRepoUrl(repoUrl);
|
|
36
|
+
if (!repo) {
|
|
37
|
+
throw new Error(`Cannot resolve GitHub repository for pub package '${name}'. `
|
|
38
|
+
+ `The 'repository' field is missing or not a GitHub URL. `
|
|
39
|
+
+ `Use 'owner/repo' format instead: ask docs add owner/repo`);
|
|
40
|
+
}
|
|
41
|
+
consola.debug(`pub: ${name}@${version} → ${repo}@${resolvedVersion}`);
|
|
42
|
+
return {
|
|
43
|
+
repo,
|
|
44
|
+
ref: resolvedVersion,
|
|
45
|
+
fallbackRefs: [`v${resolvedVersion}`],
|
|
46
|
+
resolvedVersion,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=pub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pub.js","sourceRoot":"","sources":["../../src/resolvers/pub.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAgBzC;;;;;;;GAOG;AACH,MAAM,OAAO,WAAW;IACtB,KAAK,CAAC,OAAO,CAAC,IAAY,EAAE,OAAe;QACzC,MAAM,GAAG,GAAG,gCAAgC,IAAI,EAAE,CAAA;QAClD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;QACjC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,oBAAoB,QAAQ,CAAC,MAAM,QAAQ,IAAI,EAAE,CAAC,CAAA;QACpE,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAoB,CAAA;QACpD,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAA;QAEzC,IAAI,eAAuB,CAAA;QAC3B,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;YACzB,eAAe,GAAG,aAAa,CAAA;QACjC,CAAC;aACI,CAAC;YACJ,sCAAsC;YACtC,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;YAC5D,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC7D,MAAM,IAAI,KAAK,CACb,YAAY,OAAO,gCAAgC,IAAI,KAAK;sBAC1D,mBAAmB,aAAa,EAAE,CACrC,CAAA;YACH,CAAC;YACD,eAAe,GAAG,OAAO,CAAA;QAC3B,CAAC;QAED,yBAAyB;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAA;QAC9E,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;QAClC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CACb,qDAAqD,IAAI,KAAK;kBAC5D,yDAAyD;kBACzD,0DAA0D,CAC7D,CAAA;QACH,CAAC;QAED,OAAO,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI,OAAO,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC,CAAA;QAErE,OAAO;YACL,IAAI;YACJ,GAAG,EAAE,eAAe;YACpB,YAAY,EAAE,CAAC,IAAI,eAAe,EAAE,CAAC;YACrC,eAAe;SAChB,CAAA;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { EcosystemResolver, ResolveResult } from './index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve a PyPI package to a GitHub repo + git tag.
|
|
4
|
+
*
|
|
5
|
+
* 1. Fetch `https://pypi.org/pypi/<name>/json` (or `<name>/<version>/json`)
|
|
6
|
+
* 2. Extract `info.project_urls` → find a GitHub URL
|
|
7
|
+
* 3. Use the PyPI version as the git ref
|
|
8
|
+
*/
|
|
9
|
+
export declare class PypiResolver implements EcosystemResolver {
|
|
10
|
+
resolve(name: string, version: string): Promise<ResolveResult>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=pypi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pypi.d.ts","sourceRoot":"","sources":["../../src/resolvers/pypi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAyBlE;;;;;;GAMG;AACH,qBAAa,YAAa,YAAW,iBAAiB;IAC9C,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;CAiDrE"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { consola } from 'consola';
|
|
2
|
+
import { parseRepoUrl } from './utils.js';
|
|
3
|
+
/** Keys under `project_urls` most likely to contain a source-code link. */
|
|
4
|
+
const SOURCE_URL_KEYS = [
|
|
5
|
+
'Source',
|
|
6
|
+
'Source Code',
|
|
7
|
+
'Repository',
|
|
8
|
+
'GitHub',
|
|
9
|
+
'Code',
|
|
10
|
+
'Homepage',
|
|
11
|
+
];
|
|
12
|
+
/**
|
|
13
|
+
* Resolve a PyPI package to a GitHub repo + git tag.
|
|
14
|
+
*
|
|
15
|
+
* 1. Fetch `https://pypi.org/pypi/<name>/json` (or `<name>/<version>/json`)
|
|
16
|
+
* 2. Extract `info.project_urls` → find a GitHub URL
|
|
17
|
+
* 3. Use the PyPI version as the git ref
|
|
18
|
+
*/
|
|
19
|
+
export class PypiResolver {
|
|
20
|
+
async resolve(name, version) {
|
|
21
|
+
const isExplicit = version !== 'latest';
|
|
22
|
+
const url = isExplicit
|
|
23
|
+
? `https://pypi.org/pypi/${name}/${version}/json`
|
|
24
|
+
: `https://pypi.org/pypi/${name}/json`;
|
|
25
|
+
const response = await fetch(url);
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
throw new Error(`PyPI returned ${response.status} for ${name}${isExplicit ? `@${version}` : ''}`);
|
|
28
|
+
}
|
|
29
|
+
const meta = await response.json();
|
|
30
|
+
const resolvedVersion = meta.info.version;
|
|
31
|
+
// Find GitHub URL from project_urls
|
|
32
|
+
const projectUrls = meta.info.project_urls ?? {};
|
|
33
|
+
let repoUrl = null;
|
|
34
|
+
for (const key of SOURCE_URL_KEYS) {
|
|
35
|
+
const candidate = projectUrls[key];
|
|
36
|
+
if (candidate && candidate.includes('github.com')) {
|
|
37
|
+
repoUrl = candidate;
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Fall back to home_page
|
|
42
|
+
if (!repoUrl && meta.info.home_page?.includes('github.com')) {
|
|
43
|
+
repoUrl = meta.info.home_page;
|
|
44
|
+
}
|
|
45
|
+
const repo = parseRepoUrl(repoUrl);
|
|
46
|
+
if (!repo) {
|
|
47
|
+
throw new Error(`Cannot resolve GitHub repository for PyPI package '${name}'. `
|
|
48
|
+
+ `The 'project_urls' field does not contain a GitHub URL. `
|
|
49
|
+
+ `Use 'owner/repo' format instead: ask docs add owner/repo`);
|
|
50
|
+
}
|
|
51
|
+
consola.debug(`pypi: ${name}@${version} → ${repo}@${resolvedVersion}`);
|
|
52
|
+
return {
|
|
53
|
+
repo,
|
|
54
|
+
ref: `v${resolvedVersion}`,
|
|
55
|
+
fallbackRefs: [resolvedVersion],
|
|
56
|
+
resolvedVersion,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=pypi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pypi.js","sourceRoot":"","sources":["../../src/resolvers/pypi.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAazC,2EAA2E;AAC3E,MAAM,eAAe,GAAG;IACtB,QAAQ;IACR,aAAa;IACb,YAAY;IACZ,QAAQ;IACR,MAAM;IACN,UAAU;CACX,CAAA;AAED;;;;;;GAMG;AACH,MAAM,OAAO,YAAY;IACvB,KAAK,CAAC,OAAO,CAAC,IAAY,EAAE,OAAe;QACzC,MAAM,UAAU,GAAG,OAAO,KAAK,QAAQ,CAAA;QACvC,MAAM,GAAG,GAAG,UAAU;YACpB,CAAC,CAAC,yBAAyB,IAAI,IAAI,OAAO,OAAO;YACjD,CAAC,CAAC,yBAAyB,IAAI,OAAO,CAAA;QAExC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;QACjC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,iBAAiB,QAAQ,CAAC,MAAM,QAAQ,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QACnG,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAqB,CAAA;QACrD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAA;QAEzC,oCAAoC;QACpC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,CAAA;QAChD,IAAI,OAAO,GAAkB,IAAI,CAAA;QAEjC,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YAClC,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,CAAC,CAAA;YAClC,IAAI,SAAS,IAAI,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBAClD,OAAO,GAAG,SAAS,CAAA;gBACnB,MAAK;YACP,CAAC;QACH,CAAC;QAED,yBAAyB;QACzB,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YAC5D,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAA;QAC/B,CAAC;QAED,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;QAClC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CACb,sDAAsD,IAAI,KAAK;kBAC7D,0DAA0D;kBAC1D,0DAA0D,CAC7D,CAAA;QACH,CAAC;QAED,OAAO,CAAC,KAAK,CAAC,SAAS,IAAI,IAAI,OAAO,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC,CAAA;QAEtE,OAAO;YACL,IAAI;YACJ,GAAG,EAAE,IAAI,eAAe,EAAE;YAC1B,YAAY,EAAE,CAAC,eAAe,CAAC;YAC/B,eAAe;SAChB,CAAA;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a repository URL into `owner/repo` form.
|
|
3
|
+
*
|
|
4
|
+
* Handles common formats:
|
|
5
|
+
* - `git+https://github.com/owner/repo.git`
|
|
6
|
+
* - `https://github.com/owner/repo`
|
|
7
|
+
* - `git://github.com/owner/repo.git`
|
|
8
|
+
* - `ssh://git@github.com/owner/repo.git`
|
|
9
|
+
* - `github.com/owner/repo`
|
|
10
|
+
* - URLs with extra path segments (`/tree/main`, etc.)
|
|
11
|
+
*
|
|
12
|
+
* Returns `null` for non-GitHub URLs, empty strings, or undefined.
|
|
13
|
+
*/
|
|
14
|
+
export declare function parseRepoUrl(url: string | undefined | null): string | null;
|
|
15
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/resolvers/utils.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAW1E"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const RE_GITHUB_URL = /github\.com[/:]([^/]+)\/([^/#?\s]+)/;
|
|
2
|
+
const RE_DOT_GIT = /\.git$/;
|
|
3
|
+
/**
|
|
4
|
+
* Parse a repository URL into `owner/repo` form.
|
|
5
|
+
*
|
|
6
|
+
* Handles common formats:
|
|
7
|
+
* - `git+https://github.com/owner/repo.git`
|
|
8
|
+
* - `https://github.com/owner/repo`
|
|
9
|
+
* - `git://github.com/owner/repo.git`
|
|
10
|
+
* - `ssh://git@github.com/owner/repo.git`
|
|
11
|
+
* - `github.com/owner/repo`
|
|
12
|
+
* - URLs with extra path segments (`/tree/main`, etc.)
|
|
13
|
+
*
|
|
14
|
+
* Returns `null` for non-GitHub URLs, empty strings, or undefined.
|
|
15
|
+
*/
|
|
16
|
+
export function parseRepoUrl(url) {
|
|
17
|
+
if (!url)
|
|
18
|
+
return null;
|
|
19
|
+
const match = RE_GITHUB_URL.exec(url);
|
|
20
|
+
if (!match)
|
|
21
|
+
return null;
|
|
22
|
+
const owner = match[1];
|
|
23
|
+
const repo = match[2].replace(RE_DOT_GIT, '');
|
|
24
|
+
return `${owner}/${repo}`;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/resolvers/utils.ts"],"names":[],"mappings":"AAAA,MAAM,aAAa,GAAG,qCAAqC,CAAA;AAC3D,MAAM,UAAU,GAAG,QAAQ,CAAA;AAE3B;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAC,GAA8B;IACzD,IAAI,CAAC,GAAG;QACN,OAAO,IAAI,CAAA;IAEb,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACrC,IAAI,CAAC,KAAK;QACR,OAAO,IAAI,CAAA;IAEb,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;IACtB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;IAC7C,OAAO,GAAG,KAAK,IAAI,IAAI,EAAE,CAAA;AAC3B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAA"}
|
package/dist/schemas.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAA"}
|
package/dist/skill.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function getSkillDir(projectDir: string, name: string): string;
|
|
2
|
+
export declare function generateSkill(projectDir: string, name: string, version: string, fileList: string[]): string;
|
|
3
|
+
export declare function removeSkill(projectDir: string, name: string): void;
|
|
4
|
+
//# sourceMappingURL=skill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAIA,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAAE,GACjB,MAAM,CA+CR;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAKlE"}
|
package/dist/skill.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { getLibraryDocsDir } from './storage.js';
|
|
4
|
+
export function getSkillDir(projectDir, name) {
|
|
5
|
+
return path.join(projectDir, '.claude', 'skills', `${name}-docs`);
|
|
6
|
+
}
|
|
7
|
+
export function generateSkill(projectDir, name, version, fileList) {
|
|
8
|
+
const skillDir = getSkillDir(projectDir, name);
|
|
9
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
10
|
+
const docsRelPath = path.relative(projectDir, getLibraryDocsDir(projectDir, name, version));
|
|
11
|
+
const toc = fileList
|
|
12
|
+
.filter(f => f !== 'INDEX.md')
|
|
13
|
+
.map(f => `- \`${docsRelPath}/${f}\``)
|
|
14
|
+
.join('\n');
|
|
15
|
+
const major = version.split('.')[0];
|
|
16
|
+
const content = `---
|
|
17
|
+
name: ${name}-docs
|
|
18
|
+
description: ${name} v${version} documentation reference. TRIGGER when writing or modifying code that imports or uses ${name}.
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# ${name} v${version} Documentation
|
|
22
|
+
|
|
23
|
+
This project uses **${name} v${version}**.
|
|
24
|
+
The APIs and patterns may differ from your training data.
|
|
25
|
+
**Read the relevant docs before writing any code.**
|
|
26
|
+
|
|
27
|
+
## Version
|
|
28
|
+
- Current: \`${version}\`
|
|
29
|
+
- In package.json, use \`"^${major}"\` (NOT older major versions)
|
|
30
|
+
|
|
31
|
+
## Documentation Location
|
|
32
|
+
\`${docsRelPath}/\`
|
|
33
|
+
|
|
34
|
+
## Available Guides
|
|
35
|
+
${toc}
|
|
36
|
+
|
|
37
|
+
## Instructions
|
|
38
|
+
1. Before writing any ${name}-related code, read the relevant guide in \`${docsRelPath}/\`
|
|
39
|
+
2. Heed deprecation notices and breaking changes
|
|
40
|
+
3. Prefer patterns shown in the documentation over patterns from training data
|
|
41
|
+
4. When adding ${name} to package.json, use version \`"^${major}"\`
|
|
42
|
+
`;
|
|
43
|
+
const skillPath = path.join(skillDir, 'SKILL.md');
|
|
44
|
+
fs.writeFileSync(skillPath, content, 'utf-8');
|
|
45
|
+
return skillPath;
|
|
46
|
+
}
|
|
47
|
+
export function removeSkill(projectDir, name) {
|
|
48
|
+
const skillDir = getSkillDir(projectDir, name);
|
|
49
|
+
if (fs.existsSync(skillDir)) {
|
|
50
|
+
fs.rmSync(skillDir, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.js","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAEhD,MAAM,UAAU,WAAW,CAAC,UAAkB,EAAE,IAAY;IAC1D,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,OAAO,CAAC,CAAA;AACnE,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,UAAkB,EAClB,IAAY,EACZ,OAAe,EACf,QAAkB;IAElB,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;IAC9C,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAE3C,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAC/B,UAAU,EACV,iBAAiB,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAC7C,CAAA;IAED,MAAM,GAAG,GAAG,QAAQ;SACjB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,UAAU,CAAC;SAC7B,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,WAAW,IAAI,CAAC,IAAI,CAAC;SACrC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEb,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IAEnC,MAAM,OAAO,GAAG;QACV,IAAI;eACG,IAAI,KAAK,OAAO,yFAAyF,IAAI;;;IAGxH,IAAI,KAAK,OAAO;;sBAEE,IAAI,KAAK,OAAO;;;;;eAKvB,OAAO;6BACO,KAAK;;;IAG9B,WAAW;;;EAGb,GAAG;;;wBAGmB,IAAI,+CAA+C,WAAW;;;iBAGrE,IAAI,qCAAqC,KAAK;CAC9D,CAAA;IAEC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IACjD,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IAC7C,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,UAAkB,EAAE,IAAY;IAC1D,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;IAC9C,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC1C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DocSource, FetchResult, SourceConfig } from './index.js';
|
|
2
|
+
export declare class GithubSource implements DocSource {
|
|
3
|
+
fetch(options: SourceConfig): Promise<FetchResult>;
|
|
4
|
+
private detectDocsPath;
|
|
5
|
+
private collectDocFiles;
|
|
6
|
+
/**
|
|
7
|
+
* Resolve a ref (tag or branch) to a full commit sha via `git ls-remote`.
|
|
8
|
+
* Returns undefined when git is unavailable or the ref cannot be resolved
|
|
9
|
+
* — the lockfile leaves `commit` undefined rather than guessing.
|
|
10
|
+
*/
|
|
11
|
+
private resolveCommit;
|
|
12
|
+
private isDocFile;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=github.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/sources/github.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EACT,WAAW,EAEX,YAAY,EACb,MAAM,YAAY,CAAA;AAWnB,qBAAa,YAAa,YAAW,SAAS;IACtC,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IA4DxD,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,eAAe;IAmBvB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,SAAS;CAIlB"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { execFileSync, execSync } from 'node:child_process';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { consola } from 'consola';
|
|
6
|
+
const RE_LEADING_V = /^v/;
|
|
7
|
+
const RE_SHA40 = /^[0-9a-f]{40}$/;
|
|
8
|
+
const RE_WHITESPACE = /\s+/;
|
|
9
|
+
export class GithubSource {
|
|
10
|
+
async fetch(options) {
|
|
11
|
+
const opts = options;
|
|
12
|
+
const { repo, docsPath } = opts;
|
|
13
|
+
const ref = opts.tag ?? opts.branch ?? 'main';
|
|
14
|
+
// Resolve the ref to get the actual version (strip leading "v" from tags)
|
|
15
|
+
const tagVersion = opts.tag?.replace(RE_LEADING_V, '');
|
|
16
|
+
const resolvedVersion = tagVersion ?? opts.version;
|
|
17
|
+
// Download repo archive and extract docs
|
|
18
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ask-gh-'));
|
|
19
|
+
try {
|
|
20
|
+
const archiveUrl = `https://github.com/${repo}/archive/refs/${opts.tag ? 'tags' : 'heads'}/${ref}.tar.gz`;
|
|
21
|
+
execSync(`curl -sL "${archiveUrl}" | tar xz -C "${tmpDir}"`, {
|
|
22
|
+
encoding: 'utf-8',
|
|
23
|
+
});
|
|
24
|
+
// Find extracted directory (format: reponame-ref)
|
|
25
|
+
const extractedDirs = fs.readdirSync(tmpDir);
|
|
26
|
+
if (extractedDirs.length === 0) {
|
|
27
|
+
throw new Error(`Failed to extract archive from ${repo}@${ref}`);
|
|
28
|
+
}
|
|
29
|
+
const extractedDir = path.join(tmpDir, extractedDirs[0]);
|
|
30
|
+
// Find docs
|
|
31
|
+
const targetPath = docsPath ?? this.detectDocsPath(extractedDir);
|
|
32
|
+
if (!targetPath) {
|
|
33
|
+
throw new Error(`No docs directory found in ${repo}@${ref}. Specify --path to point to the docs directory.`);
|
|
34
|
+
}
|
|
35
|
+
const docsDir = path.join(extractedDir, targetPath);
|
|
36
|
+
if (!fs.existsSync(docsDir)) {
|
|
37
|
+
throw new Error(`Path "${targetPath}" not found in ${repo}@${ref}`);
|
|
38
|
+
}
|
|
39
|
+
let files;
|
|
40
|
+
if (fs.statSync(docsDir).isFile()) {
|
|
41
|
+
// Single file specified
|
|
42
|
+
const content = fs.readFileSync(docsDir, 'utf-8');
|
|
43
|
+
files = [{ path: path.basename(docsDir), content }];
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
files = this.collectDocFiles(docsDir, docsDir);
|
|
47
|
+
}
|
|
48
|
+
const commit = this.resolveCommit(repo, ref);
|
|
49
|
+
return {
|
|
50
|
+
files,
|
|
51
|
+
resolvedVersion,
|
|
52
|
+
meta: { commit, ref },
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
detectDocsPath(dir) {
|
|
60
|
+
const candidates = ['docs', 'doc', 'documentation', 'guide', 'guides'];
|
|
61
|
+
for (const candidate of candidates) {
|
|
62
|
+
const fullPath = path.join(dir, candidate);
|
|
63
|
+
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isDirectory()) {
|
|
64
|
+
return candidate;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
collectDocFiles(baseDir, currentDir) {
|
|
70
|
+
const files = [];
|
|
71
|
+
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
72
|
+
for (const entry of entries) {
|
|
73
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
74
|
+
if (entry.isDirectory()) {
|
|
75
|
+
files.push(...this.collectDocFiles(baseDir, fullPath));
|
|
76
|
+
}
|
|
77
|
+
else if (this.isDocFile(entry.name)) {
|
|
78
|
+
const relativePath = path.relative(baseDir, fullPath);
|
|
79
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
80
|
+
files.push({ path: relativePath, content });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return files;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Resolve a ref (tag or branch) to a full commit sha via `git ls-remote`.
|
|
87
|
+
* Returns undefined when git is unavailable or the ref cannot be resolved
|
|
88
|
+
* — the lockfile leaves `commit` undefined rather than guessing.
|
|
89
|
+
*/
|
|
90
|
+
resolveCommit(repo, ref) {
|
|
91
|
+
try {
|
|
92
|
+
// execFileSync (not execSync) to bypass the shell — `ref` originates
|
|
93
|
+
// from user-supplied tag/branch and must not be interpolated into a
|
|
94
|
+
// shell command line.
|
|
95
|
+
const out = execFileSync('git', ['ls-remote', `https://github.com/${repo}.git`, ref], { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
|
|
96
|
+
// ls-remote may return multiple lines (e.g. tag + ^{} dereference).
|
|
97
|
+
// Prefer the dereferenced commit if present.
|
|
98
|
+
const lines = out.split('\n').filter(Boolean);
|
|
99
|
+
const dereferenced = lines.find(l => l.includes(`refs/tags/${ref}^{}`));
|
|
100
|
+
const sha = (dereferenced ?? lines[0])?.split(RE_WHITESPACE)[0];
|
|
101
|
+
return sha && RE_SHA40.test(sha) ? sha : undefined;
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
consola.warn(`Could not resolve commit for ${repo}@${ref}: ${err instanceof Error ? err.message : err}. `
|
|
105
|
+
+ 'Lockfile will not pin a commit sha for this entry.');
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
isDocFile(filename) {
|
|
110
|
+
const ext = path.extname(filename).toLowerCase();
|
|
111
|
+
return ['.md', '.mdx', '.txt', '.rst'].includes(ext);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/sources/github.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { SourceConfig } from '../schemas.js';
|
|
2
|
+
export type { SourceConfig };
|
|
3
|
+
export type NpmSourceOptions = Extract<SourceConfig, {
|
|
4
|
+
source: 'npm';
|
|
5
|
+
}>;
|
|
6
|
+
export type GithubSourceOptions = Extract<SourceConfig, {
|
|
7
|
+
source: 'github';
|
|
8
|
+
}>;
|
|
9
|
+
export type WebSourceOptions = Extract<SourceConfig, {
|
|
10
|
+
source: 'web';
|
|
11
|
+
}>;
|
|
12
|
+
export type LlmsTxtSourceOptions = Extract<SourceConfig, {
|
|
13
|
+
source: 'llms-txt';
|
|
14
|
+
}>;
|
|
15
|
+
export interface DocFile {
|
|
16
|
+
path: string;
|
|
17
|
+
content: string;
|
|
18
|
+
}
|
|
19
|
+
export interface FetchResult {
|
|
20
|
+
files: DocFile[];
|
|
21
|
+
resolvedVersion: string;
|
|
22
|
+
/** Source-specific metadata propagated to ask.lock */
|
|
23
|
+
meta?: {
|
|
24
|
+
/** GitHub commit sha (40 hex chars) */
|
|
25
|
+
commit?: string;
|
|
26
|
+
/** GitHub ref used (tag name or branch name) */
|
|
27
|
+
ref?: string;
|
|
28
|
+
/** npm Subresource Integrity hash from dist.integrity */
|
|
29
|
+
integrity?: string;
|
|
30
|
+
/** npm tarball URL */
|
|
31
|
+
tarball?: string;
|
|
32
|
+
/** web/llms-txt source URL(s) */
|
|
33
|
+
urls?: string[];
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export interface DocSource {
|
|
37
|
+
fetch: (options: SourceConfig) => Promise<FetchResult>;
|
|
38
|
+
}
|
|
39
|
+
type SourceKind = SourceConfig['source'];
|
|
40
|
+
export declare function getSource(type: SourceKind): DocSource;
|
|
41
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sources/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAMjD,YAAY,EAAE,YAAY,EAAE,CAAA;AAM5B,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,YAAY,EAAE;IAAE,MAAM,EAAE,KAAK,CAAA;CAAE,CAAC,CAAA;AACvE,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,YAAY,EAAE;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAA;AAC7E,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,YAAY,EAAE;IAAE,MAAM,EAAE,KAAK,CAAA;CAAE,CAAC,CAAA;AACvE,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,YAAY,EAAE;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC,CAAA;AAEhF,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,OAAO,EAAE,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;IACvB,sDAAsD;IACtD,IAAI,CAAC,EAAE;QACL,uCAAuC;QACvC,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,gDAAgD;QAChD,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,yDAAyD;QACzD,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,sBAAsB;QACtB,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,iCAAiC;QACjC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAChB,CAAA;CACF;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,WAAW,CAAC,CAAA;CACvD;AAED,KAAK,UAAU,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAA;AASxC,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,CAErD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { GithubSource } from './github.js';
|
|
2
|
+
import { LlmsTxtSource } from './llms-txt.js';
|
|
3
|
+
import { NpmSource } from './npm.js';
|
|
4
|
+
import { WebSource } from './web.js';
|
|
5
|
+
const sources = {
|
|
6
|
+
'npm': new NpmSource(),
|
|
7
|
+
'github': new GithubSource(),
|
|
8
|
+
'web': new WebSource(),
|
|
9
|
+
'llms-txt': new LlmsTxtSource(),
|
|
10
|
+
};
|
|
11
|
+
export function getSource(type) {
|
|
12
|
+
return sources[type];
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sources/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AA0CpC,MAAM,OAAO,GAAkC;IAC7C,KAAK,EAAE,IAAI,SAAS,EAAE;IACtB,QAAQ,EAAE,IAAI,YAAY,EAAE;IAC5B,KAAK,EAAE,IAAI,SAAS,EAAE;IACtB,UAAU,EAAE,IAAI,aAAa,EAAE;CAChC,CAAA;AAED,MAAM,UAAU,SAAS,CAAC,IAAgB;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAA;AACtB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llms-txt.d.ts","sourceRoot":"","sources":["../../src/sources/llms-txt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EAEX,YAAY,EACb,MAAM,YAAY,CAAA;AAGnB,qBAAa,aAAc,YAAW,SAAS;IACvC,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;CAqCzD"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { consola } from 'consola';
|
|
2
|
+
export class LlmsTxtSource {
|
|
3
|
+
async fetch(options) {
|
|
4
|
+
const opts = options;
|
|
5
|
+
const url = opts.url;
|
|
6
|
+
consola.info(` Fetching: ${url}`);
|
|
7
|
+
const response = await fetch(url, {
|
|
8
|
+
headers: {
|
|
9
|
+
'User-Agent': 'ask-docs/0.1 (documentation downloader)',
|
|
10
|
+
'Accept': 'text/plain, text/markdown',
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
if (!response.ok) {
|
|
14
|
+
throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
|
|
15
|
+
}
|
|
16
|
+
const content = await response.text();
|
|
17
|
+
if (content.trim().length === 0) {
|
|
18
|
+
throw new Error(`No content found at ${url}`);
|
|
19
|
+
}
|
|
20
|
+
// Determine filename from URL path
|
|
21
|
+
const urlObj = new URL(url);
|
|
22
|
+
const filename = urlObj.pathname.split('/').pop() || 'llms.txt';
|
|
23
|
+
const filePath = filename.endsWith('.md') || filename.endsWith('.txt')
|
|
24
|
+
? filename
|
|
25
|
+
: `${filename}.md`;
|
|
26
|
+
consola.info(` Fetched: ${url} -> ${filePath} (${content.length} chars)`);
|
|
27
|
+
return {
|
|
28
|
+
files: [{ path: filePath, content }],
|
|
29
|
+
resolvedVersion: opts.version,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=llms-txt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llms-txt.js","sourceRoot":"","sources":["../../src/sources/llms-txt.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEjC,MAAM,OAAO,aAAa;IACxB,KAAK,CAAC,KAAK,CAAC,OAAqB;QAC/B,MAAM,IAAI,GAAG,OAA+B,CAAA;QAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAA;QAEpB,OAAO,CAAC,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC,CAAA;QAElC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,OAAO,EAAE;gBACP,YAAY,EAAE,yCAAyC;gBACvD,QAAQ,EAAE,2BAA2B;aACtC;SACF,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,mBAAmB,GAAG,KAAK,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;QACtF,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QAErC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,uBAAuB,GAAG,EAAE,CAAC,CAAA;QAC/C,CAAC;QAED,mCAAmC;QACnC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QAC3B,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,UAAU,CAAA;QAC/D,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;YACpE,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,GAAG,QAAQ,KAAK,CAAA;QAEpB,OAAO,CAAC,IAAI,CAAC,cAAc,GAAG,OAAO,QAAQ,KAAK,OAAO,CAAC,MAAM,SAAS,CAAC,CAAA;QAE1E,OAAO;YACL,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;YACpC,eAAe,EAAE,IAAI,CAAC,OAAO;SAC9B,CAAA;IACH,CAAC;CACF"}
|