@varo-ui/ai 1.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/thread.ts ADDED
@@ -0,0 +1,160 @@
1
+ import type {
2
+ AgentThreadController,
3
+ AgentThreadSnapshot,
4
+ AgentThreadVersion,
5
+ } from './types'
6
+
7
+ const DESTROYED_ERROR = 'Agent thread controller is destroyed'
8
+
9
+ function assertVersionId(id: string) {
10
+ if (id.length === 0) throw new Error('Agent thread version id must not be empty')
11
+ }
12
+
13
+ function freezeVersion(version: AgentThreadVersion): AgentThreadVersion {
14
+ return Object.freeze({ ...version })
15
+ }
16
+
17
+ function freezeSnapshot(
18
+ versions: readonly AgentThreadVersion[],
19
+ activeVersionId?: string,
20
+ ): AgentThreadSnapshot {
21
+ if (activeVersionId === undefined) return Object.freeze({ versions })
22
+ return Object.freeze({ activeVersionId, versions })
23
+ }
24
+
25
+ function validateSnapshot(initial?: AgentThreadSnapshot): AgentThreadSnapshot {
26
+ const sourceVersions = initial?.versions ?? []
27
+ const versionsById = new Map<string, AgentThreadVersion>()
28
+
29
+ for (const version of sourceVersions) {
30
+ assertVersionId(version.id)
31
+ if (versionsById.has(version.id)) {
32
+ throw new Error(`Agent thread version "${version.id}" is duplicated`)
33
+ }
34
+ versionsById.set(version.id, version)
35
+ }
36
+
37
+ for (const version of sourceVersions) {
38
+ if (version.parentId !== undefined && !versionsById.has(version.parentId)) {
39
+ throw new Error(`Agent thread parent version "${version.parentId}" does not exist`)
40
+ }
41
+ }
42
+
43
+ const resolvedIds = new Set<string>()
44
+ for (const version of sourceVersions) {
45
+ if (resolvedIds.has(version.id)) continue
46
+
47
+ const path: string[] = []
48
+ const pathIds = new Set<string>()
49
+ let current: AgentThreadVersion | undefined = version
50
+ while (current !== undefined && !resolvedIds.has(current.id)) {
51
+ if (pathIds.has(current.id)) {
52
+ throw new Error(`Agent thread version "${current.id}" has a cyclic parent chain`)
53
+ }
54
+ path.push(current.id)
55
+ pathIds.add(current.id)
56
+ current = current.parentId === undefined
57
+ ? undefined
58
+ : versionsById.get(current.parentId)
59
+ }
60
+ path.forEach(id => resolvedIds.add(id))
61
+ }
62
+
63
+ const activeVersionId = initial?.activeVersionId
64
+ if (activeVersionId !== undefined && !versionsById.has(activeVersionId)) {
65
+ throw new Error(`Agent thread active version "${activeVersionId}" does not exist`)
66
+ }
67
+
68
+ return freezeSnapshot(Object.freeze(sourceVersions.map(freezeVersion)), activeVersionId)
69
+ }
70
+
71
+ export function createAgentThreadController(
72
+ initial?: AgentThreadSnapshot,
73
+ ): AgentThreadController {
74
+ const listeners = new Set<() => void>()
75
+ let snapshot = validateSnapshot(initial)
76
+ let destroyed = false
77
+
78
+ function assertActive() {
79
+ if (destroyed) throw new Error(DESTROYED_ERROR)
80
+ }
81
+
82
+ function findVersion(id: string) {
83
+ return snapshot.versions.find(version => version.id === id)
84
+ }
85
+
86
+ function replace(nextSnapshot: AgentThreadSnapshot) {
87
+ snapshot = nextSnapshot
88
+ listeners.forEach(listener => listener())
89
+ }
90
+
91
+ function append(version: AgentThreadVersion) {
92
+ assertActive()
93
+ assertVersionId(version.id)
94
+ if (findVersion(version.id)) {
95
+ throw new Error(`Agent thread version "${version.id}" already exists`)
96
+ }
97
+ if (version.parentId !== undefined && !findVersion(version.parentId)) {
98
+ throw new Error(`Agent thread parent version "${version.parentId}" does not exist`)
99
+ }
100
+
101
+ const versions = Object.freeze([...snapshot.versions, freezeVersion(version)])
102
+ replace(freezeSnapshot(versions, version.id))
103
+ }
104
+
105
+ function fork(
106
+ parentId: string,
107
+ version: Omit<AgentThreadVersion, 'parentId'>,
108
+ ) {
109
+ assertActive()
110
+ assertVersionId(version.id)
111
+ if (findVersion(version.id)) {
112
+ throw new Error(`Agent thread version "${version.id}" already exists`)
113
+ }
114
+ if (!findVersion(parentId)) {
115
+ throw new Error(`Agent thread parent version "${parentId}" does not exist`)
116
+ }
117
+
118
+ const forkedVersion = freezeVersion({ ...version, parentId })
119
+ const versions = Object.freeze([...snapshot.versions, forkedVersion])
120
+ replace(freezeSnapshot(versions, forkedVersion.id))
121
+ }
122
+
123
+ function select(id: string) {
124
+ assertActive()
125
+ if (!findVersion(id)) {
126
+ throw new Error(`Agent thread version "${id}" does not exist`)
127
+ }
128
+ replace(freezeSnapshot(snapshot.versions, id))
129
+ }
130
+
131
+ function reset(nextInitial?: AgentThreadSnapshot) {
132
+ assertActive()
133
+ const nextSnapshot = validateSnapshot(nextInitial)
134
+ replace(nextSnapshot)
135
+ }
136
+
137
+ function subscribe(listener: () => void) {
138
+ assertActive()
139
+ listeners.add(listener)
140
+ return () => {
141
+ listeners.delete(listener)
142
+ }
143
+ }
144
+
145
+ return {
146
+ append,
147
+ destroy() {
148
+ if (destroyed) return
149
+ destroyed = true
150
+ listeners.clear()
151
+ },
152
+ fork,
153
+ getSnapshot() {
154
+ return snapshot
155
+ },
156
+ reset,
157
+ select,
158
+ subscribe,
159
+ }
160
+ }
package/src/types.ts CHANGED
@@ -104,22 +104,22 @@ export interface AgentDoneEvent {
104
104
  }
