Files
Terrence Ryan 1df6ff6735 feat: Feature matrix (#793)
* feat: Add workflow to run Go program and create PR

Introduces a GitHub Actions workflow that checks out two repositories, sets up Go, installs dependencies, runs a Go program, and creates a pull request with generated documentation updates.

* fix: Update workflow name and trigger

Renamed the workflow to 'Feature Matrix Creator' and changed the trigger from push on main to manual workflow_dispatch.

* feat: Add feature-matrix tool for ADK feature extraction

Introduces a new tool under tools/feature-matrix to generate a feature support matrix for ADK runtimes by analyzing documentation. Includes Go implementation (main.go), prompt and starter markdown files, and Go module dependencies.

* feat: Update feature matrix workflow to use local tool

Removes checkout of the adk-docs-features repo and updates steps to use the local tools/feature-matrix directory for dependency installation and program execution. Simplifies the workflow by eliminating unnecessary repository cloning and file movement.

* fix: Update feature matrix prompt and matrix content

Revised the prompt to use 'Unsupported' instead of 'Planned' for features not supported, clarified disclaimer placement, and updated instructions for matrix ordering. Updated start.md to move the disclaimer and feature matrix to the top, reflect new terminology, and provide a more accurate and current feature support matrix.
2025-10-23 15:28:43 -07:00

103 lines
2.6 KiB
Go

package main
import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/google/generative-ai-go/genai"
"google.golang.org/api/option"
"github.com/charmbracelet/log"
)
func extractLocal(root string) (string, error) {
var content strings.Builder
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && strings.HasSuffix(info.Name(), ".md") {
fileContent, err := os.ReadFile(path)
if err != nil {
// log error but continue
return nil
}
content.Write(fileContent)
content.WriteString("\n\n")
}
return nil
})
if err != nil {
return "", err
}
return content.String(), nil
}
func main() {
ctx := context.Background()
// Access your API key as an environment variable (see "Set up your API key" above)
client, err := genai.NewClient(ctx, option.WithAPIKey(os.Getenv("GEMINI_API_KEY")))
if err != nil {
log.Fatal(err)
}
defer client.Close()
// For text-only input, use the gemini-pro model
model := client.GenerativeModel("gemini-2.5-pro")
model.SetTemperature(0.9)
model.SetTopP(0.95)
model.SetTopK(40)
log.Infof("reading prompt")
promptBytes, err := os.ReadFile("prompt.md")
if err != nil {
log.Fatalf("cannot read prompt from filesystem: %s", err)
}
log.Infof("reading starting matrix starting place")
outputBytes, err := os.ReadFile("start.md")
if err != nil {
log.Fatalf("cannot read example from filesystem: %s", err)
}
command := string(promptBytes) + string(outputBytes)
log.Infof("Retrieving adk-docs")
documentationContent, err := extractLocal("../../docs")
if err != nil {
log.Fatalf("cannot retrieve and process content from adk-docs repo: %s", err)
}
prompt := command + "\n\n" + documentationContent
log.Infof("sending the request to the model")
resp, err := model.GenerateContent(ctx, genai.Text(prompt))
if err != nil {
log.Fatalf("did not get a valid response back from teh model", err)
}
for i, cand := range resp.Candidates {
if cand.Content != nil {
for _, part := range cand.Content.Parts {
if txt, ok := part.(genai.Text); ok {
if i == 0 { // Only process the first candidate for the PR
outputDir := "../../docs/features"
if err := os.MkdirAll(outputDir, 0755); err != nil {
log.Fatalf("failed to create output directory: %v", err)
}
filename := fmt.Sprintf("%s/index.md", outputDir)
err := os.WriteFile(filename, []byte(txt), 0644)
if err != nil {
log.Fatalf("failed to write output file: %v", err)
}
log.Infof("wrote output to %s", filename)
}
}
}
}
}
}