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
104 changes: 104 additions & 0 deletions automation/source-repo-templates/api-docs.python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,110 @@ jobs:
' "$f" > "$f.tmp" && mv "$f.tmp" "$f"
done

- name: Cross-link package overview re-export stubs
# pydoc-markdown emits an empty `## ClassName` heading on each
# `<package>/overview.md` for every name re-exported from the
# package's `__init__.py`. The actual class/function bodies
# live on submodule pages (e.g. `models.md`, `tools.md`), so
# the overview's right-side TOC entries lead to dead-end
# in-page anchors with no content.
#
# Replace the empty stub block with a clean `## API` section
# listing each symbol as a link to where it's actually
# defined. Mapping is built by scanning every non-overview
# page for canonical definitions:
# `## ClassName Objects` (h2 + " Objects" suffix) -> class
# `#### function_name` (h4) -> function
# Other heading shapes (h2 without "Objects", h3) are skipped
# because pydoc-markdown reuses them for re-export stubs and
# for class-internal sections respectively.
working-directory: ${{ env.OUTPUT_DIR }}
run: |
python3 - <<'PYINNER'
import pathlib
import re

root = pathlib.Path(".")

def slugify(text: str) -> str:
s = text.lower().replace("\\_", "_").replace("\\", "")
s = re.sub(r"[^a-z0-9_\s-]", "", s)
s = re.sub(r"\s+", "-", s.strip())
return s

heading_re = re.compile(
r'<a id="([^"]+)"></a>\n+(#{2,6})\s+([^\n]+?)\n'
)
Comment on lines +388 to +390
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The regex-based scanning for headings does not account for CommonMark inline code spans or blocks. If a documentation page contains an example code block that includes a string matching the anchor and heading pattern, it will be incorrectly indexed in the symbol_map. Per the general rules, parsing logic should respect code boundaries to avoid modifying or indexing content inside snippets.

References
  1. When processing Markdown/MDX files to escape curly braces for JSX compatibility, ensure the logic ignores content within inline code spans (backticks) to prevent breaking code snippets.


symbol_map: dict[tuple[str, str], tuple[str, str]] = {}
for md in root.rglob("*.md"):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of rglob without sorting results in non-deterministic behavior when building the symbol_map. If multiple files contain definitions for the same symbol name (e.g., in different submodules), the link target in the overview will depend on the filesystem iteration order. Sorting the file list ensures consistent results across different environments.

          for md in sorted(root.rglob("*.md")):

if md.name in ("overview.md", "README.md"):
continue
rel = md.relative_to(root).with_suffix("").as_posix()
text = md.read_text(encoding="utf-8")
for m in heading_re.finditer(text):
full_id = m.group(1)
level = len(m.group(2))
heading = m.group(3).strip()
parts = full_id.split(".")
if len(parts) < 3:
continue
parent = parts[-2]
# Class members (e.g. `Class.method`) sit under an
# uppercase parent — those are not standalone
# symbols and shouldn't be link targets here.
if parent and parent[0].isupper():
continue
is_class_def = level == 2 and heading.endswith(" Objects")
is_func_def = level == 4
if not (is_class_def or is_func_def):
continue
key = (parts[0], parts[-1])
symbol_map.setdefault(key, (rel, slugify(heading)))

# An empty stub is `<a id="pkg.Name"></a>\n\n## Name\n`
# followed by another anchor or end-of-file (no body
# in between).
stub_re = re.compile(
r'<a id="(?P<id>[^"]+)"></a>\n+##\s+(?P<heading>[^\n]+?)\n'
r'(?=\n<a id="|\s*\Z)'
)

