@lota-sdk/ui 0.1.5
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 +57 -0
- package/src/chat/attachments.ts +83 -0
- package/src/chat/index.ts +4 -0
- package/src/chat/message-parts.ts +101 -0
- package/src/chat/messages.ts +39 -0
- package/src/chat/transport.ts +8 -0
- package/src/index.ts +3 -0
- package/src/runtime/active-thread-helpers.ts +59 -0
- package/src/runtime/index.ts +6 -0
- package/src/runtime/session-common.ts +27 -0
- package/src/runtime/use-active-thread-session.ts +264 -0
- package/src/runtime/use-session-messages.ts +122 -0
- package/src/runtime/use-thread-chat.ts +109 -0
- package/src/runtime/use-thread-management.ts +328 -0
- package/src/tools/execution-plan.ts +80 -0
- package/src/tools/index.ts +3 -0
- package/src/tools/tool-registry.ts +22 -0
- package/src/tools/user-questions.ts +77 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { UserQuestionItem, UserQuestionsArgs } from '@lota-sdk/shared/schemas/tools'
|
|
2
|
+
|
|
3
|
+
export type UserQuestionAnswer = { selected: string[]; customText: string }
|
|
4
|
+
export type UserQuestionsSubmitPayload = {
|
|
5
|
+
text: string
|
|
6
|
+
questions: UserQuestionsArgs['questions']
|
|
7
|
+
answers: UserQuestionAnswer[]
|
|
8
|
+
}
|
|
9
|
+
export type UserQuestionsResolution = 'pending' | 'answered' | 'skipped'
|
|
10
|
+
|
|
11
|
+
const ANSWER_PREFIX = 'Answers:'
|
|
12
|
+
|
|
13
|
+
export function formatUserQuestionsAnswerText(
|
|
14
|
+
questions: UserQuestionsArgs['questions'],
|
|
15
|
+
answers: UserQuestionAnswer[],
|
|
16
|
+
): string {
|
|
17
|
+
const lines = [ANSWER_PREFIX]
|
|
18
|
+
|
|
19
|
+
for (let index = 0; index < questions.length; index += 1) {
|
|
20
|
+
const question = questions[index]
|
|
21
|
+
const answer = answers.at(index)
|
|
22
|
+
const parts: string[] = []
|
|
23
|
+
|
|
24
|
+
if (answer) {
|
|
25
|
+
for (const selected of answer.selected) {
|
|
26
|
+
parts.push(selected)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (answer.customText.trim()) {
|
|
30
|
+
parts.push(`custom: "${answer.customText.trim()}"`)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
lines.push(`${index + 1}. ${question.question}: ${parts.join(', ') || '(no answer)'}`)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return lines.join('\n')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function resolveUserQuestionsResolution<
|
|
41
|
+
TMessage extends { role: string; parts: Array<{ type: string; text?: string }> },
|
|
42
|
+
>(messages: TMessage[] | undefined, currentMessageIndex: number | undefined): UserQuestionsResolution {
|
|
43
|
+
if (!messages || typeof currentMessageIndex !== 'number') return 'pending'
|
|
44
|
+
if (currentMessageIndex < 0 || currentMessageIndex >= messages.length - 1) return 'pending'
|
|
45
|
+
|
|
46
|
+
const nextMessage = messages[currentMessageIndex + 1]
|
|
47
|
+
if (nextMessage.role === 'user') {
|
|
48
|
+
const textPart = nextMessage.parts.find(
|
|
49
|
+
(part) => part.type === 'text' && typeof part.text === 'string' && part.text.length > 0,
|
|
50
|
+
)
|
|
51
|
+
if (textPart?.text?.startsWith(ANSWER_PREFIX)) return 'answered'
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return 'skipped'
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function createInitialUserQuestionAnswers(questions: UserQuestionsArgs['questions']): UserQuestionAnswer[] {
|
|
58
|
+
return questions.map(() => ({ selected: [], customText: '' }))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function toUserQuestionKey(question: UserQuestionItem): string {
|
|
62
|
+
const options = question.options?.join('|') ?? ''
|
|
63
|
+
return `${question.type}:${question.question}:${options}:${question.allowCustomAnswer === false ? 'fixed' : 'custom'}`
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function withDedupedQuestionValues(values: string[]): Array<{ key: string; value: string }> {
|
|
67
|
+
const seen = new Map<string, number>()
|
|
68
|
+
return values.map((value) => {
|
|
69
|
+
const count = (seen.get(value) ?? 0) + 1
|
|
70
|
+
seen.set(value, count)
|
|
71
|
+
return { key: count === 1 ? value : `${value}__${count}`, value }
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function toUserQuestionsResetKey(questions: UserQuestionsArgs['questions']): string {
|
|
76
|
+
return questions.map((question) => toUserQuestionKey(question)).join('||')
|
|
77
|
+
}
|