hermes: recover expired dashboard sessions
All checks were successful
Tests / Declarative: Post Actions passed: 229
All checks were successful
Tests / Declarative: Post Actions passed: 229
This commit is contained in:
parent
fce7fd5415
commit
55f5d52544
@ -20,6 +20,74 @@ RUN uv pip install --python /opt/hermes/.venv/bin/python ddgs==9.14.4
|
|||||||
# reconnects to that same conversation must keep using the same key.
|
# reconnects to that same conversation must keep using the same key.
|
||||||
RUN node <<'NODE'
|
RUN node <<'NODE'
|
||||||
const fs = require("node:fs");
|
const fs = require("node:fs");
|
||||||
|
const apiPath = "/opt/hermes/web/src/lib/api.ts";
|
||||||
|
let apiSource = fs.readFileSync(apiPath, "utf8");
|
||||||
|
const sessionHeaderBefore = [
|
||||||
|
'function setSessionHeader(headers: Headers, token: string): void {',
|
||||||
|
' if (!headers.has(SESSION_HEADER)) {',
|
||||||
|
' headers.set(SESSION_HEADER, token);',
|
||||||
|
' }',
|
||||||
|
'}',
|
||||||
|
].join("\n");
|
||||||
|
const sessionHeaderAfter = [
|
||||||
|
sessionHeaderBefore,
|
||||||
|
'',
|
||||||
|
'/**',
|
||||||
|
' * Recover an expired outer OAuth2 Proxy session without losing the SPA route.',
|
||||||
|
' * Background fetch redirects cannot complete an OIDC browser flow, so API',
|
||||||
|
' * routes deliberately return 401 and the dashboard performs this top-level',
|
||||||
|
' * navigation once instead.',
|
||||||
|
' */',
|
||||||
|
'function redirectToProxyLogin<T>(): Promise<T> {',
|
||||||
|
' const rd =',
|
||||||
|
' window.location.pathname + window.location.search + window.location.hash;',
|
||||||
|
' try {',
|
||||||
|
' sessionStorage.setItem("hermes.lastLocation", rd);',
|
||||||
|
' } catch {',
|
||||||
|
' /* privacy mode — the rd query parameter remains authoritative */',
|
||||||
|
' }',
|
||||||
|
' window.location.assign(',
|
||||||
|
' `${BASE}/oauth2/start?rd=${encodeURIComponent(rd)}`,',
|
||||||
|
' );',
|
||||||
|
' return new Promise<T>(() => {});',
|
||||||
|
'}',
|
||||||
|
].join("\n");
|
||||||
|
const plainUnauthorizedBefore = [
|
||||||
|
' if (!window.__HERMES_AUTH_REQUIRED__ && !options?.allowUnauthorized) {',
|
||||||
|
].join("\n");
|
||||||
|
const plainUnauthorizedAfter = [
|
||||||
|
' // OAuth2 Proxy API routes intentionally return a plain 401 when its',
|
||||||
|
' // session expires. A background fetch cannot complete OIDC, so promote',
|
||||||
|
' // it to a top-level navigation and return to this exact dashboard route.',
|
||||||
|
' if (window.__HERMES_AUTH_REQUIRED__ && !options?.allowUnauthorized) {',
|
||||||
|
' return redirectToProxyLogin<T>();',
|
||||||
|
' }',
|
||||||
|
'',
|
||||||
|
plainUnauthorizedBefore,
|
||||||
|
].join("\n");
|
||||||
|
const ticketFailureBefore = [
|
||||||
|
' if (!res.ok) {',
|
||||||
|
' throw new Error(`/api/auth/ws-ticket: HTTP ${res.status}`);',
|
||||||
|
' }',
|
||||||
|
].join("\n");
|
||||||
|
const ticketFailureAfter = [
|
||||||
|
' if (res.status === 401) {',
|
||||||
|
' return redirectToProxyLogin<{ ticket: string; ttl_seconds: number }>();',
|
||||||
|
' }',
|
||||||
|
ticketFailureBefore,
|
||||||
|
].join("\n");
|
||||||
|
for (const [before, after, label] of [
|
||||||
|
[sessionHeaderBefore, sessionHeaderAfter, "proxy login helper"],
|
||||||
|
[plainUnauthorizedBefore, plainUnauthorizedAfter, "plain 401 recovery"],
|
||||||
|
[ticketFailureBefore, ticketFailureAfter, "ticket 401 recovery"],
|
||||||
|
]) {
|
||||||
|
if (!apiSource.includes(before)) {
|
||||||
|
throw new Error(`Hermes API ${label} patch context changed`);
|
||||||
|
}
|
||||||
|
apiSource = apiSource.replace(before, after);
|
||||||
|
}
|
||||||
|
fs.writeFileSync(apiPath, apiSource);
|
||||||
|
|
||||||
const path = "/opt/hermes/web/src/pages/ChatPage.tsx";
|
const path = "/opt/hermes/web/src/pages/ChatPage.tsx";
|
||||||
let source = fs.readFileSync(path, "utf8");
|
let source = fs.readFileSync(path, "utf8");
|
||||||
const socketBefore = [
|
const socketBefore = [
|
||||||
@ -512,6 +580,8 @@ RUN cd /opt/hermes/web \
|
|||||||
&& grep -Fq 'resume:${resumeParam}' src/pages/ChatPage.tsx \
|
&& grep -Fq 'resume:${resumeParam}' src/pages/ChatPage.tsx \
|
||||||
&& grep -Fq 'eventsRetryAttempt.current' src/components/ChatSidebar.tsx \
|
&& grep -Fq 'eventsRetryAttempt.current' src/components/ChatSidebar.tsx \
|
||||||
&& grep -Fq 'reconnecting…' src/components/ChatSidebar.tsx \
|
&& grep -Fq 'reconnecting…' src/components/ChatSidebar.tsx \
|
||||||
|
&& grep -Fq 'redirectToProxyLogin' src/lib/api.ts \
|
||||||
|
&& grep -Fq '/oauth2/start?rd=' src/lib/api.ts \
|
||||||
&& grep -Fq 'HERMES_DASHBOARD_OIDC_ALLOWED_USER_IDS' \
|
&& grep -Fq 'HERMES_DASHBOARD_OIDC_ALLOWED_USER_IDS' \
|
||||||
/opt/hermes/hermes_cli/dashboard_auth/middleware.py \
|
/opt/hermes/hermes_cli/dashboard_auth/middleware.py \
|
||||||
&& grep -Fq '_resolve_request_route' \
|
&& grep -Fq '_resolve_request_route' \
|
||||||
|
|||||||
@ -179,7 +179,7 @@ spec:
|
|||||||
requests: {cpu: 25m, memory: 32Mi}
|
requests: {cpu: 25m, memory: 32Mi}
|
||||||
limits: {cpu: 100m, memory: 64Mi}
|
limits: {cpu: 100m, memory: 64Mi}
|
||||||
- name: install-agent-tools
|
- name: install-agent-tools
|
||||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
|
image: registry.bstein.dev/bstein/hermes-agent@sha256:222b507ba8d45dd5acb7a33158341fd728b8255b3afae49a74044eaf9029bd1d
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
command:
|
command:
|
||||||
- sh
|
- sh
|
||||||
@ -227,7 +227,7 @@ spec:
|
|||||||
requests: {cpu: 100m, memory: 256Mi}
|
requests: {cpu: 100m, memory: 256Mi}
|
||||||
limits: {cpu: "1", memory: 1Gi}
|
limits: {cpu: "1", memory: 1Gi}
|
||||||
- name: patch-auth
|
- name: patch-auth
|
||||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
|
image: registry.bstein.dev/bstein/hermes-agent@sha256:222b507ba8d45dd5acb7a33158341fd728b8255b3afae49a74044eaf9029bd1d
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
command:
|
command:
|
||||||
- /opt/hermes/.venv/bin/python
|
- /opt/hermes/.venv/bin/python
|
||||||
@ -250,7 +250,7 @@ spec:
|
|||||||
requests: {cpu: 25m, memory: 64Mi}
|
requests: {cpu: 25m, memory: 64Mi}
|
||||||
limits: {cpu: 100m, memory: 128Mi}
|
limits: {cpu: 100m, memory: 128Mi}
|
||||||
- name: patch-tui-gateway
|
- name: patch-tui-gateway
|
||||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
|
image: registry.bstein.dev/bstein/hermes-agent@sha256:222b507ba8d45dd5acb7a33158341fd728b8255b3afae49a74044eaf9029bd1d
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
command:
|
command:
|
||||||
- /opt/hermes/.venv/bin/python
|
- /opt/hermes/.venv/bin/python
|
||||||
@ -273,7 +273,7 @@ spec:
|
|||||||
requests: {cpu: 25m, memory: 64Mi}
|
requests: {cpu: 25m, memory: 64Mi}
|
||||||
limits: {cpu: 100m, memory: 128Mi}
|
limits: {cpu: 100m, memory: 128Mi}
|
||||||
- name: patch-codex-runtime
|
- name: patch-codex-runtime
|
||||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
|
image: registry.bstein.dev/bstein/hermes-agent@sha256:222b507ba8d45dd5acb7a33158341fd728b8255b3afae49a74044eaf9029bd1d
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
command:
|
command:
|
||||||
- /opt/hermes/.venv/bin/python
|
- /opt/hermes/.venv/bin/python
|
||||||
@ -306,7 +306,7 @@ spec:
|
|||||||
requests: {cpu: 25m, memory: 64Mi}
|
requests: {cpu: 25m, memory: 64Mi}
|
||||||
limits: {cpu: 100m, memory: 128Mi}
|
limits: {cpu: 100m, memory: 128Mi}
|
||||||
- name: bootstrap-coordinator
|
- name: bootstrap-coordinator
|
||||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
|
image: registry.bstein.dev/bstein/hermes-agent@sha256:222b507ba8d45dd5acb7a33158341fd728b8255b3afae49a74044eaf9029bd1d
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
command:
|
command:
|
||||||
- /opt/hermes/.venv/bin/python
|
- /opt/hermes/.venv/bin/python
|
||||||
@ -335,7 +335,7 @@ spec:
|
|||||||
requests: {cpu: 50m, memory: 128Mi}
|
requests: {cpu: 50m, memory: 128Mi}
|
||||||
limits: {cpu: 500m, memory: 512Mi}
|
limits: {cpu: 500m, memory: 512Mi}
|
||||||
- name: configure-agent-clients
|
- name: configure-agent-clients
|
||||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
|
image: registry.bstein.dev/bstein/hermes-agent@sha256:222b507ba8d45dd5acb7a33158341fd728b8255b3afae49a74044eaf9029bd1d
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
command:
|
command:
|
||||||
- sh
|
- sh
|
||||||
@ -373,7 +373,7 @@ spec:
|
|||||||
requests: {cpu: 25m, memory: 32Mi}
|
requests: {cpu: 25m, memory: 32Mi}
|
||||||
limits: {cpu: 250m, memory: 128Mi}
|
limits: {cpu: 250m, memory: 128Mi}
|
||||||
- name: prepare-ttyd-index
|
- name: prepare-ttyd-index
|
||||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
|
image: registry.bstein.dev/bstein/hermes-agent@sha256:222b507ba8d45dd5acb7a33158341fd728b8255b3afae49a74044eaf9029bd1d
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
command:
|
command:
|
||||||
- /opt/hermes/.venv/bin/python
|
- /opt/hermes/.venv/bin/python
|
||||||
@ -395,7 +395,7 @@ spec:
|
|||||||
limits: {cpu: 250m, memory: 128Mi}
|
limits: {cpu: 250m, memory: 128Mi}
|
||||||
containers:
|
containers:
|
||||||
- name: hermes
|
- name: hermes
|
||||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
|
image: registry.bstein.dev/bstein/hermes-agent@sha256:222b507ba8d45dd5acb7a33158341fd728b8255b3afae49a74044eaf9029bd1d
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
command: [/init, /opt/hermes/docker/main-wrapper.sh]
|
command: [/init, /opt/hermes/docker/main-wrapper.sh]
|
||||||
args: [gateway, run]
|
args: [gateway, run]
|
||||||
@ -503,6 +503,7 @@ spec:
|
|||||||
- --http-address=0.0.0.0:4180
|
- --http-address=0.0.0.0:4180
|
||||||
- --skip-provider-button=true
|
- --skip-provider-button=true
|
||||||
- --reverse-proxy=true
|
- --reverse-proxy=true
|
||||||
|
- --api-route=^/api/
|
||||||
- --trusted-proxy-ip=10.42.0.0/16
|
- --trusted-proxy-ip=10.42.0.0/16
|
||||||
ports:
|
ports:
|
||||||
- {name: auth-http, containerPort: 4180, protocol: TCP}
|
- {name: auth-http, containerPort: 4180, protocol: TCP}
|
||||||
@ -529,7 +530,7 @@ spec:
|
|||||||
- {name: allowlist, mountPath: /etc/oauth2-proxy, readOnly: true}
|
- {name: allowlist, mountPath: /etc/oauth2-proxy, readOnly: true}
|
||||||
- {name: oauth-tmp, mountPath: /tmp}
|
- {name: oauth-tmp, mountPath: /tmp}
|
||||||
- name: terminal
|
- name: terminal
|
||||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
|
image: registry.bstein.dev/bstein/hermes-agent@sha256:222b507ba8d45dd5acb7a33158341fd728b8255b3afae49a74044eaf9029bd1d
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
command: [/bin/sh, -ec]
|
command: [/bin/sh, -ec]
|
||||||
args:
|
args:
|
||||||
@ -622,7 +623,7 @@ spec:
|
|||||||
requests: {cpu: 25m, memory: 64Mi}
|
requests: {cpu: 25m, memory: 64Mi}
|
||||||
limits: {cpu: 500m, memory: 512Mi}
|
limits: {cpu: 500m, memory: 512Mi}
|
||||||
- name: cli-lane-runner
|
- name: cli-lane-runner
|
||||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
|
image: registry.bstein.dev/bstein/hermes-agent@sha256:222b507ba8d45dd5acb7a33158341fd728b8255b3afae49a74044eaf9029bd1d
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
command: [/bin/sh, -ec]
|
command: [/bin/sh, -ec]
|
||||||
args:
|
args:
|
||||||
@ -663,7 +664,7 @@ spec:
|
|||||||
requests: {cpu: 100m, memory: 256Mi}
|
requests: {cpu: 100m, memory: 256Mi}
|
||||||
limits: {cpu: "3", memory: 6Gi}
|
limits: {cpu: "3", memory: 6Gi}
|
||||||
- name: model-steward
|
- name: model-steward
|
||||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
|
image: registry.bstein.dev/bstein/hermes-agent@sha256:222b507ba8d45dd5acb7a33158341fd728b8255b3afae49a74044eaf9029bd1d
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
command: [/opt/hermes/.venv/bin/python, /opt/coordinator/hermes_coordinator.py, --loop, --interval, "3600"]
|
command: [/opt/hermes/.venv/bin/python, /opt/coordinator/hermes_coordinator.py, --loop, --interval, "3600"]
|
||||||
env:
|
env:
|
||||||
@ -689,7 +690,7 @@ spec:
|
|||||||
requests: {cpu: 25m, memory: 64Mi}
|
requests: {cpu: 25m, memory: 64Mi}
|
||||||
limits: {cpu: 250m, memory: 512Mi}
|
limits: {cpu: 250m, memory: 512Mi}
|
||||||
- name: image-broker
|
- name: image-broker
|
||||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
|
image: registry.bstein.dev/bstein/hermes-agent@sha256:222b507ba8d45dd5acb7a33158341fd728b8255b3afae49a74044eaf9029bd1d
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
command: [/bin/sh, -ec]
|
command: [/bin/sh, -ec]
|
||||||
args:
|
args:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user