Chapter 5: Lazy Frames and Advanced Fill Strategies
A lazy frame is evaluated only when it is read. This is useful for expensive formatting, late-bound context, and derived views that do not need to be stored eagerly.
Basic Usage
import { lazyFrame } from 'chronoai';
agent.set('display-name', lazyFrame({
compute({ read }) {
const first = read('first-name')?.value ?? '';
const last = read('last-name')?.value ?? '';
return `${first} ${last}`.trim();
},
}));
console.log(agent.read('display-name')?.value);
The frame is placed on the timeline, but its value is computed when read() resolves it.
More Examples
Formatting
agent.set('price-label', lazyFrame({
compute({ read }) {
const price = read('price')?.value ?? 0;
return `$${price.toFixed(2)}`;
},
}));
Cross-timeline Aggregation
agent.set('profile-card', lazyFrame({
compute({ read }) {
return {
name: read('name')?.value,
role: read('role')?.value,
status: read('status')?.value,
};
},
}));
Range Collection
Lazy frames can also collect history at read time.
agent.set('conversation-preview', lazyFrame({
compute({ collect }) {
return collect({
select: ['user-input', 'content-body'],
from: 1,
to: 'current',
});
},
}));
Lazy Frame vs reactionFrame
| Use | Choose |
|---|---|
| Value should update when dependencies change | reactionFrame |
| Value should be computed only when read | lazyFrame |
| Value should participate in DAG propagation | reactionFrame |
| Value is a view or formatter | lazyFrame |
Recursive Read Protection
ChronoAI protects against recursive lazy reads. A lazy frame should not directly or indirectly read itself.
If you hit recursion, split the value into two timelines: one source timeline and one view timeline.
intervalFill
intervalFill produces values based on time intervals.
useTimeline<number>({
name: 'clock',
fill: intervalFill({
interval: 1000,
fn: () => Date.now(),
}),
});
It is useful for clocks, polling state, or time-based UI.
customFill
customFill gives full control over how an empty timepoint is resolved.
useTimeline<string>({
name: 'label',
fill: customFill({
fn(ctx) {
return ctx.read('source')?.value ?? 'empty';
},
}),
});
Use it when built-in strategies do not fit.
Summary
- Lazy frames compute on read.
- They are good for views, formatting, and late aggregation.
- Reaction frames are better for graph propagation.
- Interval and custom fills cover advanced resolution behavior.
Next
Continue with Chapter 6: Command System.