eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
138 lines (137 loc) • 6.32 kB
TypeScript
/**
* Builders for the framework's reserved `$eve.*` workflow attributes.
*
* Each builder returns a plain `Record<string, string | number | undefined>`
* suitable for `setEveAttributes` from
* {@link "#runtime/attributes/emit.js" }. Builders are intentionally
* pure data → data transforms: they hold zero dependencies on the
* workflow runtime so the workflow body, step bodies, and tests can
* all call them identically.
*
* `$eve.*` is the framework-owned attribute namespace. Authored code
* never emits these tags directly — they describe the structural shape
* of a session/turn/subagent run so dashboards can stitch a tree of
* workflow runs back together without inspecting their bodies.
*
* Tag inventory (recap):
* - `$eve.type` — `"session" | "turn" | "subagent"`
* - `$eve.parent` — sessionId of the **immediate** parent
* - `$eve.root` — sessionId of the **root** session in the chain
* - `$eve.parent_call` — parent runtime-action tool call id (subagent rows only)
* - `$eve.parent_turn` — parent turn id that dispatched the subagent (subagent rows only)
* - `$eve.subagent` — active compiled graph node id (subagent rows only)
* - `$eve.trigger` — channel adapter kind (session/subagent rows)
* - `$eve.title` — truncated session title from the first user message
*/
import type { EveAttributeValue } from "#runtime/attributes/emit.js";
/**
* Active compiled graph node id for the session's agent. Returned by
* `createSessionStep` so workflow bodies don't have to load the bundle
* themselves. Equal to the framework root sentinel (`"__root__"`) for
* the root agent; equal to the subagent's compiled node id for
* delegated child runs. Tag emitters use this to populate
* `$eve.subagent`.
*/
export interface SessionIdentitySummary {
readonly nodeId: string;
}
/**
* Parent session lineage decoded from the serialized run context.
*/
export interface SessionParentLineage {
readonly callId?: string;
readonly rootSessionId?: string;
readonly sessionId?: string;
readonly turnId?: string;
}
/**
* Reads the active channel kind from a deserialized context map.
* Returns `undefined` when the channel slot is missing or malformed —
* tag emission silently drops undefined values.
*/
export declare function readChannelKind(serializedContext: Record<string, unknown>): string | undefined;
/**
* Reads parent session lineage from a deserialized context map. Returns
* an empty object for top-level runs or malformed delegated contexts.
*/
export declare function readParentLineage(serializedContext: Record<string, unknown>): SessionParentLineage;
/**
* Reads the immediate parent session id from a deserialized context map.
* Returns `undefined` when the run is a top-level session.
*/
export declare function readParentSessionId(serializedContext: Record<string, unknown>): string | undefined;
/**
* Reads the **root** session id from a deserialized context map.
*
* `eve.parentSession.rootSessionId` is denormalized at every dispatch
* site (see {@link "#channel/types.js".SessionParent}) so a subagent
* five levels deep can still attribute itself to the top user-facing
* session without walking the chain. Returns `undefined` for top-level
* runs, which carry no `eve.parentSession`.
*/
export declare function readRootSessionId(serializedContext: Record<string, unknown>): string | undefined;
/**
* Maximum visible length (in code points) of a derived `$eve.title`.
*
* Titles render as the first column of the dashboard's run table, so
* they get a tighter, display-oriented cap here than the generic
* runtime byte budget (`EVE_ATTRIBUTE_VALUE_MAX_BYTES`). Mostly-ASCII
* titles stay within that budget; a title dominated by multi-byte
* characters may still be further truncated by the runtime tag
* truncator, which is acceptable.
*/
export declare const EVE_SESSION_TITLE_MAX_CHARS = 125;
/**
* Derives the `$eve.title` value from the first user message of a
* top-level session.
*
* Returns `undefined` when no plain-text content is available; the
* attribute emitter strips undefined values. Multimodal messages
* (image/file parts) contribute only their text parts to keep the
* title human-readable. Long prompts are truncated to
* {@link EVE_SESSION_TITLE_MAX_CHARS} code points with a trailing
* ellipsis so the dashboard's title column stays readable.
*/
export declare function deriveSessionTitle(message: unknown): string | undefined;
/**
* Builds the `$eve.*` attribute payload for a top-level session run
* (`workflowEntry` invoked without an `eve.parentSession`).
*
* `$eve.root` is intentionally omitted — the session row IS the root,
* so its own `workflowRunId` already identifies the chain root.
*/
export declare function buildSessionAttributes(input: {
readonly inputMessage: unknown;
readonly serializedContext: Record<string, unknown>;
}): Record<string, EveAttributeValue>;
/**
* Builds the `$eve.*` attribute payload for a delegated subagent root
* run (`workflowEntry` invoked with an `eve.parentSession`).
*
* `$eve.root` carries the **root** session id so the dashboard can
* group every descendant under one query: `search($eve.root=<root>)`
* returns all turns and nested subagents under that user-facing
* session in a single round trip.
*/
export declare function buildSubagentRootAttributes(input: {
readonly identity: SessionIdentitySummary;
readonly parentCallId?: string;
readonly parentSessionId: string;
readonly parentTurnId?: string;
readonly rootSessionId: string;
readonly serializedContext: Record<string, unknown>;
}): Record<string, EveAttributeValue>;
/**
* Builds the `$eve.*` attribute payload for one turn workflow run.
*
* Turns live one level below their session: `$eve.parent` always points
* to the parent's sessionId (which is the session-row's
* `workflowRunId`), and `$eve.root` denormalizes the chain root (equal
* to `$eve.parent` for turns of top-level sessions). Turn ordering is
* recovered from each run's `createdAt`, so no explicit sequence tag is
* emitted.
*/
export declare function buildTurnAttributes(input: {
readonly parentSessionId: string;
readonly rootSessionId: string;
}): Record<string, EveAttributeValue>;