mirror of
https://github.com/vercel/eve.git
synced 2026-09-20 05:35:39 +08:00
710 lines
27 KiB
HTML
710 lines
27 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
<title>eve · Session network hops</title>
|
|
<style>
|
|
:root {
|
|
color-scheme: light dark;
|
|
font-family: ui-sans-serif, system-ui, sans-serif;
|
|
background: #111;
|
|
color: #eee;
|
|
}
|
|
body {
|
|
max-width: 1250px;
|
|
margin: auto;
|
|
padding: 44px 28px;
|
|
}
|
|
h1 {
|
|
font-size: 36px;
|
|
letter-spacing: -1.5px;
|
|
margin: 12px 0;
|
|
}
|
|
h2 {
|
|
font-size: 19px;
|
|
margin-top: 32px;
|
|
}
|
|
p {
|
|
max-width: 930px;
|
|
line-height: 1.6;
|
|
color: #aaa;
|
|
}
|
|
code {
|
|
font-family: ui-monospace, monospace;
|
|
font-size: 12px;
|
|
}
|
|
header > small {
|
|
color: #76d7ca;
|
|
letter-spacing: 2px;
|
|
}
|
|
nav {
|
|
position: sticky;
|
|
top: 0;
|
|
background: #111e;
|
|
padding: 16px 0;
|
|
display: flex;
|
|
gap: 18px;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
border-bottom: 1px solid #333;
|
|
}
|
|
select,
|
|
button {
|
|
background: #222;
|
|
color: #eee;
|
|
border: 1px solid #555;
|
|
border-radius: 6px;
|
|
padding: 9px;
|
|
}
|
|
label {
|
|
font-size: 13px;
|
|
}
|
|
.cards {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 14px;
|
|
margin: 25px 0;
|
|
}
|
|
.card {
|
|
border: 1px solid #333;
|
|
border-radius: 10px;
|
|
padding: 20px;
|
|
}
|
|
.card strong {
|
|
display: block;
|
|
font-size: 20px;
|
|
margin-bottom: 8px;
|
|
}
|
|
.card span {
|
|
color: #aaa;
|
|
font-size: 13px;
|
|
}
|
|
#chain {
|
|
background: #192724;
|
|
padding: 18px;
|
|
border-radius: 8px;
|
|
line-height: 1.9;
|
|
font-size: 14px;
|
|
}
|
|
table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-top: 16px;
|
|
font-size: 13px;
|
|
}
|
|
th {
|
|
text-align: left;
|
|
color: #aaa;
|
|
font-weight: 500;
|
|
}
|
|
td,
|
|
th {
|
|
border-bottom: 1px solid #303030;
|
|
padding: 15px 12px;
|
|
vertical-align: top;
|
|
}
|
|
td:first-child {
|
|
width: 27%;
|
|
}
|
|
td:nth-child(2) {
|
|
width: 24%;
|
|
color: #b5d9d3;
|
|
}
|
|
summary {
|
|
cursor: pointer;
|
|
line-height: 1.5;
|
|
}
|
|
details p {
|
|
margin: 10px 0;
|
|
font-size: 13px;
|
|
}
|
|
small.lane {
|
|
display: block;
|
|
color: #999;
|
|
margin-top: 7px;
|
|
}
|
|
.response {
|
|
color: #cbb0ff;
|
|
}
|
|
.background {
|
|
color: #d8be84;
|
|
}
|
|
.observer {
|
|
color: #97c3e8;
|
|
}
|
|
.conditional {
|
|
color: #aaa;
|
|
}
|
|
footer {
|
|
margin-top: 35px;
|
|
border-top: 1px solid #333;
|
|
padding-top: 16px;
|
|
}
|
|
li {
|
|
color: #bbb;
|
|
line-height: 1.7;
|
|
}
|
|
a {
|
|
color: #76d7ca;
|
|
}
|
|
@media (max-width: 700px) {
|
|
body {
|
|
padding: 20px 12px;
|
|
}
|
|
.cards {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
td,
|
|
th {
|
|
padding: 12px 5px;
|
|
}
|
|
h1 {
|
|
font-size: 29px;
|
|
}
|
|
}
|
|
@media print {
|
|
nav,
|
|
button {
|
|
display: none;
|
|
}
|
|
body {
|
|
background: white;
|
|
color: black;
|
|
}
|
|
details {
|
|
display: block;
|
|
}
|
|
}
|
|
</style>
|
|
<header>
|
|
<small>eve / RUNTIME AUDIT / 2026-09-11</small>
|
|
<h1>One inbox. Resume first.</h1>
|
|
<p>
|
|
The path from a request to the first model call, with post-acceptance identity resolution and
|
|
optional infrastructure shown separately. This is a source-derived map, not measured latency.
|
|
</p>
|
|
</header>
|
|
<div class="cards">
|
|
<div class="card">
|
|
<strong>1 eve inbox + aliases</strong
|
|
><span
|
|
>Also 1 SDK cancellation hook per new turn. No eager authorization, workflow-reply, or
|
|
anchor hook.</span
|
|
>
|
|
</div>
|
|
<div class="card">
|
|
<strong>0 eve send preflights</strong
|
|
><span
|
|
>The SDK still looks up the token inside resumeHook. Known-session sends never hydrate hook
|
|
metadata.</span
|
|
>
|
|
</div>
|
|
<div class="card">
|
|
<strong>3 separate clocks</strong
|
|
><span
|
|
>First model request · dispatch response · visible turn settlement. These are not
|
|
interchangeable.</span
|
|
>
|
|
</div>
|
|
</div>
|
|
<nav>
|
|
<label
|
|
>Path
|
|
<select id="mode">
|
|
<option value="stable">Existing session ID</option>
|
|
<option value="alias">Existing continuation alias</option>
|
|
<option value="new">New session</option>
|
|
<option value="handoff">Idle deployment handoff</option>
|
|
</select></label
|
|
>
|
|
<label
|
|
><input id="extra" type="checkbox" checked /> Show response, observer, and conditional
|
|
work</label
|
|
><button id="download">Download hop data</button><button id="print">Print</button>
|
|
</nav>
|
|
<h2>Critical dependency chain</h2>
|
|
<div id="chain"></div>
|
|
<p>
|
|
Rows are logical operations, not a single serial waterfall. Startup claims are concurrent; timer
|
|
startup overlaps the first turn. Cold replay, retained-VM execution, SDK preloads, and
|
|
stream-key caches change the physical requests. Expand a row for its justification and source.
|
|
</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Operation</th>
|
|
<th>Network work / durable operations</th>
|
|
<th>Why it exists</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="rows"></tbody>
|
|
</table>
|
|
<h2>Identity and the remaining SDK boundary</h2>
|
|
<p>
|
|
<code>sessionId = anchorRunId</code> identifies the original stream-owning run.
|
|
<code>hook.runId = ownerRunId</code> identifies the current executor. Hook metadata stores only
|
|
<code>{ sessionId }</code>. Reading metadata is explicit and lazy, after resume acceptance. A
|
|
random named stream still needs its owning run ID.
|
|
</p>
|
|
<h2>What this map does not claim</h2>
|
|
<ul id="limits"></ul>
|
|
<footer>
|
|
<p id="version"></p>
|
|
<p>
|
|
The earlier Downloads map describes the holder architecture. This map has no child turn
|
|
workflow or per-turn snapshot-stream round trip. Its companion JSON is the same data embedded
|
|
here.
|
|
</p>
|
|
</footer>
|
|
<script id="data" type="application/json">
|
|
{
|
|
"title": "eve session network hops",
|
|
"captured": "2026-09-11",
|
|
"baseCommit": "adb6beff622b274970d4e48b7178b7d44c11d456",
|
|
"workingTree": true,
|
|
"sdk": "@workflow/core 5.0.0-beta.50",
|
|
"evidence": "Source-derived operation inventory, not a latency benchmark. World, cache, replay, payload size, and authored integrations change request counts.",
|
|
"clocks": [
|
|
"HTTP request to first provider request",
|
|
"HTTP request to dispatch acceptance / returned Session identity",
|
|
"HTTP request to visible turn settlement"
|
|
],
|
|
"invariants": {
|
|
"sessionId": "original stream-owning run ID",
|
|
"ownerRunId": "current executor; changes on handoff",
|
|
"metadata": "{ sessionId }, accessed only when requested after resumption",
|
|
"startupHooks": "1 eve stable inbox + requested aliases + 1 SDK cancellation hook for the first turn"
|
|
},
|
|
"limitations": [
|
|
"Alias-only delivery cannot distinguish an unowned address from a handoff gap. Atomic handoff is an upstream requirement.",
|
|
"Rows name SDK operations, not a guaranteed count of lower-level HTTP retries or queue deliveries.",
|
|
"Authorization, sandbox, memory, telemetry and authored hooks must be measured for a specific deployed agent."
|
|
],
|
|
"rows": [
|
|
{
|
|
"id": "ingress",
|
|
"title": "HTTP request + request authorization",
|
|
"modes": ["new", "stable", "alias", "handoff"],
|
|
"lane": "critical",
|
|
"operations": "1 HTTP request; auth-dependent I/O",
|
|
"why": "Authenticate and authorize the resource before delivery. Auth provider/cache costs are application dependent.",
|
|
"source": {
|
|
"path": "packages/eve/src/channel/channel-address.ts",
|
|
"symbol": "createChannelAddress"
|
|
}
|
|
},
|
|
{
|
|
"id": "lookup",
|
|
"title": "SDK hook lookup",
|
|
"modes": ["stable", "alias", "handoff"],
|
|
"lane": "critical",
|
|
"operations": "1 hooks.getByToken",
|
|
"why": "resumeHook(token, command) resolves the live hook and its resume context. No eve preflight; no metadata hydration.",
|
|
"source": {
|
|
"path": "packages/eve/node_modules/@workflow/core/dist/runtime/resume-hook.js",
|
|
"symbol": "async function resumeHookImpl"
|
|
}
|
|
},
|
|
{
|
|
"id": "missing",
|
|
"title": "Try alias before creating",
|
|
"modes": ["new"],
|
|
"lane": "conditional",
|
|
"operations": "0 for ID-only; 1 hooks.getByToken for an unowned alias",
|
|
"why": "An ID-only create goes straight to start. A missing channel alias starts a candidate immediately; an ambiguous failure does not.",
|
|
"source": {
|
|
"path": "packages/eve/src/channel/channel-address.ts",
|
|
"symbol": "const existing = await dispatch()"
|
|
}
|
|
},
|
|
{
|
|
"id": "key",
|
|
"title": "Resume payload encryption",
|
|
"modes": ["stable", "alias", "handoff"],
|
|
"lane": "conditional",
|
|
"operations": "0 with stored public key; key/run reads on SDK fallback",
|
|
"why": "Current hooks carry resume context. Sealing to the public key is local; this is distinct from decrypting metadata.",
|
|
"source": {
|
|
"path": "packages/eve/node_modules/@workflow/core/dist/runtime/resume-hook.js",
|
|
"symbol": "async function resolveHookEncryptionKey"
|
|
}
|
|
},
|
|
{
|
|
"id": "receive",
|
|
"title": "Durably accept payload",
|
|
"modes": ["stable", "alias", "handoff"],
|
|
"lane": "critical",
|
|
"operations": "1 hook_received event write",
|
|
"why": "Commit the command before publishing its wake. Backend retry/dedup capabilities control transport retries.",
|
|
"source": {
|
|
"path": "packages/eve/node_modules/@workflow/core/dist/runtime/resume-hook.js",
|
|
"symbol": "async function resumeHookImpl"
|
|
}
|
|
},
|
|
{
|
|
"id": "wake",
|
|
"title": "Publish owner wake",
|
|
"modes": ["stable", "alias", "handoff"],
|
|
"lane": "critical",
|
|
"operations": "1 queue publish",
|
|
"why": "Targets the current owner on its pinned deployment; acceptance requires the durable write and publish.",
|
|
"source": {
|
|
"path": "packages/eve/node_modules/@workflow/core/dist/runtime/resume-hook.js",
|
|
"symbol": "async function resumeHookImpl"
|
|
}
|
|
},
|
|
{
|
|
"id": "identity",
|
|
"title": "Return stable identity to alias caller",
|
|
"modes": ["alias", "handoff"],
|
|
"lane": "response",
|
|
"operations": "0 hook reads; lazy metadata key access as needed",
|
|
"why": "Runs AFTER resume acceptance, concurrent with the awakened workflow. Known session addresses and forwarding-only senders do not access metadata.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/session-inbox/resume.ts",
|
|
"symbol": "get sessionId()"
|
|
}
|
|
},
|
|
{
|
|
"id": "start",
|
|
"title": "Start original session workflow",
|
|
"modes": ["new"],
|
|
"lane": "critical",
|
|
"operations": "run_created + queue publish",
|
|
"why": "One session workflow, no child turn workflow. SDK start may overlap publication and persistence.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/workflow-runtime.ts",
|
|
"symbol": "async createSession"
|
|
}
|
|
},
|
|
{
|
|
"id": "activation",
|
|
"title": "Workflow activation / event history",
|
|
"modes": ["new", "stable", "alias", "handoff"],
|
|
"lane": "critical",
|
|
"operations": "run lifecycle writes + history reads, capability/replay dependent",
|
|
"why": "Queue delivery is a compute hop, not an extra producer HTTP call. Retained VM and preload paths differ from cold replay.",
|
|
"source": {
|
|
"path": "packages/eve/node_modules/@workflow/core/dist/runtime/suspension-handler.js",
|
|
"symbol": "handleSuspension"
|
|
}
|
|
},
|
|
{
|
|
"id": "claims",
|
|
"title": "Register stable inbox and initial alias",
|
|
"modes": ["new"],
|
|
"lane": "critical",
|
|
"operations": "1 hook_created per address; one concurrent claim batch",
|
|
"why": "One stable address, plus the requested alias. getConflict is a registration fence preventing duplicate first-turn execution, not hooks.getByToken.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/session/entry.ts",
|
|
"symbol": "const [sessionCreation"
|
|
}
|
|
},
|
|
{
|
|
"id": "state",
|
|
"title": "Initialize or restore session state",
|
|
"modes": ["new", "stable", "alias", "handoff"],
|
|
"lane": "critical",
|
|
"operations": "new: createSessionStep lifecycle; existing: inline snapshot hydration",
|
|
"why": "New-session initialization overlaps address claiming. Current snapshots are carried in durable step results, not fetched from a per-turn snapshot stream.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/create-session-step.ts",
|
|
"symbol": "async function createSessionStep"
|
|
}
|
|
},
|
|
{
|
|
"id": "handoff-check",
|
|
"title": "Check idle handoff eligibility",
|
|
"modes": ["handoff"],
|
|
"lane": "critical",
|
|
"operations": "isSessionIdleForHandoffStep lifecycle",
|
|
"why": "Only a fresh delivery to an idle session can trigger transfer. Same-deployment and busy sessions do not run this step.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/session/handoff.ts",
|
|
"symbol": "async checkpoint"
|
|
}
|
|
},
|
|
{
|
|
"id": "anchor",
|
|
"title": "Register terminal anchor, first handoff only",
|
|
"modes": ["handoff"],
|
|
"lane": "critical",
|
|
"operations": "1 hook_created on original owner's first attempt",
|
|
"why": "Keeps the original run and its public stream alive after its execution ownership transfers.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/session/entry.ts",
|
|
"symbol": "const ensureAnchor"
|
|
}
|
|
},
|
|
{
|
|
"id": "release",
|
|
"title": "Release owned addresses and drain accepted reads",
|
|
"modes": ["handoff"],
|
|
"lane": "critical",
|
|
"operations": "1 hook_disposed per address",
|
|
"why": "If another accepted command is found, reclaim and abandon handoff. Release and claim are not atomic.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/session-inbox/inbox.ts",
|
|
"symbol": "async release()"
|
|
}
|
|
},
|
|
{
|
|
"id": "successor",
|
|
"title": "Register activation callback and start successor",
|
|
"modes": ["handoff"],
|
|
"lane": "critical",
|
|
"operations": "activation hook_created + startSessionOwnerStep lifecycle + run_created + publish",
|
|
"why": "Activation callback is registered before starting a run that can signal it. Successor receives explicit anchorRunId, snapshot, address set, and configured timeout duration. Successful activation restarts that duration.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/session/handoff.ts",
|
|
"symbol": "async start"
|
|
}
|
|
},
|
|
{
|
|
"id": "reclaim",
|
|
"title": "Validate and claim transferred addresses",
|
|
"modes": ["handoff"],
|
|
"lane": "critical",
|
|
"operations": "validation step lifecycle + 1 hook_created per address, batched",
|
|
"why": "No model work until all claims succeed. Preserves stable identity and uses the original stream writer.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/session/entry.ts",
|
|
"symbol": "await validateSessionCheckpointStep"
|
|
}
|
|
},
|
|
{
|
|
"id": "ack",
|
|
"title": "Acknowledge successor activation",
|
|
"modes": ["handoff"],
|
|
"lane": "critical",
|
|
"operations": "signalSessionOwnerActivationStep + resume lookup/write/publish",
|
|
"why": "Old owner can now exit or park as anchor. Later owners signal the anchor only at session end.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/session/handoff-steps.ts",
|
|
"symbol": "signalSessionOwnerActivationStep"
|
|
}
|
|
},
|
|
{
|
|
"id": "timeout",
|
|
"title": "Start deadline workflow concurrently",
|
|
"modes": ["new", "handoff"],
|
|
"lane": "background",
|
|
"operations": "startSessionTimeoutStep + timer run_created/publish/lifecycle + durable wait scheduling",
|
|
"why": "Default deadline infrastructure. Does not block the first model call; startup operations are joined before the session loop advances.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/session/entry.ts",
|
|
"symbol": "const initialTurn"
|
|
}
|
|
},
|
|
{
|
|
"id": "abort",
|
|
"title": "SDK cancellation hook and abort stream",
|
|
"modes": ["new", "stable", "alias", "handoff"],
|
|
"lane": "critical",
|
|
"operations": "1 abrt_* hook_created for the new turn; abort stream read",
|
|
"why": "AbortSignal transport is required for cancelling active durable steps. No eve getConflict call and no steering abort.",
|
|
"source": {
|
|
"path": "packages/eve/node_modules/@workflow/core/dist/serialization.js",
|
|
"symbol": "function reduceAbortWithListener"
|
|
}
|
|
},
|
|
{
|
|
"id": "step",
|
|
"title": "Execute turnStep",
|
|
"modes": ["new", "stable", "alias", "handoff"],
|
|
"lane": "critical",
|
|
"operations": "step_started; step_created/queue delivery when not inline",
|
|
"why": "SDK may execute inline or queue a step. Registration awaiters affect inline eligibility; do not equate a step call with exactly one network request.",
|
|
"source": {
|
|
"path": "packages/eve/node_modules/@workflow/core/dist/runtime/suspension-handler.js",
|
|
"symbol": "const lazyInlineCorrelationIds"
|
|
}
|
|
},
|
|
{
|
|
"id": "prepare",
|
|
"title": "Rehydrate context, deliver message, prepare model",
|
|
"modes": ["new", "stable", "alias", "handoff"],
|
|
"lane": "critical",
|
|
"operations": "local work + authored hooks/connections/sandbox I/O",
|
|
"why": "No universal count: authored integrations, dynamic model selection, memory, sandbox, and tracing can add work before the provider call.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/session/turn-step.ts",
|
|
"symbol": "async function turnStep"
|
|
}
|
|
},
|
|
{
|
|
"id": "writer",
|
|
"title": "Resolve stream writer encryption/routing",
|
|
"modes": ["new", "stable", "alias", "handoff"],
|
|
"lane": "conditional",
|
|
"operations": "run/key reads depending on writable serialization and caches",
|
|
"why": "Original owner uses getWritable(); a successor uses the anchor run's forwarded writable. Stream names are run-scoped.",
|
|
"source": {
|
|
"path": "packages/eve/node_modules/@workflow/core/dist/runtime/run.js",
|
|
"symbol": "getWritable(options"
|
|
}
|
|
},
|
|
{
|
|
"id": "preamble",
|
|
"title": "Publish pre-model events",
|
|
"modes": ["new", "stable", "alias", "handoff"],
|
|
"lane": "critical",
|
|
"operations": "stream write batches; batch count is variable",
|
|
"why": "Lifecycle events and authored handlers can be awaited before the model call. Count actual stream batches, not individual events.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/session/turn-step.ts",
|
|
"symbol": "await emitTurnPreamble"
|
|
}
|
|
},
|
|
{
|
|
"id": "model",
|
|
"title": "MODEL REQUEST — stop time-to-model clock",
|
|
"modes": ["new", "stable", "alias", "handoff"],
|
|
"lane": "critical",
|
|
"operations": "1 provider request for this first call",
|
|
"why": "Provider response latency is outside time-to-model. Subsequent tool/model cycles have their own costs.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/session/turn-step.ts",
|
|
"symbol": "await runModelCallBatch"
|
|
}
|
|
},
|
|
{
|
|
"id": "settle",
|
|
"title": "Commit results, admit steering, settle turn",
|
|
"modes": ["new", "stable", "alias", "handoff"],
|
|
"lane": "completion",
|
|
"operations": "step_completed + optional next step + settleTurnStep + stream batches",
|
|
"why": "Steering uses the same turn after a committed boundary; queue waits for settlement. No child turn run or owner-release handshake per ordinary turn.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/session/turn.ts",
|
|
"symbol": "async runTurn"
|
|
}
|
|
},
|
|
{
|
|
"id": "read",
|
|
"title": "Client stream observer",
|
|
"modes": ["new", "stable", "alias", "handoff"],
|
|
"lane": "observer",
|
|
"operations": "stream GET + read-key resolution as needed; tail-info only when requested",
|
|
"why": "Separate clock/branch. An already-open stream is not a new request per chunk. Reconnects target the original run.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/workflow-runtime.ts",
|
|
"symbol": "async getEventStream"
|
|
}
|
|
},
|
|
{
|
|
"id": "activity",
|
|
"title": "Optional channel activity collector",
|
|
"modes": ["new", "stable", "alias", "handoff"],
|
|
"lane": "conditional",
|
|
"operations": "new root collector start; hook + activity resume/write/publish batches",
|
|
"why": "Only channels with activity renderers. Collector startup can precede session start; separate from the ordinary ID-only path.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/workflow-runtime.ts",
|
|
"symbol": "let collectorRunId"
|
|
}
|
|
},
|
|
{
|
|
"id": "reset",
|
|
"title": "Explicit reset release acknowledgement",
|
|
"modes": ["new", "stable", "alias", "handoff"],
|
|
"lane": "conditional",
|
|
"operations": "bounded hooks.getByToken polling after reset acceptance",
|
|
"why": "Not an ordinary send cost. Confirms the previous owner released the stable address before reset returns.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/workflow-runtime.ts",
|
|
"symbol": "async function waitForCommandHookRelease"
|
|
}
|
|
},
|
|
{
|
|
"id": "resolve",
|
|
"title": "Explicit resolveSession()",
|
|
"modes": ["new", "stable", "alias", "handoff"],
|
|
"lane": "conditional",
|
|
"operations": "1 hooks.getByToken + lazy metadata hydration",
|
|
"why": "Requested read-only identity resolution. Never used as a send preflight.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/workflow-runtime.ts",
|
|
"symbol": "async resolveContinuation"
|
|
}
|
|
},
|
|
{
|
|
"id": "task-owner",
|
|
"title": "Background task ownership resolution",
|
|
"modes": ["new", "stable", "alias", "handoff"],
|
|
"lane": "conditional",
|
|
"operations": "bounded hooks.getByToken polling inside durable work",
|
|
"why": "Not the ordinary turn path. Reads runId only; no metadata hydration.",
|
|
"source": {
|
|
"path": "packages/eve/src/execution/workflow-runtime.ts",
|
|
"symbol": "async function waitForCommandHookOwner"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
</script>
|
|
<script>
|
|
const data = JSON.parse(document.querySelector("#data").textContent);
|
|
const chains = {
|
|
stable:
|
|
"Request authorization → resumeHook: lookup → durable hook_received → queue wake → owner activation/replay → turnStep → preparation + stream events → MODEL REQUEST",
|
|
alias:
|
|
"Request authorization → resumeHook: lookup → durable hook_received → queue wake → owner activation/replay → turnStep → MODEL REQUEST. Parallel response branch after wake: metadata → stable session ID.",
|
|
new: "Request authorization → [channel only: failed resume] → start owner → [session initialization ∥ stable + alias claims] → [first turn ∥ timer startup] → preparation + stream events → MODEL REQUEST",
|
|
handoff:
|
|
"Resume existing owner → detect idle deployment change → ensure anchor → release addresses → activation hook + successor start → validate checkpoint + batch claims → signal activation → [first turn ∥ timer startup] → MODEL REQUEST",
|
|
};
|
|
const make = (tag, text) => {
|
|
const element = document.createElement(tag);
|
|
if (text !== undefined) element.textContent = text;
|
|
return element;
|
|
};
|
|
function render() {
|
|
const mode = document.querySelector("#mode").value;
|
|
const extra = document.querySelector("#extra").checked;
|
|
document.querySelector("#chain").textContent = chains[mode];
|
|
const body = document.querySelector("#rows");
|
|
body.replaceChildren();
|
|
for (const row of data.rows.filter(
|
|
(row) => row.modes.includes(mode) && (extra || row.lane === "critical"),
|
|
)) {
|
|
const tr = make("tr");
|
|
const title = make("td", row.title);
|
|
const lane = make("small", row.lane);
|
|
lane.className = "lane " + row.lane;
|
|
title.append(lane);
|
|
const detail = make("details");
|
|
detail.append(make("summary", row.why));
|
|
detail.append(make("p", row.source.path));
|
|
detail.append(make("code", row.source.symbol));
|
|
tr.append(title, make("td", row.operations), make("td"));
|
|
tr.lastChild.append(detail);
|
|
body.append(tr);
|
|
}
|
|
}
|
|
for (const limit of data.limitations)
|
|
document.querySelector("#limits").append(make("li", limit));
|
|
document.querySelector("#version").textContent =
|
|
data.sdk +
|
|
" · Base " +
|
|
data.baseCommit +
|
|
" · Includes uncommitted implementation changes. " +
|
|
data.evidence;
|
|
document.querySelector("#mode").addEventListener("change", render);
|
|
document.querySelector("#extra").addEventListener("change", render);
|
|
document.querySelector("#print").addEventListener("click", () => window.print());
|
|
document.querySelector("#download").addEventListener("click", () => {
|
|
const url = URL.createObjectURL(
|
|
new Blob([JSON.stringify(data, null, 2)], { type: "application/json" }),
|
|
);
|
|
const a = make("a");
|
|
a.href = url;
|
|
a.download = "session-network-hops.json";
|
|
a.click();
|
|
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
});
|
|
render();
|
|
</script>
|
|
</html>
|