refactor: remove glabPath and ghPath options from providers and update related code
This commit is contained in:
8
index.ts
8
index.ts
@@ -29,14 +29,6 @@ const plugin = {
|
|||||||
qa: { type: "string", description: "QA engineer model" },
|
qa: { type: "string", description: "QA engineer model" },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
glabPath: {
|
|
||||||
type: "string",
|
|
||||||
description: "Path to glab CLI binary. Defaults to 'glab' on PATH.",
|
|
||||||
},
|
|
||||||
ghPath: {
|
|
||||||
type: "string",
|
|
||||||
description: "Path to gh CLI binary. Defaults to 'gh' on PATH.",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ const STATE_LABELS = [
|
|||||||
export type StateLabel = (typeof STATE_LABELS)[number];
|
export type StateLabel = (typeof STATE_LABELS)[number];
|
||||||
|
|
||||||
type GlabOptions = {
|
type GlabOptions = {
|
||||||
glabPath?: string;
|
|
||||||
repoPath: string;
|
repoPath: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -33,8 +32,7 @@ async function glab(
|
|||||||
args: string[],
|
args: string[],
|
||||||
opts: GlabOptions,
|
opts: GlabOptions,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const bin = opts.glabPath ?? "glab";
|
const { stdout } = await execFileAsync("glab", args, {
|
||||||
const { stdout } = await execFileAsync(bin, args, {
|
|
||||||
cwd: opts.repoPath,
|
cwd: opts.repoPath,
|
||||||
timeout: 30_000,
|
timeout: 30_000,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import {
|
|||||||
const execFileAsync = promisify(execFile);
|
const execFileAsync = promisify(execFile);
|
||||||
|
|
||||||
export type GitHubProviderOptions = {
|
export type GitHubProviderOptions = {
|
||||||
ghPath?: string;
|
|
||||||
repoPath: string;
|
repoPath: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,16 +49,14 @@ function toIssue(gh: GhIssue): Issue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class GitHubProvider implements IssueProvider {
|
export class GitHubProvider implements IssueProvider {
|
||||||
private ghPath: string;
|
|
||||||
private repoPath: string;
|
private repoPath: string;
|
||||||
|
|
||||||
constructor(opts: GitHubProviderOptions) {
|
constructor(opts: GitHubProviderOptions) {
|
||||||
this.ghPath = opts.ghPath ?? "gh";
|
|
||||||
this.repoPath = opts.repoPath;
|
this.repoPath = opts.repoPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async gh(args: string[]): Promise<string> {
|
private async gh(args: string[]): Promise<string> {
|
||||||
const { stdout } = await execFileAsync(this.ghPath, args, {
|
const { stdout } = await execFileAsync("gh", args, {
|
||||||
cwd: this.repoPath,
|
cwd: this.repoPath,
|
||||||
timeout: 30_000,
|
timeout: 30_000,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,21 +20,18 @@ import {
|
|||||||
const execFileAsync = promisify(execFile);
|
const execFileAsync = promisify(execFile);
|
||||||
|
|
||||||
export type GitLabProviderOptions = {
|
export type GitLabProviderOptions = {
|
||||||
glabPath?: string;
|
|
||||||
repoPath: string;
|
repoPath: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class GitLabProvider implements IssueProvider {
|
export class GitLabProvider implements IssueProvider {
|
||||||
private glabPath: string;
|
|
||||||
private repoPath: string;
|
private repoPath: string;
|
||||||
|
|
||||||
constructor(opts: GitLabProviderOptions) {
|
constructor(opts: GitLabProviderOptions) {
|
||||||
this.glabPath = opts.glabPath ?? "glab";
|
|
||||||
this.repoPath = opts.repoPath;
|
this.repoPath = opts.repoPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async glab(args: string[]): Promise<string> {
|
private async glab(args: string[]): Promise<string> {
|
||||||
const { stdout } = await execFileAsync(this.glabPath, args, {
|
const { stdout } = await execFileAsync("glab", args, {
|
||||||
cwd: this.repoPath,
|
cwd: this.repoPath,
|
||||||
timeout: 30_000,
|
timeout: 30_000,
|
||||||
});
|
});
|
||||||
@@ -76,7 +73,7 @@ export class GitLabProvider implements IssueProvider {
|
|||||||
const { promisify } = await import("node:util");
|
const { promisify } = await import("node:util");
|
||||||
const execAsync = promisify(exec);
|
const execAsync = promisify(exec);
|
||||||
|
|
||||||
let cmd = `${this.glabPath} issue create --title "${title.replace(/"/g, '\\"')}" --description "$(cat ${tempFile})" --label "${label}" --output json`;
|
let cmd = `glab issue create --title "${title.replace(/"/g, '\\"')}" --description "$(cat ${tempFile})" --label "${label}" --output json`;
|
||||||
if (assignees && assignees.length > 0) {
|
if (assignees && assignees.length > 0) {
|
||||||
cmd += ` --assignee "${assignees.join(",")}"`;
|
cmd += ` --assignee "${assignees.join(",")}"`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ import { execFileSync } from "node:child_process";
|
|||||||
import type { IssueProvider } from "../issue-provider.js";
|
import type { IssueProvider } from "../issue-provider.js";
|
||||||
import { GitLabProvider } from "./gitlab.js";
|
import { GitLabProvider } from "./gitlab.js";
|
||||||
import { GitHubProvider } from "./github.js";
|
import { GitHubProvider } from "./github.js";
|
||||||
|
import { resolveRepoPath } from "../utils.js";
|
||||||
|
|
||||||
export type ProviderOptions = {
|
export type ProviderOptions = {
|
||||||
provider?: "gitlab" | "github";
|
provider?: "gitlab" | "github";
|
||||||
glabPath?: string;
|
repo?: string;
|
||||||
ghPath?: string;
|
repoPath?: string;
|
||||||
repoPath: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function detectProvider(repoPath: string): "gitlab" | "github" {
|
function detectProvider(repoPath: string): "gitlab" | "github" {
|
||||||
@@ -39,16 +39,21 @@ export type ProviderWithType = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function createProvider(opts: ProviderOptions): ProviderWithType {
|
export function createProvider(opts: ProviderOptions): ProviderWithType {
|
||||||
const type = opts.provider ?? detectProvider(opts.repoPath);
|
const repoPath = opts.repoPath ?? (opts.repo ? resolveRepoPath(opts.repo) : null);
|
||||||
|
if (!repoPath) {
|
||||||
|
throw new Error("Either repoPath or repo must be provided to createProvider");
|
||||||
|
}
|
||||||
|
|
||||||
|
const type = opts.provider ?? detectProvider(repoPath);
|
||||||
|
|
||||||
if (type === "github") {
|
if (type === "github") {
|
||||||
return {
|
return {
|
||||||
provider: new GitHubProvider({ ghPath: opts.ghPath, repoPath: opts.repoPath }),
|
provider: new GitHubProvider({ repoPath }),
|
||||||
type: "github",
|
type: "github",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
provider: new GitLabProvider({ glabPath: opts.glabPath, repoPath: opts.repoPath }),
|
provider: new GitLabProvider({ repoPath }),
|
||||||
type: "gitlab",
|
type: "gitlab",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,9 +170,7 @@ export function createProjectRegisterTool(api: OpenClawPluginApi) {
|
|||||||
const repoPath = resolveRepoPath(repo);
|
const repoPath = resolveRepoPath(repo);
|
||||||
|
|
||||||
// 3. Create provider and verify it works
|
// 3. Create provider and verify it works
|
||||||
const glabPath = (api.pluginConfig as Record<string, unknown>)?.glabPath as string | undefined;
|
const { provider, type: providerType } = createProvider({ repo });
|
||||||
const ghPath = (api.pluginConfig as Record<string, unknown>)?.ghPath as string | undefined;
|
|
||||||
const { provider, type: providerType } = createProvider({ glabPath, ghPath, repoPath });
|
|
||||||
|
|
||||||
const healthy = await provider.healthCheck();
|
const healthy = await provider.healthCheck();
|
||||||
if (!healthy) {
|
if (!healthy) {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import { type StateLabel } from "../issue-provider.js";
|
|||||||
import { createProvider } from "../providers/index.js";
|
import { createProvider } from "../providers/index.js";
|
||||||
import { log as auditLog } from "../audit.js";
|
import { log as auditLog } from "../audit.js";
|
||||||
import { detectContext, generateGuardrails } from "../context-guard.js";
|
import { detectContext, generateGuardrails } from "../context-guard.js";
|
||||||
import { resolveRepoPath } from "../utils.js";
|
|
||||||
|
|
||||||
export function createQueueStatusTool(api: OpenClawPluginApi) {
|
export function createQueueStatusTool(api: OpenClawPluginApi) {
|
||||||
return (ctx: ToolContext) => ({
|
return (ctx: ToolContext) => ({
|
||||||
@@ -69,11 +68,8 @@ export function createQueueStatusTool(api: OpenClawPluginApi) {
|
|||||||
const project = getProject(data, pid);
|
const project = getProject(data, pid);
|
||||||
if (!project) continue;
|
if (!project) continue;
|
||||||
|
|
||||||
const repoPath = resolveRepoPath(project.repo);
|
|
||||||
const { provider } = createProvider({
|
const { provider } = createProvider({
|
||||||
glabPath: (api.pluginConfig as Record<string, unknown>)?.glabPath as string | undefined,
|
repo: project.repo,
|
||||||
ghPath: (api.pluginConfig as Record<string, unknown>)?.ghPath as string | undefined,
|
|
||||||
repoPath,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fetch queue counts from issue tracker
|
// Fetch queue counts from issue tracker
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import { readProjects, updateWorker, getSessionForModel } from "../projects.js";
|
|||||||
import { type StateLabel } from "../issue-provider.js";
|
import { type StateLabel } from "../issue-provider.js";
|
||||||
import { createProvider } from "../providers/index.js";
|
import { createProvider } from "../providers/index.js";
|
||||||
import { log as auditLog } from "../audit.js";
|
import { log as auditLog } from "../audit.js";
|
||||||
import { resolveRepoPath } from "../utils.js";
|
|
||||||
|
|
||||||
export function createSessionHealthTool(api: OpenClawPluginApi) {
|
export function createSessionHealthTool(api: OpenClawPluginApi) {
|
||||||
return (ctx: ToolContext) => ({
|
return (ctx: ToolContext) => ({
|
||||||
@@ -48,11 +47,8 @@ export function createSessionHealthTool(api: OpenClawPluginApi) {
|
|||||||
let fixesApplied = 0;
|
let fixesApplied = 0;
|
||||||
|
|
||||||
for (const [groupId, project] of Object.entries(data.projects)) {
|
for (const [groupId, project] of Object.entries(data.projects)) {
|
||||||
const repoPath = resolveRepoPath(project.repo);
|
|
||||||
const { provider } = createProvider({
|
const { provider } = createProvider({
|
||||||
glabPath: (api.pluginConfig as Record<string, unknown>)?.glabPath as string | undefined,
|
repo: project.repo,
|
||||||
ghPath: (api.pluginConfig as Record<string, unknown>)?.ghPath as string | undefined,
|
|
||||||
repoPath,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const role of ["dev", "qa"] as const) {
|
for (const role of ["dev", "qa"] as const) {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { log as auditLog } from "../audit.js";
|
|||||||
import { dispatchTask } from "../dispatch.js";
|
import { dispatchTask } from "../dispatch.js";
|
||||||
import { type StateLabel } from "../issue-provider.js";
|
import { type StateLabel } from "../issue-provider.js";
|
||||||
import { createProvider } from "../providers/index.js";
|
import { createProvider } from "../providers/index.js";
|
||||||
|
import { resolveRepoPath } from "../utils.js";
|
||||||
import {
|
import {
|
||||||
deactivateWorker,
|
deactivateWorker,
|
||||||
getProject,
|
getProject,
|
||||||
@@ -24,7 +25,6 @@ import {
|
|||||||
readProjects,
|
readProjects,
|
||||||
} from "../projects.js";
|
} from "../projects.js";
|
||||||
import type { ToolContext } from "../types.js";
|
import type { ToolContext } from "../types.js";
|
||||||
import { resolveRepoPath } from "../utils.js";
|
|
||||||
|
|
||||||
const execFileAsync = promisify(execFile);
|
const execFileAsync = promisify(execFile);
|
||||||
|
|
||||||
@@ -105,17 +105,12 @@ export function createTaskCompleteTool(api: OpenClawPluginApi) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const repoPath = resolveRepoPath(project.repo);
|
|
||||||
const { provider } = createProvider({
|
const { provider } = createProvider({
|
||||||
glabPath: (api.pluginConfig as Record<string, unknown>)?.glabPath as
|
repo: project.repo,
|
||||||
| string
|
|
||||||
| undefined,
|
|
||||||
ghPath: (api.pluginConfig as Record<string, unknown>)?.ghPath as
|
|
||||||
| string
|
|
||||||
| undefined,
|
|
||||||
repoPath,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const repoPath = resolveRepoPath(project.repo);
|
||||||
|
|
||||||
const output: Record<string, unknown> = {
|
const output: Record<string, unknown> = {
|
||||||
success: true,
|
success: true,
|
||||||
project: project.name,
|
project: project.name,
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|||||||
import { jsonResult } from "openclaw/plugin-sdk";
|
import { jsonResult } from "openclaw/plugin-sdk";
|
||||||
import type { ToolContext } from "../types.js";
|
import type { ToolContext } from "../types.js";
|
||||||
import { readProjects } from "../projects.js";
|
import { readProjects } from "../projects.js";
|
||||||
import { resolveRepoPath } from "../utils.js";
|
|
||||||
import { createProvider } from "../providers/index.js";
|
import { createProvider } from "../providers/index.js";
|
||||||
import { log as auditLog } from "../audit.js";
|
import { log as auditLog } from "../audit.js";
|
||||||
import type { StateLabel } from "../issue-provider.js";
|
import type { StateLabel } from "../issue-provider.js";
|
||||||
@@ -95,12 +94,8 @@ The issue is created with a state label (defaults to "Planning"). Returns the cr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Create provider
|
// 2. Create provider
|
||||||
const repoPath = resolveRepoPath(project.repo);
|
|
||||||
const config = api.pluginConfig as Record<string, unknown> | undefined;
|
|
||||||
const { provider, type: providerType } = createProvider({
|
const { provider, type: providerType } = createProvider({
|
||||||
glabPath: config?.glabPath as string | undefined,
|
repo: project.repo,
|
||||||
ghPath: config?.ghPath as string | undefined,
|
|
||||||
repoPath,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3. Create the issue
|
// 3. Create the issue
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import { selectModel } from "../model-selector.js";
|
|||||||
import { getProject, getWorker, readProjects } from "../projects.js";
|
import { getProject, getWorker, readProjects } from "../projects.js";
|
||||||
import type { ToolContext } from "../types.js";
|
import type { ToolContext } from "../types.js";
|
||||||
import { detectContext, generateGuardrails } from "../context-guard.js";
|
import { detectContext, generateGuardrails } from "../context-guard.js";
|
||||||
import { resolveRepoPath } from "../utils.js";
|
|
||||||
|
|
||||||
export function createTaskPickupTool(api: OpenClawPluginApi) {
|
export function createTaskPickupTool(api: OpenClawPluginApi) {
|
||||||
return (ctx: ToolContext) => ({
|
return (ctx: ToolContext) => ({
|
||||||
@@ -96,15 +95,8 @@ export function createTaskPickupTool(api: OpenClawPluginApi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. Fetch issue and verify state
|
// 3. Fetch issue and verify state
|
||||||
const repoPath = resolveRepoPath(project.repo);
|
|
||||||
const { provider } = createProvider({
|
const { provider } = createProvider({
|
||||||
glabPath: (api.pluginConfig as Record<string, unknown>)?.glabPath as
|
repo: project.repo,
|
||||||
| string
|
|
||||||
| undefined,
|
|
||||||
ghPath: (api.pluginConfig as Record<string, unknown>)?.ghPath as
|
|
||||||
| string
|
|
||||||
| undefined,
|
|
||||||
repoPath,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const issue = await provider.getIssue(issueId);
|
const issue = await provider.getIssue(issueId);
|
||||||
|
|||||||
@@ -9,19 +9,23 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "Model mapping per developer tier (junior, medior, senior, qa)",
|
"description": "Model mapping per developer tier (junior, medior, senior, qa)",
|
||||||
"properties": {
|
"properties": {
|
||||||
"junior": { "type": "string", "description": "Junior dev model (default: anthropic/claude-haiku-4-5)" },
|
"junior": {
|
||||||
"medior": { "type": "string", "description": "Medior dev model (default: anthropic/claude-sonnet-4-5)" },
|
"type": "string",
|
||||||
"senior": { "type": "string", "description": "Senior dev model (default: anthropic/claude-opus-4-5)" },
|
"description": "Junior dev model (default: anthropic/claude-haiku-4-5)"
|
||||||
"qa": { "type": "string", "description": "QA engineer model (default: anthropic/claude-sonnet-4-5)" }
|
},
|
||||||
|
"medior": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Medior dev model (default: anthropic/claude-sonnet-4-5)"
|
||||||
|
},
|
||||||
|
"senior": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Senior dev model (default: anthropic/claude-opus-4-5)"
|
||||||
|
},
|
||||||
|
"qa": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "QA engineer model (default: anthropic/claude-sonnet-4-5)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"glabPath": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Path to glab CLI binary. Defaults to 'glab' on PATH."
|
|
||||||
},
|
|
||||||
"ghPath": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Path to gh CLI binary. Defaults to 'gh' on PATH."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user