Conversation
Adds a dependency-free dashboard (public/) served by the existing node:http control API, plus the backend it needs: - account list sourced from .env (scripts/api/envAccounts.js) instead of a hand-maintained copy, so the UI cannot drift from the real accounts - per-account login status derived from the session store's stored cookies (scripts/api/sessionStore.js), so the UI can show which accounts still hold a live Microsoft auth cookie - task scheduling: taskScheduler.js persists tasks to scheduled_tasks.json, taskRunner.js polls and starts them one at a time, and both are wired into server.js behind API_ALLOW_SCHEDULE_WRITE - live log streaming over SSE so the dashboard console mirrors the run logParser: treat ExperimentalWarning as a warning rather than an error. Node prints it on stderr for the SQLite session store, and the old /\bWARN/ pattern missed it, so every run opened with a red herring. scheduled_tasks.json is gitignored: it is per-machine run state, not project config. eslint gains a browser-globals block for public/**. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A Stop from the dashboard previously just killed the process tree, which left Chromium instances to be reaped by the OS and could orphan them. - src/util/Abort.ts: run-wide AbortController plus a registry of live browsers, so an abort can force-close every Chromium it knows about. - Browser.ts registers each launched browser and unregisters on disconnect. - index.ts: SIGINT/SIGTERM now abort first (closing browsers) before flushing webhooks and exiting; the between-accounts delay and the 30-minute Edge browsing task are both interruptible, and the account loop stops rather than starting a fresh login. - processManager.js: writes an __ABORT__ sentinel to the child's stdin because Windows cannot deliver a real SIGTERM to a child process; the existing kill timer still escalates to a tree kill if the bot does not exit in time. Covered by tests/abort.test.mjs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Toggling Visual Search or 30-Minute Edge Browsing in the Web UI had no effect. The env vars reached the spawned bot correctly, but nothing in the child ever consumed them: applyEnvOverrides() was only called by the Docker entrypoint and the CLI, so loadConfig() read config.json verbatim and both flags stayed false. Add mergeEnvOverrides(), which applies the overrides to an already-parsed config object in memory, and call it from loadConfig() before validateConfig() - so overridden values pass the same schema checks as file values, and config.json is never rewritten. applyEnvOverrides() now preflights and delegates to the same merge, keeping Docker behaviour. Also widen boolean parsing to the shell-style words Load.ts already accepts (1/0, yes/no, on/off, case-insensitive) instead of only true/false, tolerate partial failure so one bad value no longer discards valid overrides, and mask secret values (webhook URLs, bot tokens) in the applied-override log. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…te task The background Edge browsing activity only posted progress reports to the rewards API; no browser tab was actually browsing. EdgeLiveBrowsing opens a tab in the already-authenticated context and reads for the full session window: scrolls with human-shaped pauses, dwells at the end of an article, and occasionally follows a link instead of jumping back to a feed. Links are restricted to the current host or a bing/microsoft/msn/microsoftedge suffix so a session cannot wander onto arbitrary sites. The session honours the run's AbortSignal at every wait, so a Stop unwinds it instead of hanging, and failures are logged as a warning rather than failing the whole activity. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Author
|
Opened against the wrong repository by mistake - this targets my own fork, not upstream. Closing; no review needed here. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a browser-based control dashboard for the script and fixes the run-control
gaps it exposed: toggles that were sent but never applied, and a Stop button that
killed the process without closing Chromium.
Four commits, each independently reviewable:
b860db0public/) + scheduling & account endpoints in the control APIfa93375760b2f3CONFIG_*env overrides are applied on every bot start9938d4eWhy
1. Web dashboard and scheduling (
b860db0)The control API (
scripts/api/server.js) had no UI.public/is adependency-free static dashboard (vanilla JS, no build step) served by the
existing server: start/stop a run, watch logs live over SSE, see per-account
login status, and schedule runs for later.
Supporting pieces:
scripts/api/taskScheduler.js— persists scheduled tasks toscheduled_tasks.json, splits due vs. missed tasks (1h grace window).scripts/api/taskRunner.js— 30s tick, one run at a time, maps task togglesto
CONFIG_*env vars viabuildEnvForTask.scripts/api/envAccounts.js— reads account emails from.envso the UI canlist accounts without a separate config.
scripts/api/sessionStore.js— reports real login status per account from thesession DB (live / expired / never logged in) instead of guessing.
logParser.js—ExperimentalWarningwas being classified as ERROR, whichmade every run look like it failed in the log console. Now a warning.
2. Graceful stop (
fa93375)Stop sent
SIGTERMand, on Windows, that isTerminateProcess— the bot nevergot a chance to run its handler, so Chromium instances survived until the OS
reaped the tree (and sometimes not even then).
Now:
src/util/Abort.ts— a process-wide abort signal plus a registry of livebrowsers.
Browser.tsregisters on launch and unregisters ondisconnected.processManager.jswrites an__ABORT__sentinel to the child's stdin (theonly cross-platform way to say "stop" to a Node child on Windows) and still
sends
SIGTERMon POSIX. The existing kill timer escalates to a tree kill ifthe bot does not exit in time, so a hung run is still stoppable.
src/index.tsaborts on stop: closes every tracked browser, cancels theEdge-browsing background task, breaks out of the account loop before starting
a fresh login, and wakes up from the multi-minute inter-account delay (which
previously made Stop look frozen).
Force-stop still hard-kills the tree immediately — unchanged.
3.
CONFIG_*overrides never reached the bot (760b2f3)This is the actual bug behind "Visual Search and 30-Minute Edge Browsing are
skipped even when toggled on".
The chain was intact right up to the last link:
CONFIG_WORKER_VISUAL_SEARCH/CONFIG_EXPERIMENTAL_EDGE_BROWSINGcorrectly.buildEnvForTaskandProcessManager._resolveEnvforwarded them into the child's env correctly.applyEnvOverrides— the only thingthat translates
CONFIG_*into config — was called solely from the Dockerentrypoint and the CLI. A locally spawned
node dist/index.jsreadconfig.jsonverbatim, where both flags arefalse, so theifguards insrc/index.tsnever fired. Restarting the server changed nothing.Fix, in-memory and per-run:
mergeEnvOverrides(config, env)applies overrides to an already-parsed configobject.
loadConfig()calls it beforevalidateConfig, so overridden valuesgo through the same zod schema as file values.
config.jsonis never rewritten — it is a real gitignored user file.Overrides live and die with the run.
'true'/'false'to shell-style words(
1/0,yes/no,on/off, case-insensitive, trimmed), matching whatLoad.tsalready accepts for its own env flags.overrides; each rejected var logs a warning instead of failing silently.
[Config] override: CONFIG_… -> .path = …)so a toggle that did not take effect is visible in the log console. Webhook
URLs and bot tokens are marked
secretand masked as***.applyEnvOverrides(Docker) now preflights then delegates to the same merge,so both paths share one implementation. Docker behaviour is unchanged, and
FORCE_HEADLESSstill wins overCONFIG_HEADLESS.4. Real browsing during the Edge task (
9938d4e)The 30-minute Edge browsing activity only posted progress reports — no browser
activity accompanied them.
EdgeLiveBrowsing.tsopens a tab in thealready-authenticated context and reads like a person: scrolls with variable
pauses, dwells at the end of an article, occasionally follows a link, then moves
to another feed. Runs alongside the report loop and is fully abort-aware.
Link following is restricted to an allowlist of hosts
(
bing.com,microsoft.com,msn.com,microsoftedge.com) plus the currenthost, so a hostile feed link cannot navigate the authenticated session off-site.
Testing
npm test— 32/32 pass (22 existing + 10 new). New suites:tests/configEnvOverrides.test.mjs,tests/abort.test.mjs,tests/sessionStatus.test.mjs.npx tsc --noEmitclean,eslintclean,prettier --checkclean on alltouched files.
was an integration gap:
POST /startwith the exact UI payload, toggles ON → the spawned childresolved
doVisualSearch=true edgeBrowsing=true. Toggles OFF → bothfalse.POST /schedule/taskswith both flags → task fired on the 30s tick → childresolved both
true, task finisheddone.config.jsonconfirmed untouched on disk after every run.Notes for reviewers
saying it is open to anything on the machine. That is pre-existing, but this PR
widens what is reachable (account list, scheduling, run control), so it is
worth a decision. Schedule writes are gated behind
API_ALLOW_SCHEDULE_WRITE(default off) for that reason.
scheduled_tasks.jsonis gitignored — it is user runtime state.public/is intentionally build-free: no bundler, no npm deps, servedstraight by the existing
node:httpserver..claude/launch.jsonis included so the dev-server preview points at thedashboard on port 3010.
EdgeLiveBrowsingis underexperimental/and only runs whenexperimental.edgeBrowsingis on.🤖 Generated with Claude Code