Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ private void start() {

if (needsDocGeneration()) {
webSite = generateDocs(config.getSourceRoot());
exportLlmTxtIfNeeded();
}

if (config.isPreviewMode()) {
Expand Down Expand Up @@ -150,6 +151,21 @@ public void export() {
FileUtils.writeTextContent(lookupPath, artifactsDirName);
}

private void exportLlmTxtIfNeeded() {
Path llmTxtOutputPath = config.getLlmTxtOutputPath();
if (llmTxtOutputPath == null) {
return;
}

Path fullOutputPath = llmTxtOutputPath.isAbsolute() ?
llmTxtOutputPath :
config.getSourceRoot().resolve(llmTxtOutputPath);

ProgressReporter.reportPhase("exporting llm.txt");
Path llmTxtSource = deployPath.resolve("llm.txt");
copyFile(llmTxtSource, fullOutputPath);
}

private static void copyFile(Path source, Path target) {
ConsoleOutputs.out("copy ", Color.PURPLE, source, Color.YELLOW, " to ", Color.PURPLE, target);
FileUtils.copyFile(source, target);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ public enum OptionKey {
DEPLOY("deploy", "documentation deploy root dir", true, false),

DOC_ID("doc-id", "documentation id", true, false),
LLM_TXT_OUTPUT_PATH("llm-txt-output-path", "save llm.txt to specified path during build", true, false),

EXPORT("export", "export destination directory", true, false),

Expand Down Expand Up @@ -153,6 +154,7 @@ public boolean hasMultipleArgs() {
Set<OptionKey> buildOptions = EnumSet.copyOf(commonOptions);
buildOptions.add(OptionKey.DOC_ID);
buildOptions.add(OptionKey.DEPLOY);
buildOptions.add(OptionKey.LLM_TXT_OUTPUT_PATH);
COMMAND_OPTIONS.put(Command.BUILD, buildOptions);

Set<OptionKey> exportOptions = EnumSet.copyOf(commonOptions);
Expand Down Expand Up @@ -227,6 +229,7 @@ public enum ModifiedTimeStrategy {
private List<String> specifiedCustomCommands;
private String actor;
private List<String> lookupPaths;
private Path llmTxtOutputPath;

private boolean isValidateExternalLinks;

Expand Down Expand Up @@ -335,28 +338,30 @@ public ModifiedTimeStrategy getModifiedTimeStrategy() {
return modifiedTimeStrategy;
}

public Path getLlmTxtOutputPath() {
return llmTxtOutputPath;
}

public Path getDeployRoot() {
return validateIsSet("deployRoot", deployRoot);
}

public void print() {
printVersion();

if (!isScaffoldMode() && !isServeMode()) {
print("source root", sourceRoot);
}

if (isPreviewMode() || isServeMode()) {
print("source root", sourceRoot);
print("deploy root", deployRoot);
print(" host", host);
print(" port", port);
}

if (isGenerateOnlyMode()) {
print(" doc id", docId);
}

if (isExportMode()) {
} else if (isGenerateOnlyMode()) {
print(" source root", sourceRoot);
print(" doc id", docId);
if (getLlmTxtOutputPath() != null) {
print("llm txt output path", llmTxtOutputPath);
}
} else if (isExportMode()) {
print("source root", sourceRoot);
print("export root", exportRoot);
}
}
Expand Down Expand Up @@ -435,6 +440,10 @@ private void parseArgs(String[] args) {
Arrays.asList(commandLine.getOptionValues(OptionKey.LOOKUP_PATHS.getKey())):
Collections.emptyList();

llmTxtOutputPath = commandLine.hasOption(OptionKey.LLM_TXT_OUTPUT_PATH.getKey()) ?
Paths.get(commandLine.getOptionValue(OptionKey.LLM_TXT_OUTPUT_PATH.getKey())).toAbsolutePath() :
null;

modifiedTimeStrategy = determineModifiedTimeStrategy(commandLine);

validateMode(commandLine);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ class ZnaiCliConfigTest {
OptionKey.VALIDATE_EXTERNAL_LINKS,
OptionKey.ACTOR,
OptionKey.MODIFIED_TIME,
OptionKey.LOOKUP_PATHS
OptionKey.LOOKUP_PATHS,
OptionKey.LLM_TXT_OUTPUT_PATH
)
}

Expand Down
8 changes: 8 additions & 0 deletions znai-docs/pre-filter/maven-plugin-llm.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<plugin>
<groupId>org.testingisdocumenting.znai</groupId>
<artifactId>znai-maven-plugin</artifactId>
<version>${project.version}</version>
<configuration>
<llmTxtOutputPath>\${project.basedir}/full-guide.md</llmTxtOutputPath>
</configuration>
</plugin>
14 changes: 13 additions & 1 deletion znai-docs/znai/flow/llm.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,16 @@ Note: Initial experimental support

Znai generates a single markdown file called `llm.txt` to be used by LLMs.
It is deployed at the root of the documentation and can be used in multiple scenarios.
The primary use case is to provide guide context to systems like Claude Code.
The primary use case is to provide guide context to systems like Claude Code.

# Generate During Build To Keep In Repository

`````tabs
CLI:
```cli {highlight: "llm-txt"}
znai build --llm-txt-output-path full-guide.md
```

Maven: :include-file: maven-plugin-llm.xml {title: "expose llm.txt to source tree", highlight: "llmTxt"}
`````

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Add: Option to expose llm.txt during build to be pushed to repo
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,18 @@ class ZnaiMavenBuildRunner extends AbstractMojo {
@Parameter(defaultValue = '${project.build.directory}')
private String deployRoot

@Parameter
private String llmTxtOutputPath

@Override
void execute() throws MojoExecutionException, MojoFailureException {
def extraArgs = llmTxtOutputPath ?
['llm-txt-output-path': llmTxtOutputPath] : [:]
ZnaiMavenRunner.run(new MavenPluginConsoleOuput(getLog()), ["build"], [
'doc-id': docId,
source : sourceRoot,
deploy : deployRoot,
*: extraArgs
])
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public LlmContentGenerator(DocMeta docMeta,

public String generateContent() {
StringBuilder llmContent = new StringBuilder();
llmContent.append("[//]: # (this is an auto generated file)\n");
llmContent.append("\"").append(docMeta.getTitle()).append("\" full guide:\n\n");

pageByTocItem.forEach((tocItem, page) -> {
Expand All @@ -62,11 +63,11 @@ public String generateContent() {
return;
}

llmContent.append("# ").append(tocItem.getChapterTitle()).append(" :: ").append(tocItem.getPageTitle());
var headerParts = Stream.of(tocItem.isIndex() ? "Index": "", tocItem.getChapterTitle(), tocItem.getPageTitle(), section.title())
.filter(s -> !s.isEmpty())
.collect(Collectors.joining(" :: "));

if (!section.title().isEmpty()) {
llmContent.append(" :: ").append(section.title());
}
llmContent.append("# ").append(headerParts);
llmContent.append("\n");

String sectionUrl = section.title().isEmpty()
Expand Down