mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-11 12:17:45 +02:00
[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:
@@ -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=
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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": []
|
||||
}
|
||||
|
||||
@@ -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."
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user