mirror of https://github.com/openclaw/openclaw.git
refactor(github-copilot): lazy-load provider registration
This commit is contained in:
parent
1c1f32e756
commit
e56ffd48df
|
|
@ -1,14 +1,4 @@
|
|||
import { definePluginEntry, type ProviderAuthContext } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import {
|
||||
coerceSecretRef,
|
||||
ensureAuthProfileStore,
|
||||
listProfilesForProvider,
|
||||
} from "openclaw/plugin-sdk/provider-auth";
|
||||
import { githubCopilotLoginCommand } from "openclaw/plugin-sdk/provider-auth-login";
|
||||
import { PROVIDER_ID, resolveCopilotForwardCompatModel } from "./models.js";
|
||||
import { wrapCopilotAnthropicStream } from "./stream.js";
|
||||
import { DEFAULT_COPILOT_API_BASE_URL, resolveCopilotApiToken } from "./token.js";
|
||||
import { fetchCopilotUsage } from "./usage.js";
|
||||
|
||||
const COPILOT_ENV_VARS = ["COPILOT_GITHUB_TOKEN", "GH_TOKEN", "GITHUB_TOKEN"];
|
||||
const COPILOT_XHIGH_MODEL_IDS = ["gpt-5.2", "gpt-5.2-codex"] as const;
|
||||
|
|
@ -21,85 +11,104 @@ function buildGithubCopilotReplayPolicy(modelId?: string) {
|
|||
: {};
|
||||
}
|
||||
|
||||
function resolveFirstGithubToken(params: { agentDir?: string; env: NodeJS.ProcessEnv }): {
|
||||
githubToken: string;
|
||||
hasProfile: boolean;
|
||||
} {
|
||||
const authStore = ensureAuthProfileStore(params.agentDir, {
|
||||
allowKeychainPrompt: false,
|
||||
});
|
||||
const hasProfile = listProfilesForProvider(authStore, PROVIDER_ID).length > 0;
|
||||
const envToken =
|
||||
params.env.COPILOT_GITHUB_TOKEN ?? params.env.GH_TOKEN ?? params.env.GITHUB_TOKEN ?? "";
|
||||
const githubToken = envToken.trim();
|
||||
if (githubToken || !hasProfile) {
|
||||
return { githubToken, hasProfile };
|
||||
}
|
||||
|
||||
const profileId = listProfilesForProvider(authStore, PROVIDER_ID)[0];
|
||||
const profile = profileId ? authStore.profiles[profileId] : undefined;
|
||||
if (profile?.type !== "token") {
|
||||
return { githubToken: "", hasProfile };
|
||||
}
|
||||
const directToken = profile.token?.trim() ?? "";
|
||||
if (directToken) {
|
||||
return { githubToken: directToken, hasProfile };
|
||||
}
|
||||
const tokenRef = coerceSecretRef(profile.tokenRef);
|
||||
if (tokenRef?.source === "env" && tokenRef.id.trim()) {
|
||||
return {
|
||||
githubToken: (params.env[tokenRef.id] ?? process.env[tokenRef.id] ?? "").trim(),
|
||||
hasProfile,
|
||||
};
|
||||
}
|
||||
return { githubToken: "", hasProfile };
|
||||
}
|
||||
|
||||
async function runGitHubCopilotAuth(ctx: ProviderAuthContext) {
|
||||
await ctx.prompter.note(
|
||||
[
|
||||
"This will open a GitHub device login to authorize Copilot.",
|
||||
"Requires an active GitHub Copilot subscription.",
|
||||
].join("\n"),
|
||||
"GitHub Copilot",
|
||||
);
|
||||
|
||||
if (!process.stdin.isTTY) {
|
||||
await ctx.prompter.note("GitHub Copilot login requires an interactive TTY.", "GitHub Copilot");
|
||||
return { profiles: [] };
|
||||
}
|
||||
|
||||
try {
|
||||
await githubCopilotLoginCommand({ yes: true, profileId: "github-copilot:github" }, ctx.runtime);
|
||||
} catch (err) {
|
||||
await ctx.prompter.note(`GitHub Copilot login failed: ${String(err)}`, "GitHub Copilot");
|
||||
return { profiles: [] };
|
||||
}
|
||||
|
||||
const authStore = ensureAuthProfileStore(undefined, {
|
||||
allowKeychainPrompt: false,
|
||||
});
|
||||
const credential = authStore.profiles["github-copilot:github"];
|
||||
if (!credential || credential.type !== "token") {
|
||||
return { profiles: [] };
|
||||
}
|
||||
|
||||
return {
|
||||
profiles: [
|
||||
{
|
||||
profileId: "github-copilot:github",
|
||||
credential,
|
||||
},
|
||||
],
|
||||
defaultModel: "github-copilot/gpt-4o",
|
||||
};
|
||||
}
|
||||
|
||||
export default definePluginEntry({
|
||||
id: "github-copilot",
|
||||
name: "GitHub Copilot Provider",
|
||||
description: "Bundled GitHub Copilot provider plugin",
|
||||
register(api) {
|
||||
async register(api) {
|
||||
const {
|
||||
coerceSecretRef,
|
||||
DEFAULT_COPILOT_API_BASE_URL,
|
||||
ensureAuthProfileStore,
|
||||
fetchCopilotUsage,
|
||||
githubCopilotLoginCommand,
|
||||
listProfilesForProvider,
|
||||
PROVIDER_ID,
|
||||
resolveCopilotApiToken,
|
||||
resolveCopilotForwardCompatModel,
|
||||
wrapCopilotAnthropicStream,
|
||||
} = await import("./register.runtime.js");
|
||||
|
||||
function resolveFirstGithubToken(params: { agentDir?: string; env: NodeJS.ProcessEnv }): {
|
||||
githubToken: string;
|
||||
hasProfile: boolean;
|
||||
} {
|
||||
const authStore = ensureAuthProfileStore(params.agentDir, {
|
||||
allowKeychainPrompt: false,
|
||||
});
|
||||
const hasProfile = listProfilesForProvider(authStore, PROVIDER_ID).length > 0;
|
||||
const envToken =
|
||||
params.env.COPILOT_GITHUB_TOKEN ?? params.env.GH_TOKEN ?? params.env.GITHUB_TOKEN ?? "";
|
||||
const githubToken = envToken.trim();
|
||||
if (githubToken || !hasProfile) {
|
||||
return { githubToken, hasProfile };
|
||||
}
|
||||
|
||||
const profileId = listProfilesForProvider(authStore, PROVIDER_ID)[0];
|
||||
const profile = profileId ? authStore.profiles[profileId] : undefined;
|
||||
if (profile?.type !== "token") {
|
||||
return { githubToken: "", hasProfile };
|
||||
}
|
||||
const directToken = profile.token?.trim() ?? "";
|
||||
if (directToken) {
|
||||
return { githubToken: directToken, hasProfile };
|
||||
}
|
||||
const tokenRef = coerceSecretRef(profile.tokenRef);
|
||||
if (tokenRef?.source === "env" && tokenRef.id.trim()) {
|
||||
return {
|
||||
githubToken: (params.env[tokenRef.id] ?? process.env[tokenRef.id] ?? "").trim(),
|
||||
hasProfile,
|
||||
};
|
||||
}
|
||||
return { githubToken: "", hasProfile };
|
||||
}
|
||||
|
||||
async function runGitHubCopilotAuth(ctx: ProviderAuthContext) {
|
||||
await ctx.prompter.note(
|
||||
[
|
||||
"This will open a GitHub device login to authorize Copilot.",
|
||||
"Requires an active GitHub Copilot subscription.",
|
||||
].join("\n"),
|
||||
"GitHub Copilot",
|
||||
);
|
||||
|
||||
if (!process.stdin.isTTY) {
|
||||
await ctx.prompter.note(
|
||||
"GitHub Copilot login requires an interactive TTY.",
|
||||
"GitHub Copilot",
|
||||
);
|
||||
return { profiles: [] };
|
||||
}
|
||||
|
||||
try {
|
||||
await githubCopilotLoginCommand(
|
||||
{ yes: true, profileId: "github-copilot:github" },
|
||||
ctx.runtime,
|
||||
);
|
||||
} catch (err) {
|
||||
await ctx.prompter.note(`GitHub Copilot login failed: ${String(err)}`, "GitHub Copilot");
|
||||
return { profiles: [] };
|
||||
}
|
||||
|
||||
const authStore = ensureAuthProfileStore(undefined, {
|
||||
allowKeychainPrompt: false,
|
||||
});
|
||||
const credential = authStore.profiles["github-copilot:github"];
|
||||
if (!credential || credential.type !== "token") {
|
||||
return { profiles: [] };
|
||||
}
|
||||
|
||||
return {
|
||||
profiles: [
|
||||
{
|
||||
profileId: "github-copilot:github",
|
||||
credential,
|
||||
},
|
||||
],
|
||||
defaultModel: "github-copilot/gpt-4o",
|
||||
};
|
||||
}
|
||||
|
||||
api.registerProvider({
|
||||
id: PROVIDER_ID,
|
||||
label: "GitHub Copilot",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
export {
|
||||
coerceSecretRef,
|
||||
ensureAuthProfileStore,
|
||||
listProfilesForProvider,
|
||||
} from "openclaw/plugin-sdk/provider-auth";
|
||||
export { githubCopilotLoginCommand } from "openclaw/plugin-sdk/provider-auth-login";
|
||||
export { PROVIDER_ID, resolveCopilotForwardCompatModel } from "./models.js";
|
||||
export { wrapCopilotAnthropicStream } from "./stream.js";
|
||||
export { DEFAULT_COPILOT_API_BASE_URL, resolveCopilotApiToken } from "./token.js";
|
||||
export { fetchCopilotUsage } from "./usage.js";
|
||||
Loading…
Reference in New Issue