@assistant-ui/core 0.2.18 → 0.2.19

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.
Files changed (228) hide show
  1. package/dist/index.d.ts +4 -2
  2. package/dist/index.js +3 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/internal.d.ts +2 -1
  5. package/dist/internal.js +2 -1
  6. package/dist/model-context/interactable-composer-metadata.d.ts +105 -0
  7. package/dist/model-context/interactable-composer-metadata.d.ts.map +1 -0
  8. package/dist/model-context/interactable-composer-metadata.js +259 -0
  9. package/dist/model-context/interactable-composer-metadata.js.map +1 -0
  10. package/dist/model-context/registry.d.ts.map +1 -1
  11. package/dist/model-context/registry.js +1 -0
  12. package/dist/model-context/registry.js.map +1 -1
  13. package/dist/model-context/types.d.ts +6 -0
  14. package/dist/model-context/types.d.ts.map +1 -1
  15. package/dist/model-context/types.js +4 -0
  16. package/dist/model-context/types.js.map +1 -1
  17. package/dist/react/AssistantProvider.d.ts +1 -1
  18. package/dist/react/AssistantProvider.js +1 -1
  19. package/dist/react/AssistantRuntimeProvider.d.ts +1 -1
  20. package/dist/react/RuntimeAdapter.js +1 -1
  21. package/dist/react/client/Interactables.d.ts +8 -2
  22. package/dist/react/client/Interactables.d.ts.map +1 -1
  23. package/dist/react/client/Interactables.js +190 -94
  24. package/dist/react/client/Interactables.js.map +1 -1
  25. package/dist/react/client/Tools.js +1 -1
  26. package/dist/react/client/interactable-model-context.d.ts +9 -6
  27. package/dist/react/client/interactable-model-context.d.ts.map +1 -1
  28. package/dist/react/client/interactable-model-context.js +154 -32
  29. package/dist/react/client/interactable-model-context.js.map +1 -1
  30. package/dist/react/index.d.ts +15 -6
  31. package/dist/react/index.js +12 -5
  32. package/dist/react/interactables-legacy/Interactables.d.ts +12 -0
  33. package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -0
  34. package/dist/react/interactables-legacy/Interactables.js +264 -0
  35. package/dist/react/interactables-legacy/Interactables.js.map +1 -0
  36. package/dist/react/interactables-legacy/interactable-model-context.d.ts +12 -0
  37. package/dist/react/interactables-legacy/interactable-model-context.d.ts.map +1 -0
  38. package/dist/react/interactables-legacy/interactable-model-context.js +54 -0
  39. package/dist/react/interactables-legacy/interactable-model-context.js.map +1 -0
  40. package/dist/react/interactables-legacy/scopes.d.ts +58 -0
  41. package/dist/react/interactables-legacy/scopes.d.ts.map +1 -0
  42. package/dist/react/interactables-legacy/scopes.js +0 -0
  43. package/dist/react/interactables-legacy/useAssistantInteractable.d.ts +31 -0
  44. package/dist/react/interactables-legacy/useAssistantInteractable.d.ts.map +1 -0
  45. package/dist/react/{model-context → interactables-legacy}/useAssistantInteractable.js +6 -2
  46. package/dist/react/interactables-legacy/useAssistantInteractable.js.map +1 -0
  47. package/dist/react/interactables-legacy/useInteractableState.d.ts +21 -0
  48. package/dist/react/interactables-legacy/useInteractableState.d.ts.map +1 -0
  49. package/dist/react/interactables-legacy/useInteractableState.js +84 -0
  50. package/dist/react/interactables-legacy/useInteractableState.js.map +1 -0
  51. package/dist/react/model-context/interactableTool.d.ts +53 -0
  52. package/dist/react/model-context/interactableTool.d.ts.map +1 -0
  53. package/dist/react/model-context/interactableTool.js +188 -0
  54. package/dist/react/model-context/interactableTool.js.map +1 -0
  55. package/dist/react/model-context/useAssistantContext.js +1 -1
  56. package/dist/react/model-context/useAssistantDataUI.js +1 -1
  57. package/dist/react/model-context/useAssistantInstructions.js +1 -1
  58. package/dist/react/model-context/useAssistantTool.js +1 -1
  59. package/dist/react/model-context/useAssistantToolUI.js +1 -1
  60. package/dist/react/model-context/useAuiToolOverrides.js +1 -1
  61. package/dist/react/model-context/useInteractable.d.ts +73 -0
  62. package/dist/react/model-context/useInteractable.d.ts.map +1 -0
  63. package/dist/react/model-context/useInteractable.js +100 -0
  64. package/dist/react/model-context/useInteractable.js.map +1 -0
  65. package/dist/react/model-context/useInteractableState.d.ts +8 -5
  66. package/dist/react/model-context/useInteractableState.d.ts.map +1 -1
  67. package/dist/react/model-context/useInteractableState.js +48 -48
  68. package/dist/react/model-context/useInteractableState.js.map +1 -1
  69. package/dist/react/model-context/useInteractableVersions.d.ts +19 -0
  70. package/dist/react/model-context/useInteractableVersions.d.ts.map +1 -0
  71. package/dist/react/model-context/useInteractableVersions.js +51 -0
  72. package/dist/react/model-context/useInteractableVersions.js.map +1 -0
  73. package/dist/react/primitive-hooks/useThreadMessageIds.d.ts +15 -0
  74. package/dist/react/primitive-hooks/useThreadMessageIds.d.ts.map +1 -0
  75. package/dist/react/primitive-hooks/useThreadMessageIds.js +26 -0
  76. package/dist/react/primitive-hooks/useThreadMessageIds.js.map +1 -0
  77. package/dist/react/primitive-hooks/useVoice.js +1 -1
  78. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js +1 -1
  79. package/dist/react/primitives/composer/ComposerAttachments.js +1 -1
  80. package/dist/react/primitives/composer/ComposerQueue.js +1 -1
  81. package/dist/react/primitives/generativeUI/GenerativeUI.js +1 -1
  82. package/dist/react/primitives/message/MessageAttachments.js +1 -1
  83. package/dist/react/primitives/message/MessageGroupedParts.js +1 -1
  84. package/dist/react/primitives/message/MessageParts.js +1 -1
  85. package/dist/react/primitives/message/MessageQuote.js +1 -1
  86. package/dist/react/primitives/part/PartMessages.d.ts +5 -2
  87. package/dist/react/primitives/part/PartMessages.d.ts.map +1 -1
  88. package/dist/react/primitives/part/PartMessages.js +8 -8
  89. package/dist/react/primitives/part/PartMessages.js.map +1 -1
  90. package/dist/react/primitives/thread/ThreadMessages.d.ts +31 -1
  91. package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
  92. package/dist/react/primitives/thread/ThreadMessages.js +64 -2
  93. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  94. package/dist/react/primitives/thread/ThreadSuggestions.js +1 -1
  95. package/dist/react/primitives/threadList/ThreadListItems.js +1 -1
  96. package/dist/react/providers/MessageByIdProvider.d.ts +9 -0
  97. package/dist/react/providers/MessageByIdProvider.d.ts.map +1 -0
  98. package/dist/react/providers/MessageByIdProvider.js +57 -0
  99. package/dist/react/providers/MessageByIdProvider.js.map +1 -0
  100. package/dist/react/providers/ReadonlyThreadProvider.js +1 -1
  101. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +1 -1
  102. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +3 -0
  103. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  104. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +16 -1
  105. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  106. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +1 -1
  107. package/dist/react/runtimes/cloud/auiV0.js +1 -1
  108. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +1 -1
  109. package/dist/react/runtimes/createRuntimeExtras.d.ts +20 -0
  110. package/dist/react/runtimes/createRuntimeExtras.d.ts.map +1 -0
  111. package/dist/react/runtimes/createRuntimeExtras.js +43 -0
  112. package/dist/react/runtimes/createRuntimeExtras.js.map +1 -0
  113. package/dist/react/runtimes/useLocalRuntime.js +1 -1
  114. package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
  115. package/dist/react/runtimes/useRemoteThreadListRuntime.js +6 -2
  116. package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
  117. package/dist/react/runtimes/useStreamingTiming.d.ts +26 -0
  118. package/dist/react/runtimes/useStreamingTiming.d.ts.map +1 -0
  119. package/dist/react/runtimes/useStreamingTiming.js +43 -0
  120. package/dist/react/runtimes/useStreamingTiming.js.map +1 -0
  121. package/dist/react/types/scopes/interactables.d.ts +40 -24
  122. package/dist/react/types/scopes/interactables.d.ts.map +1 -1
  123. package/dist/react/types/store-augmentation.d.ts +3 -1
  124. package/dist/react/types/store-augmentation.d.ts.map +1 -1
  125. package/dist/react/utils/useJSONEqual.d.ts +11 -0
  126. package/dist/react/utils/useJSONEqual.d.ts.map +1 -0
  127. package/dist/react/utils/useJSONEqual.js +30 -0
  128. package/dist/react/utils/useJSONEqual.js.map +1 -0
  129. package/dist/runtime/base/base-composer-runtime-core.d.ts +5 -0
  130. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  131. package/dist/runtime/base/base-composer-runtime-core.js +13 -0
  132. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  133. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
  134. package/dist/runtime/base/default-edit-composer-runtime-core.js +6 -1
  135. package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
  136. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  137. package/dist/runtime/base/default-thread-composer-runtime-core.js +4 -1
  138. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  139. package/dist/runtime/utils/message-repository.d.ts +1 -0
  140. package/dist/runtime/utils/message-repository.d.ts.map +1 -1
  141. package/dist/runtime/utils/message-repository.js +6 -3
  142. package/dist/runtime/utils/message-repository.js.map +1 -1
  143. package/dist/runtime/utils/streaming-timing.d.ts +59 -0
  144. package/dist/runtime/utils/streaming-timing.d.ts.map +1 -0
  145. package/dist/runtime/utils/streaming-timing.js +76 -0
  146. package/dist/runtime/utils/streaming-timing.js.map +1 -0
  147. package/dist/runtime/utils/thread-message-like.js +2 -1
  148. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  149. package/dist/runtimes/external-store/external-store-adapter.d.ts +26 -1
  150. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  151. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +9 -0
  152. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  153. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +19 -0
  154. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  155. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  156. package/dist/runtimes/local/local-thread-runtime-core.js +1 -1
  157. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  158. package/dist/runtimes/remote-thread-list/types.d.ts +12 -0
  159. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  160. package/dist/store/clients/suggestions.js +1 -1
  161. package/dist/store/clients/thread-message-client.js +1 -1
  162. package/dist/store/runtime-clients/composer-runtime-client.js +1 -1
  163. package/dist/store/runtime-clients/message-runtime-client.js +1 -1
  164. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +1 -1
  165. package/dist/store/runtime-clients/thread-runtime-client.js +1 -1
  166. package/dist/tests/remote-thread-list-test-helpers.d.ts +1 -1
  167. package/dist/tests/remote-thread-list-test-helpers.d.ts.map +1 -1
  168. package/dist/tests/remote-thread-list-test-helpers.js +3 -2
  169. package/dist/tests/remote-thread-list-test-helpers.js.map +1 -1
  170. package/package.json +9 -9
  171. package/src/index.ts +17 -0
  172. package/src/internal.ts +7 -0
  173. package/src/model-context/interactable-composer-metadata.test.ts +550 -0
  174. package/src/model-context/interactable-composer-metadata.ts +395 -0
  175. package/src/model-context/registry.ts +5 -0
  176. package/src/model-context/types.ts +12 -0
  177. package/src/react/client/Interactables.test.ts +358 -0
  178. package/src/react/client/Interactables.ts +339 -86
  179. package/src/react/client/interactable-model-context.test.ts +418 -0
  180. package/src/react/client/interactable-model-context.ts +252 -58
  181. package/src/react/index.ts +72 -3
  182. package/src/react/interactables-legacy/Interactables.ts +332 -0
  183. package/src/react/interactables-legacy/interactable-model-context.test.ts +54 -0
  184. package/src/react/interactables-legacy/interactable-model-context.ts +80 -0
  185. package/src/react/interactables-legacy/scopes.ts +66 -0
  186. package/src/react/{model-context → interactables-legacy}/useAssistantInteractable.ts +10 -1
  187. package/src/react/interactables-legacy/useInteractableState.ts +67 -0
  188. package/src/react/model-context/interactableTool.tsx +175 -0
  189. package/src/react/model-context/useInteractable.ts +233 -0
  190. package/src/react/model-context/useInteractableState.ts +31 -23
  191. package/src/react/model-context/useInteractableVersions.ts +48 -0
  192. package/src/react/primitive-hooks/useThreadMessageIds.ts +27 -0
  193. package/src/react/primitives/part/PartMessages.test.tsx +17 -0
  194. package/src/react/primitives/part/PartMessages.tsx +13 -8
  195. package/src/react/primitives/thread/ThreadMessages.tsx +67 -0
  196. package/src/react/providers/MessageByIdProvider.tsx +23 -0
  197. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +21 -1
  198. package/src/react/runtimes/createRuntimeExtras.test.ts +58 -0
  199. package/src/react/runtimes/createRuntimeExtras.ts +68 -0
  200. package/src/react/runtimes/createRuntimeExtras.use.test.ts +50 -0
  201. package/src/react/runtimes/useRemoteThreadListRuntime.ts +13 -1
  202. package/src/react/runtimes/useStreamingTiming.ts +68 -0
  203. package/src/react/types/scopes/interactables.ts +45 -23
  204. package/src/react/types/store-augmentation.ts +4 -2
  205. package/src/react/utils/useJSONEqual.ts +20 -0
  206. package/src/runtime/base/base-composer-runtime-core.ts +13 -0
  207. package/src/runtime/base/default-edit-composer-runtime-core.ts +18 -1
  208. package/src/runtime/base/default-thread-composer-runtime-core.ts +11 -1
  209. package/src/runtime/utils/message-repository.ts +11 -7
  210. package/src/runtime/utils/streaming-timing.test.ts +301 -0
  211. package/src/runtime/utils/streaming-timing.ts +161 -0
  212. package/src/runtime/utils/thread-message-like.ts +2 -1
  213. package/src/runtimes/external-store/external-store-adapter.ts +28 -0
  214. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +33 -1
  215. package/src/runtimes/local/local-thread-runtime-core.ts +4 -1
  216. package/src/runtimes/remote-thread-list/types.ts +13 -0
  217. package/src/tests/MessageRepository.test.ts +2 -0
  218. package/src/tests/composer-can-send.test.ts +1 -0
  219. package/src/tests/default-edit-composer-runtime-core.test.ts +78 -1
  220. package/src/tests/default-thread-composer-runtime-core.test.ts +82 -0
  221. package/src/tests/external-store-thread-runtime-core.test.ts +337 -0
  222. package/src/tests/groupParts.test.ts +32 -0
  223. package/src/tests/remote-thread-list-reactive-threadId.test.ts +90 -0
  224. package/src/tests/remote-thread-list-test-helpers.ts +2 -1
  225. package/src/tests/thread-message-like.test.ts +50 -0
  226. package/dist/react/model-context/useAssistantInteractable.d.ts +0 -22
  227. package/dist/react/model-context/useAssistantInteractable.d.ts.map +0 -1
  228. package/dist/react/model-context/useAssistantInteractable.js.map +0 -1
