Skip to content

feat(web-ui): live points, token auth, re-login, history/errors tabs, light mode - #615

Open
Zer02811 wants to merge 10 commits into
TheNetsky:v4from
Zer02811:claude/busy-chatterjee-3698e9
Open

Zer02811 wants to merge 10 commits into
TheNetsky:v4from
Zer02811:claude/busy-chatterjee-3698e9

Conversation

@Zer02811

Copy link
Copy Markdown

What changed

🔐 Token authentication

  • API token field in the header — paste your API_TOKEN once and it's saved to localStorage
  • Every fetch now carries Authorization: Bearer <token>; the SSE log stream passes ?token= (the only endpoint that allows it, per tokenFromReq in scripts/api/server.js)
  • A 401 surfaces as a "Token needed" status badge instead of an empty dashboard
  • Changing/clearing the token reconnects the log stream and re-checks health automatically

📊 Live Points panel

Polls GET /points every 5 s and shows what run history cannot know until a run finishes:

  • Current balance, points collected this run, accounts seen
  • Per-account row with by-source breakdown (search, bonus, read, …), earnable leftovers, and Edge-browsing status
  • Replaces the stale lastCollected number the account cards were showing before

🔑 Re-login button for expired accounts

  • When an account shows Login Expired, a Re-login button appears
  • One click → DELETE /sessions/:email (clears the stale cookie) → starts a fresh run for that account
  • Replaces the old "go run npm run manual-login from a terminal" dance

🗂️ History & Errors tabs

The single log console is now three tabs:

  • Live Logs — unchanged
  • History — collapsible runs with start time, duration, exit code, per-account results
  • Errors — account errors first, then warn+ log entries (from GET /errors)

☀️ Light mode

prefers-color-scheme: light gets a proper palette instead of the hard-coded dark theme.

Testing

  • 8/8 Node tests pass (tests/publicUi.test.mjs): proxy payload rules, history/errors rendering, HTML escaping, exit-code formatting
  • Verified against a live API: header token field, Live Points (balance 474, +200 from one run, breakdown urlReward 50 · checkIn 5 · read 30 · punchcard 70 · search 60), History/Errors tab switching
  • The 3 pre-existing test failures (abortRun, configEnvOverrides) are unchanged — they fail on main too because this worktree has no dist/ build

Notes for reviewers

  • No server-side changes — everything is additive frontend on top of the existing /points, /history, /errors, /sessions endpoints
  • Token is stored in localStorage keyed control_api_token; clearing it and refreshing is enough to test the unauthenticated flow
  • The diff is large but mostly additive — new sections and CSS blocks, no restructuring of existing handlers

🤖 Generated with Claude Code

Zer02811 and others added 10 commits September 13, 2026 18:56
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>
A-Z walkthrough for users with no coding experience: prerequisites,
Node.js setup, starting the dashboard, and using every UI section
(accounts, manual login, toggles, running, scheduling, live logs).
Documents the non-obvious defaults: API_ALLOW_SCHEDULE_WRITE is off so
Schedule Run fails until enabled, Remove only hides an account locally,
and Add Account never takes a password. Vietnamese version keeps UI
labels, commands, and error strings in English so they match the
on-screen text.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adds GET/PUT /accounts/:id/proxy and a proxy editor to the dashboard, so a
proxy can be changed without hand-editing .env and restarting the server.

The write path validates against the same rules the bot enforces in
src/util/Validator.ts (AccountProxySchema) and src/util/Proxy.ts: four
protocols, a bare hostname means http://, port 1-65535, credentials must not
sit in the URL, username and password must be set together, and SOCKS cannot
carry authentication at all because Patchright does not support it. A proxy
the API accepts is therefore always one the next run accepts.

Values are stored as ACCOUNT_N_PROXY_* lines in .env, matching where the bot
already reads them. Active lines are replaced in place so repeated saves do
not accumulate duplicates, and the write goes through a temp file plus rename
because OneDrive can lock the target. Commented template lines are never
treated as configuration.

The stored password is never returned - the read endpoint reports only
hasPassword. Leaving the password field blank keeps whatever is on disk, so
the UI never has to echo a secret back to the browser.

Editing is refused with 409 while a run is active; the change applies to the
next run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PROXY_GUIDE.vi.md walks someone who has never used a proxy through it: what a
proxy actually does, whether they need one at all (a single account does not),
which of the four supported types to pick and why SOCKS cannot use a password,
how to obtain one, how to enter it in the new editor, and how to tell a dead
proxy from a working one before blaming the tool.

Also documents the "Use for API requests too" toggle, which is the part most
people get wrong. It maps to proxyHttp: off means only the browser goes through
the proxy while direct Rewards API calls leave from the local connection, on
means both do. The guide recommends leaving it off, since cheap proxies
frequently break the API calls and that surfaces as unexplained fetch and
timeout errors.

Links the two guides to each other - the Web UI guide gains a per-account
proxy section, the proxy guide points back at it for install steps.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adds a section distinguishing a proxy vendor (you get one address plus your
own username and password) from a free public proxy list (thousands of IPs
shared with everyone). The two look similar enough that buying the wrong one
is easy, and the failure mode is quiet: the tool starts fine and the account
gets flagged later.

Public lists are unusable here - every IP is already in use by hundreds of
other people, the addresses die within hours, and there is no credential to
control or revoke. Some are deliberately seeded to harvest traffic, which
matters when the traffic is a Microsoft login.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… light mode

- API token field in the header; every fetch carries it and the SSE log
  stream passes ?token= (the only endpoint that accepts it). 401s surface
  as a 'Token needed' status instead of a silent empty page.
- Live Points section polled from /points: current balance, points earned
  this run, accounts seen, and a per-account row with by-source breakdown,
  earnable leftovers and Edge-browsing status.
- Re-login button on expired accounts: deletes the stored session via
  DELETE /sessions/:email then starts a fresh run.
- Run output split into Live Logs / History / Errors tabs; history shows
  collapsible runs, errors shows account errors first then warn+ logs.
- Light mode via prefers-color-scheme.
- Node tests for the proxy payload and the history/errors renderers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@tiaruebar1024

Copy link
Copy Markdown
Contributor

Will you ever stop trying to make the biggest changes ever in 1 pull request, and with claude code? Like web ui you already did like 4 pull requests on, there's an external repo which offers web ui if you want it so much. There is no need for internal web ui, as long as it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants