31 Commits

Author SHA1 Message Date
Brandon Zhang
9e2932fbc3 Use styled modal dialogs for confirmations 2026-03-27 18:51:34 +08:00
Brandon Zhang
920376449a Hide the settings panel for now 2026-03-27 18:38:36 +08:00
Brandon Zhang
b0c24e10c8 Restore global instruction numbering 2026-03-27 18:38:28 +08:00
Brandon Zhang
c690d0c483 Hardcode agent stale timeout 2026-03-27 18:32:25 +08:00
Brandon Zhang
07e31ce215 Fix consumed instruction ordering and clear history 2026-03-27 18:32:18 +08:00
Brandon Zhang
27592f2750 Stop updating removed header badges 2026-03-27 18:21:47 +08:00
Brandon Zhang
167633c7be Bump version to 1.0.1 2026-03-27 18:21:40 +08:00
Brandon Zhang
18352a99d5 Show server type in the web UI 2026-03-27 18:19:26 +08:00
Brandon Zhang
3360c2ad85 Remove duplicate Go README 2026-03-27 18:16:37 +08:00
Brandon Zhang
7a8dd14bd3 Show server version in logs and UI 2026-03-27 18:16:30 +08:00
Brandon Zhang
8d4392ee5a Add Go rebuild helper script 2026-03-27 18:06:52 +08:00
Brandon Zhang
8d4608d8b4 Clamp agent-facing remaining_pending 2026-03-27 18:06:48 +08:00
Brandon Zhang
65edecccec Ignore local binary build artifacts 2026-03-27 18:04:11 +08:00
Brandon Zhang
65b29bcf03 Improve SSE status and event auth handling 2026-03-27 17:55:28 +08:00
Brandon Zhang
f437f6939c Hardcode Go default empty response 2026-03-27 17:55:05 +08:00
Brandon Zhang
372e30ff6f Hardcode Python default empty response 2026-03-27 17:54:38 +08:00
Brandon Zhang
8a0dffbcae feat: add Go server implementation in go-server/
Full Go port of local-mcp with all core features. Copied from local-mcp-go
worktree to consolidate into single-branch repo (easier maintenance).
Architecture:
- internal/config:  Environment variable configuration
- internal/models:  Shared types (Instruction, Settings, AgentActivity, etc.)
- internal/db:      SQLite init with modernc.org/sqlite (pure Go, no CGo)
- internal/store:   Database operations + WakeupSignal + AgentTracker
- internal/events:  SSE broker for browser /api/events endpoint
- internal/mcp:     get_user_request MCP tool with 5s keepalive progress bars
- internal/api:     chi HTTP router with Bearer auth middleware
- main.go:          Entry point with auto port switching and Windows interactive banner
Dependencies:
- github.com/mark3labs/mcp-go@v0.46.0
- github.com/go-chi/chi/v5@v5.2.5
- modernc.org/sqlite@v1.47.0  (pure Go SQLite)
- github.com/google/uuid@v1.6.0
Static assets embedded via //go:embed static
Features matching Python:
- Same wait strategy: 50s with 5s progress keepalives
- Same hardcoded constants (DEFAULT_WAIT_SECONDS, DEFAULT_EMPTY_RESPONSE)
- Auto port switching (tries 8000-8009)
- Windows interactive mode (formatted banner on double-click launch)
Build:  cd go-server && go build -o local-mcp.exe .
Run:    ./local-mcp.exe
Binary size: ~18 MB (vs Python ~60+ MB memory footprint)
Startup:     ~10 ms (vs Python ~1-2s)
2026-03-27 15:45:26 +08:00
Brandon Zhang
4db402f258 feat: hardcode wait time and default response as constants
Changes:
- Add DEFAULT_WAIT_SECONDS = 50 (replaces config.default_wait_seconds)
- Add DEFAULT_EMPTY_RESPONSE = 'call this tool... ' (replaces config.default_empty_response)
- Remove wait and empty response fields from WebUI Settings panel
  (only agent_stale_after_seconds remains configurable)
