@assistant-ui/react 0.5.22 → 0.5.24

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.mjs CHANGED
@@ -2144,6 +2144,13 @@ var MessageRepository = class {
2144
2144
  }
2145
2145
  }
2146
2146
  if (operation !== "cut") {
2147
+ for (let current = newParent; current; current = current.prev) {
2148
+ if (current.current.id === child.current.id) {
2149
+ throw new Error(
2150
+ "MessageRepository(performOp/link): A message with the same id already exists in the parent tree. This error occurs if the same message id is found multiple times. This is likely an internal bug in assistant-ui."
2151
+ );
2152
+ }
2153
+ }
2147
2154
  newParentOrRoot.children = [
2148
2155
  ...newParentOrRoot.children,
2149
2156
  child.current.id
@@ -2273,6 +2280,25 @@ var MessageRepository = class {
2273
2280
  }
2274
2281
  }
2275
2282
  }
2283
+ export() {
2284
+ const exportItems = [];
2285
+ for (const [, message] of this.messages) {
2286
+ exportItems.push({
2287
+ message: message.current,
2288
+ parentId: message.prev?.current.id ?? null
2289
+ });
2290
+ }
2291
+ return {
2292
+ headId: this.head?.current.id ?? null,
2293
+ messages: exportItems
2294
+ };
2295
+ }
2296
+ import({ headId, messages }) {
2297
+ for (const { message, parentId } of messages) {
2298
+ this.addOrUpdateMessage(parentId, message);
2299
+ }
2300
+ this.resetHead(headId ?? messages.at(-1)?.message.id ?? null);
2301
+ }
2276
2302
  };
2277
2303
 
2278
2304
  // src/ui/base/tooltip-icon-button.tsx
@@ -2831,6 +2857,13 @@ var LocalThreadRuntime = class {
2831
2857
  this.performRoundtrip(parentId, message);
2832
2858
  }
2833
2859
  }
2860
+ export() {
2861
+ return this.repository.export();
2862
+ }
2863
+ import(data) {
2864
+ this.repository.import(data);
2865
+ this.notifySubscribers();
2866
+ }
2834
2867
  };
2835
2868
 
2836
2869
  // src/runtimes/local/LocalRuntime.tsx
@@ -2867,18 +2900,12 @@ var useLocalRuntime = (adapter, options) => {
2867
2900
  return runtime;
2868
2901
  };
2869
2902
 
2870
- // src/runtimes/external-store/ExternalStoreThreadRuntime.tsx
2871
- import { create as create15 } from "zustand";
2872
-
2873
2903
  // src/runtimes/external-store/getExternalStoreMessage.tsx
2874
2904
  var symbolInnerMessage = Symbol("innerMessage");
2875
2905
  var getExternalStoreMessage = (message) => {
2876
2906
  return message[symbolInnerMessage];
2877
2907
  };
2878
2908
 
2879
- // src/runtimes/external-store/useExternalStoreSync.tsx
2880
- import { useEffect as useEffect11, useInsertionEffect as useInsertionEffect4, useMemo as useMemo4, useRef as useRef6 } from "react";
2881
-
2882
2909
  // src/runtimes/external-store/ThreadMessageConverter.ts
2883
2910
  var ThreadMessageConverter = class {
2884
2911
  cache = /* @__PURE__ */ new WeakMap();
@@ -2899,6 +2926,7 @@ var AUTO_STATUS_COMPLETE = Object.freeze({
2899
2926
  type: "complete",
2900
2927
  reason: "unknown"
2901
2928
  });
2929
+ var isAutoStatus = (status) => status === AUTO_STATUS_RUNNING || status === AUTO_STATUS_COMPLETE;
2902
2930
  var getAutoStatus = (isLast, isRunning) => isLast && isRunning ? AUTO_STATUS_RUNNING : AUTO_STATUS_COMPLETE;
2903
2931
 
2904
2932
  // src/runtimes/external-store/ThreadMessageLike.tsx
@@ -2969,106 +2997,114 @@ var fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
2969
2997
  }
