mirror of
https://github.com/kennethnym/aris.git
synced 2026-03-20 17:11:17 +00:00
Compare commits
3 Commits
feat/feed-
...
feat/time-
| Author | SHA1 | Date | |
|---|---|---|---|
|
c9be3b190c
|
|||
|
0f8b1ec4eb
|
|||
|
4f55439f77
|
@@ -1,87 +0,0 @@
|
|||||||
import { describe, expect, test } from "bun:test"
|
|
||||||
|
|
||||||
import type { FeedItem, Slot } from "./feed"
|
|
||||||
|
|
||||||
describe("FeedItem slots", () => {
|
|
||||||
test("FeedItem without slots is valid", () => {
|
|
||||||
const item: FeedItem<"test", { value: number }> = {
|
|
||||||
id: "test-1",
|
|
||||||
type: "test",
|
|
||||||
timestamp: new Date(),
|
|
||||||
data: { value: 42 },
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(item.slots).toBeUndefined()
|
|
||||||
})
|
|
||||||
|
|
||||||
test("FeedItem with unfilled slots", () => {
|
|
||||||
const item: FeedItem<"weather", { temp: number }> = {
|
|
||||||
id: "weather-1",
|
|
||||||
type: "weather",
|
|
||||||
timestamp: new Date(),
|
|
||||||
data: { temp: 18 },
|
|
||||||
slots: {
|
|
||||||
insight: {
|
|
||||||
description: "A short contextual insight about the current weather",
|
|
||||||
content: null,
|
|
||||||
},
|
|
||||||
"cross-source": {
|
|
||||||
description: "Connection between weather and calendar events",
|
|
||||||
content: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(item.slots).toBeDefined()
|
|
||||||
expect(Object.keys(item.slots!)).toEqual(["insight", "cross-source"])
|
|
||||||
expect(item.slots!.insight!.content).toBeNull()
|
|
||||||
expect(item.slots!["cross-source"]!.content).toBeNull()
|
|
||||||
})
|
|
||||||
|
|
||||||
test("FeedItem with filled slots", () => {
|
|
||||||
const item: FeedItem<"weather", { temp: number }> = {
|
|
||||||
id: "weather-1",
|
|
||||||
type: "weather",
|
|
||||||
timestamp: new Date(),
|
|
||||||
data: { temp: 18 },
|
|
||||||
slots: {
|
|
||||||
insight: {
|
|
||||||
description: "A short contextual insight about the current weather",
|
|
||||||
content: "Rain after 3pm — grab a jacket before your walk",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(item.slots!.insight!.content).toBe("Rain after 3pm — grab a jacket before your walk")
|
|
||||||
})
|
|
||||||
|
|
||||||
test("Slot interface enforces required fields", () => {
|
|
||||||
const slot: Slot = {
|
|
||||||
description: "Test slot description",
|
|
||||||
content: null,
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(slot.description).toBe("Test slot description")
|
|
||||||
expect(slot.content).toBeNull()
|
|
||||||
|
|
||||||
const filledSlot: Slot = {
|
|
||||||
description: "Test slot description",
|
|
||||||
content: "Filled content",
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(filledSlot.content).toBe("Filled content")
|
|
||||||
})
|
|
||||||
|
|
||||||
test("FeedItem with empty slots record", () => {
|
|
||||||
const item: FeedItem<"test", { value: number }> = {
|
|
||||||
id: "test-1",
|
|
||||||
type: "test",
|
|
||||||
timestamp: new Date(),
|
|
||||||
data: { value: 1 },
|
|
||||||
slots: {},
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(item.slots).toEqual({})
|
|
||||||
expect(Object.keys(item.slots!)).toHaveLength(0)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -23,20 +23,6 @@ export interface FeedItemSignals {
|
|||||||
timeRelevance?: TimeRelevance
|
timeRelevance?: TimeRelevance
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A named slot for LLM-fillable content on a feed item.
|
|
||||||
*
|
|
||||||
* Sources declare slots with a description that tells the LLM what content
|
|
||||||
* to generate. The enhancement harness fills `content` asynchronously;
|
|
||||||
* until then it remains `null`.
|
|
||||||
*/
|
|
||||||
export interface Slot {
|
|
||||||
/** Tells the LLM what this slot wants — written by the source */
|
|
||||||
description: string
|
|
||||||
/** LLM-filled text content, null until enhanced */
|
|
||||||
content: string | null
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A single item in the feed.
|
* A single item in the feed.
|
||||||
*
|
*
|
||||||
@@ -50,12 +36,6 @@ export interface Slot {
|
|||||||
* timestamp: new Date(),
|
* timestamp: new Date(),
|
||||||
* data: { temp: 18, condition: "cloudy" },
|
* data: { temp: 18, condition: "cloudy" },
|
||||||
* signals: { urgency: 0.5, timeRelevance: "ambient" },
|
* signals: { urgency: 0.5, timeRelevance: "ambient" },
|
||||||
* slots: {
|
|
||||||
* insight: {
|
|
||||||
* description: "A short contextual insight about the current weather",
|
|
||||||
* content: null,
|
|
||||||
* },
|
|
||||||
* },
|
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@@ -73,6 +53,4 @@ export interface FeedItem<
|
|||||||
data: TData
|
data: TData
|
||||||
/** Source-provided hints for post-processors. Optional — omit if no signals apply. */
|
/** Source-provided hints for post-processors. Optional — omit if no signals apply. */
|
||||||
signals?: FeedItemSignals
|
signals?: FeedItemSignals
|
||||||
/** Named slots for LLM-fillable content. Keys are slot names. */
|
|
||||||
slots?: Record<string, Slot>
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export type { ActionDefinition } from "./action"
|
|||||||
export { UnknownActionError } from "./action"
|
export { UnknownActionError } from "./action"
|
||||||
|
|
||||||
// Feed
|
// Feed
|
||||||
export type { FeedItem, FeedItemSignals, Slot } from "./feed"
|
export type { FeedItem, FeedItemSignals } from "./feed"
|
||||||
export { TimeRelevance } from "./feed"
|
export { TimeRelevance } from "./feed"
|
||||||
|
|
||||||
// Feed Source
|
// Feed Source
|
||||||
|
|||||||
Reference in New Issue
Block a user