@yoonion/mimi-seed-mcp 0.3.20 → 0.3.21
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/dist/ci/github.js +18 -13
- package/dist/registers/ci.js +25 -10
- package/package.json +1 -1
package/dist/ci/github.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
function base(cfg) {
|
|
2
|
+
// GitHub Enterprise: host = https://github.example.com → API base = https://github.example.com/api/v3
|
|
3
|
+
if (cfg.host)
|
|
4
|
+
return `${cfg.host.replace(/\/$/, '')}/api/v3`;
|
|
5
|
+
return 'https://api.github.com';
|
|
6
|
+
}
|
|
2
7
|
function headers(token) {
|
|
3
8
|
return {
|
|
4
9
|
Authorization: `Bearer ${token}`,
|
|
@@ -7,10 +12,10 @@ function headers(token) {
|
|
|
7
12
|
'Content-Type': 'application/json',
|
|
8
13
|
};
|
|
9
14
|
}
|
|
10
|
-
async function ghFetch(
|
|
11
|
-
const res = await fetch(`${
|
|
15
|
+
async function ghFetch(cfg, endpoint, options) {
|
|
16
|
+
const res = await fetch(`${base(cfg)}${endpoint}`, {
|
|
12
17
|
...options,
|
|
13
|
-
headers: { ...headers(token), ...(options?.headers ?? {}) },
|
|
18
|
+
headers: { ...headers(cfg.token), ...(options?.headers ?? {}) },
|
|
14
19
|
});
|
|
15
20
|
if (res.status === 204)
|
|
16
21
|
return null;
|
|
@@ -20,7 +25,7 @@ async function ghFetch(token, endpoint, options) {
|
|
|
20
25
|
return JSON.parse(body);
|
|
21
26
|
}
|
|
22
27
|
export async function listWorkflows(cfg) {
|
|
23
|
-
const data = await ghFetch(cfg
|
|
28
|
+
const data = await ghFetch(cfg, `/repos/${cfg.owner}/${cfg.repo}/actions/workflows`);
|
|
24
29
|
return data.workflows.map((w) => ({
|
|
25
30
|
id: w.id,
|
|
26
31
|
name: w.name,
|
|
@@ -30,19 +35,19 @@ export async function listWorkflows(cfg) {
|
|
|
30
35
|
}));
|
|
31
36
|
}
|
|
32
37
|
export async function triggerBuild(cfg, workflow, ref = 'main', inputs = {}) {
|
|
33
|
-
// workflow: filename (deploy.yml) or numeric ID string
|
|
34
38
|
const wfId = /^\d+$/.test(workflow) ? Number(workflow) : workflow;
|
|
35
|
-
|
|
39
|
+
const startTime = new Date();
|
|
40
|
+
await ghFetch(cfg, `/repos/${cfg.owner}/${cfg.repo}/actions/workflows/${wfId}/dispatches`, {
|
|
36
41
|
method: 'POST',
|
|
37
42
|
body: JSON.stringify({ ref, inputs }),
|
|
38
43
|
});
|
|
39
|
-
// Dispatch returns 204 with no run ID — poll briefly then
|
|
44
|
+
// Dispatch returns 204 with no run ID — poll briefly then filter by start time
|
|
40
45
|
await new Promise((r) => setTimeout(r, 3000));
|
|
41
|
-
const runs = await listRecentBuilds(cfg, workflow,
|
|
42
|
-
return runs[0] ?? null;
|
|
46
|
+
const runs = await listRecentBuilds(cfg, workflow, 5);
|
|
47
|
+
return runs.find((r) => new Date(r.createdAt) >= startTime) ?? runs[0] ?? null;
|
|
43
48
|
}
|
|
44
49
|
export async function getBuildStatus(cfg, runId) {
|
|
45
|
-
const data = await ghFetch(cfg
|
|
50
|
+
const data = await ghFetch(cfg, `/repos/${cfg.owner}/${cfg.repo}/actions/runs/${runId}`);
|
|
46
51
|
return normalize(data);
|
|
47
52
|
}
|
|
48
53
|
export async function listRecentBuilds(cfg, workflow, limit = 10) {
|
|
@@ -54,11 +59,11 @@ export async function listRecentBuilds(cfg, workflow, limit = 10) {
|
|
|
54
59
|
else {
|
|
55
60
|
endpoint = `/repos/${cfg.owner}/${cfg.repo}/actions/runs?per_page=${limit}`;
|
|
56
61
|
}
|
|
57
|
-
const data = await ghFetch(cfg
|
|
62
|
+
const data = await ghFetch(cfg, endpoint);
|
|
58
63
|
return data.workflow_runs.map(normalize);
|
|
59
64
|
}
|
|
60
65
|
export async function cancelBuild(cfg, runId) {
|
|
61
|
-
await ghFetch(cfg
|
|
66
|
+
await ghFetch(cfg, `/repos/${cfg.owner}/${cfg.repo}/actions/runs/${runId}/cancel`, {
|
|
62
67
|
method: 'POST',
|
|
63
68
|
});
|
|
64
69
|
}
|
package/dist/registers/ci.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import { requireCiConfig, saveCiConfig } from '../ci/config.js';
|
|
3
3
|
import * as github from '../ci/github.js';
|
|
4
4
|
import * as gitlab from '../ci/gitlab.js';
|
|
5
|
-
function dispatch(fn, cfg, ...args) {
|
|
6
|
-
return fn[cfg.provider](cfg, ...args);
|
|
7
|
-
}
|
|
8
5
|
export function registerCiTools(server) {
|
|
9
6
|
server.tool('ci_save_config', [
|
|
10
7
|
'GitHub Actions 또는 GitLab CI 연결 설정을 저장합니다.',
|
|
11
8
|
'저장 위치: ~/.mimi-seed/ci.json (mode 0600).',
|
|
12
9
|
'GitHub: provider="github", token="ghp_..." (repo+workflow 스코프 필요)',
|
|
10
|
+
'GitHub Enterprise: host="https://github.example.com" 추가',
|
|
13
11
|
'GitLab.com: provider="gitlab", token="glpat-..."',
|
|
14
12
|
'Self-hosted GitLab: host="https://gitlab.example.com" 추가',
|
|
15
13
|
].join(' '), {
|
|
@@ -17,17 +15,17 @@ export function registerCiTools(server) {
|
|
|
17
15
|
token: z.string().describe('Personal Access Token'),
|
|
18
16
|
owner: z.string().describe('GitHub org/user 또는 GitLab namespace'),
|
|
19
17
|
repo: z.string().describe('저장소 이름 (경로 없이 repo명만)'),
|
|
20
|
-
host: z.string().optional().describe('GitLab self-hosted URL
|
|
18
|
+
host: z.string().optional().describe('GitHub Enterprise 또는 GitLab self-hosted URL'),
|
|
21
19
|
}, async ({ provider, token, owner, repo, host }) => {
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
const config = { provider, token, owner, repo, host };
|
|
21
|
+
saveCiConfig(config);
|
|
24
22
|
return {
|
|
25
23
|
content: [{
|
|
26
24
|
type: 'text',
|
|
27
25
|
text: [
|
|
28
|
-
`✅ CI 설정 저장 완료 (${
|
|
29
|
-
` 저장소: ${
|
|
30
|
-
|
|
26
|
+
`✅ CI 설정 저장 완료 (${provider})`,
|
|
27
|
+
` 저장소: ${owner}/${repo}`,
|
|
28
|
+
host ? ` Host: ${host}` : '',
|
|
31
29
|
'',
|
|
32
30
|
'ci_list_workflows 로 사용 가능한 워크플로를 확인하세요.',
|
|
33
31
|
].filter(Boolean).join('\n'),
|
|
@@ -153,4 +151,21 @@ export function registerCiTools(server) {
|
|
|
153
151
|
}],
|
|
154
152
|
};
|
|
155
153
|
});
|
|
154
|
+
server.tool('ci_cancel_build', '진행 중인 빌드를 취소합니다. (GitHub Actions run / GitLab pipeline)', {
|
|
155
|
+
run_id: z.string().describe('빌드 ID (ci_trigger_build 또는 ci_list_recent_builds 반환값)'),
|
|
156
|
+
}, async ({ run_id }) => {
|
|
157
|
+
const cfg = requireCiConfig();
|
|
158
|
+
if (cfg.provider === 'github') {
|
|
159
|
+
await github.cancelBuild(cfg, run_id);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
await gitlab.cancelBuild(cfg, run_id);
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
content: [{
|
|
166
|
+
type: 'text',
|
|
167
|
+
text: `⛔ 빌드 #${run_id} 취소 요청 완료.\nci_get_build_status(run_id="${run_id}") 로 상태를 확인하세요.`,
|
|
168
|
+
}],
|
|
169
|
+
};
|
|
170
|
+
});
|
|
156
171
|
}
|
package/package.json
CHANGED