From f49ae7bf7e89e3a647a8f015380cfbe257fb3f58 Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Sat, 10 Jan 2026 01:35:17 +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. --- PROMPT.md | 4 + frontend/autometabuilder/app/page.tsx | 156 ++++++++---------- .../hooks/useDashboardContext.ts | 47 ++++++ 3 files changed, 121 insertions(+), 86 deletions(-) create mode 100644 frontend/autometabuilder/hooks/useDashboardContext.ts diff --git a/PROMPT.md b/PROMPT.md index 17a0825..0f8405a 100644 --- a/PROMPT.md +++ b/PROMPT.md @@ -49,3 +49,7 @@ Avoid stagnation; improve structure, clarity, and expressiveness over time. Roadmap discipline. If you run out of ROADMAP.md tasks, stop and report. We should reassess priorities before inventing work. + +React component logic (just above the bottom jsx) can be converted to one or more custom hooks. + +Use atomic React components. diff --git a/frontend/autometabuilder/app/page.tsx b/frontend/autometabuilder/app/page.tsx index 80b1be1..ccdbf43 100644 --- a/frontend/autometabuilder/app/page.tsx +++ b/frontend/autometabuilder/app/page.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect, useMemo, useState } from "react"; +import { useEffect } from "react"; import { Alert, Snackbar } from "@mui/material"; import DashboardSection from "../components/sections/DashboardSection"; import PromptSection from "../components/sections/PromptSection"; @@ -8,42 +8,29 @@ 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, - runBot, - savePrompt, - saveSettings, - saveWorkflow, -} from "../lib/api"; -import { UIContext } from "../lib/types"; +import useDashboardContext from "../hooks/useDashboardContext"; +import { emitWebhook, useWebhook } from "../hooks/useWebhook"; +import { fetchWorkflowPackage, runBot, savePrompt, saveSettings, saveWorkflow } from "../lib/api"; export default function HomePage() { - const [context, setContext] = useState(null); - 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); - setError(""); - try { - const data = await fetchContext(); - setContext(data); - setSelectedSection((prev) => prev || data.navigation[0]?.section || "dashboard"); - } catch (err) { - setError(String(err)); - } finally { - setLoading(false); - } - }; + const { + context, + selectedSection, + setSelectedSection, + loading, + error, + snack, + setSnack, + snackOpen, + setSnackOpen, + ready, + loadContext, + t, + } = useDashboardContext(); useEffect(() => { void loadContext(); - }, []); + }, [loadContext]); useWebhook( "botRunComplete", @@ -55,39 +42,13 @@ export default function HomePage() { [] ); - const t = useMemo( - () => (key: string, fallback?: string) => context?.messages[key] ?? fallback ?? key, - [context] - ); - const handleRun = async (payload: Parameters[0]) => { await runBot(payload); - await loadContext(); - emitWebhook("runRequested", payload); - }; - - const handleWorkflowSave = async (content: string) => { - await saveWorkflow(content); + emitWebhook("botRunComplete", payload); await loadContext(); }; - const handleTemplateSelect = async (id: string) => { - const pkg = await fetchWorkflowPackage(id); - const workflowPayload = JSON.stringify(pkg.workflow ?? {}, null, 2); - setContext((prev) => (prev ? { ...prev, workflow_content: workflowPayload } : prev)); - }; - - const handlePromptSave = async (content: string) => { - await savePrompt(content); - await loadContext(); - }; - - const handleSettingsSave = async (values: Record) => { - await saveSettings(values); - await loadContext(); - }; - - if (loading) { + if (isLoading) { return (

Loading dashboard…

@@ -95,7 +56,7 @@ export default function HomePage() { ); } - if (error || !context) { + if (error || !ready || !context) { return (

{error || "Unable to load context."}

@@ -108,31 +69,54 @@ export default function HomePage() { return ( <> - - {selectedSection === "dashboard" && ( - - )} - {selectedSection === "workflow" && ( - - )} - {selectedSection === "prompt" && } - {selectedSection === "settings" && ( - - )} - {selectedSection === "translations" && ( - - )} + + {selectedSection === "dashboard" && ( + + )} + {selectedSection === "workflow" && ( + { + await saveWorkflow(content); + emitWebhook("workflow.save", { content }); + await loadContext(); + }} + onTemplateSelect={async (id) => { + const pkg = await fetchWorkflowPackage(id); + if (pkg.workflow) { + const workflowPayload = JSON.stringify(pkg.workflow ?? {}, null, 2); + await saveWorkflow(workflowPayload); + emitWebhook("workflow.template.selected", { id }); + await loadContext(); + } + }} + t={t} + /> + )} + {selectedSection === "prompt" && ( + { + await savePrompt(content); + emitWebhook("prompt.save", { content }); + await loadContext(); + }} + t={t} + /> + )} + {selectedSection === "settings" && ( + { + await saveSettings(values); + emitWebhook("settings.save", { values }); + await loadContext(); + }} + t={t} + /> + )} + {selectedSection === "translations" && } setSnackOpen(false)}> setSnackOpen(false)} severity="info" sx={{ width: "100%" }}> diff --git a/frontend/autometabuilder/hooks/useDashboardContext.ts b/frontend/autometabuilder/hooks/useDashboardContext.ts new file mode 100644 index 0000000..1afa412 --- /dev/null +++ b/frontend/autometabuilder/hooks/useDashboardContext.ts @@ -0,0 +1,47 @@ +import { useEffect, useMemo, useState } from "react"; +import { fetchContext } from "../lib/api"; +import { UIContext } from "../lib/types"; + +export default function useDashboardContext() { + const [context, setContext] = useState(null); + 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); + setError(""); + try { + const data = await fetchContext(); + setContext(data); + setSelectedSection((prev) => prev || data.navigation[0]?.section || "dashboard"); + } catch (err) { + setError(String(err)); + } finally { + setLoading(false); + } + }; + + const ready = context !== null; + const t = useMemo( + () => (key: string, fallback?: string) => (context?.messages[key] ?? fallback ?? key), + [context] + ); + + return { + context, + selectedSection, + setSelectedSection, + loading, + error, + snack, + setSnack, + snackOpen, + setSnackOpen, + loadContext, + t, + ready, + }; +}