|
| 1 | +#!/usr/bin/env bash |
| 2 | +set -euo pipefail |
| 3 | + |
| 4 | +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| 5 | +REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)" |
| 6 | +COMPONENT_PATH="$REPO_ROOT/tests/playground-ci/component" |
| 7 | + |
| 8 | +EXTENSION_PATH="${HOMEBOY_EXTENSION_PATH:-/Users/chubes/Developer/homeboy-extensions/wordpress}" |
| 9 | +AGENTS_API_PATH="${AGENTS_API_PATH:-$REPO_ROOT}" |
| 10 | +DM_PATH="${DM_PATH:-/Users/chubes/Developer/data-machine}" |
| 11 | +DMC_PATH="${DMC_PATH:-/Users/chubes/Developer/data-machine-code}" |
| 12 | +OPENAI_PROVIDER_PATH="${OPENAI_PROVIDER_PATH:-/Users/chubes/Studio/intelligence-chubes4/wp-content/plugins/ai-provider-for-openai}" |
| 13 | +STUDIO_SITE_PATH="${STUDIO_SITE_PATH:-/Users/chubes/Studio/intelligence-chubes4}" |
| 14 | +DOCS_AGENT_OPENAI_MODEL="${DOCS_AGENT_OPENAI_MODEL:-gpt-5.5}" |
| 15 | +DOCS_AGENT_TARGET_REPO="${DOCS_AGENT_TARGET_REPO:-Automattic/agents-api}" |
| 16 | +DOCS_AGENT_REF="${DOCS_AGENT_REF:-main}" |
| 17 | +DOCS_AGENT_WORKFLOW="${DOCS_AGENT_WORKFLOW:-technical}" |
| 18 | +DOCS_AGENT_PROMPT="${DOCS_AGENT_PROMPT:-Generate or update technical developer documentation for Agents API from source code. Open a documentation PR only if needed.}" |
| 19 | + |
| 20 | +case "$DOCS_AGENT_WORKFLOW" in |
| 21 | + technical) |
| 22 | + DOCS_AGENT_PIPELINE_SLUG="technical-docs-pipeline" |
| 23 | + DOCS_AGENT_FLOW_SLUG="technical-docs-flow" |
| 24 | + DOCS_AGENT_WORKLOAD_ID="technical-docs-generation" |
| 25 | + DOCS_AGENT_WORKLOAD_LABEL="Run Docs Agent technical documentation" |
| 26 | + DOCS_AGENT_AUDIENCE="technical developer-facing" |
| 27 | + ;; |
| 28 | + user) |
| 29 | + DOCS_AGENT_PIPELINE_SLUG="user-docs-pipeline" |
| 30 | + DOCS_AGENT_FLOW_SLUG="user-docs-flow" |
| 31 | + DOCS_AGENT_WORKLOAD_ID="user-docs-generation" |
| 32 | + DOCS_AGENT_WORKLOAD_LABEL="Run Docs Agent user documentation" |
| 33 | + DOCS_AGENT_AUDIENCE="non-technical user-facing" |
| 34 | + ;; |
| 35 | + *) |
| 36 | + echo "ERROR: DOCS_AGENT_WORKFLOW must be technical or user" >&2 |
| 37 | + exit 1 |
| 38 | + ;; |
| 39 | +esac |
| 40 | + |
| 41 | +if [ ! -f "$EXTENSION_PATH/scripts/bench/bench-runner.sh" ]; then |
| 42 | + echo "ERROR: Homeboy WordPress extension not found at $EXTENSION_PATH" >&2 |
| 43 | + exit 1 |
| 44 | +fi |
| 45 | +if [ ! -d "$AGENTS_API_PATH" ] || [ ! -d "$DM_PATH" ] || [ ! -d "$DMC_PATH" ]; then |
| 46 | + echo "ERROR: Agents API, Data Machine, and Data Machine Code checkouts are required" >&2 |
| 47 | + exit 1 |
| 48 | +fi |
| 49 | +if [ ! -d "$OPENAI_PROVIDER_PATH" ]; then |
| 50 | + echo "ERROR: AI Provider for OpenAI plugin not found at $OPENAI_PROVIDER_PATH" >&2 |
| 51 | + exit 1 |
| 52 | +fi |
| 53 | +if ! command -v jq >/dev/null 2>&1; then |
| 54 | + echo "ERROR: jq required" >&2 |
| 55 | + exit 1 |
| 56 | +fi |
| 57 | + |
| 58 | +GITHUB_TOKEN="${GITHUB_TOKEN:-${GH_TOKEN:-}}" |
| 59 | +if [ -z "$GITHUB_TOKEN" ] && command -v gh >/dev/null 2>&1; then |
| 60 | + GITHUB_TOKEN="$(gh auth token 2>/dev/null || true)" |
| 61 | +fi |
| 62 | +if [ -z "$GITHUB_TOKEN" ]; then |
| 63 | + echo "ERROR: GITHUB_TOKEN or GH_TOKEN is required, or gh must be authenticated" >&2 |
| 64 | + exit 1 |
| 65 | +fi |
| 66 | + |
| 67 | +OPENAI_API_KEY="${OPENAI_API_KEY:-}" |
| 68 | +if [ -z "$OPENAI_API_KEY" ] && command -v studio >/dev/null 2>&1 && [ -d "$STUDIO_SITE_PATH" ]; then |
| 69 | + OPENAI_API_KEY="$(cd "$STUDIO_SITE_PATH" && studio wp option get connectors_ai_openai_api_key 2>/dev/null || true)" |
| 70 | +fi |
| 71 | +if [ -z "$OPENAI_API_KEY" ]; then |
| 72 | + echo "ERROR: OPENAI_API_KEY is required, or the local Studio site must store connectors_ai_openai_api_key" >&2 |
| 73 | + exit 1 |
| 74 | +fi |
| 75 | + |
| 76 | +CONFIG_TMPFILE=$(mktemp "${TMPDIR:-/tmp}/docs-agent-config.XXXXXX.json") |
| 77 | +RESULTS_TMPFILE=$(mktemp "${TMPDIR:-/tmp}/docs-agent-results.XXXXXX.json") |
| 78 | +TRANSCRIPT_ARTIFACT_DIR="$COMPONENT_PATH/artifacts/docs-agent" |
| 79 | + |
| 80 | +cleanup() { |
| 81 | + rm -f "$CONFIG_TMPFILE" "$RESULTS_TMPFILE" |
| 82 | +} |
| 83 | +trap cleanup EXIT |
| 84 | + |
| 85 | +rm -rf "$TRANSCRIPT_ARTIFACT_DIR" |
| 86 | +mkdir -p "$TRANSCRIPT_ARTIFACT_DIR" |
| 87 | + |
| 88 | +HE_AGENT_RUNNER="$EXTENSION_PATH/scripts/agent/run-datamachine-agent.sh" |
| 89 | +if [ ! -f "$HE_AGENT_RUNNER" ]; then |
| 90 | + echo "ERROR: generic Data Machine agent runner not found at $HE_AGENT_RUNNER" >&2 |
| 91 | + exit 1 |
| 92 | +fi |
| 93 | + |
| 94 | +EVENT_NAME="${GITHUB_EVENT_NAME:-manual}" |
| 95 | +TARGET_REF="${GITHUB_REF_NAME:-main}" |
| 96 | +HEAD_SHA="${GITHUB_SHA:-}" |
| 97 | +RUN_URL="" |
| 98 | +if [ -n "${GITHUB_SERVER_URL:-}" ] && [ -n "${GITHUB_REPOSITORY:-}" ] && [ -n "${GITHUB_RUN_ID:-}" ]; then |
| 99 | + RUN_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" |
| 100 | +fi |
| 101 | + |
| 102 | +PROMPT=$(cat <<EOF |
| 103 | +${DOCS_AGENT_PROMPT} |
| 104 | +
|
| 105 | +Target repository: ${DOCS_AGENT_TARGET_REPO} |
| 106 | +Event name: ${EVENT_NAME} |
| 107 | +Target ref: ${TARGET_REF} |
| 108 | +Head SHA: ${HEAD_SHA} |
| 109 | +Workflow run: ${RUN_URL} |
| 110 | +Writable documentation paths: README.md, docs/** |
| 111 | +Selected docs workflow: ${DOCS_AGENT_WORKFLOW} (${DOCS_AGENT_AUDIENCE}) |
| 112 | +
|
| 113 | +Generate documentation from source code for the selected audience. If no documentation update is needed, finish cleanly without opening a pull request. If an update is needed, write only allowed documentation paths and open one pull request. |
| 114 | +EOF |
| 115 | +) |
| 116 | + |
| 117 | +jq -n \ |
| 118 | + --arg componentPath "$COMPONENT_PATH" \ |
| 119 | + --arg agentsApi "$AGENTS_API_PATH" \ |
| 120 | + --arg dm "$DM_PATH" \ |
| 121 | + --arg dmc "$DMC_PATH" \ |
| 122 | + --arg openaiProvider "$OPENAI_PROVIDER_PATH" \ |
| 123 | + --arg githubToken "$GITHUB_TOKEN" \ |
| 124 | + --arg openaiKey "$OPENAI_API_KEY" \ |
| 125 | + --arg model "$DOCS_AGENT_OPENAI_MODEL" \ |
| 126 | + --arg targetRepo "$DOCS_AGENT_TARGET_REPO" \ |
| 127 | + --arg docsAgentRef "$DOCS_AGENT_REF" \ |
| 128 | + --arg pipelineSlug "$DOCS_AGENT_PIPELINE_SLUG" \ |
| 129 | + --arg flowSlug "$DOCS_AGENT_FLOW_SLUG" \ |
| 130 | + --arg workloadId "$DOCS_AGENT_WORKLOAD_ID" \ |
| 131 | + --arg workloadLabel "$DOCS_AGENT_WORKLOAD_LABEL" \ |
| 132 | + --arg prompt "$PROMPT" \ |
| 133 | + '{ |
| 134 | + component_id: "agents-api-docs-agent-ci-driver", |
| 135 | + component_path: $componentPath, |
| 136 | + workload_id: $workloadId, |
| 137 | + workload_label: $workloadLabel, |
| 138 | + validation_dependencies: [$agentsApi, $dm, $dmc, $openaiProvider], |
| 139 | + playground_wordpress_version: "7.0", |
| 140 | + bundle_repo: "https://github.com/Automattic/docs-agent.git", |
| 141 | + bundle_ref: $docsAgentRef, |
| 142 | + bundle_path_in_repo: "bundles/docs-agent", |
| 143 | + agent_slug: "docs-agent", |
| 144 | + pipeline_slug: $pipelineSlug, |
| 145 | + flow_slug: $flowSlug, |
| 146 | + provider: "openai", |
| 147 | + model: $model, |
| 148 | + provider_register_function: "WordPress\\OpenAiAiProvider\\register_provider", |
| 149 | + provider_credentials: { |
| 150 | + connectors_ai_openai_api_key: "OPENAI_API_KEY" |
| 151 | + }, |
| 152 | + github_token_env: "GITHUB_TOKEN", |
| 153 | + github_profile_id: "docs-agent-ci", |
| 154 | + target_repo: $targetRepo, |
| 155 | + allowed_repos: [$targetRepo], |
| 156 | + success_requires_pr: false, |
| 157 | + max_turns: 12, |
| 158 | + prompt: $prompt, |
| 159 | + step_budget: 16, |
| 160 | + time_budget_ms: 600000, |
| 161 | + transcript_dir: "/wordpress/wp-content/plugins/agents-api-docs-agent-ci-driver/artifacts/docs-agent", |
| 162 | + required_abilities: [ |
| 163 | + "datamachine/import-agent", |
| 164 | + "datamachine/run-flow", |
| 165 | + "datamachine/drain-job", |
| 166 | + "datamachine/create-or-update-github-file" |
| 167 | + ], |
| 168 | + tool_recorders: [ |
| 169 | + { |
| 170 | + tool: "create_or_update_github_file", |
| 171 | + forced_parameters: { |
| 172 | + allowed_file_paths: ["README.md", "docs/**"] |
| 173 | + }, |
| 174 | + record: { |
| 175 | + engine_key: "docs_agent", |
| 176 | + tool_results_key: "github_tool_results" |
| 177 | + } |
| 178 | + }, |
| 179 | + { |
| 180 | + tool: "create_github_pull_request", |
| 181 | + record: { |
| 182 | + engine_key: "docs_agent", |
| 183 | + tool_results_key: "github_tool_results", |
| 184 | + event: { |
| 185 | + key: "pr", |
| 186 | + type: "pull_request", |
| 187 | + only_if_success: true |
| 188 | + } |
| 189 | + } |
| 190 | + } |
| 191 | + ], |
| 192 | + bench_env: { |
| 193 | + GITHUB_TOKEN: $githubToken, |
| 194 | + OPENAI_API_KEY: $openaiKey |
| 195 | + } |
| 196 | + }' > "$CONFIG_TMPFILE" |
| 197 | + |
| 198 | +echo "============================================" |
| 199 | +echo "Docs Agent maintenance" |
| 200 | +echo "============================================" |
| 201 | +echo "Target repo: $DOCS_AGENT_TARGET_REPO" |
| 202 | +echo "OpenAI model: $DOCS_AGENT_OPENAI_MODEL" |
| 203 | +echo "Docs ref: $DOCS_AGENT_REF" |
| 204 | +echo "Workflow: $DOCS_AGENT_WORKFLOW" |
| 205 | +echo "Prompt: $DOCS_AGENT_PROMPT" |
| 206 | +echo "" |
| 207 | + |
| 208 | +GITHUB_TOKEN="$GITHUB_TOKEN" \ |
| 209 | +OPENAI_API_KEY="$OPENAI_API_KEY" \ |
| 210 | +HOMEBOY_BENCH_RESULTS_FILE="$RESULTS_TMPFILE" \ |
| 211 | +HOMEBOY_EXTENSION_PATH="$EXTENSION_PATH" \ |
| 212 | + bash "$HE_AGENT_RUNNER" "$CONFIG_TMPFILE" |
| 213 | + |
| 214 | +if [ ! -s "$RESULTS_TMPFILE" ]; then |
| 215 | + echo "ERROR: results file empty or missing at $RESULTS_TMPFILE" >&2 |
| 216 | + exit 1 |
| 217 | +fi |
| 218 | + |
| 219 | +cat "$RESULTS_TMPFILE" |
| 220 | + |
| 221 | +scenario='.scenarios[] | select(.id == "'"$DOCS_AGENT_WORKLOAD_ID"'")' |
| 222 | +job_status=$(jq -r "$scenario | .metadata.job_status // \"unknown\"" "$RESULTS_TMPFILE") |
| 223 | +success_status=$(jq -r "$scenario | .metadata.success_status // \"unknown\"" "$RESULTS_TMPFILE") |
| 224 | +docs_agent_pr_url=$(jq -r "$scenario | .metadata.engine_data.docs_agent.pr.url // \"\"" "$RESULTS_TMPFILE") |
| 225 | + |
| 226 | +echo "============================================" |
| 227 | +echo "Docs Agent summary" |
| 228 | +echo "============================================" |
| 229 | +printf '%-24s %s\n' "Persisted job status:" "$job_status" |
| 230 | +printf '%-24s %s\n' "Success status:" "$success_status" |
| 231 | +printf '%-24s %s\n' "Docs Agent PR URL:" "$docs_agent_pr_url" |
| 232 | + |
| 233 | +if [ -n "${GITHUB_OUTPUT:-}" ]; then |
| 234 | + { |
| 235 | + echo "job_status=$job_status" |
| 236 | + echo "success_status=$success_status" |
| 237 | + echo "docs_agent_pr_url=$docs_agent_pr_url" |
| 238 | + } >> "$GITHUB_OUTPUT" |
| 239 | +fi |
| 240 | + |
| 241 | +if [ "$job_status" = "completed" ] && { [ "$success_status" = "pr_opened" ] || [ "$success_status" = "no_changes" ]; }; then |
| 242 | + echo "Docs Agent maintenance PASSED - $success_status" |
| 243 | + exit 0 |
| 244 | +fi |
| 245 | + |
| 246 | +echo "Docs Agent maintenance FAILED - see envelope above" >&2 |
| 247 | +exit 1 |
0 commit comments