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
74 changes: 63 additions & 11 deletions .agents/skills/sync-openapi-spec/scripts/sync_openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,20 +465,46 @@ def transform(source: dict[str, Any]) -> dict[str, Any]:
out["info"] = {**out["info"], **DOCS_INFO_OVERRIDES}

src_tags = source.get("tags") or []
out_tags = [
candidate_tags = [
t
for t in src_tags
if isinstance(t, dict) and t.get("name") not in EXCLUDED_TAGS
]
if out_tags:
out["tags"] = out_tags

src_paths = source.get("paths") or {}
kept_paths = {
path: strip_internal_operations(item)
for path, item in src_paths.items()
if isinstance(item, dict) and _should_keep_path(path, item)
}

tag_by_name = {
tag["name"]: tag
for tag in candidate_tags
if isinstance(tag.get("name"), str)
}
kept_tag_names = {
tag
for path_item in kept_paths.values()
for tag in _path_tags(path_item)
}
pending_parents = list(kept_tag_names)
while pending_parents:
tag_name = pending_parents.pop()
tag = tag_by_name.get(tag_name)
parent = tag.get("parent") if tag else None
if (
isinstance(parent, str)
and parent in tag_by_name
and parent not in kept_tag_names
):
kept_tag_names.add(parent)
pending_parents.append(parent)
out_tags = [
tag for tag in candidate_tags if tag.get("name") in kept_tag_names
]
if out_tags:
out["tags"] = out_tags
out["paths"] = kept_paths

seed_refs: set[str] = set()
Expand Down Expand Up @@ -584,11 +610,20 @@ def _summarize_drift(
def _unknown_classifications(source: dict[str, Any]) -> list[str]:
"""Flag tags or paths the policy doesn't already cover.

The skill's policy currently knows about the `agent`, `schedules`,
`factory`, and `networking` tags (kept) and `memory_stores`/`memory`/
`harness-support` (dropped). Anything else needs human triage.
The skill's policy knows about the public agent and factory tag
hierarchies, plus `memory_stores`/`memory`/`harness-support` (dropped).
Anything else needs human triage.
"""
KNOWN_TAGS = {"agent", "schedules", "factory", "networking"} | set(EXCLUDED_TAGS)
KNOWN_TAGS = {
"agent",
"schedules",
"factory",
"factory-notifications",
"factory-metrics",
"factory-scorers",
"factory-benchmarks",
"networking",
} | set(EXCLUDED_TAGS)

notes: list[str] = []
for tag in source.get("tags") or []:
Expand Down Expand Up @@ -618,10 +653,16 @@ def _unknown_classifications(source: dict[str, Any]) -> list[str]:
def _self_test() -> int:
"""Sanity-check the transform on a small synthetic spec."""
sample = {
"openapi": "3.0.0",
"openapi": "3.2.0",
"info": {"title": "t", "version": "1"},
"tags": [
{"name": "agent"},
{"name": "agent", "summary": "Agents"},
{
"name": "schedules",
"summary": "Scheduled Agents",
"parent": "agent",
},
{"name": "unused", "summary": "Unused"},
{"name": "memory_stores", "x-internal": True},
{"name": "harness-support"},
],
Expand Down Expand Up @@ -688,6 +729,13 @@ def _self_test() -> int:
"responses": {"200": {"description": "ok"}},
}
},
"/schedules": {
"get": {
"tags": ["schedules"],
"operationId": "listSchedules",
"responses": {"200": {"description": "ok"}},
}
},
},
"components": {
"securitySchemes": {"bearerAuth": {"type": "http", "scheme": "bearer"}},
Expand Down Expand Up @@ -778,6 +826,7 @@ def _self_test() -> int:
assert paths == {
"/agent/run",
"/agent/runs/{runId}/followups",
"/schedules",
}, f"unexpected paths: {paths}"

schemas = set(out["components"]["schemas"].keys())
Expand Down Expand Up @@ -810,8 +859,11 @@ def _self_test() -> int:
assert "BENCHMARK_TRIAL" not in pruned["description"]
assert "CUSTOM_WEBHOOK" not in pruned["description"]

tag_names = [t["name"] for t in out.get("tags") or []]
assert tag_names == ["agent"], f"unexpected tags: {tag_names}"
tags = {t["name"]: t for t in out.get("tags") or []}
assert set(tags) == {"agent", "schedules"}, f"unexpected tags: {set(tags)}"
assert tags["agent"]["summary"] == "Agents"
assert tags["schedules"]["summary"] == "Scheduled Agents"
assert tags["schedules"]["parent"] == "agent"

assert out["components"].get("securitySchemes"), "securitySchemes should be preserved"
assert out["info"]["title"] == "Warp Platform API"
Expand Down
10 changes: 8 additions & 2 deletions astro.config.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// @ts-check
import { readFileSync } from 'node:fs';
import { defineConfig, envField } from 'astro/config';
import remarkGfm from 'remark-gfm';
import mermaid from 'astro-mermaid';
Expand All @@ -7,6 +8,7 @@ import sitemap from '@astrojs/sitemap';
import starlight from '@astrojs/starlight';
import starlightLlmsTxt from 'starlight-llms-txt';
import starlightSidebarTopics from 'starlight-sidebar-topics';
import { parse } from 'yaml';
import pageTitleOverride from './src/plugins/page-title-override.ts';
import remarkHeadingVars from './src/plugins/heading-vars.ts';
import { varsTransformPlugin } from './src/plugins/vars-transform.ts';
Expand All @@ -15,6 +17,10 @@ import { sidebarTopics } from './src/sidebar.ts';
import docsMarkdownIntegration from './src/integrations/docs-markdown-integration.js';
import { DOCS_ORIGIN } from './src/lib/site.js';

const openApiVersion = parse(
readFileSync(new URL('./developers/agent-api-openapi.yaml', import.meta.url), 'utf8'),
).openapi;

// https://astro.build/config
export default defineConfig({
site: DOCS_ORIGIN,
Expand Down Expand Up @@ -200,12 +206,12 @@ export default defineConfig({
{
label: 'Oz Agent API (OpenAPI spec, YAML)',
url: 'https://docs.warp.dev/openapi.yaml',
description: 'Machine-readable OpenAPI 3.0 specification for the Oz Agent API.',
description: `Machine-readable OpenAPI ${openApiVersion} specification for the Oz Agent API.`,
},
{
label: 'Oz Agent API (OpenAPI spec, JSON)',
url: 'https://docs.warp.dev/openapi.json',
description: 'Machine-readable OpenAPI 3.0 specification (JSON format) for the Oz Agent API.',
description: `Machine-readable OpenAPI ${openApiVersion} specification (JSON format) for the Oz Agent API.`,
},
],
// Excludes pages that cause a stack overflow in hast-util-to-text
Expand Down
2 changes: 1 addition & 1 deletion src/pages/api.astro
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ const specBaseUrl = (specObject.servers as Array<{ url?: string }> | undefined)?
}
})();
</script>
<script is:inline src="https://cdn.jsdelivr.net/npm/@scalar/api-reference@1.57.1" crossorigin="anonymous"></script>
<script is:inline src="https://cdn.jsdelivr.net/npm/@scalar/api-reference@1.74.0" crossorigin="anonymous"></script>
<div class="api-feedback-links">
<DocsFeedbackLinks
editUrl="https://github.com/warpdotdev/docs/edit/main/developers/agent-api-openapi.yaml"
Expand Down
Loading