pi-project-gate 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/helpers.ts +20 -8
- package/src/tools/issues.ts +6 -6
- package/src/tools/project.ts +7 -7
package/package.json
CHANGED
package/src/helpers.ts
CHANGED
|
@@ -16,13 +16,25 @@ export function resolveGitea(cwd: string): { repo: string; token: string } {
|
|
|
16
16
|
return { repo, token: credMatch ? credMatch[2] : "" };
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export function giteaApi(path: string, method: string, body: Record<string, unknown> | null, opts: { repo: string; token?: string },
|
|
19
|
+
export async function giteaApi(path: string, method: string, body: Record<string, unknown> | null, opts: { repo: string; token?: string }, _cwd: string): Promise<{ ok: boolean; data: unknown; error?: string }> {
|
|
20
20
|
const base = `http://127.0.0.1:3001/api/v1/repos/${opts.repo}`;
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
const url = `${base}${path}`;
|
|
22
|
+
const headers: Record<string, string> = { "Content-Type": "application/json" };
|
|
23
|
+
if (opts.token) headers["Authorization"] = `token ${opts.token}`;
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const res = await fetch(url, {
|
|
27
|
+
method,
|
|
28
|
+
headers,
|
|
29
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
30
|
+
});
|
|
31
|
+
const text = await res.text();
|
|
32
|
+
if (!res.ok) {
|
|
33
|
+
const lines = text.split("\n");
|
|
34
|
+
return { ok: false, data: null, error: text || lines.slice(0, -1).join("\n") || "API error" };
|
|
35
|
+
}
|
|
36
|
+
try { return { ok: true, data: JSON.parse(text) }; } catch { return { ok: true, data: text }; }
|
|
37
|
+
} catch (e: any) {
|
|
38
|
+
return { ok: false, data: null, error: e.message || "Network error" };
|
|
39
|
+
}
|
|
28
40
|
}
|
package/src/tools/issues.ts
CHANGED
|
@@ -51,7 +51,7 @@ export const createTool = {
|
|
|
51
51
|
if (params.milestone) payload.milestone = params.milestone;
|
|
52
52
|
if (params.assignee) payload.assignee = params.assignee;
|
|
53
53
|
|
|
54
|
-
const r = giteaApi("/issues", "POST", payload, opts, ctx.cwd);
|
|
54
|
+
const r = await giteaApi("/issues", "POST", payload, opts, ctx.cwd);
|
|
55
55
|
if (!r.ok || !r.data) {
|
|
56
56
|
return {
|
|
57
57
|
content: [{ type: "text", text: `❌ Failed to create issue: ${r.error || "unknown error"}` }],
|
|
@@ -101,7 +101,7 @@ export const updateTool = {
|
|
|
101
101
|
const issueId = String(params.issue_id).replace(/^#/, "");
|
|
102
102
|
|
|
103
103
|
// Fetch current issue to verify it exists
|
|
104
|
-
const current = giteaApi(`/issues/${issueId}`, "GET", null, opts, ctx.cwd);
|
|
104
|
+
const current = await giteaApi(`/issues/${issueId}`, "GET", null, opts, ctx.cwd);
|
|
105
105
|
if (!current.ok || !current.data) {
|
|
106
106
|
return {
|
|
107
107
|
content: [{ type: "text", text: `❌ Issue #${issueId} not found.` }],
|
|
@@ -144,7 +144,7 @@ export const updateTool = {
|
|
|
144
144
|
};
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
const r = giteaApi(`/issues/${issueId}`, "PATCH", payload, opts, ctx.cwd);
|
|
147
|
+
const r = await giteaApi(`/issues/${issueId}`, "PATCH", payload, opts, ctx.cwd);
|
|
148
148
|
if (!r.ok || !r.data) {
|
|
149
149
|
return {
|
|
150
150
|
content: [{ type: "text", text: `❌ Failed to update issue: ${r.error || "unknown error"}` }],
|
|
@@ -201,7 +201,7 @@ export const listTool = {
|
|
|
201
201
|
if (params.assignee) queryParts.push(`assignee=${encodeURIComponent(params.assignee)}`);
|
|
202
202
|
if (params.q) queryParts.push(`q=${encodeURIComponent(params.q)}`);
|
|
203
203
|
|
|
204
|
-
const r = giteaApi(`/issues?${queryParts.join("&")}`, "GET", null, opts, ctx.cwd);
|
|
204
|
+
const r = await giteaApi(`/issues?${queryParts.join("&")}`, "GET", null, opts, ctx.cwd);
|
|
205
205
|
if (!r.ok) {
|
|
206
206
|
return {
|
|
207
207
|
content: [{ type: "text", text: `❌ Failed to list issues: ${r.error || "unknown error"}` }],
|
|
@@ -257,7 +257,7 @@ export const getTool = {
|
|
|
257
257
|
const opts = resolveGitea(ctx.cwd);
|
|
258
258
|
const issueId = String(params.issue_id).replace(/^#/, "");
|
|
259
259
|
|
|
260
|
-
const r = giteaApi(`/issues/${issueId}`, "GET", null, opts, ctx.cwd);
|
|
260
|
+
const r = await giteaApi(`/issues/${issueId}`, "GET", null, opts, ctx.cwd);
|
|
261
261
|
if (!r.ok || !r.data) {
|
|
262
262
|
return {
|
|
263
263
|
content: [{ type: "text", text: `❌ Issue #${issueId} not found.` }],
|
|
@@ -289,7 +289,7 @@ export const getTool = {
|
|
|
289
289
|
// Fetch comments
|
|
290
290
|
const includeComments = params.include_comments !== false;
|
|
291
291
|
if (includeComments) {
|
|
292
|
-
const cr = giteaApi(
|
|
292
|
+
const cr = await giteaApi(
|
|
293
293
|
`/issues/${issueId}/comments?limit=20`,
|
|
294
294
|
"GET",
|
|
295
295
|
null,
|
package/src/tools/project.ts
CHANGED
|
@@ -13,7 +13,7 @@ export const checkTool = {
|
|
|
13
13
|
async execute(_id: string, params: any, _s: any, _u: any, ctx: ExtensionContext) {
|
|
14
14
|
const config = loadConfig(ctx.cwd); const opts = resolveGitea(ctx.cwd);
|
|
15
15
|
const issueId = params.issue_id.replace(/^#/, "");
|
|
16
|
-
const r = giteaApi(`/issues/${issueId}`, "GET", null, opts, ctx.cwd);
|
|
16
|
+
const r = await giteaApi(`/issues/${issueId}`, "GET", null, opts, ctx.cwd);
|
|
17
17
|
if (!r.ok || !r.data) return { content: [{ type: "text", text: `Issue #${issueId} not found.` }], isError: true, details: {} };
|
|
18
18
|
const issue = r.data as Record<string, unknown>;
|
|
19
19
|
const lines: string[] = []; const issues: string[] = [];
|
|
@@ -27,7 +27,7 @@ export const checkTool = {
|
|
|
27
27
|
const deps = parseDependencies(body, config);
|
|
28
28
|
if (deps.length > 0) {
|
|
29
29
|
const blocked: string[] = [];
|
|
30
|
-
for (const dep of deps) { const dr = giteaApi(`/issues/${dep}`, "GET", null, opts, ctx.cwd); if (dr.ok && (dr.data as any)?.state === "open") blocked.push(dep); }
|
|
30
|
+
for (const dep of deps) { const dr = await giteaApi(`/issues/${dep}`, "GET", null, opts, ctx.cwd); if (dr.ok && (dr.data as any)?.state === "open") blocked.push(dep); }
|
|
31
31
|
if (blocked.length > 0) issues.push(`🔒 Blocked by: #${blocked.join(", #")}`);
|
|
32
32
|
else lines.push(" Dependencies: ✅");
|
|
33
33
|
}
|
|
@@ -46,7 +46,7 @@ export const startTool = {
|
|
|
46
46
|
async execute(_id: string, params: any, _s: any, _u: any, ctx: ExtensionContext) {
|
|
47
47
|
const config = loadConfig(ctx.cwd); const opts = resolveGitea(ctx.cwd);
|
|
48
48
|
const issueId = params.issue_id.replace(/^#/, "");
|
|
49
|
-
const r = giteaApi(`/issues/${issueId}`, "GET", null, opts, ctx.cwd);
|
|
49
|
+
const r = await giteaApi(`/issues/${issueId}`, "GET", null, opts, ctx.cwd);
|
|
50
50
|
if (!r.ok || !r.data) return { content: [{ type: "text", text: `Issue #${issueId} not found.` }], isError: true, details: {} };
|
|
51
51
|
const issue = r.data as Record<string, unknown>;
|
|
52
52
|
const body = (issue.body as string) || "";
|
|
@@ -55,10 +55,10 @@ export const startTool = {
|
|
|
55
55
|
const deps = parseDependencies(body, config);
|
|
56
56
|
if (deps.length > 0) {
|
|
57
57
|
const blocked: string[] = [];
|
|
58
|
-
for (const dep of deps) { const dr = giteaApi(`/issues/${dep}`, "GET", null, opts, ctx.cwd); if (dr.ok && (dr.data as any)?.state === "open") blocked.push(dep); }
|
|
58
|
+
for (const dep of deps) { const dr = await giteaApi(`/issues/${dep}`, "GET", null, opts, ctx.cwd); if (dr.ok && (dr.data as any)?.state === "open") blocked.push(dep); }
|
|
59
59
|
if (blocked.length > 0) return { content: [{ type: "text", text: `🔒 Blocked: #${blocked.join(", #")}` }], isError: true, details: {} };
|
|
60
60
|
}
|
|
61
|
-
const wipR = giteaApi("/pulls?state=open&limit=100", "GET", null, opts, ctx.cwd);
|
|
61
|
+
const wipR = await giteaApi("/pulls?state=open&limit=100", "GET", null, opts, ctx.cwd);
|
|
62
62
|
const prs = Array.isArray(wipR.data) ? wipR.data : [];
|
|
63
63
|
const author = (issue.user as any)?.login || "factory";
|
|
64
64
|
const currentWip = prs.filter((p: any) => p.user?.login === author).length;
|
|
@@ -75,13 +75,13 @@ export const statusTool = {
|
|
|
75
75
|
async execute(_id: string, _p: any, _s: any, _u: any, ctx: ExtensionContext) {
|
|
76
76
|
const config = loadConfig(ctx.cwd); const opts = resolveGitea(ctx.cwd);
|
|
77
77
|
const lines = ["📊 Project Status", ""];
|
|
78
|
-
const wipR = giteaApi("/pulls?state=open&limit=100", "GET", null, opts, ctx.cwd);
|
|
78
|
+
const wipR = await giteaApi("/pulls?state=open&limit=100", "GET", null, opts, ctx.cwd);
|
|
79
79
|
const prs = Array.isArray(wipR.data) ? wipR.data : [];
|
|
80
80
|
const byAuthor: Record<string, number> = {};
|
|
81
81
|
for (const pr of prs) { const a = (pr as any).user?.login || "?"; byAuthor[a] = (byAuthor[a] || 0) + 1; }
|
|
82
82
|
lines.push(`🏗 WIP: ${prs.length} open PRs (limit: ${config.maxWip})`);
|
|
83
83
|
for (const [a, c] of Object.entries(byAuthor).sort(([, a], [, b]) => b - a)) lines.push(` ${a}: ${c}/${config.maxWip} ${c >= config.maxWip ? "⚠️" : "✅"}`);
|
|
84
|
-
const issuesR = giteaApi("/issues?state=open&limit=10", "GET", null, opts, ctx.cwd);
|
|
84
|
+
const issuesR = await giteaApi("/issues?state=open&limit=10", "GET", null, opts, ctx.cwd);
|
|
85
85
|
if (issuesR.ok && Array.isArray(issuesR.data)) {
|
|
86
86
|
const assigned = (issuesR.data as any[]).filter((i: any) => i.assignee).slice(0, 5);
|
|
87
87
|
if (assigned.length > 0) { lines.push("", "In Progress:"); for (const i of assigned) lines.push(` - #${i.number} [${i.assignee?.login}] ${i.title}`); }
|