@varo-ui/ai 1.2.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/README.md +16 -1
- package/dist/index.d.mts +44 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +340 -46
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/agent-stream.ts +17 -2
- package/src/event-channel.ts +35 -12
- package/src/index.ts +1 -0
- package/src/markdown-view.ts +126 -45
- package/src/sse.ts +34 -9
- package/src/text-stream.ts +126 -39
- package/src/thread.ts +160 -0
- package/src/types.ts +48 -17
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
+
}
|