Rationale:
These values are fundamental to the 60s timeout mitigation strategy and
should not be user-configurable. The 50s wait with 5s keepalives is the
optimal balance for staying under the Copilot 60s wall-clock limit while
providing responsive progress feedback.
2026-03-27 15:45:06 +08:00
Brandon Zhang
ba91349232 experiment: reduce keepalive to 5s and add progress bar
EXPERIMENT (NOT FOR PRODUCTION YET)
Changes:
- KEEPALIVE_INTERVAL_SECONDS reduced from 20s to 5s
- Keepalive messages now show progress bar with dots: ●●●●○○○○○○
- Show elapsed time, total wait, and remaining seconds
- Example:  Waiting for instructions... ●●●●○○○○○○ 20s / 50s (agent=copilot, 30s remaining)
Goal: Test if more frequent progress updates provide better UX and prevent
      perceived freezing during the 50s wait. No functional change - the
      60s client timeout limit remains the binding constraint.
2026-03-27 15:44:49 +08:00
Brandon Zhang
204f7c4ff6 docs(agents): add warning about committing compiled binaries
Binary executables bloat .git history and cause storage issues on
constrained upstream repos. Added recovery procedure:
git reset --soft HEAD~N, git reset HEAD <file>, delete, recommit.
2026-03-27 14:49:17 +08:00
Brandon Zhang
fa9d5c61c9 docs(agents): note that git commands require --no-pager to avoid terminal hang
git may invoke less as a pager which blocks the terminal waiting for
user interaction.  Always use 'git --no-pager <command>' or pipe
through Out-String/Format-List in PowerShell sessions.
2026-03-27 14:00:12 +08:00
Brandon Zhang
298ad54b5c fix(ui/theme): replace light theme with clean material design palette
The previous light theme used warm/organic off-whites and muted tones
that felt muddy.  Replaced with a crisp material-inspired palette:
Surfaces
- bg-void   #f0f2f5  (cool-grey base)
- bg-base   #f5f7fa  (very light cool background)
- bg-raised #ffffff  (pure white cards)
- bg-hover  #e3e8f0  (clear interactive hover)
Typography
- text-primary   #1a202c  (near-black, high contrast)
- text-secondary #4a5568  (balanced mid-grey)
- text-muted     #8896a7  (clear but soft)
Accents (Material Design colour values)
- cyan  #0277bd  Blue 700 (replaces washed-out #007fa8)
- green #388e3c  Green 700
- amber #e65100  Deep Orange 900 (warmer, more material)
- red   #d32f2f  Red 700
Shadows
Dual-layer transparent shadows for better depth perception on light
backgrounds.
Also adds @keyframes fade-in-up used by the shortcuts add form.
2026-03-27 13:55:36 +08:00
Brandon Zhang
93bce1521b feat(ui): add quick shortcuts panel with add/edit/delete support
Adds a compact shortcuts row inside the composer panel for one-click
instruction queuing, with full lifecycle management stored in localStorage.
Features
--------
- Six built-in defaults (Stop, Summarize, Explain error, Undo, Continue, etc.)
- Click any chip → instantly POSTs to /api/instructions, no typing required
  - Cyan border pulse on fire; green glow flash on success
- Edit mode (toggle button in header):
  - Per-chip edit (✏) button → replaces chip with inline input, Enter to save
  - Per-chip delete (✕) button → removes with vanish animation
  - '+ Add' chip → inline form appended below rail
- All changes persisted to localStorage key 'local-mcp-shortcuts'
- Accessible: button elements, aria-labels, keyboard support (Enter/Escape)
Files
-----
- static/js/shortcuts.js   new module (loadShortcuts, renderShortcuts,
                           startInlineEdit, showAddPrompt, initShortcuts)
- static/index.html        #shortcuts-container inside composer .panel-body
- static/js/app.js         import + initShortcuts() in bootstrap()
- static/css/components.css .shortcuts-container, .shortcut-chip variants,
                           .shortcut-inline-edit, keyframes chip-fire/sent/vanish