rewritten = 0
for overview in root.rglob("overview.md"):
text = overview.read_text(encoding="utf-8")
stubs = list(stub_re.finditer(text))
if not stubs:
continue
pre = text[: stubs[0].start()].rstrip() + "\n\n"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This logic assumes that all stubs are located at the end of the overview.md file and that no important content exists after the first detected stub. By using text[: stubs[0].start()], any content following the first stub (such as a footer, manual notes, or even non-empty headings that didn't match the stub_re) will be permanently deleted during the rewrite. It would be safer to replace only the specific ranges occupied by the stubs or to ensure that trailing content is preserved.

overview_dir = overview.parent.relative_to(root).as_posix()
api_lines: list[str] = []
for stub in stubs:
full_id = stub.group("id")
parts = full_id.split(".")
if len(parts) != 2:
continue
package, name = parts
target = symbol_map.get((package, name))
if target:
target_rel, slug = target
if target_rel.startswith(overview_dir + "/"):
target_rel = target_rel[len(overview_dir) + 1:]
api_lines.append(
f"- [`{name}`](./{target_rel}#{slug})"
)
else:
# Symbol re-exported from `__init__.py` but not
# documented anywhere (e.g. typing helpers).
api_lines.append(f"- `{name}`")
if not api_lines:
continue
new_text = pre + "## API\n\n" + "\n".join(api_lines) + "\n"
overview.write_text(new_text, encoding="utf-8")
rewritten += 1
print(f" rewrote {rewritten} package overview pages")
PYINNER

- name: Build pages index
# Flat JSON array of generated Markdown paths (without
# extension) so the docs repo can later splice them into
Expand Down
31 changes: 8 additions & 23 deletions sdks/python/api/resq-dsa/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,11 @@ rabin_karp: Rabin-Karp string pattern matching algorithm.
>>> bloom.has("emergency")
True

<a id="resq_dsa.BloomFilter"></a>

## BloomFilter

<a id="resq_dsa.CountMinSketch"></a>

## CountMinSketch

<a id="resq_dsa.Graph"></a>

## Graph

<a id="resq_dsa.BoundedHeap"></a>

## BoundedHeap

<a id="resq_dsa.Trie"></a>

## Trie

<a id="resq_dsa.rabin_karp"></a>

## rabin\_karp
## API

- [`BloomFilter`](./bloom#bloomfilter-objects)
- [`CountMinSketch`](./count_min#countminsketch-objects)
- [`Graph`](./graph#graph-objects)
- [`BoundedHeap`](./heap#boundedheap-objects)
- [`Trie`](./trie#trie-objects)
- [`rabin_karp`](./trie#rabin_karp)
161 changes: 34 additions & 127 deletions sdks/python/api/resq-mcp/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,130 +14,37 @@ This package provides:
from resq_mcp import mcp
mcp.run()

<a id="resq_mcp.annotations"></a>

## annotations

<a id="resq_mcp.Settings"></a>

## Settings

<a id="resq_mcp.settings"></a>

## settings

<a id="resq_mcp.Coordinates"></a>

## Coordinates

<a id="resq_mcp.DetectedObject"></a>

## DetectedObject

<a id="resq_mcp.DisasterScenario"></a>

## DisasterScenario

<a id="resq_mcp.ErrorResponse"></a>

## ErrorResponse

<a id="resq_mcp.Sector"></a>

## Sector

<a id="resq_mcp.DeploymentRequest"></a>

## DeploymentRequest

<a id="resq_mcp.DeploymentStatus"></a>

## DeploymentStatus

<a id="resq_mcp.NetworkStatus"></a>

## NetworkStatus

<a id="resq_mcp.SectorAnalysis"></a>

## SectorAnalysis

<a id="resq_mcp.SectorStatusSummary"></a>

## SectorStatusSummary

<a id="resq_mcp.SwarmStatus"></a>

## SwarmStatus

<a id="resq_mcp.get_all_sectors_status"></a>

## get\_all\_sectors\_status

<a id="resq_mcp.get_drone_swarm_status"></a>

## get\_drone\_swarm\_status

<a id="resq_mcp.request_drone_deployment"></a>

## request\_drone\_deployment

<a id="resq_mcp.scan_current_sector"></a>

## scan\_current\_sector

<a id="resq_mcp.OptimizationStrategy"></a>

## OptimizationStrategy

<a id="resq_mcp.SimulationRequest"></a>

## SimulationRequest

<a id="resq_mcp.get_optimization_strategy"></a>

## get\_optimization\_strategy

<a id="resq_mcp.run_simulation"></a>

## run\_simulation

<a id="resq_mcp.IncidentReport"></a>

## IncidentReport

<a id="resq_mcp.IncidentValidation"></a>

## IncidentValidation

<a id="resq_mcp.MissionParameters"></a>

## MissionParameters

<a id="resq_mcp.update_mission_params"></a>

## update\_mission\_params

<a id="resq_mcp.validate_incident"></a>

## validate\_incident

<a id="resq_mcp.PreAlert"></a>

## PreAlert

<a id="resq_mcp.VulnerabilityMap"></a>

## VulnerabilityMap

<a id="resq_mcp.get_predictive_alerts"></a>

## get\_predictive\_alerts

<a id="resq_mcp.get_vulnerability_map"></a>

## get\_vulnerability\_map

<a id="resq_mcp.mcp"></a>

## mcp
## API

- `annotations`
- [`Settings`](./core/config#settings-objects)
- [`settings`](./core/config#settings)
- [`Coordinates`](./models#coordinates-objects)
- [`DetectedObject`](./models#detectedobject-objects)
- [`DisasterScenario`](./models#disasterscenario-objects)
- [`ErrorResponse`](./models#errorresponse-objects)
- [`Sector`](./models#sector-objects)
- [`DeploymentRequest`](./models#deploymentrequest-objects)
- [`DeploymentStatus`](./models#deploymentstatus-objects)
- [`NetworkStatus`](./models#networkstatus-objects)
- [`SectorAnalysis`](./models#sectoranalysis-objects)
- [`SectorStatusSummary`](./models#sectorstatussummary-objects)
- [`SwarmStatus`](./models#swarmstatus-objects)
- [`get_all_sectors_status`](./tools#get_all_sectors_status)
- [`get_drone_swarm_status`](./tools#get_drone_swarm_status)
- [`request_drone_deployment`](./tools#request_drone_deployment)
- [`scan_current_sector`](./tools#scan_current_sector)
- [`OptimizationStrategy`](./models#optimizationstrategy-objects)
- [`SimulationRequest`](./models#simulationrequest-objects)
- [`get_optimization_strategy`](./dtsop/service#get_optimization_strategy)
- [`run_simulation`](./dtsop/tools#run_simulation)
- [`IncidentReport`](./models#incidentreport-objects)
- [`IncidentValidation`](./models#incidentvalidation-objects)
- [`MissionParameters`](./models#missionparameters-objects)
- [`update_mission_params`](./hce/tools#update_mission_params)
- [`validate_incident`](./hce/tools#validate_incident)
- [`PreAlert`](./models#prealert-objects)
- [`VulnerabilityMap`](./models#vulnerabilitymap-objects)
- [`get_predictive_alerts`](./pdie/service#get_predictive_alerts)
- [`get_vulnerability_map`](./pdie/service#get_vulnerability_map)
- [`mcp`](./server#mcp)
Loading