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>
This commit is contained in:
2026-02-15 12:26:23 +00:00
parent 4d6cac7ec8
commit 699155e0d8
29 changed files with 1169 additions and 116 deletions

View File

@@ -1,4 +1,6 @@
import type { Context, FeedSource } from "@aris/core"
import type { ActionDefinition, Context, FeedSource } from "@aris/core"
import { UnknownActionError } from "@aris/core"
import type {
ApiCalendarEvent,
@@ -63,7 +65,7 @@ const PRIORITY_ALL_DAY = 0.4
* ```
*/
export class GoogleCalendarSource implements FeedSource<CalendarFeedItem> {
readonly id = "google-calendar"
readonly id = "aris.google-calendar"
private readonly client: GoogleCalendarClient
private readonly calendarIds: string[] | undefined
@@ -75,6 +77,14 @@ export class GoogleCalendarSource implements FeedSource<CalendarFeedItem> {
this.lookaheadHours = options.lookaheadHours ?? DEFAULT_LOOKAHEAD_HOURS
}
async listActions(): Promise<Record<string, ActionDefinition>> {
return {}
}
async executeAction(actionId: string): Promise<void> {
throw new UnknownActionError(actionId)
}
async fetchContext(context: Context): Promise<Partial<Context> | null> {
const events = await this.fetchAllEvents(context.time)