2026-03-27 13:55:22 +08:00
Brandon Zhang
056ae70e9a feat(mcp): add periodic SSE keepalive notifications during queue wait
When the tool is waiting for an instruction, send ctx.info() log
notifications to the client every KEEPALIVE_INTERVAL_SECONDS (default 20).
Purpose
-------
These notifications write bytes to the SSE stream, resetting any
transport-level HTTP read timeout on the client side (e.g. httpx
Timeout(read=N)).  This prevents premature connection drops when
wait periods exceed the client's inactivity window.
Caveat
------
Application-level wall-clock timers (anyio.fail_after / JS SDK
equivalents) are NOT affected by SSE events -- they count from
request start regardless.  This is confirmed by experiments in
tests/test_keepalive.py and tests/run_keepalive_experiments.py.
Experiment results (summarised in tests/run_keepalive_experiments.py)
----------------------------------------------------------------------
- Exp 1: anyio.fail_after(5s) fires at 5.98s with NO keepalives.
- Exp 2: anyio.fail_after(10s) fires at 10.90s WITH keepalives every 2s.
         Keepalives have ZERO effect on app-level timers.
- Exp 3b: httpx read=8s, keepalive=2s -> SUCCESS at 51s.
          Keepalives DO prevent transport-level read timeouts.
The Copilot extension 60s limit is almost certainly application-level
(hardcoded wall-clock), so default_wait_seconds=50 remains the correct
mitigation (returns before the 60s deadline).  The keepalives provide
defence-in-depth against any proxy/NAT inactivity drops.
2026-03-27 13:54:52 +08:00
Brandon Zhang
b1fdd98740 fix(script): add Windows .venv/Scripts path fallback in server.sh
On Windows the venv Python binary lives at .venv/Scripts/python.exe,
not .venv/bin/python.  Fall back to the Windows path when the Unix
path does not exist so the script works cross-platform.
2026-03-27 13:53:38 +08:00
009fd039a2 feat: optional Bearer-token authentication via API_TOKEN env var
Disabled by default (empty API_TOKEN). When set:
- All /api/* and /mcp requests require: Authorization: Bearer <token>
- Public exemptions: /, /healthz, /static/*, /auth-check
- Web UI: pre-flight /auth-check on load; shows token modal if required
- Token stored in sessionStorage, sent on every API request
- Mid-session 401s re-trigger the token modal
- MCP clients must pass the header: Authorization: Bearer <token>
Files changed:
- app/config.py: api_token field + API_TOKEN env var
- app/api/auth.py: Starlette BaseHTTPMiddleware for token enforcement
- main.py: register middleware + /auth-check public endpoint
- static/js/api.js: token storage, auth header, 401 handler hook
- static/js/app.js: auth pre-flight, showTokenModal(), bootstrap()
- static/css/components.css: .auth-overlay / .auth-card styles
- README.md: API_TOKEN env var docs + MCP client header example
2026-03-27 04:28:12 +08:00
1cc75afe87 feat: add server.sh bash management script (macOS/Linux)
Equivalent to server.ps1 for bash environments:
- start / stop / restart / status / logs [N|-f]
- Detached background process via nohup
- PID file in logs/ with live-process verification
- Port-based fallback detection via lsof
- Memory reporting (Linux /proc + macOS ps)
- Colour output with ANSI codes
- stderr error highlighting in status view
- Follow mode (-f) for live log tailing
2026-03-27 04:21:40 +08:00
7de4a03d94 fix: Enter key confirms edit (Shift+Enter for newline)
Edit textarea now mirrors composer behavior:
- Enter alone → save the edit
- Shift+Enter → insert newline
- Escape → cancel edit
2026-03-27 04:17:57 +08:00
589f45ba32 refactor: remove wait_seconds from get_user_request tool
Wait time is now fully server-controlled via default_wait_seconds setting.
Agents can no longer request a different wait duration - only the user
controls this via the web UI.
- Remove wait_seconds param from get_user_request signature
- Simplify actual_wait to min(cfg.default_wait_seconds, MAX_WAIT)
- Update Settings panel label from 'Min Wait' to 'Wait (sec)'
- Update hint text to explain server-only control
- Update README: input schema, behavior rules, settings description, changelog
2026-03-27 04:16:33 +08:00
256a445e2f feat: add Clear History button to delete all consumed instructions
- Backend: instruction_service.clear_consumed() bulk-deletes consumed rows
- Backend: DELETE /api/instructions/consumed route (preserves pending)
- Frontend: Clear button in consumed panel header (hidden when empty)
- Frontend: SSE handler for history.cleared event - instant UI update
- Frontend: api.clearConsumed() fetch wrapper
2026-03-27 04:16:24 +08:00
86eba27a24 init 2026-03-27 03:58:57 +08:00