Skip to content

Commit 24cc6a0

Browse files
authored
Merge pull request #38 from oslabs-beta/paython-mcp
Paython mcp
2 parents 6a092e4 + 154355c commit 24cc6a0

File tree

10 files changed

+645
-326
lines changed

10 files changed

+645
-326
lines changed

client/src/lib/api.ts

Lines changed: 52 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -82,30 +82,60 @@ export const api = {
8282

8383

8484
// AI wizard – talks to /agent/wizard on the backend
85+
// askYamlWizard: async (input: {
86+
// repoUrl: string;
87+
// provider: string;
88+
// branch: string;
89+
// message?: string;
90+
// yaml?: string;
91+
// }) => {
92+
// const res = await fetch(`${SERVER_BASE}/agent/wizard/ai`, {
93+
// method: "POST",
94+
// headers: { "Content-Type": "application/json" },
95+
// credentials: "include",
96+
// body: JSON.stringify(input),
97+
// });
98+
99+
// const payload = await res.json().catch(() => ({}));
100+
// if (!res.ok || (payload as any)?.success === false) {
101+
// throw new Error(
102+
// (payload as any)?.error || res.statusText || "Agent error"
103+
// );
104+
// }
105+
106+
// // whatever runWizardAgent returns is in payload.data
107+
// return (payload as any).data;
108+
// },
109+
85110
askYamlWizard: async (input: {
86-
repoUrl: string;
87-
provider: string;
88-
branch: string;
89-
message?: string;
90-
yaml?: string;
91-
}) => {
92-
const res = await fetch(`${SERVER_BASE}/agent/wizard`, {
93-
method: "POST",
94-
headers: { "Content-Type": "application/json" },
95-
credentials: "include",
96-
body: JSON.stringify(input),
97-
});
111+
repoUrl: string;
112+
provider: string;
113+
branch: string;
114+
message?: string; // frontend name
115+
yaml?: string;
116+
}) => {
117+
const payload = {
118+
...input,
119+
prompt: input.message ?? "", // 👈 REQUIRED BY BACKEND
120+
};
121+
122+
delete (payload as any).message; // 👈 prevent backend confusion
123+
124+
const res = await fetch(`${SERVER_BASE}/agent/wizard/ai`, {
125+
method: "POST",
126+
headers: { "Content-Type": "application/json" },
127+
credentials: "include",
128+
body: JSON.stringify(payload),
129+
});
98130

99-
const payload = await res.json().catch(() => ({}));
100-
if (!res.ok || (payload as any)?.success === false) {
101-
throw new Error(
102-
(payload as any)?.error || res.statusText || "Agent error"
103-
);
104-
}
131+
const data = await res.json().catch(() => ({}));
105132

106-
// whatever runWizardAgent returns is in payload.data
107-
return (payload as any).data;
108-
},
133+
if (!res.ok || data?.success === false) {
134+
throw new Error(data?.error || res.statusText || "Agent error");
135+
}
136+
137+
return data.data;
138+
},
109139

110140
// ===== MCP helpers for repos / branches / pipeline generation =====
111141
async listRepos(): Promise<{ repos: string[] }> {
@@ -151,85 +181,10 @@ export const api = {
151181
return { branches: cachedBranches.get(repo) ?? [] };
152182
}
153183
},
154-
// async listRepos(): Promise<{ repos: string[] }> {
155-
// // If we already have repos cached, reuse them.
156-
// if (cachedRepos && cachedRepos.length > 0) {
157-
// return { repos: cachedRepos };
158-
// }
159-
160-
// // If we've already tried once and failed, don't hammer the server.
161-
// if (reposAttempted && !cachedRepos) {
162-
// return { repos: [] };
163-
// }
164-
165-
// reposAttempted = true;
166-
167-
// try {
168-
// const outer = await mcp<{
169-
// provider: string;
170-
// user: string;
171-
// repositories: { full_name: string }[];
172-
// }>("repo_reader", {});
173-
174-
// const repos = outer?.repositories?.map((r) => r.full_name) ?? [];
175-
// cachedRepos = repos;
176-
// return { repos };
177-
// } catch (err) {
178-
// console.error("[api.listRepos] failed:", err);
179-
// // Don't throw to avoid retry loops from effects; just return whatever we have (or empty).
180-
// return { repos: cachedRepos ?? [] };
181-
// }
182-
// },
183-
184-
async listBranches(repo: string): Promise<{ branches: string[] }> {
185-
// ✅ If we already have branches cached for this repo, reuse them.
186-
const cached = cachedBranches.get(repo);
187-
if (cached) {
188-
return { branches: cached };
189-
}
190-
191-
try {
192-
// For now we still use repo_reader, but we only call it
193-
// when the cache is cold. We can later swap this to a
194-
// more specific MCP tool like "repo_branches".
195-
const outer = await mcp<{
196-
success?: boolean;
197-
data?: { repositories: { full_name: string; branches?: string[] }[] };
198-
repositories?: { full_name: string; branches?: string[] }[];
199-
}>("repo_reader", {
200-
// This extra input is safe: current server ignores it,
201-
// future server can use it to optimize.
202-
repoFullName: repo,
203-
});
204-
205-
// Unwrap the payload (tool responses come back as { success, data })
206-
const body = (outer as any)?.data ?? outer;
207-
208-
const match = body?.repositories?.find((r: any) => r.full_name === repo);
209-
const branches = match?.branches ?? [];
210-
211-
// Cache even empty arrays so we don't re-query a repo with no branches
212-
cachedBranches.set(repo, branches);
213-
214-
return { branches };
215-
} catch (err) {
216-
console.error("[api.listBranches] failed:", err);
217-
218-
// If we have anything cached (even empty), use it.
219-
const fallback = cachedBranches.get(repo) ?? [];
220-
return { branches: fallback };
221-
}
222-
},
223184