2970
2998
  };
2971
2999
 
2972
- // src/runtimes/external-store/useExternalStoreSync.tsx
2973
- var useExternalStoreSync = (adapter, updateData) => {
2974
- const adapterRef = useRef6(adapter);
2975
- useInsertionEffect4(() => {
2976
- adapterRef.current = adapter;
2977
- });
2978
- const [converter, convertCallback] = useMemo4(() => {
2979
- const converter2 = adapter.convertMessage ?? ((m) => m);
2980
- const convertCallback2 = (cache, m, idx) => {
2981
- const autoStatus = getAutoStatus(
2982
- adapterRef.current.messages.at(-1) === m,
2983
- adapterRef.current.isRunning ?? false
2984
- );
2985
- if (cache && (cache.role !== "assistant" || cache.status === autoStatus))
2986
- return cache;
2987
- const newMessage = fromThreadMessageLike(
2988
- converter2(m, idx),
2989
- idx.toString(),
2990
- autoStatus
2991
- );
2992
- newMessage[symbolInnerMessage] = m;
2993
- return newMessage;
2994
- };
2995
- return [new ThreadMessageConverter(), convertCallback2];
2996
- }, [adapter.convertMessage]);
2997
- useEffect11(() => {
2998
- updateData(
2999
- adapter.isDisabled ?? false,
3000
- adapter.isRunning ?? false,
3001
- converter.convertMessages(adapter.messages, convertCallback)
3002
- );
3003
- }, [
3004
- updateData,
3005
- converter,
3006
- convertCallback,
3007
- adapter.isDisabled,
3008
- adapter.isRunning,
3009
- adapter.messages
3010
- ]);
3011
- };
3012
-
3013
3000
  // src/runtimes/external-store/ExternalStoreThreadRuntime.tsx
3014
3001
  var hasUpcomingMessage = (isRunning, messages) => {
3015
3002
  return isRunning && messages[messages.length - 1]?.role !== "assistant";
3016
3003
  };
