[eric] cleanup: convention fixes for merged #113/#107 (p-private rename, dead code, scratch files, em-dash, lint exceptions)

This commit is contained in:
ciregenz
2026-06-29 21:52:53 -07:00
parent 1b6d747326
commit e1639468a5
6 changed files with 9 additions and 99 deletions
@@ -33,7 +33,6 @@ p_refresh_task: Optional[asyncio.Task] = None
# The curated repo's recursive file tree, warmed hourly alongside the catalog. A curated install reads paths from here and fetches contents over raw, so it makes ZERO GitHub API calls in the normal case (the trees API is the 60/hr-limited part); update detection reads per-folder tree SHAs from it too. Empty until the first refresh warms it; install falls back to one live tree call then.
p_curated_tree: list[dict] = []
p_curated_tree_at: float = 0
# Community repo trees for update detection, cached briefly (best-effort) so an updates check on skills.sh-installed skills doesn't refetch every page load nor burn the API.
P_COMMUNITY_TREE_TTL = 600
p_community_tree_cache: dict[str, tuple] = {}
@@ -173,14 +172,13 @@ async def p_warm_curated_tree() -> None:
over raw). One cheap call per hourly refresh, reused by every install in that hour.
Isolated, a failure here never touches the SKILL.md catalog; install falls back to
a live tree call while the cache is cold."""
global p_curated_tree, p_curated_tree_at
global p_curated_tree
owner, _, repo = REPO.partition("/")
try:
async with httpx.AsyncClient(timeout=30.0, headers=github_headers()) as client:
tree = await p_tree_at(client, owner, repo, BRANCH)
if tree:
p_curated_tree = tree
p_curated_tree_at = time.time()
logger.info(f"Curated skill tree warmed: {len(p_tree_blob_paths(tree))} file paths cached")
except RegistryRateLimited:
# Visible on purpose: a rate-limited warm-up means installs stay on the slow live-call path until the IP's quota resets or a token is set.
@@ -432,7 +430,7 @@ async def p_build_resolved_skill(
if "SKILL.md" not in files:
raise ValueError("SKILL.md could not be fetched")
meta, p_body = p_parse_frontmatter(files["SKILL.md"])
meta, _ = p_parse_frontmatter(files["SKILL.md"])
# Reuse the .swarm importer's content scan: flag files holding secret-shaped literals (the author's leaked key, or a sketchy skill) so the user sees it before installing from an unvetted repo.
from backend.common.secret_scan import find_secrets_in_files
secret_findings = find_secrets_in_files({rel: data.encode("utf-8", "ignore") for rel, data in files.items()})
@@ -624,7 +622,7 @@ async def p_safe_repo_tree(source: str):
if owner and repo:
try:
async with httpx.AsyncClient(timeout=30.0, headers=github_headers()) as client:
p_branch, tree = await p_fetch_repo_tree(client, owner, repo)
_, tree = await p_fetch_repo_tree(client, owner, repo)
except Exception:
tree = None
p_community_tree_cache[source] = (now, tree)
@@ -671,7 +669,7 @@ async def registry_update(req: p_UpdateRequest):
bumping its version. Re-runs the secret scan and returns any findings so the UI can
flag a community update that newly ships secrets. A skill with no source (user-made)
can't be updated."""
from backend.apps.skills.skills import sync_skills, write_folder_skill, p_clear_skill_dir
from backend.apps.skills.skills import sync_skills, write_folder_skill, clear_skill_dir
target = next((s for s in sync_skills() if s.id == req.skill_id), None)
if target is None:
raise HTTPException(status_code=404, detail="skill not found")
@@ -690,7 +688,7 @@ async def registry_update(req: p_UpdateRequest):
raise HTTPException(status_code=502, detail=f"could not fetch skill: {e}")
# Overwrite in place: clear first so files removed upstream don't linger, keep the user's command alias, refresh everything else from source.
p_clear_skill_dir(target.id)
clear_skill_dir(target.id)
skill = write_folder_skill(
target.id,
resolved["files"],
+1 -1
View File
@@ -361,7 +361,7 @@ async def get_skill(skill_id: str):
raise HTTPException(status_code=404, detail="Skill not found")
def p_clear_skill_dir(skill_id: str) -> None:
def clear_skill_dir(skill_id: str) -> None:
"""Empty a skill's folder before an in-place update so files removed upstream
don't linger as orphans. write_folder_skill recreates the dir right after."""
import shutil
-72
View File
@@ -1,72 +0,0 @@
// key-probe.js: inspect keyboard events INSIDE a game's guest webview.
//
// Why: the open question on the keyboard fix is whether tool-issued
// sendInputEvent delivers correct key codes once the guest is focused, or
// whether it arrives with an empty `code` / keyCode:0 (which games ignore) and
// we must switch to CDP Input.dispatchKeyEvent. This probe answers it directly
// instead of inferring from whether the sprite moved.
//
// Usage:
// 1. Right-click the game webview -> Inspect -> Console (this is the GUEST
// console, http://127.0.0.1:<port>/..., NOT the host app devtools).
// 2. Paste this whole file and hit Enter. You'll see "[key-probe] armed".
// 3. Fire one tool-issued press_key, e.g. { key: "ArrowRight", hold_ms: 800 }.
// 4. Read the logged lines, or call __keyProbe.dump() for a table.
//
// What to look for per event:
// - isTrusted: should be true (native OS-level event). false = a JS
// dispatchEvent, not our native path.
// - code: should be e.g. "ArrowRight". EMPTY string is the failure signal.
// - keyCode/which: should be e.g. 39. 0 is the failure signal.
// - holdMs (on keyup): wall-clock ms the key was held. ~0 means the hold
// collapsed to an instant tap (down+up same tick); ~800 means hold worked.
// Decision: clean code + nonzero keyCode -> stay on sendInputEvent. Empty
// code / keyCode 0 -> move the keyboard path to CDP Input.dispatchKeyEvent.
(function () {
if (window.__keyProbe) {
try { window.__keyProbe.disarm(); } catch (_) {}
}
var events = [];
var downAt = Object.create(null); // key -> timestamp, to measure hold duration
function row(e) {
var now = (performance && performance.now) ? performance.now() : Date.now();
var holdMs = null;
if (e.type === 'keydown') {
downAt[e.code || e.key] = now;
} else if (e.type === 'keyup') {
var k = e.code || e.key;
if (downAt[k] != null) { holdMs = Math.round(now - downAt[k]); delete downAt[k]; }
}
var r = {
type: e.type,
key: e.key,
code: e.code, // EMPTY = failure signal
keyCode: e.keyCode, // 0 = failure signal
which: e.which,
isTrusted: e.isTrusted, // true = native; false = synthetic JS
repeat: e.repeat,
target: (e.target && (e.target.tagName || e.target.nodeName)) || '(none)',
holdMs: holdMs, // only set on keyup
};
events.push(r);
var warn = (r.code === '' || r.code == null) ? ' <-- EMPTY code'
: (r.keyCode === 0) ? ' <-- keyCode 0' : '';
console.log('[key-probe]', r.type, JSON.stringify(r) + warn);
}
// Capture phase + on window so we see the event even if the game stops
// propagation on its own listener.
var types = ['keydown', 'keyup', 'keypress'];
types.forEach(function (t) { window.addEventListener(t, row, true); });
window.__keyProbe = {
events: events,
dump: function () { try { console.table(events); } catch (_) { console.log(events); } return events; },
clear: function () { events.length = 0; for (var k in downAt) delete downAt[k]; console.log('[key-probe] cleared'); },
disarm: function () { types.forEach(function (t) { window.removeEventListener(t, row, true); }); console.log('[key-probe] disarmed'); },
};
console.log('[key-probe] armed on', location.href, '- fire a press_key, then __keyProbe.dump(). document.activeElement =', document.activeElement && (document.activeElement.tagName || document.activeElement.nodeName));
})();
-18
View File
@@ -1,18 +0,0 @@
#!/bin/bash
# watch-moves.sh: human-readable, moves-only view of the App Agent.
# Shows just the actions it takes (clicks, keypresses, waits), one per line,
# plus task-start and bridge-missing milestones. Hides all the dispatch/result/
# electron echo noise. Usage: bash backend/watch-moves.sh [logfile]
LOG="${1:-/tmp/openswarm.log}"
tail -f "$LOG" | awk '
{ gsub(/\033\[[0-9;]*m/, "") } # strip color codes
match($0, /[0-9][0-9]:[0-9][0-9]:[0-9][0-9]/) { t = substr($0, RSTART, 8) }
/\[app-agent\] START loop/ { print ""; print "=== " t " TASK START ==="; next }
/BRIDGE MISSING/ { print t " !! bridge missing: app is NOT agent-operable, driving UI blind"; next }
/\[browser-action\]/ {
sub(/.*\[browser-action\] [A-Za-z]+: /, "") # drop everything up to the action
sub(/ *-> .*/, "") # drop the trailing browser_id
print t " > " $0
next
}
'
+1 -1
View File
@@ -2444,7 +2444,7 @@ app.on('web-contents-created', (_event, contents) => {
`).catch(() => {});
// Agent bridge (window.OPENSWARM_APP). Injected into EVERY app's main world
// from the shell so it exists regardless of frontend/src — the lightweight
// from the shell so it exists regardless of frontend/src; the lightweight
// App Builder mode deletes frontend/src (and with it the template's own
// agentBridge.ts), so this is the only entry point a trimmed app can't lose.
// Idempotent + guarded: a workspace app that imports its own bridge installs
+2
View File
@@ -93,6 +93,7 @@
"backend/tests/test_disconnect_resilience.py",
"backend/tests/test_outputs_runtime_cleanup.py",
"backend/tests/test_service.py",
"backend/tests/test_skill_registry_community.py",
"backend/tests/test_streaming_harness.py",
"backend/tests/test_swarm_bundle.py",
"backend/tests/test_v2_invariants.py",
@@ -197,6 +198,7 @@
"p-private": [
"backend/apps/workflows/workflows.py",
"backend/tests/test_schedule_recurrence.py",
"backend/tests/test_skill_registry_community.py",
"backend/tests/test_ssrf_guard.py",
"backend/tests/test_workflows_semantics.py",
"backend/tests/test_workflows_storage.py"