From 7f495c97a9cd884aceb486755280e55c8fb2c8e0 Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Sat, 10 Jan 2026 01:13:47 +0000 Subject: [PATCH] Introduce AutoMetabuilder core components and workflow packages: - Implement core components: CLI argument parsing, environment loading, GitHub service creation, and logging configuration. - Add support for OpenAI client setup and model resolution. - Develop SDLC context loader from GitHub and repository files. - Implement workflow context and engine builders. - Introduce major workflow packages: `game_tick_loop` and `contextual_iterative_loop`. - Update localization files with new package descriptions and labels. - Streamline web navigation by loading items from a dedicated JSON file. --- frontend/autometabuilder/app/page.tsx | 28 +- .../components/layout/PageLayout.tsx | 25 +- .../components/layout/Sidebar.tsx | 44 +- .../components/sections/DashboardSection.tsx | 121 ++-- .../components/sections/PromptSection.tsx | 43 +- .../components/sections/SettingsSection.tsx | 70 +- .../sections/TranslationsSection.tsx | 93 ++- .../components/sections/WorkflowSection.tsx | 83 ++- frontend/autometabuilder/hooks/useWebhook.ts | 22 + frontend/package-lock.json | 637 ++++++++++++++++++ frontend/package.json | 4 + 11 files changed, 1000 insertions(+), 170 deletions(-) create mode 100644 frontend/autometabuilder/hooks/useWebhook.ts diff --git a/frontend/autometabuilder/app/page.tsx b/frontend/autometabuilder/app/page.tsx index 1d58518..80b1be1 100644 --- a/frontend/autometabuilder/app/page.tsx +++ b/frontend/autometabuilder/app/page.tsx @@ -1,12 +1,14 @@ "use client"; import { useEffect, useMemo, useState } from "react"; +import { Alert, Snackbar } from "@mui/material"; import DashboardSection from "../components/sections/DashboardSection"; import PromptSection from "../components/sections/PromptSection"; import SettingsSection from "../components/sections/SettingsSection"; import TranslationsSection from "../components/sections/TranslationsSection"; import WorkflowSection from "../components/sections/WorkflowSection"; import PageLayout from "../components/layout/PageLayout"; +import useWebhook, { emitWebhook } from "../hooks/useWebhook"; import { fetchContext, fetchWorkflowPackage, @@ -22,6 +24,8 @@ export default function HomePage() { const [selectedSection, setSelectedSection] = useState("dashboard"); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); + const [snack, setSnack] = useState(""); + const [snackOpen, setSnackOpen] = useState(false); const loadContext = async () => { setLoading(true); @@ -41,6 +45,16 @@ export default function HomePage() { void loadContext(); }, []); + useWebhook( + "botRunComplete", + (detail) => { + const mode = (detail as { mode?: string })?.mode ?? "once"; + setSnack(`Run finished: ${mode}`); + setSnackOpen(true); + }, + [] + ); + const t = useMemo( () => (key: string, fallback?: string) => context?.messages[key] ?? fallback ?? key, [context] @@ -49,6 +63,7 @@ export default function HomePage() { const handleRun = async (payload: Parameters[0]) => { await runBot(payload); await loadContext(); + emitWebhook("runRequested", payload); }; const handleWorkflowSave = async (content: string) => { @@ -92,8 +107,9 @@ export default function HomePage() { } return ( - + )} - + + setSnackOpen(false)}> + setSnackOpen(false)} severity="info" sx={{ width: "100%" }}> + {snack} + + + ); } diff --git a/frontend/autometabuilder/components/layout/PageLayout.tsx b/frontend/autometabuilder/components/layout/PageLayout.tsx index 2d12ba1..ecc5b53 100644 --- a/frontend/autometabuilder/components/layout/PageLayout.tsx +++ b/frontend/autometabuilder/components/layout/PageLayout.tsx @@ -1,4 +1,5 @@ import { ReactNode } from "react"; +import { Box, Toolbar, Typography } from "@mui/material"; import { NavigationItem } from "../../lib/types"; import Sidebar from "./Sidebar"; @@ -12,15 +13,21 @@ type PageLayoutProps = { export default function PageLayout({ navItems, section, onSectionChange, t, children }: PageLayoutProps) { return ( -
+ -
-
-

{t("ui.app.title", "AutoMetabuilder Dashboard")}

-

{t("ui.dashboard.subtitle", "Control the bot and monitor system activity")}

-
-
{children}
-
-
+ + +
+ + {t("ui.app.title", "AutoMetabuilder Dashboard")} + + + {t("ui.dashboard.subtitle", "Control the bot and monitor system activity")} + +
+
+ {children} +
+ ); } diff --git a/frontend/autometabuilder/components/layout/Sidebar.tsx b/frontend/autometabuilder/components/layout/Sidebar.tsx index bdf360e..a588d41 100644 --- a/frontend/autometabuilder/components/layout/Sidebar.tsx +++ b/frontend/autometabuilder/components/layout/Sidebar.tsx @@ -1,3 +1,4 @@ +import { Box, Divider, Drawer, List, ListItemButton, ListItemText, Typography } from "@mui/material"; import { NavigationItem } from "../../lib/types"; type SidebarProps = { @@ -9,23 +10,30 @@ type SidebarProps = { export default function Sidebar({ items, selected, onSelect, t }: SidebarProps) { return ( - + + + + + {t("ui.app.name", "AutoMetabuilder")} + + + + + {items.map((item) => ( + onSelect(item.section)} + data-section={item.section} + sx={{ + color: selected === item.section ? "#fff" : "rgba(226,232,240,0.8)", + }} + > + + + ))} + + + ); } diff --git a/frontend/autometabuilder/components/sections/DashboardSection.tsx b/frontend/autometabuilder/components/sections/DashboardSection.tsx index 168e9b5..5208ae8 100644 --- a/frontend/autometabuilder/components/sections/DashboardSection.tsx +++ b/frontend/autometabuilder/components/sections/DashboardSection.tsx @@ -1,5 +1,19 @@ import { useState } from "react"; +import { + Box, + Button, + Checkbox, + FormControl, + FormControlLabel, + Paper, + Radio, + RadioGroup, + Stack, + TextField, + Typography, +} from "@mui/material"; import { UIStatus } from "../../lib/types"; +import { emitWebhook } from "../../hooks/useWebhook"; type DashboardSectionProps = { status: UIStatus; @@ -20,6 +34,7 @@ export default function DashboardSection({ status, logs, onRun, t }: DashboardSe try { await onRun({ mode, iterations, yolo: isYolo, stop_at_mvp: stopAtMvp }); setFeedback(t("ui.dashboard.start_bot", "Start Bot") + " " + t("ui.dashboard.status.running", "Running")); + emitWebhook("botRunComplete", { mode, iterations }); } catch (error) { console.error(error); setFeedback(t("ui.dashboard.status.idle", "Idle")); @@ -27,52 +42,72 @@ export default function DashboardSection({ status, logs, onRun, t }: DashboardSe }; return ( -
-
-

{t("ui.dashboard.title", "Dashboard")}

-

{t("ui.dashboard.subtitle", "Control the bot and monitor system activity")}

-
-
-
-

{t("ui.dashboard.bot_control", "Bot Control")}

-
- - - -
+ + + {t("ui.dashboard.title", "Dashboard")} + + + {t("ui.dashboard.subtitle", "Control the bot and monitor system activity")} + + + + + {t("ui.dashboard.bot_control", "Bot Control")} + + + setMode(event.target.value)} name="run-mode"> + {["once", "iterations", "yolo"].map((value) => ( + } + label={t(`ui.dashboard.run.${value}.title`, value === "iterations" ? "Repeat" : value.charAt(0).toUpperCase() + value.slice(1))} + /> + ))} + + {mode === "iterations" && ( - + setIterations(Number(event.target.value) || 1)} + sx={{ mt: 1, width: 140 }} + /> )} - - -

- {status.is_running ? t("ui.dashboard.status.running", "Running") : t("ui.dashboard.status.idle", "Idle")} •{" "} + + + {status.is_running ? t("ui.dashboard.status.running", "Running") : t("ui.dashboard.status.idle", "Idle")} • + {" "} {status.mvp_reached ? t("ui.dashboard.status.mvp_reached", "Reached") : t("ui.dashboard.status.mvp_progress", "In Progress")} -

-

{feedback}

-
-
-

{t("ui.dashboard.logs.title", "Recent Logs")}

-
{logs.slice(-1200) || t("ui.dashboard.status.idle", "Idle")}
-
-
-
+ + + {feedback} + + + + + {t("ui.dashboard.logs.title", "Recent Logs")} + + + {logs.slice(-1200) || t("ui.dashboard.status.idle", "Idle")} + + + + ); } diff --git a/frontend/autometabuilder/components/sections/PromptSection.tsx b/frontend/autometabuilder/components/sections/PromptSection.tsx index 7474377..fc57a04 100644 --- a/frontend/autometabuilder/components/sections/PromptSection.tsx +++ b/frontend/autometabuilder/components/sections/PromptSection.tsx @@ -1,4 +1,5 @@ import { useEffect, useState } from "react"; +import { Box, Button, Paper, Stack, TextField, Typography } from "@mui/material"; type PromptSectionProps = { content: string; @@ -21,18 +22,36 @@ export default function PromptSection({ content, onSave, t }: PromptSectionProps }; return ( -
-
-

{t("ui.prompt.title", "Prompt Builder")}

-

{t("ui.prompt.subtitle", "Shape how the assistant thinks, speaks, and decides")}

-
-