refactor(skill): streamline Xget skill documentation and remove deprecated test cases

This commit is contained in:
xixu-me committed 2026-03-15 17:42:45 +08:00
1 parent ba9d2f6224
commit 11a032f243
4 files changed
+24 -98

No files matched your search

+6 -12
View File
@@ -6,8 +6,6 @@ description:
self-hosted Xget instance. Use this skill when a task involves Xget URL
rewriting, registry acceleration, proxy base URLs, self-hosting, or choosing
the correct Xget prefix for Git, packages, OCI images, or inference APIs.
Prefer the user's own Xget domain; treat the public demo as a last-resort
fallback.
license: GPL-3.0-or-later
compatibility:
Requires network access to refresh the live platform map. Optional Node.js 18+
@@ -17,10 +15,7 @@ allowed-tools: Bash(node:*) Bash(curl:*) Read
# Xget
Use this skill for Xget-specific tasks only. Default to the user's self-hosted
Xget domain or an explicit internal instance. Do not default to
`https://xget.xi-xu.me` unless the user explicitly wants the public demo or no
self-hosted option exists.
Use this skill for Xget-specific tasks only.
## Defaults
@@ -29,10 +24,8 @@ self-hosted option exists.
- `XGET_BASE_URL` from the environment
- if neither exists and the task is not just writing docs, ask the user for
their self-hosted Xget domain and configure `XGET_BASE_URL`
- `https://xget.example.com` only for docs or templates when a real domain is
not available yet
- `https://xget.xi-xu.me` only as an explicitly labeled fallback after the
user declines or cannot provide a self-hosted domain
- `https://xget.example.com` only as a placeholder in docs or templates when
a real domain is not available yet
2. Keep platform data fresh. Do not hardcode the full prefix list from memory.
Run:
@@ -97,5 +90,6 @@ node scripts/xget.mjs platforms --format table
Report that no current Xget mapping was found.
- The default pip snippet should omit `trusted-host`; add it only when the
deployment really needs it and keep it aligned with the actual host.
- When generating docs or templates without a real domain, prefer
`https://xget.example.com` over the public demo.
- When generating docs or templates without a real domain, use
`https://xget.example.com` as a clearly labeled placeholder rather than a
default instance.
+3 -5
View File
@@ -6,12 +6,10 @@ Use these defaults in order:
1. User-provided Xget base URL
2. `XGET_BASE_URL` from the environment
3. `https://xget.example.com` only for templates and docs
4. `https://xget.xi-xu.me` only as a clearly labeled public-demo fallback
3. `https://xget.example.com` only as a placeholder in templates and docs
The Xget README explicitly labels `xget.xi-xu.me` as a pre-deployed instance
with no reliability guarantee, while the self-hosting docs and DigitalOcean
guide show recommended self-hosted domains such as `xget.example.com`.
This skill should not surface or assume a public demo domain. Prefer
self-hosted guidance and custom-domain examples such as `xget.example.com`.
## Live platform source
+15 -4
View File
@@ -8,6 +8,7 @@ import vm from 'node:vm';
const DEFAULT_SOURCE_URL = 'https://raw.gitcode.com/xixu-me/xget/raw/main/src/config/platforms.js';
const DEFAULT_BASE_PLACEHOLDER = 'https://xget.example.com';
const MISSING_BASE_URL_HINT = `Missing --base-url and XGET_BASE_URL. For docs, use ${DEFAULT_BASE_PLACEHOLDER}.`;
const CRATES_API_PREFIX = '/api/v1/crates';
@@ -245,6 +246,16 @@ function normalizeBaseUrl(value) {
}
}
/**
* Resolve an explicit or environment-provided base URL without inventing a fallback instance.
* @param {string | undefined} optionValue
* @param {string | undefined} envValue
* @returns {string | null}
*/
export function resolveBaseUrl(optionValue, envValue) {
return normalizeBaseUrl(optionValue ?? envValue);
}
/**
* @param {string} value
* @param {string} flagName
@@ -590,8 +601,8 @@ async function main() {
if (command === 'convert') {
const baseUrl =
normalizeBaseUrl(getStringOption(options, 'base-url') ?? process.env.XGET_BASE_URL) ??
fail(`Missing --base-url and XGET_BASE_URL. For docs, use ${DEFAULT_BASE_PLACEHOLDER}.`, 2);
resolveBaseUrl(getStringOption(options, 'base-url'), process.env.XGET_BASE_URL) ??
fail(MISSING_BASE_URL_HINT, 2);
const rawUrl = getStringOption(options, 'url');
if (!rawUrl) {
@@ -630,8 +641,8 @@ async function main() {
if (command === 'snippet') {
const baseUrl =
normalizeBaseUrl(getStringOption(options, 'base-url') ?? process.env.XGET_BASE_URL) ??
fail(`Missing --base-url and XGET_BASE_URL. For docs, use ${DEFAULT_BASE_PLACEHOLDER}.`, 2);
resolveBaseUrl(getStringOption(options, 'base-url'), process.env.XGET_BASE_URL) ??
fail(MISSING_BASE_URL_HINT, 2);
const preset = getStringOption(options, 'preset');
if (!preset) {
-77
View File
@@ -1,77 +0,0 @@
import { describe, expect, it } from 'vitest';
import { PLATFORMS } from '../../src/config/platforms.js';
import {
buildConvertedUrl,
createPlatformEntries,
createSnippet,
findPlatformForUrl
} from '../../skills/xget/scripts/xget.mjs';
const BASE_URL = 'https://xget.example.com';
const platforms = createPlatformEntries(PLATFORMS);
/**
* Convert an upstream URL with the xget skill helpers.
* @param {string} url
* @returns {{ platform: { key: string } | null, convertedUrl: string | null }} Converted result.
*/
function convert(url) {
const upstreamUrl = new URL(url);
const platform = findPlatformForUrl(platforms, upstreamUrl);
return {
platform,
convertedUrl: platform ? buildConvertedUrl(BASE_URL, platform, upstreamUrl) : null
};
}
describe('xget skill helpers', () => {
describe('URL conversion', () => {
it('converts Homebrew repository URLs to the homebrew prefix', () => {
const result = convert('https://github.com/Homebrew/homebrew-core/raw/HEAD/Formula/g/git.rb');
expect(result.platform?.key).toBe('homebrew');
expect(result.convertedUrl).toBe(
'https://xget.example.com/homebrew/homebrew-core/raw/HEAD/Formula/g/git.rb'
);
});
it('converts Homebrew API URLs to the homebrew/api prefix', () => {
const result = convert('https://formulae.brew.sh/api/formula/git.json');
expect(result.platform?.key).toBe('homebrew-api');
expect(result.convertedUrl).toBe('https://xget.example.com/homebrew/api/formula/git.json');
});
it('routes Homebrew bottle URLs to homebrew/bottles instead of cr/ghcr', () => {
const result = convert('https://ghcr.io/v2/homebrew/core/git/manifests/2.39.0');
expect(result.platform?.key).toBe('homebrew-bottles');
expect(result.convertedUrl).toBe(
'https://xget.example.com/homebrew/bottles/v2/homebrew/core/git/manifests/2.39.0'
);
});
it('normalizes crates.io API URLs to the documented /crates path shape', () => {
const result = convert('https://crates.io/api/v1/crates/serde/1.0.0/download');
expect(result.platform?.key).toBe('crates');
expect(result.convertedUrl).toBe('https://xget.example.com/crates/serde/1.0.0/download');
});
});
describe('snippets', () => {
it('omits trusted-host from the default pip preset', () => {
const snippet = createSnippet(BASE_URL, 'pip');
expect(snippet.commands).toEqual([
'pip config set global.index-url https://xget.example.com/pypi/simple/',
'pip config list'
]);
expect(snippet.notes).toContain(
'Only add "pip config set global.trusted-host xget.example.com" when the deployment really needs it.'
);
});
});
});