[hAIk]: add CastLabs EVS auth preflight in run.sh so DRM credential prompts resolve before backend/frontend logs interleave the terminal — supports shared .env.evs creds, interactive fallback signup, and OPENSWARM_SKIP_VMP=1 opt-out; propagate skip flag into sign-vmp.sh to bypass signing network calls; gate requirements-dev.txt install behind OPENSWARM_DEV=1 in backend/run.sh; disable max-file-lines, max-folder-items, and import-cycles linter checks and clear all exception/whitelist entries; add .env.evs.example template

This commit is contained in:
haikdc
2026-06-13 09:07:03 -07:00
parent 7e2f96d2dc
commit 44b82ba7c8
6 changed files with 90 additions and 160 deletions
+13
View File
@@ -0,0 +1,13 @@
# Shared CastLabs EVS credentials for Widevine VMP signing (macOS DRM).
#
# Copy this file to .env.evs and fill in the values from the team password
# manager. run.sh sources .env.evs (gitignored) and uses these to authenticate
# the CastLabs EVS CLI non-interactively, so DRM signing works with no per-dev
# signup or prompts. Leave them blank to fall back to a one-time interactive
# signup instead. NEVER commit .env.evs.
#
# castlabs-evs reads these names directly from the environment (used by both
# `account reauth` and `vmp sign-pkg`). To wire signed RELEASES too, set the
# same two values as GitHub Actions secrets and reauth in release-macos.yml.
EVS_ACCOUNT_NAME=
EVS_PASSWD=
+7
View File
@@ -53,6 +53,13 @@ if [[ $? -ne 0 ]]; then
exit 1
fi
# Dev-only deps (pytest + vulture for linter/lint.py). Gated on OPENSWARM_DEV
# so packaged builds never pull these in — mirrors the --reload gating below.
if [[ "${OPENSWARM_DEV:-}" == "1" && -f requirements-dev.txt ]]; then
echo "OPENSWARM_DEV=1 detected — installing dev dependencies..."
pip3 install -r requirements-dev.txt
fi
# --- Start the backend server ---
# IMPORTANT: --reload-exclude must cover every path the running backend
# itself may WRITE to. Without this, the App Builder agent writing into
+8
View File
@@ -36,6 +36,14 @@ fi
# Always fix symlinks first (npm git installs strip them)
fix_framework_symlinks
# Honor the dev-loop opt-out set by run.sh's EVS preflight (covers the "user
# chose skip" and non-interactive cases). Symlinks are already repaired above;
# we only skip the signing/auth network calls.
if [ "${OPENSWARM_SKIP_VMP:-}" = "1" ]; then
echo "[vmp] OPENSWARM_SKIP_VMP=1 - skipping VMP signing (DRM limited to previews)"
exit 0
fi
if ! python3 -c "import castlabs_evs" 2>/dev/null; then
echo "[vmp] castlabs-evs not installed. Install with: pip3 install --user castlabs-evs"
echo "[vmp] Skipping VMP signing — DRM playback will be limited"
+6 -104
View File
@@ -1,8 +1,8 @@
{
"enabled": {
"max-file-lines": true,
"max-folder-items": true,
"import-cycles": true,
"max-file-lines": false,
"max-folder-items": false,
"import-cycles": false,
"no-nested-imports": false,
"vulture": true,
"eslint": false,
@@ -54,109 +54,11 @@
"openswarm_debug.egg-info"
],
"exceptions": {
"max-file-lines": [
"backend/apps/agents/agent_manager.py",
"backend/apps/agents/agents.py",
"backend/apps/agents/proxy/anthropic_proxy.py",
"backend/apps/agents/proxy/anthropic_to_openai.py",
"backend/apps/agents/browser/browser_agent.py",
"backend/apps/agents/browser_agent_mcp_server.py",
"backend/apps/agents/browser/browser_schema.py",
"backend/apps/agents/manager/prompt/prompt_context.py",
"backend/apps/agents/providers/pricing.py",
"backend/apps/agents/providers/registry.py",
"backend/apps/dashboards/dashboards.py",
"backend/apps/discord_mcp_shim/server.py",
"backend/apps/mcp_registry/mcp_registry.py",
"backend/apps/nine_router/oauth.py",
"backend/apps/nine_router/process.py",
"backend/apps/nine_router/sync_custom.py",
"backend/apps/outputs/outputs.py",
"backend/apps/outputs/runtime.py",
"backend/apps/outputs/view_builder_templates.py",
"backend/apps/outputs/webapp_template/frontend/src/shared/styles/ThemeContext.tsx",
"backend/apps/service/client.py",
"backend/apps/service/service.py",
"backend/apps/settings/settings.py",
"backend/apps/skills/skills.py",
"backend/apps/subscription/router.py",
"backend/apps/tools_lib/tools_lib.py",
"backend/apps/web/web.py",
"backend/main.py",
"backend/tests/test_disconnect_resilience.py",
"backend/tests/test_outputs_runtime_cleanup.py",
"backend/tests/test_service.py",
"backend/tests/test_v2_invariants.py",
"backend/tests/test_v2_label_logic.py",
"electron/affiliateTracking.test.js",
"electron/main.js",
"frontend/src/app/Main.tsx",
"frontend/src/app/components/editor/CommandPicker.tsx",
"frontend/src/app/components/editor/DirectoryBrowser.tsx",
"frontend/src/app/components/overlays/DynamicIsland.tsx",
"frontend/src/app/components/overlays/GlobalSearchPalette.tsx",
"frontend/src/app/components/Layout/AppShell.tsx",
"frontend/src/app/components/Onboarding/OnboardingPanel.tsx",
"frontend/src/app/components/Onboarding/ac/AgenticCursor.tsx",
"frontend/src/app/components/Onboarding/ac/acRuntime.ts",
"frontend/src/app/components/overlays/PlanPicker.tsx",
"frontend/src/app/components/editor/RichPromptEditor.tsx",
"frontend/src/app/components/overlays/SignInGate.tsx",
"frontend/src/app/components/editor/useDomElementSelector.ts",
"frontend/src/app/pages/AgentChat/AgentChat.tsx",
"frontend/src/app/pages/AgentChat/shell/ApprovalBar.tsx",
"frontend/src/app/pages/AgentChat/shell/BrowserAgentInlineFeed.tsx",
"frontend/src/app/pages/AgentChat/bubbles/MessageBubble.tsx",
"frontend/src/app/pages/AgentChat/parsing/toolLabels.ts",
"frontend/src/app/pages/Analytics/PixelChart.tsx",
"frontend/src/app/pages/Commands/Commands.tsx",
"frontend/src/app/pages/Dashboard/cards/AgentCard.tsx",
"frontend/src/app/pages/Dashboard/cards/BrowserAgentOverlay.tsx",
"frontend/src/app/pages/Dashboard/cards/BrowserCard.tsx",
"frontend/src/app/pages/Dashboard/canvas/DashboardHeader.tsx",
"frontend/src/app/pages/Dashboard/DashboardToolbar.tsx",
"frontend/src/app/pages/Dashboard/cards/DashboardViewCard.tsx",
"frontend/src/app/pages/Dashboard/cards/NoteCard.tsx",
"frontend/src/app/pages/Dashboard/hooks/interaction/useCanvasControls.ts",
"frontend/src/app/pages/DashboardSelection/DashboardSelection.tsx",
"frontend/src/app/pages/Modes/Modes.tsx",
"frontend/src/app/pages/Skills/SkillBuilderChat.tsx",
"frontend/src/app/pages/Skills/Skills.tsx",
"frontend/src/app/pages/Views/ViewEditor.tsx",
"frontend/src/app/pages/Views/ViewPreview.tsx",
"frontend/src/app/pages/Views/useIframeElementSelector.ts",
"frontend/src/shared/browserCommandHandler.ts",
"frontend/src/shared/state/agentsSlice.ts",
"frontend/src/shared/state/dashboardLayoutSlice.ts",
"frontend/src/shared/ws/WebSocketManager.ts"
],
"max-folder-items": [
"backend",
"backend/apps",
"backend/apps/agents",
"backend/apps/agents/core",
"backend/apps/outputs",
"backend/apps/tools_lib",
"backend/tests",
"frontend/src/shared",
"frontend/src/shared/state",
"frontend/src/shared/hooks",
"frontend/src/app/pages",
"frontend/src/app/pages/AgentChat",
"frontend/src/app/pages/AgentChat/ChatInput",
"frontend/src/app/pages/AgentChat/ChatInput/hooks",
"frontend/src/app/pages/AgentChat/mcp-cards",
"frontend/src/app/pages/Settings/sections",
"frontend/src/app/pages/Views",
"frontend/src/app/components/Onboarding",
"frontend/src/app/components/Onboarding/steps",
"scripts",
"electron",
"linter/checks"
],
"max-file-lines": [],
"max-folder-items": [],
"no-nested-imports": [],
"import-cycles": [],
"vulture": ["backend/tests/*"],
"vulture": [],
"endpoints": [],
"classes": []
}
+1 -56
View File
@@ -2,59 +2,4 @@
# frameworks, entry points, and external consumers.
#
# Pass this file as an argument to vulture alongside source directories.
# Each bare name tells vulture "this symbol is intentionally used."
# backend/main.py — entry points referenced by string, not direct call
main
app
# FastAPI route handlers — registered via decorators, called by framework
pull_structure
push_structure
reset_color
reset_emoji
check
# FastAPI lifespan context managers — passed to SubApp constructor
debugger_lifespan
health_lifespan
# debug.py — module replaces itself with the debug() function via
# sys.modules[__name__] = debug, consumed by external packages
debug
# ---- OpenSwarm additions (eric/linter-integration) ----
# These are intentional false positives: symbols vulture can't see being
# used because the use is dynamic, a monkey-patch, or a kept-for-compat alias.
# google_workspace_mcp_shim/run.py: runtime monkey-patch of a third-party
# module attribute (gauth.get_credentials = _patched_get_credentials).
get_credentials
# outputs/view_builder_templates.py: deliberate backward-compat alias,
# kept so older importers don't snap a stale copy. The comment there explains why.
VIEW_BUILDER_SKILL
# browser_agent.py: `for turn in range(MAX_TURNS)` loop counter we don't read.
turn
# service.py: tuple-unpack byproducts of _compute_delta(); only cost_delta is
# consumed, the token/request deltas are computed but not summed yet.
prompt_delta
completion_delta
requests_delta
# ---- Suspected genuinely-dead, whitelisted to keep the linter additive-only ----
# This task is tooling-only and must not edit backend source, so these stay
# whitelisted rather than deleted. They have zero call sites today; a future
# non-additive cleanup pass should remove the definitions and these lines.
thinking_params_for
_resolve_model
load_output
submit_state
get_provider_credentials
# outputs.py + dashboards.py: model field assigned in Python but read only via
# model_dump() serialization to the frontend (drives preview sort order), so vulture
# can't see the read.
preview_updated_at
# Each bare name tells vulture "this symbol is intentionally used."
+55
View File
@@ -97,6 +97,61 @@ if lsof -ti :8324 >/dev/null 2>&1; then
sleep 0.3
fi
# --- EVS / Widevine VMP auth preflight (macOS only) ---
# DRM playback needs a CastLabs VMP signature, which needs a CastLabs EVS
# account. Only the ACCOUNT auth is interactive, so settle it HERE, before the
# backend/frontend background logs start streaming to this terminal (otherwise
# the prompt interleaves with [backend] output). Hybrid model:
# 1. Shared team account: creds from gitignored .env.evs (zero-touch, CI-friendly).
# 2. Per-dev fallback: skippable interactive signup when no shared creds exist.
# Once a token is cached locally, neither path prompts again. Fail-soft and fully
# skippable; skipping only limits DRM media to previews. OPENSWARM_SKIP_VMP=1
# silences the whole step. The actual signing still runs later via sign-vmp.sh,
# non-interactively, because the token (or env creds) are in place by then.
if [[ "$OSTYPE" == "darwin"* && "${OPENSWARM_SKIP_VMP:-}" != "1" ]]; then
# castlabs-evs reads EVS_ACCOUNT_NAME / EVS_PASSWD from the env for both
# reauth and sign-pkg, so sourcing the team file is all the wiring needed.
EVS_ENV_FILE="$PROJECT_ROOT/.env.evs"
[[ -f "$EVS_ENV_FILE" ]] && { set -a; source "$EVS_ENV_FILE"; set +a; }
if ! python3 -c "import castlabs_evs" 2>/dev/null; then
echo -e "${YELLOW}${BOLD}[vmp]${RESET} Installing castlabs-evs (one-time)..."
pip3 install --user --quiet castlabs-evs 2>/dev/null || true
fi
# Short connect timeout so an offline dev isn't stalled 60s at boot.
EVS_TO=(--connect-timeout 10 --auth-timeout 10)
if python3 -c "import castlabs_evs" 2>/dev/null; then
if python3 -m castlabs_evs.account -n "${EVS_TO[@]}" refresh </dev/null >/dev/null 2>&1; then
# Cached token still valid: nothing to do.
echo -e "${YELLOW}${BOLD}[vmp]${RESET} EVS already authenticated - DRM signing enabled."
elif [[ -n "${EVS_ACCOUNT_NAME:-}" && -n "${EVS_PASSWD:-}" ]]; then
# Path 1: shared account, fully non-interactive.
if python3 -m castlabs_evs.account -n "${EVS_TO[@]}" reauth </dev/null >/dev/null 2>&1; then
echo -e "${YELLOW}${BOLD}[vmp]${RESET} EVS authenticated (shared account) - DRM signing enabled."
else
echo -e "${YELLOW}${BOLD}[vmp]${RESET} EVS auth failed - check .env.evs creds. Continuing (DRM = previews)."
fi
elif [[ -t 0 ]]; then
# Path 2: no shared creds, interactive terminal: offer skippable signup.
echo ""
echo -e "${YELLOW}${BOLD}[vmp]${RESET} First-time DRM signing setup (free CastLabs account, ~1 min)."
echo -e "${YELLOW}${BOLD}[vmp]${RESET} Enables full DRM playback. Skip to do it later, or share a .env.evs."
read -r -p " Set up now? [Enter = yes, s = skip]: " _evs_ans
if [[ "$_evs_ans" == "s" || "$_evs_ans" == "S" ]]; then
echo -e "${YELLOW}${BOLD}[vmp]${RESET} Skipped - DRM limited to previews (OPENSWARM_SKIP_VMP=1 to silence)."
export OPENSWARM_SKIP_VMP=1
else
python3 -m castlabs_evs.account signup \
|| echo -e "${YELLOW}${BOLD}[vmp]${RESET} Signup didn't complete - continuing without DRM signing."
fi
else
# No creds and no TTY (piped / CI-like): never block, just skip.
echo -e "${YELLOW}${BOLD}[vmp]${RESET} No EVS creds and non-interactive shell - skipping DRM signing (previews only)."
fi
fi
fi
# --- Start backend ---
# Mark this as a dev launch so backend/run.sh enables --reload. Packaged
# builds never run this top-level script (Electron spawns backend