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

@@ -34,12 +34,12 @@ describe("WeatherSource", () => {
describe("properties", () => {
test("has correct id", () => {
const source = new WeatherSource({ credentials: mockCredentials })
expect(source.id).toBe("weather")
expect(source.id).toBe("aris.weather")
})
test("depends on location", () => {
const source = new WeatherSource({ credentials: mockCredentials })
expect(source.dependencies).toEqual(["location"])
expect(source.dependencies).toEqual(["aris.location"])
})
test("throws error if neither client nor credentials provided", () => {
@@ -78,7 +78,10 @@ describe("WeatherSource", () => {
})
test("converts temperature to imperial", async () => {
const source = new WeatherSource({ client: mockClient, units: Units.imperial })
const source = new WeatherSource({
client: mockClient,
units: Units.imperial,
})
const context = createMockContext({ lat: 37.7749, lng: -122.4194 })
const result = await source.fetchContext(context)