224185
async createPipeline(payload: any) {
225186
const { repo, branch, template = "node_app", options } = payload || {};
226-
const data = await mcp("pipeline_generator", {
227-
repo,
228-
branch,
229-
provider: "aws",
230-
template,
231-
options: options || {},
232-
});
187+
const data = await mcp("pipeline_generator", payload);
233188
return data;
234189
},
235190

client/src/pages/ConfigurePage.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,9 @@ export default function ConfigurePage() {
209209
disabled={busy}
210210
value={options.nodeVersion}
211211
onChange={(e) => setOption("nodeVersion", e.target.value)}
212-
className="rounded-md border px-3 py-2 text-sm font-mono"
212+
className="rounded-md border px-3 py-2 text-sm font-mono
213+
text-slate-900 bg-white
214+
disabled:bg-slate-100 disabled:text-slate-400"
213215
placeholder="20"
214216
/>
215217
</label>
@@ -220,7 +222,9 @@ export default function ConfigurePage() {
220222
disabled={busy}
221223
value={options.installCmd}
222224
onChange={(e) => setOption("installCmd", e.target.value)}
223-
className="rounded-md border px-3 py-2 text-sm font-mono"
225+
className="rounded-md border px-3 py-2 text-sm font-mono
226+
text-slate-900 bg-white
227+
disabled:bg-slate-100 disabled:text-slate-400"
224228
placeholder="npm ci"
225229
/>
226230
</label>
@@ -231,7 +235,9 @@ export default function ConfigurePage() {
231235
disabled={busy}
232236
value={options.testCmd}
233237
onChange={(e) => setOption("testCmd", e.target.value)}
234-
className="rounded-md border px-3 py-2 text-sm font-mono"
238+
className="rounded-md border px-3 py-2 text-sm font-mono
239+
text-slate-900 bg-white
240+
disabled:bg-slate-100 disabled:text-slate-400"
235241
placeholder="npm test"
236242
/>
237243
</label>
@@ -242,7 +248,9 @@ export default function ConfigurePage() {
242248
disabled={busy}
243249
value={options.buildCmd}
244250
onChange={(e) => setOption("buildCmd", e.target.value)}
245-
className="rounded-md border px-3 py-2 text-sm font-mono"
251+
className="rounded-md border px-3 py-2 text-sm font-mono
252+
text-slate-900 bg-white
253+
disabled:bg-slate-100 disabled:text-slate-400"
246254
placeholder="npm run build"
247255
/>
248256
</label>

client/src/store/usePipelineStore.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type PipelineState = {
1515
buildCmd: string;
1616
awsRoleArn?: string;
1717
};
18+
provider: "aws" | "jenkins";
1819

1920
// outputs from MCP
2021
result?: McpPipeline;
@@ -36,6 +37,7 @@ type PipelineState = {
3637

3738
type PipelineActions = {
3839
setTemplate(t: string): void;
40+
setProvider(p: "aws" | "jenkins"): void;
3941
toggleStage(s: Stage): void;
4042
setOption<K extends keyof PipelineState["options"]>(
4143
k: K,
@@ -61,6 +63,7 @@ const initial: PipelineState = {
6163
testCmd: "npm test",
6264
buildCmd: "npm run build",
6365
},
66+
provider: "aws",
6467
roles: [],
6568
editing: false,
6669
status: "idle",

0 commit comments

Comments
 (0)