@@ -26,6 +26,7 @@ var ModelContextRegistry = class {
26
26
  };
27
27
  if (providerContexts.callSettings) context.callSettings = providerContexts.callSettings;
28
28
  if (providerContexts.config) context.config = providerContexts.config;
29
+ if (providerContexts.unstable_composerMetadata) context.unstable_composerMetadata = providerContexts.unstable_composerMetadata;
29
30
  return context;
30
31
  }
31
32
  subscribe(callback) {
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","names":["Tool","ModelContext","ModelContextProvider","mergeModelContexts","AssistantToolProps","AssistantInstructionsConfig","Unsubscribe","ModelContextRegistryToolHandle","ModelContextRegistryInstructionHandle","ModelContextRegistryProviderHandle","ModelContextRegistry","_tools","Map","_instructions","_providers","_subscribers","Set","_providerUnsubscribes","getModelContext","instructions","Array","from","values","filter","Boolean","system","length","join","undefined","tools","Record","toolProps","toolName","render","tool","providerContexts","context","Object","keys","callSettings","config","subscribe","callback","add","delete","notifySubscribers","addTool","TArgs","TResult","id","Symbol","set","update","newTool","has","remove","addInstruction","instruction","disabled","newConfig","newInstruction","newDisabled","addProvider","provider","unsubscribe","get"],"sources":["../../src/model-context/registry.ts"],"sourcesContent":["import type { Tool } from \"assistant-stream\";\nimport {\n type ModelContext,\n type ModelContextProvider,\n mergeModelContexts,\n type AssistantToolProps,\n type AssistantInstructionsConfig,\n} from \"./types\";\nimport type { Unsubscribe } from \"../types/unsubscribe\";\nimport type {\n ModelContextRegistryToolHandle,\n ModelContextRegistryInstructionHandle,\n ModelContextRegistryProviderHandle,\n} from \"./registry-handles\";\n\nexport class ModelContextRegistry implements ModelContextProvider {\n private _tools = new Map<symbol, AssistantToolProps<any, any>>();\n private _instructions = new Map<symbol, string>();\n private _providers = new Map<symbol, ModelContextProvider>();\n private _subscribers = new Set<() => void>();\n private _providerUnsubscribes = new Map<symbol, Unsubscribe | undefined>();\n\n getModelContext(): ModelContext {\n const instructions = Array.from(this._instructions.values()).filter(\n Boolean,\n );\n\n const system =\n instructions.length > 0 ? instructions.join(\"\\n\\n\") : undefined;\n\n const tools: Record<string, Tool<any, any>> = {};\n for (const toolProps of this._tools.values()) {\n const { toolName, render, ...tool } = toolProps;\n tools[toolName] = tool;\n }\n\n const providerContexts = mergeModelContexts(\n new Set(this._providers.values()),\n );\n\n const context: ModelContext = {\n system,\n tools: Object.keys(tools).length > 0 ? tools : undefined,\n };\n\n if (providerContexts.system) {\n context.system = context.system\n ? `${context.system}\\n\\n${providerContexts.system}`\n : providerContexts.system;\n }\n\n if (providerContexts.tools) {\n context.tools = { ...(context.tools || {}), ...providerContexts.tools };\n }\n\n if (providerContexts.callSettings) {\n context.callSettings = providerContexts.callSettings;\n }\n\n if (providerContexts.config) {\n context.config = providerContexts.config;\n }\n\n return context;\n }\n\n subscribe(callback: () => void): Unsubscribe {\n this._subscribers.add(callback);\n return () => this._subscribers.delete(callback);\n }\n\n private notifySubscribers(): void {\n for (const callback of this._subscribers) {\n callback();\n }\n }\n\n addTool<TArgs extends Record<string, unknown>, TResult>(\n tool: AssistantToolProps<TArgs, TResult>,\n ): ModelContextRegistryToolHandle<TArgs, TResult> {\n const id = Symbol();\n\n this._tools.set(id, tool);\n this.notifySubscribers();\n\n return {\n update: (newTool: AssistantToolProps<TArgs, TResult>) => {\n if (this._tools.has(id)) {\n this._tools.set(id, newTool);\n this.notifySubscribers();\n }\n },\n remove: () => {\n this._tools.delete(id);\n this.notifySubscribers();\n },\n };\n }\n\n addInstruction(\n config: string | AssistantInstructionsConfig,\n ): ModelContextRegistryInstructionHandle {\n const id = Symbol();\n\n const instruction =\n typeof config === \"string\" ? config : config.instruction;\n const disabled = typeof config === \"object\" ? config.disabled : false;\n\n if (!disabled) {\n this._instructions.set(id, instruction);\n this.notifySubscribers();\n }\n\n return {\n update: (newConfig: string | AssistantInstructionsConfig) => {\n const newInstruction =\n typeof newConfig === \"string\" ? newConfig : newConfig.instruction;\n const newDisabled =\n typeof newConfig === \"object\" ? newConfig.disabled : false;\n\n if (newDisabled) {\n this._instructions.delete(id);\n } else {\n this._instructions.set(id, newInstruction);\n }\n this.notifySubscribers();\n },\n remove: () => {\n this._instructions.delete(id);\n this.notifySubscribers();\n },\n };\n }\n\n addProvider(\n provider: ModelContextProvider,\n ): ModelContextRegistryProviderHandle {\n const id = Symbol();\n\n this._providers.set(id, provider);\n\n const unsubscribe = provider.subscribe?.(() => {\n this.notifySubscribers();\n });\n this._providerUnsubscribes.set(id, unsubscribe);\n\n this.notifySubscribers();\n\n return {\n remove: () => {\n this._providers.delete(id);\n const unsubscribe = this._providerUnsubscribes.get(id);\n unsubscribe?.();\n this._providerUnsubscribes.delete(id);\n this.notifySubscribers();\n },\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","names":["Tool","ModelContext","ModelContextProvider","mergeModelContexts","AssistantToolProps","AssistantInstructionsConfig","Unsubscribe","ModelContextRegistryToolHandle","ModelContextRegistryInstructionHandle","ModelContextRegistryProviderHandle","ModelContextRegistry","_tools","Map","_instructions","_providers","_subscribers","Set","_providerUnsubscribes","getModelContext","instructions","Array","from","values","filter","Boolean","system","length","join","undefined","tools","Record","toolProps","toolName","render","tool","providerContexts","context","Object","keys","callSettings","config","unstable_composerMetadata","subscribe","callback","add","delete","notifySubscribers","addTool","TArgs","TResult","id","Symbol","set","update","newTool","has","remove","addInstruction","instruction","disabled","newConfig","newInstruction","newDisabled","addProvider","provider","unsubscribe","get"],"sources":["../../src/model-context/registry.ts"],"sourcesContent":["import type { Tool } from \"assistant-stream\";\nimport {\n type ModelContext,\n type ModelContextProvider,\n mergeModelContexts,\n type AssistantToolProps,\n type AssistantInstructionsConfig,\n} from \"./types\";\nimport type { Unsubscribe } from \"../types/unsubscribe\";\nimport type {\n ModelContextRegistryToolHandle,\n ModelContextRegistryInstructionHandle,\n ModelContextRegistryProviderHandle,\n} from \"./registry-handles\";\n\nexport class ModelContextRegistry implements ModelContextProvider {\n private _tools = new Map<symbol, AssistantToolProps<any, any>>();\n private _instructions = new Map<symbol, string>();\n private _providers = new Map<symbol, ModelContextProvider>();\n private _subscribers = new Set<() => void>();\n private _providerUnsubscribes = new Map<symbol, Unsubscribe | undefined>();\n\n getModelContext(): ModelContext {\n const instructions = Array.from(this._instructions.values()).filter(\n Boolean,\n );\n\n const system =\n instructions.length > 0 ? instructions.join(\"\\n\\n\") : undefined;\n\n const tools: Record<string, Tool<any, any>> = {};\n for (const toolProps of this._tools.values()) {\n const { toolName, render, ...tool } = toolProps;\n tools[toolName] = tool;\n }\n\n const providerContexts = mergeModelContexts(\n new Set(this._providers.values()),\n );\n\n const context: ModelContext = {\n system,\n tools: Object.keys(tools).length > 0 ? tools : undefined,\n };\n\n if (providerContexts.system) {\n context.system = context.system\n ? `${context.system}\\n\\n${providerContexts.system}`\n : providerContexts.system;\n }\n\n if (providerContexts.tools) {\n context.tools = { ...(context.tools || {}), ...providerContexts.tools };\n }\n\n if (providerContexts.callSettings) {\n context.callSettings = providerContexts.callSettings;\n }\n\n if (providerContexts.config) {\n context.config = providerContexts.config;\n }\n\n if (providerContexts.unstable_composerMetadata) {\n context.unstable_composerMetadata =\n providerContexts.unstable_composerMetadata;\n }\n\n return context;\n }\n\n subscribe(callback: () => void): Unsubscribe {\n this._subscribers.add(callback);\n return () => this._subscribers.delete(callback);\n }\n\n private notifySubscribers(): void {\n for (const callback of this._subscribers) {\n callback();\n }\n }\n\n addTool<TArgs extends Record<string, unknown>, TResult>(\n tool: AssistantToolProps<TArgs, TResult>,\n ): ModelContextRegistryToolHandle<TArgs, TResult> {\n const id = Symbol();\n\n this._tools.set(id, tool);\n this.notifySubscribers();\n\n return {\n update: (newTool: AssistantToolProps<TArgs, TResult>) => {\n if (this._tools.has(id)) {\n this._tools.set(id, newTool);\n this.notifySubscribers();\n }\n },\n remove: () => {\n this._tools.delete(id);\n this.notifySubscribers();\n },\n };\n }\n\n addInstruction(\n config: string | AssistantInstructionsConfig,\n ): ModelContextRegistryInstructionHandle {\n const id = Symbol();\n\n const instruction =\n typeof config === \"string\" ? config : config.instruction;\n const disabled = typeof config === \"object\" ? config.disabled : false;\n\n if (!disabled) {\n this._instructions.set(id, instruction);\n this.notifySubscribers();\n }\n\n return {\n update: (newConfig: string | AssistantInstructionsConfig) => {\n const newInstruction =\n typeof newConfig === \"string\" ? newConfig : newConfig.instruction;\n const newDisabled =\n typeof newConfig === \"object\" ? newConfig.disabled : false;\n\n if (newDisabled) {\n this._instructions.delete(id);\n } else {\n this._instructions.set(id, newInstruction);\n }\n this.notifySubscribers();\n },\n remove: () => {\n this._instructions.delete(id);\n this.notifySubscribers();\n },\n };\n }\n\n addProvider(\n provider: ModelContextProvider,\n ): ModelContextRegistryProviderHandle {\n const id = Symbol();\n\n this._providers.set(id, provider);\n\n const unsubscribe = provider.subscribe?.(() => {\n this.notifySubscribers();\n });\n this._providerUnsubscribes.set(id, unsubscribe);\n\n this.notifySubscribers();\n\n return {\n remove: () => {\n this._providers.delete(id);\n const unsubscribe = this._providerUnsubscribes.get(id);\n unsubscribe?.();\n this._providerUnsubscribes.delete(id);\n this.notifySubscribers();\n },\n };\n }\n}\n"],"mappings":"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"}
@@ -23,6 +23,12 @@ type ModelContext = {
23
23
  tools?: Record<string, Tool<any, any>> | undefined;
24
24
  callSettings?: LanguageModelV1CallSettings | undefined;
25
25
  config?: LanguageModelConfig | undefined;
26
+ /**
27
+ * Persisted message metadata pulled at send time and merged into the outgoing
28
+ * user message's `metadata.custom` (not forwarded to the model directly).
29
+ * Ignored by the transport, which only reads system/tools/callSettings/config.
30
+ */
31
+ unstable_composerMetadata?: Record<string, unknown> | undefined;
26
32
  };
