Commit Graph

9 Commits

Author SHA1 Message Date
96e22e227c feat: replace flat context with tuple-keyed store (#50)
Context keys are now tuples instead of strings, inspired by
React Query's query keys. This prevents context collisions
when multiple instances of the same source type are registered.

Sources write to structured keys like
["aris.google-calendar", "nextEvent", { account: "work" }]
and consumers can query by prefix via context.find().

Co-authored-by: Ona <no-reply@ona.com>
2026-03-01 22:52:41 +00:00
82ac2b577d feat: add post-processor pipeline to FeedEngine (#41)
* feat: add post-processor pipeline to FeedEngine

Add FeedPostProcessor type and FeedEnhancement interface.
Post-processors run after item collection on all update
paths (refresh, reactive context, reactive items).

Pipeline is chained — each processor sees items as modified
by the previous one. Enhancement merging handles additional
items, suppression, and grouped items. Throwing processors
are caught and recorded in FeedResult.errors.

Co-authored-by: Ona <no-reply@ona.com>

* docs: document intentional TItems cast in post-processor merge

Co-authored-by: Ona <no-reply@ona.com>

* fix: filter stale item IDs from groups after pipeline

Groups accumulated during the pipeline can reference items
that a later processor suppressed. The engine now strips
stale IDs and drops empty groups before returning.

Co-authored-by: Ona <no-reply@ona.com>

* refactor: use reduce for stale group filtering

Co-authored-by: Ona <no-reply@ona.com>

---------

Co-authored-by: Ona <no-reply@ona.com>
2026-02-28 15:57:01 +00:00
28d26b3c87 Replace FeedItem.priority with signals (#39)
* feat: replace FeedItem.priority with signals

Remove priority field from FeedItem and engine-level sorting.
Add FeedItemSignals with urgency and timeRelevance fields.
Update all source packages to emit signals instead of priority.

Ranking is now the post-processing layer's responsibility.
Urgency values are unchanged from the old priority values.

Co-authored-by: Ona <no-reply@ona.com>

* fix: use TimeRelevance enum in all tests

Co-authored-by: Ona <no-reply@ona.com>

---------

Co-authored-by: Ona <no-reply@ona.com>
2026-02-28 12:02:57 +00:00
08dd437952 feat: add caching to FeedEngine
Add lastFeed() method that returns cached FeedResult within
a configurable TTL (default 5 min). refresh() always fetches
fresh data and updates the cache. Periodic auto-refresh via
recursive setTimeout when engine is started. Reactive updates
reset the timer to avoid redundant fetches.

Co-authored-by: Ona <no-reply@ona.com>
2026-02-24 01:13:41 +00:00
699155e0d8 feat: add actions to FeedSource interface
Add listActions() and executeAction() to FeedSource for write
operations back to external services. Actions use arktype schemas
for input validation via StandardSchemaV1.

- ActionDefinition type with optional input schema
- FeedEngine routes actions with existence and ID validation
- Source IDs use reverse-domain format (aris.location, aris.tfl)
- LocationSource: update-location action with schema validation
- TflSource: set-lines-of-interest action with lineId validation
- No-op implementations for sources without actions

Co-authored-by: Ona <no-reply@ona.com>
2026-02-15 12:53:10 +00:00
181160b018 feat(core): add FeedEngine for FeedSource orchestration
Introduces FeedEngine that consumes FeedSource instances and manages
the dependency graph for context flow and item collection.

- Validates dependency graph (missing deps, circular references)
- Topologically sorts sources for execution order
- Runs fetchContext() in dependency order, accumulating context
- Runs fetchItems() on all sources with final context
- Supports reactive updates via onContextUpdate/onItemsUpdate
- Graceful error handling (continues after source failures)

Marks DataSource, ContextProvider, ContextBridge, Reconciler, and
FeedController as deprecated in favor of FeedSource + FeedEngine.

Co-authored-by: Ona <no-reply@ona.com>
2026-01-24 22:42:00 +00:00
1d9de2851a feat(core): add FeedSource interface
Unifies DataSource and ContextProvider into a single interface that
forms a dependency graph. Sources declare dependencies on other sources
and can provide context, feed items, or both.

Deprecates DataSource, ContextProvider, and ContextBridge.

Co-authored-by: Ona <no-reply@ona.com>
2026-01-18 23:32:47 +00:00
b73e603c90 feat(core): return RefreshResult from ContextBridge.refresh()
Surfaces provider errors through RefreshResult.errors instead of
silently ignoring them.

Co-authored-by: Ona <no-reply@ona.com>
2026-01-18 20:28:54 +00:00
3c16dd4275 feat(core): add FeedController orchestration layer
Adds orchestration for feed reconciliation with context-driven updates:

- FeedController: holds context, debounces updates, reconciles sources
- ContextBridge: bridges context providers to controller
- ContextProvider: reactive + on-demand context value interface
- Branded ContextKey<T> for type-safe context keys

Moves source files to src/ directory and consolidates tests into
integration test.

Co-authored-by: Ona <no-reply@ona.com>
2026-01-18 00:58:29 +00:00