Skip to content

Add a local web interface (codonopt gui) - #2

Merged
thomdehoog merged 6 commits into
finish-codon-optimizerfrom
web-interface
Oct 10, 2026
Merged

thomdehoog merged 6 commits into
finish-codon-optimizerfrom
web-interface

Conversation

@thomdehoog

Copy link
Copy Markdown
Owner

Stacked on #1 (base finish-codon-optimizer): adds codonopt gui, a local web interface.

What it is

  • Two environments. The interface is TypeScript in web/ (esbuild, tsc, Playwright) compiled to plain HTML/CSS/JS in src/codonopt/web/, which is committed. Running it needs only Python: pip install -e . then codonopt gui (or python -m codonopt gui). Install .[gui] for a native pywebview window; otherwise it opens in the browser.
  • Server (server.py, stdlib only): job API with polling and cooperative cancel; loopback-only bind, Host/Origin checks, per-process token, strict CSP, size and time limits, no filesystem access from the API.
  • UI: sequence input (paste, open file, example, auto-detect protein/DNA), host table or custom table, keep-out sites, GC/homopolymer/splice targets, effort levels, advanced weights; results with highlighted changed codons, before/after table, GC chart, score breakdown, copy/download. Light/dark, responsive, no external assets, 43 kB total.
  • Supporting changes: gc_profile, table_from_text, should_stop/cancelled in the optimizer, __main__.py.

Testing

  • pytest: all pass (incl. 61 server tests and a check that built assets ship).
  • cd web && npm run check: type-check plus build-drift check.
  • npm test: 9 Playwright tests against the real Python server (run, protein preserved, errors, cancel, download, light/dark, phone width).

Not tested

The native pywebview window itself (not installable in the build sandbox); the server and page are exercised in Chromium. Blob downloads in the native window rely on ALLOW_DOWNLOADS.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Wq3oxFtutXhnAgmzKztG9g


Generated by Claude Code

- codonopt gui: stdlib-only local server (loopback, token, CSP, job API
  with cancellation) opening in pywebview or the browser
- web/: TypeScript + CSS sources, esbuild build with --check for drift,
  Playwright end-to-end tests; built files committed to src/codonopt/web
- gc_profile metric, table_from_text, cooperative cancel in the optimizer
- python -m codonopt entry point; README sections

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wq3oxFtutXhnAgmzKztG9g
…ck and e2e

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wq3oxFtutXhnAgmzKztG9g
…ructure

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wq3oxFtutXhnAgmzKztG9g
Found by reviewing the interface branch.

Client:
- a second submit before the first POST answered started a second job whose
  timer was never cleared; the page then showed whichever finished first
- a poll answering after its job was replaced painted the old result over the
  new run and cleared the new run's timer; polls now check they are current
- a failed Stop left the button dead on "Stopping..."; it now reverts and says
  the run is still going
- startup failures and 2xx responses with no JSON body left a silent dead page
- unreadable or oversized dropped files were ignored without a word
- the form is inert until the defaults arrive, so early typing is not wiped
- copy buttons clicked twice kept the word "Copied" as their label
- aria-live moved off the whole results region onto a small status line

Validation:
- an empty custom codon table silently optimised against the human table
- too-long DNA showed a green badge; the limit now counts codons, and an
  appended stop codon
- integers too wide for a float, or wider than int() parses, escaped as a 500

Tests and CI: wait on a real readiness signal instead of a dead 10 s sleep
(the suite drops from 1.8 min to 35 s), watch for browser errors in every
test, take a per-run port, keep traces and screenshots on failure, retry twice
in CI, and run the MaxEntScan splice path that CI never covered.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wq3oxFtutXhnAgmzKztG9g
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wq3oxFtutXhnAgmzKztG9g
Playwright loads the config again in every worker, so a pid-based port made
each worker look for the server on a different port than the one it was
started on. Every test failed with ECONNREFUSED in CI; local runs passed only
because they set CODONOPT_PORT explicitly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wq3oxFtutXhnAgmzKztG9g
@thomdehoog
thomdehoog merged commit 8b8e4c4 into finish-codon-optimizer Oct 10, 2026
10 of 12 checks passed
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