27
33
  type ModelContextProvider = {
28
34
  getModelContext: () => ModelContext;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../../src/model-context/types.ts"],"mappings":";;;;KAGY,2BAAA;EACV,SAAA;EACA,WAAA;EACA,IAAA;EACA,eAAA;EACA,gBAAA;EACA,IAAA;EACA,OAAA,GAAU,MAAM;AAAA;AAAA,KAGN,mBAAA;EACV,MAAA;EACA,OAAA;EACA,SAAA;EACA,eAAA;AAAA;AAAA,KAGU,YAAA;EACV,QAAA;EACA,MAAA;EACA,KAAA,GAAQ,MAAA,SAAe,IAAA;EACvB,YAAA,GAAe,2BAAA;EACf,MAAA,GAAS,mBAAA;AAAA;AAAA,KAGC,oBAAA;EACV,eAAA,QAAuB,YAAA;EACvB,SAAA,IAAa,QAAA,iBAAyB,WAAW;AAAA;AAAA,KAGvC,kBAAA,eACI,MAAA,8BAEZ,IAAA,CAAK,KAAA,EAAO,OAAA;EACd,QAAA;EACA,MAAA;AAAA;AAAA,KAGU,2BAAA;EACV,QAAA;EACA,WAAW;AAAA;AAAA,KAGD,sBAAA;EACV,UAAA;EACA,QAAQ;AAAA;AAAA,cAGG,kBAAA,GACX,SAAA,EAAW,GAAA,CAAI,oBAAA,MACd,YAAA"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../src/model-context/types.ts"],"mappings":";;;;KAGY,2BAAA;EACV,SAAA;EACA,WAAA;EACA,IAAA;EACA,eAAA;EACA,gBAAA;EACA,IAAA;EACA,OAAA,GAAU,MAAM;AAAA;AAAA,KAGN,mBAAA;EACV,MAAA;EACA,OAAA;EACA,SAAA;EACA,eAAA;AAAA;AAAA,KAGU,YAAA;EACV,QAAA;EACA,MAAA;EACA,KAAA,GAAQ,MAAA,SAAe,IAAA;EACvB,YAAA,GAAe,2BAAA;EACf,MAAA,GAAS,mBAAA;EAVT;;;;AAEe;EAcf,yBAAA,GAA4B,MAAA;AAAA;AAAA,KAGlB,oBAAA;EACV,eAAA,QAAuB,YAAA;EACvB,SAAA,IAAa,QAAA,iBAAyB,WAAW;AAAA;AAAA,KAGvC,kBAAA,eACI,MAAA,8BAEZ,IAAA,CAAK,KAAA,EAAO,OAAA;EACd,QAAA;EACA,MAAA;AAAA;AAAA,KAGU,2BAAA;EACV,QAAA;EACA,WAAW;AAAA;AAAA,KAGD,sBAAA;EACV,UAAA;EACA,QAAQ;AAAA;AAAA,cAGG,kBAAA,GACX,SAAA,EAAW,GAAA,CAAI,oBAAA,MACd,YAAA"}
