diff --git a/docs-site/requirements.txt b/docs-site/requirements.txt new file mode 100644 index 000000000..e9079a625 --- /dev/null +++ b/docs-site/requirements.txt @@ -0,0 +1,5 @@ +# Pins the API reference doc generator used by scripts/generate-api-docs.sh. +# pydoc-markdown parses the SDK source statically (no install/import of the +# packages), pulling docspec-python transitively. Keep in sync with the version +# installed in .github/workflows/api-docs.yml. +pydoc-markdown==4.8.2 diff --git a/scripts/generate-api-docs.sh b/scripts/generate-api-docs.sh new file mode 100755 index 000000000..e0b469fb4 --- /dev/null +++ b/scripts/generate-api-docs.sh @@ -0,0 +1,116 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -euo pipefail + +PACKAGE="${1:?package required (core|adk|langchain|llamaindex)}" +VERSION="${2:?version required (e.g. v1.0.0 or dev)}" +BASE_URL="${3:-/}" + +# Absolute repo root: the pydoc-markdown config's search_path is resolved +# relative to the config file's directory (a temp dir), not the CWD, so it must +# be absolute. Captured before the later `cd docs-site`. +ROOT="$(pwd)" + +# Map the URL slug to its package title and the curated list of public modules +# to document. The list is explicit (not whole-package recursion) so internal +# surface -- utils, itransport, the mcp_transport.v* protocol impls, and every +# package's version module -- stays out of the page, matching the Go/JS docs. +case "$PACKAGE" in + core) + TITLE="Core" + MODULES=(client sync_client tool sync_tool auth_methods protocol) ;; + adk) + TITLE="ADK" + MODULES=(client tool toolset credentials) ;; + langchain) + TITLE="LangChain" + MODULES=(client tools async_client async_tools) ;; + llamaindex) + TITLE="LlamaIndex" + MODULES=(client tools async_client async_tools) ;; + *) echo "Unknown package: $PACKAGE" >&2; exit 1 ;; +esac + +DIR="packages/toolbox-${PACKAGE}" +MODULE="toolbox_${PACKAGE}" + +# Per-build content tree in a temp dir, kept out of the checked-in +# docs-site/content so concurrent package builds never trample each other. +# The package's API reference is the home page, so /// lands +# directly on the docs (the repo README lives only at the site root). +CONTENT_DIR="$(mktemp -d)" +CFG="$(mktemp)" +# return 0 so a leftover non-zero never becomes the script's exit code, since an +# EXIT trap's last status replaces it. +cleanup() { rm -rf "$CONTENT_DIR"; rm -f "$CFG"; return 0; } +trap cleanup EXIT + +# Build the YAML module block (" - toolbox_." per line). +MODULE_YAML="" +for m in "${MODULES[@]}"; do + MODULE_YAML+=" - ${MODULE}.${m}"$'\n' +done + +# Generate the package's API reference as a single markdown page. +# pydoc-markdown parses the source statically (AST via docspec-python); it never +# imports the package, so the wrappers (adk/langchain/llamaindex) document their +# toolbox_core references as plain names without core being installed or built -- +# no dependency build step is needed for any package. +# filter (exclude_private, skip_empty_modules): drop _-prefixed internals and +# empty modules; dunders like __init__/__call__ are kept (public surface). +# google: parse Google-style Args:/Returns:/Raises: blocks. +# crossref: resolve {@link X}-style refs to in-page #anchors (no stray .md). +# renderer markdown -> a single _index.md, the Hugo section index for +# ///. Parameters render as lists (Go-SDK style); the Raises +# section is kept as pydoc-markdown emits it. +cat > "$CFG" < ()" +# heading) to the generated page so Docsy renders the section index correctly. +tmp="$(mktemp)" +{ printf -- '---\ntitle: "%s"\ntype: docs\n---\n\n' "${TITLE} (${VERSION})"; cat "${CONTENT_DIR}/_index.md"; } > "$tmp" +mv "$tmp" "${CONTENT_DIR}/_index.md" + +cd docs-site +HUGO_PARAMS_VERSION="${VERSION}" HUGO_PARAMS_PACKAGE="${PACKAGE}" hugo \ + --minify \ + --contentDir "${CONTENT_DIR}" \ + --baseURL "${BASE_URL}${PACKAGE}/${VERSION}/" \ + --destination "public/${PACKAGE}/${VERSION}" + +# Hoist the home-scoped outputs from this version's dir up to the package root, +# where the navbar version selector fetches them. They list every version of the +# package, so they must live once per package (not per version) and are shared +# across all of this package's version pages. keep_files on deploy preserves them. +mv "public/${PACKAGE}/${VERSION}/releases.releases" "public/${PACKAGE}/releases.releases" +mkdir -p "public/${PACKAGE}/latest" +mv "public/${PACKAGE}/${VERSION}/latest.html" "public/${PACKAGE}/latest/index.html" diff --git a/scripts/generate-root.sh b/scripts/generate-root.sh new file mode 100755 index 000000000..dba506136 --- /dev/null +++ b/scripts/generate-root.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -euo pipefail + +BASE_URL="${1:-/}" + +# Render the repo README (from the checked-out tag) as the root landing page. +# Built only on tag pushes so the root URL tracks the latest release and stays +# stable between main-branch dev builds. +CONTENT_DIR="$(mktemp -d)" +trap 'rm -rf "$CONTENT_DIR"' EXIT + +cat > "$CONTENT_DIR/_index.md" </ { intoc = 1 } + intoc { if (//) intoc = 0; next } + !h1done && /^# / { h1done = 1; next } + { print } +' README.md >> "$CONTENT_DIR/_index.md" + +cd docs-site +hugo \ + --minify \ + --contentDir "${CONTENT_DIR}" \ + --baseURL "${BASE_URL}" \ + --destination "public"