@alia.onl/sdk 21.2.0 → 21.3.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/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @alia.onl/sdk
2
2
 
3
+ ## 21.3.0
4
+
5
+ The SDK runs on Expo SDK 58 (React Native 0.88, React 19.3) as well as Expo 57.
6
+
7
+ ### Changed
8
+
9
+ - **Peers admit Expo SDK 58.** Every `expo-*` peer is `^57.0.0 || ^58.0.0`, `react-native` is
10
+ `^0.86.0 || ^0.88.0` and `react-native-gesture-handler` `^2.32.0 || ^3.3.0` (SDK 58 ships 3.3).
11
+ `@oxy.so/bloom` is `>=10.21.0`, the first Bloom whose `TextInput` ref props type-check under
12
+ React Native 0.88's strict TypeScript API.
13
+
14
+ ### Fixed
15
+
16
+ - **A picked image is read with `expo-file-system`'s `File` API** (`new File(uri).base64()`). The
17
+ root entry's `readAsStringAsync` is the legacy API, which throws at runtime since the package
18
+ moved it to `expo-file-system/legacy`, so attaching a photo on iOS or Android failed.
19
+ - **An edit and a regenerate call `AliaRuntimeHost.onTurnStart`**, like a send from the composer
20
+ or a retry: each sends a new turn. A host that judges what a turn does against the moment it
21
+ was sent (a host tool's staleness check) used to judge an edited or regenerated turn against the
22
+ turn before it. An edit that sends nothing (an unknown message, empty content) calls nothing.
23
+
3
24
  ## 21.2.0
4
25
 
5
26
  ### Added
package/README.md CHANGED
@@ -357,6 +357,8 @@ const host: AliaRuntimeHost = {
357
357
  </AliaRuntimeProvider>;
358
358
  ```
359
359
 
360
+ `onTurnStart` is called just before each turn the runtime sends — from the composer, a retry,
361
+ an edit or a regenerate — so a host can take what the turn will be judged against at that send.
360
362
  `onTurnEnd` is called exactly once for each turn the runtime sends, when it stops streaming —
361
363
  the answer was written, the person pressed Stop, or the turn failed — and only while the
362
364
  conversation that sent it is still mounted. A host that holds back what would take the chat off
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alia.onl/sdk",
3
- "version": "21.2.0",
3
+ "version": "21.3.0",
4
4
  "description": "Alia AI chat SDK — the conversation runtime, chat UI, voice calls and dictation for Oxy apps",
5
5
  "main": "src/index.ts",
6
6
  "react-native": "src/index.ts",
@@ -50,28 +50,28 @@
50
50
  },
51
51
  "peerDependencies": {
52
52
  "react": "^19.2.3",
53
- "react-native": "^0.86.0",
53
+ "react-native": "^0.86.0 || ^0.88.0",
54
54
  "@expo/vector-icons": "^15.1.1",
55
- "@oxy.so/bloom": ">=10.17.0",
55
+ "@oxy.so/bloom": ">=10.21.0",
56
56
  "@oxy.so/core": ">=3.0.0",
57
57
  "@oxy.so/services": ">=11.12.0",
58
58
  "@tanstack/react-query": "^5.101",
59
59
  "@react-native-async-storage/async-storage": "^2.2.0",
60
- "expo-blur": "^57.0.0",
60
+ "expo-blur": "^57.0.0 || ^58.0.0",
61
61
  "react-native-reanimated": "^4.5.0",
62
- "react-native-gesture-handler": "^2.32.0",
62
+ "react-native-gesture-handler": "^2.32.0 || ^3.3.0",
63
63
  "react-native-safe-area-context": "^5.8.0",
64
64
  "react-native-keyboard-controller": "^1.21.9",
65
65
  "react-native-svg": "^15.15.5",
66
- "expo-audio": "^57.0.0",
67
- "expo-image": "^57.0.0",
68
- "expo-image-picker": "^57.0.2",
69
- "expo-document-picker": "^57.0.0",
70
- "expo-haptics": "^57.0.0",
66
+ "expo-audio": "^57.0.0 || ^58.0.0",
67
+ "expo-image": "^57.0.0 || ^58.0.0",
68
+ "expo-image-picker": "^57.0.2 || ^58.0.0",
69
+ "expo-document-picker": "^57.0.0 || ^58.0.0",
70
+ "expo-haptics": "^57.0.0 || ^58.0.0",
71
71
  "nativewind": "^5.0.0-preview.3",
72
- "expo-clipboard": "^57.0.0",
73
- "expo-file-system": "^57.0.0",
74
- "expo-web-browser": "^57.0.0",
72
+ "expo-clipboard": "^57.0.0 || ^58.0.0",
73
+ "expo-file-system": "^57.0.0 || ^58.0.0",
74
+ "expo-web-browser": "^57.0.0 || ^58.0.0",
75
75
  "react-native-css": "^3.0.7",
76
76
  "react-native-audio-api": "^0.13.6"
77
77
  },
@@ -85,7 +85,7 @@
85
85
  },
86
86
  "devDependencies": {
87
87
  "@types/react-test-renderer": "^19.1.0",
88
- "react-test-renderer": "19.2.3",
88
+ "react-test-renderer": "19.3.0",
89
89
  "typescript": "^5.9.3",
90
90
  "vitest": "^4.1.10",
91
91
  "react-native-audio-api": "0.13.6",
@@ -1,4 +1,4 @@
1
- import * as FileSystem from 'expo-file-system';
1
+ import { File } from 'expo-file-system';
2
2
  import { Platform } from 'react-native';
3
3
 
4
4
  /**
@@ -12,9 +12,8 @@ import { Platform } from 'react-native';
12
12
  export async function imageUriToDataUrl(uri: string, mimeType?: string): Promise<string> {
13
13
  if (uri.startsWith('data:')) return uri;
14
14
  if (Platform.OS !== 'web') {
15
- const base64 = await FileSystem.readAsStringAsync(uri, {
16
- encoding: FileSystem.EncodingType.Base64,
17
- });
15
+ // The `File` API: the legacy `readAsStringAsync` from the package root throws at runtime.
16
+ const base64 = await new File(uri).base64();
18
17
  return `data:${mimeType || 'image/jpeg'};base64,${base64}`;
19
18
  }
20
19
  const blob = await (await fetch(uri)).blob();
@@ -4,6 +4,7 @@ import type { TextInput } from 'react-native';
4
4
  /**
5
5
  * What a ref to a `TextInput` holds. `ComponentRef`, not `TextInput` itself: React Native 0.88
6
6
  * types `TextInput` as a function component, so the class is no longer its instance type, and
7
- * `focus()` is only on the instance.
7
+ * `focus()` is only on the instance. An interface rather than an alias, so a declaration that
8
+ * returns one can name it: on 0.88 the instance type lives in a file React Native does not export.
8
9
  */
9
- export type TextInputHandle = ComponentRef<typeof TextInput>;
10
+ export interface TextInputHandle extends ComponentRef<typeof TextInput> {}
@@ -70,7 +70,7 @@ export interface AliaRuntimeHost {
70
70
  deviceInfo?: () => Promise<unknown>;
71
71
  /** The modes the host's composer controls own; read when the turn is sent, not when it is built. */
72
72
  turnRequest?: () => AliaTurnRequest;
73
- /** A turn is about to be sent from the composer or a retry. */
73
+ /** A turn is about to be sent: from the composer, a retry, an edit or a regenerate. */
74
74
  onTurnStart?: () => void;
75
75
  /**
76
76
  * A turn this runtime sent has stopped streaming: it finished, was stopped, or failed. Called
@@ -394,6 +394,9 @@ export function useConversationThread({
394
394
  }
395
395
  if (isEmptyContent(content)) return false;
396
396
 
397
+ // An edit sends a new turn (so does a regenerate, through here).
398
+ host.onTurnStart?.();
399
+
397
400
  setMessages((prev) => {
398
401
  const idx = prev.findIndex((msg) => msg.id === messageId);
399
402
  return idx < 0 ? prev : prev.slice(0, idx);
@@ -420,7 +423,7 @@ export function useConversationThread({
420
423
  releaseAttachments(attachments ?? []);
421
424
  return true;
422
425
  },
423
- [setMessages, append, messages, conversationId, labels, upload],
426
+ [setMessages, append, messages, conversationId, host, labels, upload],
424
427
  );
425
428
 
426
429
  /** The user turn a reply answers: the nearest one before it, or `undefined`. */