3017
3004
  var ExternalStoreThreadRuntime = class {
3018
- constructor(store) {
3019
- this.store = store;
3020
- this.updateData(
3021
- store.isDisabled ?? false,
3022
- store.isRunning ?? false,
3023
- store.messages
3024
- );
3025
- this.useStore = create15(() => ({
3026
- store
3027
- }));
3028
- }
3029
3005
  _subscriptions = /* @__PURE__ */ new Set();
3030
3006
  repository = new MessageRepository();
3031
3007
  assistantOptimisticId = null;
3032
- useStore;
3033
3008
  get capabilities() {
3034
3009
  return {
3035
- switchToBranch: this.store.setMessages !== void 0,
3036
- edit: this.store.onEdit !== void 0,
3037
- reload: this.store.onReload !== void 0,
3038
- cancel: this.store.onCancel !== void 0,
3039
- copy: this.store.onCopy !== null
3010
+ switchToBranch: this._store.setMessages !== void 0,
3011
+ edit: this._store.onEdit !== void 0,
3012
+ reload: this._store.onReload !== void 0,
3013
+ cancel: this._store.onCancel !== void 0,
3014
+ copy: this._store.onCopy !== null
3040
3015
  };
3041
3016
  }
3042
3017
  messages = [];
3043
3018
  isDisabled = false;
3044
3019
  isRunning = false;
3020
+ converter = new ThreadMessageConverter();
3021
+ _store;
3022
+ constructor(store) {
3023
+ this.store = store;
3024
+ }
3025
+ set store(store) {
3026
+ const oldStore = this._store;
3027
+ if (oldStore) {
3028
+ if (oldStore.convertMessage !== store.convertMessage) {
3029
+ this.converter = new ThreadMessageConverter();
3030
+ } else if (oldStore.isDisabled === store.isDisabled && oldStore.isRunning === store.isRunning && oldStore.messages === store.messages) {
3031
+ return;
3032
+ }
3033
+ }
3034
+ this._store = store;
3035
+ const isRunning = store.isRunning ?? false;
3036
+ const isDisabled = store.isDisabled ?? false;
3037
+ const convertCallback = (cache, m, idx) => {
3038
+ if (!store.convertMessage) return m;
3039
+ const isLast = idx === store.messages.length - 1;
3040
+ const autoStatus = getAutoStatus(isLast, isRunning);
3041
+ if (cache && (cache.role !== "assistant" || !isAutoStatus(cache.status) || cache.status === autoStatus))
3042
+ return cache;
3043
+ const newMessage = fromThreadMessageLike(
3044
+ store.convertMessage(m, idx),
3045
+ idx.toString(),
3046
+ autoStatus
3047
+ );
3048
+ newMessage[symbolInnerMessage] = m;
3049
+ return newMessage;
3050
+ };
3051
+ const messages = this.converter.convertMessages(
3052
+ store.messages,
3053
+ convertCallback
3054
+ );
3055
+ for (let i = 0; i < messages.length; i++) {
3056
+ const message = messages[i];
3057
+ const parent = messages[i - 1];
3058
+ this.repository.addOrUpdateMessage(parent?.id ?? null, message);
3059
+ }
3060
+ if (this.assistantOptimisticId) {
3061
+ this.repository.deleteMessage(this.assistantOptimisticId);
3062
+ this.assistantOptimisticId = null;
3063
+ }
3064
+ if (hasUpcomingMessage(isRunning, messages)) {
3065
+ this.assistantOptimisticId = this.repository.appendOptimisticMessage(
3066
+ messages.at(-1)?.id ?? null,
3067
+ {
3068
+ role: "assistant",
3069
+ content: []
3070
+ }
3071
+ );
3072
+ }
3073
+ this.repository.resetHead(
3074
+ this.assistantOptimisticId ?? messages.at(-1)?.id ?? null
3075
+ );
3076
+ this.messages = this.repository.getMessages();
3077
+ this.isDisabled = isDisabled;
3078
+ this.isRunning = isRunning;
3079
+ for (const callback of this._subscriptions) callback();
3080
+ }
3045
3081
  getBranches(messageId) {
3046
3082
  return this.repository.getBranches(messageId);
3047
3083
  }
3048
3084
  switchToBranch(branchId) {
3049
- if (!this.store.setMessages)
3085
+ if (!this._store.setMessages)
3050
3086
  throw new Error("Runtime does not support switching branches.");
3051
3087
  this.repository.switchToBranch(branchId);
3052
3088
  this.updateMessages(this.repository.getMessages());
3053
3089
  }
3054
3090
  async append(message) {
3055
3091
  if (message.parentId !== (this.messages.at(-1)?.id ?? null)) {
3056
- if (!this.store.onEdit)
3092
+ if (!this._store.onEdit)
3057
3093
  throw new Error("Runtime does not support editing messages.");
3058
- await this.store.onEdit(message);
3094
+ await this._store.onEdit(message);
3059
3095
  } else {
3060
- await this.store.onNew(message);
3096
+ await this._store.onNew(message);
3061
3097
  }
3062
3098
  }
3063
3099
  async startRun(parentId) {
3064
- if (!this.store.onReload)
3100
+ if (!this._store.onReload)
3065
3101
  throw new Error("Runtime does not support reloading messages.");
3066
- await this.store.onReload(parentId);
3102
+ await this._store.onReload(parentId);
3067
3103
  }
3068
3104
  cancelRun() {
3069
- if (!this.store.onCancel)
3105
+ if (!this._store.onCancel)
3070
3106
  throw new Error("Runtime does not support cancelling runs.");
3071
- this.store.onCancel();
3107
+ this._store.onCancel();
3072
3108
  if (this.assistantOptimisticId) {
3073
3109
  this.repository.deleteMessage(this.assistantOptimisticId);
3074
3110
  this.assistantOptimisticId = null;
@@ -3083,51 +3119,14 @@ var ExternalStoreThreadRuntime = class {
3083
3119
  return () => this._subscriptions.delete(callback);
3084
3120
  }
3085
3121
  updateMessages = (messages) => {
3086
- this.store.setMessages?.(
3122
+ this._store.setMessages?.(
3087
3123
  messages.flatMap(getExternalStoreMessage).filter((m) => m != null)
3088
3124
  );
3089
3125
  };
3090
- onStoreUpdated() {
3091
- if (this.useStore.getState().store !== this.store) {
3092
- this.useStore.setState({ store: this.store });
3093
- }
3094
- }
3095
- updateData = (isDisabled, isRunning, vm) => {
3096
- for (let i = 0; i < vm.length; i++) {
3097
- const message = vm[i];
3098
- const parent = vm[i - 1];
3099
- this.repository.addOrUpdateMessage(parent?.id ?? null, message);
3100
- }
3101
- if (this.assistantOptimisticId) {
3102
- this.repository.deleteMessage(this.assistantOptimisticId);
3103
- this.assistantOptimisticId = null;
3104
- }
3105
- if (hasUpcomingMessage(isRunning, vm)) {
3106
- this.assistantOptimisticId = this.repository.appendOptimisticMessage(
3107
- vm.at(-1)?.id ?? null,
3108
- {
3109
- role: "assistant",
3110
- content: []
3111
- }
3112
- );
3113
- }
3114
- this.repository.resetHead(
3115
- this.assistantOptimisticId ?? vm.at(-1)?.id ?? null
3116
- );
3117
- this.messages = this.repository.getMessages();
3118
- this.isDisabled = isDisabled;
3119
- this.isRunning = isRunning;
3120
- for (const callback of this._subscriptions) callback();
3121
- };
3122
- unstable_synchronizer = () => {
3123
- const { store } = this.useStore();
3124
- useExternalStoreSync(store, this.updateData);
3125
- return null;
3126
- };
3127
3126
  addToolResult(options) {
3128
- if (!this.store.onAddToolResult)
3127
+ if (!this._store.onAddToolResult)
3129
3128
  throw new Error("Runtime does not support tool results.");
3130
- this.store.onAddToolResult(options);
3129
+ this._store.onAddToolResult(options);
3131
3130
  }
3132
3131
  };
3133
3132
 
@@ -3140,9 +3139,6 @@ var ExternalStoreRuntime = class extends BaseAssistantRuntime {
3140
3139
  set store(store) {
3141
3140
  this.thread.store = store;
3142
3141
  }
3143
- onStoreUpdated() {
3144
- return this.thread.onStoreUpdated();
3145
- }
3146
3142
  getModelConfig() {
3147
3143
  return this._proxyConfigProvider.getModelConfig();
3148
3144
  }
@@ -3163,15 +3159,12 @@ var ExternalStoreRuntime = class extends BaseAssistantRuntime {
3163
3159
  };
3164
3160
 
3165
3161
  // src/runtimes/external-store/useExternalStoreRuntime.tsx
3166
- import { useEffect as useEffect12, useInsertionEffect as useInsertionEffect5, useState as useState10 } from "react";
3162
+ import { useInsertionEffect as useInsertionEffect4, useState as useState10 } from "react";
3167
3163
  var useExternalStoreRuntime = (store) => {
3168
3164
  const [runtime] = useState10(() => new ExternalStoreRuntime(store));
3169
- useInsertionEffect5(() => {
3165
+ useInsertionEffect4(() => {
3170
3166
  runtime.store = store;
3171
3167
  });
3172
- useEffect12(() => {
3173
- runtime.onStoreUpdated();
3174
- });
3175
3168
  return runtime;
3176
3169
  };
3177
3170