Finish Copilot production setup on current master

Preserve the reviewed candidate source and mainline provider behavior.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-10-09 10:54:11 -05:00
1 parent cc1670aa56
commit aaa65bbfbf
74 files changed
+57873 -251

No files matched your search

+7 -1
View File
@@ -32,6 +32,7 @@ export const AI_PROVIDERS = [
"openai",
"openrouter",
"xai",
"github",
"google",
] as const;
export const aiProviderSchema = z.enum(AI_PROVIDERS);
@@ -79,6 +80,10 @@ export const AI_CONNECTION_CAPABILITIES: Record<
>;
}
> = {
github: {
name: "GitHub Copilot",
methods: { api_key: { adapters: ["copilot_runtime"], envKey: "COPILOT_GITHUB_TOKEN" } },
},
google: { name: "Google", methods: { api_key: { adapters: ["gemini_local"], envKey: "GEMINI_API_KEY" } } },
anthropic: {
name: "Claude",
@@ -123,7 +128,7 @@ export function isAiConnectionCompatible(
// A fixed binding contains identity only. The service checks authoritative
// connection metadata before resolving credentials or running the harness.
if ("mode" in requirement && requirement.mode !== "responsible_user" && requirement.method === "api_key")
return ["claude_local", "codex_local", "opencode_local", "hermes_local", "gemini_local", "grok_local"].includes(adapterType);
return ["claude_local", "codex_local", "opencode_local", "hermes_local", "gemini_local", "grok_local", "copilot_runtime"].includes(adapterType);
const methods = AI_CONNECTION_CAPABILITIES[requirement.provider].methods;
const candidates = "mode" in requirement && requirement.mode === "responsible_user"
? Object.values(methods)
@@ -185,6 +190,7 @@ export const createAiConnectionSchema = z
ownership: z.enum(["personal", "shared"]),
routing: aiProviderRoutingSchema.optional(),
apiKey: z.string().trim().min(1).max(32768).optional(),
environmentId: z.string().uuid().nullable().optional(),
loginSessionId: z.string().max(128).optional(),
connectionId: z.string().uuid().optional(),
agentIds: z.array(z.string().uuid()).max(1000).default([]),
@@ -81,6 +81,7 @@ export function aiRoutingHarness(
acpxAgent?: unknown,
): string {
if (adapter !== "paperclip_runner") return adapter;
if (provider === "acpx" && acpxAgent === "copilot") return "copilot_runtime";
const runner =
provider === "acpx" && (acpxAgent === "claude" || acpxAgent === "grok")
? acpxAgent
+3 -2
View File
@@ -299,8 +299,9 @@ describe("AppDefinition catalog", () => {
it("separates GitHub tools from the review bot without changing the provider identity", () => {
const github = getConnectableAppDefinition("github")!;
const bot = getConnectableAppDefinition("github-code-review-bot")!;
expect(github.methods.map((method) => method.key)).toEqual(["managed", "mcp-key"]);
expect(github.methods.every((method) => method.purpose === "tool")).toBe(true);
expect(github.methods.map((method) => method.key)).toEqual(["managed", "mcp-key", "copilot-token"]);
expect(github.methods.filter((method) => method.purpose === "tool").map((method) => method.key)).toEqual(["managed", "mcp-key"]);
expect(github.methods.find((method) => method.key === "copilot-token")).toMatchObject({ purpose: "ai", transport: "runtime_auth" });
expect(bot.name).toBe("GitHub Code Review Bot");
expect(bot.methods).toHaveLength(1);
expect(bot.methods[0]).toMatchObject({ provider: "github", purpose: "channel", transport: "chat_sdk" });
@@ -2,9 +2,10 @@
"schemaVersion": 1,
"slug": "github",
"name": "GitHub",
"description": "Give agents access to GitHub repositories, issues, and pull requests.",
"description": "Connect GitHub repository access or authenticate GitHub Copilot agents.",
"categories": [
"developer"
"developer",
"ai"
],
"featured": true,
"branding": {
@@ -68,7 +69,7 @@
"required": true,
"placeholder": "github_pat_...",
"secret": true,
"helperMd": "Repository contents, issues, pull requests and other granted toolsets; selected repos and installation/PAT permissions apply. Create a key with read and write permissions for these actions; Paperclip cannot increase an existing key’s permissions."
"helperMd": "Repository contents, issues, pull requests and other granted toolsets; selected repos and installation/PAT permissions apply. Create a key with read and write permissions for these actions; Paperclip cannot increase an existing key\u2019s permissions."
}
],
"keyPlacement": {
@@ -80,6 +81,42 @@
"organization",
"repository"
]
},
{
"key": "copilot-token",
"label": "GitHub Copilot personal access token",
"purpose": "ai",
"transport": "runtime_auth",
"auth": "api_key",
"ai": {
"provider": "github",
"method": "api_key"
},
"grantKinds": [
"user",
"organization"
],
"ownershipModes": [
"customer"
],
"whenToUse": "Authenticate the GitHub Copilot agent runtime with a personal or explicitly shared account.",
"guidanceMd": "Create a personal fine-grained token with the Copilot Requests permission. Copilot authentication is separate from repository and MCP access. [GitHub authentication instructions](https://docs.github.com/en/copilot/how-tos/copilot-cli/set-up-copilot-cli/authenticate-copilot-cli).",
"riskTier": "S3",
"credentialFields": [
{
"key": "apiKey",
"label": "Personal access token",
"type": "password",
"required": true,
"placeholder": "github_pat_...",
"secret": true,
"helperMd": "Use a personal fine-grained token with Copilot Requests permission."
}
],
"keyPlacement": {
"location": "env",
"name": "COPILOT_GITHUB_TOKEN"
}
}
]
}