@adea-ai/ui 0.67.1 → 0.68.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 +58 -0
- package/dist/NOTICE +34 -0
- package/dist/components/conversation/index.d.ts +1 -0
- package/dist/components/conversation/index.d.ts.map +1 -1
- package/dist/components/conversation/index.js +2 -1
- package/dist/components/conversation/transcript-composition.d.ts +66 -0
- package/dist/components/conversation/transcript-composition.d.ts.map +1 -0
- package/dist/components/conversation/transcript-composition.js +395 -0
- package/dist/components/conversation/transcript-composition.js.map +1 -0
- package/dist/components/conversation/transcript-folding.d.ts +22 -0
- package/dist/components/conversation/transcript-folding.d.ts.map +1 -0
- package/dist/components/conversation/transcript-folding.js +43 -0
- package/dist/components/conversation/transcript-folding.js.map +1 -0
- package/dist/components/conversation/transcript-grouping.d.ts +54 -0
- package/dist/components/conversation/transcript-grouping.d.ts.map +1 -0
- package/dist/components/conversation/transcript-grouping.js +155 -0
- package/dist/components/conversation/transcript-grouping.js.map +1 -0
- package/dist/index.js +2 -1
- package/dist/r/conversation.json +15 -0
- package/dist/r/registry.json +15 -0
- package/dist/r/src/components/conversation/index.ts +17 -0
- package/dist/r/src/components/conversation/transcript-composition.tsx +555 -0
- package/dist/r/src/components/conversation/transcript-folding.ts +61 -0
- package/dist/r/src/components/conversation/transcript-grouping.ts +204 -0
- package/package.json +8 -1
- package/registry.json +15 -0
- package/src/components/conversation/index.ts +17 -0
- package/src/components/conversation/transcript-composition.tsx +555 -0
- package/src/components/conversation/transcript-folding.ts +61 -0
- package/src/components/conversation/transcript-grouping.ts +204 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0.
|
|
4
|
+
*
|
|
5
|
+
* Substantially translated from KiroCrew groupDisplayItems.ts at
|
|
6
|
+
* 283e136c0f902e965a535a7c9548c57c7504fed0. Protocol classification is supplied
|
|
7
|
+
* by the host; no Kiro role, metadata parser, store, or transport is imported.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** Immutable, already-redacted host rows. Unknown rows remain visible singles. */
|
|
11
|
+
export type TranscriptRow<T> = Readonly<{
|
|
12
|
+
id: string
|
|
13
|
+
value: T
|
|
14
|
+
hidden?: boolean
|
|
15
|
+
groupable?: boolean
|
|
16
|
+
working?: boolean
|
|
17
|
+
/** True only for a content-bearing reasoning trace, never an empty placeholder. */
|
|
18
|
+
reasoning?: boolean
|
|
19
|
+
opensTurn?: 'reset' | 'continue'
|
|
20
|
+
synthesis?: boolean
|
|
21
|
+
/** A proven answer boundary, supplied by the host rather than inferred from text. */
|
|
22
|
+
turnEnd?: boolean
|
|
23
|
+
/** Content that a synthesis does not restate; prevents interim folding. */
|
|
24
|
+
foreign?: boolean
|
|
25
|
+
/** Explicit host eligibility; unknown content never folds. */
|
|
26
|
+
fold?: 'tool' | 'prose'
|
|
27
|
+
/** Errors, approvals, questions, diffs, renderables and interactive payloads bypass every fold. */
|
|
28
|
+
alwaysVisible?: boolean
|
|
29
|
+
/** A host-designated substantive answer. No text-length or role heuristic is applied. */
|
|
30
|
+
conclusion?: boolean
|
|
31
|
+
/** Request/result classification is supplied by the host, never parsed from display text. */
|
|
32
|
+
call?: Readonly<{ phase: 'request' | 'result'; id?: string }>
|
|
33
|
+
}>
|
|
34
|
+
|
|
35
|
+
export type TranscriptTurnItem<T> =
|
|
36
|
+
| Readonly<{ kind: 'single'; row: TranscriptRow<T>; index: number }>
|
|
37
|
+
| Readonly<{ kind: 'group'; rows: readonly TranscriptRow<T>[]; startIndex: number }>
|
|
38
|
+
|
|
39
|
+
export type TranscriptDisplayItem<T> =
|
|
40
|
+
| TranscriptTurnItem<T>
|
|
41
|
+
| Readonly<{
|
|
42
|
+
kind: 'turn'
|
|
43
|
+
items: readonly TranscriptTurnItem<T>[]
|
|
44
|
+
/** Presentation bookkeeping, never evidence of successful runtime completion. */
|
|
45
|
+
complete: boolean
|
|
46
|
+
interim?: boolean
|
|
47
|
+
}>
|
|
48
|
+
|
|
49
|
+
export type GroupedTranscript<T> = Readonly<{
|
|
50
|
+
turns: readonly TranscriptDisplayItem<T>[]
|
|
51
|
+
trailingTurnIndex: number
|
|
52
|
+
}>
|
|
53
|
+
|
|
54
|
+
/** Ordered O(N) grouping; approvals are retained unless their host explicitly owns them elsewhere. */
|
|
55
|
+
export function groupTranscriptRows<T>(rows: readonly TranscriptRow<T>[]): GroupedTranscript<T> {
|
|
56
|
+
const raw: TranscriptTurnItem<T>[] = []
|
|
57
|
+
let group: TranscriptRow<T>[] = []
|
|
58
|
+
let groupStart = 0
|
|
59
|
+
rows.forEach((row, index) => {
|
|
60
|
+
if (row.hidden) return
|
|
61
|
+
if (row.groupable) {
|
|
62
|
+
if (!group.length) groupStart = index
|
|
63
|
+
group.push(row)
|
|
64
|
+
} else {
|
|
65
|
+
if (group.length) {
|
|
66
|
+
raw.push({ kind: 'group', rows: group, startIndex: groupStart })
|
|
67
|
+
group = []
|
|
68
|
+
}
|
|
69
|
+
raw.push({ kind: 'single', row, index })
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
if (group.length) raw.push({ kind: 'group', rows: group, startIndex: groupStart })
|
|
73
|
+
|
|
74
|
+
const turns: TranscriptDisplayItem<T>[] = []
|
|
75
|
+
let items: TranscriptTurnItem<T>[] = []
|
|
76
|
+
let regionStart = 0
|
|
77
|
+
let foreign = false
|
|
78
|
+
let pendingAnswer = false
|
|
79
|
+
const flush = (batch: TranscriptTurnItem<T>[]) => {
|
|
80
|
+
const working = batch.some((item) => item.kind === 'group' || item.row.working)
|
|
81
|
+
const reasoning = batch.reduce(
|
|
82
|
+
(count, item) => count + Number(item.kind === 'single' && item.row.reasoning === true),
|
|
83
|
+
0
|
|
84
|
+
)
|
|
85
|
+
if ((working && batch.length > 2) || reasoning >= 2)
|
|
86
|
+
turns.push({ kind: 'turn', items: batch, complete: true })
|
|
87
|
+
else turns.push(...batch)
|
|
88
|
+
}
|
|
89
|
+
const foldInterim = () => {
|
|
90
|
+
const region = turns.splice(regionStart)
|
|
91
|
+
const folded = region.flatMap((item) => (item.kind === 'turn' ? [...item.items] : [item]))
|
|
92
|
+
if (folded.length) turns.push({ kind: 'turn', items: folded, complete: true, interim: true })
|
|
93
|
+
}
|
|
94
|
+
const settleAnswer = () => {
|
|
95
|
+
if (!pendingAnswer) return
|
|
96
|
+
const end = items.findIndex((item) => item.kind === 'single' && item.row.turnEnd)
|
|
97
|
+
if (end >= 0) {
|
|
98
|
+
flush(items.slice(0, end + 1))
|
|
99
|
+
items = items.slice(end + 1)
|
|
100
|
+
regionStart = turns.length
|
|
101
|
+
// Recompute from retained rows: an unrelated injection after the answer
|
|
102
|
+
// must still protect the next wave, while an earlier one must not poison it.
|
|
103
|
+
foreign = items.some((item) => item.kind === 'single' && item.row.foreign)
|
|
104
|
+
} else foreign = true
|
|
105
|
+
pendingAnswer = false
|
|
106
|
+
}
|
|
107
|
+
for (const item of raw) {
|
|
108
|
+
if (item.kind === 'single' && item.row.synthesis) {
|
|
109
|
+
settleAnswer()
|
|
110
|
+
if (items.length) {
|
|
111
|
+
flush(items)
|
|
112
|
+
items = []
|
|
113
|
+
}
|
|
114
|
+
if (!foreign) foldInterim()
|
|
115
|
+
items.push(item)
|
|
116
|
+
regionStart = turns.length
|
|
117
|
+
pendingAnswer = true
|
|
118
|
+
continue
|
|
119
|
+
}
|
|
120
|
+
if (item.kind === 'single' && item.row.foreign) foreign = true
|
|
121
|
+
if (item.kind === 'single' && item.row.opensTurn) {
|
|
122
|
+
settleAnswer()
|
|
123
|
+
if (items.length) {
|
|
124
|
+
flush(items)
|
|
125
|
+
items = []
|
|
126
|
+
}
|
|
127
|
+
turns.push(item)
|
|
128
|
+
if (item.row.opensTurn === 'reset') {
|
|
129
|
+
regionStart = turns.length
|
|
130
|
+
foreign = false
|
|
131
|
+
pendingAnswer = false
|
|
132
|
+
}
|
|
133
|
+
continue
|
|
134
|
+
}
|
|
135
|
+
items.push(item)
|
|
136
|
+
}
|
|
137
|
+
let trailingTurnIndex = -1
|
|
138
|
+
if (items.length) {
|
|
139
|
+
const before = turns.length
|
|
140
|
+
flush(items)
|
|
141
|
+
if (turns.length === before + 1 && turns.at(-1)?.kind === 'turn')
|
|
142
|
+
trailingTurnIndex = turns.length - 1
|
|
143
|
+
}
|
|
144
|
+
return { turns, trailingTurnIndex }
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function sameItem<T>(a: TranscriptTurnItem<T>, b: TranscriptTurnItem<T>): boolean {
|
|
148
|
+
if (a.kind === 'single') return b.kind === 'single' && a.row === b.row && a.index === b.index
|
|
149
|
+
if (b.kind !== 'group' || a.startIndex !== b.startIndex || a.rows.length !== b.rows.length)
|
|
150
|
+
return false
|
|
151
|
+
return a.rows.every((row, index) => row === b.rows[index])
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function sameDisplayItem<T>(a: TranscriptDisplayItem<T>, b: TranscriptDisplayItem<T>): boolean {
|
|
155
|
+
if (a.kind === 'turn') {
|
|
156
|
+
return (
|
|
157
|
+
b.kind === 'turn' &&
|
|
158
|
+
a.complete === b.complete &&
|
|
159
|
+
!!a.interim === !!b.interim &&
|
|
160
|
+
a.items.length === b.items.length &&
|
|
161
|
+
a.items.every((item, index) => sameItem(item, b.items[index]!))
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
return b.kind !== 'turn' && sameItem(a, b)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** One previous immutable input/result pair per caller; no global or growing transcript cache. */
|
|
168
|
+
export function createTranscriptGrouper<T>(): (
|
|
169
|
+
rows: readonly TranscriptRow<T>[]
|
|
170
|
+
) => GroupedTranscript<T> {
|
|
171
|
+
let previousRows: readonly TranscriptRow<T>[] | undefined
|
|
172
|
+
let previous: GroupedTranscript<T> | undefined
|
|
173
|
+
return (rows) => {
|
|
174
|
+
if (previous && rows === previousRows) return previous
|
|
175
|
+
const fresh = groupTranscriptRows(rows)
|
|
176
|
+
const turns = [...fresh.turns]
|
|
177
|
+
let allReused =
|
|
178
|
+
previous?.turns.length === turns.length &&
|
|
179
|
+
previous.trailingTurnIndex === fresh.trailingTurnIndex
|
|
180
|
+
if (previous) {
|
|
181
|
+
for (let index = 0; index < turns.length; index++) {
|
|
182
|
+
const candidate = previous.turns[index]
|
|
183
|
+
if (candidate && sameDisplayItem(turns[index]!, candidate)) turns[index] = candidate
|
|
184
|
+
else allReused = false
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
previousRows = rows
|
|
188
|
+
if (previous && allReused) return previous
|
|
189
|
+
previous = { turns, trailingTurnIndex: fresh.trailingTurnIndex }
|
|
190
|
+
return previous
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** Shallow-copies the display list and changes only its trailing turn. The host supplies running authority. */
|
|
195
|
+
export function applyTranscriptRunningState<T>(
|
|
196
|
+
grouped: GroupedTranscript<T>,
|
|
197
|
+
running: boolean
|
|
198
|
+
): readonly TranscriptDisplayItem<T>[] {
|
|
199
|
+
if (grouped.trailingTurnIndex < 0 || !running) return grouped.turns
|
|
200
|
+
const turns = [...grouped.turns]
|
|
201
|
+
const trailing = turns[grouped.trailingTurnIndex]
|
|
202
|
+
if (trailing?.kind === 'turn') turns[grouped.trailingTurnIndex] = { ...trailing, complete: false }
|
|
203
|
+
return turns
|
|
204
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adea-ai/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.68.0",
|
|
4
4
|
"description": "The Adea design system: Kobalte-backed Solid components, semantic OKLCH tokens, and the app-shell layout primitives shared by Adea and Cortana.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adea",
|
|
@@ -76,6 +76,12 @@
|
|
|
76
76
|
"solid": "./src/components/conversation/paste-tokens.ts",
|
|
77
77
|
"development": "./src/components/conversation/paste-tokens.ts",
|
|
78
78
|
"import": "./dist/components/conversation/paste-tokens.js"
|
|
79
|
+
},
|
|
80
|
+
"./components/conversation/transcript-composition": {
|
|
81
|
+
"types": "./dist/components/conversation/transcript-composition.d.ts",
|
|
82
|
+
"solid": "./src/components/conversation/transcript-composition.tsx",
|
|
83
|
+
"development": "./src/components/conversation/transcript-composition.tsx",
|
|
84
|
+
"import": "./dist/components/conversation/transcript-composition.js"
|
|
79
85
|
}
|
|
80
86
|
},
|
|
81
87
|
"scripts": {
|
|
@@ -93,6 +99,7 @@
|
|
|
93
99
|
"check:packed-layout": "node scripts/check-packed-layout.mjs",
|
|
94
100
|
"check:packed-consumer": "bun scripts/check-packed-consumer.ts",
|
|
95
101
|
"check:packed-conversation": "bun scripts/check-packed-conversation.ts",
|
|
102
|
+
"check:packed-transcript": "bun scripts/check-packed-transcript.ts",
|
|
96
103
|
"check:packed-layout-renderer": "bun scripts/check-packed-layout-renderer.ts",
|
|
97
104
|
"check:packed-appearance": "bun scripts/check-packed-appearance.ts",
|
|
98
105
|
"check:packed-paste-model": "node scripts/check-packed-paste-model.mjs"
|
package/registry.json
CHANGED
|
@@ -1890,6 +1890,21 @@
|
|
|
1890
1890
|
"path": "src/components/conversation/thread-panel.tsx",
|
|
1891
1891
|
"type": "registry:ui",
|
|
1892
1892
|
"target": "components/conversation/thread-panel.tsx"
|
|
1893
|
+
},
|
|
1894
|
+
{
|
|
1895
|
+
"path": "src/components/conversation/transcript-composition.tsx",
|
|
1896
|
+
"type": "registry:ui",
|
|
1897
|
+
"target": "components/conversation/transcript-composition.tsx"
|
|
1898
|
+
},
|
|
1899
|
+
{
|
|
1900
|
+
"path": "src/components/conversation/transcript-folding.ts",
|
|
1901
|
+
"type": "registry:ui",
|
|
1902
|
+
"target": "components/conversation/transcript-folding.ts"
|
|
1903
|
+
},
|
|
1904
|
+
{
|
|
1905
|
+
"path": "src/components/conversation/transcript-grouping.ts",
|
|
1906
|
+
"type": "registry:ui",
|
|
1907
|
+
"target": "components/conversation/transcript-grouping.ts"
|
|
1893
1908
|
}
|
|
1894
1909
|
]
|
|
1895
1910
|
},
|
|
@@ -23,6 +23,23 @@ export {
|
|
|
23
23
|
MessageRow,
|
|
24
24
|
type MessageRowProps,
|
|
25
25
|
} from './message-row'
|
|
26
|
+
export {
|
|
27
|
+
TranscriptComposition,
|
|
28
|
+
transcriptDisclosureKey,
|
|
29
|
+
type TranscriptCompositionProps,
|
|
30
|
+
type TranscriptCompositionFold,
|
|
31
|
+
type TranscriptCompositionRowContext,
|
|
32
|
+
type TranscriptCompositionRendererProps,
|
|
33
|
+
type TranscriptDisplayKind,
|
|
34
|
+
type GroupedTranscript,
|
|
35
|
+
type TranscriptDisplayItem,
|
|
36
|
+
type TranscriptFoldState,
|
|
37
|
+
type TranscriptFoldMode,
|
|
38
|
+
type TranscriptFoldPlan,
|
|
39
|
+
type TranscriptMounting,
|
|
40
|
+
type TranscriptRow,
|
|
41
|
+
type TranscriptTurnItem,
|
|
42
|
+
} from './transcript-composition'
|
|
26
43
|
export {
|
|
27
44
|
AttachmentCard,
|
|
28
45
|
ThreadPanel,
|