@@ -32,6 +32,10 @@ const mergeModelContexts = (configSet) => {
32
32
  ...acc.callSettings,
33
33
  ...config.callSettings
34
34
  };
35
+ if (config.unstable_composerMetadata) acc.unstable_composerMetadata = {
36
+ ...acc.unstable_composerMetadata,
37
+ ...config.unstable_composerMetadata
38
+ };
35
39
  return acc;
36
40
  }, {});
37
41
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","names":["Unsubscribe","Tool","LanguageModelV1CallSettings","maxTokens","temperature","topP","presencePenalty","frequencyPenalty","seed","headers","Record","LanguageModelConfig","apiKey","baseUrl","modelName","reasoningEffort","ModelContext","priority","system","tools","callSettings","config","ModelContextProvider","getModelContext","subscribe","callback","AssistantToolProps","TArgs","TResult","toolName","render","AssistantInstructionsConfig","disabled","instruction","AssistantContextConfig","getContext","mergeModelContexts","configSet","Set","configs","Array","from","map","c","sort","a","b","toolPriorities","reduce","acc","name","tool","Object","entries","existing","existingPriority","Error","higherPriorityTool","lowerPriorityTool","Math","max"],"sources":["../../src/model-context/types.ts"],"sourcesContent":["import type { Unsubscribe } from \"../types/unsubscribe\";\nimport type { Tool } from \"assistant-stream\";\n\nexport type LanguageModelV1CallSettings = {\n maxTokens?: number;\n temperature?: number;\n topP?: number;\n presencePenalty?: number;\n frequencyPenalty?: number;\n seed?: number;\n headers?: Record<string, string | undefined>;\n};\n\nexport type LanguageModelConfig = {\n apiKey?: string;\n baseUrl?: string;\n modelName?: string;\n reasoningEffort?: string;\n};\n\nexport type ModelContext = {\n priority?: number | undefined;\n system?: string | undefined;\n tools?: Record<string, Tool<any, any>> | undefined;\n callSettings?: LanguageModelV1CallSettings | undefined;\n config?: LanguageModelConfig | undefined;\n};\n\nexport type ModelContextProvider = {\n getModelContext: () => ModelContext;\n subscribe?: (callback: () => void) => Unsubscribe;\n};\n\nexport type AssistantToolProps<\n TArgs extends Record<string, unknown>,\n TResult,\n> = Tool<TArgs, TResult> & {\n toolName: string;\n render?: unknown;\n};\n\nexport type AssistantInstructionsConfig = {\n disabled?: boolean | undefined;\n instruction: string;\n};\n\nexport type AssistantContextConfig = {\n getContext: () => string;\n disabled?: boolean | undefined;\n};\n\nexport const mergeModelContexts = (\n configSet: Set<ModelContextProvider>,\n): ModelContext => {\n const configs = Array.from(configSet)\n .map((c) => c.getModelContext())\n .sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));\n\n const toolPriorities: Record<string, number> = {};\n\n return configs.reduce((acc, config) => {\n const priority = config.priority ?? 0;\n if (config.system) {\n if (acc.system) {\n acc.system += `\\n\\n${config.system}`;\n } else {\n acc.system = config.system;\n }\n }\n if (config.tools) {\n for (const [name, tool] of Object.entries(config.tools)) {\n const existing = acc.tools?.[name];\n if (existing && existing !== tool) {\n const existingPriority = toolPriorities[name]!;\n if (existingPriority === priority) {\n throw new Error(\n `You tried to define a tool with the name ${name}, but it already exists.`,\n );\n }\n\n const higherPriorityTool =\n existingPriority > priority ? existing : tool;\n const lowerPriorityTool =\n existingPriority > priority ? tool : existing;\n acc.tools![name] = {\n ...lowerPriorityTool,\n ...higherPriorityTool,\n } as Tool<any, any>;\n toolPriorities[name] = Math.max(existingPriority, priority);\n continue;\n }\n\n if (!acc.tools) acc.tools = {};\n acc.tools[name] = tool;\n toolPriorities[name] ??= priority;\n }\n }\n if (config.config) {\n acc.config = {\n ...acc.config,\n ...config.config,\n };\n }\n if (config.callSettings) {\n acc.callSettings = {\n ...acc.callSettings,\n ...config.callSettings,\n };\n }\n return acc;\n }, {} as ModelContext);\n};\n"],"mappings":";AAmDA,MAAaoC,sBACXC,cACiB;CACjB,MAAME,UAAUC,MAAMC,KAAKJ,SAAS,CAAC,CAClCK,KAAKC,MAAMA,EAAEpB,gBAAgB,CAAC,CAAC,CAC/BqB,MAAMC,GAAGC,OAAOA,EAAE7B,YAAY,MAAM4B,EAAE5B,YAAY,EAAE;CAEvD,MAAM8B,iBAAyC,CAAC;CAEhD,OAAOR,QAAQS,QAAQC,KAAK5B,WAAW;EACrC,MAAMJ,WAAWI,OAAOJ,YAAY;EACpC,IAAII,OAAOH,QACT,IAAI+B,IAAI/B,QACN+B,IAAI/B,UAAU,OAAOG,OAAOH;OAE5B+B,IAAI/B,SAASG,OAAOH;EAGxB,IAAIG,OAAOF,OACT,KAAK,MAAM,CAAC+B,MAAMC,SAASC,OAAOC,QAAQhC,OAAOF,KAAK,GAAG;GACvD,MAAMmC,WAAWL,IAAI9B,QAAQ+B;GAC7B,IAAII,YAAYA,aAAaH,MAAM;IACjC,MAAMI,mBAAmBR,eAAeG;IACxC,IAAIK,qBAAqBtC,UACvB,MAAM,IAAIuC,MACR,4CAA4CN,KAAI,yBAClD;IAGF,MAAMO,qBACJF,mBAAmBtC,WAAWqC,WAAWH;IAC3C,MAAMO,oBACJH,mBAAmBtC,WAAWkC,OAAOG;IACvCL,IAAI9B,MAAO+B,QAAQ;KACjB,GAAGQ;KACH,GAAGD;IACL;IACAV,eAAeG,QAAQS,KAAKC,IAAIL,kBAAkBtC,QAAQ;IAC1D;GACF;GAEA,IAAI,CAACgC,IAAI9B,OAAO8B,IAAI9B,QAAQ,CAAC;GAC7B8B,IAAI9B,MAAM+B,QAAQC;GAClBJ,eAAeG,UAAUjC;EAC3B;EAEF,IAAII,OAAOA,QACT4B,IAAI5B,SAAS;GACX,GAAG4B,IAAI5B;GACP,GAAGA,OAAOA;EACZ;EAEF,IAAIA,OAAOD,cACT6B,IAAI7B,eAAe;GACjB,GAAG6B,IAAI7B;GACP,GAAGC,OAAOD;EACZ;EAEF,OAAO6B;CACT,GAAG,CAAC,CAAiB;AACvB"}
1
+ {"version":3,"file":"types.js","names":["Unsubscribe","Tool","LanguageModelV1CallSettings","maxTokens","temperature","topP","presencePenalty","frequencyPenalty","seed","headers","Record","LanguageModelConfig","apiKey","baseUrl","modelName","reasoningEffort","ModelContext","priority","system","tools","callSettings","config","unstable_composerMetadata","ModelContextProvider","getModelContext","subscribe","callback","AssistantToolProps","TArgs","TResult","toolName","render","AssistantInstructionsConfig","disabled","instruction","AssistantContextConfig","getContext","mergeModelContexts","configSet","Set","configs","Array","from","map","c","sort","a","b","toolPriorities","reduce","acc","name","tool","Object","entries","existing","existingPriority","Error","higherPriorityTool","lowerPriorityTool","Math","max"],"sources":["../../src/model-context/types.ts"],"sourcesContent":["import type { Unsubscribe } from \"../types/unsubscribe\";\nimport type { Tool } from \"assistant-stream\";\n\nexport type LanguageModelV1CallSettings = {\n maxTokens?: number;\n temperature?: number;\n topP?: number;\n presencePenalty?: number;\n frequencyPenalty?: number;\n seed?: number;\n headers?: Record<string, string | undefined>;\n};\n\nexport type LanguageModelConfig = {\n apiKey?: string;\n baseUrl?: string;\n modelName?: string;\n reasoningEffort?: string;\n};\n\nexport type ModelContext = {\n priority?: number | undefined;\n system?: string | undefined;\n tools?: Record<string, Tool<any, any>> | undefined;\n callSettings?: LanguageModelV1CallSettings | undefined;\n config?: LanguageModelConfig | undefined;\n /**\n * Persisted message metadata pulled at send time and merged into the outgoing\n * user message's `metadata.custom` (not forwarded to the model directly).\n * Ignored by the transport, which only reads system/tools/callSettings/config.\n */\n unstable_composerMetadata?: Record<string, unknown> | undefined;\n};\n\nexport type ModelContextProvider = {\n getModelContext: () => ModelContext;\n subscribe?: (callback: () => void) => Unsubscribe;\n};\n\nexport type AssistantToolProps<\n TArgs extends Record<string, unknown>,\n TResult,\n> = Tool<TArgs, TResult> & {\n toolName: string;\n render?: unknown;\n};\n\nexport type AssistantInstructionsConfig = {\n disabled?: boolean | undefined;\n instruction: string;\n};\n\nexport type AssistantContextConfig = {\n getContext: () => string;\n disabled?: boolean | undefined;\n};\n\nexport const mergeModelContexts = (\n configSet: Set<ModelContextProvider>,\n): ModelContext => {\n const configs = Array.from(configSet)\n .map((c) => c.getModelContext())\n .sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));\n\n const toolPriorities: Record<string, number> = {};\n\n return configs.reduce((acc, config) => {\n const priority = config.priority ?? 0;\n if (config.system) {\n if (acc.system) {\n acc.system += `\\n\\n${config.system}`;\n } else {\n acc.system = config.system;\n }\n }\n if (config.tools) {\n for (const [name, tool] of Object.entries(config.tools)) {\n const existing = acc.tools?.[name];\n if (existing && existing !== tool) {\n const existingPriority = toolPriorities[name]!;\n if (existingPriority === priority) {\n throw new Error(\n `You tried to define a tool with the name ${name}, but it already exists.`,\n );\n }\n\n const higherPriorityTool =\n existingPriority > priority ? existing : tool;\n const lowerPriorityTool =\n existingPriority > priority ? tool : existing;\n acc.tools![name] = {\n ...lowerPriorityTool,\n ...higherPriorityTool,\n } as Tool<any, any>;\n toolPriorities[name] = Math.max(existingPriority, priority);\n continue;\n }\n\n if (!acc.tools) acc.tools = {};\n acc.tools[name] = tool;\n toolPriorities[name] ??= priority;\n }\n }\n if (config.config) {\n acc.config = {\n ...acc.config,\n ...config.config,\n };\n }\n if (config.callSettings) {\n acc.callSettings = {\n ...acc.callSettings,\n ...config.callSettings,\n };\n }\n if (config.unstable_composerMetadata) {\n acc.unstable_composerMetadata = {\n ...acc.unstable_composerMetadata,\n ...config.unstable_composerMetadata,\n };\n }\n return acc;\n }, {} as ModelContext);\n};\n"],"mappings":";AAyDA,MAAaqC,sBACXC,cACiB;CACjB,MAAME,UAAUC,MAAMC,KAAKJ,SAAS,CAAC,CAClCK,KAAKC,MAAMA,EAAEpB,gBAAgB,CAAC,CAAC,CAC/BqB,MAAMC,GAAGC,OAAOA,EAAE9B,YAAY,MAAM6B,EAAE7B,YAAY,EAAE;CAEvD,MAAM+B,iBAAyC,CAAC;CAEhD,OAAOR,QAAQS,QAAQC,KAAK7B,WAAW;EACrC,MAAMJ,WAAWI,OAAOJ,YAAY;EACpC,IAAII,OAAOH,QACT,IAAIgC,IAAIhC,QACNgC,IAAIhC,UAAU,OAAOG,OAAOH;OAE5BgC,IAAIhC,SAASG,OAAOH;EAGxB,IAAIG,OAAOF,OACT,KAAK,MAAM,CAACgC,MAAMC,SAASC,OAAOC,QAAQjC,OAAOF,KAAK,GAAG;GACvD,MAAMoC,WAAWL,IAAI/B,QAAQgC;GAC7B,IAAII,YAAYA,aAAaH,MAAM;IACjC,MAAMI,mBAAmBR,eAAeG;IACxC,IAAIK,qBAAqBvC,UACvB,MAAM,IAAIwC,MACR,4CAA4CN,KAAI,yBAClD;IAGF,MAAMO,qBACJF,mBAAmBvC,WAAWsC,WAAWH;IAC3C,MAAMO,oBACJH,mBAAmBvC,WAAWmC,OAAOG;IACvCL,IAAI/B,MAAOgC,QAAQ;KACjB,GAAGQ;KACH,GAAGD;IACL;IACAV,eAAeG,QAAQS,KAAKC,IAAIL,kBAAkBvC,QAAQ;IAC1D;GACF;GAEA,IAAI,CAACiC,IAAI/B,OAAO+B,IAAI/B,QAAQ,CAAC;GAC7B+B,IAAI/B,MAAMgC,QAAQC;GAClBJ,eAAeG,UAAUlC;EAC3B;EAEF,IAAII,OAAOA,QACT6B,IAAI7B,SAAS;GACX,GAAG6B,IAAI7B;GACP,GAAGA,OAAOA;EACZ;EAEF,IAAIA,OAAOD,cACT8B,IAAI9B,eAAe;GACjB,GAAG8B,IAAI9B;GACP,GAAGC,OAAOD;EACZ;EAEF,IAAIC,OAAOC,2BACT4B,IAAI5B,4BAA4B;GAC9B,GAAG4B,IAAI5B;GACP,GAAGD,OAAOC;EACZ;EAEF,OAAO4B;CACT,GAAG,CAAC,CAAiB;AACvB"}
@@ -1,6 +1,6 @@
1
1
  import { AssistantRuntime } from "../runtime/api/assistant-runtime.js";
