Skip to content

Commit 1cc083a

Browse files
authored
gemini_investigate: add github_search_issues to delegated functions (#16)
* Fix gemini_investigate: use role 'user' for functionResponse turns (Gemini API rejects role 'function') * Add notion_get_page to gemini_investigate's delegated function set, so investigations can actually read page content (previously only notion_search/notion_query_database were available) * Raise gemini_investigate HARD_MAX_STEPS from 10 to 20 -- Vercel Fluid Compute defaults to a 300s function timeout, giving far more headroom than the original 10-step cap assumed * Update gemini_investigate tool description: hard cap is now 20, not 10 * Add GEMINI_FALLBACK_MODELS config for rate-limit cascade * Cascade through GEMINI_FALLBACK_MODELS on 429 rate-limit errors, since free-tier quotas are tracked per model * Add github_search_issues to gemini_investigate's delegated function set, mirroring the connectors/github/search.js search_issues tool
1 parent 9c3e10e commit 1cc083a

1 file changed

Lines changed: 28 additions & 0 deletions

File tree

connectors/gemini/delegate.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,34 @@ const FUNCTIONS = [
105105
return data.map((c) => `${c.sha.slice(0, 7)}${c.commit.message.split("\n")[0]} (${c.commit.author?.name}, ${c.commit.author?.date?.slice(0, 10)})`).join("\n");
106106
},
107107
},
108+
{
109+
name: "github_search_issues",
110+
description: "Search issues and pull requests across GitHub using GitHub's issue-search syntax (label:, is:issue, is:open, stars:>N, org:, repo:, -repo:, -org:, no:assignee, etc., combined with spaces as AND). Useful for cross-repo discovery like good-first-issue scanning -- github_read_file/github_get_file_tree only work within a single already-known repo.",
111+
parameters: {
112+
type: "object",
113+
properties: {
114+
query: { type: "string", description: "GitHub issue-search query string, e.g. 'label:\"good first issue\" is:open is:issue no:assignee stars:>2000 -org:someorg'" },
115+
sort: { type: "string", description: "Sort field: created, updated, or comments (default: best-match relevance)" },
116+
order: { type: "string", description: "Sort order: asc or desc (default: desc)" },
117+
per_page: { type: "number", description: "Number of results to return, max 100 (default 20)" },
118+
},
119+
required: ["query"],
120+
},
121+
execute: async ({ query, sort, order = "desc", per_page = 20 }) => {
122+
let path = `/search/issues?q=${encodeURIComponent(query)}&order=${order}&per_page=${Math.min(per_page, 100)}`;
123+
if (sort) path += `&sort=${sort}`;
124+
const data = await githubRequest(path);
125+
if (!data.items?.length) return "No results found.";
126+
const lines = data.items.map((item) => {
127+
const kind = item.pull_request ? "PR" : "Issue";
128+
const labels = item.labels?.length ? ` [${item.labels.map((l) => l.name).join(", ")}]` : "";
129+
const assignee = item.assignee ? ` (assigned: ${item.assignee.login})` : " (unassigned)";
130+
return `${kind} #${item.number} [${item.state}] ${item.title}${labels}${assignee} -- ${item.repository_url.replace("https://api.github.com/repos/", "")} | created ${item.created_at.slice(0, 10)} | ${item.html_url}`;
131+
});
132+
const text = `Found ${data.total_count} total result(s), showing ${data.items.length}:\n${lines.join("\n")}`;
133+
return text.length > 20000 ? text.slice(0, 20000) + "\n...[truncated]" : text;
134+
},
135+
},
108136
{
109137
name: "cf_query_logs",
110138
description: "Query Cloudflare Workers Observability logs/traces/events for a time range.",

0 commit comments

Comments
 (0)