@aleph-alpha/chat-kit 5.4.0 → 5.6.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/dist/{CkHistory.vue_vue_type_script_setup_true_lang-D9oP6oEj.js → CkHistory.vue_vue_type_script_setup_true_lang-DHzZgEn-.js} +28 -10
- package/dist/adapters/responses-api.d.ts +3 -1
- package/dist/adapters/responses-api.d.ts.map +1 -1
- package/dist/adapters/responses-api.js +158 -3
- package/dist/components/base/CkConversationLayout/CkConversationLayout.vue.d.ts +6 -0
- package/dist/components/base/CkConversationLayout/CkConversationLayout.vue.d.ts.map +1 -1
- package/dist/components/composed/CkConversation/CkConversation.vue.d.ts +6 -0
- package/dist/components/composed/CkConversation/CkConversation.vue.d.ts.map +1 -1
- package/dist/components/index.js +1 -1
- package/dist/composables/index.js +1 -1
- package/dist/handlers/index.js +1 -1
- package/dist/handlers/useMessageHandler.d.ts +7 -2
- package/dist/handlers/useMessageHandler.d.ts.map +1 -1
- package/dist/helpers/conversationTree.d.ts +44 -4
- package/dist/helpers/conversationTree.d.ts.map +1 -1
- package/dist/{index-CyrVnbS9.js → index-Hcwv9Hby.js} +3 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/services/types.d.ts +7 -0
- package/dist/services/types.d.ts.map +1 -1
- package/dist/types.d.ts +38 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/{useMessageHandler-N50Yj-NU.js → useMessageHandler-Tellov3w.js} +112 -30
- package/package.json +2 -2
- package/src/adapters/arena.spec.ts +86 -0
- package/src/adapters/responses-api.ts +276 -2
- package/src/components/base/CkConversationLayout/CkConversationLayout.vue +30 -4
- package/src/components/composed/CkConversation/CkConversation.vue +10 -0
- package/src/composables/useConversations.spec.ts +2 -0
- package/src/composables/useConversations.ts +1 -0
- package/src/handlers/useMessageHandler.ts +46 -6
- package/src/helpers/comparison.spec.ts +114 -0
- package/src/helpers/conversationTree.spec.ts +98 -0
- package/src/helpers/conversationTree.ts +211 -26
- package/src/index.ts +2 -0
- package/src/services/types.ts +7 -0
- package/src/types.ts +40 -0
package/dist/types.d.ts
CHANGED
|
@@ -89,11 +89,49 @@ export interface TreeMessage {
|
|
|
89
89
|
status: MessageStatus;
|
|
90
90
|
createdAt: Date;
|
|
91
91
|
metadata?: MessageMetadata;
|
|
92
|
+
/**
|
|
93
|
+
* When set, this node's `childrenIds` are a **comparison** (a preference
|
|
94
|
+
* pair / draft set rendered side-by-side) rather than ordinary regenerate
|
|
95
|
+
* alternatives. Set when the comparison is opened and left set once voted —
|
|
96
|
+
* the comparison stays a distinct, labelled view until the user continues
|
|
97
|
+
* past the winner, at which point it collapses to linear history.
|
|
98
|
+
*/
|
|
99
|
+
comparing?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* The child id chosen when a `comparing` node is voted on (mirrored to
|
|
102
|
+
* `activeChildIndex`). Absent = not yet voted. Its presence flips the
|
|
103
|
+
* comparison from the blind "awaiting vote" state to the revealed "resolved"
|
|
104
|
+
* state; once the winner branch gains children the comparison is history.
|
|
105
|
+
*/
|
|
106
|
+
comparisonWinnerId?: string;
|
|
92
107
|
}
|
|
93
108
|
export interface ConversationTree {
|
|
94
109
|
nodes: Record<string, TreeMessage>;
|
|
95
110
|
rootId: string | null;
|
|
96
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* One side of an active comparison: the head child that defines the lane plus
|
|
114
|
+
* that lane's full active sub-path (length 1 for a fresh pair, longer once the
|
|
115
|
+
* conversation has continued inside the lane).
|
|
116
|
+
*/
|
|
117
|
+
export interface ComparisonLane {
|
|
118
|
+
branchId: string;
|
|
119
|
+
path: BaseMessage[];
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* The single active comparison surfaced alongside the linear `messages` path.
|
|
123
|
+
* Non-null only while the active path's tail fork is unresolved (blind) or
|
|
124
|
+
* voted-but-not-continued (revealed). Its `forkParentId` is the last item of
|
|
125
|
+
* `messages`; everything below the fork lives in `lanes`.
|
|
126
|
+
*/
|
|
127
|
+
export interface ActiveComparison {
|
|
128
|
+
forkParentId: string;
|
|
129
|
+
/** false = awaiting vote (blind); true = voted, not yet continued (revealed). */
|
|
130
|
+
resolved: boolean;
|
|
131
|
+
/** The chosen lane's head id once resolved. */
|
|
132
|
+
winnerBranchId: string | null;
|
|
133
|
+
lanes: ComparisonLane[];
|
|
134
|
+
}
|
|
97
135
|
/**
|
|
98
136
|
* High-level conversation record consumed by `CkHistory`.
|
|
99
137
|
*
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE1D,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG,aAAa,GAAG,WAAW,GAAG,YAAY,CAAC;AAE9E;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,WAAW,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,kBAAkB,GAClB,kBAAkB,GAClB,uBAAuB,CAAC;AAE5B;;;;;;;;;;GAUG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEtD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,SAAS,EAAE,IAAI,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,CAAC,EAAE,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,47 +3,98 @@ import { reactive, ref, computed, readonly } from "vue";
|
|
|
3
3
|
function createEmptyTree() {
|
|
4
4
|
return { nodes: {}, rootId: null };
|
|
5
5
|
}
|
|
6
|
-
function
|
|
7
|
-
const
|
|
8
|
-
|
|
6
|
+
function toBaseMessage(nodes, node) {
|
|
7
|
+
const base = {
|
|
8
|
+
id: node.id,
|
|
9
|
+
role: node.role,
|
|
10
|
+
content: node.content,
|
|
11
|
+
createdAt: node.createdAt,
|
|
12
|
+
status: node.status,
|
|
13
|
+
...node.metadata !== void 0 ? { metadata: node.metadata } : {}
|
|
14
|
+
};
|
|
15
|
+
if (node.parentId !== null) {
|
|
16
|
+
const parent = nodes[node.parentId];
|
|
17
|
+
if (parent && parent.childrenIds.length > 1) {
|
|
18
|
+
base.siblingIds = [...parent.childrenIds];
|
|
19
|
+
base.siblingIndex = parent.childrenIds.indexOf(node.id);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return base;
|
|
23
|
+
}
|
|
24
|
+
function isActiveComparison(nodes, node) {
|
|
25
|
+
if (!node.comparing || node.childrenIds.length < 2) return false;
|
|
26
|
+
const winnerId = node.comparisonWinnerId;
|
|
27
|
+
if (winnerId == null) return true;
|
|
28
|
+
const winner = nodes[winnerId];
|
|
29
|
+
return !winner || winner.childrenIds.length === 0;
|
|
30
|
+
}
|
|
31
|
+
function laneWalk(nodes, headId) {
|
|
9
32
|
const path = [];
|
|
33
|
+
let current = headId;
|
|
34
|
+
while (current !== null) {
|
|
35
|
+
const node = nodes[current];
|
|
36
|
+
if (!node) break;
|
|
37
|
+
path.push(toBaseMessage(nodes, node));
|
|
38
|
+
if (node.childrenIds.length === 0) break;
|
|
39
|
+
current = node.childrenIds[node.activeChildIndex];
|
|
40
|
+
}
|
|
41
|
+
return path;
|
|
42
|
+
}
|
|
43
|
+
function projectActivePath(tree) {
|
|
44
|
+
const { nodes, rootId } = tree;
|
|
45
|
+
const trunk = [];
|
|
46
|
+
if (!rootId || !nodes[rootId]) return { trunk, activeComparison: null };
|
|
10
47
|
let current = rootId;
|
|
11
48
|
while (current !== null) {
|
|
12
49
|
const node = nodes[current];
|
|
13
50
|
if (!node) break;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
51
|
+
trunk.push(toBaseMessage(nodes, node));
|
|
52
|
+
if (isActiveComparison(nodes, node)) {
|
|
53
|
+
const lanes = node.childrenIds.map((branchId) => ({
|
|
54
|
+
branchId,
|
|
55
|
+
path: laneWalk(nodes, branchId)
|
|
56
|
+
}));
|
|
57
|
+
const winnerBranchId = node.comparisonWinnerId ?? null;
|
|
58
|
+
return {
|
|
59
|
+
trunk,
|
|
60
|
+
activeComparison: {
|
|
61
|
+
forkParentId: node.id,
|
|
62
|
+
resolved: winnerBranchId !== null,
|
|
63
|
+
winnerBranchId,
|
|
64
|
+
lanes
|
|
65
|
+
}
|
|
66
|
+
};
|
|
28
67
|
}
|
|
29
|
-
path.push(base);
|
|
30
68
|
if (node.childrenIds.length === 0) break;
|
|
31
69
|
current = node.childrenIds[node.activeChildIndex];
|
|
32
70
|
}
|
|
33
|
-
return
|
|
71
|
+
return { trunk, activeComparison: null };
|
|
34
72
|
}
|
|
35
|
-
function addNode(tree, node) {
|
|
73
|
+
function addNode(tree, node, opts = { activate: true }) {
|
|
36
74
|
tree.nodes[node.id] = node;
|
|
37
75
|
if (node.parentId !== null) {
|
|
38
76
|
const parent = tree.nodes[node.parentId];
|
|
39
77
|
if (parent && !parent.childrenIds.includes(node.id)) {
|
|
40
78
|
parent.childrenIds.push(node.id);
|
|
41
|
-
|
|
79
|
+
if (opts.activate)
|
|
80
|
+
parent.activeChildIndex = parent.childrenIds.length - 1;
|
|
42
81
|
}
|
|
43
82
|
} else if (tree.rootId === null) {
|
|
44
83
|
tree.rootId = node.id;
|
|
45
84
|
}
|
|
46
85
|
}
|
|
86
|
+
function markComparison(tree, parentId) {
|
|
87
|
+
const parent = tree.nodes[parentId];
|
|
88
|
+
if (parent) parent.comparing = true;
|
|
89
|
+
}
|
|
90
|
+
function voteComparison(tree, parentId, winnerBranchId) {
|
|
91
|
+
const parent = tree.nodes[parentId];
|
|
92
|
+
if (!parent) return;
|
|
93
|
+
const idx = parent.childrenIds.indexOf(winnerBranchId);
|
|
94
|
+
if (idx === -1) return;
|
|
95
|
+
parent.comparisonWinnerId = winnerBranchId;
|
|
96
|
+
parent.activeChildIndex = idx;
|
|
97
|
+
}
|
|
47
98
|
function updateNode(tree, id, updates) {
|
|
48
99
|
const node = tree.nodes[id];
|
|
49
100
|
if (!node) return;
|
|
@@ -81,12 +132,18 @@ function deleteSubtrees(tree, ids) {
|
|
|
81
132
|
delete tree.nodes[currentId];
|
|
82
133
|
}
|
|
83
134
|
}
|
|
84
|
-
function cutBranchAfter(tree, id) {
|
|
135
|
+
function cutBranchAfter(tree, id, keepChildId) {
|
|
85
136
|
const node = tree.nodes[id];
|
|
86
|
-
if (!node) return;
|
|
87
|
-
|
|
88
|
-
|
|
137
|
+
if (!node || !Object.prototype.hasOwnProperty.call(tree.nodes, id)) return;
|
|
138
|
+
const kept = keepChildId !== void 0 && node.childrenIds.includes(keepChildId) ? keepChildId : null;
|
|
139
|
+
deleteSubtrees(
|
|
140
|
+
tree,
|
|
141
|
+
kept === null ? node.childrenIds : node.childrenIds.filter((childId) => childId !== kept)
|
|
142
|
+
);
|
|
143
|
+
node.childrenIds = kept === null ? [] : [kept];
|
|
89
144
|
node.activeChildIndex = 0;
|
|
145
|
+
delete node.comparing;
|
|
146
|
+
delete node.comparisonWinnerId;
|
|
90
147
|
}
|
|
91
148
|
function cutBranchAt(tree, id) {
|
|
92
149
|
const node = tree.nodes[id];
|
|
@@ -106,6 +163,14 @@ function cutBranchAt(tree, id) {
|
|
|
106
163
|
if (parent.activeChildIndex >= parent.childrenIds.length) {
|
|
107
164
|
parent.activeChildIndex = Math.max(0, parent.childrenIds.length - 1);
|
|
108
165
|
}
|
|
166
|
+
if (parent.comparing) {
|
|
167
|
+
if (parent.childrenIds.length < 2) {
|
|
168
|
+
delete parent.comparing;
|
|
169
|
+
delete parent.comparisonWinnerId;
|
|
170
|
+
} else if (parent.comparisonWinnerId === id) {
|
|
171
|
+
delete parent.comparisonWinnerId;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
109
174
|
}
|
|
110
175
|
function navigate(tree, targetId) {
|
|
111
176
|
const node = tree.nodes[targetId];
|
|
@@ -119,9 +184,14 @@ function navigate(tree, targetId) {
|
|
|
119
184
|
const useMessageHandler = () => {
|
|
120
185
|
const tree = reactive(createEmptyTree());
|
|
121
186
|
const currentUserMessage = ref("");
|
|
122
|
-
const
|
|
187
|
+
const projection = computed(() => projectActivePath(tree));
|
|
188
|
+
const messages = computed(() => projection.value.trunk);
|
|
189
|
+
const activeComparison = computed(
|
|
190
|
+
() => projection.value.activeComparison
|
|
191
|
+
);
|
|
123
192
|
const currentLeafId = computed(() => {
|
|
124
|
-
|
|
193
|
+
if (projection.value.activeComparison) return null;
|
|
194
|
+
const list = projection.value.trunk;
|
|
125
195
|
return list.length > 0 ? list[list.length - 1].id : null;
|
|
126
196
|
});
|
|
127
197
|
function resolveParentId(parentId) {
|
|
@@ -171,6 +241,9 @@ const useMessageHandler = () => {
|
|
|
171
241
|
function updateMessage(message) {
|
|
172
242
|
const existing = tree.nodes[message.id];
|
|
173
243
|
if (existing) {
|
|
244
|
+
if (message.comparing && existing.parentId) {
|
|
245
|
+
markComparison(tree, existing.parentId);
|
|
246
|
+
}
|
|
174
247
|
updateNode(tree, message.id, {
|
|
175
248
|
content: message.content,
|
|
176
249
|
role: message.role,
|
|
@@ -178,9 +251,13 @@ const useMessageHandler = () => {
|
|
|
178
251
|
...message.metadata !== void 0 ? { metadata: message.metadata } : {}
|
|
179
252
|
});
|
|
180
253
|
} else {
|
|
254
|
+
const parentId = resolveParentId(message.parentId);
|
|
255
|
+
if (message.comparing && parentId) {
|
|
256
|
+
markComparison(tree, parentId);
|
|
257
|
+
}
|
|
181
258
|
const node = {
|
|
182
259
|
id: message.id,
|
|
183
|
-
parentId
|
|
260
|
+
parentId,
|
|
184
261
|
childrenIds: [],
|
|
185
262
|
activeChildIndex: 0,
|
|
186
263
|
role: message.role,
|
|
@@ -218,8 +295,8 @@ const useMessageHandler = () => {
|
|
|
218
295
|
function navigate$1(targetId) {
|
|
219
296
|
navigate(tree, targetId);
|
|
220
297
|
}
|
|
221
|
-
function cutBranchAfter$1(messageId) {
|
|
222
|
-
cutBranchAfter(tree, messageId);
|
|
298
|
+
function cutBranchAfter$1(messageId, keepChildId) {
|
|
299
|
+
cutBranchAfter(tree, messageId, keepChildId);
|
|
223
300
|
}
|
|
224
301
|
function cutBranchAt$1(messageId) {
|
|
225
302
|
cutBranchAt(tree, messageId);
|
|
@@ -227,8 +304,12 @@ const useMessageHandler = () => {
|
|
|
227
304
|
function getTree() {
|
|
228
305
|
return readonly(tree);
|
|
229
306
|
}
|
|
307
|
+
function voteComparison$1(parentId, winnerBranchId) {
|
|
308
|
+
voteComparison(tree, parentId, winnerBranchId);
|
|
309
|
+
}
|
|
230
310
|
return {
|
|
231
311
|
messages,
|
|
312
|
+
activeComparison,
|
|
232
313
|
currentUserMessage: readonly(currentUserMessage),
|
|
233
314
|
currentLeafId,
|
|
234
315
|
updateMessage,
|
|
@@ -242,6 +323,7 @@ const useMessageHandler = () => {
|
|
|
242
323
|
navigate: navigate$1,
|
|
243
324
|
cutBranchAfter: cutBranchAfter$1,
|
|
244
325
|
cutBranchAt: cutBranchAt$1,
|
|
326
|
+
voteComparison: voteComparison$1,
|
|
245
327
|
getTree
|
|
246
328
|
};
|
|
247
329
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aleph-alpha/chat-kit",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.6.0",
|
|
4
4
|
"description": "Chat kit package for building chat interfaces with Vue",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
"wait-on": "9.0.3",
|
|
108
108
|
"@aleph-alpha/eslint-config-frontend": "0.7.0",
|
|
109
109
|
"@aleph-alpha/prettier-config-frontend": "2.1.0",
|
|
110
|
-
"@aleph-alpha/tsconfig-frontend": "0.7.
|
|
110
|
+
"@aleph-alpha/tsconfig-frontend": "0.7.1"
|
|
111
111
|
},
|
|
112
112
|
"scripts": {
|
|
113
113
|
"build": "vite build && vue-tsc --project tsconfig.build.json --declaration --emitDeclarationOnly --outDir dist",
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { responsesToTree, type StoredResponse } from './responses-api';
|
|
4
|
+
|
|
5
|
+
function arenaResponse(
|
|
6
|
+
id: string,
|
|
7
|
+
matchupId: string,
|
|
8
|
+
slot: 'a' | 'b',
|
|
9
|
+
modelId: string,
|
|
10
|
+
answer: string,
|
|
11
|
+
): StoredResponse {
|
|
12
|
+
return {
|
|
13
|
+
id,
|
|
14
|
+
object: 'response',
|
|
15
|
+
created_at: 1,
|
|
16
|
+
completed_at: 2,
|
|
17
|
+
status: 'completed',
|
|
18
|
+
model: modelId,
|
|
19
|
+
previous_response_id: null,
|
|
20
|
+
request_input: [{ role: 'user', content: 'prompt' }],
|
|
21
|
+
output: [
|
|
22
|
+
{
|
|
23
|
+
type: 'message',
|
|
24
|
+
id: `msg-${id}`,
|
|
25
|
+
status: 'completed',
|
|
26
|
+
role: 'assistant',
|
|
27
|
+
content: [{ type: 'output_text', text: answer }],
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
metadata: {
|
|
31
|
+
arena: JSON.stringify({
|
|
32
|
+
matchup_id: matchupId,
|
|
33
|
+
slot,
|
|
34
|
+
model_id: modelId,
|
|
35
|
+
variant: 'king-of-the-hill',
|
|
36
|
+
}),
|
|
37
|
+
},
|
|
38
|
+
} as StoredResponse;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe('responsesToTree arena collapse', () => {
|
|
42
|
+
it('folds an unvoted pair into one comparison node with two lanes', () => {
|
|
43
|
+
const tree = responsesToTree([
|
|
44
|
+
arenaResponse('respA', 'm1', 'a', 'phoenix-latest', 'A'),
|
|
45
|
+
arenaResponse('respB', 'm1', 'b', 'kimi-k2.6', 'B'),
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
// Single root user node, marked comparing, with two assistant children.
|
|
49
|
+
const root = tree.nodes[tree.rootId!]!;
|
|
50
|
+
expect(root.role).toBe('user');
|
|
51
|
+
expect(root.comparing).toBe(true);
|
|
52
|
+
expect(root.comparisonWinnerId).toBeUndefined();
|
|
53
|
+
expect(root.childrenIds).toHaveLength(2);
|
|
54
|
+
|
|
55
|
+
const children = root.childrenIds.map((id) => tree.nodes[id]!);
|
|
56
|
+
expect(children.every((c) => c.role === 'assistant')).toBe(true);
|
|
57
|
+
// Model id stamped for lane labels; ordered slot a then b.
|
|
58
|
+
const slots = children.map(
|
|
59
|
+
(c) => (c.metadata.arena as { slot?: string }).slot,
|
|
60
|
+
);
|
|
61
|
+
expect(slots).toEqual(['a', 'b']);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('marks the recorded winner when arenaWinners is supplied', () => {
|
|
65
|
+
const tree = responsesToTree(
|
|
66
|
+
[
|
|
67
|
+
arenaResponse('respA', 'm1', 'a', 'phoenix-latest', 'A'),
|
|
68
|
+
arenaResponse('respB', 'm1', 'b', 'kimi-k2.6', 'B'),
|
|
69
|
+
],
|
|
70
|
+
{ arenaWinners: { m1: 'respB' } },
|
|
71
|
+
);
|
|
72
|
+
const root = tree.nodes[tree.rootId!]!;
|
|
73
|
+
// Winner is respB's assistant node (its wire message id).
|
|
74
|
+
expect(root.comparisonWinnerId).toBe('msg-respB');
|
|
75
|
+
expect(root.childrenIds[root.activeChildIndex]).toBe('msg-respB');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('leaves a single surviving response as an ordinary linear turn', () => {
|
|
79
|
+
// 7-Discard: after continue, the BE dropped the loser — one response left.
|
|
80
|
+
const tree = responsesToTree([
|
|
81
|
+
arenaResponse('respA', 'm1', 'a', 'phoenix-latest', 'A'),
|
|
82
|
+
]);
|
|
83
|
+
const root = tree.nodes[tree.rootId!]!;
|
|
84
|
+
expect(root.comparing).toBeUndefined();
|
|
85
|
+
});
|
|
86
|
+
});
|