105
105
  }
106
106
 
107
- export type AgentStreamEvent =
108
- | AgentMessageStartEvent
109
- | AgentTextDeltaEvent
110
- | AgentMessageEndEvent
111
- | AgentReasoningStartEvent
112
- | AgentReasoningDeltaEvent
113
- | AgentReasoningEndEvent
114
- | AgentToolStartEvent
115
- | AgentToolUpdateEvent
116
- | AgentToolResultEvent
117
- | AgentToolErrorEvent
118
- | AgentApprovalRequiredEvent
119
- | AgentApprovalResolvedEvent
120
- | AgentDataEvent
121
- | AgentErrorEvent
122
- | AgentDoneEvent
107
+ export type AgentStreamEvent
108
+ = | AgentMessageStartEvent
109
+ | AgentTextDeltaEvent
110
+ | AgentMessageEndEvent
111
+ | AgentReasoningStartEvent
112
+ | AgentReasoningDeltaEvent
113
+ | AgentReasoningEndEvent
114
+ | AgentToolStartEvent
115
+ | AgentToolUpdateEvent
116
+ | AgentToolResultEvent
117
+ | AgentToolErrorEvent
118
+ | AgentApprovalRequiredEvent
119
+ | AgentApprovalResolvedEvent
120
+ | AgentDataEvent
121
+ | AgentErrorEvent
122
+ | AgentDoneEvent
123
123
 
124
124
  export interface AgentStreamMessage {
125
125
  final: boolean
@@ -184,22 +184,28 @@ export interface TextStreamSnapshot {
184
184
  }
185
185
 
186
186
  export interface TextStreamOptions {
187
+ burstInitialContent?: boolean
188
+ burstRevealThresholdChars?: number
189
+ catchUpLatencyMs?: number
187
190
  catchUpThreshold?: number
191
+ flushOnFinish?: boolean
188
192
  maxCharsPerCommit?: number
189
193
  maxCharsPerSecond?: number
190
194
  maxCommitFps?: number
191
195
  minCharsPerSecond?: number
196
+ startDelayMs?: number
192
197
  targetLatencyMs?: number
193
198
  }
194
199
 
195
200
  export interface TextStreamController {
196
201
  destroy: () => void
202
+ dispose: () => void
197
203
  enqueue: (chunk: string) => void
198
204
  finish: (options?: { flush?: boolean }) => void
199
205
  flush: () => void
200
206
  getSnapshot: () => TextStreamSnapshot
201
207
  pause: () => void
202
- reset: (content?: string) => void
208
+ reset: (content?: string, options?: { prefixKnown?: boolean }) => void
203
209
  resume: () => void
204
210
  subscribe: (listener: () => void) => () => void
205
211
  }
@@ -220,3 +226,28 @@ export interface AgentEventChannel {
220
226
  push: (event: AgentStreamEvent) => void
221
227
  source: AsyncIterable<AgentStreamEvent>
222
228
  }
229
+
230
+ export interface AgentThreadVersion {
231
+ readonly createdAt?: string
232
+ readonly id: string
233
+ readonly label?: string
234
+ readonly messageId?: string
235
+ readonly parentId?: string
236
+ readonly pinned?: boolean
237
+ readonly summary?: string
238
+ }
239
+
240
+ export interface AgentThreadSnapshot {
241
+ readonly activeVersionId?: string
242
+ readonly versions: readonly AgentThreadVersion[]
243
+ }
244
+
245
+ export interface AgentThreadController {
246
+ append: (version: AgentThreadVersion) => void
247
+ destroy: () => void
248
+ fork: (parentId: string, version: Omit<AgentThreadVersion, 'parentId'>) => void
249
+ getSnapshot: () => AgentThreadSnapshot
250
+ reset: (initial?: AgentThreadSnapshot) => void
251
+ select: (id: string) => void
252
+ subscribe: (listener: () => void) => () => void
253
+ }