@farming-labs/docs 0.2.61 → 0.2.62
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/package.json +1 -1
- package/dist/agent-DFHlw_JC.mjs +0 -624
- package/dist/agent-Fl0pjVNF.mjs +0 -4352
- package/dist/agent-evals-f4_OL10T.mjs +0 -2144
- package/dist/agent-export-D0zQhasD.mjs +0 -910
- package/dist/agent-scope-C_U--OZ7.mjs +0 -283
- package/dist/agent-skills-bundle.d.mts +0 -13
- package/dist/agent-skills-bundle.mjs +0 -12
- package/dist/agent-skills-server-CIeBszxp.mjs +0 -263
- package/dist/agent-skills-server-CKq3_jMj.d.mts +0 -12
- package/dist/agent-skills-vite.d.mts +0 -31
- package/dist/agent-skills-vite.mjs +0 -70
- package/dist/agents-ibnXrWyp.mjs +0 -221
- package/dist/analytics-Bx44lg6d.mjs +0 -177
- package/dist/cli/index.d.mts +0 -15
- package/dist/cli/index.mjs +0 -452
- package/dist/client/react.d.mts +0 -45
- package/dist/client/react.mjs +0 -223
- package/dist/cloud-analytics-CSyFE6SS.mjs +0 -132
- package/dist/cloud-ask-ai-D7ZgF47y.d.mts +0 -23
- package/dist/cloud-ask-ai-sbpjOR2K.mjs +0 -382
- package/dist/cloud-pdNC-tyj.mjs +0 -1615
- package/dist/code-blocks-DnNVNK2M.mjs +0 -871
- package/dist/codeblocks-CFuurVIH.mjs +0 -250
- package/dist/config-Wcdj-D0a.mjs +0 -369
- package/dist/dev-Cmy6DtdF.mjs +0 -1333
- package/dist/docs-cloud-server.d.mts +0 -70
- package/dist/docs-cloud-server.mjs +0 -310
- package/dist/doctor-CXostbsI.mjs +0 -2036
- package/dist/downgrade-w7e6Se0L.mjs +0 -184
- package/dist/errors-DbOhkE1h.mjs +0 -20
- package/dist/golden-evaluations-CBZ_JZjf.mjs +0 -1498
- package/dist/i18n-CCaFUnAN.mjs +0 -40
- package/dist/index.d.mts +0 -1141
- package/dist/index.mjs +0 -10
- package/dist/init-CQY0Woe3.mjs +0 -1264
- package/dist/mcp-DyPcoLwm.mjs +0 -156
- package/dist/mcp.d.mts +0 -298
- package/dist/mcp.mjs +0 -4426
- package/dist/metadata-Dv1ah0Aj.mjs +0 -237
- package/dist/package-version-n5AFur8a.mjs +0 -128
- package/dist/reading-time-C-SAhQT9.mjs +0 -742
- package/dist/review-D2UBrxFq.mjs +0 -673
- package/dist/robots-5Yqz9mz7.mjs +0 -179
- package/dist/robots-C08kDLsz.mjs +0 -201
- package/dist/search-9OnMGMvt.mjs +0 -1758
- package/dist/search-C6heDO8h.d.mts +0 -274
- package/dist/search-CNsRpz90.mjs +0 -104
- package/dist/server.d.mts +0 -342
- package/dist/server.mjs +0 -13
- package/dist/sitemap-BpYnSsfJ.mjs +0 -249
- package/dist/sitemap-server-D_0Kzanj.mjs +0 -1137
- package/dist/standards-discovery-C4HUqMd2.d.mts +0 -227
- package/dist/standards-discovery-C54V_aJH.mjs +0 -510
- package/dist/templates-Bq_P7ctv.mjs +0 -2465
- package/dist/types-EhFhYGfr.d.mts +0 -3305
- package/dist/upgrade-oz-GChgt.mjs +0 -56
- package/dist/utils-DpiIioYb.mjs +0 -225
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
//#region src/agent-scope.ts
|
|
2
|
-
/** Normalize framework aliases used by page metadata, agent contracts, MCP, and evaluations. */
|
|
3
|
-
function normalizeAgentFramework(value) {
|
|
4
|
-
const normalized = value.toLowerCase().replace(/[^a-z0-9]/gu, "");
|
|
5
|
-
if ([
|
|
6
|
-
"next",
|
|
7
|
-
"nextjs",
|
|
8
|
-
"nextjsapp",
|
|
9
|
-
"reactnext"
|
|
10
|
-
].includes(normalized)) return "nextjs";
|
|
11
|
-
if ([
|
|
12
|
-
"tanstack",
|
|
13
|
-
"tanstackstart",
|
|
14
|
-
"start"
|
|
15
|
-
].includes(normalized)) return "tanstackstart";
|
|
16
|
-
if (["svelte", "sveltekit"].includes(normalized)) return "sveltekit";
|
|
17
|
-
if (["nuxt", "nuxtjs"].includes(normalized)) return "nuxt";
|
|
18
|
-
return normalized;
|
|
19
|
-
}
|
|
20
|
-
function normalizeAgentLocale(value) {
|
|
21
|
-
return value.trim().toLowerCase().replace(/_/gu, "-");
|
|
22
|
-
}
|
|
23
|
-
function normalizeAgentVersion(value) {
|
|
24
|
-
return value.trim().toLowerCase().replace(/^v(?=\d)/u, "");
|
|
25
|
-
}
|
|
26
|
-
function normalizeAgentScopeValues(value) {
|
|
27
|
-
const values = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
|
|
28
|
-
return Array.from(new Set(values.map((item) => item.trim()).filter(Boolean)));
|
|
29
|
-
}
|
|
30
|
-
function compareVersions(left, right) {
|
|
31
|
-
for (let index = 0; index < 3; index += 1) if (left[index] !== right[index]) return left[index] > right[index] ? 1 : -1;
|
|
32
|
-
return 0;
|
|
33
|
-
}
|
|
34
|
-
function parseExactVersion(value) {
|
|
35
|
-
const match = normalizeAgentVersion(value).match(/^(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-[0-9a-z.-]+)?(?:\+[0-9a-z.-]+)?$/iu);
|
|
36
|
-
if (!match) return void 0;
|
|
37
|
-
return [
|
|
38
|
-
Number(match[1]),
|
|
39
|
-
Number(match[2] ?? 0),
|
|
40
|
-
Number(match[3] ?? 0)
|
|
41
|
-
];
|
|
42
|
-
}
|
|
43
|
-
function parseVersionOperand(value) {
|
|
44
|
-
const normalized = normalizeAgentVersion(value);
|
|
45
|
-
if (normalized === "*" || normalized === "x") return {
|
|
46
|
-
version: [
|
|
47
|
-
0,
|
|
48
|
-
0,
|
|
49
|
-
0
|
|
50
|
-
],
|
|
51
|
-
components: 0,
|
|
52
|
-
wildcard: true
|
|
53
|
-
};
|
|
54
|
-
const match = normalized.match(/^(\d+)(?:\.(\d+|x|\*))?(?:\.(\d+|x|\*))?$/iu);
|
|
55
|
-
if (!match) return void 0;
|
|
56
|
-
const raw = [
|
|
57
|
-
match[1],
|
|
58
|
-
match[2],
|
|
59
|
-
match[3]
|
|
60
|
-
];
|
|
61
|
-
const wildcardIndex = raw.findIndex((part, index) => index > 0 && (part?.toLowerCase() === "x" || part === "*"));
|
|
62
|
-
if (wildcardIndex >= 0 && raw.slice(wildcardIndex + 1).some((part) => part && part.toLowerCase() !== "x" && part !== "*")) return;
|
|
63
|
-
const components = wildcardIndex >= 0 ? wildcardIndex : raw.filter(Boolean).length;
|
|
64
|
-
return {
|
|
65
|
-
version: [
|
|
66
|
-
Number(raw[0]),
|
|
67
|
-
Number(raw[1] ?? 0) || 0,
|
|
68
|
-
Number(raw[2] ?? 0) || 0
|
|
69
|
-
],
|
|
70
|
-
components,
|
|
71
|
-
wildcard: wildcardIndex >= 0
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
function nextVersionBoundary(operand) {
|
|
75
|
-
const [major, minor] = operand.version;
|
|
76
|
-
if (operand.components <= 0) return void 0;
|
|
77
|
-
if (operand.components === 1) return [
|
|
78
|
-
major + 1,
|
|
79
|
-
0,
|
|
80
|
-
0
|
|
81
|
-
];
|
|
82
|
-
return [
|
|
83
|
-
major,
|
|
84
|
-
minor + 1,
|
|
85
|
-
0
|
|
86
|
-
];
|
|
87
|
-
}
|
|
88
|
-
function operandRange(operand) {
|
|
89
|
-
if (operand.components === 0) return {
|
|
90
|
-
minimumInclusive: true,
|
|
91
|
-
maximumInclusive: false
|
|
92
|
-
};
|
|
93
|
-
if (operand.components < 3 || operand.wildcard) return {
|
|
94
|
-
minimum: operand.version,
|
|
95
|
-
minimumInclusive: true,
|
|
96
|
-
maximum: nextVersionBoundary(operand),
|
|
97
|
-
maximumInclusive: false
|
|
98
|
-
};
|
|
99
|
-
return {
|
|
100
|
-
minimum: operand.version,
|
|
101
|
-
minimumInclusive: true,
|
|
102
|
-
maximum: operand.version,
|
|
103
|
-
maximumInclusive: true
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
function caretRange(operand) {
|
|
107
|
-
const [major, minor, patch] = operand.version;
|
|
108
|
-
let maximum;
|
|
109
|
-
if (major > 0) maximum = [
|
|
110
|
-
major + 1,
|
|
111
|
-
0,
|
|
112
|
-
0
|
|
113
|
-
];
|
|
114
|
-
else if (operand.components <= 1) maximum = [
|
|
115
|
-
1,
|
|
116
|
-
0,
|
|
117
|
-
0
|
|
118
|
-
];
|
|
119
|
-
else if (minor > 0 || operand.components === 2) maximum = [
|
|
120
|
-
0,
|
|
121
|
-
minor + 1,
|
|
122
|
-
0
|
|
123
|
-
];
|
|
124
|
-
else maximum = [
|
|
125
|
-
0,
|
|
126
|
-
0,
|
|
127
|
-
patch + 1
|
|
128
|
-
];
|
|
129
|
-
return {
|
|
130
|
-
minimum: operand.version,
|
|
131
|
-
minimumInclusive: true,
|
|
132
|
-
maximum,
|
|
133
|
-
maximumInclusive: false
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
function tildeRange(operand) {
|
|
137
|
-
const [major, minor] = operand.version;
|
|
138
|
-
const maximum = operand.components <= 1 ? [
|
|
139
|
-
major + 1,
|
|
140
|
-
0,
|
|
141
|
-
0
|
|
142
|
-
] : [
|
|
143
|
-
major,
|
|
144
|
-
minor + 1,
|
|
145
|
-
0
|
|
146
|
-
];
|
|
147
|
-
return {
|
|
148
|
-
minimum: operand.version,
|
|
149
|
-
minimumInclusive: true,
|
|
150
|
-
maximum,
|
|
151
|
-
maximumInclusive: false
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
function intersectRanges(left, right) {
|
|
155
|
-
let minimum = left.minimum;
|
|
156
|
-
let minimumInclusive = left.minimumInclusive;
|
|
157
|
-
if (!minimum || right.minimum && compareVersions(right.minimum, minimum) > 0) {
|
|
158
|
-
minimum = right.minimum;
|
|
159
|
-
minimumInclusive = right.minimumInclusive;
|
|
160
|
-
} else if (right.minimum && compareVersions(right.minimum, minimum) === 0) minimumInclusive = minimumInclusive && right.minimumInclusive;
|
|
161
|
-
let maximum = left.maximum;
|
|
162
|
-
let maximumInclusive = left.maximumInclusive;
|
|
163
|
-
if (!maximum || right.maximum && compareVersions(right.maximum, maximum) < 0) {
|
|
164
|
-
maximum = right.maximum;
|
|
165
|
-
maximumInclusive = right.maximumInclusive;
|
|
166
|
-
} else if (right.maximum && compareVersions(right.maximum, maximum) === 0) maximumInclusive = maximumInclusive && right.maximumInclusive;
|
|
167
|
-
if (minimum && maximum) {
|
|
168
|
-
const compared = compareVersions(minimum, maximum);
|
|
169
|
-
if (compared > 0 || compared === 0 && !(minimumInclusive && maximumInclusive)) return void 0;
|
|
170
|
-
}
|
|
171
|
-
return {
|
|
172
|
-
minimum,
|
|
173
|
-
minimumInclusive,
|
|
174
|
-
maximum,
|
|
175
|
-
maximumInclusive
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
function comparatorRange(operator, operand) {
|
|
179
|
-
if (!operator || operator === "=") return operandRange(operand);
|
|
180
|
-
if (operator === ">=") return {
|
|
181
|
-
minimum: operand.version,
|
|
182
|
-
minimumInclusive: true,
|
|
183
|
-
maximumInclusive: false
|
|
184
|
-
};
|
|
185
|
-
if (operator === ">") {
|
|
186
|
-
const partialBoundary = operand.components < 3 ? nextVersionBoundary(operand) : void 0;
|
|
187
|
-
return {
|
|
188
|
-
minimum: partialBoundary ?? operand.version,
|
|
189
|
-
minimumInclusive: Boolean(partialBoundary),
|
|
190
|
-
maximumInclusive: false
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
if (operator === "<") return {
|
|
194
|
-
minimumInclusive: true,
|
|
195
|
-
maximum: operand.version,
|
|
196
|
-
maximumInclusive: false
|
|
197
|
-
};
|
|
198
|
-
const partialBoundary = operand.components < 3 ? nextVersionBoundary(operand) : void 0;
|
|
199
|
-
return {
|
|
200
|
-
minimumInclusive: true,
|
|
201
|
-
maximum: partialBoundary ?? operand.version,
|
|
202
|
-
maximumInclusive: !partialBoundary
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
function parseVersionRangeBranch(value) {
|
|
206
|
-
const branch = normalizeAgentVersion(value).trim();
|
|
207
|
-
if (!branch) return void 0;
|
|
208
|
-
const hyphen = branch.match(/^(.+?)\s+-\s+(.+)$/u);
|
|
209
|
-
if (hyphen) {
|
|
210
|
-
const minimumOperand = parseVersionOperand(hyphen[1]);
|
|
211
|
-
const maximumOperand = parseVersionOperand(hyphen[2]);
|
|
212
|
-
if (!minimumOperand || !maximumOperand) return void 0;
|
|
213
|
-
const maximumBoundary = maximumOperand.components < 3 ? nextVersionBoundary(maximumOperand) : maximumOperand.version;
|
|
214
|
-
return intersectRanges({
|
|
215
|
-
minimum: minimumOperand.version,
|
|
216
|
-
minimumInclusive: true,
|
|
217
|
-
maximumInclusive: false
|
|
218
|
-
}, {
|
|
219
|
-
minimumInclusive: true,
|
|
220
|
-
maximum: maximumBoundary,
|
|
221
|
-
maximumInclusive: maximumOperand.components === 3
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
const special = branch.match(/^(\^|~)\s*(.+)$/u);
|
|
225
|
-
if (special) {
|
|
226
|
-
const operand = parseVersionOperand(special[2]);
|
|
227
|
-
if (!operand || operand.components === 0) return void 0;
|
|
228
|
-
return special[1] === "^" ? caretRange(operand) : tildeRange(operand);
|
|
229
|
-
}
|
|
230
|
-
const comparators = Array.from(branch.matchAll(/(>=|<=|>|<|=)\s*([^\s]+)/gu));
|
|
231
|
-
if (comparators.length > 0) {
|
|
232
|
-
if (comparators.map((match) => match[0]).join(" ").replace(/\s+/gu, " ") !== branch.replace(/\s+/gu, " ")) return void 0;
|
|
233
|
-
let range = {
|
|
234
|
-
minimumInclusive: true,
|
|
235
|
-
maximumInclusive: false
|
|
236
|
-
};
|
|
237
|
-
for (const comparator of comparators) {
|
|
238
|
-
const operand = parseVersionOperand(comparator[2]);
|
|
239
|
-
if (!operand) return void 0;
|
|
240
|
-
const next = intersectRanges(range, comparatorRange(comparator[1], operand));
|
|
241
|
-
if (!next) return void 0;
|
|
242
|
-
range = next;
|
|
243
|
-
}
|
|
244
|
-
return range;
|
|
245
|
-
}
|
|
246
|
-
const operand = parseVersionOperand(branch);
|
|
247
|
-
return operand ? operandRange(operand) : void 0;
|
|
248
|
-
}
|
|
249
|
-
function parseVersionRanges(value) {
|
|
250
|
-
return normalizeAgentVersion(value).split("||").map((branch) => parseVersionRangeBranch(branch)).filter((range) => Boolean(range));
|
|
251
|
-
}
|
|
252
|
-
function rangeContains(range, version) {
|
|
253
|
-
if (range.minimum) {
|
|
254
|
-
const compared = compareVersions(version, range.minimum);
|
|
255
|
-
if (compared < 0 || compared === 0 && !range.minimumInclusive) return false;
|
|
256
|
-
}
|
|
257
|
-
if (range.maximum) {
|
|
258
|
-
const compared = compareVersions(version, range.maximum);
|
|
259
|
-
if (compared > 0 || compared === 0 && !range.maximumInclusive) return false;
|
|
260
|
-
}
|
|
261
|
-
return true;
|
|
262
|
-
}
|
|
263
|
-
function rangesOverlap(left, right) {
|
|
264
|
-
return Boolean(intersectRanges(left, right));
|
|
265
|
-
}
|
|
266
|
-
/** Match an exact requested version against an exact or range-like documented constraint. */
|
|
267
|
-
function agentVersionConstraintMatches(requested, constraint) {
|
|
268
|
-
if (normalizeAgentVersion(requested) === normalizeAgentVersion(constraint)) return Boolean(normalizeAgentVersion(requested));
|
|
269
|
-
const wanted = parseExactVersion(requested);
|
|
270
|
-
if (!wanted) return false;
|
|
271
|
-
return parseVersionRanges(constraint).some((range) => rangeContains(range, wanted));
|
|
272
|
-
}
|
|
273
|
-
/** Return true when two exact or range-like documented version constraints can select one version. */
|
|
274
|
-
function agentVersionConstraintsOverlap(left, right) {
|
|
275
|
-
const normalizedLeft = normalizeAgentVersion(left);
|
|
276
|
-
if (normalizedLeft === normalizeAgentVersion(right)) return Boolean(normalizedLeft);
|
|
277
|
-
const leftRanges = parseVersionRanges(left);
|
|
278
|
-
const rightRanges = parseVersionRanges(right);
|
|
279
|
-
return leftRanges.some((leftRange) => rightRanges.some((rightRange) => rangesOverlap(leftRange, rightRange)));
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
//#endregion
|
|
283
|
-
export { normalizeAgentScopeValues as a, normalizeAgentLocale as i, agentVersionConstraintsOverlap as n, normalizeAgentVersion as o, normalizeAgentFramework as r, agentVersionConstraintMatches as t };
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { A as DocsPublishedAgentSkill } from "./standards-discovery-C4HUqMd2.mjs";
|
|
2
|
-
|
|
3
|
-
//#region src/agent-skills-bundle.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* Build-time snapshot of configured Agent Skills.
|
|
6
|
-
*
|
|
7
|
-
* `docsAgentSkills()` replaces this module in production bundles. The undefined
|
|
8
|
-
* fallback keeps direct Node usage and development setups on the filesystem
|
|
9
|
-
* resolver when the build plugin is not installed.
|
|
10
|
-
*/
|
|
11
|
-
declare const bundledAgentSkills: readonly DocsPublishedAgentSkill[] | undefined;
|
|
12
|
-
//#endregion
|
|
13
|
-
export { bundledAgentSkills };
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
//#region src/agent-skills-bundle.ts
|
|
2
|
-
/**
|
|
3
|
-
* Build-time snapshot of configured Agent Skills.
|
|
4
|
-
*
|
|
5
|
-
* `docsAgentSkills()` replaces this module in production bundles. The undefined
|
|
6
|
-
* fallback keeps direct Node usage and development setups on the filesystem
|
|
7
|
-
* resolver when the build plugin is not installed.
|
|
8
|
-
*/
|
|
9
|
-
const bundledAgentSkills = void 0;
|
|
10
|
-
|
|
11
|
-
//#endregion
|
|
12
|
-
export { bundledAgentSkills };
|
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
import { k as resolveDocsPublishedAgentSkill, u as DEFAULT_AGENT_SKILLS_ROUTE_PREFIX } from "./standards-discovery-C54V_aJH.mjs";
|
|
2
|
-
import { existsSync, lstatSync, readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { createHash } from "node:crypto";
|
|
5
|
-
import { gzipSync } from "node:zlib";
|
|
6
|
-
|
|
7
|
-
//#region src/agent-skills-server.ts
|
|
8
|
-
const COMPANION_DIRECTORIES = new Set([
|
|
9
|
-
"references",
|
|
10
|
-
"scripts",
|
|
11
|
-
"assets"
|
|
12
|
-
]);
|
|
13
|
-
const IGNORED_COLLECTION_DIRECTORIES = new Set([".git", "node_modules"]);
|
|
14
|
-
const MAX_COLLECTION_DEPTH = 12;
|
|
15
|
-
const MAX_FILES_PER_SKILL = 256;
|
|
16
|
-
const MAX_FILE_BYTES = 1024 * 1024;
|
|
17
|
-
const MAX_SKILL_BYTES = 8 * 1024 * 1024;
|
|
18
|
-
function isInside(parent, candidate) {
|
|
19
|
-
const relative = path.relative(parent, candidate);
|
|
20
|
-
return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
21
|
-
}
|
|
22
|
-
function findWorkspaceRoot(rootDir) {
|
|
23
|
-
let current = realpathSync(rootDir);
|
|
24
|
-
for (;;) {
|
|
25
|
-
if (existsSync(path.join(current, ".git")) || existsSync(path.join(current, "pnpm-workspace.yaml")) || existsSync(path.join(current, "pnpm-workspace.yml"))) return current;
|
|
26
|
-
const parent = path.dirname(current);
|
|
27
|
-
if (parent === current) return realpathSync(rootDir);
|
|
28
|
-
current = parent;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
function normalizeConfiguredPaths(input) {
|
|
32
|
-
if (!input) return [];
|
|
33
|
-
const value = typeof input === "string" || Array.isArray(input) ? input : input.paths;
|
|
34
|
-
return (typeof value === "string" ? [value] : [...value]).map((candidate) => candidate.trim()).filter(Boolean);
|
|
35
|
-
}
|
|
36
|
-
function resolveSafeConfiguredPath(configuredPath, rootDir, workspaceRoot) {
|
|
37
|
-
const candidate = path.resolve(rootDir, configuredPath);
|
|
38
|
-
if (!existsSync(candidate)) throw new Error(`Configured Agent Skill path does not exist: ${configuredPath}`);
|
|
39
|
-
if (lstatSync(candidate).isSymbolicLink()) throw new Error(`Configured Agent Skill paths may not be symlinks: ${configuredPath}`);
|
|
40
|
-
const resolved = realpathSync(candidate);
|
|
41
|
-
if (!isInside(workspaceRoot, resolved)) throw new Error(`Agent Skill symlink escapes the workspace: ${configuredPath}`);
|
|
42
|
-
return resolved;
|
|
43
|
-
}
|
|
44
|
-
function collectSkillDocuments(candidate, workspaceRoot, results, visited, depth = 0) {
|
|
45
|
-
if (depth > MAX_COLLECTION_DEPTH) throw new Error(`Agent Skill collection exceeds ${MAX_COLLECTION_DEPTH} directory levels.`);
|
|
46
|
-
const resolved = realpathSync(candidate);
|
|
47
|
-
if (!isInside(workspaceRoot, resolved)) throw new Error(`Agent Skill symlink escapes the workspace: ${candidate}`);
|
|
48
|
-
if (visited.has(resolved)) return;
|
|
49
|
-
visited.add(resolved);
|
|
50
|
-
const info = statSync(resolved);
|
|
51
|
-
if (info.isFile()) {
|
|
52
|
-
if (path.basename(resolved) !== "SKILL.md") throw new Error(`Agent Skill file must be named SKILL.md: ${candidate}`);
|
|
53
|
-
results.add(resolved);
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
if (!info.isDirectory()) throw new Error(`Agent Skill path must be a regular file or directory: ${candidate}`);
|
|
57
|
-
const directSkill = path.join(resolved, "SKILL.md");
|
|
58
|
-
if (existsSync(directSkill)) {
|
|
59
|
-
const directInfo = lstatSync(directSkill);
|
|
60
|
-
if (!directInfo.isFile() || directInfo.isSymbolicLink()) throw new Error(`Agent Skill SKILL.md must be a non-symlink regular file: ${directSkill}`);
|
|
61
|
-
results.add(directSkill);
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
for (const entry of readdirSync(resolved, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
65
|
-
if (IGNORED_COLLECTION_DIRECTORIES.has(entry.name) || entry.name.startsWith(".") || COMPANION_DIRECTORIES.has(entry.name)) continue;
|
|
66
|
-
const entryPath = path.join(resolved, entry.name);
|
|
67
|
-
if (entry.isSymbolicLink()) throw new Error(`Agent Skill collections may not contain symlinks: ${entryPath}`);
|
|
68
|
-
else if (entry.isDirectory() || entry.isFile()) {
|
|
69
|
-
if (entry.isDirectory() || entry.name === "SKILL.md") collectSkillDocuments(entryPath, workspaceRoot, results, visited, depth + 1);
|
|
70
|
-
} else throw new Error(`Unsafe filesystem entry in Agent Skill collection: ${entryPath}`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
function encodeSkillFileUrl(name, relativePath) {
|
|
74
|
-
const encodedPath = relativePath.split("/").map((segment) => encodeURIComponent(segment)).join("/");
|
|
75
|
-
return `${DEFAULT_AGENT_SKILLS_ROUTE_PREFIX}/${encodeURIComponent(name)}/${encodedPath}`;
|
|
76
|
-
}
|
|
77
|
-
function mediaTypeFor(relativePath) {
|
|
78
|
-
const extension = path.extname(relativePath).toLowerCase();
|
|
79
|
-
if ([".md", ".mdx"].includes(extension)) return "text/markdown";
|
|
80
|
-
if ([
|
|
81
|
-
".txt",
|
|
82
|
-
".sh",
|
|
83
|
-
".bash",
|
|
84
|
-
".zsh",
|
|
85
|
-
".py",
|
|
86
|
-
".js",
|
|
87
|
-
".mjs",
|
|
88
|
-
".cjs",
|
|
89
|
-
".ts",
|
|
90
|
-
".tsx",
|
|
91
|
-
".jsx",
|
|
92
|
-
".css",
|
|
93
|
-
".html",
|
|
94
|
-
".svg",
|
|
95
|
-
".csv",
|
|
96
|
-
".yaml",
|
|
97
|
-
".yml"
|
|
98
|
-
].includes(extension)) return "text/plain";
|
|
99
|
-
if (extension === ".json") return "application/json";
|
|
100
|
-
if (extension === ".png") return "image/png";
|
|
101
|
-
if ([".jpg", ".jpeg"].includes(extension)) return "image/jpeg";
|
|
102
|
-
if (extension === ".gif") return "image/gif";
|
|
103
|
-
if (extension === ".webp") return "image/webp";
|
|
104
|
-
if (extension === ".pdf") return "application/pdf";
|
|
105
|
-
return "application/octet-stream";
|
|
106
|
-
}
|
|
107
|
-
function hashBytes(content) {
|
|
108
|
-
return createHash("sha256").update(content).digest("hex");
|
|
109
|
-
}
|
|
110
|
-
function preserveFileBytes(content, mediaType) {
|
|
111
|
-
if (mediaType.startsWith("text/") || mediaType === "application/json") {
|
|
112
|
-
const text = content.toString("utf8");
|
|
113
|
-
if (Buffer.from(text, "utf8").equals(content)) return text;
|
|
114
|
-
}
|
|
115
|
-
return new Uint8Array(content);
|
|
116
|
-
}
|
|
117
|
-
function compareSkillFilePath(left, right) {
|
|
118
|
-
if (left.path === "SKILL.md") return -1;
|
|
119
|
-
if (right.path === "SKILL.md") return 1;
|
|
120
|
-
return left.path.localeCompare(right.path);
|
|
121
|
-
}
|
|
122
|
-
function readCompanionFiles(skillDir, name, rootSkillBytes) {
|
|
123
|
-
const files = [];
|
|
124
|
-
let totalBytes = rootSkillBytes;
|
|
125
|
-
function visit(absoluteDir, relativeDir, depth = 0) {
|
|
126
|
-
if (depth > MAX_COLLECTION_DEPTH) throw new Error(`Agent Skill companion tree exceeds ${MAX_COLLECTION_DEPTH} levels: ${skillDir}`);
|
|
127
|
-
for (const entry of readdirSync(absoluteDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
128
|
-
const absolutePath = path.join(absoluteDir, entry.name);
|
|
129
|
-
const relativePath = path.posix.join(relativeDir, entry.name);
|
|
130
|
-
if (entry.isSymbolicLink()) throw new Error(`Agent Skill companion files may not be symlinks: ${absolutePath}`);
|
|
131
|
-
if (entry.isDirectory()) {
|
|
132
|
-
visit(absolutePath, relativePath, depth + 1);
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
if (!entry.isFile()) throw new Error(`Unsafe filesystem entry in Agent Skill: ${absolutePath}`);
|
|
136
|
-
const executable = (statSync(absolutePath).mode & 73) !== 0;
|
|
137
|
-
const content = readFileSync(absolutePath);
|
|
138
|
-
if (content.byteLength > MAX_FILE_BYTES) throw new Error(`Agent Skill file exceeds ${MAX_FILE_BYTES} bytes: ${absolutePath}`);
|
|
139
|
-
totalBytes += content.byteLength;
|
|
140
|
-
if (totalBytes > MAX_SKILL_BYTES || files.length >= MAX_FILES_PER_SKILL - 1) throw new Error(`Agent Skill exceeds safe publication limits: ${skillDir}`);
|
|
141
|
-
const mediaType = mediaTypeFor(relativePath);
|
|
142
|
-
const value = preserveFileBytes(content, mediaType);
|
|
143
|
-
const sha256 = hashBytes(value);
|
|
144
|
-
files.push({
|
|
145
|
-
path: relativePath,
|
|
146
|
-
url: encodeSkillFileUrl(name, relativePath),
|
|
147
|
-
mediaType,
|
|
148
|
-
content: value,
|
|
149
|
-
sha256,
|
|
150
|
-
digest: `sha256:${sha256}`,
|
|
151
|
-
executable
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
for (const directory of [...COMPANION_DIRECTORIES].sort()) {
|
|
156
|
-
const absoluteDir = path.join(skillDir, directory);
|
|
157
|
-
if (!existsSync(absoluteDir)) continue;
|
|
158
|
-
const info = lstatSync(absoluteDir);
|
|
159
|
-
if (info.isSymbolicLink() || !info.isDirectory()) throw new Error(`Agent Skill ${directory}/ must be a non-symlink directory: ${absoluteDir}`);
|
|
160
|
-
visit(absoluteDir, directory);
|
|
161
|
-
}
|
|
162
|
-
return files;
|
|
163
|
-
}
|
|
164
|
-
function writeTarString(header, offset, length, value) {
|
|
165
|
-
const encoded = Buffer.from(value, "utf8");
|
|
166
|
-
if (encoded.byteLength > length) throw new Error(`Agent Skill archive path is too long: ${value}`);
|
|
167
|
-
header.set(encoded, offset);
|
|
168
|
-
}
|
|
169
|
-
function writeTarOctal(header, offset, length, value) {
|
|
170
|
-
writeTarString(header, offset, length, value.toString(8).padStart(length - 1, "0"));
|
|
171
|
-
}
|
|
172
|
-
function createTarHeader(name, size, executable) {
|
|
173
|
-
const header = new Uint8Array(512);
|
|
174
|
-
writeTarString(header, 0, 100, name);
|
|
175
|
-
writeTarOctal(header, 100, 8, executable ? 493 : 420);
|
|
176
|
-
writeTarOctal(header, 108, 8, 0);
|
|
177
|
-
writeTarOctal(header, 116, 8, 0);
|
|
178
|
-
writeTarOctal(header, 124, 12, size);
|
|
179
|
-
writeTarOctal(header, 136, 12, 0);
|
|
180
|
-
header.fill(32, 148, 156);
|
|
181
|
-
header[156] = "0".charCodeAt(0);
|
|
182
|
-
writeTarString(header, 257, 6, "ustar");
|
|
183
|
-
writeTarString(header, 263, 2, "00");
|
|
184
|
-
writeTarString(header, 148, 8, `${header.reduce((sum, byte) => sum + byte, 0).toString(8).padStart(6, "0")}\0 `);
|
|
185
|
-
return header;
|
|
186
|
-
}
|
|
187
|
-
function createDeterministicTarGzip(files) {
|
|
188
|
-
const chunks = [];
|
|
189
|
-
let total = 0;
|
|
190
|
-
for (const file of [...files].sort(compareSkillFilePath)) {
|
|
191
|
-
const content = typeof file.content === "string" ? Buffer.from(file.content) : file.content;
|
|
192
|
-
const header = createTarHeader(file.path, content.byteLength, file.executable === true);
|
|
193
|
-
chunks.push(header, content);
|
|
194
|
-
total += header.byteLength + content.byteLength;
|
|
195
|
-
const padding = (512 - content.byteLength % 512) % 512;
|
|
196
|
-
if (padding) {
|
|
197
|
-
chunks.push(new Uint8Array(padding));
|
|
198
|
-
total += padding;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
chunks.push(new Uint8Array(1024));
|
|
202
|
-
total += 1024;
|
|
203
|
-
const tar = new Uint8Array(total);
|
|
204
|
-
let offset = 0;
|
|
205
|
-
for (const chunk of chunks) {
|
|
206
|
-
tar.set(chunk, offset);
|
|
207
|
-
offset += chunk.byteLength;
|
|
208
|
-
}
|
|
209
|
-
const archive = new Uint8Array(gzipSync(tar, { level: 9 }));
|
|
210
|
-
if (archive.byteLength > 9) archive[9] = 255;
|
|
211
|
-
return archive;
|
|
212
|
-
}
|
|
213
|
-
async function publishSkillDocument(skillPath) {
|
|
214
|
-
const skillDir = path.dirname(skillPath);
|
|
215
|
-
const skillDocument = readFileSync(skillPath, "utf8");
|
|
216
|
-
const skillDocumentBytes = Buffer.byteLength(skillDocument, "utf8");
|
|
217
|
-
if (skillDocumentBytes > MAX_FILE_BYTES) throw new Error(`Agent Skill SKILL.md exceeds ${MAX_FILE_BYTES} bytes: ${skillPath}`);
|
|
218
|
-
const base = await resolveDocsPublishedAgentSkill({
|
|
219
|
-
preferredDocument: skillDocument,
|
|
220
|
-
fallbackDocument: skillDocument
|
|
221
|
-
});
|
|
222
|
-
if (base.name !== path.basename(skillDir)) throw new Error(`Agent Skill frontmatter name "${base.name}" must match its directory "${path.basename(skillDir)}".`);
|
|
223
|
-
const companions = readCompanionFiles(skillDir, base.name, skillDocumentBytes);
|
|
224
|
-
const files = [...base.files, ...companions].sort(compareSkillFilePath);
|
|
225
|
-
if (companions.length === 0) return {
|
|
226
|
-
...base,
|
|
227
|
-
files
|
|
228
|
-
};
|
|
229
|
-
const content = createDeterministicTarGzip(files);
|
|
230
|
-
const sha256 = hashBytes(content);
|
|
231
|
-
return {
|
|
232
|
-
name: base.name,
|
|
233
|
-
type: "archive",
|
|
234
|
-
description: base.description,
|
|
235
|
-
url: `${DEFAULT_AGENT_SKILLS_ROUTE_PREFIX}/${encodeURIComponent(base.name)}.tar.gz`,
|
|
236
|
-
digest: `sha256:${sha256}`,
|
|
237
|
-
content,
|
|
238
|
-
sha256,
|
|
239
|
-
skillDocument,
|
|
240
|
-
files
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
/** Resolve and safely package all project skills configured through `agent.skills`. */
|
|
244
|
-
async function resolveConfiguredAgentSkills(input, options = {}) {
|
|
245
|
-
const configuredPaths = normalizeConfiguredPaths(input);
|
|
246
|
-
if (configuredPaths.length === 0) return [];
|
|
247
|
-
const rootDir = realpathSync(options.rootDir ?? process.cwd());
|
|
248
|
-
const workspaceRoot = realpathSync(options.workspaceRoot ?? findWorkspaceRoot(rootDir));
|
|
249
|
-
if (!isInside(workspaceRoot, rootDir)) throw new Error("Agent Skill rootDir must stay inside the configured workspace root.");
|
|
250
|
-
const documents = /* @__PURE__ */ new Set();
|
|
251
|
-
const visited = /* @__PURE__ */ new Set();
|
|
252
|
-
for (const configuredPath of configuredPaths) collectSkillDocuments(resolveSafeConfiguredPath(configuredPath, rootDir, workspaceRoot), workspaceRoot, documents, visited);
|
|
253
|
-
const published = await Promise.all([...documents].sort().map(publishSkillDocument));
|
|
254
|
-
const names = /* @__PURE__ */ new Set();
|
|
255
|
-
for (const skill of published) {
|
|
256
|
-
if (names.has(skill.name)) throw new Error(`Duplicate configured Agent Skill name: ${skill.name}`);
|
|
257
|
-
names.add(skill.name);
|
|
258
|
-
}
|
|
259
|
-
return published.sort((left, right) => left.name.localeCompare(right.name));
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
//#endregion
|
|
263
|
-
export { resolveConfiguredAgentSkills as t };
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { A as DocsPublishedAgentSkill } from "./standards-discovery-C4HUqMd2.mjs";
|
|
2
|
-
import { P as DocsAgentSkillsInput } from "./types-EhFhYGfr.mjs";
|
|
3
|
-
|
|
4
|
-
//#region src/agent-skills-server.d.ts
|
|
5
|
-
interface ResolveConfiguredAgentSkillsOptions {
|
|
6
|
-
rootDir?: string;
|
|
7
|
-
workspaceRoot?: string;
|
|
8
|
-
}
|
|
9
|
-
/** Resolve and safely package all project skills configured through `agent.skills`. */
|
|
10
|
-
declare function resolveConfiguredAgentSkills(input: DocsAgentSkillsInput | undefined, options?: ResolveConfiguredAgentSkillsOptions): Promise<DocsPublishedAgentSkill[]>;
|
|
11
|
-
//#endregion
|
|
12
|
-
export { resolveConfiguredAgentSkills as n, ResolveConfiguredAgentSkillsOptions as t };
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { A as DocsPublishedAgentSkill } from "./standards-discovery-C4HUqMd2.mjs";
|
|
2
|
-
import { P as DocsAgentSkillsInput } from "./types-EhFhYGfr.mjs";
|
|
3
|
-
import { t as ResolveConfiguredAgentSkillsOptions } from "./agent-skills-server-CKq3_jMj.mjs";
|
|
4
|
-
|
|
5
|
-
//#region src/agent-skills-vite.d.ts
|
|
6
|
-
declare const DOCS_AGENT_SKILLS_BUNDLE_MODULE = "@farming-labs/docs/agent-skills-bundle";
|
|
7
|
-
interface DocsAgentSkillsBuildConfig {
|
|
8
|
-
agent?: {
|
|
9
|
-
skills?: DocsAgentSkillsInput;
|
|
10
|
-
};
|
|
11
|
-
rootDir?: string;
|
|
12
|
-
}
|
|
13
|
-
interface DocsAgentSkillsBuildPluginOptions extends ResolveConfiguredAgentSkillsOptions {}
|
|
14
|
-
/** Minimal Rollup/Vite plugin surface, kept dependency-free for framework configs. */
|
|
15
|
-
interface DocsAgentSkillsBuildPlugin {
|
|
16
|
-
name: string;
|
|
17
|
-
enforce: "pre";
|
|
18
|
-
resolveId(source: string): string | undefined;
|
|
19
|
-
load(id: string): Promise<string | undefined>;
|
|
20
|
-
}
|
|
21
|
-
/** Render a self-contained virtual module without relying on Node at runtime. */
|
|
22
|
-
declare function renderDocsAgentSkillsBundle(skills: readonly DocsPublishedAgentSkill[]): string;
|
|
23
|
-
/**
|
|
24
|
-
* Snapshot configured Agent Skills into the server bundle.
|
|
25
|
-
*
|
|
26
|
-
* The same plugin object works in Vite, Astro/Svelte/TanStack, and Nitro's
|
|
27
|
-
* Rollup build. Paths remain relative to the project root unless overridden.
|
|
28
|
-
*/
|
|
29
|
-
declare function docsAgentSkills(config: DocsAgentSkillsBuildConfig, options?: DocsAgentSkillsBuildPluginOptions): DocsAgentSkillsBuildPlugin;
|
|
30
|
-
//#endregion
|
|
31
|
-
export { DOCS_AGENT_SKILLS_BUNDLE_MODULE, DocsAgentSkillsBuildPlugin, DocsAgentSkillsBuildPluginOptions, docsAgentSkills, renderDocsAgentSkillsBundle };
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import "./standards-discovery-C54V_aJH.mjs";
|
|
2
|
-
import { t as resolveConfiguredAgentSkills } from "./agent-skills-server-CIeBszxp.mjs";
|
|
3
|
-
|
|
4
|
-
//#region src/agent-skills-vite.ts
|
|
5
|
-
const DOCS_AGENT_SKILLS_BUNDLE_MODULE = "@farming-labs/docs/agent-skills-bundle";
|
|
6
|
-
const RESOLVED_BUNDLE_MODULE = "\0farming-labs:agent-skills-bundle";
|
|
7
|
-
function isBundleModuleId(id) {
|
|
8
|
-
if (id === RESOLVED_BUNDLE_MODULE) return true;
|
|
9
|
-
const cleanId = id.split("?", 1)[0].replaceAll("\\", "/");
|
|
10
|
-
return /(?:^|\/)agent-skills-bundle\.(?:[cm]?js|ts)$/.test(cleanId);
|
|
11
|
-
}
|
|
12
|
-
function serializeContent(content) {
|
|
13
|
-
return typeof content === "string" ? { text: content } : { base64: Buffer.from(content).toString("base64") };
|
|
14
|
-
}
|
|
15
|
-
function serializeSkill(skill) {
|
|
16
|
-
return {
|
|
17
|
-
...skill,
|
|
18
|
-
content: serializeContent(skill.content),
|
|
19
|
-
files: skill.files.map((file) => ({
|
|
20
|
-
...file,
|
|
21
|
-
content: serializeContent(file.content)
|
|
22
|
-
}))
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
/** Render a self-contained virtual module without relying on Node at runtime. */
|
|
26
|
-
function renderDocsAgentSkillsBundle(skills) {
|
|
27
|
-
return `const snapshot = ${JSON.stringify(skills.map(serializeSkill)).replaceAll("\u2028", "\\u2028").replaceAll("\u2029", "\\u2029")};
|
|
28
|
-
function decodeBase64(value) {
|
|
29
|
-
const binary = globalThis.atob(value);
|
|
30
|
-
const bytes = new Uint8Array(binary.length);
|
|
31
|
-
for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
|
|
32
|
-
return bytes;
|
|
33
|
-
}
|
|
34
|
-
function hydrateContent(content) {
|
|
35
|
-
return typeof content.text === "string" ? content.text : decodeBase64(content.base64);
|
|
36
|
-
}
|
|
37
|
-
export const bundledAgentSkills = snapshot.map((skill) => ({
|
|
38
|
-
...skill,
|
|
39
|
-
content: hydrateContent(skill.content),
|
|
40
|
-
files: skill.files.map((file) => ({ ...file, content: hydrateContent(file.content) })),
|
|
41
|
-
}));
|
|
42
|
-
`;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Snapshot configured Agent Skills into the server bundle.
|
|
46
|
-
*
|
|
47
|
-
* The same plugin object works in Vite, Astro/Svelte/TanStack, and Nitro's
|
|
48
|
-
* Rollup build. Paths remain relative to the project root unless overridden.
|
|
49
|
-
*/
|
|
50
|
-
function docsAgentSkills(config, options = {}) {
|
|
51
|
-
let source;
|
|
52
|
-
return {
|
|
53
|
-
name: "farming-labs-agent-skills",
|
|
54
|
-
enforce: "pre",
|
|
55
|
-
resolveId(id) {
|
|
56
|
-
return id === DOCS_AGENT_SKILLS_BUNDLE_MODULE ? RESOLVED_BUNDLE_MODULE : void 0;
|
|
57
|
-
},
|
|
58
|
-
async load(id) {
|
|
59
|
-
if (!isBundleModuleId(id)) return void 0;
|
|
60
|
-
source ??= resolveConfiguredAgentSkills(config.agent?.skills, {
|
|
61
|
-
rootDir: options.rootDir ?? config.rootDir ?? process.cwd(),
|
|
62
|
-
workspaceRoot: options.workspaceRoot
|
|
63
|
-
}).then(renderDocsAgentSkillsBundle);
|
|
64
|
-
return source;
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
//#endregion
|
|
70
|
-
export { DOCS_AGENT_SKILLS_BUNDLE_MODULE, docsAgentSkills, renderDocsAgentSkillsBundle };
|