* Build a tiny inline script that seeds runtime config into the page. * * - `sessionApiKey`: exposed to the app two ways so a fresh-localStorage * browser can authenticate even though the published bundle has no * VITE_SESSION_API_KEY baked in: * 1. `window.__AGENT_CANVAS_SESSION_API_KE
( sessionApiKey, authRequired, runtimeServicesInfo, lockToCloud, basePath, )
| 270 | * files can resolve through the same subpath as the built bundle. |
| 271 | */ |
| 272 | function makeConfigInjectionScript( |
| 273 | sessionApiKey, |
| 274 | authRequired, |
| 275 | runtimeServicesInfo, |
| 276 | lockToCloud, |
| 277 | basePath, |
| 278 | ) { |
| 279 | const parts = []; |
| 280 | |
| 281 | if (sessionApiKey) { |
| 282 | const keyLiteral = JSON.stringify(sessionApiKey); |
| 283 | // Window global — read at module init by getBakedSessionApiKey(). |
| 284 | // Set first so it's available even if the localStorage write throws. |
| 285 | parts.push(`window.__AGENT_CANVAS_SESSION_API_KEY__=${keyLiteral};`); |
| 286 | // Always overwrite when the stored key differs from the runtime key. |
| 287 | // A previous session may have persisted a now-stale key; the runtime |
| 288 | // value (from --session-api-key) is the server's truth. |
| 289 | parts.push( |
| 290 | `try{` + |
| 291 | `var _k='openhands-agent-server-config',` + |
| 292 | `_c=JSON.parse(localStorage.getItem(_k)||'{}');` + |
| 293 | `if(_c.sessionApiKey!==${keyLiteral}){` + |
| 294 | `_c.sessionApiKey=${keyLiteral};` + |
| 295 | `localStorage.setItem(_k,JSON.stringify(_c));` + |
| 296 | `}` + |
| 297 | `}catch(e){}`, |
| 298 | ); |
| 299 | } |
| 300 | |
| 301 | if (authRequired) { |
| 302 | parts.push(`window.__AGENT_CANVAS_AUTH_REQUIRED__=true;`); |
| 303 | } |
| 304 | |
| 305 | if (runtimeServicesInfo) { |
| 306 | // Stored as the raw JSON string so the browser-side parser |
| 307 | // (parseRuntimeServicesInfo) can JSON.parse it exactly like the |
| 308 | // VITE_RUNTIME_SERVICES_INFO env var. JSON.stringify produces a safe JS |
| 309 | // string literal for the inline <script>. |
| 310 | parts.push( |
| 311 | `window.__AGENT_CANVAS_RUNTIME_SERVICES_INFO__=${JSON.stringify(runtimeServicesInfo)};`, |
| 312 | ); |
| 313 | } |
| 314 | |
| 315 | if (lockToCloud) { |
| 316 | parts.push( |
| 317 | `window.__AGENT_CANVAS_LOCK_TO_CLOUD__=${JSON.stringify(lockToCloud)};`, |
| 318 | ); |
| 319 | } |
| 320 | |
| 321 | if (basePath && basePath !== "/") { |
| 322 | parts.push( |
| 323 | `window.__AGENT_CANVAS_BASE_PATH__=${JSON.stringify(basePath)};`, |
| 324 | ); |
| 325 | } |
| 326 | |
| 327 | if (parts.length === 0) return ""; |
| 328 | |
| 329 | return `<script>(function(){${parts.join("")}}());</script>`; |
no outgoing calls
no test coverage detected