From 798448acca63c3320cc05500a5d729238e7cd1bd Mon Sep 17 00:00:00 2001 From: ciregenz Date: Tue, 23 Jun 2026 21:11:44 -0700 Subject: [PATCH] [eric] apps: leading-_ -> p_ for function-local vars/args/nested-fns across 53 apps modules (scope-aware AST rename, module symbols untouched, p-private 0) --- backend/apps/agents/agents.py | 30 +++---- .../apps/agents/browser/browser_metrics.py | 4 +- backend/apps/agents/browser/browser_skills.py | 10 +-- backend/apps/agents/browser/browser_wait.py | 12 +-- backend/apps/agents/core/mcp_preflight.py | 2 +- .../apps/agents/manager/prompt/attachments.py | 2 +- backend/apps/agents/providers/registry.py | 10 +-- backend/apps/agents/proxy/anthropic_proxy.py | 24 +++--- backend/apps/dashboards/dashboards.py | 2 +- backend/apps/mcp_registry/mcp_registry.py | 4 +- backend/apps/modes/modes.py | 6 +- backend/apps/nine_router/oauth.py | 8 +- backend/apps/nine_router/process.py | 80 +++++++++---------- backend/apps/outputs/html_inject.py | 4 +- backend/apps/outputs/outputs.py | 10 +-- backend/apps/outputs/publish_build.py | 4 +- backend/apps/outputs/publish_scan.py | 6 +- backend/apps/outputs/runtime.py | 10 +-- .../apps/outputs/view_builder_templates.py | 4 +- backend/apps/service/client.py | 4 +- backend/apps/service/service.py | 4 +- backend/apps/service/version.py | 10 +-- backend/apps/settings/settings.py | 20 ++--- backend/apps/skill_registry/skill_registry.py | 6 +- backend/apps/subscription/free_trial.py | 4 +- backend/apps/swarm/closure.py | 4 +- backend/apps/swarm/entities/dashboards.py | 2 +- backend/apps/swarm/entities/skills.py | 2 +- backend/apps/swarm/redact.py | 6 +- backend/apps/swarm/ziputil.py | 2 +- backend/apps/tools_lib/mcp_config.py | 58 +++++++------- backend/apps/tools_lib/mcp_discovery.py | 16 ++-- backend/apps/tools_lib/oauth_tokens.py | 6 +- backend/apps/tools_lib/tools_lib.py | 8 +- 34 files changed, 192 insertions(+), 192 deletions(-) diff --git a/backend/apps/agents/agents.py b/backend/apps/agents/agents.py index 02d144d9..cf07ba9c 100644 --- a/backend/apps/agents/agents.py +++ b/backend/apps/agents/agents.py @@ -78,7 +78,7 @@ async def send_message(session_id: str, body: dict): from backend.apps.agents.core.mcp_preflight import run_preflight from backend.apps.agents.core.ws_manager import ws_manager as _ws - async def _emit_preflight(): + async def p_emit_preflight(): try: result = await run_preflight(prompt, task_id=session_id) if result.get("suggestions") or result.get("is_vague"): @@ -91,7 +91,7 @@ async def send_message(session_id: str, body: dict): pass import asyncio as _asyncio - _asyncio.create_task(_emit_preflight()) + _asyncio.create_task(p_emit_preflight()) except Exception: pass @@ -568,17 +568,17 @@ async def list_models(): conns = await _9r_providers() raw_providers = {c.get("provider", "") for c in conns if c.get("isActive") or c.get("testStatus") == "active"} # 9Router uses "claude"; our models use api="anthropic". Map across. - _9R_TO_API = { + p_9R_TO_API = { "claude": "anthropic", "codex": "codex", "gemini-cli": "gemini-cli", "antigravity": "gemini-cli", # AG = same Gemini models, separate OAuth. } - connected = raw_providers | {_9R_TO_API.get(p, p) for p in raw_providers} + connected = raw_providers | {p_9R_TO_API.get(p, p) for p in raw_providers} except Exception as e: logger.debug(f"Failed to fetch 9Router providers: {e}") - def _serialize(models: list[dict]) -> list[dict]: + def p_serialize(models: list[dict]) -> list[dict]: # Tiers describe the model; billing_kind describes the wallet. Pricing shown only for paid. from backend.apps.agents.providers.registry import ( COST_PER_1M_TOKENS, @@ -588,8 +588,8 @@ async def list_models(): out = [] for m in models: input_cost = output_cost = 0.0 - for (_p, _v), rates in COST_PER_1M_TOKENS.items(): - if _v == m["value"]: + for (p_p, p_v), rates in COST_PER_1M_TOKENS.items(): + if p_v == m["value"]: input_cost, output_cost = rates break api = m.get("api", "") @@ -634,16 +634,16 @@ async def list_models(): # Pro mode splits into Pro proxy + Anthropic alternates; own-key collapses to one adaptive group. notes: list[dict] = [] if is_openswarm_pro: - result["OpenSwarm Pro"] = _serialize(adaptive) + result["OpenSwarm Pro"] = p_serialize(adaptive) anth_alternates: list[dict] = [] if has_claude_sub: anth_alternates += cc_variants if has_api_key: anth_alternates += api_variants if anth_alternates: - result["Anthropic"] = _serialize(anth_alternates) + result["Anthropic"] = p_serialize(anth_alternates) elif has_api_key or has_claude_sub: - rows = _serialize(adaptive) + rows = p_serialize(adaptive) # When an Anthropic key is set, these adaptive rows run on it: own-key routing prefers the # user's key over any sub (agent_manager + anthropic_proxy._pick_upstream), so it holds even # with a Claude sub connected. Label + bucket as API key (not 9router-state dependent). @@ -657,7 +657,7 @@ async def list_models(): # on our pinned 9Router) have no adaptive twin to relabel, so add them or they vanish. adaptive_ids = {m.get("model_id") for m in adaptive} api_only = [m for m in api_variants if m.get("model_id") not in adaptive_ids] - rows = _serialize(api_only) + rows + rows = p_serialize(api_only) + rows elif has_claude_sub: # Only a sub: the adaptive rows route through 9router's cc/ lane, so they're covered # by the subscription, not pay-per-use. @@ -666,12 +666,12 @@ async def list_models(): # Sub-only models with no adaptive twin (Fable 5) won't ride the relabeled rows, so add their cc/ entry. adaptive_ids = {m.get("model_id") for m in adaptive} cc_only = [m for m in cc_variants if m.get("model_id") not in adaptive_ids] - rows = _serialize(cc_only) + rows + rows = p_serialize(cc_only) + rows # With BOTH a key and a sub the adaptive rows above run on the key, so also surface the # subscription (cc) variants; they route via 9router's cc/ lane and stay selectable, the # way OpenAI/Gemini show both a subscription row and an API-key row. if has_api_key and has_claude_sub: - rows += _serialize(cc_variants) + rows += p_serialize(cc_variants) result["Anthropic"] = rows has_openai_key = bool(getattr(settings, "openai_api_key", None)) @@ -698,8 +698,8 @@ async def list_models(): if not nine_router_up or api not in connected: continue in_cost = out_cost = 0.0 - for (_p, _v), rates in _CPM.items(): - if _v == m["value"]: + for (p_p, p_v), rates in _CPM.items(): + if p_v == m["value"]: in_cost, out_cost = rates break billing_kind = _cbk_native( diff --git a/backend/apps/agents/browser/browser_metrics.py b/backend/apps/agents/browser/browser_metrics.py index 7c92f6ac..f94ae457 100644 --- a/backend/apps/agents/browser/browser_metrics.py +++ b/backend/apps/agents/browser/browser_metrics.py @@ -209,13 +209,13 @@ def p_maybe_self_audit() -> None: if p_task_count % P_AUDIT_EVERY_N != 0: return - def _run(): + def p_run(): try: from backend.apps.agents.browser import browser_self_audit browser_self_audit.run_and_write() except Exception: pass try: - threading.Thread(target=_run, name="browser-self-audit", daemon=True).start() + threading.Thread(target=p_run, name="browser-self-audit", daemon=True).start() except Exception: pass diff --git a/backend/apps/agents/browser/browser_skills.py b/backend/apps/agents/browser/browser_skills.py index 73268ea6..c7aff3ef 100644 --- a/backend/apps/agents/browser/browser_skills.py +++ b/backend/apps/agents/browser/browser_skills.py @@ -171,11 +171,11 @@ def template_task(task: str) -> tuple[str, list[str]]: """Replace each quoted span with a fixed token; return (templated, [values]).""" values: list[str] = [] - def _repl(m): + def p_repl(m): values.append(m.group(1)) return P_SLOT_TOKEN - return P_QUOTE_RE.sub(_repl, task or ""), values + return P_QUOTE_RE.sub(p_repl, task or ""), values def compute_sig(task: str) -> str: @@ -238,7 +238,7 @@ def distill_steps(action_log: list[dict]) -> list[dict]: steps: list[dict] = [] productive_count = 0 - def _emit_simple(tool, inp): + def p_emit_simple(tool, inp): nonlocal productive_count if tool in ("BrowserType", "type") and inp.get("selector") is not None: steps.append({"tool": "BrowserType", "params": {"selector": inp.get("selector"), "text": inp.get("text", "")}}) @@ -284,7 +284,7 @@ def distill_steps(action_log: list[dict]) -> list[dict]: steps.append({"tool": "BrowserClickByName", "params": {"role": (r or {}).get("clicked_role", ""), "name": name}}) productive_count += 1 continue - if not _emit_simple(st, sp): + if not p_emit_simple(st, sp): return [] continue if tool == "BrowserNavigate" and inp.get("url"): @@ -757,7 +757,7 @@ def render_route_hint(skill: dict, task: str, score: float) -> tuple[str, list[t _, values = template_task(task) # first_unsafe_step is the batching boundary (it stops at composer typing # too); the IRREVERSIBLE flag goes only on genuinely outward-facing clicks - unsafe_i, _why = first_unsafe_step(steps) + unsafe_i, p_why = first_unsafe_step(steps) lines = [] for i, s in enumerate(steps): mark = "" diff --git a/backend/apps/agents/browser/browser_wait.py b/backend/apps/agents/browser/browser_wait.py index 123ece2e..563e988c 100644 --- a/backend/apps/agents/browser/browser_wait.py +++ b/backend/apps/agents/browser/browser_wait.py @@ -106,12 +106,12 @@ async def smart_wait(execute_fn, browser_id, tab_id, max_ms, *, until="", last_elems = None elems_changed_at = start # DOM-settle clock: when the element count last changed - def _elapsed(): + def p_elapsed(): return (time.monotonic() - start) * 1000 - while _elapsed() < max_ms: - await asyncio.sleep(min(poll_ms, max(0, max_ms - _elapsed())) / 1000) - if _elapsed() >= max_ms: + while p_elapsed() < max_ms: + await asyncio.sleep(min(poll_ms, max(0, max_ms - p_elapsed())) / 1000) + if p_elapsed() >= max_ms: break # Bound each probe so a wedged tab can't make us inherit the 30s command # timeout. A timeout is a not-responding signal (not a verdict): count @@ -156,13 +156,13 @@ async def smart_wait(execute_fn, browser_id, tab_id, max_ms, *, until="", break continue if decide_stop(probe.get("ready"), probe.get("quiet", 0), dom_stable_ms, - probe.get("found"), _elapsed(), + probe.get("found"), p_elapsed(), floor_ms=floor_ms, settle_window_ms=quiet_window_ms): settled = True found = bool(probe.get("found")) break - waited = round(_elapsed()) + waited = round(p_elapsed()) if found: state = "found target" elif settled: diff --git a/backend/apps/agents/core/mcp_preflight.py b/backend/apps/agents/core/mcp_preflight.py index 11d04b0e..c2845ffa 100644 --- a/backend/apps/agents/core/mcp_preflight.py +++ b/backend/apps/agents/core/mcp_preflight.py @@ -181,7 +181,7 @@ def p_decorate(llm_suggestion: dict, available: list[CuratedEntry]) -> dict | No async def p_call_classifier(settings, prompt: str, available: list[CuratedEntry], task_id: str | None = None) -> dict: """One aux-model call, returns validated JSON {is_vague, suggestions}.""" - aux_model, _base = await resolve_aux_model(settings, preferred_tier="haiku") + aux_model, p_base = await resolve_aux_model(settings, preferred_tier="haiku") client = get_anthropic_client_for_model(settings, aux_model) catalog_lines = "\n".join( diff --git a/backend/apps/agents/manager/prompt/attachments.py b/backend/apps/agents/manager/prompt/attachments.py index 56a03967..fae15f63 100644 --- a/backend/apps/agents/manager/prompt/attachments.py +++ b/backend/apps/agents/manager/prompt/attachments.py @@ -307,6 +307,6 @@ def resolve_attachments(context_paths: Optional[List], api_type: str, model: str # blocks emitted, so behavior is the safe text-only old path). @typechecked def resolve_context_paths(context_paths: Optional[List]) -> str: - text, _native, refusals = resolve_attachments(context_paths, api_type="anthropic", model="") + text, p_native, refusals = resolve_attachments(context_paths, api_type="anthropic", model="") refusal_text = "\n\n".join(refusals) return "\n\n".join(p for p in (text, refusal_text) if p) diff --git a/backend/apps/agents/providers/registry.py b/backend/apps/agents/providers/registry.py index 45730d4e..1697bb61 100644 --- a/backend/apps/agents/providers/registry.py +++ b/backend/apps/agents/providers/registry.py @@ -169,7 +169,7 @@ def find_custom_provider_for_value(settings, value: str): if not isinstance(value, str) or not value.startswith(_CUSTOM_VALUE_PREFIX): return None rest = value[len(_CUSTOM_VALUE_PREFIX):] - slug, _sep, _bare = rest.partition("/") + slug, p_sep, p_bare = rest.partition("/") if not slug: return None for cp in getattr(settings, "custom_providers", None) or []: @@ -204,7 +204,7 @@ def find_builtin_model(short_name: str) -> dict | None: } if isinstance(short_name, str) and short_name.startswith(_CUSTOM_VALUE_PREFIX): rest = short_name[len(_CUSTOM_VALUE_PREFIX):] - slug, _sep, bare_model = rest.partition("/") + slug, p_sep, bare_model = rest.partition("/") if slug and bare_model: # Routing string `cp-/` matches the prefix we use # when sync_custom_providers registers the provider node. @@ -280,7 +280,7 @@ def resolve_model_id_for_sdk(short_name: str, settings: AppSettings) -> str: # connected AG sub is preferred over the AI Studio key, which otherwise # silently shadowed it. The map is AG's allowlist; pro variants 404/400 on # AG and are deliberately absent, so they fall through to the key. - _ANTIGRAVITY_MAP = { + P_ANTIGRAVITY_MAP = { # gemini-3-pro-preview disabled: AG returns 404 even with active conn. # gemini-3.1-pro-preview disabled: AG's `gemini-3.1-pro-high` variant # 400s every request with "invalid argument" (the `-high` thinking- @@ -293,7 +293,7 @@ def resolve_model_id_for_sdk(short_name: str, settings: AppSettings) -> str: rid = entry.get("router_model_id", "") if isinstance(rid, str) and rid.startswith("gc/"): suffix = rid[len("gc/"):] - ag_suffix = _ANTIGRAVITY_MAP.get(suffix) + ag_suffix = P_ANTIGRAVITY_MAP.get(suffix) if ag_suffix and p_antigravity_connected(): return "ag/" + ag_suffix if getattr(settings, "google_api_key", None): @@ -392,7 +392,7 @@ def get_context_window(provider: str, model: str, settings: AppSettings | None = bare_model = model if isinstance(model, str) and model.startswith(_CUSTOM_VALUE_PREFIX): rest = model[len(_CUSTOM_VALUE_PREFIX):] - _slug, _sep, bare_model = rest.partition("/") + p_slug, p_sep, bare_model = rest.partition("/") for cp in getattr(settings, "custom_providers", []): for m in (getattr(cp, "models", None) or []): if m.get("value") == bare_model or m.get("id") == bare_model: diff --git a/backend/apps/agents/proxy/anthropic_proxy.py b/backend/apps/agents/proxy/anthropic_proxy.py index 7903acd5..24df6255 100644 --- a/backend/apps/agents/proxy/anthropic_proxy.py +++ b/backend/apps/agents/proxy/anthropic_proxy.py @@ -184,9 +184,9 @@ def scrub_request_for_openai_gpt5(body: bytes) -> bytes: if "temperature" in parsed and parsed["temperature"] != 1: parsed.pop("temperature", None) mutated = True - for _k in ("top_p", "top_k", "frequency_penalty", "presence_penalty", + for p_k in ("top_p", "top_k", "frequency_penalty", "presence_penalty", "logprobs", "top_logprobs", "logit_bias"): - if parsed.pop(_k, None) is not None: + if parsed.pop(p_k, None) is not None: mutated = True try: before = json.dumps(parsed.get("messages"), sort_keys=True) if "messages" in parsed else "" @@ -426,22 +426,22 @@ async def proxy(rest: str, request: Request): forward_to_openrouter as _forward_or, ) from backend.apps.settings.settings import load_settings as _load - _s = _load() + p_s = _load() if p_is_openai_max_completion_tokens_model(model): - _oak = (getattr(_s, "openai_api_key", "") or "").strip() - if _should_bypass_oai(parsed_for_bypass, _oak): + p_oak = (getattr(p_s, "openai_api_key", "") or "").strip() + if _should_bypass_oai(parsed_for_bypass, p_oak): status, body_stream, hdrs = await _forward_oai( - parsed_for_bypass, _oak, + parsed_for_bypass, p_oak, ) return StreamingResponse( body_stream, status_code=status, headers=hdrs, media_type=hdrs.get("content-type", "text/event-stream"), ) if p_is_openrouter_model(model): - _ork = (getattr(_s, "openrouter_api_key", "") or "").strip() - if _should_bypass_or(parsed_for_bypass, _ork): + p_ork = (getattr(p_s, "openrouter_api_key", "") or "").strip() + if _should_bypass_or(parsed_for_bypass, p_ork): status, body_stream, hdrs = await _forward_or( - parsed_for_bypass, _ork, + parsed_for_bypass, p_ork, ) return StreamingResponse( body_stream, status_code=status, headers=hdrs, @@ -479,11 +479,11 @@ async def proxy(rest: str, request: Request): # the retry, which hangs the whole turn for the full read window. Bound Gemini # so a stalled first response fails fast (~2 min) instead of stalling ~10 min; # other providers keep the generous window for long reasoning turns. - _read_timeout = 120.0 if p_is_gemini_model(model) else 600.0 + p_read_timeout = 120.0 if p_is_gemini_model(model) else 600.0 try: if wants_stream: - client = httpx.AsyncClient(timeout=httpx.Timeout(_read_timeout, connect=30.0)) + client = httpx.AsyncClient(timeout=httpx.Timeout(p_read_timeout, connect=30.0)) req = client.build_request( request.method, url, content=body, headers=forward_headers, params=dict(request.query_params), @@ -507,7 +507,7 @@ async def proxy(rest: str, request: Request): media_type=upstream.headers.get("content-type", "text/event-stream"), ) else: - async with httpx.AsyncClient(timeout=httpx.Timeout(_read_timeout, connect=30.0)) as client: + async with httpx.AsyncClient(timeout=httpx.Timeout(p_read_timeout, connect=30.0)) as client: r = await client.request( request.method, url, content=body, headers=forward_headers, params=dict(request.query_params), diff --git a/backend/apps/dashboards/dashboards.py b/backend/apps/dashboards/dashboards.py index bae156c3..dace1da5 100644 --- a/backend/apps/dashboards/dashboards.py +++ b/backend/apps/dashboards/dashboards.py @@ -323,7 +323,7 @@ async def generate_name(dashboard_id: str): from backend.apps.settings.credentials import get_anthropic_client_for_model from backend.apps.agents.providers.registry import resolve_aux_model global_settings = load_settings() - aux_model, _aux_base = await resolve_aux_model(global_settings, preferred_tier="haiku") + aux_model, p_aux_base = await resolve_aux_model(global_settings, preferred_tier="haiku") client = get_anthropic_client_for_model(global_settings, aux_model) # Mirrors generate_title's hardening: the tasks are inert text to LABEL, never answer, diff --git a/backend/apps/mcp_registry/mcp_registry.py b/backend/apps/mcp_registry/mcp_registry.py index f3b35a5c..96fed0f8 100644 --- a/backend/apps/mcp_registry/mcp_registry.py +++ b/backend/apps/mcp_registry/mcp_registry.py @@ -253,7 +253,7 @@ async def p_fetch_github_stars(servers: dict[str, dict]): rate_limited = False fetched = 0 - async def _fetch_one(client: httpx.AsyncClient, repo: str): + async def p_fetch_one(client: httpx.AsyncClient, repo: str): nonlocal rate_limited, fetched if rate_limited: return @@ -277,7 +277,7 @@ async def p_fetch_github_stars(servers: dict[str, dict]): logger.debug(f"GitHub stars fetch failed for {repo}: {exc}") async with httpx.AsyncClient(timeout=15.0) as client: - await asyncio.gather(*[_fetch_one(client, r) for r in to_fetch]) + await asyncio.gather(*[p_fetch_one(client, r) for r in to_fetch]) logger.info(f"GitHub stars: fetched {fetched} new, {len(p_stars_cache)} total cached") p_apply_stars(servers) diff --git a/backend/apps/modes/modes.py b/backend/apps/modes/modes.py index 491b8cb5..5a3d6e4a 100644 --- a/backend/apps/modes/modes.py +++ b/backend/apps/modes/modes.py @@ -20,9 +20,9 @@ async def modes_lifespan(): if os.path.exists(chat_path): try: import json as _json - with open(chat_path) as _f: - _data = _json.load(_f) - if _data.get("is_builtin") is True and _data.get("id") == "chat": + with open(chat_path) as p_f: + p_data = _json.load(p_f) + if p_data.get("is_builtin") is True and p_data.get("id") == "chat": os.remove(chat_path) logger.info("Removed deprecated built-in chat.json (merged into ask)") except Exception: diff --git a/backend/apps/nine_router/oauth.py b/backend/apps/nine_router/oauth.py index 291ef033..7a9f914e 100644 --- a/backend/apps/nine_router/oauth.py +++ b/backend/apps/nine_router/oauth.py @@ -80,7 +80,7 @@ async def p_start_codex_callback_listener(timeout: float = 300.0) -> asyncio.bas callback_served = asyncio.Event() - async def _handle(reader: asyncio.StreamReader, writer: asyncio.StreamWriter): + async def p_handle(reader: asyncio.StreamReader, writer: asyncio.StreamWriter): try: # Read the request line ("GET /auth/callback?... HTTP/1.1\r\n") raw_request_line = await asyncio.wait_for(reader.readline(), timeout=5.0) @@ -165,7 +165,7 @@ async def p_start_codex_callback_listener(timeout: float = 300.0) -> asyncio.bas pass try: - server = await asyncio.start_server(_handle, "127.0.0.1", P_CODEX_CALLBACK_PORT) + server = await asyncio.start_server(p_handle, "127.0.0.1", P_CODEX_CALLBACK_PORT) except OSError as e: # Port already in use; probably another Codex connect attempt still # running, or an actual Codex CLI process holding 1455. Log and bail. @@ -175,7 +175,7 @@ async def p_start_codex_callback_listener(timeout: float = 300.0) -> asyncio.bas ) return None - async def _lifecycle(): + async def p_lifecycle(): try: await asyncio.wait_for(callback_served.wait(), timeout=timeout) # Give the served HTML a moment to run its JS (postMessage + @@ -193,7 +193,7 @@ async def p_start_codex_callback_listener(timeout: float = 300.0) -> asyncio.bas except Exception: pass - asyncio.create_task(_lifecycle()) + asyncio.create_task(p_lifecycle()) logger.info(f"Started Codex callback listener on http://localhost:{P_CODEX_CALLBACK_PORT}{P_CODEX_CALLBACK_PATH}") return server diff --git a/backend/apps/nine_router/process.py b/backend/apps/nine_router/process.py index 453eb052..75fef294 100644 --- a/backend/apps/nine_router/process.py +++ b/backend/apps/nine_router/process.py @@ -213,20 +213,20 @@ def cli_auth_headers() -> dict[str, str]: def p_find_9router_dir() -> str | None: """Locate the bundled 9Router directory (works in both dev and packaged mode).""" - _is_packaged = os.environ.get("OPENSWARM_PACKAGED") == "1" + p_is_packaged = os.environ.get("OPENSWARM_PACKAGED") == "1" - if _is_packaged: + if p_is_packaged: import sys - _resources = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) - _candidate = os.path.join(_resources, "router") - if os.path.isdir(_candidate): - return _candidate + p_resources = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) + p_candidate = os.path.join(p_resources, "router") + if os.path.isdir(p_candidate): + return p_candidate else: - _backend_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) - _project_root = os.path.dirname(_backend_dir) - _candidate = os.path.join(_project_root, "router") - if os.path.isdir(_candidate): - return _candidate + p_backend_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + p_project_root = os.path.dirname(p_backend_dir) + p_candidate = os.path.join(p_project_root, "router") + if os.path.isdir(p_candidate): + return p_candidate return None @@ -396,12 +396,12 @@ async def ensure_running(): async def p_ensure_running_impl(): """Start 9Router if not already running.""" global p_process - _is_packaged = os.environ.get("OPENSWARM_PACKAGED") == "1" + p_is_packaged = os.environ.get("OPENSWARM_PACKAGED") == "1" if is_running(): # In dev mode, kill stale standalone servers (from previous builds) # so we can start `next dev` which always uses latest source code - if not _is_packaged: + if not p_is_packaged: import subprocess as _sp try: result = _sp.run( @@ -422,20 +422,20 @@ async def p_ensure_running_impl(): logger.info("9Router already running on port %d", NINE_ROUTER_PORT) return p_rotate_request_log() - _9router_dir = p_find_9router_dir() - _patch = p_gpt5_patch_path() + p_9router_dir = p_find_9router_dir() + p_patch = p_gpt5_patch_path() - if _is_packaged: + if p_is_packaged: # Packaged: run the pre-built standalone server staged at # /router/server.js by fetch-router at build time. We do NOT # fall back to the dev npm path here, a user machine has no npm, so that # only ever fails silently; every miss is reported instead. - if not _9router_dir: + if not p_9router_dir: p_report_start_failure("router_not_bundled") return - standalone_server = os.path.join(_9router_dir, "server.js") + standalone_server = os.path.join(p_9router_dir, "server.js") if not os.path.exists(standalone_server): - standalone_server = os.path.join(_9router_dir, ".next", "standalone", "server.js") + standalone_server = os.path.join(p_9router_dir, ".next", "standalone", "server.js") if not os.path.exists(standalone_server): p_report_start_failure("server_missing", router_dir_found=True) return @@ -444,7 +444,7 @@ async def p_ensure_running_impl(): p_report_start_failure("node_not_found", router_dir_found=True, server_found=True) return logger.info("Starting 9Router (production) on port %d...", NINE_ROUTER_PORT) - cmd = [node, f"--max-old-space-size={P_NODE_HEAP_MB}"] + (["--require", _patch] if _patch else []) + [standalone_server] + cmd = [node, f"--max-old-space-size={P_NODE_HEAP_MB}"] + (["--require", p_patch] if p_patch else []) + [standalone_server] cwd = os.path.dirname(standalone_server) env = {**os.environ, "PORT": str(NINE_ROUTER_PORT), "NODE_ENV": "production"} if node == os.environ.get("OPENSWARM_ELECTRON_PATH"): @@ -464,7 +464,7 @@ async def p_ensure_running_impl(): "Starting 9Router (dev cache, 9router@%s) on port %d...", NINE_ROUTER_NPM_VERSION, NINE_ROUTER_PORT, ) - cmd = [node, f"--max-old-space-size={P_NODE_HEAP_MB}"] + (["--require", _patch] if _patch else []) + [cached_server] + cmd = [node, f"--max-old-space-size={P_NODE_HEAP_MB}"] + (["--require", p_patch] if p_patch else []) + [cached_server] cwd = os.path.dirname(cached_server) env = {**os.environ, "PORT": str(NINE_ROUTER_PORT), "NODE_ENV": "production"} @@ -473,30 +473,30 @@ async def p_ensure_running_impl(): # whole reason #90 was un-diagnosable). Packaged prod (NODE_ENV=production # standalone) is quiet, so one fixed temp file, truncated each start attempt, # won't grow; dev keeps its chatty-Next.js DEVNULL unless debug is set. - _cap_path = os.path.join(tempfile.gettempdir(), "openswarm-9router-start.log") - _cap_file = None - if _is_packaged: + p_cap_path = os.path.join(tempfile.gettempdir(), "openswarm-9router-start.log") + p_cap_file = None + if p_is_packaged: try: - _cap_file = open(_cap_path, "wb") - _stdout, _stderr = _cap_file, subprocess.STDOUT + p_cap_file = open(p_cap_path, "wb") + p_stdout, p_stderr = p_cap_file, subprocess.STDOUT except OSError: - _stdout, _stderr = subprocess.DEVNULL, subprocess.DEVNULL + p_stdout, p_stderr = subprocess.DEVNULL, subprocess.DEVNULL elif os.environ.get("OPENSWARM_DEBUG_9ROUTER"): - _log_path = os.path.join( + p_log_path = os.path.join( os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "data", "9router.log", ) - os.makedirs(os.path.dirname(_log_path), exist_ok=True) - _stdout, _stderr = open(_log_path, "a", buffering=1), subprocess.STDOUT - logger.info(f"9Router debug logging enabled → {_log_path}") + os.makedirs(os.path.dirname(p_log_path), exist_ok=True) + p_stdout, p_stderr = open(p_log_path, "a", buffering=1), subprocess.STDOUT + logger.info(f"9Router debug logging enabled → {p_log_path}") else: - _stdout, _stderr = subprocess.DEVNULL, subprocess.DEVNULL + p_stdout, p_stderr = subprocess.DEVNULL, subprocess.DEVNULL try: - p_process = subprocess.Popen(cmd, cwd=cwd, stdout=_stdout, stderr=_stderr, env=env) - if _cap_file is not None: - _cap_file.close() # the child holds its own fd; the parent copy isn't needed - timeout = 20 if _is_packaged else 30 + p_process = subprocess.Popen(cmd, cwd=cwd, stdout=p_stdout, stderr=p_stderr, env=env) + if p_cap_file is not None: + p_cap_file.close() # the child holds its own fd; the parent copy isn't needed + timeout = 20 if p_is_packaged else 30 for _ in range(timeout * 2): await asyncio.sleep(0.5) if is_running(): @@ -506,19 +506,19 @@ async def p_ensure_running_impl(): # exit code (non-None = it crashed; None = wedged or just slow). p_report_start_failure( "not_ready_in_time", - detail=p_read_capture_tail(_cap_path) if _is_packaged else "", + detail=p_read_capture_tail(p_cap_path) if p_is_packaged else "", returncode=p_process.poll(), timeout_s=timeout, ) except Exception as e: - if _cap_file is not None and not _cap_file.closed: + if p_cap_file is not None and not p_cap_file.closed: try: - _cap_file.close() + p_cap_file.close() except OSError: pass p_report_start_failure( "spawn_exception", - detail=f"{e}\n{p_read_capture_tail(_cap_path) if _is_packaged else ''}", + detail=f"{e}\n{p_read_capture_tail(p_cap_path) if p_is_packaged else ''}", ) diff --git a/backend/apps/outputs/html_inject.py b/backend/apps/outputs/html_inject.py index 80b5a4b2..4397893b 100644 --- a/backend/apps/outputs/html_inject.py +++ b/backend/apps/outputs/html_inject.py @@ -147,7 +147,7 @@ def inject_token_into_relative_urls(html: str, token: str) -> str: if not token: return html - def _patch(match: re.Match) -> str: + def p_patch(match: re.Match) -> str: attr, quote, url = match.group(1), match.group(2), match.group(3) lowered = url.lower().lstrip() if lowered.startswith(P_ABSOLUTE_URL_PREFIXES): @@ -164,7 +164,7 @@ def inject_token_into_relative_urls(html: str, token: str) -> str: sep = "&" if "?" in base else "?" return f'{attr}={quote}{base}{sep}token={token}{frag}{quote}' - return P_HREF_SRC_ATTR_RE.sub(_patch, html) + return P_HREF_SRC_ATTR_RE.sub(p_patch, html) def decode_data_param(d: str) -> tuple[str, str]: diff --git a/backend/apps/outputs/outputs.py b/backend/apps/outputs/outputs.py index 5e8178e7..9f25ec6f 100644 --- a/backend/apps/outputs/outputs.py +++ b/backend/apps/outputs/outputs.py @@ -78,7 +78,7 @@ outputs = SubApp("outputs", outputs_lifespan) # --------------------------------------------------------------------------- @outputs.router.get("/workspace/{workspace_id}/serve/{filepath:path}") -async def serve_workspace_file(workspace_id: str, filepath: str, _d: str = ""): +async def serve_workspace_file(workspace_id: str, filepath: str, p_d: str = ""): """Serve a file from a workspace folder. For index.html, inject OUTPUT data.""" folder = os.path.join(WORKSPACE_DIR, workspace_id) full_path = os.path.normpath(os.path.join(folder, filepath)) @@ -91,7 +91,7 @@ async def serve_workspace_file(workspace_id: str, filepath: str, _d: str = ""): content = f.read() if filepath == "index.html": - input_json, result_json = decode_data_param(_d) if _d else ("{}", "null") + input_json, result_json = decode_data_param(p_d) if p_d else ("{}", "null") backend_url_json = backend_url_for_workspace(workspace_id) content = inject_data_into_html(content, input_json, result_json, backend_url_json, with_runtime=True) # Iframe sub-resource fetches (,