Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
554 commits
Select commit Hold shift + click to select a range
790fc70
test: keep bare git fixtures on master
AJV20 May 28, 2026
923b719
fix: surface gateway auth errors in browser
AJV20 May 28, 2026
fa34c72
Merge PR #3044
May 28, 2026
b77398a
Merge PR #3043
May 28, 2026
0147f05
Merge PR #3055
May 28, 2026
0fd12b2
Merge PR #3056
May 28, 2026
d446a6c
Merge PR #3049
May 28, 2026
2443db6
Merge PR #3071
May 28, 2026
167ed85
Merge PR #3070
May 28, 2026
50a0d25
Merge PR #3047
May 28, 2026
2107160
Merge PR #3054
May 28, 2026
4058c74
Merge PR #3072
May 28, 2026
34d7585
Merge PR #3051
May 28, 2026
95aa69f
stage-batch35: stamp v0.51.153 / Release DY
May 28, 2026
354fec9
speed up swipe action reveal
dobby-d-elf May 28, 2026
60d4b2d
fix: harden WebUI bugfix sweep
AJV20 May 28, 2026
b103f4a
Merge pull request #3081 from nesquena/release/stage-batch35
nesquena-hermes May 28, 2026
dc5b4b1
Merge PR #3037
May 28, 2026
007ba46
Merge PR #3048
May 28, 2026
11ea6c3
Merge PR #3060
May 28, 2026
83f8080
Merge PR #3053
May 28, 2026
c642c1e
Merge PR #3069
May 28, 2026
921b94a
Merge PR #3046
May 28, 2026
4412aea
Merge PR #3059
May 28, 2026
1c89c7d
Merge PR #3064
May 28, 2026
a3fc305
Merge PR #3077
May 28, 2026
cf6e311
Merge remote-tracking branch 'origin/master' into fix/webui-bugfix-sweep
AJV20 May 28, 2026
1cd58f6
fix(session): preserve sidecar order in display merges
ai-ag2026 May 28, 2026
07aed6b
fix(session): preserve subsecond message timestamp order
ai-ag2026 May 28, 2026
371f77c
stage-batch36: stamp v0.51.154 / Release DZ
May 28, 2026
0f6eab3
Fix browser chat provider fallback on fresh sessions
george-andraws May 28, 2026
0a2dabc
stage-batch36: tighten #3064 MEDIA: token gate to non-user-role messages
May 28, 2026
6267716
Merge pull request #3088 from nesquena/release/stage-batch36
nesquena-hermes May 28, 2026
2f73eb0
Merge PR #3039
May 28, 2026
88bdc99
Merge PR #3085
May 28, 2026
ad9b38c
Merge PR #3086
May 28, 2026
2893f87
stage-batch37: stamp v0.51.155 / Release EA
May 28, 2026
609a0c8
fix: carry WebUI context through gateway chat
AJV20 May 28, 2026
20f8c7c
Merge pull request #3089 from nesquena/release/stage-batch37
nesquena-hermes May 28, 2026
b253d34
refine swipe action reveal timing
dobby-d-elf May 28, 2026
00f4b11
fix: limit webui durable memory guidance
AJV20 May 28, 2026
2cb3c9f
Merge remote-tracking branch 'origin/master' into HEAD
AJV20 May 28, 2026
c494e41
Merge remote-tracking branch 'origin/master' into fix/webui-gateway-c…
AJV20 May 28, 2026
79fd4b6
test: make gateway context test self-contained
AJV20 May 28, 2026
d5b3626
Merge remote-tracking branch 'origin/master' into fix/selective-durab…
AJV20 May 28, 2026
1aa352e
Merge remote-tracking branch 'origin/master' into fix/session-list-to…
dobby-d-elf May 28, 2026
b554fd8
fix(reasoning): 推理强度补齐 max 档,与 hermes_constants 对齐
theseussss May 28, 2026
d539d5c
fix: budget webui prefill context
AJV20 May 28, 2026
d2265aa
Merge PR #3084
May 28, 2026
b92204a
fix(sidebar): keep newer continuation visible over older snapshot
hermes-agent May 21, 2026
f7b4c6b
Merge PR #3087
May 28, 2026
993e251
stage-batch38: stamp v0.51.156 / Release EB
May 28, 2026
5ec136a
Merge pull request #3095 from nesquena/release/stage-batch38
nesquena-hermes May 28, 2026
22db5bb
Merge PR #3092
May 28, 2026
1a64097
Merge PR #3093
May 28, 2026
20f8bc3
Merge PR #3090
May 28, 2026
6719f35
Merge PR #3094
May 28, 2026
c1a7668
Merge PR #3091
May 28, 2026
65dc5f7
stage-batch39: add CHANGELOG entry for #3091 (no entry in original PR)
May 28, 2026
0459f60
stage-batch39: stamp v0.51.157 / Release EC
May 28, 2026
b76a6df
fix: forward gateway tool activity to webui
AJV20 May 28, 2026
cf003ae
Merge pull request #3096 from nesquena/release/stage-batch39
nesquena-hermes May 28, 2026
d8a48ee
Merge remote-tracking branch 'origin/master' into fix/webui-gateway-t…
AJV20 May 28, 2026
53f16c4
fix: log WebUI shutdown diagnostics
ai-ag2026 May 28, 2026
b476126
fix(ui): match tool result snippet limit to backend (200 -> 4000 chars)
mysoul12138 May 29, 2026
f5dc947
fix: submit composer on numpad enter
dso2ng May 29, 2026
7f63a1c
Add regression test for JS/Python snippet limit parity
mysoul12138 May 29, 2026
7c3d85d
Fix #3107: throttle active-session external-refresh poll from 5s to 30s
Sanjays2402 May 29, 2026
e09c6aa
Fix #3076: don't force mobile send-on-Enter when a real keyboard is a…
Sanjays2402 May 29, 2026
35f89c4
fix: harden external notes guardrails
AJV20 May 29, 2026
ce82ea3
fix: add joplin search auth compatibility
AJV20 May 29, 2026
3c2f98e
fix: polish WebUI assistant replies
AJV20 May 29, 2026
e6aa927
fix(models): preserve provider-qualified model selections in the picker
plerohellec May 29, 2026
649f64b
Merge PR #3129 into stage-batch40
May 29, 2026
d072039
Merge PR #3130 into stage-batch40
May 29, 2026
9aff2a1
Merge PR #3137 into stage-batch40
May 29, 2026
3206aec
Merge PR #3138 into stage-batch40
May 29, 2026
ff78a42
Merge PR #3139 into stage-batch40
May 29, 2026
edd8075
stage-batch40: CHANGELOG for v0.51.158 (Release ED)
May 29, 2026
1ebd160
Merge pull request #3143 from nesquena/release/stage-batch40
nesquena-hermes May 29, 2026
9ca0bdc
Merge PR #3098 into stage-batch41
May 29, 2026
5c96764
Merge PR #3099 into stage-batch41
May 29, 2026
de90ca3
Merge PR #3117 into stage-batch41
May 29, 2026
111e7a1
Merge PR #3118 into stage-batch41
May 29, 2026
11ba36b
Merge PR #3135 into stage-batch41
May 29, 2026
4e382e4
stage-batch41: update test_issue1824 snippet-limit assertion 200->400…
May 29, 2026
6d61fbd
stage-batch41: CHANGELOG for v0.51.159 (Release EE)
May 29, 2026
95cee09
Merge pull request #3144 from nesquena/release/stage-batch41
nesquena-hermes May 29, 2026
017179b
fix: speed up session index metadata refresh
ai-ag2026 May 29, 2026
39f09a5
fix: read skills disabled state from active profile
chouzz May 29, 2026
1f51ef1
fix: detect shared OpenCode API key
zapabob May 29, 2026
23f5ee1
review-3142: align load_metadata_only comment with sidecar-first logic
May 29, 2026
dc2ed59
Merge PR #3136 (OpenCode shared key) into stage-batch42
May 29, 2026
8933fe9
Merge PR #3112 (skills disabled read-path) into stage-batch42
May 29, 2026
bd0e915
Merge PR #3142 (session-index metadata refresh perf) into stage-batch42
May 29, 2026
cb7360e
stage-batch42: CHANGELOG for v0.51.160 (Release EF) + skills/session-…
May 29, 2026
c8afb37
Merge pull request #3146 from nesquena/release/stage-batch42
nesquena-hermes May 29, 2026
24b1750
Fix #3114: keep jump-to-question button on intermediate assistant mes…
Sanjays2402 May 29, 2026
d45bc32
test: update #2246 question-jump assertions for #3114 (button on all …
May 30, 2026
01c2780
Fix #3018: preserve per-turn ephemeral fields across session refreshes
Sanjays2402 May 29, 2026
6d56280
test: update session-rotate-url-sync marker for #3018 split assignmen…
May 30, 2026
0002cda
fix: stale unread dot, compression timer leak, tool card duplication …
mysoul12138 May 29, 2026
5b37710
Fix tool card duplication: skip detail when snippet equals preview
mysoul12138 May 29, 2026
02e8a6c
Merge PR #3127 (jump-to-question on intermediate assistant msgs) into…
May 30, 2026
86d5d63
Merge PR #3131 (preserve per-turn ephemeral fields) into stage-batch43
May 30, 2026
9059b8f
Merge PR #3116 (stale unread + compression timer + tool-card dedup) i…
May 30, 2026
49a16e5
stage-batch43: CHANGELOG for v0.51.161 (Release EG)
May 30, 2026
7edd435
stage-batch43: extend #3018 carry-forward to _finishDone completion p…
May 30, 2026
3119ea8
test: update rotate-url-sync completion_marker for #3018 _finishDone …
May 30, 2026
cbc74e3
Merge pull request #3147 from nesquena/release/stage-batch43
nesquena-hermes May 30, 2026
317d828
Add clear button to conversation filter
george-andraws May 27, 2026
28498aa
fix: scope conversation filter clear search CSS
george-andraws May 28, 2026
01c63be
Merge PR #3026 (clear button on conversation filter) into stage-batch44
May 30, 2026
e0c2717
test: cover code-only title language fallback
ai-ag2026 May 28, 2026
ed12948
stage-batch44: CHANGELOG for v0.51.162 (Release EH)
May 30, 2026
24a2668
Merge pull request #3148 from nesquena/release/stage-batch44
nesquena-hermes May 30, 2026
da9211b
fix(session): copy all critical fields on duplicate and branch to pre…
AlexeyDsov May 28, 2026
71d0b1c
Merge PR #3101 (session duplicate/branch field propagation) into stag…
May 30, 2026
315cca2
stage-batch45: CHANGELOG for v0.51.163 (Release EI)
May 30, 2026
e90ebd2
Merge pull request #3149 from nesquena/release/stage-batch45
nesquena-hermes May 30, 2026
b53bc1a
fix: harden webui passive performance paths
AJV20 May 29, 2026
694fdd1
review-3105: bound _wait_until_restart_safe with 300s max-wait + exec…
May 30, 2026
938a58b
Merge PR #3105 (passive performance hardening + bounded restart-safet…
May 30, 2026
a7848c8
stage-batch46: CHANGELOG for v0.51.164 (Release EJ)
May 30, 2026
832cf8e
Merge pull request #3151 from nesquena/release/stage-batch46
nesquena-hermes May 30, 2026
ab4de3b
Fix #3103: stop emitting Connection: close on long-lived SSE streams
Sanjays2402 May 29, 2026
2fc692f
test: pin #3103 — SSE event-stream handlers must not emit Connection:…
May 30, 2026
728bf42
Merge PR #3128 (stop Connection: close on long-lived SSE streams) int…
May 30, 2026
5f0d753
stage-batch47: CHANGELOG for v0.51.165 (Release EK)
May 30, 2026
3005811
Merge pull request #3153 from nesquena/release/stage-batch47
nesquena-hermes May 30, 2026
d2686ea
fix: honor shared OpenCode key at runtime
AJV20 May 30, 2026
e68c670
fix: keep agent cron sessions in project chips
AJV20 May 30, 2026
798ca58
Merge PR #3150 (honor shared OpenCode key at runtime, closes #3145) i…
May 30, 2026
c2663f8
Merge PR #3152 (keep agent cron sessions in project chips, #3134) int…
May 30, 2026
abe87b9
Merge pull request #3156 from nesquena/release/stage-batch48
nesquena-hermes May 30, 2026
6791b1d
Merge PR #2252 (swipe actions for touch devices + session list FLIP) …
May 30, 2026
359a86c
Merge PR #2252 (swipe actions for touch devices + session list FLIP) …
May 30, 2026
6702805
stage-batch49: CHANGELOG for v0.51.167 (Release EM)
May 30, 2026
9cd7729
Merge pull request #3161 from nesquena/release/stage-batch49
nesquena-hermes May 30, 2026
e5b31ca
fix(#3162): const→let in _ensureMessagesLoaded (brick-class mobile Ty…
May 30, 2026
e8e93ad
Merge pull request #3163 from nesquena/fix-3162
nesquena-hermes May 30, 2026
f50763b
docs: clarify docker host and home paths
AJV20 May 30, 2026
7efb4c5
fix: scope skill toggles to active profile
AJV20 May 30, 2026
fbc0742
fix: ignore release tags already contained by head
AJV20 May 30, 2026
d032653
test(#3066): mark profile-skill tests requires_agent_modules (skill_u…
May 30, 2026
d37e57f
Merge pull request #3165 from nesquena/release/stage-batch51
nesquena-hermes May 30, 2026
5cb82f9
fix: make SSE replay cursors run-aware
AJV20 May 30, 2026
0fc38ce
Merge pull request #3167 from nesquena/release/stage-batch52
nesquena-hermes May 30, 2026
d34d118
fix: label tool output cards persistently
AJV20 May 30, 2026
a7c871d
feat: add Neon cyberpunk skin
hermes-agent May 30, 2026
5d73101
test: make .send-btn / .app-titlebar global-selector finders skin-var…
May 30, 2026
7dc4273
Merge pull request #3168 from nesquena/release/stage-batch53
nesquena-hermes May 30, 2026
1a99104
fix: use getModelLabel() in _formatSessionModelWithGateway fallback
mysoul12138 May 30, 2026
97dde9a
fix: restore legacy tool card visuals
ai-ag2026 May 30, 2026
b3483d9
fix: close evicted agents from WebUI cache
ai-ag2026 May 30, 2026
fb7fa5b
fix: handle Windows media and turn journal edge cases
ai-ag2026 May 30, 2026
000e1dc
fix: hash dirty WebUI dev builds
ai-ag2026 May 30, 2026
cb01e04
fix: preserve tilde workspace suggestions
ai-ag2026 May 30, 2026
09d2f4b
fix: exclude hidden snapshots from pin quota
ai-ag2026 May 30, 2026
d578548
fix: keep tool cards anchored during history paging
ai-ag2026 May 30, 2026
b891e4f
fix: avoid double rebasing legacy tool cards
ai-ag2026 May 30, 2026
4639d35
test: cover hidden snapshot pin quota route
ai-ag2026 May 30, 2026
71e6eab
fix: let cron sessions bypass CLI_VISIBLE_SESSION_LIMIT for project c…
mysoul12138 May 30, 2026
9932899
fix: guard session cache ownership across compression
ai-ag2026 May 30, 2026
9458df6
fix: dedupe sidebar completion session ids
ai-ag2026 May 30, 2026
141f27d
Merge branch 'pr-3188' into release/stage-batch54
May 30, 2026
637ae65
Merge branch 'pr-3182' into release/stage-batch54
May 30, 2026
9e48a2a
Merge branch 'pr-3183' into release/stage-batch54
May 30, 2026
cb193a9
docs(changelog): v0.51.172 release header (stage-batch54)
May 30, 2026
79145c0
Merge pull request #3198 from nesquena/release/stage-batch54
nesquena-hermes May 30, 2026
6d1ae11
Merge branch 'pr-3180' into release/stage-batch55
May 30, 2026
58aec3e
Merge branch 'pr-3184' into release/stage-batch55
May 30, 2026
db952ac
Merge branch 'pr-3187' into release/stage-batch55
May 30, 2026
91f33a5
Merge branch 'pr-3192' into release/stage-batch55
May 30, 2026
025dd73
Merge branch 'pr-3178' into release/stage-batch55
May 30, 2026
76d0528
docs(changelog): v0.51.173 release header (stage-batch55)
May 30, 2026
9f775d3
Merge pull request #3200 from nesquena/release/stage-batch55
nesquena-hermes May 30, 2026
d6c1b69
fix(reasoning): expose effort levels for bare/dot-separated model nam…
Carry00 May 30, 2026
1048d2c
feat: include CLI session usage in WebUI Insights
May 30, 2026
c26e254
fix: clarify sidebar session tooltips
ai-ag2026 May 30, 2026
06842f6
fix(insights): exclude source='webui' from CLI session pass + add tests
May 30, 2026
7ec16ba
docs(changelog): v0.51.174 release header (stage-batch56)
May 30, 2026
05122e2
Merge pull request #3204 from nesquena/release/stage-batch56
nesquena-hermes May 30, 2026
d3ee177
feat: add internal conversation links
ai-ag2026 May 30, 2026
ce40266
test: harden session link sanitization
ai-ag2026 May 30, 2026
8e44dc8
feat: resolve session links in conversation filter
ai-ag2026 May 30, 2026
9e38b0f
docs(changelog): v0.51.175 release header (stage-batch57)
May 30, 2026
d2aa066
feat: surface session attention badges
ai-ag2026 May 28, 2026
0560a3f
Merge pull request #3205 from nesquena/release/stage-batch57
nesquena-hermes May 30, 2026
00e6d95
feat: add distinct attention request sound
ai-ag2026 May 30, 2026
01c1239
refactor(sessions): simplify attention indicator to a color-coded dot
May 30, 2026
4ef544c
Merge branch 'pr-3190' into release/stage-batch58
May 30, 2026
f8f1052
Merge pull request #3206 from nesquena/release/stage-batch58
nesquena-hermes May 30, 2026
f4772ff
ci(docker): cache smoke-test image layers via GHA cache (#3197 docker…
May 30, 2026
113c979
Merge pull request #3207 from nesquena/release/stage-batch59
nesquena-hermes May 30, 2026
f9acf46
ci: run test suite in 3 parallel shards + make suite shard-safe
May 30, 2026
e41fee1
Merge pull request #3212 from nesquena/release/stage-batch60
nesquena-hermes May 30, 2026
2a60aa0
Merge #3202: reasoning effort for bare/dot-separated custom-provider …
May 30, 2026
5cd2aef
Merge #3203: clarify sidebar session tooltips
May 30, 2026
cceeca8
polish(#3203): keep localized attention tooltip precedence over gener…
May 30, 2026
d6d74b5
polish(#3203): preserve localized 'Forked from' base in fork tooltip
May 30, 2026
f50aac6
Merge pull request #3213 from nesquena/release/stage-batch61
nesquena-hermes May 30, 2026
bc50e95
Merge #3166: close evicted agents from WebUI cache (commit memory + s…
May 30, 2026
22e628b
Merge #3191: guard session cache ownership across compression
May 30, 2026
82f92eb
Merge pull request #3216 from nesquena/release/stage-batch62
nesquena-hermes May 30, 2026
6ecc32b
Close evicted cached agents on identity mismatch
AJV20 May 30, 2026
7607f3f
Merge #3218: route identity-mismatch agent-cache evictions through se…
May 31, 2026
5134d89
absorb #3201: set _streamFinalized immediately in SSE done handler (c…
May 31, 2026
634a70b
test(#3218): extend cache-eviction lock-discipline guard to the self-…
May 31, 2026
82fe933
Merge pull request #3221 from nesquena/release/stage-batchA
nesquena-hermes May 31, 2026
5b2cbe1
ci: add headless browser smoke test (runtime brick-class gate) (#3231)
nesquena-hermes May 31, 2026
5915d67
docs: add GitHub search report — upstream issues/PRs related to fork …
May 26, 2026
2cee44b
fix(helpers): catch client disconnect errors in response write path
python-king2 May 22, 2026
e531a05
fix(server): catch client disconnect errors in response write path
python-king2 May 26, 2026
59b7a3a
fix: eliminate silent failures in client disconnect handling
May 30, 2026
78652ec
fix: consolidate _CLIENT_DISCONNECT_ERRORS, remove scratch file
May 31, 2026
79f526b
fix(helpers): use ssl.SSLError instead of broad OSError in disconnect…
May 31, 2026
c4d845c
docs(CHANGELOG): v0.51.182 — consolidated client-disconnect handling …
May 31, 2026
dca4a2a
fix(#3210 review): convert bare urlopen TimeoutError to ValueError in…
May 31, 2026
0405fef
Merge pull request #3233 from nesquena/release/stage-batchB2
nesquena-hermes May 31, 2026
aae3b41
fix: render file artifact links as media
AJV20 May 31, 2026
63bb2f9
fix(security #3234): /api/media hard-denies WebUI state + secret/conf…
May 31, 2026
c36fda2
test: widen _handle_media CSP-slice window to 7000 after #3234 deny-l…
May 31, 2026
68a6099
fix(security #3234): harden /api/media deny-list (Codex review)
May 31, 2026
c514b32
fix(security #3234): cover ALL Hermes roots in /api/media deny-list (…
May 31, 2026
343bad7
fix(security #3234): redesign /api/media deny with active-workspace c…
May 31, 2026
26305c2
fix(security #3234): gate active-workspace carve-out against broad/in…
May 31, 2026
5758d4a
fix(security/#3234 + #3219): case-fold deny checks + make bare file:/…
May 31, 2026
4fa051e
fix(security/#3234 + #3219): unify case-folded path checks, fix works…
May 31, 2026
124044d
fix(security #3234): do not deny STATE_DIR wholesale — keep STATE_DIR…
May 31, 2026
ce7a2c1
fix(security #3234): enumerate named-profile roots, drop wholesale pr…
May 31, 2026
d1645ff
fix(security #3234): deny passkeys.json + .passkey_challenges.json + …
May 31, 2026
a62d35a
fix(security #3234): deny atomic-write temp auth/state files under He…
May 31, 2026
d3b69ab
fix(security #3234): deny per-profile webui_state state subdirs (Code…
May 31, 2026
83a45b6
Merge pull request #3240 from nesquena/release/stage-batchC
nesquena-hermes May 31, 2026
3b852bd
test: skip terminal cleanup collection on non-posix
zapabob May 31, 2026
6091428
fix: preserve scroll on CLI import refresh
andrewkangkr May 31, 2026
41a8b1d
feat: add raw audio upload mode — send audio as attachment instead of…
lucasrc May 28, 2026
f6b658c
fix: use _setButtonTooltipAndKey for mic tooltip to update data-i18n-…
lucasrc May 28, 2026
a1e7032
chore: remove stale plan files from previous branch
lucasrc May 28, 2026
6258afb
fix: tooltip conflict with RAW badge — use span instead of ::after
lucasrc May 28, 2026
5ebf984
fix: rename _updateMicBadge → _updateMicTooltip, use monkeypatch in t…
lucasrc May 28, 2026
038bf99
fix: _stopMic skips recognition.stop() when raw audio mode is active
lucasrc May 30, 2026
6a7e8a7
docs(CHANGELOG): v0.51.184 — raw audio mode (#3169) + scroll-preserve…
May 31, 2026
c74a019
fix(#3169): honor explicit Send-click (_micPendingSend) in raw-audio …
May 31, 2026
0cceb3b
fix(#3169): pin capture backend at mic start (_activeCaptureMode) — t…
May 31, 2026
13c7f71
Merge pull request #3244 from nesquena/release/stage-batchD
nesquena-hermes May 31, 2026
b570b7b
Merge tag 'v0.51.132' into sync/upstream-v0.51.132
Du7chManiac May 31, 2026
a3c17a9
Merge tag 'v0.51.184' into sync/upstream-v0.51.132
Du7chManiac May 31, 2026
1d2a336
ci(docker-smoke): use the fork image name + realize the layer cache
Du7chManiac May 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
42 changes: 42 additions & 0 deletions .github/workflows/browser-smoke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Browser smoke

# Headless page-load smoke: boots the real server.py (agent-free) and loads the
# key pages in Chromium, failing on any console error or uncaught JS exception.
# This catches the runtime-JS brick class (const-reassign, function/window
# collision) that `node --check`, ESLint, and the mocked pytest suite cannot
# see — they only manifest when a real browser executes the page.
#
# No secrets, no credentials: the server boots agent-free and the smoke script
# strips every *_API_KEY from the environment before launch.

on:
pull_request:
branches: [master]
push:
branches: [master]

jobs:
browser-smoke:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
cache-dependency-path: |
**/requirements*.txt
**/pyproject.toml

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install "pyyaml>=6.0" playwright
# Install only the Chromium browser + its system deps.
python -m playwright install --with-deps chromium

- name: Run browser smoke
run: python tests/browser_smoke.py
60 changes: 45 additions & 15 deletions .github/workflows/docker-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ name: Docker smoke
#
# Scope (intentionally small for v1):
# - 3 compose variants (single, two-container, three-container)
# - For multi-container variants, rebuild the local Dockerfile and re-tag
# it as ghcr.io/nesquena/hermes-webui:latest BEFORE `up` so the PR's
# changes to docker_init.bash / Dockerfile actually execute. Without this
# the multi-container variants would pull the previous release from GHCR
# - For multi-container variants, the image is built from the PR's local
# Dockerfile (via the build-image job + GHA layer cache) and tagged
# ghcr.io/thecouchcoder-com/hermes-webui:latest — the name those compose
# files reference — BEFORE `up`, so the PR's changes to
# docker_init.bash / Dockerfile actually execute. Without this the
# multi-container variants would pull the previous release from GHCR
# and silently miss every PR-level regression.
# - Pre-flight `docker compose config` job to catch schema/interpolation drift.
# - Reaper before each smoke run + trap on EXIT for orphan defence.
Expand Down Expand Up @@ -66,10 +68,31 @@ jobs:
echo "::endgroup::"
done

# Build the Docker image once and cache layers via GHA cache.
# The smoke matrix jobs then pull from this cache instead of rebuilding
# from scratch, saving ~1-3 minutes per variant.
build-image:
name: Build Docker image (cache layers)
runs-on: ubuntu-latest
needs: compose-config
steps:
- uses: actions/checkout@v4

- uses: docker/setup-buildx-action@v3

- name: Build and cache Docker image
uses: docker/build-push-action@v6
with:
context: .
load: true
tags: ghcr.io/thecouchcoder-com/hermes-webui:latest
cache-from: type=gha
cache-to: type=gha,mode=max

smoke:
name: Smoke ${{ matrix.variant }}
runs-on: ubuntu-latest
needs: compose-config
needs: [compose-config, build-image]
timeout-minutes: 15
strategy:
fail-fast: false
Expand All @@ -81,6 +104,23 @@ jobs:
steps:
- uses: actions/checkout@v4

- uses: docker/setup-buildx-action@v3

# Restore the cached Docker image from the build-image job.
# Read-only: the build-image job already populated the GHA cache, so the
# smoke variants only need cache-from (no redundant cache-to re-export).
# This builds and tags ghcr.io/thecouchcoder-com/hermes-webui:latest —
# the image the multi-container compose files reference — straight from
# the layer cache, so the PR's Dockerfile changes are exercised without a
# from-scratch rebuild on every variant.
- name: Restore Docker image from cache
uses: docker/build-push-action@v6
with:
context: .
load: true
tags: ghcr.io/thecouchcoder-com/hermes-webui:latest
cache-from: type=gha

- name: Resolve compose file + project name
id: vars
run: |
Expand Down Expand Up @@ -119,16 +159,6 @@ jobs:
docker network rm "$n" || true
done

- name: Build local Dockerfile
# We always build the local Dockerfile so the PR's changes are tested,
# even on the multi-container variants whose compose files reference
# ghcr.io/thecouchcoder-com/hermes-webui:latest. Without this retag,
# multi-container smoke runs would try to pull from GHCR (we don't
# publish a `:latest` tag) and fail before the PR's code is exercised.
run: |
set -euo pipefail
docker build -t ghcr.io/thecouchcoder-com/hermes-webui:latest .

- name: Prepare ephemeral host paths
id: paths
run: |
Expand Down
22 changes: 19 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,19 @@ jobs:
test:
runs-on: ubuntu-latest
strategy:
# Don't cancel the other shards/versions when one fails — we want the full
# failure picture across the matrix in a single run.
fail-fast: false
matrix:
python-version: ['3.11', '3.12', '3.13']
# Split the suite across 3 parallel shards per Python version. pytest-shard
# partitions tests deterministically by test-id hash; the suite was made
# shard-safe (no cross-test state leakage) so every shard passes
# independently. See docs/agent-memory note on test-suite shard-safety.
# NOTE: pytest-shard is 0-indexed — shard ids must be 0..num_shards-1.
# Using 1-based ids would crash the out-of-range job AND silently skip
# shard 0's tests.
shard: [0, 1, 2]

steps:
- uses: actions/checkout@v4
Expand All @@ -20,11 +31,16 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: |
**/setup.cfg
**/requirements*.txt
**/pyproject.toml

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install "pyyaml>=6.0" pytest pytest-timeout pytest-asyncio
pip install "pyyaml>=6.0" pytest pytest-timeout pytest-asyncio pytest-shard
# Install the `mcp` package so tests/test_mcp_server.py runs in CI.
# The package is an optional runtime dep of mcp_server.py — users
# who run the MCP integration install it themselves; CI installs
Expand All @@ -33,5 +49,5 @@ jobs:
# importorskip and the matrix stays green.
pip install mcp || echo "mcp install failed — test_mcp_server.py will importorskip"

- name: Run tests
run: pytest tests/ -v --timeout=60
- name: Run tests (shard ${{ matrix.shard }} of 3)
run: pytest tests/ -v --timeout=60 --shard-id=${{ matrix.shard }} --num-shards=3
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ graphify-out/
.graphify_uncached.txt

.venv/

# Dev-only lint tooling (ESLint runtime-error guard) — see TESTING.md
node_modules/
package-lock.json
4 changes: 4 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ Environment variables controlling behavior:
HERMES_WEBUI_DEFAULT_MODEL Optional model override; unset means provider default
HERMES_WEBUI_PASSWORD Optional: enable password auth (off by default)
HERMES_WEBUI_SKIP_ONBOARDING Optional: bypass the first-run onboarding wizard
HERMES_PREFILL_MESSAGES_FILE Optional JSON message list for browser-turn prefill context
HERMES_WEBUI_PREFILL_MESSAGES_SCRIPT Optional command that prints JSON messages or plain-text user prefill context
HERMES_WEBUI_PREFILL_MESSAGES_SCRIPT_TIMEOUT Optional script timeout in seconds (default 5, max 30)
HERMES_WEBUI_PREFILL_CONTEXT_MAX_CHARS Optional parsed prefill budget in characters (default 12000, 0 disables)
HERMES_HOME Base directory for Hermes state (~/.hermes by default)

Test isolation environment variables (set by conftest.py):
Expand Down
Loading
Loading