mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-05 09:17:42 +02:00
[eric] app builder: fix windows-built apps failing by always creating the workspace .env (the windows build dropped the .env.example it seeds from) and writing app files as utf-8 (windows cp1252 choked on arrows and chess pieces); stays on 1.1.69 to rebuild only the windows installer
This commit is contained in:
@@ -230,7 +230,7 @@ def ensure_webapp_workspace_seeded_and_registered(
|
||||
from backend.apps.outputs.runtime import _find_free_port
|
||||
frontend_port = _find_free_port()
|
||||
seed_webapp_template_workspace(folder, frontend_port)
|
||||
with open(os.path.join(folder, "SKILL.md"), "w") as f:
|
||||
with open(os.path.join(folder, "SKILL.md"), "w", encoding="utf-8") as f:
|
||||
f.write(load_app_builder_skill())
|
||||
existing = [o for o in _load_all() if o.workspace_id == workspace_id]
|
||||
if existing:
|
||||
@@ -311,11 +311,11 @@ async def seed_workspace(body: WorkspaceSeedRequest):
|
||||
# SKILL.md still goes in workspace root; agent reads it for
|
||||
# context. Live content (user-editable via Skills page) is
|
||||
# injected into the system prompt regardless.
|
||||
with open(os.path.join(folder, "SKILL.md"), "w") as f:
|
||||
with open(os.path.join(folder, "SKILL.md"), "w", encoding="utf-8") as f:
|
||||
f.write(load_app_builder_skill())
|
||||
meta = body.meta or {}
|
||||
if body.meta and not already_seeded:
|
||||
with open(os.path.join(folder, "meta.json"), "w") as f:
|
||||
with open(os.path.join(folder, "meta.json"), "w", encoding="utf-8") as f:
|
||||
json.dump(body.meta, f, indent=2)
|
||||
# Create (or look up) the Output record so the app appears in
|
||||
# the Apps sidebar the moment the user kicks off generation.
|
||||
@@ -360,12 +360,12 @@ async def seed_workspace(body: WorkspaceSeedRequest):
|
||||
if not full_path.startswith(os.path.normpath(folder)):
|
||||
continue
|
||||
os.makedirs(os.path.dirname(full_path), exist_ok=True)
|
||||
with open(full_path, "w") as f:
|
||||
with open(full_path, "w", encoding="utf-8") as f:
|
||||
f.write(content)
|
||||
else:
|
||||
for rel_path, content in VIEW_TEMPLATE_FILES.items():
|
||||
full_path = os.path.join(folder, rel_path)
|
||||
with open(full_path, "w") as f:
|
||||
with open(full_path, "w", encoding="utf-8") as f:
|
||||
f.write(content)
|
||||
|
||||
# Seed the workspace's SKILL.md with the LIVE skill content so an
|
||||
@@ -374,11 +374,11 @@ async def seed_workspace(body: WorkspaceSeedRequest):
|
||||
# already-seeded workspaces (the system-prompt injection in
|
||||
# agent_manager reads live, so the agent always has the latest
|
||||
# rules regardless of this on-disk copy).
|
||||
with open(os.path.join(folder, "SKILL.md"), "w") as f:
|
||||
with open(os.path.join(folder, "SKILL.md"), "w", encoding="utf-8") as f:
|
||||
f.write(load_app_builder_skill())
|
||||
|
||||
if body.meta:
|
||||
with open(os.path.join(folder, "meta.json"), "w") as f:
|
||||
with open(os.path.join(folder, "meta.json"), "w", encoding="utf-8") as f:
|
||||
json.dump(body.meta, f, indent=2)
|
||||
|
||||
return {"path": os.path.abspath(folder), "template_mode": "flat"}
|
||||
@@ -494,7 +494,7 @@ async def write_workspace_file(workspace_id: str, filepath: str, body: dict):
|
||||
if full_path != folder_norm and not full_path.startswith(folder_norm + os.sep):
|
||||
raise HTTPException(status_code=403, detail="Path traversal not allowed")
|
||||
os.makedirs(os.path.dirname(full_path), exist_ok=True)
|
||||
with open(full_path, "w") as f:
|
||||
with open(full_path, "w", encoding="utf-8") as f:
|
||||
f.write(body.get("content", ""))
|
||||
return {"ok": True}
|
||||
|
||||
|
||||
@@ -467,7 +467,7 @@ def _ensure_warm_python_venv() -> str | None:
|
||||
logger.warning("warm-venv pip install failed: %s", r.stderr[-1500:])
|
||||
return None
|
||||
|
||||
with open(sentinel, "w") as fh:
|
||||
with open(sentinel, "w", encoding="utf-8") as fh:
|
||||
fh.write("ok\n")
|
||||
logger.info("webapp-template: warm backend venv ready at %s", venv_dir)
|
||||
return venv_dir
|
||||
@@ -568,6 +568,16 @@ def seed_webapp_template_workspace(workspace_dir: str, frontend_port: int) -> No
|
||||
src_example = os.path.join(WEBAPP_TEMPLATE_DIR, ".env.example")
|
||||
if os.path.exists(src_example):
|
||||
shutil.copyfile(src_example, env_path)
|
||||
else:
|
||||
# .env.example can be absent from a packaged build whose copy step
|
||||
# stripped dotfiles (the Windows build's recursive '.env.*' exclude did
|
||||
# exactly this). Write the default directly so the workspace always has
|
||||
# a .env with BACKEND_PORT=NONE; without it run.sh sees no BACKEND_PORT,
|
||||
# takes the backend branch, and dies on a backend that isn't there,
|
||||
# leaving the app stuck on the splash. Mac was unaffected because its
|
||||
# build anchors the exclude and ships .env.example.
|
||||
with open(env_path, "w", encoding="utf-8") as f:
|
||||
f.write("BACKEND_PORT=NONE\nFRONTEND_PORT=4949\n")
|
||||
|
||||
_patch_env_port(env_path, "FRONTEND_PORT", str(frontend_port))
|
||||
_patch_env_port(env_example_path, "FRONTEND_PORT", str(frontend_port))
|
||||
|
||||
@@ -39,8 +39,14 @@ cleanup() {
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
if [[ "${BACKEND_PORT}" == "NONE" ]]; then
|
||||
echo "BACKEND_PORT=NONE — running frontend only (no backend)."
|
||||
if [[ "${BACKEND_PORT}" == "NONE" || -z "${BACKEND_PORT}" || ! -f "$ROOT_DIR/backend/run.sh" ]]; then
|
||||
# Frontend-only is the safe default: BACKEND_PORT=NONE (frontend-only app),
|
||||
# OR unset/empty (e.g. .env missing — never start a backend that isn't
|
||||
# configured), OR there is genuinely no backend/run.sh to run. Without the
|
||||
# last two guards an unset BACKEND_PORT fell through to the backend branch
|
||||
# and `bash backend/run.sh` died with "No such file or directory", tearing
|
||||
# the whole app down before the frontend could show.
|
||||
echo "Running frontend only (no backend configured)."
|
||||
echo ""
|
||||
|
||||
bash "$ROOT_DIR/frontend/run.sh" 2>&1 | awk '{printf "\033[32m[frontend]\033[0m %s\n", $0; fflush()}' &
|
||||
|
||||
Reference in New Issue
Block a user