@lota-sdk/ui 0.4.10 → 0.4.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lota-sdk/ui",
3
- "version": "0.4.10",
3
+ "version": "0.4.12",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -25,8 +25,8 @@
25
25
  "registry": "https://registry.npmjs.org/"
26
26
  },
27
27
  "dependencies": {
28
- "@lota-sdk/shared": "0.4.10",
29
- "ai": "^6.0.167"
28
+ "@lota-sdk/shared": "0.4.12",
29
+ "ai": "^6.0.168"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "@ai-sdk/react": "^3.0.118",
@@ -34,8 +34,8 @@
34
34
  "react": "^19.2.0"
35
35
  },
36
36
  "devDependencies": {
37
- "@ai-sdk/react": "^3.0.169",
38
- "@tanstack/react-query": "^5.99.0",
37
+ "@ai-sdk/react": "^3.0.170",
38
+ "@tanstack/react-query": "^5.99.1",
39
39
  "@types/react": "^19.2.14",
40
40
  "react": "^19.2.5"
41
41
  }
@@ -1,4 +1,5 @@
1
1
  export * from './active-thread-helpers'
2
+ export * from './live-turn-trace'
2
3
  export * from './session-common'
3
4
  export * from './use-active-thread-session'
4
5
  export * from './use-session-messages'
@@ -0,0 +1,146 @@
1
+ import { agentActivityDataSchema, multiAgentEventDataSchema, thinkingStepDataSchema } from '@lota-sdk/shared'
2
+ import type { AgentActivityData } from '@lota-sdk/shared'
3
+
4
+ export interface LiveTurnRoutingState {
5
+ phase: 'routing' | 'waiting-for-agent' | 'agent-message-persisted'
6
+ agentId?: string
7
+ agentName?: string
8
+ note?: string
9
+ }
10
+
11
+ export interface LiveTurnActivity {
12
+ id: string
13
+ traceId: string
14
+ kind: 'tool'
15
+ toolName: string
16
+ toolCallId?: string
17
+ agentId?: string
18
+ agentName?: string
19
+ status: 'running' | 'done' | 'error'
20
+ errorText?: string
21
+ }
22
+
23
+ export interface LiveTurnThinkingStep {
24
+ id: string
25
+ traceId: string
26
+ index: number
27
+ title: string
28
+ status: 'streaming' | 'done'
29
+ }
30
+
31
+ export interface LiveTurnTrace {
32
+ routing: LiveTurnRoutingState | null
33
+ activities: LiveTurnActivity[]
34
+ thinkingSteps: LiveTurnThinkingStep[]
35
+ }
36
+
37
+ export interface LiveTurnTraceDataPartLike {
38
+ type?: unknown
39
+ data?: unknown
40
+ }
41
+
42
+ export function createEmptyLiveTurnTrace(): LiveTurnTrace {
43
+ return { routing: null, activities: [], thinkingSteps: [] }
44
+ }
45
+
46
+ function toActivityStatus(phase: AgentActivityData['phase']): LiveTurnActivity['status'] {
47
+ if (phase === 'failed') return 'error'
48
+ if (phase === 'completed') return 'done'
49
+ return 'running'
50
+ }
51
+
52
+ function upsertActivity(current: LiveTurnActivity[], nextActivity: LiveTurnActivity): LiveTurnActivity[] {
53
+ const index = current.findIndex((activity) => activity.id === nextActivity.id)
54
+ if (index === -1) {
55
+ return [...current, nextActivity]
56
+ }
57
+
58
+ const updated = [...current]
59
+ updated[index] = { ...updated[index], ...nextActivity }
60
+ return updated
61
+ }
62
+
63
+ function upsertThinkingStep(current: LiveTurnThinkingStep[], nextStep: LiveTurnThinkingStep): LiveTurnThinkingStep[] {
64
+ const index = current.findIndex((step) => step.id === nextStep.id)
65
+ if (index === -1) {
66
+ return [...current, nextStep].sort((left, right) => left.index - right.index)
67
+ }
68
+
69
+ const updated = [...current]
70
+ updated[index] = { ...updated[index], ...nextStep }
71
+ return updated.sort((left, right) => left.index - right.index)
72
+ }
73
+
74
+ export function hasLiveTurnTrace(trace: LiveTurnTrace): boolean {
75
+ return trace.routing !== null || trace.activities.length > 0 || trace.thinkingSteps.length > 0
76
+ }
77
+
78
+ export function reduceLiveTurnTraceDataPart(
79
+ current: LiveTurnTrace,
80
+ dataPart: LiveTurnTraceDataPartLike,
81
+ ): LiveTurnTrace {
82
+ const partType = typeof dataPart.type === 'string' ? dataPart.type : ''
83
+ if (!partType.startsWith('data-')) {
84
+ return current
85
+ }
86
+
87
+ switch (partType) {
88
+ case 'data-multi-agent-event': {
89
+ const parsed = multiAgentEventDataSchema.safeParse(dataPart.data)
90
+ if (!parsed.success) return current
91
+
92
+ if (parsed.data.phase === 'complete') {
93
+ return createEmptyLiveTurnTrace()
94
+ }
95
+
96
+ return {
97
+ ...current,
98
+ routing: {
99
+ phase: parsed.data.phase,
100
+ ...(parsed.data.agentId ? { agentId: parsed.data.agentId } : {}),
101
+ ...(parsed.data.agentName ? { agentName: parsed.data.agentName } : {}),
102
+ ...(parsed.data.note ? { note: parsed.data.note } : {}),
103
+ },
104
+ }
105
+ }
106
+
107
+ case 'data-agent-activity': {
108
+ const parsed = agentActivityDataSchema.safeParse(dataPart.data)
109
+ if (!parsed.success) return current
110
+
111
+ return {
112
+ ...current,
113
+ activities: upsertActivity(current.activities, {
114
+ id: parsed.data.activityId,
115
+ traceId: parsed.data.traceId,
116
+ kind: parsed.data.kind,
117
+ toolName: parsed.data.toolName,
118
+ ...(parsed.data.toolCallId ? { toolCallId: parsed.data.toolCallId } : {}),
119
+ ...(parsed.data.agentId ? { agentId: parsed.data.agentId } : {}),
120
+ ...(parsed.data.agentName ? { agentName: parsed.data.agentName } : {}),
121
+ status: toActivityStatus(parsed.data.phase),
122
+ ...(parsed.data.errorText ? { errorText: parsed.data.errorText } : {}),
123
+ }),
124
+ }
125
+ }
126
+
127
+ case 'data-thinking-step': {
128
+ const parsed = thinkingStepDataSchema.safeParse(dataPart.data)
129
+ if (!parsed.success) return current
130
+
131
+ return {
132
+ ...current,
133
+ thinkingSteps: upsertThinkingStep(current.thinkingSteps, {
134
+ id: parsed.data.stepId,
135
+ traceId: parsed.data.traceId,
136
+ index: parsed.data.index,
137
+ title: parsed.data.title,
138
+ status: parsed.data.status,
139
+ }),
140
+ }
141
+ }
142
+
143
+ default:
144
+ return current
145
+ }
146
+ }