Repository navigation
feat: serverless executors and browser worker - #3
Merged
Merged
Conversation
Add RuntimeKind/RuntimeCapabilities/RuntimePlacement types, the optional effect_id/continuity_epoch/lease_secs/target_runtime_id/runtime_kinds task fields, and a builder `runtime` step option that emits params.$runtime. Replace NodeJS.Timeout with ReturnType<typeof setTimeout> in the worker. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NqczyJaTHD2CWHq3m6FAWU
createBrowserSession mints a short-lived browser worker token from the customer backend via POST /runtimes/browser-sessions; releaseTask wraps the new voluntary give-back endpoint. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NqczyJaTHD2CWHq3m6FAWU
…lpers Add @orch8.io/sdk/browser (exports subpath with a browser condition). Its module graph has no Node built-ins. BrowserWorker authenticates with a short-lived session token from the customer's backend, polls with kind=browser capabilities, heartbeats per lease_secs, completes/fails, releases in-flight tasks with keepalive fetch on pagehide/hidden, refreshes the token before expiry and stops when it lapses. The lease loop runs in a dedicated Web Worker (pre-bundled to a string, started from a Blob URL) while handlers run on the main thread with DOM access; it falls back to the main thread when workers are unavailable or blocked by CSP. check:browser bundles the entry with esbuild for platform=browser, fails on any node: reference, and runs the lease worker source in isolation. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NqczyJaTHD2CWHq3m6FAWU
Avoids a redundant getToken() round-trip when the engine starts before the token command arrives; the crash-recovery path reuses the same command. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NqczyJaTHD2CWHq3m6FAWU
jsdom + mocked fetch: poll capabilities, heartbeat cadence per lease_secs, 409 lease loss aborting the signal, keepalive release on pagehide/hidden, bfcache resume, unstarted-claim release, token refresh and expiry stop, 401 re-auth, exponential backoff, oversized output rejection, timeouts and no payloads in events. The Web Worker path runs the generated source in an isolated VM realm; staleness of the generated source is checked too. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NqczyJaTHD2CWHq3m6FAWU
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NqczyJaTHD2CWHq3m6FAWU
…down - WorkerConfig.capabilities advertises RuntimeCapabilities with each poll (runtime_id = workerId, kind default server, trust default registered, handlers default to the configured names, fresh observed_at/expires_at capped at five minutes), so Node workers can claim tasks with $runtime placement requirements. - Handlers get a WorkerTaskContext second argument with effectId, leaseSecs, continuityEpoch and workerId; the push runner passes it too. workerTaskContext() lives in internal/ so the push entry does not pull in the worker. - Claimed-but-unstarted tasks (a batch that lands after stop(), or tasks beyond free capacity, previously orphaned until lease expiry) are released with started: false; 404/405 from older servers is tolerated. - Heartbeat interval also honours each in-flight task's lease_secs. Verified: typecheck, vitest (242 tests, 8 new), npm run check:browser. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NqczyJaTHD2CWHq3m6FAWU
… completion A task released before its handler was invoked (pagehide fired as the tab received it) was reported as started: true and the handler still ran with an aborted signal. Mark the task started only when the handler is invoked, and never invoke it after a release, so the engine returns the task to pending immediately. A 413 from complete (output above the engine's browser output cap) left the claim held until lease expiry. Fail the step non-retryably with the engine's reason instead. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NqczyJaTHD2CWHq3m6FAWU
npm run test:e2e:browser runs a jsdom page (lease loop in main-thread mode; jsdom has no Worker) against a live engine over real fetch: happy path with page data and provenance, no-secrets dispatch and context filtering, token scope, tab close via release, token refresh and expiry, oversized output (client guard and engine 413), and CORS preflights. Skipped unless ORCH8_E2E_URL and ORCH8_E2E_ADMIN_KEY are set. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NqczyJaTHD2CWHq3m6FAWU
…tisement Orch8Client drew request ids from node:crypto, which kept it off Cloudflare Workers without nodejs_compat. It now uses the Web Crypto global and falls back to node:crypto lazily on Node 18. The worker's capability advertisement moves to internal/capabilities so other executors build the same payload. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EEPZNNP6CHDVjcDw3W92W5
@orch8.io/sdk/serverless claims up to maxTasks through the existing worker lease API, runs them concurrently with heartbeats, and releases every lease still held at deadlineMs - releaseMarginMs (started: true). A claim whose timeout_ms cannot fit the budget is released started: false, and a result that arrives after its release is never acknowledged. createLambdaExecutor budgets from getRemainingTimeInMillis() minus a safety margin; createCloudflareExecutor offers scheduled and a secret-guarded fetch trigger, using fetch only. The entry bundles without Node built-ins. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EEPZNNP6CHDVjcDw3W92W5
README section and examples for Lambda (with a SAM template), Cloudflare Workers (with wrangler.toml) and a plain drainOnce script, plus docs/browser-executor.md covering targeting, lifecycle and security for steps that run in the user's tab. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EEPZNNP6CHDVjcDw3W92W5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Includes the BrowserWorker branch. Adds @orch8.io/sdk/serverless: drainOnce with deadline-aware lease release, AWS Lambda and Cloudflare Workers adapters, examples and docs; the client now uses Web Crypto so it runs on Workers without nodejs_compat.
Checks: typecheck, build, check:browser, pnpm test.
https://claude.ai/code/session_01EEPZNNP6CHDVjcDw3W92W5