You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by gs...@apache.org on 2026/10/09 17:54:27 UTC
(tooling-llmao) branch main updated: help: link My Keys and Models, and hide Sign in when already signed in
This is an automated email from the ASF dual-hosted git repository.
gstein pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-llmao.git
The following commit(s) were added to refs/heads/main by this push:
new 9e82e74 help: link My Keys and Models, and hide Sign in when already signed in
9e82e74 is described below
commit 9e82e74758270f7c917d61859c2f056e294e673c
Author: Greg Stein <gs...@gmail.com>
AuthorDate: Fri Oct 9 12:54:20 2026 -0500
help: link My Keys and Models, and hide Sign in when already signed in
The articles named those pages without linking them. My Keys goes to /keys and the Models page goes to /models. Help Home and the FAQ use [if-any uid] from basic_info, so a signed-in reader is sent to My Keys and a signed-out reader gets Sign in. A file with that directive is EZT before Markdown, and a literal bracket is written [[]].
Co-authored-by: Grok <gr...@x.ai>
---
docs/help-authoring.md | 2 ++
docs/help/claude-code.md | 4 ++--
docs/help/codex.md | 2 +-
docs/help/faq.md | 19 ++++++++++++-------
docs/help/grok-build.md | 2 +-
docs/help/index.md | 17 +++++++++++------
docs/help/pi.md | 4 ++--
pages.py | 17 ++++++++++++++---
tests/test_help.py | 7 +++++++
9 files changed, 52 insertions(+), 22 deletions(-)
diff --git a/docs/help-authoring.md b/docs/help-authoring.md
index 96f3864..7a066ea 100644
--- a/docs/help-authoring.md
+++ b/docs/help-authoring.md
@@ -2,6 +2,8 @@
`docs/help/*.md` is rendered on each request by `pages.py`. `index.md` is `/help`. Any other file is `/help/<slug>`. Raw HTML in those files is left intact, because the files are committed here. Images belong under `static/` and are referenced as `/static/...`.
+A file that contains `[if-any` is run through EZT before Markdown. The data is the page's `basic_info`, and the field used here is `uid` (set when someone is signed in, None otherwise). Write a literal `[` in that file as `[[]]`, which is how a Markdown link survives: `[[]My Keys](/keys)`.
+
User-facing pages name `https://llm.apache.org` and the OpenAI API. They do not name LiteLLM.
## Mermaid, when we want it
diff --git a/docs/help/claude-code.md b/docs/help/claude-code.md
index b410628..a075e15 100644
--- a/docs/help/claude-code.md
+++ b/docs/help/claude-code.md
@@ -1,6 +1,6 @@
# Claude Code
-Point Claude Code at `https://llm.apache.org`. Use a model id from the Models page. This example uses `gemma4-26b`, an open-weight model the gateway hosts. `$LLMAO_KEY` is the personal access token from My Keys.
+Point Claude Code at `https://llm.apache.org`. Use a model id from the [Models page](/models). This example uses `gemma4-26b`, an open-weight model the gateway hosts. `$LLMAO_KEY` is the personal access token from [My Keys](/keys).
```sh
export ANTHROPIC_BASE_URL=https://llm.apache.org
@@ -17,7 +17,7 @@ claude
Set `ANTHROPIC_AUTH_TOKEN`, not `ANTHROPIC_API_KEY`. The base URL has no `/v1`. Every role uses the same model, because the gateway answers only for the models it serves.
-`CLAUDE_CODE_MAX_CONTEXT_TOKENS` matters. Claude Code assumes a 200k window for a model it does not recognise and compacts too late. Set it below the model's window. 120000 against 131072 leaves room for the response. The Models page lists each window.
+`CLAUDE_CODE_MAX_CONTEXT_TOKENS` matters. Claude Code assumes a 200k window for a model it does not recognise and compacts too late. Set it below the model's window. 120000 against 131072 leaves room for the response. The [Models page](/models) lists each window.
Prefer `gemma4-26b`. A model that reasons before it emits can sit silent long enough that Claude Code abandons the stream and retries. `gemma4-26b` starts emitting immediately.
diff --git a/docs/help/codex.md b/docs/help/codex.md
index 40a7419..9e51877 100644
--- a/docs/help/codex.md
+++ b/docs/help/codex.md
@@ -1,6 +1,6 @@
# Codex
-Codex uses the Responses API under `/v1`. Put this in `$CODEX_HOME/config.toml` (by default `~/.codex/config.toml`). `$LLMAO_KEY` is the personal access token from My Keys. The model id comes from the Models page. This example uses `qwen3.8-27b`.
+Codex uses the Responses API under `/v1`. Put this in `$CODEX_HOME/config.toml` (by default `~/.codex/config.toml`). `$LLMAO_KEY` is the personal access token from [My Keys](/keys). The model id comes from the [Models page](/models). This example uses `qwen3.8-27b`.
```toml
model_provider = "llmao"
diff --git a/docs/help/faq.md b/docs/help/faq.md
index a145c64..e2e2c19 100644
--- a/docs/help/faq.md
+++ b/docs/help/faq.md
@@ -2,16 +2,21 @@
## Where do I get a key?
-Sign in, open My Keys, and create a personal key. The model id on the Models page is the `model` parameter.
+[if-any uid]
+Open [[]My Keys](/keys) and create a personal key.
+[else]
+[[]Sign in](/auth?login=/), open [[]My Keys](/keys), and create a personal key.
+[end]
+The model id on the [[]Models page](/models) is the `model` parameter.
## How do I connect a tool?
Point a tool that speaks the OpenAI API at `https://llm.apache.org` and use your personal access token as the API key. Setup for each tool:
-* [Claude Code](/help/claude-code)
-* [Codex](/help/codex)
-* [Grok Build](/help/grok-build)
-* [Pi](/help/pi)
+* [[]Claude Code](/help/claude-code)
+* [[]Codex](/help/codex)
+* [[]Grok Build](/help/grok-build)
+* [[]Pi](/help/pi)
## Why did a request succeed with an empty answer?
@@ -23,7 +28,7 @@ A small output budget on a reasoning model can return HTTP 200 with empty conten
## Why was the request rejected before it ran?
-Prompt and output share the context window. A client whose output budget is larger than that window is rejected before the prompt is counted. Raising the client's context setting makes that worse. The Models page lists each window.
+Prompt and output share the context window. A client whose output budget is larger than that window is rejected before the prompt is counted. Raising the client's context setting makes that worse. The [[]Models page](/models) lists each window.
## Why did the answer stop at a round number?
@@ -31,4 +36,4 @@ A stop on a round token count is the output budget. Raise it. A stop on a round
## Who can see my prompts?
-The Models page states that for each model. Private means every deployment runs on infrastructure the ASF controls. External means every request is sent to a third-party provider. MIXED means a request may take either path, and you cannot choose which.
+The [[]Models page](/models) states that for each model. Private means every deployment runs on infrastructure the ASF controls. External means every request is sent to a third-party provider. MIXED means a request may take either path, and you cannot choose which.
diff --git a/docs/help/grok-build.md b/docs/help/grok-build.md
index 4773ff6..1c3026d 100644
--- a/docs/help/grok-build.md
+++ b/docs/help/grok-build.md
@@ -1,6 +1,6 @@
# Grok Build
-Grok Build checks a model id against its own catalog, so the gateway's model is a `[model.<id>]` block on chat completions. Put this in `~/.grok/config.toml`. The model id comes from the Models page. This example uses `qwen3.8-27b`. The key is the personal access token from My Keys.
+Grok Build checks a model id against its own catalog, so the gateway's model is a `[model.<id>]` block on chat completions. Put this in `~/.grok/config.toml`. The model id comes from the [Models page](/models). This example uses `qwen3.8-27b`. The key is the personal access token from [My Keys](/keys).
```toml
[model."qwen3.8-27b"]
diff --git a/docs/help/index.md b/docs/help/index.md
index 4597e0a..85615ee 100644
--- a/docs/help/index.md
+++ b/docs/help/index.md
@@ -1,14 +1,19 @@
# Help
-Apache LLMAO is the ASF's gateway to AI models. Sign in with your ASF account, create a personal access token, and use that token as the key in a tool that speaks the OpenAI API. Usage is attributed to you.
+Apache LLMAO is the ASF's gateway to AI models.
+[if-any uid]
+Create a personal access token on [[]My Keys](/keys), and use that token as the key in a tool that speaks the OpenAI API. Usage is attributed to you.
+[else]
+[[]Sign in](/auth?login=/) with your ASF account, create a personal access token, and use that token as the key in a tool that speaks the OpenAI API. Usage is attributed to you.
+[end]
Point the tool at `https://llm.apache.org`. The endpoint follows the OpenAI API.
-* [FAQ](/help/faq)
-* [Claude Code](/help/claude-code)
-* [Codex](/help/codex)
-* [Grok Build](/help/grok-build)
-* [Pi](/help/pi)
+* [[]FAQ](/help/faq)
+* [[]Claude Code](/help/claude-code)
+* [[]Codex](/help/codex)
+* [[]Grok Build](/help/grok-build)
+* [[]Pi](/help/pi)
## More tools
diff --git a/docs/help/pi.md b/docs/help/pi.md
index 5161867..d42d598 100644
--- a/docs/help/pi.md
+++ b/docs/help/pi.md
@@ -1,6 +1,6 @@
# Pi
-This connects the Pi coding agent to `https://llm.apache.org/v1` with the [pi-localllm-provider](https://www.npmjs.com/package/pi-localllm-provider) extension. You need Pi installed (`pi --version`; see [pi.dev](https://pi.dev)) and a personal access token from My Keys.
+This connects the Pi coding agent to `https://llm.apache.org/v1` with the [pi-localllm-provider](https://www.npmjs.com/package/pi-localllm-provider) extension. You need Pi installed (`pi --version`; see [pi.dev](https://pi.dev)) and a personal access token from [My Keys](/keys).
Install the extension:
@@ -20,4 +20,4 @@ Choose **Add server**.
2. Base URL: `https://llm.apache.org/v1`
3. API key: your personal access token.
-Confirm the server. Pi lists the models the gateway offers. Enable all of them, or a subset. They then sit alongside your other providers. The current set includes `gemma4-26b`, `qwen3-8b`, and `qwen3.8-27b`. The Models page is the list.
+Confirm the server. Pi lists the models the gateway offers. Enable all of them, or a subset. They then sit alongside your other providers. The current set includes `gemma4-26b`, `qwen3-8b`, and `qwen3.8-27b`. The [Models page](/models) is the list.
diff --git a/pages.py b/pages.py
index 877cae0..63bb199 100644
--- a/pages.py
+++ b/pages.py
@@ -20,6 +20,7 @@
from __future__ import annotations
import functools
+import io
import pathlib
import re
import time
@@ -268,10 +269,13 @@ def _help_title(text: str, slug: str) -> str:
return slug
-def help_article(slug: str, directory: pathlib.Path | None = None):
+def help_article(slug: str, directory: pathlib.Path | None = None, uid=None):
"""One help article, or None when the slug is not a file in the directory.
Raw HTML in the markdown is left intact. The files are committed here.
+ A file that contains ``[if-any`` is EZT first. ``uid`` comes from
+ ``basic_info`` and is None when nobody is signed in. A literal ``[``
+ in that file is written ``[[]]``.
"""
if not _HELP_SLUG.fullmatch(slug):
return None
@@ -280,9 +284,16 @@ def help_article(slug: str, directory: pathlib.Path | None = None):
if not path.is_file():
return None
text = path.read_text(encoding="utf-8")
+ title = _help_title(text, slug)
+ if "[if-any " in text:
+ template = ezt.Template(compress_whitespace=0)
+ template.parse(text, base_format=ezt.FORMAT_RAW)
+ buf = io.StringIO()
+ template.generate(buf, edict(uid=uid))
+ text = buf.getvalue()
return edict(
slug=slug,
- title=_help_title(text, slug),
+ title=title,
html=cmarkgfm.github_flavored_markdown_to_html(text, options=Options.CMARK_OPT_UNSAFE),
)
@@ -305,7 +316,7 @@ def help_articles(directory: pathlib.Path | None = None) -> list:
@APP.use_template(TEMPLATES / "help.ezt")
@page(title="Help")
async def help_page(result, slug: str = "index"):
- doc = help_article(slug)
+ doc = help_article(slug, uid=result.uid)
if doc is None:
quart.abort(404)
result.title = doc.title
diff --git a/tests/test_help.py b/tests/test_help.py
index ea37d9c..d58e830 100644
--- a/tests/test_help.py
+++ b/tests/test_help.py
@@ -75,6 +75,13 @@ def test_index_links_each_tool_page():
prose = "\n".join(path.read_text(encoding="utf-8") for path in help_dir.glob("*.md"))
assert "LiteLLM" not in prose
assert "Anthropic" not in prose
+ assert "/keys" in prose
+ assert "/models" in prose
+ signed_out = _pages().help_article("index")
+ signed_in = _pages().help_article("index", uid="gstein")
+ assert 'href="/auth?login=/"' in signed_out.html
+ assert "/auth?login=/" not in signed_in.html
+ assert 'href="/keys"' in signed_in.html
def test_home_page_does_not_list_api_paths():
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org