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