@farming-labs/next 0.2.62 → 0.2.63
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/api.mjs +9 -6
- package/dist/config.d.mts +1 -1
- package/dist/config.mjs +123 -45
- package/package.json +6 -4
package/dist/api.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
3
|
import { createDocsAPI as createDocsAPI$1, createDocsMCPAPI as createDocsMCPAPI$1 } from "@farming-labs/theme/api";
|
|
4
|
+
import { bundledAgentSkills } from "@farming-labs/docs/agent-skills-bundle";
|
|
4
5
|
import { createDocsCloudRouteHandler } from "@farming-labs/docs/cloud/server";
|
|
5
6
|
|
|
6
7
|
//#region src/api.ts
|
|
@@ -113,10 +114,11 @@ async function isDocsCloudPostRequest(request) {
|
|
|
113
114
|
}
|
|
114
115
|
function createDocsAPI(options = {}, cloudIntegration) {
|
|
115
116
|
const rootDir = options.rootDir ?? inferNextProjectRootFromCaller();
|
|
116
|
-
const handlers = createDocsAPI$1(
|
|
117
|
+
const handlers = createDocsAPI$1({
|
|
117
118
|
...options,
|
|
118
|
-
rootDir
|
|
119
|
-
|
|
119
|
+
...rootDir ? { rootDir } : {},
|
|
120
|
+
_preloadedAgentSkills: options._preloadedAgentSkills ?? bundledAgentSkills
|
|
121
|
+
});
|
|
120
122
|
const integration = resolveDocsCloudIntegration(cloudIntegration);
|
|
121
123
|
if (!integration) return handlers;
|
|
122
124
|
return {
|
|
@@ -141,10 +143,11 @@ function createDocsAPI(options = {}, cloudIntegration) {
|
|
|
141
143
|
}
|
|
142
144
|
function createDocsMCPAPI(options = {}) {
|
|
143
145
|
const rootDir = options.rootDir ?? inferNextProjectRootFromCaller();
|
|
144
|
-
return createDocsMCPAPI$1(
|
|
146
|
+
return createDocsMCPAPI$1({
|
|
145
147
|
...options,
|
|
146
|
-
rootDir
|
|
147
|
-
|
|
148
|
+
...rootDir ? { rootDir } : {},
|
|
149
|
+
_preloadedAgentSkills: options._preloadedAgentSkills ?? bundledAgentSkills
|
|
150
|
+
});
|
|
148
151
|
}
|
|
149
152
|
|
|
150
153
|
//#endregion
|
package/dist/config.d.mts
CHANGED
|
@@ -2,6 +2,6 @@ import { DocsConfig } from "@farming-labs/docs";
|
|
|
2
2
|
import { NextConfig } from "next";
|
|
3
3
|
|
|
4
4
|
//#region src/config.d.ts
|
|
5
|
-
declare function withDocs(nextConfig?: NextConfig, docsConfig?: Pick<DocsConfig, "mcp">): NextConfig;
|
|
5
|
+
declare function withDocs(nextConfig?: NextConfig, docsConfig?: Pick<DocsConfig, "agent" | "mcp">): NextConfig;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { withDocs };
|
package/dist/config.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { dirname, isAbsolute, join, relative
|
|
2
|
+
import { dirname, extname, isAbsolute, join, relative } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { DEFAULT_A2A_AGENT_CARD_ROUTE, DEFAULT_AGENT_SKILLS_INDEX_ROUTE, DEFAULT_AGENT_SKILLS_ROUTE_PREFIX, DEFAULT_AGENT_SKILL_ARCHIVE_FORMAT, DEFAULT_API_CATALOG_ROUTE, DEFAULT_LEGACY_SKILLS_INDEX_ROUTE, DEFAULT_LEGACY_SKILLS_ROUTE_PREFIX, DOCS_AI_AGENT_USER_AGENT_HEADER_PATTERN, DOCS_BOT_LIKE_USER_AGENT_HEADER_PATTERN, DOCS_TRADITIONAL_BOT_USER_AGENT_HEADER_PATTERN } from "@farming-labs/docs";
|
|
5
|
-
import { ensureDocsReviewWorkflow } from "@farming-labs/docs/server";
|
|
5
|
+
import { ensureDocsReviewWorkflow, renderDocsAgentSkillsBundle, resolveConfiguredAgentSkillsSync } from "@farming-labs/docs/server";
|
|
6
6
|
import matter from "gray-matter";
|
|
7
|
+
import { parse } from "@babel/parser";
|
|
7
8
|
import createMDX from "@next/mdx";
|
|
8
9
|
|
|
9
10
|
//#region src/config.ts
|
|
@@ -144,6 +145,8 @@ const FILE_EXTS = [
|
|
|
144
145
|
"js"
|
|
145
146
|
];
|
|
146
147
|
const INTERNAL_DOCS_CONFIG_ALIAS = "@farming-labs/next-internal-docs-config";
|
|
148
|
+
const AGENT_SKILLS_BUNDLE_ALIAS = "@farming-labs/docs/agent-skills-bundle";
|
|
149
|
+
const AGENT_SKILLS_BUNDLE_PATH = ".docs/agent-skills-bundle.mjs";
|
|
147
150
|
const NEXT_PACKAGE_ROOT = fileURLToPath(new URL("..", import.meta.url));
|
|
148
151
|
const DEFAULT_AGENT_SPEC_ROUTE = "/api/docs/agent/spec";
|
|
149
152
|
const DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE = "/.well-known/agent";
|
|
@@ -188,8 +191,8 @@ function resolvePackageSubpath(packageDir, relativePath) {
|
|
|
188
191
|
}
|
|
189
192
|
function toTurbopackAliasPath(root, value) {
|
|
190
193
|
if (!isAbsolute(value)) return value;
|
|
191
|
-
const relativePath = relative(root, value);
|
|
192
|
-
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
194
|
+
const relativePath = relative(root, value).replaceAll("\\", "/");
|
|
195
|
+
return relativePath === ".." || relativePath.startsWith("../") ? relativePath : relativePath.startsWith("./") ? relativePath : `./${relativePath}`;
|
|
193
196
|
}
|
|
194
197
|
const FUMADOCS_OPENAPI_PACKAGE_ALIAS = resolvePackageAlias("fumadocs-openapi") ?? "fumadocs-openapi";
|
|
195
198
|
const FUMADOCS_CORE_PACKAGE_ALIAS = resolvePackageAlias("fumadocs-core") ?? "fumadocs-core";
|
|
@@ -545,43 +548,119 @@ function readDocsConfigPath(root) {
|
|
|
545
548
|
}
|
|
546
549
|
return "docs.config.ts";
|
|
547
550
|
}
|
|
548
|
-
function
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
if (
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
const
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
551
|
+
function unwrapStaticExpression(expression) {
|
|
552
|
+
let current = expression;
|
|
553
|
+
while (current.type === "ParenthesizedExpression" || current.type === "TSAsExpression" || current.type === "TSSatisfiesExpression" || current.type === "TSTypeAssertion" || current.type === "TSNonNullExpression" || current.type === "TSInstantiationExpression") current = current.expression;
|
|
554
|
+
return current;
|
|
555
|
+
}
|
|
556
|
+
function readStaticPropertyName(property) {
|
|
557
|
+
const key = unwrapStaticExpression(property.key);
|
|
558
|
+
if (property.computed) return void 0;
|
|
559
|
+
if (key.type === "Identifier") return key.name;
|
|
560
|
+
if (key.type === "StringLiteral") return key.value;
|
|
561
|
+
if (key.type === "NumericLiteral") return String(key.value);
|
|
562
|
+
if (key.type === "BigIntLiteral") return key.value;
|
|
563
|
+
if (key.type === "TemplateLiteral" && key.expressions.length === 0) return key.quasis[0]?.value.cooked ?? void 0;
|
|
564
|
+
}
|
|
565
|
+
function resolveStaticObjectProperty(object, key) {
|
|
566
|
+
let resolution = { status: "absent" };
|
|
567
|
+
for (const entry of object.properties) {
|
|
568
|
+
if (entry.type === "SpreadElement") {
|
|
569
|
+
resolution = { status: "unknown" };
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
const name = readStaticPropertyName(entry);
|
|
573
|
+
if (name === void 0) {
|
|
574
|
+
if (entry.computed) resolution = { status: "unknown" };
|
|
575
|
+
continue;
|
|
576
|
+
}
|
|
577
|
+
if (name === "__proto__" && !entry.computed && entry.type === "ObjectProperty" && !entry.shorthand) {
|
|
578
|
+
if (resolution.status !== "value") resolution = { status: "unknown" };
|
|
579
|
+
continue;
|
|
580
|
+
}
|
|
581
|
+
if (name !== key) continue;
|
|
582
|
+
if (entry.type !== "ObjectProperty" || entry.shorthand) {
|
|
583
|
+
resolution = { status: "unknown" };
|
|
584
|
+
continue;
|
|
582
585
|
}
|
|
586
|
+
resolution = {
|
|
587
|
+
status: "value",
|
|
588
|
+
value: entry.value
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
return resolution;
|
|
592
|
+
}
|
|
593
|
+
function hasDefineDocsImport(program, localName) {
|
|
594
|
+
return program.body.some((statement) => statement.type === "ImportDeclaration" && statement.importKind !== "type" && statement.source.value === "@farming-labs/docs" && statement.specifiers.some((specifier) => specifier.type === "ImportSpecifier" && specifier.importKind !== "type" && specifier.local.name === localName && specifier.imported.type === "Identifier" && specifier.imported.name === "defineDocs"));
|
|
595
|
+
}
|
|
596
|
+
function readDocsConfigRootObject(configPath, content) {
|
|
597
|
+
let program;
|
|
598
|
+
try {
|
|
599
|
+
const extension = extname(configPath).toLowerCase();
|
|
600
|
+
program = parse(content, {
|
|
601
|
+
sourceType: "module",
|
|
602
|
+
sourceFilename: configPath,
|
|
603
|
+
plugins: extension === ".tsx" ? [
|
|
604
|
+
"typescript",
|
|
605
|
+
"jsx",
|
|
606
|
+
"decorators-legacy"
|
|
607
|
+
] : extension === ".ts" ? ["typescript", "decorators-legacy"] : extension === ".jsx" ? ["jsx", "decorators-legacy"] : ["decorators-legacy"],
|
|
608
|
+
createParenthesizedExpressions: true
|
|
609
|
+
}).program;
|
|
610
|
+
} catch (error) {
|
|
611
|
+
throw new Error(`withDocs could not parse ${configPath} while bundling Agent Skills: ${error instanceof Error ? error.message : String(error)}`);
|
|
583
612
|
}
|
|
584
|
-
|
|
613
|
+
const defaults = program.body.filter((statement) => statement.type === "ExportDefaultDeclaration");
|
|
614
|
+
if (defaults.length !== 1) throw new Error("withDocs could not statically determine agent.skills. Pass the live docs config as the second withDocs argument or use a literal agent object.");
|
|
615
|
+
let expression = unwrapStaticExpression(defaults[0].declaration);
|
|
616
|
+
if (expression.type === "CallExpression") {
|
|
617
|
+
const callee = expression.callee.type === "V8IntrinsicIdentifier" ? void 0 : unwrapStaticExpression(expression.callee);
|
|
618
|
+
const argument = expression.arguments[0];
|
|
619
|
+
if (!callee || callee.type !== "Identifier" || !hasDefineDocsImport(program, callee.name) || !argument || argument.type === "SpreadElement" || argument.type === "ArgumentPlaceholder") throw new Error("withDocs could not statically determine agent.skills. Pass the live docs config as the second withDocs argument or use a literal agent object.");
|
|
620
|
+
expression = unwrapStaticExpression(argument);
|
|
621
|
+
}
|
|
622
|
+
if (expression.type !== "ObjectExpression") throw new Error("withDocs could not statically determine agent.skills. Pass the live docs config as the second withDocs argument or use a literal agent object.");
|
|
623
|
+
return expression;
|
|
624
|
+
}
|
|
625
|
+
function readStaticStringPaths(expression) {
|
|
626
|
+
const value = unwrapStaticExpression(expression);
|
|
627
|
+
if (value.type === "StringLiteral") return [value.value];
|
|
628
|
+
if (value.type !== "ArrayExpression") return null;
|
|
629
|
+
const paths = [];
|
|
630
|
+
for (const entry of value.elements) {
|
|
631
|
+
if (!entry || entry.type === "SpreadElement") return null;
|
|
632
|
+
const item = unwrapStaticExpression(entry);
|
|
633
|
+
if (item.type !== "StringLiteral") return null;
|
|
634
|
+
paths.push(item.value);
|
|
635
|
+
}
|
|
636
|
+
return paths;
|
|
637
|
+
}
|
|
638
|
+
function readAgentSkillPaths(root, configPath) {
|
|
639
|
+
const absoluteConfigPath = join(root, configPath);
|
|
640
|
+
if (!existsSync(absoluteConfigPath)) return [];
|
|
641
|
+
const agent = resolveStaticObjectProperty(readDocsConfigRootObject(absoluteConfigPath, readFileSync(absoluteConfigPath, "utf8")), "agent");
|
|
642
|
+
if (agent.status === "absent") return [];
|
|
643
|
+
if (agent.status === "unknown") throw new Error("withDocs could not statically determine agent.skills from a composed agent config. Pass the live docs config as the second withDocs argument.");
|
|
644
|
+
const agentValue = unwrapStaticExpression(agent.value);
|
|
645
|
+
if (agentValue.type !== "ObjectExpression") throw new Error("withDocs could not statically determine agent.skills from a composed agent config. Pass the live docs config as the second withDocs argument.");
|
|
646
|
+
const skills = resolveStaticObjectProperty(agentValue, "skills");
|
|
647
|
+
if (skills.status === "absent") return [];
|
|
648
|
+
if (skills.status === "unknown") throw new Error("withDocs could not statically determine agent.skills from a composed agent config. Pass the live docs config as the second withDocs argument.");
|
|
649
|
+
const skillsValue = unwrapStaticExpression(skills.value);
|
|
650
|
+
let configured;
|
|
651
|
+
if (skillsValue.type === "ObjectExpression") {
|
|
652
|
+
const paths = resolveStaticObjectProperty(skillsValue, "paths");
|
|
653
|
+
configured = paths.status === "value" ? readStaticStringPaths(paths.value) : null;
|
|
654
|
+
} else configured = readStaticStringPaths(skillsValue);
|
|
655
|
+
if (!configured) throw new Error("withDocs could not statically bundle agent.skills. Use a literal path, a literal path array, or { paths: [...] } so configured skills are included in production.");
|
|
656
|
+
return configured;
|
|
657
|
+
}
|
|
658
|
+
function writeAgentSkillsBundle(root, configuredSkills) {
|
|
659
|
+
const bundlePath = join(root, AGENT_SKILLS_BUNDLE_PATH);
|
|
660
|
+
const source = `${GENERATED_BANNER}${renderDocsAgentSkillsBundle(resolveConfiguredAgentSkillsSync(configuredSkills, { rootDir: root }))}`;
|
|
661
|
+
mkdirSync(dirname(bundlePath), { recursive: true });
|
|
662
|
+
if (!existsSync(bundlePath) || readFileSync(bundlePath, "utf8") !== source) writeFileSync(bundlePath, source, "utf8");
|
|
663
|
+
return bundlePath;
|
|
585
664
|
}
|
|
586
665
|
/** Read the OG endpoint from docs.config.ts[x] (returns undefined if not set). */
|
|
587
666
|
function readOgEndpoint(root) {
|
|
@@ -1809,8 +1888,7 @@ function withDocs(nextConfig = {}, docsConfig) {
|
|
|
1809
1888
|
const mcp = docsConfig ? resolveMcpConfig(docsConfig.mcp) : readMcpConfig(root);
|
|
1810
1889
|
const nextBasePath = normalizeRoutePrefix(nextConfig.basePath);
|
|
1811
1890
|
if (mcp.enabled && mcp.protectedResource && nextBasePath) throw new Error(`@farming-labs/next: mcp.security.protectedResource cannot be combined with Next.js basePath ${JSON.stringify(nextBasePath)} because RFC 9728 metadata must be hosted at origin-root well-known URLs. Host the protected docs app at the origin root or publish the metadata and MCP proxy at the edge.`);
|
|
1812
|
-
const
|
|
1813
|
-
if (agentSkillTraceGlobs.some((glob) => glob.startsWith("../"))) nextConfig.outputFileTracingRoot ??= workspaceRoot ?? commonTracingRoot(root, agentSkillTraceGlobs);
|
|
1891
|
+
const agentSkillsBundlePath = writeAgentSkillsBundle(root, docsConfig === void 0 || !Object.hasOwn(docsConfig, "agent") ? readAgentSkillPaths(root, docsConfigPath) : docsConfig.agent?.skills);
|
|
1814
1892
|
const agentFeedback = readAgentFeedbackConfig(root);
|
|
1815
1893
|
const docsConfigRelativeAlias = docsConfigPath.startsWith("./") || docsConfigPath.startsWith("../") ? docsConfigPath : `./${docsConfigPath}`;
|
|
1816
1894
|
ensureDocsReviewWorkflow({
|
|
@@ -1957,6 +2035,7 @@ function withDocs(nextConfig = {}, docsConfig) {
|
|
|
1957
2035
|
...workspaceRoot ? createDocsWorkspaceAliases(root, workspaceRoot) : {},
|
|
1958
2036
|
...existingResolveAlias,
|
|
1959
2037
|
[INTERNAL_DOCS_CONFIG_ALIAS]: docsConfigRelativeAlias,
|
|
2038
|
+
[AGENT_SKILLS_BUNDLE_ALIAS]: toTurbopackAliasPath(root, agentSkillsBundlePath),
|
|
1960
2039
|
"fumadocs-openapi": toTurbopackAliasPath(root, FUMADOCS_OPENAPI_PACKAGE_ALIAS),
|
|
1961
2040
|
"fumadocs-openapi/ui": toTurbopackAliasPath(root, FUMADOCS_OPENAPI_UI_ALIAS),
|
|
1962
2041
|
"fumadocs-openapi/server": toTurbopackAliasPath(root, FUMADOCS_OPENAPI_SERVER_ALIAS),
|
|
@@ -1988,6 +2067,7 @@ function withDocs(nextConfig = {}, docsConfig) {
|
|
|
1988
2067
|
"@farming-labs/theme/api": join(workspaceRoot, "packages", "fumadocs", "dist", "docs-api.mjs")
|
|
1989
2068
|
});
|
|
1990
2069
|
resolvedConfig.resolve.alias[INTERNAL_DOCS_CONFIG_ALIAS] = docsConfigAbsolutePath;
|
|
2070
|
+
resolvedConfig.resolve.alias[AGENT_SKILLS_BUNDLE_ALIAS] = agentSkillsBundlePath;
|
|
1991
2071
|
resolvedConfig.resolve.alias["fumadocs-openapi"] = FUMADOCS_OPENAPI_PACKAGE_ALIAS;
|
|
1992
2072
|
resolvedConfig.resolve.alias["fumadocs-openapi/ui"] = FUMADOCS_OPENAPI_UI_ALIAS;
|
|
1993
2073
|
resolvedConfig.resolve.alias["fumadocs-openapi/server"] = FUMADOCS_OPENAPI_SERVER_ALIAS;
|
|
@@ -2028,14 +2108,12 @@ function withDocs(nextConfig = {}, docsConfig) {
|
|
|
2028
2108
|
skillTraceFile,
|
|
2029
2109
|
agentsTraceFile,
|
|
2030
2110
|
agentTraceFile,
|
|
2031
|
-
sitemapManifestTraceFile
|
|
2032
|
-
...agentSkillTraceGlobs
|
|
2111
|
+
sitemapManifestTraceFile
|
|
2033
2112
|
])],
|
|
2034
2113
|
[DEFAULT_MCP_ROUTE]: [...new Set([
|
|
2035
2114
|
...existingTracingIncludes[DEFAULT_MCP_ROUTE] ?? [],
|
|
2036
2115
|
docsTraceGlob,
|
|
2037
|
-
skillTraceFile
|
|
2038
|
-
...agentSkillTraceGlobs
|
|
2116
|
+
skillTraceFile
|
|
2039
2117
|
])]
|
|
2040
2118
|
};
|
|
2041
2119
|
return withMDX(nextConfig);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/next",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.63",
|
|
4
4
|
"description": "Next.js adapter for @farming-labs/docs — MDX config wrapper",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -86,6 +86,7 @@
|
|
|
86
86
|
}
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
|
+
"@babel/parser": "7.29.7",
|
|
89
90
|
"@mdx-js/loader": "^3.1.0",
|
|
90
91
|
"@mdx-js/react": "^3.1.0",
|
|
91
92
|
"@next/mdx": "^16.1.6",
|
|
@@ -100,17 +101,18 @@
|
|
|
100
101
|
"zod": "^4.3.6"
|
|
101
102
|
},
|
|
102
103
|
"devDependencies": {
|
|
104
|
+
"@babel/types": "7.29.7",
|
|
103
105
|
"@types/node": "^22.10.0",
|
|
104
106
|
"@types/react": "^19.2.2",
|
|
105
107
|
"@types/react-dom": "^19.2.2",
|
|
106
108
|
"tsdown": "^0.20.3",
|
|
107
109
|
"typescript": "^5.9.3",
|
|
108
110
|
"vitest": "^4.1.8",
|
|
109
|
-
"@farming-labs/
|
|
110
|
-
"@farming-labs/
|
|
111
|
+
"@farming-labs/theme": "0.2.63",
|
|
112
|
+
"@farming-labs/docs": "0.2.63"
|
|
111
113
|
},
|
|
112
114
|
"peerDependencies": {
|
|
113
|
-
"@farming-labs/docs": ">=0.
|
|
115
|
+
"@farming-labs/docs": ">=0.2.61",
|
|
114
116
|
"@farming-labs/theme": ">=0.0.1",
|
|
115
117
|
"next": ">=16.0.0",
|
|
116
118
|
"react": ">=19.2.0",
|