Feat/stateless backend creation tool - #242
Open
StpMax wants to merge 14 commits into
Open
Conversation
…ckend_creation_tool
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Feat:
generate_artifact— FSM orchestrator for LLM-driven artifact generationFQE-2213
Description
Adds a new
generate_artifacttool — an orchestrator built around a deterministic finite-state machine (FSM) that drives LLM generation of finished artifacts (HTML apps and fullstack apps), including data-sufficiency checks, spec generation, code generation, and verification steps.Unlike the previous description, this is not a simple async tool-use/tool-result loop wrapped around a single call — it's a graph of steps (
orchestrator.py) where decision nodes ("is there enough data?", "can the data be fetched?", "is this a fullstack stack or not?") produce Pydantic verdicts, and generation nodes are bounded tool-use loops (engine.py).Architecture
state.py—GenState: session, artifact type, path, brief, fullstack flag, data notes, API spec, list of written files, step trace. Also the verdict models:DataVerdict,RequiredData,FetchVerdict,VerifyResult.orchestrator.py— the FSM graph itself (described as a Graphviz digraph and embedded into the prompts so the LLM understands its place in the pipeline):is_data_enough→define_required_data→is_possible_to_fetch→fetch_data_sample→ back tois_data_enough(capped atDATA_LOOP_MAX = 3iterations).make_tech_spec→ deterministic branch onis_fullstack.html-app:generate_frontend→verify_frontend.make_api_spec(single call producing an OpenAPI 3.1 JSON spec) → in parallel (asyncio.gather)generate_backend→verify_backendandgenerate_frontend→verify_frontend→ thenrun_app→verify_fullstack(actually launches the backend and health-checks it).engine.py— the reusable primitives: one-shot API spec generation, and_run_loop— the shared bounded tool-use/tool-result loop (MAX_ROUNDS = 16, raised from 12 because sub-generators now also spend rounds on scratchpad calls). Oncebackend.pyis written, the backend step auto-injects an instruction to also writerequirements.txt. Each side (backend/frontend) may retry generation once (GEN_VERIFY_MAX_RETRIES = 1) with verifier errors fed back in; app launch also allows one retry (RUNAPP_MAX_RETRIES = 1) with thebackend.logtail included.Artifact types
html-app— a single self-contained HTML file with data embedded inline; no API spec, no backend.fullstack-stateless-app— backend + frontend, with an explicit "STATELESS" constraint injected into the prompts: no sqlite/local files/in-process mutable stores; external DB/API access is fine.fullstack-stateful-app— same flow, but local persistence (e.g. sqlite) is allowed.Verification (
verifiers.py)verify_frontend— static HTML checks: valid<body>, viewport meta,api-basemeta (fullstack only), no absolute URLs infetch()(CDN exempted), mandatory/api/*prefix, forbidden globals, no!importanton*and noz-index > 1000; warnings for missing stableids and non-ECharts chart CDNs.evaluate_backend/verify_backend— checks for the presence ofapp/handler/SECRETS, that all routes live under/api/*(root routes are an error), presence of/api/health, an AST-based check thatSECRETS[...]isn't copied at module level, presence of core dependencies (fastapi,mangum,uvicorn) inrequirements.txt(PEP 508-aware parsing with extras/specifiers), and extraction ofDS_*env vars. The real verification installs dependencies into the scratchpad's venv, runspy_compile, and imports/introspectsbackend.pyin a subprocess with a 15s timeout.Data access (
sub_tools.py)The previous
data_refs/test-data-pickling mechanism is gone — the engine explicitly no longer fabricates test data or pre-pickles variables. Instead, the sub-generator only has access towrite_file/read_file/finish(all sandboxed under the artifact root, rejecting../absolute-path escapes) plus the samescratchpadtool the main agent uses. The brief's free-form## Datasection is still central, but data is now obtained through thefetch_data_sampleloop, and every scratchpadexeccall is recorded and deterministically rendered intodata_notes(_render_exec_notes, capped byEXEC_CODE_MAX=2000,EXEC_OUTPUT_MAX=300,EXEC_NOTES_MAX=8000, oldest entries dropped first) — so backend/frontend generation sees the actual working data-access code rather than a free-text summary.Other new modules
anton/core/llm/serialize.py— provider-agnostic serialization of LLM messages/responses into JSON-compatible dicts (serialize_content,serialize_messages,serialize_response), used by both the existing history hook and the newdebug_trace.py.debug_trace.py— JSONL step tracing for the FSM, enabled via theANTON_DEBUG_ARTIFACT_GENERATE_TOOLenv var; a no-op (NullTrace) otherwise. Writes are best-effort and never raise.Integration
session.py— registersGENERATE_ARTIFACT_TOOLin the core tool set.tool_defs.py— defines the tool (slug+context); its description requires a 4-section markdown brief (## User request,## Conversation context,## Functional Requirements Specification,## Data); also updatescreate_artifact's description to recommendfullstack-stateless-appwhenever external DB access can be done statelessly.tool_handlers.py—handle_generate_artifact: validates input, callsgenerate_artifact.generate(...), and wraps errors/exceptions via_generation_failed(), which explicitly instructs the outer agent not to try to fix the artifact itself but to report the failure to the user instead.Tests
Adds 7 test files (
tests/test_artifact_*.py) covering: FSM graph/prompt completeness,_run_loopbehavior, state constants and models, the full orchestrator (data loop, backend/frontend retries, happy paths for html-app and fullstack), backend verification (import/health/routes/secrets/requirements), frontend verification (viewport/api-base/URL policies), and error wrapping intool_handlers.