2026-02-15 12:26:23 +00:00
|
|
|
import type { ActionDefinition } from "./action"
|
2026-03-01 22:52:41 +00:00
|
|
|
import type { Context, ContextEntry } from "./context"
|
2026-01-18 23:32:47 +00:00
|
|
|
import type { FeedItem } from "./feed"
|
|
|
|
|
|
|
|
|
|
/**
|
2026-02-15 12:26:23 +00:00
|
|
|
* Unified interface for sources that provide context, feed items, and actions.
|
2026-01-18 23:32:47 +00:00
|
|
|
*
|
2026-02-15 12:26:23 +00:00
|
|
|
* Sources form a dependency graph — a source declares which other sources
|
2026-01-18 23:32:47 +00:00
|
|
|
* it depends on, and the graph ensures dependencies are resolved before
|
|
|
|
|
* dependents run.
|
|
|
|
|
*
|
2026-02-15 12:26:23 +00:00
|
|
|
* Source IDs use reverse domain notation. Built-in sources use `aris.<name>`,
|
|
|
|
|
* third parties use their own domain (e.g., `com.spotify`).
|
|
|
|
|
*
|
|
|
|
|
* Every method maps to a protocol operation for remote source support:
|
|
|
|
|
* - `id`, `dependencies` → source/describe
|
|
|
|
|
* - `listActions()` → source/listActions
|
|
|
|
|
* - `executeAction()` → source/executeAction
|
|
|
|
|
* - `fetchContext()` → source/fetchContext
|
|
|
|
|
* - `fetchItems()` → source/fetchItems
|
|
|
|
|
* - `onContextUpdate()` → source/contextUpdated (notification)
|
|
|
|
|
* - `onItemsUpdate()` → source/itemsUpdated (notification)
|
2026-01-18 23:32:47 +00:00
|
|
|
*
|
|
|
|
|
* @example
|
|
|
|
|
* ```ts
|
|
|
|
|
* const locationSource: FeedSource = {
|
2026-02-15 12:26:23 +00:00
|
|
|
* id: "aris.location",
|
|
|
|
|
* async listActions() { return { "update-location": { id: "update-location" } } },
|
|
|
|
|
* async executeAction(actionId) { throw new UnknownActionError(actionId) },
|
|
|
|
|
* async fetchContext() { ... },
|
2026-02-14 16:20:24 +00:00
|
|
|
* }
|
2026-01-18 23:32:47 +00:00
|
|
|
* ```
|
|
|
|
|
*/
|
|
|
|
|
export interface FeedSource<TItem extends FeedItem = FeedItem> {
|
2026-02-15 12:26:23 +00:00
|
|
|
/** Unique identifier for this source in reverse-domain format */
|
2026-01-18 23:32:47 +00:00
|
|
|
readonly id: string
|
|
|
|
|
|
|
|
|
|
/** IDs of sources this source depends on */
|
|
|
|
|
readonly dependencies?: readonly string[]
|
|
|
|
|
|
2026-02-15 12:26:23 +00:00
|
|
|
/**
|
|
|
|
|
* List actions this source supports. Empty record if none.
|
|
|
|
|
* Maps to: source/listActions
|
|
|
|
|
*/
|
|
|
|
|
listActions(): Promise<Record<string, ActionDefinition>>
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Execute an action by ID. Throws on unknown action or invalid input.
|
|
|
|
|
* Maps to: source/executeAction
|
|
|
|
|
*/
|
|
|
|
|
executeAction(actionId: string, params: unknown): Promise<unknown>
|
|
|
|
|
|
2026-01-18 23:32:47 +00:00
|
|
|
/**
|
|
|
|
|
* Subscribe to reactive context updates.
|
|
|
|
|
* Called when the source can push context changes proactively.
|
|
|
|
|
* Returns cleanup function.
|
2026-02-15 12:26:23 +00:00
|
|
|
* Maps to: source/contextUpdated (notification, source → host)
|
2026-01-18 23:32:47 +00:00
|
|
|
*/
|
|
|
|
|
onContextUpdate?(
|
2026-03-01 22:52:41 +00:00
|
|
|
callback: (entries: readonly ContextEntry[]) => void,
|
2026-01-18 23:32:47 +00:00
|
|
|
getContext: () => Context,
|
|
|
|
|
): () => void
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Fetch context on-demand.
|
|
|
|
|
* Called during manual refresh or initial load.
|
2026-02-14 16:20:24 +00:00
|
|
|
* Return null if this source cannot provide context.
|
2026-02-15 12:26:23 +00:00
|
|
|
* Maps to: source/fetchContext
|
2026-01-18 23:32:47 +00:00
|
|
|
*/
|
2026-03-01 22:52:41 +00:00
|
|
|
fetchContext(context: Context): Promise<readonly ContextEntry[] | null>
|
2026-01-18 23:32:47 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Subscribe to reactive feed item updates.
|
|
|
|
|
* Called when the source can push item changes proactively.
|
|
|
|
|
* Returns cleanup function.
|
2026-02-15 12:26:23 +00:00
|
|
|
* Maps to: source/itemsUpdated (notification, source → host)
|
2026-01-18 23:32:47 +00:00
|
|
|
*/
|
|
|
|
|
onItemsUpdate?(callback: (items: TItem[]) => void, getContext: () => Context): () => void
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Fetch feed items on-demand.
|
|
|
|
|
* Called during manual refresh or when dependencies update.
|
2026-02-15 12:26:23 +00:00
|
|
|
* Maps to: source/fetchItems
|
2026-01-18 23:32:47 +00:00
|
|
|
*/
|
|
|
|
|
fetchItems?(context: Context): Promise<TItem[]>
|
|
|
|
|
}
|