@alia.onl/sdk 22.1.1 → 22.1.2
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/CHANGELOG.md +9 -0
- package/package.json +1 -1
- package/src/components/AmbientField.tsx +1 -1
- package/src/components/ReplyMarkdown.tsx +8 -8
- package/src/components/canvas/ChartRenderer.tsx +1 -1
- package/src/components/thought/ThoughtPanel.tsx +1 -1
- package/src/components/thread/AliaThread.tsx +2 -2
- package/src/hooks/useTimelineWindow.ts +1 -1
- package/src/lib/audio-level.ts +2 -2
- package/src/lib/catalogue-tool.ts +1 -1
- package/src/lib/citations.ts +1 -1
- package/src/runtime/conversations.ts +9 -5
- package/src/runtime/message-history.ts +1 -1
- package/src/runtime/thread/thought-utils.ts +3 -2
- package/src/runtime/thread/thread-history.ts +1 -1
- package/src/runtime/thread/timeline.ts +2 -2
- package/src/runtime/thread/tool-cards.ts +11 -7
- package/src/runtime/use-conversation-stream.ts +6 -2
- package/src/runtime/use-conversation-thread.ts +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @alia.onl/sdk
|
|
2
2
|
|
|
3
|
+
## 22.1.2
|
|
4
|
+
|
|
5
|
+
- **Every entry type-checks under `noUncheckedIndexedAccess`.** The SDK ships source, so a
|
|
6
|
+
consumer compiling with `"noUncheckedIndexedAccess": true` (Astro) type-checked the SDK under
|
|
7
|
+
it too and got errors from indexed reads in the runtime, thread, citation and catalogue-tool
|
|
8
|
+
modules (27 from `@alia.onl/sdk/runtime` alone). Each read is now narrowed where the index is
|
|
9
|
+
known to be in range, with a loop over the values where that is simpler. Behaviour is unchanged.
|
|
10
|
+
- `check:entry-types` compiles every entry with `noUncheckedIndexedAccess` on, so CI keeps it so.
|
|
11
|
+
|
|
3
12
|
## 22.1.1
|
|
4
13
|
|
|
5
14
|
- A delayed Stop acknowledgement cannot idle a newer turn, replace its sidebar
|
package/package.json
CHANGED
|
@@ -121,7 +121,7 @@ function parseBlockData(type: string, match: RegExpExecArray): any {
|
|
|
121
121
|
switch (type) {
|
|
122
122
|
case 'COMPACTLIST': {
|
|
123
123
|
const title = match[1];
|
|
124
|
-
const itemsText = match[2];
|
|
124
|
+
const itemsText = match[2] ?? '';
|
|
125
125
|
const items = itemsText
|
|
126
126
|
.split('\n')
|
|
127
127
|
.filter((line) => line.trim().startsWith('-'))
|
|
@@ -140,26 +140,26 @@ function parseBlockData(type: string, match: RegExpExecArray): any {
|
|
|
140
140
|
return {
|
|
141
141
|
type: match[1],
|
|
142
142
|
title: match[2],
|
|
143
|
-
content: match[3].trim(),
|
|
143
|
+
content: (match[3] ?? '').trim(),
|
|
144
144
|
};
|
|
145
145
|
}
|
|
146
146
|
case 'COMPARISON': {
|
|
147
147
|
const title = match[1];
|
|
148
|
-
const content = match[2];
|
|
148
|
+
const content = match[2] ?? '';
|
|
149
149
|
const leftMatch = content.match(/LEFT:\s*({.*?})/s);
|
|
150
150
|
const rightMatch = content.match(/RIGHT:\s*({.*?})/s);
|
|
151
151
|
const conclusionMatch = content.match(/CONCLUSION:\s*(.*?)$/s);
|
|
152
152
|
|
|
153
153
|
return {
|
|
154
154
|
title,
|
|
155
|
-
left: leftMatch ? JSON.parse(leftMatch[1]) : {},
|
|
156
|
-
right: rightMatch ? JSON.parse(rightMatch[1]) : {},
|
|
157
|
-
conclusion: conclusionMatch ? conclusionMatch[1].trim() : undefined,
|
|
155
|
+
left: leftMatch ? JSON.parse(leftMatch[1] ?? '') : {},
|
|
156
|
+
right: rightMatch ? JSON.parse(rightMatch[1] ?? '') : {},
|
|
157
|
+
conclusion: conclusionMatch ? (conclusionMatch[1] ?? '').trim() : undefined,
|
|
158
158
|
};
|
|
159
159
|
}
|
|
160
160
|
case 'TIMELINE': {
|
|
161
161
|
const title = match[1];
|
|
162
|
-
const itemsText = match[2];
|
|
162
|
+
const itemsText = match[2] ?? '';
|
|
163
163
|
const items = itemsText
|
|
164
164
|
.split('\n')
|
|
165
165
|
.filter((line) => line.trim().startsWith('-'))
|
|
@@ -183,7 +183,7 @@ function parseBlockData(type: string, match: RegExpExecArray): any {
|
|
|
183
183
|
}
|
|
184
184
|
case 'CREDIBILITY': {
|
|
185
185
|
return {
|
|
186
|
-
level: parseInt(match[1], 10),
|
|
186
|
+
level: parseInt(match[1] ?? '', 10),
|
|
187
187
|
source: match[2],
|
|
188
188
|
};
|
|
189
189
|
}
|
|
@@ -30,7 +30,7 @@ export function ChartRenderer({ data, title }: ChartRendererProps) {
|
|
|
30
30
|
labels.map((label, i) => ({ label, value: values[i] || 0 }));
|
|
31
31
|
|
|
32
32
|
if (chartType === 'line' && datasets.length === 1) {
|
|
33
|
-
const series = datasets[0];
|
|
33
|
+
const series = datasets[0] as (typeof datasets)[number];
|
|
34
34
|
return (
|
|
35
35
|
<LineChartCard
|
|
36
36
|
title={series.label || title}
|
|
@@ -129,7 +129,7 @@ function StepsTab({ steps, lifecycle }: { steps: ThoughtStep[]; lifecycle: TurnL
|
|
|
129
129
|
return <EmptyState variant="compact" description={t('thought.noSteps')} />;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
const last = steps[steps.length - 1];
|
|
132
|
+
const last = steps[steps.length - 1] as (typeof steps)[number];
|
|
133
133
|
const tail = live && (last.type === 'thinking' || last.type === 'writing') ? last : null;
|
|
134
134
|
const rows = tail === null ? steps : steps.slice(0, -1);
|
|
135
135
|
|
|
@@ -213,7 +213,7 @@ export const AliaThread = memo(function AliaThread({
|
|
|
213
213
|
if (index !== lastReplyIndex || index !== rows.length - 1) return false;
|
|
214
214
|
if (index < history.length || failedTurn?.anchorMessageId === message.id) return false;
|
|
215
215
|
for (let i = index - 1; i >= history.length; i--) {
|
|
216
|
-
if (rows[i]
|
|
216
|
+
if (rows[i]?.role === 'user') return true;
|
|
217
217
|
}
|
|
218
218
|
return false;
|
|
219
219
|
};
|
|
@@ -223,7 +223,7 @@ export const AliaThread = memo(function AliaThread({
|
|
|
223
223
|
* an old message belongs to the stretch that ended, not to the one on screen.
|
|
224
224
|
*/
|
|
225
225
|
const conversationOf = (index: number): string | undefined =>
|
|
226
|
-
index < history.length ? history[index]
|
|
226
|
+
index < history.length ? history[index]?.conversationId : conversationId;
|
|
227
227
|
|
|
228
228
|
// ── Which rows are mounted, and the scroll that goes with them ──
|
|
229
229
|
/** The row a cursor jump was aimed at, as an index into what is shown, or -1. */
|
package/src/lib/audio-level.ts
CHANGED
|
@@ -71,8 +71,8 @@ export function levelFromFrames(frames: readonly number[]): number {
|
|
|
71
71
|
if (frames.length === 0) return 0;
|
|
72
72
|
|
|
73
73
|
let sumSquares = 0;
|
|
74
|
-
for (
|
|
75
|
-
sumSquares +=
|
|
74
|
+
for (const frame of frames) {
|
|
75
|
+
sumSquares += frame * frame;
|
|
76
76
|
}
|
|
77
77
|
const rms = Math.sqrt(sumSquares / frames.length);
|
|
78
78
|
|
|
@@ -12,7 +12,7 @@ const CANONICAL_TOOL = /^(?:oxy|self)_([a-z][a-z0-9-]{0,63})__([A-Za-z0-9_-]+)$/
|
|
|
12
12
|
/** The app and tool of a canonical catalogue tool name, or `null` for any other name. */
|
|
13
13
|
export function parseCatalogueTool(toolName: string): { app: string; tool: string } | null {
|
|
14
14
|
const match = CANONICAL_TOOL.exec(toolName);
|
|
15
|
-
return match ? { app: match[1], tool: match[2] } : null;
|
|
15
|
+
return match ? { app: match[1] ?? '', tool: match[2] ?? '' } : null;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
/** The renderer key of a tool name (`<app>:<tool>`), or `null` when it is not a catalogue tool. */
|
package/src/lib/citations.ts
CHANGED
|
@@ -180,7 +180,7 @@ export function splitReferences(
|
|
|
180
180
|
const m = REFERENCE_LINE_RE.exec(line);
|
|
181
181
|
if (m) {
|
|
182
182
|
flush();
|
|
183
|
-
current = { id: Number(m[1]), rest: m[2] };
|
|
183
|
+
current = { id: Number(m[1]), rest: m[2] ?? '' };
|
|
184
184
|
} else if (current && line.trim().length > 0) {
|
|
185
185
|
// A legacy entry's URL sits on the indented line after the title.
|
|
186
186
|
current.rest += ` ${line.trim()}`;
|
|
@@ -275,13 +275,14 @@ function upsertOnTop(
|
|
|
275
275
|
if (moveExisting) {
|
|
276
276
|
// Remove the conversation from its current position (if it is in any page)
|
|
277
277
|
for (let i = 0; i < pages.length; i++) {
|
|
278
|
-
const
|
|
278
|
+
const page = pages[i] as ConversationsPage;
|
|
279
|
+
const existingIndex = page.conversations.findIndex((c) => c.id === row.id);
|
|
279
280
|
if (existingIndex >= 0) {
|
|
280
281
|
pages[i] = {
|
|
281
|
-
...
|
|
282
|
+
...page,
|
|
282
283
|
conversations: [
|
|
283
|
-
...
|
|
284
|
-
...
|
|
284
|
+
...page.conversations.slice(0, existingIndex),
|
|
285
|
+
...page.conversations.slice(existingIndex + 1),
|
|
285
286
|
],
|
|
286
287
|
};
|
|
287
288
|
break;
|
|
@@ -347,7 +348,10 @@ export function useSaveConversation() {
|
|
|
347
348
|
id,
|
|
348
349
|
title: offlineTitle,
|
|
349
350
|
lastMessage,
|
|
350
|
-
createdAt:
|
|
351
|
+
createdAt:
|
|
352
|
+
existingIndex >= 0
|
|
353
|
+
? (conversations[existingIndex] as Conversation).createdAt
|
|
354
|
+
: new Date(),
|
|
351
355
|
updatedAt: new Date(),
|
|
352
356
|
messages,
|
|
353
357
|
};
|
|
@@ -102,7 +102,7 @@ export function normalizeConversationMessages(messages: readonly Message[]): Mes
|
|
|
102
102
|
messages = messages.filter((message) => message.role !== 'system');
|
|
103
103
|
|
|
104
104
|
for (let index = 0; index < messages.length; index += 1) {
|
|
105
|
-
const current = messages[index];
|
|
105
|
+
const current = messages[index] as Message;
|
|
106
106
|
const placeholder = messages[index + 1];
|
|
107
107
|
const duplicate = messages[index + 2];
|
|
108
108
|
|
|
@@ -718,8 +718,9 @@ export function turnTiming(
|
|
|
718
718
|
const index = messages.findIndex((m) => m.id === message.id);
|
|
719
719
|
let sendStamp: number | null = null;
|
|
720
720
|
for (let i = index - 1; i >= 0; i -= 1) {
|
|
721
|
-
|
|
722
|
-
|
|
721
|
+
const earlier = messages[i];
|
|
722
|
+
if (earlier?.role === 'user') {
|
|
723
|
+
sendStamp = stampToMs(earlier.createdAt);
|
|
723
724
|
break;
|
|
724
725
|
}
|
|
725
726
|
}
|
|
@@ -95,7 +95,7 @@ export function threadHistory(
|
|
|
95
95
|
): ThreadMessage[] {
|
|
96
96
|
const history: ThreadMessage[] = [];
|
|
97
97
|
for (let page = pages.length - 1; page >= 0; page -= 1) {
|
|
98
|
-
for (const message of pages[page]
|
|
98
|
+
for (const message of pages[page]?.messages ?? []) {
|
|
99
99
|
if (message.conversationId === activeConversationId) continue;
|
|
100
100
|
history.push({ ...message, id: message.id ?? message.cursor });
|
|
101
101
|
}
|
|
@@ -76,7 +76,7 @@ function tailStart(count: number): number {
|
|
|
76
76
|
/** The anchor that keeps exactly the rows mounted now, from the row at `start`. */
|
|
77
77
|
export function pinAnchor(ids: readonly string[], start: number): TimelineAnchor {
|
|
78
78
|
if (start <= 0 || ids.length === 0) return TOP;
|
|
79
|
-
return { kind: 'row', id: ids[start] };
|
|
79
|
+
return { kind: 'row', id: ids[start] as string };
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
/**
|
|
@@ -124,7 +124,7 @@ export function sameTimelineShape(previous: readonly Shape[], next: readonly Sha
|
|
|
124
124
|
if (previous === next) return true;
|
|
125
125
|
if (previous.length !== next.length) return false;
|
|
126
126
|
for (let i = 0; i < next.length; i += 1) {
|
|
127
|
-
if (!sameShape(previous[i], next[i])) return false;
|
|
127
|
+
if (!sameShape(previous[i] as Shape, next[i] as Shape)) return false;
|
|
128
128
|
}
|
|
129
129
|
return true;
|
|
130
130
|
}
|
|
@@ -125,8 +125,8 @@ function toPoints(series: readonly PricePoint[], intraday: boolean, locale: stri
|
|
|
125
125
|
|
|
126
126
|
/** First-to-last change as a ratio, or none for a run that started at nothing. */
|
|
127
127
|
function runDelta(series: readonly PricePoint[]): number | undefined {
|
|
128
|
-
const first = series[0][1];
|
|
129
|
-
const last = series[series.length - 1][1];
|
|
128
|
+
const first = (series[0] as PricePoint)[1];
|
|
129
|
+
const last = (series[series.length - 1] as PricePoint)[1];
|
|
130
130
|
return first === 0 ? undefined : (last - first) / first;
|
|
131
131
|
}
|
|
132
132
|
|
|
@@ -189,7 +189,7 @@ export function marketChart(data: MarketCardData, t: Translate, locale: string):
|
|
|
189
189
|
id,
|
|
190
190
|
label: t(`market.range.${id}`),
|
|
191
191
|
data: toPoints(run, id === '1D', locale),
|
|
192
|
-
headline: quoted(data.price) ? data.price : run[run.length - 1][1],
|
|
192
|
+
headline: quoted(data.price) ? data.price : (run[run.length - 1] as PricePoint)[1],
|
|
193
193
|
delta: id === '1D' && quoted(data.changePct) ? data.changePct / 100 : runDelta(run),
|
|
194
194
|
});
|
|
195
195
|
}
|
|
@@ -205,7 +205,7 @@ export function marketChart(data: MarketCardData, t: Translate, locale: string):
|
|
|
205
205
|
if (intraday.length >= 2) {
|
|
206
206
|
notes.push(
|
|
207
207
|
[
|
|
208
|
-
`${t('market.open')} ${format(intraday[0])}`,
|
|
208
|
+
`${t('market.open')} ${format(intraday[0] as number)}`,
|
|
209
209
|
`${t('market.dayHigh')} ${format(Math.max(...intraday))}`,
|
|
210
210
|
`${t('market.dayLow')} ${format(Math.min(...intraday))}`,
|
|
211
211
|
].join(' · '),
|
|
@@ -220,7 +220,9 @@ export function marketChart(data: MarketCardData, t: Translate, locale: string):
|
|
|
220
220
|
return {
|
|
221
221
|
title: `${data.name} · ${data.symbol}`,
|
|
222
222
|
ranges,
|
|
223
|
-
defaultRange: ranges.some((r) => r.id === '1D')
|
|
223
|
+
defaultRange: ranges.some((r) => r.id === '1D')
|
|
224
|
+
? '1D'
|
|
225
|
+
: (ranges[0] as (typeof ranges)[number]).id,
|
|
224
226
|
format,
|
|
225
227
|
formatAxisValue: (value) => formatAxis(value, locale),
|
|
226
228
|
notes,
|
|
@@ -275,7 +277,7 @@ export function faircoinChart(
|
|
|
275
277
|
id,
|
|
276
278
|
label: t(`faircoin.range.${id}`),
|
|
277
279
|
data: toPoints(run, id === '24h', locale),
|
|
278
|
-
headline: quoted(data.price) ? data.price : run[run.length - 1][1],
|
|
280
|
+
headline: quoted(data.price) ? data.price : (run[run.length - 1] as PricePoint)[1],
|
|
279
281
|
delta: id === '24h' && quoted(data.changePct) ? data.changePct / 100 : runDelta(run),
|
|
280
282
|
});
|
|
281
283
|
}
|
|
@@ -331,7 +333,9 @@ export function faircoinChart(
|
|
|
331
333
|
chart: {
|
|
332
334
|
title: `${t('faircoin.name')} · ${t('faircoin.symbol')}`,
|
|
333
335
|
ranges,
|
|
334
|
-
defaultRange: ranges.some((r) => r.id === '24h')
|
|
336
|
+
defaultRange: ranges.some((r) => r.id === '24h')
|
|
337
|
+
? '24h'
|
|
338
|
+
: (ranges[0] as (typeof ranges)[number]).id,
|
|
335
339
|
format,
|
|
336
340
|
formatAxisValue: (value) => formatAxis(value, locale),
|
|
337
341
|
notes: [],
|
|
@@ -897,7 +897,7 @@ export function useConversationStream({
|
|
|
897
897
|
const idx = invocations.findIndex((t) => t.toolCallId === tool_call_id);
|
|
898
898
|
if (idx >= 0) {
|
|
899
899
|
invocations[idx] = {
|
|
900
|
-
...invocations[idx],
|
|
900
|
+
...(invocations[idx] as ToolInvocation),
|
|
901
901
|
state: 'result',
|
|
902
902
|
result: output,
|
|
903
903
|
};
|
|
@@ -1254,7 +1254,11 @@ export function useConversationStream({
|
|
|
1254
1254
|
const idx = invocations.findIndex((t) => t.toolCallId === tool_call_id);
|
|
1255
1255
|
|
|
1256
1256
|
if (idx >= 0) {
|
|
1257
|
-
invocations[idx] = {
|
|
1257
|
+
invocations[idx] = {
|
|
1258
|
+
...(invocations[idx] as ToolInvocation),
|
|
1259
|
+
state: 'result',
|
|
1260
|
+
result: output,
|
|
1261
|
+
};
|
|
1258
1262
|
} else {
|
|
1259
1263
|
invocations.push({
|
|
1260
1264
|
toolCallId: tool_call_id,
|
|
@@ -435,7 +435,8 @@ export function useConversationThread({
|
|
|
435
435
|
(assistantMessageId: string): Message | undefined => {
|
|
436
436
|
const idx = messages.findIndex((msg) => msg.id === assistantMessageId);
|
|
437
437
|
for (let i = idx - 1; i >= 0; i--) {
|
|
438
|
-
|
|
438
|
+
const earlier = messages[i];
|
|
439
|
+
if (earlier?.role === 'user') return earlier;
|
|
439
440
|
}
|
|
440
441
|
return undefined;
|
|
441
442
|
},
|