@assistant-ui/core 0.2.22 → 0.2.23
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/adapters/thread-history.d.ts +8 -0
- package/dist/adapters/thread-history.d.ts.map +1 -1
- package/dist/internal.d.ts +3 -2
- package/dist/internal.js +3 -2
- package/dist/model-context/frame/host.d.ts.map +1 -1
- package/dist/model-context/frame/host.js +36 -21
- package/dist/model-context/frame/host.js.map +1 -1
- package/dist/model-context/types.d.ts.map +1 -1
- package/dist/model-context/types.js +13 -4
- package/dist/model-context/types.js.map +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
- package/dist/react/adapters/LocalStorageThreadListAdapter.js +1 -0
- package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
- package/dist/react/client/interactable-model-context.js +1 -0
- package/dist/react/client/interactable-model-context.js.map +1 -1
- package/dist/react/interactables-legacy/useInteractableState.js +1 -0
- package/dist/react/interactables-legacy/useInteractableState.js.map +1 -1
- package/dist/react/model-context/useInteractableState.js +1 -0
- package/dist/react/model-context/useInteractableState.js.map +1 -1
- package/dist/react/model-context/useInteractableVersions.js +1 -0
- package/dist/react/model-context/useInteractableVersions.js.map +1 -1
- package/dist/react/model-context/useToolArgsStatus.js +1 -0
- package/dist/react/model-context/useToolArgsStatus.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarCopy.js +1 -0
- package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarEdit.js +1 -0
- package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarFeedback.js +1 -0
- package/dist/react/primitive-hooks/useActionBarFeedback.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarReload.js +1 -0
- package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarSpeak.js +1 -0
- package/dist/react/primitive-hooks/useActionBarSpeak.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarStopSpeaking.js +1 -0
- package/dist/react/primitive-hooks/useActionBarStopSpeaking.js.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerNext.js +1 -0
- package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerPrevious.js +1 -0
- package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerAddAttachment.js +1 -0
- package/dist/react/primitive-hooks/useComposerAddAttachment.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerCancel.js +1 -0
- package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerDictate.js +1 -0
- package/dist/react/primitive-hooks/useComposerDictate.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerSend.js +1 -0
- package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
- package/dist/react/primitive-hooks/useEditComposerCancel.js +1 -0
- package/dist/react/primitive-hooks/useEditComposerCancel.js.map +1 -1
- package/dist/react/primitive-hooks/useEditComposerSend.js +1 -0
- package/dist/react/primitive-hooks/useEditComposerSend.js.map +1 -1
- package/dist/react/primitive-hooks/useMessageBranching.js +1 -0
- package/dist/react/primitive-hooks/useMessageBranching.js.map +1 -1
- package/dist/react/primitive-hooks/useMessageReload.js +1 -0
- package/dist/react/primitive-hooks/useMessageReload.js.map +1 -1
- package/dist/react/primitive-hooks/useSuggestionTrigger.js +1 -0
- package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemArchive.js +1 -0
- package/dist/react/primitive-hooks/useThreadListItemArchive.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemDelete.js +1 -0
- package/dist/react/primitive-hooks/useThreadListItemDelete.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemTrigger.js +1 -0
- package/dist/react/primitive-hooks/useThreadListItemTrigger.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemUnarchive.js +1 -0
- package/dist/react/primitive-hooks/useThreadListItemUnarchive.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListLoadMore.js +1 -0
- package/dist/react/primitive-hooks/useThreadListLoadMore.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListNew.js +1 -0
- package/dist/react/primitive-hooks/useThreadListNew.js.map +1 -1
- package/dist/react/providers/TextMessagePartProvider.js +1 -0
- package/dist/react/providers/TextMessagePartProvider.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +6 -4
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +31 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +11 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +1 -1
- package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts +12 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.js +2 -1
- package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +75 -73
- package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
- package/dist/react/runtimes/external-message-converter.js +1 -1
- package/dist/react/runtimes/external-message-converter.js.map +1 -1
- package/dist/react/runtimes/useExternalStoreSharedOptions.js +1 -0
- package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -1
- package/dist/react/runtimes/useLocalRuntime.d.ts +0 -1
- package/dist/react/runtimes/useLocalRuntime.d.ts.map +1 -1
- package/dist/runtime/api/assistant-runtime.d.ts +1 -1
- package/dist/runtime/api/assistant-runtime.d.ts.map +1 -1
- package/dist/runtime/api/assistant-runtime.js +1 -1
- package/dist/runtime/api/assistant-runtime.js.map +1 -1
- package/dist/runtime/api/attachment-runtime.d.ts +1 -1
- package/dist/runtime/api/attachment-runtime.d.ts.map +1 -1
- package/dist/runtime/api/attachment-runtime.js +1 -1
- package/dist/runtime/api/attachment-runtime.js.map +1 -1
- package/dist/runtime/api/composer-runtime.d.ts +2 -2
- package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
- package/dist/runtime/api/composer-runtime.js +2 -2
- package/dist/runtime/api/composer-runtime.js.map +1 -1
- package/dist/runtime/api/message-part-runtime.d.ts +4 -4
- package/dist/runtime/api/message-part-runtime.d.ts.map +1 -1
- package/dist/runtime/api/message-part-runtime.js +3 -3
- package/dist/runtime/api/message-part-runtime.js.map +1 -1
- package/dist/runtime/api/message-runtime.d.ts +1 -1
- package/dist/runtime/api/message-runtime.d.ts.map +1 -1
- package/dist/runtime/api/message-runtime.js +2 -2
- package/dist/runtime/api/message-runtime.js.map +1 -1
- package/dist/runtime/api/thread-list-item-runtime.d.ts +1 -1
- package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-item-runtime.js +2 -2
- package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.js +1 -1
- package/dist/runtime/api/thread-list-runtime.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.d.ts +2 -2
- package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.js +2 -2
- package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
- package/dist/runtime/utils/message-repository.d.ts.map +1 -1
- package/dist/runtime/utils/message-repository.js +4 -2
- package/dist/runtime/utils/message-repository.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js +12 -0
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/internal.d.ts +2 -1
- package/dist/runtimes/internal.js +2 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts +3 -0
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js +44 -13
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +32 -27
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +2 -0
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
- package/dist/store/clients/no-op-composer-client.js +1 -0
- package/dist/store/clients/no-op-composer-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.js +1 -0
- package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.js +17 -15
- package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
- package/dist/store/scopes/thread.d.ts +1 -0
- package/dist/store/scopes/thread.d.ts.map +1 -1
- package/dist/subscribable/subscribable.d.ts +3 -3
- package/dist/subscribable/subscribable.d.ts.map +1 -1
- package/dist/subscribable/subscribable.js +3 -3
- package/dist/subscribable/subscribable.js.map +1 -1
- package/package.json +7 -7
- package/src/adapters/thread-history.ts +8 -0
- package/src/internal.ts +1 -1
- package/src/model-context/frame/host.test.ts +47 -0
- package/src/model-context/frame/host.ts +46 -19
- package/src/model-context/types.ts +16 -6
- package/src/react/adapters/LocalStorageThreadListAdapter.tsx +15 -5
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +20 -6
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.ts +34 -0
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +26 -5
- package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +5 -1
- package/src/react/runtimes/cloud/auiV0.ts +14 -0
- package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +90 -88
- package/src/react/runtimes/external-message-converter.test.ts +346 -0
- package/src/react/runtimes/external-message-converter.ts +1 -1
- package/src/react/runtimes/useLocalRuntime.test.tsx +43 -0
- package/src/runtime/api/assistant-runtime.ts +4 -1
- package/src/runtime/api/attachment-runtime.ts +8 -2
- package/src/runtime/api/composer-runtime.ts +9 -5
- package/src/runtime/api/message-part-runtime.ts +10 -3
- package/src/runtime/api/message-runtime.ts +7 -2
- package/src/runtime/api/thread-list-item-runtime.ts +7 -2
- package/src/runtime/api/thread-list-runtime.ts +10 -2
- package/src/runtime/base/base-thread-runtime-core.ts +5 -1
- package/src/runtime/base/default-edit-composer-runtime-core.ts +14 -2
- package/src/runtime/base/default-thread-composer-runtime-core.ts +11 -1
- package/src/runtime/utils/message-repository.ts +19 -13
- package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +4 -1
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +15 -0
- package/src/runtimes/internal.ts +3 -0
- package/src/runtimes/local/local-thread-runtime-core.test.ts +596 -0
- package/src/runtimes/local/local-thread-runtime-core.ts +85 -21
- package/src/runtimes/local/should-continue.test.ts +122 -0
- package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +9 -10
- package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +38 -32
- package/src/store/clients/model-context-client.test.ts +21 -1
- package/src/store/runtime-clients/thread-runtime-client.ts +2 -1
- package/src/store/scopes/thread.ts +1 -0
- package/src/subscribable/subscribable.ts +16 -8
- package/src/tests/MessageRepository.test.ts +12 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-position.test.ts +121 -0
- package/src/tests/auiV0Encode.test.ts +74 -0
- package/src/tests/base-composer-runtime-core.test.ts +422 -0
- package/src/tests/external-store-thread-list-runtime-core.test.ts +6 -6
- package/src/tests/external-store-thread-runtime-core-adapter.test.ts +575 -0
- package/src/tests/external-store-thread-runtime-core.test.ts +55 -1
- package/src/tests/OptimisticState-delete-crash.test.ts +0 -208
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscribable.js","names":["Unsubscribe","notifyEventListeners","SKIP_UPDATE","Symbol","Subscribable","subscribe","callback","SubscribableWithState","path","TPath","getState","TState","NestedSubscribable","EventSubscribable","event","TEvent","binding","unstable_on","payload","shallowEqual","objA","T","objB","undefined","keysA","Object","keys","length","key","valueA","valueB","is","BaseSubscribable","_subscribers","Set","add","delete","waitForUpdate","Promise","resolve","unsubscribe","_notifySubscribers","errors","error","push","console","AggregateError","BaseSubject","_subscriptions","_connection","isConnected","_connect","notifySubscribers","errorContext","_updateConnection","size","ShallowMemoizeSubject","constructor","state","Error","_previousState","_syncState","LazyMemoizeSubject","_previousStateDirty","newState","NestedSubscriptionSubject","outerSubscribe","lastState","innerUnsubscribe","onRuntimeUpdate","outerUnsubscribe","EventSubscriptionSubject","config"],"sources":["../../src/subscribable/subscribable.ts"],"sourcesContent":["import type { Unsubscribe } from \"../types/unsubscribe\";\nimport { notifyEventListeners } from \"../utils/notify-event-listeners\";\n\nexport const SKIP_UPDATE = Symbol(\"skip-update\");\nexport type SKIP_UPDATE = typeof SKIP_UPDATE;\n\nexport type Subscribable = {\n subscribe: (callback: () => void) => Unsubscribe;\n};\n\nexport type SubscribableWithState<TState, TPath> = Subscribable & {\n path: TPath;\n getState: () => TState;\n};\n\nexport type NestedSubscribable<\n TState extends Subscribable | undefined,\n TPath,\n> = SubscribableWithState<TState, TPath>;\n\nexport type EventSubscribable<TEvent extends string> = {\n event: TEvent;\n binding: SubscribableWithState<\n | {\n unstable_on: (\n event: TEvent,\n callback: (payload?: unknown) => void,\n ) => Unsubscribe;\n }\n | undefined,\n unknown\n >;\n};\n\nfunction shallowEqual<T extends object>(\n objA: T | undefined,\n objB: T | undefined,\n) {\n if (objA === undefined && objB === undefined) return true;\n if (objA === undefined) return false;\n if (objB === undefined) return false;\n\n const keysA = Object.keys(objA);\n if (keysA.length !== Object.keys(objB).length) return false;\n\n for (const key of keysA) {\n const valueA = objA[key as keyof T];\n const valueB = objB[key as keyof T];\n if (!Object.is(valueA, valueB)) return false;\n }\n\n return true;\n}\n\nexport class BaseSubscribable {\n private _subscribers = new Set<() => void>();\n\n public subscribe(callback: () => void): Unsubscribe {\n this._subscribers.add(callback);\n return () => this._subscribers.delete(callback);\n }\n\n public waitForUpdate() {\n return new Promise<void>((resolve) => {\n const unsubscribe = this.subscribe(() => {\n unsubscribe();\n resolve();\n });\n });\n }\n\n protected _notifySubscribers() {\n const errors = [];\n for (const callback of this._subscribers) {\n try {\n callback();\n } catch (error) {\n errors.push(error);\n }\n }\n\n if (errors.length > 0) {\n if (errors.length === 1) {\n throw errors[0];\n } else {\n for (const error of errors) {\n console.error(error);\n }\n throw new AggregateError(errors);\n }\n }\n }\n}\n\n// lazy connect/disconnect: only opens upstream subscription while it has subscribers\nexport abstract class BaseSubject {\n private _subscriptions = new Set<(payload?: unknown) => void>();\n private _connection: Unsubscribe | undefined;\n\n protected get isConnected() {\n return !!this._connection;\n }\n\n protected abstract _connect(): Unsubscribe;\n\n protected notifySubscribers(payload?: unknown, errorContext?: string) {\n if (errorContext) {\n notifyEventListeners(this._subscriptions, payload, errorContext);\n return;\n }\n\n for (const callback of this._subscriptions) callback(payload);\n }\n\n private _updateConnection() {\n if (this._subscriptions.size > 0) {\n if (this._connection) return;\n this._connection = this._connect();\n } else {\n this._connection?.();\n this._connection = undefined;\n }\n }\n\n public subscribe(callback: (payload?: unknown) => void) {\n this._subscriptions.add(callback);\n this._updateConnection();\n\n return () => {\n this._subscriptions.delete(callback);\n this._updateConnection();\n };\n }\n}\n\nexport class ShallowMemoizeSubject<TState extends object, TPath>\n extends BaseSubject\n implements SubscribableWithState<TState, TPath>\n{\n public get path() {\n return this.binding.path;\n }\n\n constructor(\n private binding: SubscribableWithState<TState | SKIP_UPDATE, TPath>,\n ) {\n super();\n const state = binding.getState();\n if (state === SKIP_UPDATE)\n throw new Error(\"Entry not available in the store\");\n this._previousState = state;\n }\n\n private _previousState: TState;\n public getState = () => {\n if (!this.isConnected) this._syncState();\n return this._previousState;\n };\n\n private _syncState() {\n const state = this.binding.getState();\n if (state === SKIP_UPDATE) return false;\n if (shallowEqual(state, this._previousState)) return false;\n this._previousState = state;\n return true;\n }\n\n protected _connect() {\n const callback = () => {\n if (this._syncState()) {\n this.notifySubscribers();\n }\n };\n\n return this.binding.subscribe(callback);\n }\n}\n\nexport class LazyMemoizeSubject<TState extends object, TPath>\n extends BaseSubject\n implements SubscribableWithState<TState, TPath>\n{\n public get path() {\n return this.binding.path;\n }\n\n constructor(\n private binding: SubscribableWithState<TState | SKIP_UPDATE, TPath>,\n ) {\n super();\n }\n\n private _previousStateDirty = true;\n private _previousState: TState | undefined;\n public getState = () => {\n if (!this.isConnected || this._previousStateDirty) {\n const newState = this.binding.getState();\n if (newState !== SKIP_UPDATE) {\n this._previousState = newState;\n }\n this._previousStateDirty = false;\n }\n if (this._previousState === undefined)\n throw new Error(\"Entry not available in the store\");\n return this._previousState;\n };\n\n protected _connect() {\n const callback = () => {\n this._previousStateDirty = true;\n this.notifySubscribers();\n };\n\n return this.binding.subscribe(callback);\n }\n}\n\nexport class NestedSubscriptionSubject<\n TState extends Subscribable | undefined,\n TPath,\n>\n extends BaseSubject\n implements\n SubscribableWithState<TState, TPath>,\n NestedSubscribable<TState, TPath>\n{\n public get path() {\n return this.binding.path;\n }\n\n constructor(private binding: NestedSubscribable<TState, TPath>) {\n super();\n }\n\n public getState() {\n return this.binding.getState();\n }\n\n public outerSubscribe(callback: () => void) {\n return this.binding.subscribe(callback);\n }\n\n protected _connect(): Unsubscribe {\n const callback = () => {\n this.notifySubscribers();\n };\n\n let lastState = this.binding.getState();\n let innerUnsubscribe = lastState?.subscribe(callback);\n const onRuntimeUpdate = () => {\n const newState = this.binding.getState();\n if (newState === lastState) return;\n lastState = newState;\n\n innerUnsubscribe?.();\n innerUnsubscribe = newState?.subscribe(callback);\n\n callback();\n };\n\n const outerUnsubscribe = this.outerSubscribe(onRuntimeUpdate);\n return () => {\n outerUnsubscribe?.();\n innerUnsubscribe?.();\n };\n }\n}\n\nexport class EventSubscriptionSubject<\n TEvent extends string,\n> extends BaseSubject {\n constructor(private config: EventSubscribable<TEvent>) {\n super();\n }\n\n public getState() {\n return this.config.binding.getState();\n }\n\n public outerSubscribe(callback: () => void) {\n return this.config.binding.subscribe(callback);\n }\n\n protected _connect(): Unsubscribe {\n const errorContext = `Runtime event \"${this.config.event}\"`;\n const callback = (payload?: unknown) => {\n this.notifySubscribers(payload, errorContext);\n };\n\n let lastState = this.config.binding.getState();\n let innerUnsubscribe = lastState?.unstable_on(this.config.event, callback);\n const onRuntimeUpdate = () => {\n const newState = this.config.binding.getState();\n if (newState === lastState) return;\n lastState = newState;\n\n innerUnsubscribe?.();\n innerUnsubscribe = newState?.unstable_on(this.config.event, callback);\n };\n\n const outerUnsubscribe = this.outerSubscribe(onRuntimeUpdate);\n return () => {\n outerUnsubscribe?.();\n innerUnsubscribe?.();\n };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"subscribable.js","names":["Unsubscribe","notifyEventListeners","SKIP_UPDATE","Symbol","Subscribable","subscribe","callback","SubscribableWithState","path","TPath","getState","TState","NestedSubscribable","EventSubscribable","event","TEvent","binding","unstable_on","payload","shallowEqual","objA","T","objB","undefined","keysA","Object","keys","length","key","valueA","valueB","is","BaseSubscribable","_subscribers","Set","add","delete","waitForUpdate","Promise","resolve","unsubscribe","_notifySubscribers","errors","error","push","console","AggregateError","BaseSubject","_subscriptions","_connection","isConnected","_connect","notifySubscribers","errorContext","_updateConnection","size","ShallowMemoizeSubject","constructor","state","Error","_previousState","_syncState","LazyMemoizeSubject","_previousStateDirty","newState","NestedSubscriptionSubject","outerSubscribe","lastState","innerUnsubscribe","onRuntimeUpdate","outerUnsubscribe","EventSubscriptionSubject","config"],"sources":["../../src/subscribable/subscribable.ts"],"sourcesContent":["import type { Unsubscribe } from \"../types/unsubscribe\";\nimport { notifyEventListeners } from \"../utils/notify-event-listeners\";\n\nexport const SKIP_UPDATE = Symbol(\"skip-update\");\nexport type SKIP_UPDATE = typeof SKIP_UPDATE;\n\nexport type Subscribable = {\n subscribe: (callback: () => void) => Unsubscribe;\n};\n\nexport type SubscribableWithState<TState, TPath> = Subscribable & {\n path: TPath;\n getState: () => TState;\n};\n\nexport type NestedSubscribable<\n TState extends Subscribable | undefined,\n TPath,\n> = SubscribableWithState<TState, TPath>;\n\nexport type EventSubscribable<TEvent extends string> = {\n event: TEvent;\n binding: SubscribableWithState<\n | {\n unstable_on: (\n event: TEvent,\n callback: (payload?: unknown) => void,\n ) => Unsubscribe;\n }\n | undefined,\n unknown\n >;\n};\n\nfunction shallowEqual<T extends object>(\n objA: T | undefined,\n objB: T | undefined,\n) {\n if (objA === undefined && objB === undefined) return true;\n if (objA === undefined) return false;\n if (objB === undefined) return false;\n\n const keysA = Object.keys(objA);\n if (keysA.length !== Object.keys(objB).length) return false;\n\n for (const key of keysA) {\n const valueA = objA[key as keyof T];\n const valueB = objB[key as keyof T];\n if (!Object.is(valueA, valueB)) return false;\n }\n\n return true;\n}\n\nexport class BaseSubscribable {\n private _subscribers = new Set<() => void>();\n\n public subscribe(callback: () => void): Unsubscribe {\n this._subscribers.add(callback);\n return () => this._subscribers.delete(callback);\n }\n\n public waitForUpdate() {\n return new Promise<void>((resolve) => {\n const unsubscribe = this.subscribe(() => {\n unsubscribe();\n resolve();\n });\n });\n }\n\n protected _notifySubscribers() {\n const errors = [];\n for (const callback of this._subscribers) {\n try {\n callback();\n } catch (error) {\n errors.push(error);\n }\n }\n\n if (errors.length > 0) {\n if (errors.length === 1) {\n throw errors[0];\n } else {\n for (const error of errors) {\n console.error(error);\n }\n throw new AggregateError(errors);\n }\n }\n }\n}\n\n// lazy connect/disconnect: only opens upstream subscription while it has subscribers\nexport abstract class BaseSubject {\n private _subscriptions = new Set<(payload?: unknown) => void>();\n private _connection: Unsubscribe | undefined;\n\n protected get isConnected() {\n return !!this._connection;\n }\n\n protected abstract _connect(): Unsubscribe;\n\n protected notifySubscribers(payload?: unknown, errorContext?: string) {\n if (errorContext) {\n notifyEventListeners(this._subscriptions, payload, errorContext);\n return;\n }\n\n for (const callback of this._subscriptions) callback(payload);\n }\n\n private _updateConnection() {\n if (this._subscriptions.size > 0) {\n if (this._connection) return;\n this._connection = this._connect();\n } else {\n this._connection?.();\n this._connection = undefined;\n }\n }\n\n public subscribe(callback: (payload?: unknown) => void) {\n this._subscriptions.add(callback);\n this._updateConnection();\n\n return () => {\n this._subscriptions.delete(callback);\n this._updateConnection();\n };\n }\n}\n\nexport class ShallowMemoizeSubject<TState extends object, TPath>\n extends BaseSubject\n implements SubscribableWithState<TState, TPath>\n{\n public get path() {\n return this.binding.path;\n }\n\n private binding: SubscribableWithState<TState | SKIP_UPDATE, TPath>;\n\n constructor(binding: SubscribableWithState<TState | SKIP_UPDATE, TPath>) {\n super();\n this.binding = binding;\n const state = binding.getState();\n if (state === SKIP_UPDATE)\n throw new Error(\"Entry not available in the store\");\n this._previousState = state;\n }\n\n private _previousState: TState;\n public getState = () => {\n if (!this.isConnected) this._syncState();\n return this._previousState;\n };\n\n private _syncState() {\n const state = this.binding.getState();\n if (state === SKIP_UPDATE) return false;\n if (shallowEqual(state, this._previousState)) return false;\n this._previousState = state;\n return true;\n }\n\n protected _connect() {\n const callback = () => {\n if (this._syncState()) {\n this.notifySubscribers();\n }\n };\n\n return this.binding.subscribe(callback);\n }\n}\n\nexport class LazyMemoizeSubject<TState extends object, TPath>\n extends BaseSubject\n implements SubscribableWithState<TState, TPath>\n{\n public get path() {\n return this.binding.path;\n }\n\n private binding: SubscribableWithState<TState | SKIP_UPDATE, TPath>;\n\n constructor(binding: SubscribableWithState<TState | SKIP_UPDATE, TPath>) {\n super();\n this.binding = binding;\n }\n\n private _previousStateDirty = true;\n private _previousState: TState | undefined;\n public getState = () => {\n if (!this.isConnected || this._previousStateDirty) {\n const newState = this.binding.getState();\n if (newState !== SKIP_UPDATE) {\n this._previousState = newState;\n }\n this._previousStateDirty = false;\n }\n if (this._previousState === undefined)\n throw new Error(\"Entry not available in the store\");\n return this._previousState;\n };\n\n protected _connect() {\n const callback = () => {\n this._previousStateDirty = true;\n this.notifySubscribers();\n };\n\n return this.binding.subscribe(callback);\n }\n}\n\nexport class NestedSubscriptionSubject<\n TState extends Subscribable | undefined,\n TPath,\n>\n extends BaseSubject\n implements\n SubscribableWithState<TState, TPath>,\n NestedSubscribable<TState, TPath>\n{\n public get path() {\n return this.binding.path;\n }\n\n private binding: NestedSubscribable<TState, TPath>;\n\n constructor(binding: NestedSubscribable<TState, TPath>) {\n super();\n this.binding = binding;\n }\n\n public getState() {\n return this.binding.getState();\n }\n\n public outerSubscribe(callback: () => void) {\n return this.binding.subscribe(callback);\n }\n\n protected _connect(): Unsubscribe {\n const callback = () => {\n this.notifySubscribers();\n };\n\n let lastState = this.binding.getState();\n let innerUnsubscribe = lastState?.subscribe(callback);\n const onRuntimeUpdate = () => {\n const newState = this.binding.getState();\n if (newState === lastState) return;\n lastState = newState;\n\n innerUnsubscribe?.();\n innerUnsubscribe = newState?.subscribe(callback);\n\n callback();\n };\n\n const outerUnsubscribe = this.outerSubscribe(onRuntimeUpdate);\n return () => {\n outerUnsubscribe?.();\n innerUnsubscribe?.();\n };\n }\n}\n\nexport class EventSubscriptionSubject<\n TEvent extends string,\n> extends BaseSubject {\n private config: EventSubscribable<TEvent>;\n\n constructor(config: EventSubscribable<TEvent>) {\n super();\n this.config = config;\n }\n\n public getState() {\n return this.config.binding.getState();\n }\n\n public outerSubscribe(callback: () => void) {\n return this.config.binding.subscribe(callback);\n }\n\n protected _connect(): Unsubscribe {\n const errorContext = `Runtime event \"${this.config.event}\"`;\n const callback = (payload?: unknown) => {\n this.notifySubscribers(payload, errorContext);\n };\n\n let lastState = this.config.binding.getState();\n let innerUnsubscribe = lastState?.unstable_on(this.config.event, callback);\n const onRuntimeUpdate = () => {\n const newState = this.config.binding.getState();\n if (newState === lastState) return;\n lastState = newState;\n\n innerUnsubscribe?.();\n innerUnsubscribe = newState?.unstable_on(this.config.event, callback);\n };\n\n const outerUnsubscribe = this.outerSubscribe(onRuntimeUpdate);\n return () => {\n outerUnsubscribe?.();\n innerUnsubscribe?.();\n };\n }\n}\n"],"mappings":";;AAGA,MAAaE,cAAcC,OAAO,aAAa;AA+B/C,SAASgB,aACPC,MACAE,MACA;CACA,IAAIF,SAASG,KAAAA,KAAaD,SAASC,KAAAA,GAAW,OAAO;CACrD,IAAIH,SAASG,KAAAA,GAAW,OAAO;CAC/B,IAAID,SAASC,KAAAA,GAAW,OAAO;CAE/B,MAAMC,QAAQC,OAAOC,KAAKN,IAAI;CAC9B,IAAII,MAAMG,WAAWF,OAAOC,KAAKJ,IAAI,CAAC,CAACK,QAAQ,OAAO;CAEtD,KAAK,MAAMC,OAAOJ,OAAO;EACvB,MAAMK,SAAST,KAAKQ;EACpB,MAAME,SAASR,KAAKM;EACpB,IAAI,CAACH,OAAOM,GAAGF,QAAQC,MAAM,GAAG,OAAO;CACzC;CAEA,OAAO;AACT;AAEA,IAAaE,mBAAb,MAA8B;CAC5B,+BAAuB,IAAIE,IAAgB;CAE3C,UAAiB5B,UAAmC;EAClD,KAAK2B,aAAaE,IAAI7B,QAAQ;EAC9B,aAAa,KAAK2B,aAAaG,OAAO9B,QAAQ;CAChD;CAEA,gBAAuB;EACrB,OAAO,IAAIgC,SAAeC,YAAY;GACpC,MAAMC,cAAc,KAAKnC,gBAAgB;IACvCmC,YAAY;IACZD,QAAQ;GACV,CAAC;EACH,CAAC;CACH;CAEA,qBAA+B;EAC7B,MAAMG,SAAS,CAAA;EACf,KAAK,MAAMpC,YAAY,KAAK2B,cAC1B,IAAI;GACF3B,SAAS;EACX,SAASqC,OAAO;GACdD,OAAOE,KAAKD,KAAK;EACnB;EAGF,IAAID,OAAOf,SAAS,GAClB,IAAIe,OAAOf,WAAW,GACpB,MAAMe,OAAO;OACR;GACL,KAAK,MAAMC,SAASD,QAClBG,QAAQF,MAAMA,KAAK;GAErB,MAAM,IAAIG,eAAeJ,MAAM;EACjC;CAEJ;AACF;AAGA,IAAsBK,cAAtB,MAAkC;CAChC,iCAAyB,IAAIb,IAAiC;CAC9D;CAEA,IAAcgB,cAAc;EAC1B,OAAO,CAAC,CAAC,KAAKD;CAChB;CAIA,kBAA4B/B,SAAmBmC,cAAuB;EACpE,IAAIA,cAAc;GAChBpD,qBAAqB,KAAK+C,gBAAgB9B,SAASmC,YAAY;GAC/D;EACF;EAEA,KAAK,MAAM/C,YAAY,KAAK0C,gBAAgB1C,SAASY,OAAO;CAC9D;CAEA,oBAA4B;EAC1B,IAAI,KAAK8B,eAAeO,OAAO,GAAG;GAChC,IAAI,KAAKN,aAAa;GACtB,KAAKA,cAAc,KAAKE,SAAS;EACnC,OAAO;GACL,KAAKF,cAAc;GACnB,KAAKA,cAAc1B,KAAAA;EACrB;CACF;CAEA,UAAiBjB,UAAuC;EACtD,KAAK0C,eAAeb,IAAI7B,QAAQ;EAChC,KAAKgD,kBAAkB;EAEvB,aAAa;GACX,KAAKN,eAAeZ,OAAO9B,QAAQ;GACnC,KAAKgD,kBAAkB;EACzB;CACF;AACF;AAEA,IAAaE,wBAAb,cACUT,YAEV;CACE,IAAWvC,OAAO;EAChB,OAAO,KAAKQ,QAAQR;CACtB;CAEA;CAEAiD,YAAYzC,SAA6D;EACvE,MAAM;EACN,KAAKA,UAAUA;EACf,MAAM0C,QAAQ1C,QAAQN,SAAS;EAC/B,IAAIgD,UAAUxD,aACZ,MAAM,IAAIyD,MAAM,kCAAkC;EACpD,KAAKC,iBAAiBF;CACxB;CAEA;CACA,iBAAwB;EACtB,IAAI,CAAC,KAAKR,aAAa,KAAKW,WAAW;EACvC,OAAO,KAAKD;CACd;CAEA,aAAqB;EACnB,MAAMF,QAAQ,KAAK1C,QAAQN,SAAS;EACpC,IAAIgD,UAAUxD,aAAa,OAAO;EAClC,IAAIiB,aAAauC,OAAO,KAAKE,cAAc,GAAG,OAAO;EACrD,KAAKA,iBAAiBF;EACtB,OAAO;CACT;CAEA,WAAqB;EACnB,MAAMpD,iBAAiB;GACrB,IAAI,KAAKuD,WAAW,GAClB,KAAKT,kBAAkB;EAE3B;EAEA,OAAO,KAAKpC,QAAQX,UAAUC,QAAQ;CACxC;AACF;AAEA,IAAawD,qBAAb,cACUf,YAEV;CACE,IAAWvC,OAAO;EAChB,OAAO,KAAKQ,QAAQR;CACtB;CAEA;CAEAiD,YAAYzC,SAA6D;EACvE,MAAM;EACN,KAAKA,UAAUA;CACjB;CAEA,sBAA8B;CAC9B;CACA,iBAAwB;EACtB,IAAI,CAAC,KAAKkC,eAAe,KAAKa,qBAAqB;GACjD,MAAMC,WAAW,KAAKhD,QAAQN,SAAS;GACvC,IAAIsD,aAAa9D,aACf,KAAK0D,iBAAiBI;GAExB,KAAKD,sBAAsB;EAC7B;EACA,IAAI,KAAKH,mBAAmBrC,KAAAA,GAC1B,MAAM,IAAIoC,MAAM,kCAAkC;EACpD,OAAO,KAAKC;CACd;CAEA,WAAqB;EACnB,MAAMtD,iBAAiB;GACrB,KAAKyD,sBAAsB;GAC3B,KAAKX,kBAAkB;EACzB;EAEA,OAAO,KAAKpC,QAAQX,UAAUC,QAAQ;CACxC;AACF;AAEA,IAAa2D,4BAAb,cAIUlB,YAIV;CACE,IAAWvC,OAAO;EAChB,OAAO,KAAKQ,QAAQR;CACtB;CAEA;CAEAiD,YAAYzC,SAA4C;EACtD,MAAM;EACN,KAAKA,UAAUA;CACjB;CAEA,WAAkB;EAChB,OAAO,KAAKA,QAAQN,SAAS;CAC/B;CAEA,eAAsBJ,UAAsB;EAC1C,OAAO,KAAKU,QAAQX,UAAUC,QAAQ;CACxC;CAEA,WAAkC;EAChC,MAAMA,iBAAiB;GACrB,KAAK8C,kBAAkB;EACzB;EAEA,IAAIe,YAAY,KAAKnD,QAAQN,SAAS;EACtC,IAAI0D,mBAAmBD,WAAW9D,UAAUC,QAAQ;EACpD,MAAM+D,wBAAwB;GAC5B,MAAML,WAAW,KAAKhD,QAAQN,SAAS;GACvC,IAAIsD,aAAaG,WAAW;GAC5BA,YAAYH;GAEZI,mBAAmB;GACnBA,mBAAmBJ,UAAU3D,UAAUC,QAAQ;GAE/CA,SAAS;EACX;EAEA,MAAMgE,mBAAmB,KAAKJ,eAAeG,eAAe;EAC5D,aAAa;GACXC,mBAAmB;GACnBF,mBAAmB;EACrB;CACF;AACF;AAEA,IAAaG,2BAAb,cAEUxB,YAAY;CACpB;CAEAU,YAAYe,QAAmC;EAC7C,MAAM;EACN,KAAKA,SAASA;CAChB;CAEA,WAAkB;EAChB,OAAO,KAAKA,OAAOxD,QAAQN,SAAS;CACtC;CAEA,eAAsBJ,UAAsB;EAC1C,OAAO,KAAKkE,OAAOxD,QAAQX,UAAUC,QAAQ;CAC/C;CAEA,WAAkC;EAChC,MAAM+C,eAAe,kBAAkB,KAAKmB,OAAO1D,MAAK;EACxD,MAAMR,YAAYY,YAAsB;GACtC,KAAKkC,kBAAkBlC,SAASmC,YAAY;EAC9C;EAEA,IAAIc,YAAY,KAAKK,OAAOxD,QAAQN,SAAS;EAC7C,IAAI0D,mBAAmBD,WAAWlD,YAAY,KAAKuD,OAAO1D,OAAOR,QAAQ;EACzE,MAAM+D,wBAAwB;GAC5B,MAAML,WAAW,KAAKQ,OAAOxD,QAAQN,SAAS;GAC9C,IAAIsD,aAAaG,WAAW;GAC5BA,YAAYH;GAEZI,mBAAmB;GACnBA,mBAAmBJ,UAAU/C,YAAY,KAAKuD,OAAO1D,OAAOR,QAAQ;EACtE;EAEA,MAAMgE,mBAAmB,KAAKJ,eAAeG,eAAe;EAC5D,aAAa;GACXC,mBAAmB;GACnBF,mBAAmB;EACrB;CACF;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.23",
|
|
4
4
|
"description": "Framework-agnostic core runtime for assistant-ui",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"assistant",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
],
|
|
60
60
|
"sideEffects": false,
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"assistant-stream": "^0.3.
|
|
62
|
+
"assistant-stream": "^0.3.28",
|
|
63
63
|
"nanoid": "^6.0.0"
|
|
64
64
|
},
|
|
65
65
|
"optionalDevDependencies": {
|
|
@@ -95,11 +95,11 @@
|
|
|
95
95
|
"react-dom": "^19.2.8",
|
|
96
96
|
"vitest": "^4.1.10",
|
|
97
97
|
"zustand": "^5.0.14",
|
|
98
|
-
"@assistant-ui/store": "0.2.
|
|
99
|
-
"@assistant-ui/tap": "0.9.
|
|
100
|
-
"@assistant-ui/vite": "0.0.
|
|
101
|
-
"@assistant-ui/x-buildutils": "0.0.
|
|
102
|
-
"assistant-cloud": "0.1.
|
|
98
|
+
"@assistant-ui/store": "0.2.22",
|
|
99
|
+
"@assistant-ui/tap": "0.9.6",
|
|
100
|
+
"@assistant-ui/vite": "0.0.11",
|
|
101
|
+
"@assistant-ui/x-buildutils": "0.0.20",
|
|
102
|
+
"assistant-cloud": "0.1.37"
|
|
103
103
|
},
|
|
104
104
|
"publishConfig": {
|
|
105
105
|
"access": "public",
|
|
@@ -65,6 +65,14 @@ export type ThreadHistoryAdapter = {
|
|
|
65
65
|
options: ChatModelRunOptions,
|
|
66
66
|
): AsyncGenerator<ChatModelRunResult, void, unknown>;
|
|
67
67
|
append(item: ExportedMessageRepositoryItem): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Rewrites a previously appended message in place, keyed by its message id.
|
|
70
|
+
* Adapters that implement this let a runtime persist a run paused for tool
|
|
71
|
+
* approval and finalize the same message once the run resumes. An update may
|
|
72
|
+
* arrive for an id whose earlier write failed; treat it as an upsert keyed
|
|
73
|
+
* on the message id rather than assuming the entry exists.
|
|
74
|
+
*/
|
|
75
|
+
update?(item: ExportedMessageRepositoryItem): Promise<void>;
|
|
68
76
|
delete?(items: ExportedMessageRepositoryItem[]): Promise<void>;
|
|
69
77
|
/** Required when used with `useAISDKRuntime` / `useChatRuntime`. */
|
|
70
78
|
withFormat?<TMessage, TStorageFormat extends Record<string, unknown>>(
|
package/src/internal.ts
CHANGED
|
@@ -40,7 +40,7 @@ export { CompositeContextProvider } from "./utils/composite-context-provider";
|
|
|
40
40
|
|
|
41
41
|
// Shared attachment data-URL encoder, reused by framework adapters so the
|
|
42
42
|
// FileReader fallback lives in one place.
|
|
43
|
-
export { getFileDataURL } from "./adapters/attachment";
|
|
43
|
+
export { getFileDataURL, fileMatchesAccept } from "./adapters/attachment";
|
|
44
44
|
export { isCreateAttachment } from "./types/attachment";
|
|
45
45
|
|
|
46
46
|
// Streaming-stable tool-args stringifier, reused by framework adapters so the
|
|
@@ -88,6 +88,53 @@ describe("AssistantFrameHost", () => {
|
|
|
88
88
|
expect(vi.getTimerCount()).toBe(0);
|
|
89
89
|
});
|
|
90
90
|
|
|
91
|
+
it("rejects pending tool calls when execution is aborted", async () => {
|
|
92
|
+
const { execute, host } = createHost();
|
|
93
|
+
const abortController = new AbortController();
|
|
94
|
+
const abortError = new Error("Run cancelled");
|
|
95
|
+
abortError.name = "AbortError";
|
|
96
|
+
const result = Promise.resolve(
|
|
97
|
+
execute(
|
|
98
|
+
{},
|
|
99
|
+
{
|
|
100
|
+
...executionContext,
|
|
101
|
+
abortSignal: abortController.signal,
|
|
102
|
+
},
|
|
103
|
+
),
|
|
104
|
+
);
|
|
105
|
+
const onRejected = vi.fn();
|
|
106
|
+
void result.catch(onRejected);
|
|
107
|
+
|
|
108
|
+
abortController.abort(abortError);
|
|
109
|
+
await Promise.resolve();
|
|
110
|
+
|
|
111
|
+
expect(onRejected).toHaveBeenCalledWith(abortError);
|
|
112
|
+
expect(vi.getTimerCount()).toBe(0);
|
|
113
|
+
host.dispose();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("does not post tool calls when execution is already aborted", async () => {
|
|
117
|
+
const { execute, host, postMessage } = createHost();
|
|
118
|
+
const abortController = new AbortController();
|
|
119
|
+
const abortError = new Error("Run cancelled");
|
|
120
|
+
abortError.name = "AbortError";
|
|
121
|
+
abortController.abort(abortError);
|
|
122
|
+
|
|
123
|
+
await expect(
|
|
124
|
+
execute(
|
|
125
|
+
{},
|
|
126
|
+
{
|
|
127
|
+
...executionContext,
|
|
128
|
+
abortSignal: abortController.signal,
|
|
129
|
+
},
|
|
130
|
+
),
|
|
131
|
+
).rejects.toBe(abortError);
|
|
132
|
+
|
|
133
|
+
expect(postMessage).toHaveBeenCalledOnce();
|
|
134
|
+
expect(vi.getTimerCount()).toBe(0);
|
|
135
|
+
host.dispose();
|
|
136
|
+
});
|
|
137
|
+
|
|
91
138
|
it("rejects tool calls made after disposal without posting a request", async () => {
|
|
92
139
|
const { execute, host, postMessage } = createHost();
|
|
93
140
|
host.dispose();
|
|
@@ -40,6 +40,13 @@ const deserializeModelContext = (
|
|
|
40
40
|
}),
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
+
const getAbortReason = (signal: AbortSignal): unknown => {
|
|
44
|
+
if (signal.reason !== undefined) return signal.reason;
|
|
45
|
+
const error = new Error("Tool call was aborted");
|
|
46
|
+
error.name = "AbortError";
|
|
47
|
+
return error;
|
|
48
|
+
};
|
|
49
|
+
|
|
43
50
|
export class AssistantFrameHost implements ModelContextProvider {
|
|
44
51
|
private _context: ModelContext = {};
|
|
45
52
|
private _subscribers = new Set<() => void>();
|
|
@@ -105,7 +112,8 @@ export class AssistantFrameHost implements ModelContextProvider {
|
|
|
105
112
|
name,
|
|
106
113
|
{
|
|
107
114
|
...tool,
|
|
108
|
-
execute: (args: any
|
|
115
|
+
execute: (args: any, context: { abortSignal: AbortSignal }) =>
|
|
116
|
+
this.callTool(name, args, context.abortSignal),
|
|
109
117
|
} as Tool<any, any>,
|
|
110
118
|
]),
|
|
111
119
|
),
|
|
@@ -113,7 +121,11 @@ export class AssistantFrameHost implements ModelContextProvider {
|
|
|
113
121
|
this.notifySubscribers();
|
|
114
122
|
}
|
|
115
123
|
|
|
116
|
-
private callTool(
|
|
124
|
+
private callTool(
|
|
125
|
+
toolName: string,
|
|
126
|
+
args: any,
|
|
127
|
+
abortSignal: AbortSignal,
|
|
128
|
+
): Promise<any> {
|
|
117
129
|
return this.sendRequest(
|
|
118
130
|
{
|
|
119
131
|
type: "tool-call",
|
|
@@ -123,6 +135,7 @@ export class AssistantFrameHost implements ModelContextProvider {
|
|
|
123
135
|
},
|
|
124
136
|
30000,
|
|
125
137
|
`Tool call "${toolName}" timed out`,
|
|
138
|
+
abortSignal,
|
|
126
139
|
);
|
|
127
140
|
}
|
|
128
141
|
|
|
@@ -130,40 +143,54 @@ export class AssistantFrameHost implements ModelContextProvider {
|
|
|
130
143
|
message: T,
|
|
131
144
|
timeout = 30000,
|
|
132
145
|
timeoutMessage = "Request timed out",
|
|
146
|
+
abortSignal?: AbortSignal,
|
|
133
147
|
): Promise<any> {
|
|
134
148
|
if (this._disposed) {
|
|
135
149
|
return Promise.reject(new Error("AssistantFrameHost has been disposed"));
|
|
136
150
|
}
|
|
151
|
+
if (abortSignal?.aborted) {
|
|
152
|
+
return Promise.reject(getAbortReason(abortSignal));
|
|
153
|
+
}
|
|
137
154
|
|
|
138
155
|
return new Promise((resolve, reject) => {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
{ channel: FRAME_MESSAGE_CHANNEL, message },
|
|
143
|
-
this._targetOrigin,
|
|
144
|
-
);
|
|
145
|
-
|
|
146
|
-
const timeoutId = setTimeout(() => {
|
|
156
|
+
let timeoutId: ReturnType<typeof setTimeout> | undefined;
|
|
157
|
+
const onAbort = () => {
|
|
158
|
+
if (!abortSignal) return;
|
|
147
159
|
const pending = this._pendingRequests.get(message.id);
|
|
148
160
|
if (pending) {
|
|
149
|
-
pending.reject(
|
|
161
|
+
pending.reject(getAbortReason(abortSignal));
|
|
150
162
|
this._pendingRequests.delete(message.id);
|
|
151
163
|
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
164
|
+
};
|
|
165
|
+
const cleanup = () => {
|
|
166
|
+
if (timeoutId !== undefined) clearTimeout(timeoutId);
|
|
167
|
+
abortSignal?.removeEventListener("abort", onAbort);
|
|
168
|
+
};
|
|
156
169
|
|
|
157
170
|
this._pendingRequests.set(message.id, {
|
|
158
171
|
resolve: (value: any) => {
|
|
159
|
-
|
|
160
|
-
|
|
172
|
+
cleanup();
|
|
173
|
+
resolve(value);
|
|
161
174
|
},
|
|
162
175
|
reject: (error: any) => {
|
|
163
|
-
|
|
164
|
-
|
|
176
|
+
cleanup();
|
|
177
|
+
reject(error);
|
|
165
178
|
},
|
|
166
179
|
});
|
|
180
|
+
|
|
181
|
+
timeoutId = setTimeout(() => {
|
|
182
|
+
const pending = this._pendingRequests.get(message.id);
|
|
183
|
+
if (pending) {
|
|
184
|
+
pending.reject(new Error(timeoutMessage));
|
|
185
|
+
this._pendingRequests.delete(message.id);
|
|
186
|
+
}
|
|
187
|
+
}, timeout);
|
|
188
|
+
abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
189
|
+
|
|
190
|
+
this._iframeWindow.postMessage(
|
|
191
|
+
{ channel: FRAME_MESSAGE_CHANNEL, message },
|
|
192
|
+
this._targetOrigin,
|
|
193
|
+
);
|
|
167
194
|
});
|
|
168
195
|
}
|
|
169
196
|
|
|
@@ -55,6 +55,12 @@ export type AssistantContextConfig = {
|
|
|
55
55
|
disabled?: boolean | undefined;
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
+
const stripOverwrite = (tool: Tool<any, any>): Tool<any, any> => {
|
|
59
|
+
if (!tool.overwrite) return tool;
|
|
60
|
+
const { overwrite: _, ...rest } = tool;
|
|
61
|
+
return rest as Tool<any, any>;
|
|
62
|
+
};
|
|
63
|
+
|
|
58
64
|
export const mergeModelContexts = (
|
|
59
65
|
configSet: Set<ModelContextProvider>,
|
|
60
66
|
): ModelContext => {
|
|
@@ -79,25 +85,29 @@ export const mergeModelContexts = (
|
|
|
79
85
|
if (existing && existing !== tool) {
|
|
80
86
|
const existingPriority = toolPriorities[name]!;
|
|
81
87
|
if (existingPriority === priority) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
88
|
+
if (!tool.overwrite) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
`You tried to define a tool with the name ${name}, but it already exists.`,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
acc.tools![name] = stripOverwrite(tool);
|
|
94
|
+
continue;
|
|
85
95
|
}
|
|
86
96
|
|
|
87
97
|
const higherPriorityTool =
|
|
88
98
|
existingPriority > priority ? existing : tool;
|
|
89
99
|
const lowerPriorityTool =
|
|
90
100
|
existingPriority > priority ? tool : existing;
|
|
91
|
-
acc.tools![name] = {
|
|
101
|
+
acc.tools![name] = stripOverwrite({
|
|
92
102
|
...lowerPriorityTool,
|
|
93
103
|
...higherPriorityTool,
|
|
94
|
-
} as Tool<any, any
|
|
104
|
+
} as Tool<any, any>);
|
|
95
105
|
toolPriorities[name] = Math.max(existingPriority, priority);
|
|
96
106
|
continue;
|
|
97
107
|
}
|
|
98
108
|
|
|
99
109
|
if (!acc.tools) acc.tools = {};
|
|
100
|
-
acc.tools[name] = tool;
|
|
110
|
+
acc.tools[name] = stripOverwrite(tool);
|
|
101
111
|
toolPriorities[name] ??= priority;
|
|
102
112
|
}
|
|
103
113
|
}
|
|
@@ -275,12 +275,22 @@ export const parseStoredMessageRepository = (
|
|
|
275
275
|
};
|
|
276
276
|
|
|
277
277
|
class AsyncStorageHistoryAdapter implements ThreadHistoryAdapter {
|
|
278
|
+
private storage: AsyncStorageLike;
|
|
279
|
+
private aui: ReturnType<typeof useAui>;
|
|
280
|
+
private prefix: string;
|
|
281
|
+
private mutationQueue: KeyedMutationQueue;
|
|
282
|
+
|
|
278
283
|
constructor(
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
) {
|
|
284
|
+
storage: AsyncStorageLike,
|
|
285
|
+
aui: ReturnType<typeof useAui>,
|
|
286
|
+
prefix: string,
|
|
287
|
+
mutationQueue: KeyedMutationQueue,
|
|
288
|
+
) {
|
|
289
|
+
this.storage = storage;
|
|
290
|
+
this.aui = aui;
|
|
291
|
+
this.prefix = prefix;
|
|
292
|
+
this.mutationQueue = mutationQueue;
|
|
293
|
+
}
|
|
284
294
|
|
|
285
295
|
private _messagesKey(remoteId: string) {
|
|
286
296
|
return `${this.prefix}messages:${remoteId}`;
|
|
@@ -356,22 +356,36 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
|
356
356
|
[remoteMetadata.remoteId]: mappingId,
|
|
357
357
|
};
|
|
358
358
|
|
|
359
|
-
//
|
|
360
|
-
//
|
|
359
|
+
// A concurrent `list()` may already have placed this thread; keep that
|
|
360
|
+
// position and only merge metadata. A genuinely absent thread stays
|
|
361
|
+
// appended: it may live on an unloaded page, and a prepend would pin it
|
|
362
|
+
// above newer threads permanently since `classifyThreads` skips ids it
|
|
363
|
+
// has already seen. Filtering both arrays first still prevents
|
|
364
|
+
// duplication or a wrong-status entry from `list()`.
|
|
365
|
+
const remoteId = remoteMetadata.remoteId;
|
|
366
|
+
const wasInTarget =
|
|
367
|
+
remoteMetadata.status === "regular"
|
|
368
|
+
? state.threadIds.includes(remoteId)
|
|
369
|
+
: state.archivedThreadIds.includes(remoteId);
|
|
370
|
+
|
|
361
371
|
const threadIdsWithoutRemote = state.threadIds.filter(
|
|
362
|
-
(id) => id !==
|
|
372
|
+
(id) => id !== remoteId,
|
|
363
373
|
);
|
|
364
374
|
const archivedThreadIdsWithoutRemote = state.archivedThreadIds.filter(
|
|
365
|
-
(id) => id !==
|
|
375
|
+
(id) => id !== remoteId,
|
|
366
376
|
);
|
|
367
377
|
|
|
368
378
|
const newThreadIds =
|
|
369
379
|
remoteMetadata.status === "regular"
|
|
370
|
-
?
|
|
380
|
+
? wasInTarget
|
|
381
|
+
? state.threadIds
|
|
382
|
+
: [...threadIdsWithoutRemote, remoteId]
|
|
371
383
|
: threadIdsWithoutRemote;
|
|
372
384
|
const newArchivedThreadIds =
|
|
373
385
|
remoteMetadata.status === "archived"
|
|
374
|
-
?
|
|
386
|
+
? wasInTarget
|
|
387
|
+
? state.archivedThreadIds
|
|
388
|
+
: [...archivedThreadIdsWithoutRemote, remoteId]
|
|
375
389
|
: archivedThreadIdsWithoutRemote;
|
|
376
390
|
|
|
377
391
|
this._state.update({
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { extractAuiV0 } from "./AssistantCloudThreadHistoryAdapter";
|
|
3
|
+
|
|
4
|
+
const auiV0Message = (status: { type: string; reason?: string }) => ({
|
|
5
|
+
role: "assistant",
|
|
6
|
+
status,
|
|
7
|
+
content: [
|
|
8
|
+
{
|
|
9
|
+
type: "tool-call",
|
|
10
|
+
toolCallId: "call-1",
|
|
11
|
+
toolName: "send_email",
|
|
12
|
+
args: {},
|
|
13
|
+
argsText: "{}",
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
metadata: { steps: [{ usage: { inputTokens: 1, outputTokens: 2 } }] },
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe("extractAuiV0", () => {
|
|
20
|
+
it("returns null for a requires-action message so paused writes never report", () => {
|
|
21
|
+
expect(
|
|
22
|
+
extractAuiV0(
|
|
23
|
+
auiV0Message({ type: "requires-action", reason: "tool-calls" }),
|
|
24
|
+
),
|
|
25
|
+
).toBeNull();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("reports a terminal message once with its usage", () => {
|
|
29
|
+
const result = extractAuiV0(auiV0Message({ type: "complete" }));
|
|
30
|
+
expect(result?.status).toBe("completed");
|
|
31
|
+
expect(result?.inputTokens).toBe(1);
|
|
32
|
+
expect(result?.outputTokens).toBe(2);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -22,10 +22,13 @@ const globalPersistence = new WeakMap<
|
|
|
22
22
|
>();
|
|
23
23
|
|
|
24
24
|
class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
) {
|
|
25
|
+
private cloudRef: RefObject<AssistantCloud>;
|
|
26
|
+
private aui: AssistantClient;
|
|
27
|
+
|
|
28
|
+
constructor(cloudRef: RefObject<AssistantCloud>, aui: AssistantClient) {
|
|
29
|
+
this.cloudRef = cloudRef;
|
|
30
|
+
this.aui = aui;
|
|
31
|
+
}
|
|
29
32
|
|
|
30
33
|
private get _persistence(): CloudMessagePersistence {
|
|
31
34
|
const key = this.aui.threadListItem();
|
|
@@ -102,6 +105,21 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
|
|
|
102
105
|
}
|
|
103
106
|
}
|
|
104
107
|
|
|
108
|
+
async update(item: ExportedMessageRepositoryItem) {
|
|
109
|
+
if (!this._persistence.isPersisted(item.message.id)) {
|
|
110
|
+
return this.append(item);
|
|
111
|
+
}
|
|
112
|
+
const { message } = item;
|
|
113
|
+
const remoteId = this.aui.threadListItem().getState().remoteId;
|
|
114
|
+
if (!remoteId) return;
|
|
115
|
+
const encoded = auiV0Encode(message);
|
|
116
|
+
await this._persistence.update(remoteId, message.id, "aui/v0", encoded);
|
|
117
|
+
|
|
118
|
+
if (this.cloudRef.current.telemetry.enabled) {
|
|
119
|
+
this._maybeReportRun(remoteId, "aui/v0", encoded);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
105
123
|
async delete() {
|
|
106
124
|
throw new Error(
|
|
107
125
|
"Assistant Cloud does not support deleting thread messages yet.",
|
|
@@ -341,7 +359,7 @@ const AUI_STATUS_MAP: Record<string, TelemetryData["status"]> = {
|
|
|
341
359
|
incomplete: "incomplete",
|
|
342
360
|
};
|
|
343
361
|
|
|
344
|
-
function extractAuiV0<T>(content: T): TelemetryData | null {
|
|
362
|
+
export function extractAuiV0<T>(content: T): TelemetryData | null {
|
|
345
363
|
const msg = content as {
|
|
346
364
|
role?: string;
|
|
347
365
|
status?: { type: string };
|
|
@@ -369,6 +387,9 @@ function extractAuiV0<T>(content: T): TelemetryData | null {
|
|
|
369
387
|
};
|
|
370
388
|
|
|
371
389
|
if (msg.role !== "assistant") return null;
|
|
390
|
+
// A paused (requires-action) write is not a finished run; reporting it would
|
|
391
|
+
// mislabel it "completed" and double-count steps once the terminal write reports.
|
|
392
|
+
if (msg.status?.type === "requires-action") return null;
|
|
372
393
|
|
|
373
394
|
const toolCalls = msg.content
|
|
374
395
|
?.filter((p) => p.type === "tool-call" && p.toolName && p.toolCallId)
|
|
@@ -19,7 +19,11 @@ const guessAttachmentType = (
|
|
|
19
19
|
export class CloudFileAttachmentAdapter implements AttachmentAdapter {
|
|
20
20
|
public accept = "*";
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
private cloud: AssistantCloud;
|
|
23
|
+
|
|
24
|
+
constructor(cloud: AssistantCloud) {
|
|
25
|
+
this.cloud = cloud;
|
|
26
|
+
}
|
|
23
27
|
|
|
24
28
|
private uploadedUrls = new Map<string, string>();
|
|
25
29
|
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
SourceProviderMetadata,
|
|
7
7
|
ThreadMessage,
|
|
8
8
|
TextMessagePart,
|
|
9
|
+
ToolApprovalOption,
|
|
9
10
|
Unstable_AudioMessagePart,
|
|
10
11
|
} from "../../../types/message";
|
|
11
12
|
import type { CompleteAttachment } from "../../../types/attachment";
|
|
@@ -18,6 +19,16 @@ import type {
|
|
|
18
19
|
} from "assistant-stream/utils";
|
|
19
20
|
import type { ExportedMessageRepositoryItem } from "../../../runtime/utils/message-repository";
|
|
20
21
|
|
|
22
|
+
type AuiV0ToolApproval = {
|
|
23
|
+
readonly id: string;
|
|
24
|
+
readonly approved?: boolean;
|
|
25
|
+
readonly reason?: string;
|
|
26
|
+
readonly isAutomatic?: boolean;
|
|
27
|
+
readonly options?: readonly ToolApprovalOption[];
|
|
28
|
+
readonly optionId?: string;
|
|
29
|
+
readonly resolution?: "cancelled" | "expired";
|
|
30
|
+
};
|
|
31
|
+
|
|
21
32
|
type AuiV0MessagePart =
|
|
22
33
|
| {
|
|
23
34
|
readonly type: "text";
|
|
@@ -51,6 +62,7 @@ type AuiV0MessagePart =
|
|
|
51
62
|
readonly args: ReadonlyJSONObject;
|
|
52
63
|
readonly result?: ReadonlyJSONValue;
|
|
53
64
|
readonly isError?: true;
|
|
65
|
+
readonly approval?: AuiV0ToolApproval;
|
|
54
66
|
}
|
|
55
67
|
| {
|
|
56
68
|
readonly type: "tool-call";
|
|
@@ -59,6 +71,7 @@ type AuiV0MessagePart =
|
|
|
59
71
|
readonly argsText: string;
|
|
60
72
|
readonly result?: ReadonlyJSONValue;
|
|
61
73
|
readonly isError?: true;
|
|
74
|
+
readonly approval?: AuiV0ToolApproval;
|
|
62
75
|
}
|
|
63
76
|
| {
|
|
64
77
|
readonly type: "image";
|
|
@@ -216,6 +229,7 @@ export function auiV0Encode(message: ThreadMessage): AuiV0Message {
|
|
|
216
229
|
? { result: part.result as ReadonlyJSONValue }
|
|
217
230
|
: undefined),
|
|
218
231
|
...(part.isError ? { isError: true } : undefined),
|
|
232
|
+
...(part.approval ? { approval: part.approval } : undefined),
|
|
219
233
|
};
|
|
220
234
|
}
|
|
221
235
|
|