my harness for niri
1import type { Message, RunnerState, UserMessage } from "../types.js"
2
3/** Generic decoded tool arguments object. */
4export type ToolArgs = Record<string, any>
5
6/** Supported image detail levels for multimodal requests. */
7export type ImageDetail = "auto" | "low" | "high"
8
9/** Mutable state consumed by the runner loop on each turn. */
10export interface LoopState {
11 conversation: Message[]
12 pendingInputs: UserMessage[]
13 tokenCount: number
14 contextSize: number
15 toolInFlight: boolean
16 memoryRecallCooldowns: Record<number, number>
17 memoryRecallTurn: number
18}
19
20/** Lifecycle hooks injected by the runner orchestrator into the loop. */
21export interface LoopHooks {
22 /** Waits for the next incoming event from any trigger source. */
23 waitForEvent: () => Promise<UserMessage>
24 /** Waits up to timeoutMs for the next event; resolves null on timeout. */
25 waitForEventWithTimeout: (timeoutMs: number) => Promise<UserMessage | null>
26 /** Injects an incoming event into the in-memory conversation. */
27 injectIncomingEvent: (convId: number, event: UserMessage) => void
28 /** Flushes events deferred while a tool call was in flight. */
29 flushDeferredEvents: () => void
30 /** Clears persisted session state when ending a run. */
31 clearSession: () => Promise<void>
32 /** Persists the current in-memory session state. */
33 saveSession: () => Promise<void>
34}
35
36/** Internal runtime state for the runner service. */
37export interface RunnerStateInternal extends RunnerState {
38 toolInFlight: boolean
39 deferredEvents: Array<{ event: UserMessage; priority: boolean }>
40}