system.github_actions.genai.mts•5.29 kB
system({
title: "github workflows",
description:
"Queries results from workflows in GitHub actions. Prefer using diffs to compare logs.",
})
export default function (ctx: ChatGenerationContext) {
const { defTool } = ctx
defTool(
"github_actions_workflows_list",
"List all github workflows.",
{},
async (args) => {
const { context } = args
context.log("github action list workflows")
const res = await github.listWorkflows()
return CSV.stringify(
res.map(({ id, name, path }) => ({ id, name, path })),
{ header: true }
)
}
)
defTool(
"github_actions_runs_list",
`List all runs for a workflow or the entire repository.
- Use 'git_actions_list_workflows' to list workflows.
- Omit 'workflow_id' to list all runs.
- head_sha is the commit hash.`,
{
type: "object",
properties: {
workflow_id: {
type: "string",
description:
"ID or filename of the workflow to list runs for. Empty lists all runs.",
},
branch: {
type: "string",
description: "Branch to list runs for.",
},
status: {
type: "string",
enum: ["success", "failure"],
description: "Filter runs by completion status",
},
count: {
type: "number",
description: "Number of runs to list. Default is 20.",
},
},
},
async (args) => {
const { workflow_id, branch, status, context, count } = args
context.log(
`github action list ${status || ""} runs for ${workflow_id ? `workflow ${workflow_id}` : `repository`} and branch ${branch || "all"}`
)
const res = await github.listWorkflowRuns(workflow_id, {
branch,
status,
count,
})
return CSV.stringify(
res.map(({ id, name, conclusion, head_sha }) => ({
id,
name,
conclusion,
head_sha,
})),
{ header: true }
)
}
)
defTool(
"github_actions_jobs_list",
"List all jobs for a github workflow run.",
{
type: "object",
properties: {
run_id: {
type: "string",
description:
"ID of the run to list jobs for. Use 'git_actions_list_runs' to list runs for a workflow.",
},
},
required: ["run_id"],
},
async (args) => {
const { run_id, context } = args
context.log(`github action list jobs for run ${run_id}`)
const res = await github.listWorkflowJobs(run_id)
return CSV.stringify(
res.map(({ id, name, conclusion }) => ({
id,
name,
conclusion,
})),
{ header: true }
)
}
)
defTool(
"github_actions_job_logs_get",
"Download github workflow job log. If the log is too large, use 'github_actions_job_logs_diff' to compare logs.",
{
type: "object",
properties: {
job_id: {
type: "string",
description: "ID of the job to download log for.",
},
},
required: ["job_id"],
},
async (args) => {
const { job_id, context } = args
context.log(`github action download job log ${job_id}`)
let log = await github.downloadWorkflowJobLog(job_id, {
llmify: true,
})
if ((await tokenizers.count(log)) > 1000) {
log = await tokenizers.truncate(log, 1000, { last: true })
const annotations = await parsers.annotations(log)
if (annotations.length > 0)
log += "\n\n" + YAML.stringify(annotations)
}
return log
}
)
defTool(
"github_actions_job_logs_diff",
"Diffs two github workflow job logs.",
{
type: "object",
properties: {
job_id: {
type: "string",
description: "ID of the job to compare.",
},
other_job_id: {
type: "string",
description: "ID of the other job to compare.",
},
},
required: ["job_id", "other_job_id"],
},
async (args) => {
const { job_id, other_job_id, context } = args
context.log(`github action diff job logs ${job_id} ${other_job_id}`)
const log = await github.diffWorkflowJobLogs(job_id, other_job_id)
return log
}
)
}