2
- import { ComponentType, FC, PropsWithChildren } from "react";
3
2
  import { AssistantClient } from "@assistant-ui/store";
3
+ import { ComponentType, FC, PropsWithChildren } from "react";
4
4
 
5
5
  //#region src/react/AssistantProvider.d.ts
6
6
  declare const getRenderComponent: (runtime: AssistantRuntime) => ComponentType | undefined;
@@ -1,6 +1,6 @@
1
1
  import { RuntimeAdapter } from "./RuntimeAdapter.js";
2
- import { memo } from "@assistant-ui/tap/react-shim";
3
2
  import { AuiProvider, useAui } from "@assistant-ui/store";
3
+ import { memo } from "@assistant-ui/tap/react-shim";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  //#region src/react/AssistantProvider.tsx
6
6
  const getRenderComponent = (runtime) => {
@@ -1,6 +1,6 @@
1
1
  import { AssistantRuntime } from "../runtime/api/assistant-runtime.js";
2
- import { ReactNode } from "react";
3
2
  import { AssistantClient } from "@assistant-ui/store";
3
+ import { ReactNode } from "react";
4
4
 
5
5
  //#region src/react/AssistantRuntimeProvider.d.ts
6
6
  /**
@@ -2,8 +2,8 @@ import { ThreadListClient } from "../store/runtime-clients/thread-list-runtime-c
2
2
  import { baseRuntimeAdapterTransformScopes } from "../store/clients/runtime-adapter.js";
3
3
  import { DataRenderers } from "./client/DataRenderers.js";
4
4
  import { Tools } from "./client/Tools.js";
5
- import { useEffect } from "@assistant-ui/tap/react-shim";
6
5
  import { attachTransformScopes, useAssistantClientRef } from "@assistant-ui/store";
6
+ import { useEffect } from "@assistant-ui/tap/react-shim";
7
7
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
8
8
  import { resource, useResource } from "@assistant-ui/tap";
9
9
  //#region src/react/RuntimeAdapter.ts
@@ -1,7 +1,13 @@
1
+ import { Unstable_InteractablesConfig } from "../types/scopes/interactables.js";
1
2
  import { ClientOutput } from "@assistant-ui/store";
2
3
 
3
4
  //#region src/react/client/Interactables.d.ts
4
- declare const Interactables: import("@assistant-ui/tap").Resource<ClientOutput<"interactables">, []>;
5
+ /**
6
+ * Registers the unstable interactables store scope.
7
+ *
8
+ * @deprecated Unstable / Experimental (not actually removed).
9
+ */
10
+ declare const unstable_Interactables: import("@assistant-ui/tap").Resource<ClientOutput<"unstable_interactables">, [(Unstable_InteractablesConfig | undefined)?]>;
5
11
  //#endregion
6
- export { Interactables };
12
+ export { unstable_Interactables };
7
13
  //# sourceMappingURL=Interactables.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Interactables.d.ts","names":[],"sources":["../../../src/react/client/Interactables.ts"],"mappings":";;;cAgUa,aAAA,8BAAa,QAAA,CAAA,YAAA"}
1
+ {"version":3,"file":"Interactables.d.ts","names":[],"sources":["../../../src/react/client/Interactables.ts"],"mappings":";;;;;;AA6jBA;;;cAAa,sBAAA,8BAAsB,QAAA,CAAA,YAAA,8BAAA,4BAAA"}
@@ -1,30 +1,55 @@
1
+ import { findModelKnownState, interactableToolName } from "../../model-context/interactable-composer-metadata.js";
1
2
  import { ModelContext } from "../../store/clients/model-context-client.js";
2
3
  import { buildInteractableModelContext } from "./interactable-model-context.js";
3
4
  import { toJSONSchema, toPartialJSONSchema } from "assistant-stream";
4
- import { useCallback, useEffect, useMemo, useRef, useState } from "@assistant-ui/tap/react-shim";
5
5
  import { attachTransformScopes, useAssistantClientRef } from "@assistant-ui/store";
6
+ import { useCallback, useEffect, useMemo, useRef, useState } from "@assistant-ui/tap/react-shim";
6
7
  import { resource } from "@assistant-ui/tap";
7
8
  //#region src/react/client/Interactables.ts
8
9
  const PERSISTENCE_DEBOUNCE_MS = 500;
9
- const useInteractables = () => {
10
+ const hasInteractableCreateCall = (messages, id, name) => messages.some((message) => message.role === "assistant" && message.content?.some((part) => {
11
+ if (!part || typeof part !== "object") return false;
12
+ const p = part;
13
+ return p.type === "tool-call" && p.toolCallId === id && p.toolName === name;
14
+ }));
15
+ const useInteractablesResource = ({ persistence } = {}) => {
10
16
  const [state, setState] = useState(() => ({
11
17
  definitions: {},
12
18
  persistence: {}
13
19
  }));
14
20
  const clientRef = useAssistantClientRef();
15
21
  const stateRef = useRef(state);
16
- useEffect(() => {
17
- stateRef.current = state;
18
- }, [state]);
19
22
  const subscribersRef = useRef(/* @__PURE__ */ new Set());
20
23
  const partialSchemaCacheRef = useRef(/* @__PURE__ */ new Map());
21
- const detachedStateRef = useRef(/* @__PURE__ */ new Map());
24
+ const streamBaselinesRef = useRef(/* @__PURE__ */ new Map());
25
+ const detachedAppStateRef = useRef(/* @__PURE__ */ new Map());
26
+ const detachedThreadStateRef = useRef(/* @__PURE__ */ new Map());
27
+ const registrationCountsRef = useRef(/* @__PURE__ */ new Map());
28
+ const updateToolUIsRef = useRef(/* @__PURE__ */ new Map());
29
+ const loadedStateRef = useRef(/* @__PURE__ */ new Map());
30
+ const touchedIdsRef = useRef(/* @__PURE__ */ new Set());
22
31
  const adapterRef = useRef(void 0);
23
32
  const debounceTimerRef = useRef(void 0);
24
33
  const syncSeqRef = useRef(0);
25
34
  const hasPendingLocalChangeRef = useRef(false);
26
35
  const flushResolversRef = useRef([]);
27
36
  const dirtyIdsRef = useRef(/* @__PURE__ */ new Set());
37
+ const setStateAndRef = useCallback((updater) => {
38
+ const next = updater(stateRef.current);
39
+ stateRef.current = next;
40
+ setState(next);
41
+ }, []);
42
+ const exportState = useCallback(() => {
43
+ const result = {};
44
+ for (const [id, def] of Object.entries(stateRef.current.definitions)) {
45
+ if (def.scope === "thread") continue;
46
+ result[id] = {
47
+ name: def.name,
48
+ state: def.state
49
+ };
50
+ }
51
+ return result;
52
+ }, []);
28
53
  const runPersistence = useCallback(async () => {
29
54
  const adapter = adapterRef.current;
30
55
  if (!adapter) {
@@ -36,13 +61,8 @@ const useInteractables = () => {
36
61
  const dirtyIds = new Set(dirtyIdsRef.current);
37
62
  dirtyIdsRef.current.clear();
38
63
  hasPendingLocalChangeRef.current = true;
39
- const exported = stateRef.current.definitions;
40
- const payload = {};
41
- for (const [id, def] of Object.entries(exported)) payload[id] = {
42
- name: def.name,
43
- state: def.state
44
- };
45
- setState((prev) => ({
64
+ const payload = exportState();
65
+ setStateAndRef((prev) => ({
46
66
  ...prev,
47
67
  persistence: {
48
68
  ...prev.persistence,
@@ -56,19 +76,19 @@ const useInteractables = () => {
56
76
  await adapter.save(payload);
57
77
  if (syncSeqRef.current === seq) {
58
78
  hasPendingLocalChangeRef.current = false;
59
- setState((prev_1) => {
60
- const persistence = { ...prev_1.persistence };
61
- for (const id_2 of dirtyIds) delete persistence[id_2];
79
+ setStateAndRef((prev_1) => {
80
+ const persistence_0 = { ...prev_1.persistence };
81
+ for (const id_2 of dirtyIds) delete persistence_0[id_2];
62
82
  return {
63
83
  ...prev_1,
64
- persistence
84
+ persistence: persistence_0
65
85
  };
66
86
  });
67
87
  }
68
88
  } catch (e) {
69
89
  if (syncSeqRef.current === seq) {
70
90
  hasPendingLocalChangeRef.current = false;
71
- setState((prev_0) => ({
91
+ setStateAndRef((prev_0) => ({
72
92
  ...prev_0,
73
93
  persistence: {
74
94
  ...prev_0.persistence,
@@ -86,7 +106,7 @@ const useInteractables = () => {
86
106
  flushResolversRef.current = [];
87
107
  }
88
108
  }
89
- }, []);
109
+ }, [exportState, setStateAndRef]);
90
110
  const schedulePersistence = useCallback((id_3) => {
91
111
  if (!adapterRef.current) return;
92
112
  dirtyIdsRef.current.add(id_3);
@@ -100,35 +120,68 @@ const useInteractables = () => {
100
120
  }, PERSISTENCE_DEBOUNCE_MS);
101
121
  }, PERSISTENCE_DEBOUNCE_MS);
102
122
  }, [runPersistence]);
103
- const exportState = useCallback(() => {
104
- const result = {};
105
- for (const [id_4, def_0] of Object.entries(stateRef.current.definitions)) result[id_4] = {
106
- name: def_0.name,
107
- state: def_0.state
108
- };
109
- return result;
110
- }, []);
111
- const importState = useCallback((saved) => {
112
- for (const [id_5, entry] of Object.entries(saved)) detachedStateRef.current.set(id_5, entry.state);
113
- setState((prev_2) => {
123
+ const restorePersistedState = useCallback((saved, options) => {
124
+ const shouldStash = options.shouldStash ?? (() => true);
125
+ const shouldApply = options.shouldApply ?? (() => true);
126
+ for (const [id_4, entry] of Object.entries(saved)) if (shouldStash(id_4)) options.stash.set(id_4, entry.state);
127
+ setStateAndRef((prev_2) => {
114
128
  let changed = false;
115
129
  const definitions = { ...prev_2.definitions };
116
- for (const [id_6, entry_0] of Object.entries(saved)) if (definitions[id_6]) {
117
- definitions[id_6] = {
118
- ...definitions[id_6],
130
+ for (const [id_5, entry_0] of Object.entries(saved)) {
131
+ const def_0 = definitions[id_5];
132
+ if (!def_0 || !shouldApply(id_5, def_0)) continue;
133
+ definitions[id_5] = {
134
+ ...def_0,
119
135
  state: entry_0.state
120
136
  };
121
137
  changed = true;
122
138
  }
123
- return changed ? {
139
+ if (!changed) return prev_2;
140
+ return {
124
141
  ...prev_2,
125
142
  definitions
126
- } : prev_2;
143
+ };
127
144
  });
128
- }, []);
129
- const setPersistenceAdapter = useCallback((adapter_0) => {
130
- adapterRef.current = adapter_0;
131
- }, []);
145
+ }, [setStateAndRef]);
146
+ const importState = useCallback((saved_0) => {
147
+ restorePersistedState(saved_0, { stash: detachedAppStateRef.current });
148
+ }, [restorePersistedState]);
149
+ const applyLoadedState = useCallback((saved_1) => {
150
+ restorePersistedState(saved_1, {
151
+ stash: loadedStateRef.current,
152
+ shouldStash: (id_6) => !touchedIdsRef.current.has(id_6),
153
+ shouldApply: (id_7, def_1) => !touchedIdsRef.current.has(id_7) && def_1.scope !== "thread"
154
+ });
155
+ }, [restorePersistedState]);
156
+ const loadFromAdapter = useCallback(async (adapter_0) => {
157
+ if (!adapter_0.load) return;
158
+ try {
159
+ const saved_2 = await adapter_0.load();
160
+ if (!saved_2 || adapterRef.current !== adapter_0) return;
161
+ applyLoadedState(saved_2);
162
+ } catch (e_0) {
163
+ console.warn("[Interactables] Persistence load failed.", e_0);
164
+ }
165
+ }, [applyLoadedState]);
166
+ const setPersistenceAdapter = useCallback((adapter_1) => {
167
+ adapterRef.current = adapter_1;
168
+ if (adapter_1) loadFromAdapter(adapter_1);
169
+ }, [loadFromAdapter]);
170
+ const getCurrentThreadId = useCallback(() => {
171
+ const client = clientRef.current;
172
+ if (!client) return void 0;
173
+ const threadListItem = client.threadListItem;
174
+ if (threadListItem.source != null) return threadListItem().getState().id;
175
+ const threads = client.threads;
176
+ if (threads.source != null) return threads().getState().mainThreadId;
177
+ }, [clientRef]);
178
+ useEffect(() => {
179
+ if (!persistence) return;
180
+ setPersistenceAdapter(persistence);
181
+ return () => {
182
+ if (adapterRef.current === persistence) adapterRef.current = void 0;
183
+ };
184
+ }, [persistence, setPersistenceAdapter]);
132
185
  const flush = useCallback(async () => {
133
186
  if (debounceTimerRef.current !== void 0) {
134
187
  clearTimeout(debounceTimerRef.current);
@@ -149,43 +202,28 @@ const useInteractables = () => {
149
202
  runPersistence();
150
203
  }
151
204
  }, [runPersistence]);
152
- const setDefState = useCallback((id_7, updater) => {
153
- setState((prev_3) => {
154
- const existing = prev_3.definitions[id_7];
205
+ const setDefState = useCallback((id_8, updater_0) => {
206
+ touchedIdsRef.current.add(id_8);
207
+ setStateAndRef((prev_3) => {
208
+ const existing = prev_3.definitions[id_8];
155
209
  if (!existing) return prev_3;
156
210
  return {
157
211
  ...prev_3,
158
212
  definitions: {
159
213
  ...prev_3.definitions,
160
- [id_7]: {
161
- ...existing,
162
- state: updater(existing.state)
163
- }
164
- }
165
- };
166
- });
167
- if (stateRef.current.definitions[id_7]) schedulePersistence(id_7);
168
- }, [schedulePersistence]);
169
- const setDefSelected = useCallback((id_8, selected) => {
170
- setState((prev_4) => {
171
- const existing_0 = prev_4.definitions[id_8];
172
- if (!existing_0) return prev_4;
173
- return {
174
- ...prev_4,
175
- definitions: {
176
- ...prev_4.definitions,
177
214
  [id_8]: {
178
- ...existing_0,
179
- selected
215
+ ...existing,
216
+ state: updater_0(existing.state)
180
217
  }
181
218
  }
182
219
  };
183
220
  });
184
- }, []);
221
+ if (stateRef.current.definitions[id_8]?.scope !== "thread") schedulePersistence(id_8);
222
+ }, [schedulePersistence, setStateAndRef]);
185
223
  const provider = useMemo(() => ({
186
224
  getModelContext: () => {
187
225
  const defs = stateRef.current.definitions;
188
- return buildInteractableModelContext(defs, partialSchemaCacheRef.current, setDefState) ?? {};
226
+ return buildInteractableModelContext(defs, partialSchemaCacheRef.current, setDefState, streamBaselinesRef.current) ?? {};
189
227
  },
190
228
  subscribe: (callback) => {
191
229
  subscribersRef.current.add(callback);
@@ -201,59 +239,117 @@ const useInteractables = () => {
201
239
  return clientRef.current.modelContext().register(provider);
202
240
  }, [clientRef, provider]);
203
241
  return {
204
- getState: () => state,
205
- register: useCallback((def_1) => {
206
- try {
207
- const jsonSchema = toJSONSchema(def_1.stateSchema);
208
- partialSchemaCacheRef.current.set(def_1.id, toPartialJSONSchema(jsonSchema));
209
- } catch (e_0) {
210
- console.warn(`[Interactables] Failed to create partial schema for "${def_1.name}". The update tool will require all fields.`, e_0);
242
+ getState: () => stateRef.current,
243
+ register: useCallback((def_2) => {
244
+ const threadAccessor = clientRef.current?.thread;
245
+ const threadMessages = threadAccessor && threadAccessor.source != null ? threadAccessor().getState().messages ?? [] : [];
246
+ const scope = def_2.scope ?? (hasInteractableCreateCall(threadMessages, def_2.id, def_2.name) ? "thread" : "app");
247
+ if (process.env.NODE_ENV !== "production" && stateRef.current.definitions[def_2.id] && scope !== "thread") console.warn(`[Interactables] "${def_2.name}" (${def_2.id}) is already registered. Register an app-scoped interactable once (unstable_useInteractable) and read it from other components with unstable_useInteractableState.`);
248
+ registrationCountsRef.current.set(def_2.id, (registrationCountsRef.current.get(def_2.id) ?? 0) + 1);
249
+ let releaseUpdateToolUI;
250
+ if (def_2.updateRender) {
251
+ const toolsAccessor = clientRef.current?.tools;
252
+ if (toolsAccessor && toolsAccessor.source != null) {
253
+ const toolName = interactableToolName(def_2.name);
254
+ const existing_0 = updateToolUIsRef.current.get(def_2.name);
255
+ if (existing_0) existing_0.count++;
256
+ else updateToolUIsRef.current.set(def_2.name, {
257
+ count: 1,
258
+ unsubscribe: toolsAccessor().setToolUI(toolName, def_2.updateRender, { standalone: true })
259
+ });
260
+ releaseUpdateToolUI = () => {
261
+ const entry_1 = updateToolUIsRef.current.get(def_2.name);
262
+ if (!entry_1) return;
263
+ if (--entry_1.count === 0) {
264
+ updateToolUIsRef.current.delete(def_2.name);
265
+ entry_1.unsubscribe();
266
+ }
267
+ };
268
+ } else if (process.env.NODE_ENV !== "production") console.warn(`[Interactables] "${def_2.name}" supplied an updateRender, but no tools scope is available to install it into.`);
269
+ }
270
+ if (!partialSchemaCacheRef.current.has(def_2.id)) try {
271
+ const jsonSchema = toJSONSchema(def_2.stateSchema);
272
+ partialSchemaCacheRef.current.set(def_2.id, toPartialJSONSchema(jsonSchema));
273
+ } catch (e_1) {
274
+ console.warn(`[Interactables] Failed to create partial schema for "${def_2.name}". The update tool will accept arbitrary fields without validation.`, e_1);
211
275
  }
212
- const detached = detachedStateRef.current.get(def_1.id);
213
- detachedStateRef.current.delete(def_1.id);
214
- setState((prev_5) => ({
215
- ...prev_5,
276
+ const threadId = scope === "thread" ? getCurrentThreadId() : void 0;
277
+ const detached = scope === "thread" ? threadId ? detachedThreadStateRef.current.get(threadId)?.get(def_2.id) : void 0 : detachedAppStateRef.current.get(def_2.id);
278
+ if (scope === "thread") {
279
+ if (threadId) detachedThreadStateRef.current.get(threadId)?.delete(def_2.id);
280
+ } else detachedAppStateRef.current.delete(def_2.id);
281
+ const loaded = scope === "thread" ? void 0 : loadedStateRef.current.get(def_2.id);
282
+ const known = scope === "thread" ? findModelKnownState(threadMessages, def_2.id, def_2.name) : void 0;
283
+ setStateAndRef((prev_4) => ({
284
+ ...prev_4,
216
285
  definitions: {
217
- ...prev_5.definitions,
218
- [def_1.id]: {
219
- id: def_1.id,
220
- name: def_1.name,
221
- description: def_1.description,
222
- stateSchema: def_1.stateSchema,
223
- state: prev_5.definitions[def_1.id]?.state ?? detached ?? def_1.initialState,
224
- selected: def_1.selected
286
+ ...prev_4.definitions,
287
+ [def_2.id]: {
288
+ id: def_2.id,
289
+ name: def_2.name,
290
+ description: def_2.description,
291
+ stateSchema: def_2.stateSchema,
292
+ initialState: def_2.initialState,
293
+ scope,
294
+ state: prev_4.definitions[def_2.id]?.state ?? detached ?? known?.state ?? loaded ?? def_2.initialState
225
295
  }
226
296
  }
227
297
  }));
228
298
  return () => {
299
+ releaseUpdateToolUI?.();
300
+ const remaining = (registrationCountsRef.current.get(def_2.id) ?? 1) - 1;
301
+ if (remaining > 0) {
302
+ registrationCountsRef.current.set(def_2.id, remaining);
303
+ return;
304
+ }
305
+ registrationCountsRef.current.delete(def_2.id);
229
306
  flushIfPending();
230
- setState((prev_6) => {
231
- const existing_1 = prev_6.definitions[def_1.id];
232
- if (existing_1) detachedStateRef.current.set(def_1.id, existing_1.state);
233
- partialSchemaCacheRef.current.delete(def_1.id);
234
- const { [def_1.id]: _, ...rest } = prev_6.definitions;
235
- const { [def_1.id]: __, ...restPersistence } = prev_6.persistence;
307
+ setStateAndRef((prev_5) => {
308
+ const existing_1 = prev_5.definitions[def_2.id];
309
+ if (existing_1) if (existing_1.scope === "thread") {
310
+ const threadId_0 = getCurrentThreadId();
311
+ if (threadId_0) {
312
+ let stateById = detachedThreadStateRef.current.get(threadId_0);
313
+ if (!stateById) {
314
+ stateById = /* @__PURE__ */ new Map();
315
+ detachedThreadStateRef.current.set(threadId_0, stateById);
316
+ }
317
+ stateById.set(def_2.id, existing_1.state);
318
+ }
319
+ } else detachedAppStateRef.current.set(def_2.id, existing_1.state);
320
+ partialSchemaCacheRef.current.delete(def_2.id);
321
+ const { [def_2.id]: _, ...rest } = prev_5.definitions;
322
+ const { [def_2.id]: __, ...restPersistence } = prev_5.persistence;
236
323
  return {
237
- ...prev_6,
324
+ ...prev_5,
238
325
  definitions: rest,
239
326
  persistence: restPersistence
240
327
  };
241
328
  });
242
329
  };
243
- }, [flushIfPending]),
330
+ }, [
331
+ flushIfPending,
332
+ clientRef,
333
+ getCurrentThreadId,
334
+ setStateAndRef
335
+ ]),
244
336
  setState: setDefState,
245
- setSelected: setDefSelected,
246
337
  exportState,
247
338
  importState,
248
339
  setPersistenceAdapter,
249
340
  flush
250
341
  };
251
342
  };
252
- const Interactables = resource(useInteractables);
253
- attachTransformScopes(useInteractables, (scopes, parent) => {
343
+ /**
344
+ * Registers the unstable interactables store scope.
345
+ *
346
+ * @deprecated Unstable / Experimental (not actually removed).
347
+ */
348
+ const unstable_Interactables = resource(useInteractablesResource);
349
+ attachTransformScopes(useInteractablesResource, (scopes, parent) => {
254
350
  if (!scopes.modelContext && parent.modelContext.source === null) scopes.modelContext = ModelContext();
255
351
  });
256
352
  //#endregion
257
- export { Interactables };
353
+ export { unstable_Interactables };
258
354
 
259
355
  //# sourceMappingURL=Interactables.js.map