@assistant-ui/react 0.10.37 → 0.10.39

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 (48) hide show
  1. package/dist/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  2. package/dist/cloud/AssistantCloudThreadHistoryAdapter.js +55 -0
  3. package/dist/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  4. package/dist/runtimes/adapters/index.d.ts +1 -1
  5. package/dist/runtimes/adapters/index.d.ts.map +1 -1
  6. package/dist/runtimes/adapters/index.js +1 -1
  7. package/dist/runtimes/adapters/index.js.map +1 -1
  8. package/dist/runtimes/adapters/thread-history/MessageFormatAdapter.d.ts +21 -0
  9. package/dist/runtimes/adapters/thread-history/MessageFormatAdapter.d.ts.map +1 -0
  10. package/dist/runtimes/adapters/thread-history/MessageFormatAdapter.js +1 -0
  11. package/dist/runtimes/adapters/thread-history/MessageFormatAdapter.js.map +1 -0
  12. package/dist/runtimes/adapters/thread-history/ThreadHistoryAdapter.d.ts +6 -0
  13. package/dist/runtimes/adapters/thread-history/ThreadHistoryAdapter.d.ts.map +1 -1
  14. package/dist/runtimes/adapters/thread-history/index.d.ts +3 -0
  15. package/dist/runtimes/adapters/thread-history/index.d.ts.map +1 -0
  16. package/dist/runtimes/adapters/thread-history/index.js +4 -0
  17. package/dist/runtimes/adapters/thread-history/index.js.map +1 -0
  18. package/dist/runtimes/external-store/ExternalStoreThreadRuntimeCore.js +1 -1
  19. package/dist/runtimes/external-store/ExternalStoreThreadRuntimeCore.js.map +1 -1
  20. package/dist/runtimes/external-store/auto-status.d.ts +4 -1
  21. package/dist/runtimes/external-store/auto-status.d.ts.map +1 -1
  22. package/dist/runtimes/external-store/auto-status.js +5 -1
  23. package/dist/runtimes/external-store/auto-status.js.map +1 -1
  24. package/dist/runtimes/external-store/external-message-converter.d.ts.map +1 -1
  25. package/dist/runtimes/external-store/external-message-converter.js +16 -4
  26. package/dist/runtimes/external-store/external-message-converter.js.map +1 -1
  27. package/dist/runtimes/remote-thread-list/adapter/cloud.d.ts.map +1 -1
  28. package/dist/runtimes/remote-thread-list/adapter/cloud.js +2 -0
  29. package/dist/runtimes/remote-thread-list/adapter/cloud.js.map +1 -1
  30. package/dist/runtimes/remote-thread-list/index.d.ts +1 -0
  31. package/dist/runtimes/remote-thread-list/index.d.ts.map +1 -1
  32. package/dist/runtimes/remote-thread-list/index.js +2 -0
  33. package/dist/runtimes/remote-thread-list/index.js.map +1 -1
  34. package/dist/runtimes/utils/MessageRepository.d.ts.map +1 -1
  35. package/dist/runtimes/utils/MessageRepository.js +5 -1
  36. package/dist/runtimes/utils/MessageRepository.js.map +1 -1
  37. package/package.json +1 -1
  38. package/src/cloud/AssistantCloudThreadHistoryAdapter.tsx +100 -0
  39. package/src/runtimes/adapters/index.ts +1 -1
  40. package/src/runtimes/adapters/thread-history/MessageFormatAdapter.ts +25 -0
  41. package/src/runtimes/adapters/thread-history/ThreadHistoryAdapter.ts +13 -0
  42. package/src/runtimes/adapters/thread-history/index.ts +2 -0
  43. package/src/runtimes/external-store/ExternalStoreThreadRuntimeCore.tsx +1 -1
  44. package/src/runtimes/external-store/auto-status.tsx +15 -2
  45. package/src/runtimes/external-store/external-message-converter.tsx +21 -4
  46. package/src/runtimes/remote-thread-list/adapter/cloud.tsx +2 -0
  47. package/src/runtimes/remote-thread-list/index.ts +1 -0
  48. package/src/runtimes/utils/MessageRepository.tsx +5 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantCloudThreadHistoryAdapter.d.ts","sourceRoot":"","sources":["../../src/cloud/AssistantCloudThreadHistoryAdapter.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAY,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,0DAA0D,CAAC;AAEhG,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAiDjD,eAAO,MAAM,qCAAqC,GAChD,UAAU,SAAS,CAAC,cAAc,CAAC,KAClC,oBAQF,CAAC"}
1
+ {"version":3,"file":"AssistantCloudThreadHistoryAdapter.d.ts","sourceRoot":"","sources":["../../src/cloud/AssistantCloudThreadHistoryAdapter.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAY,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,0DAA0D,CAAC;AAEhG,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAqJjD,eAAO,MAAM,qCAAqC,GAChD,UAAU,SAAS,CAAC,cAAc,CAAC,KAClC,oBAQF,CAAC"}
@@ -2,12 +2,37 @@
2
2
  import { useState } from "react";
3
3
  import { useThreadListItemRuntime } from "../context/index.js";
4
4
  import { auiV0Decode, auiV0Encode } from "./auiV0.js";
5
+ var FormattedThreadHistoryAdapter = class {
6
+ constructor(parent, formatAdapter) {
7
+ this.parent = parent;
8
+ this.formatAdapter = formatAdapter;
9
+ }
10
+ async append(item) {
11
+ const encoded = this.formatAdapter.encode(item);
12
+ const messageId = this.formatAdapter.getId(item.message);
13
+ return this.parent._appendWithFormat(
14
+ item.parentId,
15
+ messageId,
16
+ this.formatAdapter.format,
17
+ encoded
18
+ );
19
+ }
20
+ async load() {
21
+ return this.parent._loadWithFormat(
22
+ this.formatAdapter.format,
23
+ (message) => this.formatAdapter.decode(message)
24
+ );
25
+ }
26
+ };
5
27
  var AssistantCloudThreadHistoryAdapter = class {
6
28
  constructor(cloudRef, threadListItemRuntime) {
7
29
  this.cloudRef = cloudRef;
8
30
  this.threadListItemRuntime = threadListItemRuntime;
9
31
  }
10
32
  _getIdForLocalId = {};
33
+ withFormat(formatAdapter) {
34
+ return new FormattedThreadHistoryAdapter(this, formatAdapter);
35
+ }
11
36
  async append({ parentId, message }) {
12
37
  const { remoteId } = await this.threadListItemRuntime.initialize();
13
38
  const task = this.cloudRef.current.threads.messages.create(remoteId, {
@@ -33,6 +58,36 @@ var AssistantCloudThreadHistoryAdapter = class {
33
58
  };
34
59
  return payload;
35
60
  }
61
+ // Internal methods for FormattedThreadHistoryAdapter
62
+ async _appendWithFormat(parentId, messageId, format, content) {
63
+ const { remoteId } = await this.threadListItemRuntime.initialize();
64
+ const task = this.cloudRef.current.threads.messages.create(remoteId, {
65
+ parent_id: parentId ? await this._getIdForLocalId[parentId] ?? parentId : null,
66
+ format,
67
+ content
68
+ }).then(({ message_id }) => {
69
+ this._getIdForLocalId[messageId] = message_id;
70
+ return message_id;
71
+ });
72
+ this._getIdForLocalId[messageId] = task;
73
+ return task.then(() => {
74
+ });
75
+ }
76
+ async _loadWithFormat(format, decoder) {
77
+ const remoteId = this.threadListItemRuntime.getState().remoteId;
78
+ if (!remoteId) return { messages: [] };
79
+ const { messages } = await this.cloudRef.current.threads.messages.list(remoteId);
80
+ return {
81
+ messages: messages.filter((m) => m.format === format).map(
82
+ (m) => decoder({
83
+ id: m.id,
84
+ parent_id: m.parent_id,
85
+ format: m.format,
86
+ content: m.content
87
+ })
88
+ ).reverse()
89
+ };
90
+ }
36
91
  };
37
92
  var useAssistantCloudThreadHistoryAdapter = (cloudRef) => {
38
93
  const threadListItemRuntime = useThreadListItemRuntime();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cloud/AssistantCloudThreadHistoryAdapter.tsx"],"sourcesContent":["import { RefObject, useState } from \"react\";\nimport { useThreadListItemRuntime } from \"../context\";\nimport { ThreadHistoryAdapter } from \"../runtimes/adapters/thread-history/ThreadHistoryAdapter\";\nimport { ExportedMessageRepositoryItem } from \"../runtimes/utils/MessageRepository\";\nimport { AssistantCloud } from \"assistant-cloud\";\nimport { auiV0Decode, auiV0Encode } from \"./auiV0\";\nimport { ThreadListItemRuntime } from \"../api\";\n\nclass AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {\n constructor(\n private cloudRef: RefObject<AssistantCloud>,\n private threadListItemRuntime: ThreadListItemRuntime,\n ) {}\n\n private _getIdForLocalId: Record<string, string | Promise<string>> = {};\n\n async append({ parentId, message }: ExportedMessageRepositoryItem) {\n const { remoteId } = await this.threadListItemRuntime.initialize();\n const task = this.cloudRef.current.threads.messages\n .create(remoteId, {\n parent_id: parentId\n ? ((await this._getIdForLocalId[parentId]) ?? parentId)\n : null,\n format: \"aui/v0\",\n content: auiV0Encode(message),\n })\n .then(({ message_id }) => {\n this._getIdForLocalId[message.id] = message_id;\n return message_id;\n });\n\n this._getIdForLocalId[message.id] = task;\n\n return task.then(() => {});\n }\n\n async load() {\n const remoteId = this.threadListItemRuntime.getState().remoteId;\n if (!remoteId) return { messages: [] };\n const { messages } =\n await this.cloudRef.current.threads.messages.list(remoteId);\n const payload = {\n messages: messages\n .filter(\n (m): m is typeof m & { format: \"aui/v0\" } => m.format === \"aui/v0\",\n )\n .map(auiV0Decode)\n .reverse(),\n };\n return payload;\n }\n}\n\nexport const useAssistantCloudThreadHistoryAdapter = (\n cloudRef: RefObject<AssistantCloud>,\n): ThreadHistoryAdapter => {\n const threadListItemRuntime = useThreadListItemRuntime();\n const [adapter] = useState(\n () =>\n new AssistantCloudThreadHistoryAdapter(cloudRef, threadListItemRuntime),\n );\n\n return adapter;\n};\n"],"mappings":";AAAA,SAAoB,gBAAgB;AACpC,SAAS,gCAAgC;AAIzC,SAAS,aAAa,mBAAmB;AAGzC,IAAM,qCAAN,MAAyE;AAAA,EACvE,YACU,UACA,uBACR;AAFQ;AACA;AAAA,EACP;AAAA,EAEK,mBAA6D,CAAC;AAAA,EAEtE,MAAM,OAAO,EAAE,UAAU,QAAQ,GAAkC;AACjE,UAAM,EAAE,SAAS,IAAI,MAAM,KAAK,sBAAsB,WAAW;AACjE,UAAM,OAAO,KAAK,SAAS,QAAQ,QAAQ,SACxC,OAAO,UAAU;AAAA,MAChB,WAAW,WACL,MAAM,KAAK,iBAAiB,QAAQ,KAAM,WAC5C;AAAA,MACJ,QAAQ;AAAA,MACR,SAAS,YAAY,OAAO;AAAA,IAC9B,CAAC,EACA,KAAK,CAAC,EAAE,WAAW,MAAM;AACxB,WAAK,iBAAiB,QAAQ,EAAE,IAAI;AACpC,aAAO;AAAA,IACT,CAAC;AAEH,SAAK,iBAAiB,QAAQ,EAAE,IAAI;AAEpC,WAAO,KAAK,KAAK,MAAM;AAAA,IAAC,CAAC;AAAA,EAC3B;AAAA,EAEA,MAAM,OAAO;AACX,UAAM,WAAW,KAAK,sBAAsB,SAAS,EAAE;AACvD,QAAI,CAAC,SAAU,QAAO,EAAE,UAAU,CAAC,EAAE;AACrC,UAAM,EAAE,SAAS,IACf,MAAM,KAAK,SAAS,QAAQ,QAAQ,SAAS,KAAK,QAAQ;AAC5D,UAAM,UAAU;AAAA,MACd,UAAU,SACP;AAAA,QACC,CAAC,MAA4C,EAAE,WAAW;AAAA,MAC5D,EACC,IAAI,WAAW,EACf,QAAQ;AAAA,IACb;AACA,WAAO;AAAA,EACT;AACF;AAEO,IAAM,wCAAwC,CACnD,aACyB;AACzB,QAAM,wBAAwB,yBAAyB;AACvD,QAAM,CAAC,OAAO,IAAI;AAAA,IAChB,MACE,IAAI,mCAAmC,UAAU,qBAAqB;AAAA,EAC1E;AAEA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/cloud/AssistantCloudThreadHistoryAdapter.tsx"],"sourcesContent":["import { RefObject, useState } from \"react\";\nimport { useThreadListItemRuntime } from \"../context\";\nimport { ThreadHistoryAdapter } from \"../runtimes/adapters/thread-history/ThreadHistoryAdapter\";\nimport { ExportedMessageRepositoryItem } from \"../runtimes/utils/MessageRepository\";\nimport { AssistantCloud } from \"assistant-cloud\";\nimport { auiV0Decode, auiV0Encode } from \"./auiV0\";\nimport { ThreadListItemRuntime } from \"../api\";\nimport {\n MessageFormatAdapter,\n MessageFormatItem,\n MessageFormatRepository,\n MessageStorageEntry,\n} from \"../runtimes/adapters/thread-history/MessageFormatAdapter\";\nimport { GenericThreadHistoryAdapter } from \"../runtimes/adapters/thread-history/ThreadHistoryAdapter\";\nimport { ReadonlyJSONObject } from \"assistant-stream/utils\";\n\nclass FormattedThreadHistoryAdapter<TMessage, TStorageFormat>\n implements GenericThreadHistoryAdapter<TMessage>\n{\n constructor(\n private parent: AssistantCloudThreadHistoryAdapter,\n private formatAdapter: MessageFormatAdapter<TMessage, TStorageFormat>,\n ) {}\n\n async append(item: MessageFormatItem<TMessage>) {\n // Encode the message using the format adapter\n const encoded = this.formatAdapter.encode(item);\n const messageId = this.formatAdapter.getId(item.message);\n\n // Delegate to parent's internal append method with the encoded format\n return this.parent._appendWithFormat(\n item.parentId,\n messageId,\n this.formatAdapter.format,\n encoded,\n );\n }\n\n async load(): Promise<MessageFormatRepository<TMessage>> {\n // Delegate to parent's internal load method with format filter\n return this.parent._loadWithFormat(\n this.formatAdapter.format,\n (message: MessageStorageEntry<TStorageFormat>) =>\n this.formatAdapter.decode(message),\n );\n }\n}\n\nclass AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {\n constructor(\n private cloudRef: RefObject<AssistantCloud>,\n private threadListItemRuntime: ThreadListItemRuntime,\n ) {}\n\n private _getIdForLocalId: Record<string, string | Promise<string>> = {};\n\n withFormat<TMessage, TStorageFormat>(\n formatAdapter: MessageFormatAdapter<TMessage, TStorageFormat>,\n ): GenericThreadHistoryAdapter<TMessage> {\n return new FormattedThreadHistoryAdapter(this, formatAdapter);\n }\n\n async append({ parentId, message }: ExportedMessageRepositoryItem) {\n const { remoteId } = await this.threadListItemRuntime.initialize();\n const task = this.cloudRef.current.threads.messages\n .create(remoteId, {\n parent_id: parentId\n ? ((await this._getIdForLocalId[parentId]) ?? parentId)\n : null,\n format: \"aui/v0\",\n content: auiV0Encode(message),\n })\n .then(({ message_id }) => {\n this._getIdForLocalId[message.id] = message_id;\n return message_id;\n });\n\n this._getIdForLocalId[message.id] = task;\n\n return task.then(() => {});\n }\n\n async load() {\n const remoteId = this.threadListItemRuntime.getState().remoteId;\n if (!remoteId) return { messages: [] };\n const { messages } =\n await this.cloudRef.current.threads.messages.list(remoteId);\n const payload = {\n messages: messages\n .filter(\n (m): m is typeof m & { format: \"aui/v0\" } => m.format === \"aui/v0\",\n )\n .map(auiV0Decode)\n .reverse(),\n };\n return payload;\n }\n\n // Internal methods for FormattedThreadHistoryAdapter\n async _appendWithFormat<T>(\n parentId: string | null,\n messageId: string,\n format: string,\n content: T,\n ) {\n const { remoteId } = await this.threadListItemRuntime.initialize();\n\n const task = this.cloudRef.current.threads.messages\n .create(remoteId, {\n parent_id: parentId\n ? ((await this._getIdForLocalId[parentId]) ?? parentId)\n : null,\n format,\n content: content as ReadonlyJSONObject,\n })\n .then(({ message_id }) => {\n this._getIdForLocalId[messageId] = message_id;\n return message_id;\n });\n\n this._getIdForLocalId[messageId] = task;\n\n return task.then(() => {});\n }\n\n async _loadWithFormat<TMessage, TStorageFormat>(\n format: string,\n decoder: (\n message: MessageStorageEntry<TStorageFormat>,\n ) => MessageFormatItem<TMessage>,\n ): Promise<MessageFormatRepository<TMessage>> {\n const remoteId = this.threadListItemRuntime.getState().remoteId;\n if (!remoteId) return { messages: [] };\n\n const { messages } =\n await this.cloudRef.current.threads.messages.list(remoteId);\n\n return {\n messages: messages\n .filter((m) => m.format === format)\n .map((m) =>\n decoder({\n id: m.id,\n parent_id: m.parent_id,\n format: m.format,\n content: m.content as TStorageFormat,\n }),\n )\n .reverse(),\n };\n }\n}\n\nexport const useAssistantCloudThreadHistoryAdapter = (\n cloudRef: RefObject<AssistantCloud>,\n): ThreadHistoryAdapter => {\n const threadListItemRuntime = useThreadListItemRuntime();\n const [adapter] = useState(\n () =>\n new AssistantCloudThreadHistoryAdapter(cloudRef, threadListItemRuntime),\n );\n\n return adapter;\n};\n"],"mappings":"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","names":[]}
@@ -3,5 +3,5 @@ export * from "./feedback";
3
3
  export * from "./speech";
4
4
  export * from "./suggestion";
5
5
  export * from "./RuntimeAdapterProvider";
6
- export * from "./thread-history/ThreadHistoryAdapter";
6
+ export * from "./thread-history";
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtimes/adapters/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,0BAA0B,CAAC;AACzC,cAAc,uCAAuC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtimes/adapters/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC"}
@@ -4,5 +4,5 @@ export * from "./feedback/index.js";
4
4
  export * from "./speech/index.js";
5
5
  export * from "./suggestion/index.js";
6
6
  export * from "./RuntimeAdapterProvider.js";
7
- export * from "./thread-history/ThreadHistoryAdapter.js";
7
+ export * from "./thread-history/index.js";
8
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/runtimes/adapters/index.ts"],"sourcesContent":["export * from \"./attachment\";\nexport * from \"./feedback\";\nexport * from \"./speech\";\nexport * from \"./suggestion\";\nexport * from \"./RuntimeAdapterProvider\";\nexport * from \"./thread-history/ThreadHistoryAdapter\";\n"],"mappings":";AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
1
+ {"version":3,"sources":["../../../src/runtimes/adapters/index.ts"],"sourcesContent":["export * from \"./attachment\";\nexport * from \"./feedback\";\nexport * from \"./speech\";\nexport * from \"./suggestion\";\nexport * from \"./RuntimeAdapterProvider\";\nexport * from \"./thread-history\";\n"],"mappings":";AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
@@ -0,0 +1,21 @@
1
+ export interface MessageStorageEntry<TPayload> {
2
+ id: string;
3
+ parent_id: string | null;
4
+ format: string;
5
+ content: TPayload;
6
+ }
7
+ export interface MessageFormatItem<TMessage> {
8
+ parentId: string | null;
9
+ message: TMessage;
10
+ }
11
+ export interface MessageFormatRepository<TMessage> {
12
+ headId?: string | null;
13
+ messages: MessageFormatItem<TMessage>[];
14
+ }
15
+ export interface MessageFormatAdapter<TMessage, TStorageFormat> {
16
+ format: string;
17
+ encode(item: MessageFormatItem<TMessage>): TStorageFormat;
18
+ decode(stored: MessageStorageEntry<TStorageFormat>): MessageFormatItem<TMessage>;
19
+ getId(message: TMessage): string;
20
+ }
21
+ //# sourceMappingURL=MessageFormatAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageFormatAdapter.d.ts","sourceRoot":"","sources":["../../../../src/runtimes/adapters/thread-history/MessageFormatAdapter.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB,CAAC,QAAQ;IAC3C,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,QAAQ,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB,CAAC,QAAQ;IACzC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,QAAQ,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB,CAAC,QAAQ;IAC/C,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,oBAAoB,CAAC,QAAQ,EAAE,cAAc;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,GAAG,cAAc,CAAC;IAC1D,MAAM,CACJ,MAAM,EAAE,mBAAmB,CAAC,cAAc,CAAC,GAC1C,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC/B,KAAK,CAAC,OAAO,EAAE,QAAQ,GAAG,MAAM,CAAC;CAClC"}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=MessageFormatAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,10 +1,16 @@
1
1
  import { ChatModelRunOptions, ChatModelRunResult } from "../../local";
2
2
  import { ExportedMessageRepository, ExportedMessageRepositoryItem } from "../../utils/MessageRepository";
3
+ import { MessageFormatAdapter, MessageFormatItem, MessageFormatRepository } from "./MessageFormatAdapter";
4
+ export type GenericThreadHistoryAdapter<TMessage> = {
5
+ load(): Promise<MessageFormatRepository<TMessage>>;
6
+ append(item: MessageFormatItem<TMessage>): Promise<void>;
7
+ };
3
8
  export type ThreadHistoryAdapter = {
4
9
  load(): Promise<ExportedMessageRepository & {
5
10
  unstable_resume?: boolean;
6
11
  }>;
7
12
  resume?(options: ChatModelRunOptions): AsyncGenerator<ChatModelRunResult, void, unknown>;
8
13
  append(item: ExportedMessageRepositoryItem): Promise<void>;
14
+ withFormat?<TMessage, TStorageFormat>(formatAdapter: MessageFormatAdapter<TMessage, TStorageFormat>): GenericThreadHistoryAdapter<TMessage>;
9
15
  };
10
16
  //# sourceMappingURL=ThreadHistoryAdapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ThreadHistoryAdapter.d.ts","sourceRoot":"","sources":["../../../../src/runtimes/adapters/thread-history/ThreadHistoryAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC9B,MAAM,+BAA+B,CAAC;AAEvC,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,IAAI,OAAO,CAAC,yBAAyB,GAAG;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC3E,MAAM,CAAC,CACL,OAAO,EAAE,mBAAmB,GAC3B,cAAc,CAAC,kBAAkB,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACrD,MAAM,CAAC,IAAI,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D,CAAC"}
1
+ {"version":3,"file":"ThreadHistoryAdapter.d.ts","sourceRoot":"","sources":["../../../../src/runtimes/adapters/thread-history/ThreadHistoryAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC9B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,uBAAuB,EACxB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,MAAM,2BAA2B,CAAC,QAAQ,IAAI;IAClD,IAAI,IAAI,OAAO,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnD,MAAM,CAAC,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,IAAI,OAAO,CAAC,yBAAyB,GAAG;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC3E,MAAM,CAAC,CACL,OAAO,EAAE,mBAAmB,GAC3B,cAAc,CAAC,kBAAkB,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACrD,MAAM,CAAC,IAAI,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,UAAU,CAAC,CAAC,QAAQ,EAAE,cAAc,EAClC,aAAa,EAAE,oBAAoB,CAAC,QAAQ,EAAE,cAAc,CAAC,GAC5D,2BAA2B,CAAC,QAAQ,CAAC,CAAC;CAC1C,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from "./MessageFormatAdapter";
2
+ export * from "./ThreadHistoryAdapter";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/runtimes/adapters/thread-history/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC"}
@@ -0,0 +1,4 @@
1
+ // src/runtimes/adapters/thread-history/index.ts
2
+ export * from "./MessageFormatAdapter.js";
3
+ export * from "./ThreadHistoryAdapter.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/runtimes/adapters/thread-history/index.ts"],"sourcesContent":["export * from \"./MessageFormatAdapter\";\nexport * from \"./ThreadHistoryAdapter\";\n"],"mappings":";AAAA,cAAc;AACd,cAAc;","names":[]}
@@ -92,7 +92,7 @@ var ExternalStoreThreadRuntimeCore = class extends BaseThreadRuntimeCore {
92
92
  messages = !store.convertMessage ? store.messages : this._converter.convertMessages(store.messages, (cache, m, idx) => {
93
93
  if (!store.convertMessage) return m;
94
94
  const isLast = idx === store.messages.length - 1;
95
- const autoStatus = getAutoStatus(isLast, isRunning);
95
+ const autoStatus = getAutoStatus(isLast, isRunning, false);
96
96
  if (cache && (cache.role !== "assistant" || !isAutoStatus(cache.status) || cache.status === autoStatus))
97
97
  return cache;
98
98
  const messageLike = store.convertMessage(m, idx);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/runtimes/external-store/ExternalStoreThreadRuntimeCore.tsx"],"sourcesContent":["import {\n AddToolResultOptions,\n StartRunConfig,\n ThreadSuggestion,\n} from \"../core/ThreadRuntimeCore\";\n\nimport { AppendMessage, ThreadMessage } from \"../../types\";\nimport { ExternalStoreAdapter } from \"./ExternalStoreAdapter\";\nimport {\n getExternalStoreMessage,\n symbolInnerMessage,\n} from \"./getExternalStoreMessage\";\nimport { ThreadMessageConverter } from \"./ThreadMessageConverter\";\nimport { getAutoStatus, isAutoStatus } from \"./auto-status\";\nimport { fromThreadMessageLike } from \"./ThreadMessageLike\";\nimport { getThreadMessageText } from \"../../utils/getThreadMessageText\";\nimport {\n RuntimeCapabilities,\n ThreadRuntimeCore,\n} from \"../core/ThreadRuntimeCore\";\nimport { BaseThreadRuntimeCore } from \"../core/BaseThreadRuntimeCore\";\nimport { ModelContextProvider } from \"../../model-context\";\n\nconst EMPTY_ARRAY = Object.freeze([]);\n\nexport const hasUpcomingMessage = (\n isRunning: boolean,\n messages: readonly ThreadMessage[],\n) => {\n return isRunning && messages[messages.length - 1]?.role !== \"assistant\";\n};\n\nexport class ExternalStoreThreadRuntimeCore\n extends BaseThreadRuntimeCore\n implements ThreadRuntimeCore\n{\n private assistantOptimisticId: string | null = null;\n\n private _capabilities: RuntimeCapabilities = {\n switchToBranch: false,\n edit: false,\n reload: false,\n cancel: false,\n unstable_copy: false,\n speech: false,\n attachments: false,\n feedback: false,\n };\n\n public get capabilities() {\n return this._capabilities;\n }\n\n private _messages!: readonly ThreadMessage[];\n public isDisabled!: boolean;\n public get isLoading() {\n return this._store.isLoading ?? false;\n }\n\n public override get messages() {\n return this._messages;\n }\n\n public get adapters() {\n return this._store.adapters;\n }\n\n public suggestions: readonly ThreadSuggestion[] = [];\n public extras: unknown = undefined;\n\n private _converter = new ThreadMessageConverter();\n\n private _store!: ExternalStoreAdapter<any>;\n\n public override beginEdit(messageId: string) {\n if (!this._store.onEdit)\n throw new Error(\"Runtime does not support editing.\");\n\n super.beginEdit(messageId);\n }\n\n constructor(\n contextProvider: ModelContextProvider,\n store: ExternalStoreAdapter<any>,\n ) {\n super(contextProvider);\n this.__internal_setAdapter(store);\n }\n\n public __internal_setAdapter(store: ExternalStoreAdapter<any>) {\n if (this._store === store) return;\n\n const isRunning = store.isRunning ?? false;\n this.isDisabled = store.isDisabled ?? false;\n\n const oldStore = this._store as ExternalStoreAdapter<any> | undefined;\n this._store = store;\n this.extras = store.extras;\n this.suggestions = store.suggestions ?? EMPTY_ARRAY;\n this._capabilities = {\n switchToBranch: this._store.setMessages !== undefined,\n edit: this._store.onEdit !== undefined,\n reload: this._store.onReload !== undefined,\n cancel: this._store.onCancel !== undefined,\n speech: this._store.adapters?.speech !== undefined,\n unstable_copy: this._store.unstable_capabilities?.copy !== false, // default true\n attachments: !!this._store.adapters?.attachments,\n feedback: !!this._store.adapters?.feedback,\n };\n\n let messages: readonly ThreadMessage[];\n\n if (store.messageRepository) {\n // Handle messageRepository\n if (\n oldStore &&\n oldStore.isRunning === store.isRunning &&\n oldStore.messageRepository === store.messageRepository\n ) {\n this._notifySubscribers();\n return;\n }\n\n // Clear and import the message repository\n this.repository.clear();\n this.assistantOptimisticId = null;\n this.repository.import(store.messageRepository);\n\n messages = this.repository.getMessages();\n } else if (store.messages) {\n // Handle messages array\n\n if (oldStore) {\n // flush the converter cache when the convertMessage prop changes\n if (oldStore.convertMessage !== store.convertMessage) {\n this._converter = new ThreadMessageConverter();\n } else if (\n oldStore.isRunning === store.isRunning &&\n oldStore.messages === store.messages\n ) {\n this._notifySubscribers();\n // no conversion update\n return;\n }\n }\n\n messages = !store.convertMessage\n ? store.messages\n : this._converter.convertMessages(store.messages, (cache, m, idx) => {\n if (!store.convertMessage) return m;\n\n const isLast = idx === store.messages!.length - 1;\n const autoStatus = getAutoStatus(isLast, isRunning);\n\n if (\n cache &&\n (cache.role !== \"assistant\" ||\n !isAutoStatus(cache.status) ||\n cache.status === autoStatus)\n )\n return cache;\n\n const messageLike = store.convertMessage(m, idx);\n const newMessage = fromThreadMessageLike(\n messageLike,\n idx.toString(),\n autoStatus,\n );\n (newMessage as any)[symbolInnerMessage] = m;\n return newMessage;\n });\n\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i]!;\n const parent = messages[i - 1];\n this.repository.addOrUpdateMessage(parent?.id ?? null, message);\n }\n } else {\n throw new Error(\n \"ExternalStoreAdapter must provide either 'messages' or 'messageRepository'\",\n );\n }\n\n // Common logic for both paths\n if (messages.length > 0) this.ensureInitialized();\n\n if ((oldStore?.isRunning ?? false) !== (store.isRunning ?? false)) {\n if (store.isRunning) {\n this._notifyEventSubscribers(\"run-start\");\n } else {\n this._notifyEventSubscribers(\"run-end\");\n }\n }\n\n if (this.assistantOptimisticId) {\n this.repository.deleteMessage(this.assistantOptimisticId);\n this.assistantOptimisticId = null;\n }\n\n if (hasUpcomingMessage(isRunning, messages)) {\n this.assistantOptimisticId = this.repository.appendOptimisticMessage(\n messages.at(-1)?.id ?? null,\n {\n role: \"assistant\",\n content: [],\n },\n );\n }\n\n this.repository.resetHead(\n this.assistantOptimisticId ?? messages.at(-1)?.id ?? null,\n );\n\n this._messages = this.repository.getMessages();\n this._notifySubscribers();\n }\n\n public override switchToBranch(branchId: string): void {\n if (!this._store.setMessages)\n throw new Error(\"Runtime does not support switching branches.\");\n\n this.repository.switchToBranch(branchId);\n this.updateMessages(this.repository.getMessages());\n }\n\n public async append(message: AppendMessage): Promise<void> {\n if (message.parentId !== (this.messages.at(-1)?.id ?? null)) {\n if (!this._store.onEdit)\n throw new Error(\"Runtime does not support editing messages.\");\n await this._store.onEdit(message);\n } else {\n await this._store.onNew(message);\n }\n }\n\n public async startRun(config: StartRunConfig): Promise<void> {\n if (!this._store.onReload)\n throw new Error(\"Runtime does not support reloading messages.\");\n\n await this._store.onReload(config.parentId, config);\n }\n\n public async resumeRun(): Promise<void> {\n throw new Error(\"Runtime does not support resuming runs.\");\n }\n\n public cancelRun(): void {\n if (!this._store.onCancel)\n throw new Error(\"Runtime does not support cancelling runs.\");\n\n this._store.onCancel();\n\n if (this.assistantOptimisticId) {\n this.repository.deleteMessage(this.assistantOptimisticId);\n this.assistantOptimisticId = null;\n }\n\n let messages = this.repository.getMessages();\n const previousMessage = messages[messages.length - 1];\n if (\n previousMessage?.role === \"user\" &&\n previousMessage.id === messages.at(-1)?.id // ensure the previous message is a leaf node\n ) {\n this.repository.deleteMessage(previousMessage.id);\n if (!this.composer.text.trim()) {\n this.composer.setText(getThreadMessageText(previousMessage));\n }\n\n messages = this.repository.getMessages();\n } else {\n this._notifySubscribers();\n }\n\n // resync messages (for reloading, to restore the previous branch)\n setTimeout(() => {\n this.updateMessages(messages);\n }, 0);\n }\n\n public addToolResult(options: AddToolResultOptions) {\n if (!this._store.onAddToolResult && !this._store.onAddToolResult)\n throw new Error(\"Runtime does not support tool results.\");\n this._store.onAddToolResult?.(options);\n }\n\n private updateMessages = (messages: readonly ThreadMessage[]) => {\n const hasConverter = this._store.convertMessage !== undefined;\n if (hasConverter) {\n this._store.setMessages?.(\n messages.flatMap(getExternalStoreMessage).filter((m) => m != null),\n );\n } else {\n // TODO mark this as readonly in v0.8.0\n this._store.setMessages?.(messages as ThreadMessage[]);\n }\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/runtimes/external-store/ExternalStoreThreadRuntimeCore.tsx"],"sourcesContent":["import {\n AddToolResultOptions,\n StartRunConfig,\n ThreadSuggestion,\n} from \"../core/ThreadRuntimeCore\";\n\nimport { AppendMessage, ThreadMessage } from \"../../types\";\nimport { ExternalStoreAdapter } from \"./ExternalStoreAdapter\";\nimport {\n getExternalStoreMessage,\n symbolInnerMessage,\n} from \"./getExternalStoreMessage\";\nimport { ThreadMessageConverter } from \"./ThreadMessageConverter\";\nimport { getAutoStatus, isAutoStatus } from \"./auto-status\";\nimport { fromThreadMessageLike } from \"./ThreadMessageLike\";\nimport { getThreadMessageText } from \"../../utils/getThreadMessageText\";\nimport {\n RuntimeCapabilities,\n ThreadRuntimeCore,\n} from \"../core/ThreadRuntimeCore\";\nimport { BaseThreadRuntimeCore } from \"../core/BaseThreadRuntimeCore\";\nimport { ModelContextProvider } from \"../../model-context\";\n\nconst EMPTY_ARRAY = Object.freeze([]);\n\nexport const hasUpcomingMessage = (\n isRunning: boolean,\n messages: readonly ThreadMessage[],\n) => {\n return isRunning && messages[messages.length - 1]?.role !== \"assistant\";\n};\n\nexport class ExternalStoreThreadRuntimeCore\n extends BaseThreadRuntimeCore\n implements ThreadRuntimeCore\n{\n private assistantOptimisticId: string | null = null;\n\n private _capabilities: RuntimeCapabilities = {\n switchToBranch: false,\n edit: false,\n reload: false,\n cancel: false,\n unstable_copy: false,\n speech: false,\n attachments: false,\n feedback: false,\n };\n\n public get capabilities() {\n return this._capabilities;\n }\n\n private _messages!: readonly ThreadMessage[];\n public isDisabled!: boolean;\n public get isLoading() {\n return this._store.isLoading ?? false;\n }\n\n public override get messages() {\n return this._messages;\n }\n\n public get adapters() {\n return this._store.adapters;\n }\n\n public suggestions: readonly ThreadSuggestion[] = [];\n public extras: unknown = undefined;\n\n private _converter = new ThreadMessageConverter();\n\n private _store!: ExternalStoreAdapter<any>;\n\n public override beginEdit(messageId: string) {\n if (!this._store.onEdit)\n throw new Error(\"Runtime does not support editing.\");\n\n super.beginEdit(messageId);\n }\n\n constructor(\n contextProvider: ModelContextProvider,\n store: ExternalStoreAdapter<any>,\n ) {\n super(contextProvider);\n this.__internal_setAdapter(store);\n }\n\n public __internal_setAdapter(store: ExternalStoreAdapter<any>) {\n if (this._store === store) return;\n\n const isRunning = store.isRunning ?? false;\n this.isDisabled = store.isDisabled ?? false;\n\n const oldStore = this._store as ExternalStoreAdapter<any> | undefined;\n this._store = store;\n this.extras = store.extras;\n this.suggestions = store.suggestions ?? EMPTY_ARRAY;\n this._capabilities = {\n switchToBranch: this._store.setMessages !== undefined,\n edit: this._store.onEdit !== undefined,\n reload: this._store.onReload !== undefined,\n cancel: this._store.onCancel !== undefined,\n speech: this._store.adapters?.speech !== undefined,\n unstable_copy: this._store.unstable_capabilities?.copy !== false, // default true\n attachments: !!this._store.adapters?.attachments,\n feedback: !!this._store.adapters?.feedback,\n };\n\n let messages: readonly ThreadMessage[];\n\n if (store.messageRepository) {\n // Handle messageRepository\n if (\n oldStore &&\n oldStore.isRunning === store.isRunning &&\n oldStore.messageRepository === store.messageRepository\n ) {\n this._notifySubscribers();\n return;\n }\n\n // Clear and import the message repository\n this.repository.clear();\n this.assistantOptimisticId = null;\n this.repository.import(store.messageRepository);\n\n messages = this.repository.getMessages();\n } else if (store.messages) {\n // Handle messages array\n\n if (oldStore) {\n // flush the converter cache when the convertMessage prop changes\n if (oldStore.convertMessage !== store.convertMessage) {\n this._converter = new ThreadMessageConverter();\n } else if (\n oldStore.isRunning === store.isRunning &&\n oldStore.messages === store.messages\n ) {\n this._notifySubscribers();\n // no conversion update\n return;\n }\n }\n\n messages = !store.convertMessage\n ? store.messages\n : this._converter.convertMessages(store.messages, (cache, m, idx) => {\n if (!store.convertMessage) return m;\n\n const isLast = idx === store.messages!.length - 1;\n const autoStatus = getAutoStatus(isLast, isRunning, false);\n\n if (\n cache &&\n (cache.role !== \"assistant\" ||\n !isAutoStatus(cache.status) ||\n cache.status === autoStatus)\n )\n return cache;\n\n const messageLike = store.convertMessage(m, idx);\n const newMessage = fromThreadMessageLike(\n messageLike,\n idx.toString(),\n autoStatus,\n );\n (newMessage as any)[symbolInnerMessage] = m;\n return newMessage;\n });\n\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i]!;\n const parent = messages[i - 1];\n this.repository.addOrUpdateMessage(parent?.id ?? null, message);\n }\n } else {\n throw new Error(\n \"ExternalStoreAdapter must provide either 'messages' or 'messageRepository'\",\n );\n }\n\n // Common logic for both paths\n if (messages.length > 0) this.ensureInitialized();\n\n if ((oldStore?.isRunning ?? false) !== (store.isRunning ?? false)) {\n if (store.isRunning) {\n this._notifyEventSubscribers(\"run-start\");\n } else {\n this._notifyEventSubscribers(\"run-end\");\n }\n }\n\n if (this.assistantOptimisticId) {\n this.repository.deleteMessage(this.assistantOptimisticId);\n this.assistantOptimisticId = null;\n }\n\n if (hasUpcomingMessage(isRunning, messages)) {\n this.assistantOptimisticId = this.repository.appendOptimisticMessage(\n messages.at(-1)?.id ?? null,\n {\n role: \"assistant\",\n content: [],\n },\n );\n }\n\n this.repository.resetHead(\n this.assistantOptimisticId ?? messages.at(-1)?.id ?? null,\n );\n\n this._messages = this.repository.getMessages();\n this._notifySubscribers();\n }\n\n public override switchToBranch(branchId: string): void {\n if (!this._store.setMessages)\n throw new Error(\"Runtime does not support switching branches.\");\n\n this.repository.switchToBranch(branchId);\n this.updateMessages(this.repository.getMessages());\n }\n\n public async append(message: AppendMessage): Promise<void> {\n if (message.parentId !== (this.messages.at(-1)?.id ?? null)) {\n if (!this._store.onEdit)\n throw new Error(\"Runtime does not support editing messages.\");\n await this._store.onEdit(message);\n } else {\n await this._store.onNew(message);\n }\n }\n\n public async startRun(config: StartRunConfig): Promise<void> {\n if (!this._store.onReload)\n throw new Error(\"Runtime does not support reloading messages.\");\n\n await this._store.onReload(config.parentId, config);\n }\n\n public async resumeRun(): Promise<void> {\n throw new Error(\"Runtime does not support resuming runs.\");\n }\n\n public cancelRun(): void {\n if (!this._store.onCancel)\n throw new Error(\"Runtime does not support cancelling runs.\");\n\n this._store.onCancel();\n\n if (this.assistantOptimisticId) {\n this.repository.deleteMessage(this.assistantOptimisticId);\n this.assistantOptimisticId = null;\n }\n\n let messages = this.repository.getMessages();\n const previousMessage = messages[messages.length - 1];\n if (\n previousMessage?.role === \"user\" &&\n previousMessage.id === messages.at(-1)?.id // ensure the previous message is a leaf node\n ) {\n this.repository.deleteMessage(previousMessage.id);\n if (!this.composer.text.trim()) {\n this.composer.setText(getThreadMessageText(previousMessage));\n }\n\n messages = this.repository.getMessages();\n } else {\n this._notifySubscribers();\n }\n\n // resync messages (for reloading, to restore the previous branch)\n setTimeout(() => {\n this.updateMessages(messages);\n }, 0);\n }\n\n public addToolResult(options: AddToolResultOptions) {\n if (!this._store.onAddToolResult && !this._store.onAddToolResult)\n throw new Error(\"Runtime does not support tool results.\");\n this._store.onAddToolResult?.(options);\n }\n\n private updateMessages = (messages: readonly ThreadMessage[]) => {\n const hasConverter = this._store.convertMessage !== undefined;\n if (hasConverter) {\n this._store.setMessages?.(\n messages.flatMap(getExternalStoreMessage).filter((m) => m != null),\n );\n } else {\n // TODO mark this as readonly in v0.8.0\n this._store.setMessages?.(messages as ThreadMessage[]);\n }\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,9 +1,12 @@
1
1
  import { MessageStatus } from "../../types";
2
2
  export declare const isAutoStatus: (status: MessageStatus) => boolean;
3
- export declare const getAutoStatus: (isLast: boolean, isRunning: boolean) => Readonly<{
3
+ export declare const getAutoStatus: (isLast: boolean, isRunning: boolean, hasPendingToolCalls: boolean) => Readonly<{
4
4
  type: "running";
5
5
  }> | Readonly<{
6
6
  type: "complete";
7
7
  reason: "unknown";
8
+ }> | Readonly<{
9
+ type: "requires-action";
10
+ reason: "tool-calls";
8
11
  }>;
9
12
  //# sourceMappingURL=auto-status.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auto-status.d.ts","sourceRoot":"","sources":["../../../src/runtimes/external-store/auto-status.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAQ5C,eAAO,MAAM,YAAY,GAAI,QAAQ,aAAa,YACiB,CAAC;AAEpE,eAAO,MAAM,aAAa,GAAI,QAAQ,OAAO,EAAE,WAAW,OAAO;;;;;EACC,CAAC"}
1
+ {"version":3,"file":"auto-status.d.ts","sourceRoot":"","sources":["../../../src/runtimes/external-store/auto-status.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAa5C,eAAO,MAAM,YAAY,GAAI,QAAQ,aAAa,YACiB,CAAC;AAEpE,eAAO,MAAM,aAAa,GACxB,QAAQ,OAAO,EACf,WAAW,OAAO,EAClB,qBAAqB,OAAO;;;;;;;;EAMF,CAAC"}
@@ -4,8 +4,12 @@ var AUTO_STATUS_COMPLETE = Object.freeze({
4
4
  type: "complete",
5
5
  reason: "unknown"
6
6
  });
7
+ var AUTO_STATUS_PENDING = Object.freeze({
8
+ type: "requires-action",
9
+ reason: "tool-calls"
10
+ });
7
11
  var isAutoStatus = (status) => status === AUTO_STATUS_RUNNING || status === AUTO_STATUS_COMPLETE;
8
- var getAutoStatus = (isLast, isRunning) => isLast && isRunning ? AUTO_STATUS_RUNNING : AUTO_STATUS_COMPLETE;
12
+ var getAutoStatus = (isLast, isRunning, hasPendingToolCalls) => isLast && isRunning ? AUTO_STATUS_RUNNING : hasPendingToolCalls ? AUTO_STATUS_PENDING : AUTO_STATUS_COMPLETE;
9
13
  export {
10
14
  getAutoStatus,
11
15
  isAutoStatus
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/runtimes/external-store/auto-status.tsx"],"sourcesContent":["import { MessageStatus } from \"../../types\";\n\nconst AUTO_STATUS_RUNNING = Object.freeze({ type: \"running\" });\nconst AUTO_STATUS_COMPLETE = Object.freeze({\n type: \"complete\",\n reason: \"unknown\",\n});\n\nexport const isAutoStatus = (status: MessageStatus) =>\n status === AUTO_STATUS_RUNNING || status === AUTO_STATUS_COMPLETE;\n\nexport const getAutoStatus = (isLast: boolean, isRunning: boolean) =>\n isLast && isRunning ? AUTO_STATUS_RUNNING : AUTO_STATUS_COMPLETE;\n"],"mappings":";AAEA,IAAM,sBAAsB,OAAO,OAAO,EAAE,MAAM,UAAU,CAAC;AAC7D,IAAM,uBAAuB,OAAO,OAAO;AAAA,EACzC,MAAM;AAAA,EACN,QAAQ;AACV,CAAC;AAEM,IAAM,eAAe,CAAC,WAC3B,WAAW,uBAAuB,WAAW;AAExC,IAAM,gBAAgB,CAAC,QAAiB,cAC7C,UAAU,YAAY,sBAAsB;","names":[]}
1
+ {"version":3,"sources":["../../../src/runtimes/external-store/auto-status.tsx"],"sourcesContent":["import { MessageStatus } from \"../../types\";\n\nconst AUTO_STATUS_RUNNING = Object.freeze({ type: \"running\" });\nconst AUTO_STATUS_COMPLETE = Object.freeze({\n type: \"complete\",\n reason: \"unknown\",\n});\n\nconst AUTO_STATUS_PENDING = Object.freeze({\n type: \"requires-action\",\n reason: \"tool-calls\",\n});\n\nexport const isAutoStatus = (status: MessageStatus) =>\n status === AUTO_STATUS_RUNNING || status === AUTO_STATUS_COMPLETE;\n\nexport const getAutoStatus = (\n isLast: boolean,\n isRunning: boolean,\n hasPendingToolCalls: boolean,\n) =>\n isLast && isRunning\n ? AUTO_STATUS_RUNNING\n : hasPendingToolCalls\n ? AUTO_STATUS_PENDING\n : AUTO_STATUS_COMPLETE;\n"],"mappings":";AAEA,IAAM,sBAAsB,OAAO,OAAO,EAAE,MAAM,UAAU,CAAC;AAC7D,IAAM,uBAAuB,OAAO,OAAO;AAAA,EACzC,MAAM;AAAA,EACN,QAAQ;AACV,CAAC;AAED,IAAM,sBAAsB,OAAO,OAAO;AAAA,EACxC,MAAM;AAAA,EACN,QAAQ;AACV,CAAC;AAEM,IAAM,eAAe,CAAC,WAC3B,WAAW,uBAAuB,WAAW;AAExC,IAAM,gBAAgB,CAC3B,QACA,WACA,wBAEA,UAAU,YACN,sBACA,sBACE,sBACA;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"external-message-converter.d.ts","sourceRoot":"","sources":["../../../src/runtimes/external-store/external-message-converter.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAyB,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAI/E,yBAAiB,2BAA2B,CAAC;IAC3C,KAAY,OAAO,GACf,CAAC,iBAAiB,GAAG;QACnB,QAAQ,CAAC,aAAa,CAAC,EAAE;YACvB,QAAQ,CAAC,YAAY,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAAC;SACnD,CAAC;KACH,CAAC,GACF;QACE,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,MAAM,EAAE,GAAG,CAAC;QACZ,QAAQ,CAAC,EAAE,GAAG,CAAC;QACf,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;IAEN,KAAY,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,OAAO,GAAG,OAAO,EAAE,CAAC;CAC/D;AA2LD,eAAO,MAAM,uBAAuB,GAAI,CAAC,SAAS,OAAO,EACvD,UAAU,CAAC,EAAE,EACb,UAAU,2BAA2B,CAAC,QAAQ,CAAC,CAAC,CAAC,EACjD,WAAW,OAAO,oCAuBnB,CAAC;AAEF,eAAO,MAAM,2BAA2B,GAAI,CAAC,SAAS,OAAO,EAAE,kDAK5D;IACD,QAAQ,EAAE,2BAA2B,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAClD,QAAQ,EAAE,CAAC,EAAE,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,gBAAgB,GAAG,MAAM,GAAG,SAAS,CAAC;CACtD,oCA0EA,CAAC"}
1
+ {"version":3,"file":"external-message-converter.d.ts","sourceRoot":"","sources":["../../../src/runtimes/external-store/external-message-converter.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAyB,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAI/E,yBAAiB,2BAA2B,CAAC;IAC3C,KAAY,OAAO,GACf,CAAC,iBAAiB,GAAG;QACnB,QAAQ,CAAC,aAAa,CAAC,EAAE;YACvB,QAAQ,CAAC,YAAY,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAAC;SACnD,CAAC;KACH,CAAC,GACF;QACE,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,MAAM,EAAE,GAAG,CAAC;QACZ,QAAQ,CAAC,EAAE,GAAG,CAAC;QACf,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;IAEN,KAAY,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,OAAO,GAAG,OAAO,EAAE,CAAC;CAC/D;AA2LD,eAAO,MAAM,uBAAuB,GAAI,CAAC,SAAS,OAAO,EACvD,UAAU,CAAC,EAAE,EACb,UAAU,2BAA2B,CAAC,QAAQ,CAAC,CAAC,CAAC,EACjD,WAAW,OAAO,oCA6BnB,CAAC;AAEF,eAAO,MAAM,2BAA2B,GAAI,CAAC,SAAS,OAAO,EAAE,kDAK5D;IACD,QAAQ,EAAE,2BAA2B,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAClD,QAAQ,EAAE,CAAC,EAAE,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,gBAAgB,GAAG,MAAM,GAAG,SAAS,CAAC;CACtD,oCAqFA,CAAC"}
@@ -157,9 +157,13 @@ var convertExternalMessages = (messages, callback, isRunning) => {
157
157
  const chunks = chunkExternalMessages(callbackResults);
158
158
  return chunks.map((message, idx) => {
159
159
  const isLast = idx === chunks.length - 1;
160
- const autoStatus = getAutoStatus(isLast, isRunning);
160
+ const joined = joinExternalMessages(message.outputs);
161
+ const hasPendingToolCalls = typeof joined.content === "object" && joined.content.some(
162
+ (c) => c.type === "tool-call" && c.result === void 0
163
+ );
164
+ const autoStatus = getAutoStatus(isLast, isRunning, hasPendingToolCalls);
161
165
  const newMessage = fromThreadMessageLike(
162
- joinExternalMessages(message.outputs),
166
+ joined,
163
167
  idx.toString(),
164
168
  autoStatus
165
169
  );
@@ -209,7 +213,15 @@ var useExternalMessageConverter = ({
209
213
  chunks,
210
214
  (cache, message, idx) => {
211
215
  const isLast = idx === chunks.length - 1;
212
- const autoStatus = getAutoStatus(isLast, isRunning);
216
+ const joined = joinExternalMessages(message.outputs);
217
+ const hasPendingToolCalls = typeof joined.content === "object" && joined.content.some(
218
+ (c) => c.type === "tool-call" && c.result === void 0
219
+ );
220
+ const autoStatus = getAutoStatus(
221
+ isLast,
222
+ isRunning,
223
+ hasPendingToolCalls
224
+ );
213
225
  if (cache && (cache.role !== "assistant" || !isAutoStatus(cache.status) || cache.status === autoStatus)) {
214
226
  const inputs = getExternalStoreMessages(cache);
215
227
  if (shallowArrayEqual(inputs, message.inputs)) {
@@ -217,7 +229,7 @@ var useExternalMessageConverter = ({
217
229
  }
218
230
  }
219
231
  const newMessage = fromThreadMessageLike(
220
- joinExternalMessages(message.outputs),
232
+ joined,
221
233
  idx.toString(),
222
234
  autoStatus
223
235
  );
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/runtimes/external-store/external-message-converter.tsx"],"sourcesContent":["\"use client\";\n\nimport { useMemo } from \"react\";\nimport { ThreadMessageConverter } from \"./ThreadMessageConverter\";\nimport {\n getExternalStoreMessages,\n symbolInnerMessage,\n} from \"./getExternalStoreMessage\";\nimport { fromThreadMessageLike, ThreadMessageLike } from \"./ThreadMessageLike\";\nimport { getAutoStatus, isAutoStatus } from \"./auto-status\";\nimport { ToolCallMessagePart } from \"../../types\";\n\nexport namespace useExternalMessageConverter {\n export type Message =\n | (ThreadMessageLike & {\n readonly convertConfig?: {\n readonly joinStrategy?: \"concat-content\" | \"none\";\n };\n })\n | {\n role: \"tool\";\n toolCallId: string;\n toolName?: string | undefined;\n result: any;\n artifact?: any;\n isError?: boolean;\n };\n\n export type Callback<T> = (message: T) => Message | Message[];\n}\n\ntype CallbackResult<T> = {\n input: T;\n outputs: useExternalMessageConverter.Message[];\n};\n\ntype ChunkResult<T> = {\n inputs: T[];\n outputs: useExternalMessageConverter.Message[];\n};\n\ntype Mutable<T> = {\n -readonly [P in keyof T]: T[P];\n};\n\nconst joinExternalMessages = (\n messages: readonly useExternalMessageConverter.Message[],\n): ThreadMessageLike => {\n const assistantMessage: Mutable<Omit<ThreadMessageLike, \"metadata\">> & {\n content: Exclude<ThreadMessageLike[\"content\"][0], string>[];\n metadata?: Mutable<ThreadMessageLike[\"metadata\"]>;\n } = {\n role: \"assistant\",\n content: [],\n };\n for (const output of messages) {\n if (output.role === \"tool\") {\n const toolCallIdx = assistantMessage.content.findIndex(\n (c) => c.type === \"tool-call\" && c.toolCallId === output.toolCallId,\n );\n if (toolCallIdx !== -1) {\n const toolCall = assistantMessage.content[\n toolCallIdx\n ]! as ToolCallMessagePart;\n if (output.toolName) {\n if (toolCall.toolName !== output.toolName)\n throw new Error(\n `Tool call name ${output.toolCallId} ${output.toolName} does not match existing tool call ${toolCall.toolName}`,\n );\n }\n assistantMessage.content[toolCallIdx] = {\n ...toolCall,\n ...{\n [symbolInnerMessage]: [\n ...((toolCall as any)[symbolInnerMessage] ?? []),\n output,\n ],\n },\n result: output.result,\n artifact: output.artifact,\n isError: output.isError,\n };\n } else {\n throw new Error(\n `Tool call ${output.toolCallId} ${output.toolName} not found in assistant message`,\n );\n }\n } else {\n const role = output.role;\n const content = (\n typeof output.content === \"string\"\n ? [{ type: \"text\" as const, text: output.content }]\n : output.content\n ).map((c) => ({\n ...c,\n ...{ [symbolInnerMessage]: [output] },\n }));\n switch (role) {\n case \"system\":\n case \"user\":\n return {\n ...output,\n content,\n };\n case \"assistant\":\n if (assistantMessage.content.length === 0) {\n assistantMessage.id = output.id;\n assistantMessage.createdAt ??= output.createdAt;\n assistantMessage.status ??= output.status;\n\n if (output.attachments) {\n assistantMessage.attachments = [\n ...(assistantMessage.attachments ?? []),\n ...output.attachments,\n ];\n }\n\n if (output.metadata) {\n assistantMessage.metadata ??= {};\n if (output.metadata.unstable_state) {\n assistantMessage.metadata.unstable_state =\n output.metadata.unstable_state;\n }\n if (output.metadata.unstable_annotations) {\n assistantMessage.metadata.unstable_annotations = [\n ...(assistantMessage.metadata.unstable_annotations ?? []),\n ...output.metadata.unstable_annotations,\n ];\n }\n if (output.metadata.unstable_data) {\n assistantMessage.metadata.unstable_data = [\n ...(assistantMessage.metadata.unstable_data ?? []),\n ...output.metadata.unstable_data,\n ];\n }\n if (output.metadata.steps) {\n assistantMessage.metadata.steps = [\n ...(assistantMessage.metadata.steps ?? []),\n ...output.metadata.steps,\n ];\n }\n if (output.metadata.custom) {\n assistantMessage.metadata.custom = {\n ...(assistantMessage.metadata.custom ?? {}),\n ...output.metadata.custom,\n };\n }\n }\n // TODO keep this in sync\n }\n\n assistantMessage.content.push(...content);\n break;\n default: {\n const unsupportedRole: never = role;\n throw new Error(`Unknown message role: ${unsupportedRole}`);\n }\n }\n }\n }\n return assistantMessage;\n};\n\nconst chunkExternalMessages = <T,>(\n callbackResults: CallbackResult<T>[],\n joinStrategy?: \"concat-content\" | \"none\",\n) => {\n const results: ChunkResult<T>[] = [];\n let isAssistant = false;\n let pendingNone = false; // true if the previous assistant message had joinStrategy \"none\"\n let inputs: T[] = [];\n let outputs: useExternalMessageConverter.Message[] = [];\n\n const flush = () => {\n if (outputs.length) {\n results.push({\n inputs,\n outputs,\n });\n }\n inputs = [];\n outputs = [];\n isAssistant = false;\n pendingNone = false;\n };\n\n for (const callbackResult of callbackResults) {\n for (const output of callbackResult.outputs) {\n if (\n (pendingNone && output.role !== \"tool\") ||\n !isAssistant ||\n output.role === \"user\" ||\n output.role === \"system\"\n ) {\n flush();\n }\n isAssistant = output.role === \"assistant\" || output.role === \"tool\";\n\n if (inputs.at(-1) !== callbackResult.input) {\n inputs.push(callbackResult.input);\n }\n outputs.push(output);\n\n if (\n output.role === \"assistant\" &&\n (output.convertConfig?.joinStrategy === \"none\" ||\n joinStrategy === \"none\")\n ) {\n pendingNone = true;\n }\n }\n }\n flush();\n return results;\n};\n\nexport const convertExternalMessages = <T extends WeakKey>(\n messages: T[],\n callback: useExternalMessageConverter.Callback<T>,\n isRunning: boolean,\n) => {\n const callbackResults: CallbackResult<T>[] = [];\n for (const message of messages) {\n const output = callback(message);\n const outputs = Array.isArray(output) ? output : [output];\n const result = { input: message, outputs };\n callbackResults.push(result);\n }\n\n const chunks = chunkExternalMessages(callbackResults);\n\n return chunks.map((message, idx) => {\n const isLast = idx === chunks.length - 1;\n const autoStatus = getAutoStatus(isLast, isRunning);\n const newMessage = fromThreadMessageLike(\n joinExternalMessages(message.outputs),\n idx.toString(),\n autoStatus,\n );\n (newMessage as any)[symbolInnerMessage] = message.inputs;\n return newMessage;\n });\n};\n\nexport const useExternalMessageConverter = <T extends WeakKey>({\n callback,\n messages,\n isRunning,\n joinStrategy,\n}: {\n callback: useExternalMessageConverter.Callback<T>;\n messages: T[];\n isRunning: boolean;\n joinStrategy?: \"concat-content\" | \"none\" | undefined;\n}) => {\n const state = useMemo(\n () => ({\n callback,\n callbackCache: new WeakMap<T, CallbackResult<T>>(),\n chunkCache: new WeakMap<\n useExternalMessageConverter.Message,\n ChunkResult<T>\n >(),\n converterCache: new ThreadMessageConverter(),\n }),\n [callback],\n );\n\n return useMemo(() => {\n const callbackResults: CallbackResult<T>[] = [];\n for (const message of messages) {\n let result = state.callbackCache.get(message);\n if (!result) {\n const output = state.callback(message);\n const outputs = Array.isArray(output) ? output : [output];\n result = { input: message, outputs };\n state.callbackCache.set(message, result);\n }\n callbackResults.push(result);\n }\n\n const chunks = chunkExternalMessages(callbackResults, joinStrategy).map(\n (m) => {\n const key = m.outputs[0];\n if (!key) return m;\n\n const cached = state.chunkCache.get(key);\n if (cached && shallowArrayEqual(cached.outputs, m.outputs))\n return cached;\n state.chunkCache.set(key, m);\n return m;\n },\n );\n\n const threadMessages = state.converterCache.convertMessages(\n chunks,\n (cache, message, idx) => {\n const isLast = idx === chunks.length - 1;\n const autoStatus = getAutoStatus(isLast, isRunning);\n\n if (\n cache &&\n (cache.role !== \"assistant\" ||\n !isAutoStatus(cache.status) ||\n cache.status === autoStatus)\n ) {\n const inputs = getExternalStoreMessages<T>(cache);\n if (shallowArrayEqual(inputs, message.inputs)) {\n return cache;\n }\n }\n\n const newMessage = fromThreadMessageLike(\n joinExternalMessages(message.outputs),\n idx.toString(),\n autoStatus,\n );\n (newMessage as any)[symbolInnerMessage] = message.inputs;\n return newMessage;\n },\n );\n\n (threadMessages as unknown as { [symbolInnerMessage]: T[] })[\n symbolInnerMessage\n ] = messages;\n\n return threadMessages;\n }, [state, messages, isRunning, joinStrategy]);\n};\n\nconst shallowArrayEqual = (a: unknown[], b: unknown[]) => {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/runtimes/external-store/external-message-converter.tsx"],"sourcesContent":["\"use client\";\n\nimport { useMemo } from \"react\";\nimport { ThreadMessageConverter } from \"./ThreadMessageConverter\";\nimport {\n getExternalStoreMessages,\n symbolInnerMessage,\n} from \"./getExternalStoreMessage\";\nimport { fromThreadMessageLike, ThreadMessageLike } from \"./ThreadMessageLike\";\nimport { getAutoStatus, isAutoStatus } from \"./auto-status\";\nimport { ToolCallMessagePart } from \"../../types\";\n\nexport namespace useExternalMessageConverter {\n export type Message =\n | (ThreadMessageLike & {\n readonly convertConfig?: {\n readonly joinStrategy?: \"concat-content\" | \"none\";\n };\n })\n | {\n role: \"tool\";\n toolCallId: string;\n toolName?: string | undefined;\n result: any;\n artifact?: any;\n isError?: boolean;\n };\n\n export type Callback<T> = (message: T) => Message | Message[];\n}\n\ntype CallbackResult<T> = {\n input: T;\n outputs: useExternalMessageConverter.Message[];\n};\n\ntype ChunkResult<T> = {\n inputs: T[];\n outputs: useExternalMessageConverter.Message[];\n};\n\ntype Mutable<T> = {\n -readonly [P in keyof T]: T[P];\n};\n\nconst joinExternalMessages = (\n messages: readonly useExternalMessageConverter.Message[],\n): ThreadMessageLike => {\n const assistantMessage: Mutable<Omit<ThreadMessageLike, \"metadata\">> & {\n content: Exclude<ThreadMessageLike[\"content\"][0], string>[];\n metadata?: Mutable<ThreadMessageLike[\"metadata\"]>;\n } = {\n role: \"assistant\",\n content: [],\n };\n for (const output of messages) {\n if (output.role === \"tool\") {\n const toolCallIdx = assistantMessage.content.findIndex(\n (c) => c.type === \"tool-call\" && c.toolCallId === output.toolCallId,\n );\n if (toolCallIdx !== -1) {\n const toolCall = assistantMessage.content[\n toolCallIdx\n ]! as ToolCallMessagePart;\n if (output.toolName) {\n if (toolCall.toolName !== output.toolName)\n throw new Error(\n `Tool call name ${output.toolCallId} ${output.toolName} does not match existing tool call ${toolCall.toolName}`,\n );\n }\n assistantMessage.content[toolCallIdx] = {\n ...toolCall,\n ...{\n [symbolInnerMessage]: [\n ...((toolCall as any)[symbolInnerMessage] ?? []),\n output,\n ],\n },\n result: output.result,\n artifact: output.artifact,\n isError: output.isError,\n };\n } else {\n throw new Error(\n `Tool call ${output.toolCallId} ${output.toolName} not found in assistant message`,\n );\n }\n } else {\n const role = output.role;\n const content = (\n typeof output.content === \"string\"\n ? [{ type: \"text\" as const, text: output.content }]\n : output.content\n ).map((c) => ({\n ...c,\n ...{ [symbolInnerMessage]: [output] },\n }));\n switch (role) {\n case \"system\":\n case \"user\":\n return {\n ...output,\n content,\n };\n case \"assistant\":\n if (assistantMessage.content.length === 0) {\n assistantMessage.id = output.id;\n assistantMessage.createdAt ??= output.createdAt;\n assistantMessage.status ??= output.status;\n\n if (output.attachments) {\n assistantMessage.attachments = [\n ...(assistantMessage.attachments ?? []),\n ...output.attachments,\n ];\n }\n\n if (output.metadata) {\n assistantMessage.metadata ??= {};\n if (output.metadata.unstable_state) {\n assistantMessage.metadata.unstable_state =\n output.metadata.unstable_state;\n }\n if (output.metadata.unstable_annotations) {\n assistantMessage.metadata.unstable_annotations = [\n ...(assistantMessage.metadata.unstable_annotations ?? []),\n ...output.metadata.unstable_annotations,\n ];\n }\n if (output.metadata.unstable_data) {\n assistantMessage.metadata.unstable_data = [\n ...(assistantMessage.metadata.unstable_data ?? []),\n ...output.metadata.unstable_data,\n ];\n }\n if (output.metadata.steps) {\n assistantMessage.metadata.steps = [\n ...(assistantMessage.metadata.steps ?? []),\n ...output.metadata.steps,\n ];\n }\n if (output.metadata.custom) {\n assistantMessage.metadata.custom = {\n ...(assistantMessage.metadata.custom ?? {}),\n ...output.metadata.custom,\n };\n }\n }\n // TODO keep this in sync\n }\n\n assistantMessage.content.push(...content);\n break;\n default: {\n const unsupportedRole: never = role;\n throw new Error(`Unknown message role: ${unsupportedRole}`);\n }\n }\n }\n }\n return assistantMessage;\n};\n\nconst chunkExternalMessages = <T,>(\n callbackResults: CallbackResult<T>[],\n joinStrategy?: \"concat-content\" | \"none\",\n) => {\n const results: ChunkResult<T>[] = [];\n let isAssistant = false;\n let pendingNone = false; // true if the previous assistant message had joinStrategy \"none\"\n let inputs: T[] = [];\n let outputs: useExternalMessageConverter.Message[] = [];\n\n const flush = () => {\n if (outputs.length) {\n results.push({\n inputs,\n outputs,\n });\n }\n inputs = [];\n outputs = [];\n isAssistant = false;\n pendingNone = false;\n };\n\n for (const callbackResult of callbackResults) {\n for (const output of callbackResult.outputs) {\n if (\n (pendingNone && output.role !== \"tool\") ||\n !isAssistant ||\n output.role === \"user\" ||\n output.role === \"system\"\n ) {\n flush();\n }\n isAssistant = output.role === \"assistant\" || output.role === \"tool\";\n\n if (inputs.at(-1) !== callbackResult.input) {\n inputs.push(callbackResult.input);\n }\n outputs.push(output);\n\n if (\n output.role === \"assistant\" &&\n (output.convertConfig?.joinStrategy === \"none\" ||\n joinStrategy === \"none\")\n ) {\n pendingNone = true;\n }\n }\n }\n flush();\n return results;\n};\n\nexport const convertExternalMessages = <T extends WeakKey>(\n messages: T[],\n callback: useExternalMessageConverter.Callback<T>,\n isRunning: boolean,\n) => {\n const callbackResults: CallbackResult<T>[] = [];\n for (const message of messages) {\n const output = callback(message);\n const outputs = Array.isArray(output) ? output : [output];\n const result = { input: message, outputs };\n callbackResults.push(result);\n }\n\n const chunks = chunkExternalMessages(callbackResults);\n\n return chunks.map((message, idx) => {\n const isLast = idx === chunks.length - 1;\n const joined = joinExternalMessages(message.outputs);\n const hasPendingToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(\n (c) => c.type === \"tool-call\" && c.result === undefined,\n );\n const autoStatus = getAutoStatus(isLast, isRunning, hasPendingToolCalls);\n const newMessage = fromThreadMessageLike(\n joined,\n idx.toString(),\n autoStatus,\n );\n (newMessage as any)[symbolInnerMessage] = message.inputs;\n return newMessage;\n });\n};\n\nexport const useExternalMessageConverter = <T extends WeakKey>({\n callback,\n messages,\n isRunning,\n joinStrategy,\n}: {\n callback: useExternalMessageConverter.Callback<T>;\n messages: T[];\n isRunning: boolean;\n joinStrategy?: \"concat-content\" | \"none\" | undefined;\n}) => {\n const state = useMemo(\n () => ({\n callback,\n callbackCache: new WeakMap<T, CallbackResult<T>>(),\n chunkCache: new WeakMap<\n useExternalMessageConverter.Message,\n ChunkResult<T>\n >(),\n converterCache: new ThreadMessageConverter(),\n }),\n [callback],\n );\n\n return useMemo(() => {\n const callbackResults: CallbackResult<T>[] = [];\n for (const message of messages) {\n let result = state.callbackCache.get(message);\n if (!result) {\n const output = state.callback(message);\n const outputs = Array.isArray(output) ? output : [output];\n result = { input: message, outputs };\n state.callbackCache.set(message, result);\n }\n callbackResults.push(result);\n }\n\n const chunks = chunkExternalMessages(callbackResults, joinStrategy).map(\n (m) => {\n const key = m.outputs[0];\n if (!key) return m;\n\n const cached = state.chunkCache.get(key);\n if (cached && shallowArrayEqual(cached.outputs, m.outputs))\n return cached;\n state.chunkCache.set(key, m);\n return m;\n },\n );\n\n const threadMessages = state.converterCache.convertMessages(\n chunks,\n (cache, message, idx) => {\n const isLast = idx === chunks.length - 1;\n\n const joined = joinExternalMessages(message.outputs);\n const hasPendingToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(\n (c) => c.type === \"tool-call\" && c.result === undefined,\n );\n const autoStatus = getAutoStatus(\n isLast,\n isRunning,\n hasPendingToolCalls,\n );\n\n if (\n cache &&\n (cache.role !== \"assistant\" ||\n !isAutoStatus(cache.status) ||\n cache.status === autoStatus)\n ) {\n const inputs = getExternalStoreMessages<T>(cache);\n if (shallowArrayEqual(inputs, message.inputs)) {\n return cache;\n }\n }\n\n const newMessage = fromThreadMessageLike(\n joined,\n idx.toString(),\n autoStatus,\n );\n (newMessage as any)[symbolInnerMessage] = message.inputs;\n return newMessage;\n },\n );\n\n (threadMessages as unknown as { [symbolInnerMessage]: T[] })[\n symbolInnerMessage\n ] = messages;\n\n return threadMessages;\n }, [state, messages, isRunning, joinStrategy]);\n};\n\nconst shallowArrayEqual = (a: unknown[], b: unknown[]) => {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n};\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"cloud.d.ts","sourceRoot":"","sources":["../../../../src/runtimes/remote-thread-list/adapter/cloud.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAKnD,KAAK,UAAU,GAAG;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,6BAA6B,GAAG;IACnC,KAAK,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IAEnC,MAAM,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/B,MAAM,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C,CAAC;AASF,eAAO,MAAM,yBAAyB,GACpC,SAAS,6BAA6B,KACrC,uBA4EF,CAAC"}
1
+ {"version":3,"file":"cloud.d.ts","sourceRoot":"","sources":["../../../../src/runtimes/remote-thread-list/adapter/cloud.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAKnD,KAAK,UAAU,GAAG;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,6BAA6B,GAAG;IACnC,KAAK,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IAEnC,MAAM,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/B,MAAM,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C,CAAC;AASF,eAAO,MAAM,yBAAyB,GACpC,SAAS,6BAA6B,KACrC,uBA4EF,CAAC"}
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  // src/runtimes/remote-thread-list/adapter/cloud.tsx
2
4
  import {
3
5
  useCallback,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/runtimes/remote-thread-list/adapter/cloud.tsx"],"sourcesContent":["import {\n FC,\n PropsWithChildren,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n} from \"react\";\nimport { AssistantCloud } from \"assistant-cloud\";\nimport { RemoteThreadListAdapter } from \"../types\";\nimport { useAssistantCloudThreadHistoryAdapter } from \"../../../cloud/AssistantCloudThreadHistoryAdapter\";\nimport { RuntimeAdapterProvider } from \"../../adapters/RuntimeAdapterProvider\";\nimport { InMemoryThreadListAdapter } from \"./in-memory\";\n\ntype ThreadData = {\n externalId: string;\n};\n\ntype CloudThreadListAdapterOptions = {\n cloud?: AssistantCloud | undefined;\n\n create?(): Promise<ThreadData>;\n delete?(threadId: string): Promise<void>;\n};\n\nconst baseUrl =\n typeof process !== \"undefined\" &&\n process?.env?.[\"NEXT_PUBLIC_ASSISTANT_BASE_URL\"];\nconst autoCloud = baseUrl\n ? new AssistantCloud({ baseUrl, anonymous: true })\n : undefined;\n\nexport const useCloudThreadListAdapter = (\n adapter: CloudThreadListAdapterOptions,\n): RemoteThreadListAdapter => {\n const adapterRef = useRef(adapter);\n useEffect(() => {\n adapterRef.current = adapter;\n }, [adapter]);\n\n const unstable_Provider = useCallback<FC<PropsWithChildren>>(\n function Provider({ children }) {\n const history = useAssistantCloudThreadHistoryAdapter({\n get current() {\n return adapterRef.current.cloud ?? autoCloud!;\n },\n });\n const adapters = useMemo(() => ({ history }), [history]);\n\n return (\n <RuntimeAdapterProvider adapters={adapters}>\n {children}\n </RuntimeAdapterProvider>\n );\n },\n [],\n );\n\n const cloud = adapter.cloud ?? autoCloud;\n if (!cloud) return new InMemoryThreadListAdapter();\n\n return {\n list: async () => {\n const { threads } = await cloud.threads.list();\n return {\n threads: threads.map((t) => ({\n status: t.is_archived ? \"archived\" : \"regular\",\n remoteId: t.id,\n title: t.title,\n externalId: t.external_id ?? undefined,\n })),\n };\n },\n\n initialize: async () => {\n const createTask = adapter.create?.() ?? Promise.resolve();\n const t = await createTask;\n const external_id = t ? t.externalId : undefined;\n const { thread_id: remoteId } = await cloud.threads.create({\n last_message_at: new Date(),\n external_id,\n });\n\n return { externalId: external_id, remoteId: remoteId };\n },\n\n rename: async (threadId, newTitle) => {\n return cloud.threads.update(threadId, { title: newTitle });\n },\n archive: async (threadId) => {\n return cloud.threads.update(threadId, { is_archived: true });\n },\n unarchive: async (threadId) => {\n return cloud.threads.update(threadId, { is_archived: false });\n },\n delete: async (threadId) => {\n await adapter.delete?.(threadId);\n return cloud.threads.delete(threadId);\n },\n\n generateTitle: async (threadId, messages) => {\n return cloud.runs.stream({\n thread_id: threadId,\n assistant_id: \"system/thread_title\",\n messages: messages, // TODO serialize these to a more efficient format\n });\n },\n\n unstable_Provider,\n };\n};\n"],"mappings":";AAAA;AAAA,EAGE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,sBAAsB;AAE/B,SAAS,6CAA6C;AACtD,SAAS,8BAA8B;AACvC,SAAS,iCAAiC;AAsClC;AAzBR,IAAM,UACJ,OAAO,YAAY,eACnB,SAAS,MAAM,gCAAgC;AACjD,IAAM,YAAY,UACd,IAAI,eAAe,EAAE,SAAS,WAAW,KAAK,CAAC,IAC/C;AAEG,IAAM,4BAA4B,CACvC,YAC4B;AAC5B,QAAM,aAAa,OAAO,OAAO;AACjC,YAAU,MAAM;AACd,eAAW,UAAU;AAAA,EACvB,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,oBAAoB;AAAA,IACxB,SAAS,SAAS,EAAE,SAAS,GAAG;AAC9B,YAAM,UAAU,sCAAsC;AAAA,QACpD,IAAI,UAAU;AACZ,iBAAO,WAAW,QAAQ,SAAS;AAAA,QACrC;AAAA,MACF,CAAC;AACD,YAAM,WAAW,QAAQ,OAAO,EAAE,QAAQ,IAAI,CAAC,OAAO,CAAC;AAEvD,aACE,oBAAC,0BAAuB,UACrB,UACH;AAAA,IAEJ;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,QAAQ,QAAQ,SAAS;AAC/B,MAAI,CAAC,MAAO,QAAO,IAAI,0BAA0B;AAEjD,SAAO;AAAA,IACL,MAAM,YAAY;AAChB,YAAM,EAAE,QAAQ,IAAI,MAAM,MAAM,QAAQ,KAAK;AAC7C,aAAO;AAAA,QACL,SAAS,QAAQ,IAAI,CAAC,OAAO;AAAA,UAC3B,QAAQ,EAAE,cAAc,aAAa;AAAA,UACrC,UAAU,EAAE;AAAA,UACZ,OAAO,EAAE;AAAA,UACT,YAAY,EAAE,eAAe;AAAA,QAC/B,EAAE;AAAA,MACJ;AAAA,IACF;AAAA,IAEA,YAAY,YAAY;AACtB,YAAM,aAAa,QAAQ,SAAS,KAAK,QAAQ,QAAQ;AACzD,YAAM,IAAI,MAAM;AAChB,YAAM,cAAc,IAAI,EAAE,aAAa;AACvC,YAAM,EAAE,WAAW,SAAS,IAAI,MAAM,MAAM,QAAQ,OAAO;AAAA,QACzD,iBAAiB,oBAAI,KAAK;AAAA,QAC1B;AAAA,MACF,CAAC;AAED,aAAO,EAAE,YAAY,aAAa,SAAmB;AAAA,IACvD;AAAA,IAEA,QAAQ,OAAO,UAAU,aAAa;AACpC,aAAO,MAAM,QAAQ,OAAO,UAAU,EAAE,OAAO,SAAS,CAAC;AAAA,IAC3D;AAAA,IACA,SAAS,OAAO,aAAa;AAC3B,aAAO,MAAM,QAAQ,OAAO,UAAU,EAAE,aAAa,KAAK,CAAC;AAAA,IAC7D;AAAA,IACA,WAAW,OAAO,aAAa;AAC7B,aAAO,MAAM,QAAQ,OAAO,UAAU,EAAE,aAAa,MAAM,CAAC;AAAA,IAC9D;AAAA,IACA,QAAQ,OAAO,aAAa;AAC1B,YAAM,QAAQ,SAAS,QAAQ;AAC/B,aAAO,MAAM,QAAQ,OAAO,QAAQ;AAAA,IACtC;AAAA,IAEA,eAAe,OAAO,UAAU,aAAa;AAC3C,aAAO,MAAM,KAAK,OAAO;AAAA,QACvB,WAAW;AAAA,QACX,cAAc;AAAA,QACd;AAAA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../src/runtimes/remote-thread-list/adapter/cloud.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n FC,\n PropsWithChildren,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n} from \"react\";\nimport { AssistantCloud } from \"assistant-cloud\";\nimport { RemoteThreadListAdapter } from \"../types\";\nimport { useAssistantCloudThreadHistoryAdapter } from \"../../../cloud/AssistantCloudThreadHistoryAdapter\";\nimport { RuntimeAdapterProvider } from \"../../adapters/RuntimeAdapterProvider\";\nimport { InMemoryThreadListAdapter } from \"./in-memory\";\n\ntype ThreadData = {\n externalId: string;\n};\n\ntype CloudThreadListAdapterOptions = {\n cloud?: AssistantCloud | undefined;\n\n create?(): Promise<ThreadData>;\n delete?(threadId: string): Promise<void>;\n};\n\nconst baseUrl =\n typeof process !== \"undefined\" &&\n process?.env?.[\"NEXT_PUBLIC_ASSISTANT_BASE_URL\"];\nconst autoCloud = baseUrl\n ? new AssistantCloud({ baseUrl, anonymous: true })\n : undefined;\n\nexport const useCloudThreadListAdapter = (\n adapter: CloudThreadListAdapterOptions,\n): RemoteThreadListAdapter => {\n const adapterRef = useRef(adapter);\n useEffect(() => {\n adapterRef.current = adapter;\n }, [adapter]);\n\n const unstable_Provider = useCallback<FC<PropsWithChildren>>(\n function Provider({ children }) {\n const history = useAssistantCloudThreadHistoryAdapter({\n get current() {\n return adapterRef.current.cloud ?? autoCloud!;\n },\n });\n const adapters = useMemo(() => ({ history }), [history]);\n\n return (\n <RuntimeAdapterProvider adapters={adapters}>\n {children}\n </RuntimeAdapterProvider>\n );\n },\n [],\n );\n\n const cloud = adapter.cloud ?? autoCloud;\n if (!cloud) return new InMemoryThreadListAdapter();\n\n return {\n list: async () => {\n const { threads } = await cloud.threads.list();\n return {\n threads: threads.map((t) => ({\n status: t.is_archived ? \"archived\" : \"regular\",\n remoteId: t.id,\n title: t.title,\n externalId: t.external_id ?? undefined,\n })),\n };\n },\n\n initialize: async () => {\n const createTask = adapter.create?.() ?? Promise.resolve();\n const t = await createTask;\n const external_id = t ? t.externalId : undefined;\n const { thread_id: remoteId } = await cloud.threads.create({\n last_message_at: new Date(),\n external_id,\n });\n\n return { externalId: external_id, remoteId: remoteId };\n },\n\n rename: async (threadId, newTitle) => {\n return cloud.threads.update(threadId, { title: newTitle });\n },\n archive: async (threadId) => {\n return cloud.threads.update(threadId, { is_archived: true });\n },\n unarchive: async (threadId) => {\n return cloud.threads.update(threadId, { is_archived: false });\n },\n delete: async (threadId) => {\n await adapter.delete?.(threadId);\n return cloud.threads.delete(threadId);\n },\n\n generateTitle: async (threadId, messages) => {\n return cloud.runs.stream({\n thread_id: threadId,\n assistant_id: \"system/thread_title\",\n messages: messages, // TODO serialize these to a more efficient format\n });\n },\n\n unstable_Provider,\n };\n};\n"],"mappings":";;;AAEA;AAAA,EAGE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,sBAAsB;AAE/B,SAAS,6CAA6C;AACtD,SAAS,8BAA8B;AACvC,SAAS,iCAAiC;AAsClC;AAzBR,IAAM,UACJ,OAAO,YAAY,eACnB,SAAS,MAAM,gCAAgC;AACjD,IAAM,YAAY,UACd,IAAI,eAAe,EAAE,SAAS,WAAW,KAAK,CAAC,IAC/C;AAEG,IAAM,4BAA4B,CACvC,YAC4B;AAC5B,QAAM,aAAa,OAAO,OAAO;AACjC,YAAU,MAAM;AACd,eAAW,UAAU;AAAA,EACvB,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,oBAAoB;AAAA,IACxB,SAAS,SAAS,EAAE,SAAS,GAAG;AAC9B,YAAM,UAAU,sCAAsC;AAAA,QACpD,IAAI,UAAU;AACZ,iBAAO,WAAW,QAAQ,SAAS;AAAA,QACrC;AAAA,MACF,CAAC;AACD,YAAM,WAAW,QAAQ,OAAO,EAAE,QAAQ,IAAI,CAAC,OAAO,CAAC;AAEvD,aACE,oBAAC,0BAAuB,UACrB,UACH;AAAA,IAEJ;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,QAAQ,QAAQ,SAAS;AAC/B,MAAI,CAAC,MAAO,QAAO,IAAI,0BAA0B;AAEjD,SAAO;AAAA,IACL,MAAM,YAAY;AAChB,YAAM,EAAE,QAAQ,IAAI,MAAM,MAAM,QAAQ,KAAK;AAC7C,aAAO;AAAA,QACL,SAAS,QAAQ,IAAI,CAAC,OAAO;AAAA,UAC3B,QAAQ,EAAE,cAAc,aAAa;AAAA,UACrC,UAAU,EAAE;AAAA,UACZ,OAAO,EAAE;AAAA,UACT,YAAY,EAAE,eAAe;AAAA,QAC/B,EAAE;AAAA,MACJ;AAAA,IACF;AAAA,IAEA,YAAY,YAAY;AACtB,YAAM,aAAa,QAAQ,SAAS,KAAK,QAAQ,QAAQ;AACzD,YAAM,IAAI,MAAM;AAChB,YAAM,cAAc,IAAI,EAAE,aAAa;AACvC,YAAM,EAAE,WAAW,SAAS,IAAI,MAAM,MAAM,QAAQ,OAAO;AAAA,QACzD,iBAAiB,oBAAI,KAAK;AAAA,QAC1B;AAAA,MACF,CAAC;AAED,aAAO,EAAE,YAAY,aAAa,SAAmB;AAAA,IACvD;AAAA,IAEA,QAAQ,OAAO,UAAU,aAAa;AACpC,aAAO,MAAM,QAAQ,OAAO,UAAU,EAAE,OAAO,SAAS,CAAC;AAAA,IAC3D;AAAA,IACA,SAAS,OAAO,aAAa;AAC3B,aAAO,MAAM,QAAQ,OAAO,UAAU,EAAE,aAAa,KAAK,CAAC;AAAA,IAC7D;AAAA,IACA,WAAW,OAAO,aAAa;AAC7B,aAAO,MAAM,QAAQ,OAAO,UAAU,EAAE,aAAa,MAAM,CAAC;AAAA,IAC9D;AAAA,IACA,QAAQ,OAAO,aAAa;AAC1B,YAAM,QAAQ,SAAS,QAAQ;AAC/B,aAAO,MAAM,QAAQ,OAAO,QAAQ;AAAA,IACtC;AAAA,IAEA,eAAe,OAAO,UAAU,aAAa;AAC3C,aAAO,MAAM,KAAK,OAAO;AAAA,QACvB,WAAW;AAAA,QACX,cAAc;AAAA,QACd;AAAA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA;AAAA,EACF;AACF;","names":[]}
@@ -1,4 +1,5 @@
1
1
  export { useRemoteThreadListRuntime as unstable_useRemoteThreadListRuntime } from "./useRemoteThreadListRuntime";
2
2
  export type { RemoteThreadListAdapter as unstable_RemoteThreadListAdapter } from "./types";
3
3
  export { InMemoryThreadListAdapter as unstable_InMemoryThreadListAdapter } from "./adapter/in-memory";
4
+ export { useCloudThreadListAdapter as unstable_useCloudThreadListAdapter } from "./adapter/cloud";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtimes/remote-thread-list/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,IAAI,mCAAmC,EAAE,MAAM,8BAA8B,CAAC;AACjH,YAAY,EAAE,uBAAuB,IAAI,gCAAgC,EAAE,MAAM,SAAS,CAAC;AAE3F,OAAO,EAAE,yBAAyB,IAAI,kCAAkC,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtimes/remote-thread-list/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,IAAI,mCAAmC,EAAE,MAAM,8BAA8B,CAAC;AACjH,YAAY,EAAE,uBAAuB,IAAI,gCAAgC,EAAE,MAAM,SAAS,CAAC;AAE3F,OAAO,EAAE,yBAAyB,IAAI,kCAAkC,EAAE,MAAM,qBAAqB,CAAC;AACtG,OAAO,EAAE,yBAAyB,IAAI,kCAAkC,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,8 +1,10 @@
1
1
  // src/runtimes/remote-thread-list/index.ts
2
2
  import { useRemoteThreadListRuntime } from "./useRemoteThreadListRuntime.js";
3
3
  import { InMemoryThreadListAdapter } from "./adapter/in-memory.js";
4
+ import { useCloudThreadListAdapter } from "./adapter/cloud.js";
4
5
  export {
5
6
  InMemoryThreadListAdapter as unstable_InMemoryThreadListAdapter,
7
+ useCloudThreadListAdapter as unstable_useCloudThreadListAdapter,
6
8
  useRemoteThreadListRuntime as unstable_useRemoteThreadListRuntime
7
9
  };
8
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/runtimes/remote-thread-list/index.ts"],"sourcesContent":["export { useRemoteThreadListRuntime as unstable_useRemoteThreadListRuntime } from \"./useRemoteThreadListRuntime\";\nexport type { RemoteThreadListAdapter as unstable_RemoteThreadListAdapter } from \"./types\";\n\nexport { InMemoryThreadListAdapter as unstable_InMemoryThreadListAdapter } from \"./adapter/in-memory\";\n"],"mappings":";AAAA,SAAuC,kCAA2C;AAGlF,SAAsC,iCAA0C;","names":[]}
1
+ {"version":3,"sources":["../../../src/runtimes/remote-thread-list/index.ts"],"sourcesContent":["export { useRemoteThreadListRuntime as unstable_useRemoteThreadListRuntime } from \"./useRemoteThreadListRuntime\";\nexport type { RemoteThreadListAdapter as unstable_RemoteThreadListAdapter } from \"./types\";\n\nexport { InMemoryThreadListAdapter as unstable_InMemoryThreadListAdapter } from \"./adapter/in-memory\";\nexport { useCloudThreadListAdapter as unstable_useCloudThreadListAdapter } from \"./adapter/cloud\";\n"],"mappings":";AAAA,SAAuC,kCAA2C;AAGlF,SAAsC,iCAA0C;AAChF,SAAsC,iCAA0C;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"MessageRepository.d.ts","sourceRoot":"","sources":["../../../src/runtimes/utils/MessageRepository.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AA0BtD;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG;IAC1C,uBAAuB;IACvB,OAAO,EAAE,aAAa,CAAC;IACvB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,yDAAyD;IACzD,QAAQ,EAAE,KAAK,CAAC;QACd,OAAO,EAAE,aAAa,CAAC;QACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACzB,CAAC,CAAC;CACJ,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,yBAAyB;IACpC;;;;;;OAMG;0BAES,SAAS,iBAAiB,EAAE,KACrC,yBAAyB;CAY7B,CAAC;AA6CF;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B,uDAAuD;IACvD,OAAO,CAAC,QAAQ,CAAwC;IACxD,+EAA+E;IAC/E,OAAO,CAAC,IAAI,CAAkC;IAC9C,sCAAsC;IACtC,OAAO,CAAC,IAAI,CAGV;IAEF;;;;;;;;;OASG;IACH,OAAO,CAAC,SAAS;IA4DjB,+EAA+E;IAC/E,OAAO,CAAC,SAAS,CAMd;IAEH;;;OAGG;IACH,IAAI,MAAM,kBAET;IAED;;;OAGG;IACH,WAAW;IAIX;;;;;;;;OAQG;IACH,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,aAAa;IAmClE;;;;;;OAMG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM;;;;IAa5B;;;;;;;OAOG;IACH,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,iBAAiB;IAc3E;;;;;;;;OAQG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAsC1E;;;;;;OAMG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM;IAW7B;;;;;OAKG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM;IAehC;;;;;OAKG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IA2BlC;;OAEG;IACH,KAAK,IAAI,IAAI;IAUb;;;;OAIG;IACH,MAAM,IAAI,yBAAyB;IAkBnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,yBAAyB;CAQvD"}
1
+ {"version":3,"file":"MessageRepository.d.ts","sourceRoot":"","sources":["../../../src/runtimes/utils/MessageRepository.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AA0BtD;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG;IAC1C,uBAAuB;IACvB,OAAO,EAAE,aAAa,CAAC;IACvB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,yDAAyD;IACzD,QAAQ,EAAE,KAAK,CAAC;QACd,OAAO,EAAE,aAAa,CAAC;QACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACzB,CAAC,CAAC;CACJ,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,yBAAyB;IACpC;;;;;;OAMG;0BAES,SAAS,iBAAiB,EAAE,KACrC,yBAAyB;CAgB7B,CAAC;AA6CF;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B,uDAAuD;IACvD,OAAO,CAAC,QAAQ,CAAwC;IACxD,+EAA+E;IAC/E,OAAO,CAAC,IAAI,CAAkC;IAC9C,sCAAsC;IACtC,OAAO,CAAC,IAAI,CAGV;IAEF;;;;;;;;;OASG;IACH,OAAO,CAAC,SAAS;IA4DjB,+EAA+E;IAC/E,OAAO,CAAC,SAAS,CAMd;IAEH;;;OAGG;IACH,IAAI,MAAM,kBAET;IAED;;;OAGG;IACH,WAAW;IAIX;;;;;;;;OAQG;IACH,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,aAAa;IAmClE;;;;;;OAMG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM;;;;IAa5B;;;;;;;OAOG;IACH,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,iBAAiB;IAc3E;;;;;;;;OAQG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAsC1E;;;;;;OAMG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM;IAW7B;;;;;OAKG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM;IAehC;;;;;OAKG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IA2BlC;;OAEG;IACH,KAAK,IAAI,IAAI;IAUb;;;;OAIG;IACH,MAAM,IAAI,yBAAyB;IAkBnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,yBAAyB;CAQvD"}
@@ -12,7 +12,11 @@ var ExportedMessageRepository = {
12
12
  */
13
13
  fromArray: (messages) => {
14
14
  const conv = messages.map(
15
- (m) => fromThreadMessageLike(m, generateId(), getAutoStatus(false, false))
15
+ (m) => fromThreadMessageLike(
16
+ m,
17
+ generateId(),
18
+ getAutoStatus(false, false, false)
19
+ )
16
20
  );
17
21
  return {
18
22
  messages: conv.map((m, idx) => ({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/runtimes/utils/MessageRepository.tsx"],"sourcesContent":["import type { ThreadMessage } from \"../../types\";\nimport { generateId, generateOptimisticId } from \"../../utils/idUtils\";\nimport { ThreadMessageLike } from \"../external-store\";\nimport { getAutoStatus } from \"../external-store/auto-status\";\nimport { fromThreadMessageLike } from \"../external-store/ThreadMessageLike\";\n\n/**\n * Represents a parent node in the repository tree structure.\n */\ntype RepositoryParent = {\n /** IDs of child messages */\n children: string[];\n /** Reference to the next message in the active branch */\n next: RepositoryMessage | null;\n};\n\n/**\n * Represents a message node in the repository tree structure.\n */\ntype RepositoryMessage = RepositoryParent & {\n /** Reference to the parent message */\n prev: RepositoryMessage | null;\n /** The actual message data */\n current: ThreadMessage;\n /** The depth level in the tree (0 for root messages) */\n level: number;\n};\n\n/**\n * Represents a message item that can be exported from the repository.\n */\nexport type ExportedMessageRepositoryItem = {\n /** The message data */\n message: ThreadMessage;\n /** ID of the parent message, or null for root messages */\n parentId: string | null;\n};\n\n/**\n * Represents the entire repository state for export/import.\n */\nexport type ExportedMessageRepository = {\n /** ID of the head message, or null/undefined if no head */\n headId?: string | null;\n /** Array of all messages with their parent references */\n messages: Array<{\n message: ThreadMessage;\n parentId: string | null;\n }>;\n};\n\n/**\n * Utility functions for working with exported message repositories.\n */\nexport const ExportedMessageRepository = {\n /**\n * Converts an array of messages to an ExportedMessageRepository format.\n * Creates parent-child relationships based on the order of messages in the array.\n *\n * @param messages - Array of message-like objects to convert\n * @returns ExportedMessageRepository with parent-child relationships established\n */\n fromArray: (\n messages: readonly ThreadMessageLike[],\n ): ExportedMessageRepository => {\n const conv = messages.map((m) =>\n fromThreadMessageLike(m, generateId(), getAutoStatus(false, false)),\n );\n\n return {\n messages: conv.map((m, idx) => ({\n parentId: idx > 0 ? conv[idx - 1]!.id : null,\n message: m,\n })),\n };\n },\n};\n\n/**\n * Recursively finds the head (leaf) message in a branch.\n *\n * @param message - The starting message or parent node\n * @returns The leaf message of the branch, or null if not found\n */\nconst findHead = (\n message: RepositoryMessage | RepositoryParent,\n): RepositoryMessage | null => {\n if (message.next) return findHead(message.next);\n if (\"current\" in message) return message;\n return null;\n};\n\n/**\n * A utility class for caching computed values and invalidating the cache when needed.\n */\nclass CachedValue<T> {\n private _value: T | null = null;\n\n /**\n * @param func - The function that computes the cached value\n */\n constructor(private func: () => T) {}\n\n /**\n * Gets the cached value, computing it if necessary.\n */\n get value() {\n if (this._value === null) {\n this._value = this.func();\n }\n return this._value;\n }\n\n /**\n * Invalidates the cache, forcing recomputation on next access.\n */\n dirty() {\n this._value = null;\n }\n}\n\n/**\n * A repository that manages a tree of messages with branching capabilities.\n * Supports operations like adding, updating, and deleting messages, as well as\n * managing multiple conversation branches.\n */\nexport class MessageRepository {\n /** Map of message IDs to repository message objects */\n private messages = new Map<string, RepositoryMessage>();\n /** Reference to the current head (most recent) message in the active branch */\n private head: RepositoryMessage | null = null;\n /** Root node of the tree structure */\n private root: RepositoryParent = {\n children: [],\n next: null,\n };\n\n /**\n * Performs link/unlink operations between messages in the tree.\n *\n * @param newParent - The new parent message, or null\n * @param child - The child message to operate on\n * @param operation - The type of operation to perform:\n * - \"cut\": Remove the child from its current parent\n * - \"link\": Add the child to a new parent\n * - \"relink\": Both cut and link operations\n */\n private performOp(\n newParent: RepositoryMessage | null,\n child: RepositoryMessage,\n operation: \"cut\" | \"link\" | \"relink\",\n ) {\n const parentOrRoot = child.prev ?? this.root;\n const newParentOrRoot = newParent ?? this.root;\n\n if (operation === \"relink\" && parentOrRoot === newParentOrRoot) return;\n\n // cut\n if (operation !== \"link\") {\n // remove from parentOrRoot.children\n parentOrRoot.children = parentOrRoot.children.filter(\n (m) => m !== child.current.id,\n );\n\n // update parentOrRoot.next\n if (parentOrRoot.next === child) {\n const fallbackId = parentOrRoot.children.at(-1);\n const fallback = fallbackId ? this.messages.get(fallbackId) : null;\n if (fallback === undefined) {\n throw new Error(\n \"MessageRepository(performOp/cut): Fallback sibling message not found. This is likely an internal bug in assistant-ui.\",\n );\n }\n parentOrRoot.next = fallback;\n }\n }\n\n // link\n if (operation !== \"cut\") {\n // ensure the child is not part of parent tree\n for (\n let current: RepositoryMessage | null = newParent;\n current;\n current = current.prev\n ) {\n if (current.current.id === child.current.id) {\n throw new Error(\n \"MessageRepository(performOp/link): A message with the same id already exists in the parent tree. This error occurs if the same message id is found multiple times. This is likely an internal bug in assistant-ui.\",\n );\n }\n }\n\n // add to parentOrRoot.children\n newParentOrRoot.children = [\n ...newParentOrRoot.children,\n child.current.id,\n ];\n\n // update parentOrRoot.next\n if (findHead(child) === this.head || newParentOrRoot.next === null) {\n newParentOrRoot.next = child;\n }\n\n child.prev = newParent;\n }\n }\n\n /** Cached array of messages in the current active branch, from root to head */\n private _messages = new CachedValue<readonly ThreadMessage[]>(() => {\n const messages = new Array<ThreadMessage>(this.head?.level ?? 0);\n for (let current = this.head; current; current = current.prev) {\n messages[current.level] = current.current;\n }\n return messages;\n });\n\n /**\n * Gets the ID of the current head message.\n * @returns The ID of the head message, or null if no messages exist\n */\n get headId() {\n return this.head?.current.id ?? null;\n }\n\n /**\n * Gets all messages in the current active branch, from root to head.\n * @returns Array of messages in the current branch\n */\n getMessages() {\n return this._messages.value;\n }\n\n /**\n * Adds a new message or updates an existing one in the repository.\n * If the message ID already exists, the message is updated and potentially relinked to a new parent.\n * If the message is new, it's added as a child of the specified parent.\n *\n * @param parentId - ID of the parent message, or null for root messages\n * @param message - The message to add or update\n * @throws Error if the parent message is not found\n */\n addOrUpdateMessage(parentId: string | null, message: ThreadMessage) {\n const existingItem = this.messages.get(message.id);\n const prev = parentId ? this.messages.get(parentId) : null;\n if (prev === undefined)\n throw new Error(\n \"MessageRepository(addOrUpdateMessage): Parent message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n // update existing message\n if (existingItem) {\n existingItem.current = message;\n this.performOp(prev, existingItem, \"relink\");\n this._messages.dirty();\n return;\n }\n\n // create a new message\n const newItem: RepositoryMessage = {\n prev,\n current: message,\n next: null,\n children: [],\n level: prev ? prev.level + 1 : 0,\n };\n\n this.messages.set(message.id, newItem);\n this.performOp(prev, newItem, \"link\");\n\n if (this.head === prev) {\n this.head = newItem;\n }\n\n this._messages.dirty();\n }\n\n /**\n * Gets a message and its parent ID by message ID.\n *\n * @param messageId - ID of the message to retrieve\n * @returns Object containing the message and its parent ID\n * @throws Error if the message is not found\n */\n getMessage(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(updateMessage): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n return {\n parentId: message.prev?.current.id ?? null,\n message: message.current,\n };\n }\n\n /**\n * Adds an optimistic message to the repository.\n * An optimistic message is a temporary placeholder that will be replaced by a real message later.\n *\n * @param parentId - ID of the parent message, or null for root messages\n * @param message - The core message to convert to an optimistic message\n * @returns The generated optimistic ID\n */\n appendOptimisticMessage(parentId: string | null, message: ThreadMessageLike) {\n let optimisticId: string;\n do {\n optimisticId = generateOptimisticId();\n } while (this.messages.has(optimisticId));\n\n this.addOrUpdateMessage(\n parentId,\n fromThreadMessageLike(message, optimisticId, { type: \"running\" }),\n );\n\n return optimisticId;\n }\n\n /**\n * Deletes a message from the repository and relinks its children.\n *\n * @param messageId - ID of the message to delete\n * @param replacementId - Optional ID of the message to become the new parent of the children,\n * undefined means use the deleted message's parent,\n * null means use the root\n * @throws Error if the message or replacement is not found\n */\n deleteMessage(messageId: string, replacementId?: string | null | undefined) {\n const message = this.messages.get(messageId);\n\n if (!message)\n throw new Error(\n \"MessageRepository(deleteMessage): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const replacement =\n replacementId === undefined\n ? message.prev // if no replacementId is provided, use the parent\n : replacementId === null\n ? null\n : this.messages.get(replacementId);\n if (replacement === undefined)\n throw new Error(\n \"MessageRepository(deleteMessage): Replacement not found. This is likely an internal bug in assistant-ui.\",\n );\n\n for (const child of message.children) {\n const childMessage = this.messages.get(child);\n if (!childMessage)\n throw new Error(\n \"MessageRepository(deleteMessage): Child message not found. This is likely an internal bug in assistant-ui.\",\n );\n this.performOp(replacement, childMessage, \"relink\");\n }\n\n this.performOp(null, message, \"cut\");\n this.messages.delete(messageId);\n\n if (this.head === message) {\n this.head = findHead(replacement ?? this.root);\n }\n\n this._messages.dirty();\n }\n\n /**\n * Gets all branch IDs (sibling messages) at the level of a specified message.\n *\n * @param messageId - ID of the message to find branches for\n * @returns Array of message IDs representing branches\n * @throws Error if the message is not found\n */\n getBranches(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(getBranches): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const { children } = message.prev ?? this.root;\n return children;\n }\n\n /**\n * Switches the active branch to the one containing the specified message.\n *\n * @param messageId - ID of the message in the branch to switch to\n * @throws Error if the branch is not found\n */\n switchToBranch(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(switchToBranch): Branch not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const prevOrRoot = message.prev ?? this.root;\n prevOrRoot.next = message;\n\n this.head = findHead(message);\n\n this._messages.dirty();\n }\n\n /**\n * Resets the head to a specific message or null.\n *\n * @param messageId - ID of the message to set as head, or null to clear the head\n * @throws Error if the message is not found\n */\n resetHead(messageId: string | null) {\n if (messageId === null) {\n this.head = null;\n this._messages.dirty();\n return;\n }\n\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(resetHead): Branch not found. This is likely an internal bug in assistant-ui.\",\n );\n\n this.head = message;\n for (\n let current: RepositoryMessage | null = message;\n current;\n current = current.prev\n ) {\n if (current.prev) {\n current.prev.next = current;\n }\n }\n\n this._messages.dirty();\n }\n\n /**\n * Clears all messages from the repository.\n */\n clear(): void {\n this.messages.clear();\n this.head = null;\n this.root = {\n children: [],\n next: null,\n };\n this._messages.dirty();\n }\n\n /**\n * Exports the repository state for persistence.\n *\n * @returns Exportable repository state\n */\n export(): ExportedMessageRepository {\n const exportItems: ExportedMessageRepository[\"messages\"] = [];\n\n // hint: we are relying on the insertion order of the messages\n // this is important for the import function to properly link the messages\n for (const [, message] of this.messages) {\n exportItems.push({\n message: message.current,\n parentId: message.prev?.current.id ?? null,\n });\n }\n\n return {\n headId: this.head?.current.id ?? null,\n messages: exportItems,\n };\n }\n\n /**\n * Imports repository state from an exported repository.\n *\n * @param repository - The exported repository state to import\n */\n import({ headId, messages }: ExportedMessageRepository) {\n for (const { message, parentId } of messages) {\n this.addOrUpdateMessage(parentId, message);\n }\n\n // switch to the saved head id if it is not the most recent message\n this.resetHead(headId ?? messages.at(-1)?.message.id ?? null);\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/runtimes/utils/MessageRepository.tsx"],"sourcesContent":["import type { ThreadMessage } from \"../../types\";\nimport { generateId, generateOptimisticId } from \"../../utils/idUtils\";\nimport { ThreadMessageLike } from \"../external-store\";\nimport { getAutoStatus } from \"../external-store/auto-status\";\nimport { fromThreadMessageLike } from \"../external-store/ThreadMessageLike\";\n\n/**\n * Represents a parent node in the repository tree structure.\n */\ntype RepositoryParent = {\n /** IDs of child messages */\n children: string[];\n /** Reference to the next message in the active branch */\n next: RepositoryMessage | null;\n};\n\n/**\n * Represents a message node in the repository tree structure.\n */\ntype RepositoryMessage = RepositoryParent & {\n /** Reference to the parent message */\n prev: RepositoryMessage | null;\n /** The actual message data */\n current: ThreadMessage;\n /** The depth level in the tree (0 for root messages) */\n level: number;\n};\n\n/**\n * Represents a message item that can be exported from the repository.\n */\nexport type ExportedMessageRepositoryItem = {\n /** The message data */\n message: ThreadMessage;\n /** ID of the parent message, or null for root messages */\n parentId: string | null;\n};\n\n/**\n * Represents the entire repository state for export/import.\n */\nexport type ExportedMessageRepository = {\n /** ID of the head message, or null/undefined if no head */\n headId?: string | null;\n /** Array of all messages with their parent references */\n messages: Array<{\n message: ThreadMessage;\n parentId: string | null;\n }>;\n};\n\n/**\n * Utility functions for working with exported message repositories.\n */\nexport const ExportedMessageRepository = {\n /**\n * Converts an array of messages to an ExportedMessageRepository format.\n * Creates parent-child relationships based on the order of messages in the array.\n *\n * @param messages - Array of message-like objects to convert\n * @returns ExportedMessageRepository with parent-child relationships established\n */\n fromArray: (\n messages: readonly ThreadMessageLike[],\n ): ExportedMessageRepository => {\n const conv = messages.map((m) =>\n fromThreadMessageLike(\n m,\n generateId(),\n getAutoStatus(false, false, false),\n ),\n );\n\n return {\n messages: conv.map((m, idx) => ({\n parentId: idx > 0 ? conv[idx - 1]!.id : null,\n message: m,\n })),\n };\n },\n};\n\n/**\n * Recursively finds the head (leaf) message in a branch.\n *\n * @param message - The starting message or parent node\n * @returns The leaf message of the branch, or null if not found\n */\nconst findHead = (\n message: RepositoryMessage | RepositoryParent,\n): RepositoryMessage | null => {\n if (message.next) return findHead(message.next);\n if (\"current\" in message) return message;\n return null;\n};\n\n/**\n * A utility class for caching computed values and invalidating the cache when needed.\n */\nclass CachedValue<T> {\n private _value: T | null = null;\n\n /**\n * @param func - The function that computes the cached value\n */\n constructor(private func: () => T) {}\n\n /**\n * Gets the cached value, computing it if necessary.\n */\n get value() {\n if (this._value === null) {\n this._value = this.func();\n }\n return this._value;\n }\n\n /**\n * Invalidates the cache, forcing recomputation on next access.\n */\n dirty() {\n this._value = null;\n }\n}\n\n/**\n * A repository that manages a tree of messages with branching capabilities.\n * Supports operations like adding, updating, and deleting messages, as well as\n * managing multiple conversation branches.\n */\nexport class MessageRepository {\n /** Map of message IDs to repository message objects */\n private messages = new Map<string, RepositoryMessage>();\n /** Reference to the current head (most recent) message in the active branch */\n private head: RepositoryMessage | null = null;\n /** Root node of the tree structure */\n private root: RepositoryParent = {\n children: [],\n next: null,\n };\n\n /**\n * Performs link/unlink operations between messages in the tree.\n *\n * @param newParent - The new parent message, or null\n * @param child - The child message to operate on\n * @param operation - The type of operation to perform:\n * - \"cut\": Remove the child from its current parent\n * - \"link\": Add the child to a new parent\n * - \"relink\": Both cut and link operations\n */\n private performOp(\n newParent: RepositoryMessage | null,\n child: RepositoryMessage,\n operation: \"cut\" | \"link\" | \"relink\",\n ) {\n const parentOrRoot = child.prev ?? this.root;\n const newParentOrRoot = newParent ?? this.root;\n\n if (operation === \"relink\" && parentOrRoot === newParentOrRoot) return;\n\n // cut\n if (operation !== \"link\") {\n // remove from parentOrRoot.children\n parentOrRoot.children = parentOrRoot.children.filter(\n (m) => m !== child.current.id,\n );\n\n // update parentOrRoot.next\n if (parentOrRoot.next === child) {\n const fallbackId = parentOrRoot.children.at(-1);\n const fallback = fallbackId ? this.messages.get(fallbackId) : null;\n if (fallback === undefined) {\n throw new Error(\n \"MessageRepository(performOp/cut): Fallback sibling message not found. This is likely an internal bug in assistant-ui.\",\n );\n }\n parentOrRoot.next = fallback;\n }\n }\n\n // link\n if (operation !== \"cut\") {\n // ensure the child is not part of parent tree\n for (\n let current: RepositoryMessage | null = newParent;\n current;\n current = current.prev\n ) {\n if (current.current.id === child.current.id) {\n throw new Error(\n \"MessageRepository(performOp/link): A message with the same id already exists in the parent tree. This error occurs if the same message id is found multiple times. This is likely an internal bug in assistant-ui.\",\n );\n }\n }\n\n // add to parentOrRoot.children\n newParentOrRoot.children = [\n ...newParentOrRoot.children,\n child.current.id,\n ];\n\n // update parentOrRoot.next\n if (findHead(child) === this.head || newParentOrRoot.next === null) {\n newParentOrRoot.next = child;\n }\n\n child.prev = newParent;\n }\n }\n\n /** Cached array of messages in the current active branch, from root to head */\n private _messages = new CachedValue<readonly ThreadMessage[]>(() => {\n const messages = new Array<ThreadMessage>(this.head?.level ?? 0);\n for (let current = this.head; current; current = current.prev) {\n messages[current.level] = current.current;\n }\n return messages;\n });\n\n /**\n * Gets the ID of the current head message.\n * @returns The ID of the head message, or null if no messages exist\n */\n get headId() {\n return this.head?.current.id ?? null;\n }\n\n /**\n * Gets all messages in the current active branch, from root to head.\n * @returns Array of messages in the current branch\n */\n getMessages() {\n return this._messages.value;\n }\n\n /**\n * Adds a new message or updates an existing one in the repository.\n * If the message ID already exists, the message is updated and potentially relinked to a new parent.\n * If the message is new, it's added as a child of the specified parent.\n *\n * @param parentId - ID of the parent message, or null for root messages\n * @param message - The message to add or update\n * @throws Error if the parent message is not found\n */\n addOrUpdateMessage(parentId: string | null, message: ThreadMessage) {\n const existingItem = this.messages.get(message.id);\n const prev = parentId ? this.messages.get(parentId) : null;\n if (prev === undefined)\n throw new Error(\n \"MessageRepository(addOrUpdateMessage): Parent message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n // update existing message\n if (existingItem) {\n existingItem.current = message;\n this.performOp(prev, existingItem, \"relink\");\n this._messages.dirty();\n return;\n }\n\n // create a new message\n const newItem: RepositoryMessage = {\n prev,\n current: message,\n next: null,\n children: [],\n level: prev ? prev.level + 1 : 0,\n };\n\n this.messages.set(message.id, newItem);\n this.performOp(prev, newItem, \"link\");\n\n if (this.head === prev) {\n this.head = newItem;\n }\n\n this._messages.dirty();\n }\n\n /**\n * Gets a message and its parent ID by message ID.\n *\n * @param messageId - ID of the message to retrieve\n * @returns Object containing the message and its parent ID\n * @throws Error if the message is not found\n */\n getMessage(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(updateMessage): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n return {\n parentId: message.prev?.current.id ?? null,\n message: message.current,\n };\n }\n\n /**\n * Adds an optimistic message to the repository.\n * An optimistic message is a temporary placeholder that will be replaced by a real message later.\n *\n * @param parentId - ID of the parent message, or null for root messages\n * @param message - The core message to convert to an optimistic message\n * @returns The generated optimistic ID\n */\n appendOptimisticMessage(parentId: string | null, message: ThreadMessageLike) {\n let optimisticId: string;\n do {\n optimisticId = generateOptimisticId();\n } while (this.messages.has(optimisticId));\n\n this.addOrUpdateMessage(\n parentId,\n fromThreadMessageLike(message, optimisticId, { type: \"running\" }),\n );\n\n return optimisticId;\n }\n\n /**\n * Deletes a message from the repository and relinks its children.\n *\n * @param messageId - ID of the message to delete\n * @param replacementId - Optional ID of the message to become the new parent of the children,\n * undefined means use the deleted message's parent,\n * null means use the root\n * @throws Error if the message or replacement is not found\n */\n deleteMessage(messageId: string, replacementId?: string | null | undefined) {\n const message = this.messages.get(messageId);\n\n if (!message)\n throw new Error(\n \"MessageRepository(deleteMessage): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const replacement =\n replacementId === undefined\n ? message.prev // if no replacementId is provided, use the parent\n : replacementId === null\n ? null\n : this.messages.get(replacementId);\n if (replacement === undefined)\n throw new Error(\n \"MessageRepository(deleteMessage): Replacement not found. This is likely an internal bug in assistant-ui.\",\n );\n\n for (const child of message.children) {\n const childMessage = this.messages.get(child);\n if (!childMessage)\n throw new Error(\n \"MessageRepository(deleteMessage): Child message not found. This is likely an internal bug in assistant-ui.\",\n );\n this.performOp(replacement, childMessage, \"relink\");\n }\n\n this.performOp(null, message, \"cut\");\n this.messages.delete(messageId);\n\n if (this.head === message) {\n this.head = findHead(replacement ?? this.root);\n }\n\n this._messages.dirty();\n }\n\n /**\n * Gets all branch IDs (sibling messages) at the level of a specified message.\n *\n * @param messageId - ID of the message to find branches for\n * @returns Array of message IDs representing branches\n * @throws Error if the message is not found\n */\n getBranches(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(getBranches): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const { children } = message.prev ?? this.root;\n return children;\n }\n\n /**\n * Switches the active branch to the one containing the specified message.\n *\n * @param messageId - ID of the message in the branch to switch to\n * @throws Error if the branch is not found\n */\n switchToBranch(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(switchToBranch): Branch not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const prevOrRoot = message.prev ?? this.root;\n prevOrRoot.next = message;\n\n this.head = findHead(message);\n\n this._messages.dirty();\n }\n\n /**\n * Resets the head to a specific message or null.\n *\n * @param messageId - ID of the message to set as head, or null to clear the head\n * @throws Error if the message is not found\n */\n resetHead(messageId: string | null) {\n if (messageId === null) {\n this.head = null;\n this._messages.dirty();\n return;\n }\n\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(resetHead): Branch not found. This is likely an internal bug in assistant-ui.\",\n );\n\n this.head = message;\n for (\n let current: RepositoryMessage | null = message;\n current;\n current = current.prev\n ) {\n if (current.prev) {\n current.prev.next = current;\n }\n }\n\n this._messages.dirty();\n }\n\n /**\n * Clears all messages from the repository.\n */\n clear(): void {\n this.messages.clear();\n this.head = null;\n this.root = {\n children: [],\n next: null,\n };\n this._messages.dirty();\n }\n\n /**\n * Exports the repository state for persistence.\n *\n * @returns Exportable repository state\n */\n export(): ExportedMessageRepository {\n const exportItems: ExportedMessageRepository[\"messages\"] = [];\n\n // hint: we are relying on the insertion order of the messages\n // this is important for the import function to properly link the messages\n for (const [, message] of this.messages) {\n exportItems.push({\n message: message.current,\n parentId: message.prev?.current.id ?? null,\n });\n }\n\n return {\n headId: this.head?.current.id ?? null,\n messages: exportItems,\n };\n }\n\n /**\n * Imports repository state from an exported repository.\n *\n * @param repository - The exported repository state to import\n */\n import({ headId, messages }: ExportedMessageRepository) {\n for (const { message, parentId } of messages) {\n this.addOrUpdateMessage(parentId, message);\n }\n\n // switch to the saved head id if it is not the most recent message\n this.resetHead(headId ?? messages.at(-1)?.message.id ?? null);\n }\n}\n"],"mappings":";AACA,SAAS,YAAY,4BAA4B;AAEjD,SAAS,qBAAqB;AAC9B,SAAS,6BAA6B;AAkD/B,IAAM,4BAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQvC,WAAW,CACT,aAC8B;AAC9B,UAAM,OAAO,SAAS;AAAA,MAAI,CAAC,MACzB;AAAA,QACE;AAAA,QACA,WAAW;AAAA,QACX,cAAc,OAAO,OAAO,KAAK;AAAA,MACnC;AAAA,IACF;AAEA,WAAO;AAAA,MACL,UAAU,KAAK,IAAI,CAAC,GAAG,SAAS;AAAA,QAC9B,UAAU,MAAM,IAAI,KAAK,MAAM,CAAC,EAAG,KAAK;AAAA,QACxC,SAAS;AAAA,MACX,EAAE;AAAA,IACJ;AAAA,EACF;AACF;AAQA,IAAM,WAAW,CACf,YAC6B;AAC7B,MAAI,QAAQ,KAAM,QAAO,SAAS,QAAQ,IAAI;AAC9C,MAAI,aAAa,QAAS,QAAO;AACjC,SAAO;AACT;AAKA,IAAM,cAAN,MAAqB;AAAA;AAAA;AAAA;AAAA,EAMnB,YAAoB,MAAe;AAAf;AAAA,EAAgB;AAAA,EAL5B,SAAmB;AAAA;AAAA;AAAA;AAAA,EAU3B,IAAI,QAAQ;AACV,QAAI,KAAK,WAAW,MAAM;AACxB,WAAK,SAAS,KAAK,KAAK;AAAA,IAC1B;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ;AACN,SAAK,SAAS;AAAA,EAChB;AACF;AAOO,IAAM,oBAAN,MAAwB;AAAA;AAAA,EAErB,WAAW,oBAAI,IAA+B;AAAA;AAAA,EAE9C,OAAiC;AAAA;AAAA,EAEjC,OAAyB;AAAA,IAC/B,UAAU,CAAC;AAAA,IACX,MAAM;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,UACN,WACA,OACA,WACA;AACA,UAAM,eAAe,MAAM,QAAQ,KAAK;AACxC,UAAM,kBAAkB,aAAa,KAAK;AAE1C,QAAI,cAAc,YAAY,iBAAiB,gBAAiB;AAGhE,QAAI,cAAc,QAAQ;AAExB,mBAAa,WAAW,aAAa,SAAS;AAAA,QAC5C,CAAC,MAAM,MAAM,MAAM,QAAQ;AAAA,MAC7B;AAGA,UAAI,aAAa,SAAS,OAAO;AAC/B,cAAM,aAAa,aAAa,SAAS,GAAG,EAAE;AAC9C,cAAM,WAAW,aAAa,KAAK,SAAS,IAAI,UAAU,IAAI;AAC9D,YAAI,aAAa,QAAW;AAC1B,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AACA,qBAAa,OAAO;AAAA,MACtB;AAAA,IACF;AAGA,QAAI,cAAc,OAAO;AAEvB,eACM,UAAoC,WACxC,SACA,UAAU,QAAQ,MAClB;AACA,YAAI,QAAQ,QAAQ,OAAO,MAAM,QAAQ,IAAI;AAC3C,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,sBAAgB,WAAW;AAAA,QACzB,GAAG,gBAAgB;AAAA,QACnB,MAAM,QAAQ;AAAA,MAChB;AAGA,UAAI,SAAS,KAAK,MAAM,KAAK,QAAQ,gBAAgB,SAAS,MAAM;AAClE,wBAAgB,OAAO;AAAA,MACzB;AAEA,YAAM,OAAO;AAAA,IACf;AAAA,EACF;AAAA;AAAA,EAGQ,YAAY,IAAI,YAAsC,MAAM;AAClE,UAAM,WAAW,IAAI,MAAqB,KAAK,MAAM,SAAS,CAAC;AAC/D,aAAS,UAAU,KAAK,MAAM,SAAS,UAAU,QAAQ,MAAM;AAC7D,eAAS,QAAQ,KAAK,IAAI,QAAQ;AAAA,IACpC;AACA,WAAO;AAAA,EACT,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMD,IAAI,SAAS;AACX,WAAO,KAAK,MAAM,QAAQ,MAAM;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc;AACZ,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,mBAAmB,UAAyB,SAAwB;AAClE,UAAM,eAAe,KAAK,SAAS,IAAI,QAAQ,EAAE;AACjD,UAAM,OAAO,WAAW,KAAK,SAAS,IAAI,QAAQ,IAAI;AACtD,QAAI,SAAS;AACX,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAGF,QAAI,cAAc;AAChB,mBAAa,UAAU;AACvB,WAAK,UAAU,MAAM,cAAc,QAAQ;AAC3C,WAAK,UAAU,MAAM;AACrB;AAAA,IACF;AAGA,UAAM,UAA6B;AAAA,MACjC;AAAA,MACA,SAAS;AAAA,MACT,MAAM;AAAA,MACN,UAAU,CAAC;AAAA,MACX,OAAO,OAAO,KAAK,QAAQ,IAAI;AAAA,IACjC;AAEA,SAAK,SAAS,IAAI,QAAQ,IAAI,OAAO;AACrC,SAAK,UAAU,MAAM,SAAS,MAAM;AAEpC,QAAI,KAAK,SAAS,MAAM;AACtB,WAAK,OAAO;AAAA,IACd;AAEA,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WAAW,WAAmB;AAC5B,UAAM,UAAU,KAAK,SAAS,IAAI,SAAS;AAC3C,QAAI,CAAC;AACH,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAEF,WAAO;AAAA,MACL,UAAU,QAAQ,MAAM,QAAQ,MAAM;AAAA,MACtC,SAAS,QAAQ;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,wBAAwB,UAAyB,SAA4B;AAC3E,QAAI;AACJ,OAAG;AACD,qBAAe,qBAAqB;AAAA,IACtC,SAAS,KAAK,SAAS,IAAI,YAAY;AAEvC,SAAK;AAAA,MACH;AAAA,MACA,sBAAsB,SAAS,cAAc,EAAE,MAAM,UAAU,CAAC;AAAA,IAClE;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,cAAc,WAAmB,eAA2C;AAC1E,UAAM,UAAU,KAAK,SAAS,IAAI,SAAS;AAE3C,QAAI,CAAC;AACH,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAEF,UAAM,cACJ,kBAAkB,SACd,QAAQ,OACR,kBAAkB,OAChB,OACA,KAAK,SAAS,IAAI,aAAa;AACvC,QAAI,gBAAgB;AAClB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAEF,eAAW,SAAS,QAAQ,UAAU;AACpC,YAAM,eAAe,KAAK,SAAS,IAAI,KAAK;AAC5C,UAAI,CAAC;AACH,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AACF,WAAK,UAAU,aAAa,cAAc,QAAQ;AAAA,IACpD;AAEA,SAAK,UAAU,MAAM,SAAS,KAAK;AACnC,SAAK,SAAS,OAAO,SAAS;AAE9B,QAAI,KAAK,SAAS,SAAS;AACzB,WAAK,OAAO,SAAS,eAAe,KAAK,IAAI;AAAA,IAC/C;AAEA,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YAAY,WAAmB;AAC7B,UAAM,UAAU,KAAK,SAAS,IAAI,SAAS;AAC3C,QAAI,CAAC;AACH,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAEF,UAAM,EAAE,SAAS,IAAI,QAAQ,QAAQ,KAAK;AAC1C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,eAAe,WAAmB;AAChC,UAAM,UAAU,KAAK,SAAS,IAAI,SAAS;AAC3C,QAAI,CAAC;AACH,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAEF,UAAM,aAAa,QAAQ,QAAQ,KAAK;AACxC,eAAW,OAAO;AAElB,SAAK,OAAO,SAAS,OAAO;AAE5B,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAU,WAA0B;AAClC,QAAI,cAAc,MAAM;AACtB,WAAK,OAAO;AACZ,WAAK,UAAU,MAAM;AACrB;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,SAAS,IAAI,SAAS;AAC3C,QAAI,CAAC;AACH,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAEF,SAAK,OAAO;AACZ,aACM,UAAoC,SACxC,SACA,UAAU,QAAQ,MAClB;AACA,UAAI,QAAQ,MAAM;AAChB,gBAAQ,KAAK,OAAO;AAAA,MACtB;AAAA,IACF;AAEA,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,SAAS,MAAM;AACpB,SAAK,OAAO;AACZ,SAAK,OAAO;AAAA,MACV,UAAU,CAAC;AAAA,MACX,MAAM;AAAA,IACR;AACA,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAoC;AAClC,UAAM,cAAqD,CAAC;AAI5D,eAAW,CAAC,EAAE,OAAO,KAAK,KAAK,UAAU;AACvC,kBAAY,KAAK;AAAA,QACf,SAAS,QAAQ;AAAA,QACjB,UAAU,QAAQ,MAAM,QAAQ,MAAM;AAAA,MACxC,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,QAAQ,KAAK,MAAM,QAAQ,MAAM;AAAA,MACjC,UAAU;AAAA,IACZ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,EAAE,QAAQ,SAAS,GAA8B;AACtD,eAAW,EAAE,SAAS,SAAS,KAAK,UAAU;AAC5C,WAAK,mBAAmB,UAAU,OAAO;AAAA,IAC3C;AAGA,SAAK,UAAU,UAAU,SAAS,GAAG,EAAE,GAAG,QAAQ,MAAM,IAAI;AAAA,EAC9D;AACF;","names":[]}
package/package.json CHANGED
@@ -28,7 +28,7 @@
28
28
  "conversational-ui",
29
29
  "conversational-ai"
30
30
  ],
31
- "version": "0.10.37",
31
+ "version": "0.10.39",
32
32
  "license": "MIT",
33
33
  "type": "module",
34
34
  "exports": {
@@ -5,6 +5,46 @@ import { ExportedMessageRepositoryItem } from "../runtimes/utils/MessageReposito
5
5
  import { AssistantCloud } from "assistant-cloud";
6
6
  import { auiV0Decode, auiV0Encode } from "./auiV0";
7
7
  import { ThreadListItemRuntime } from "../api";
8
+ import {
9
+ MessageFormatAdapter,
10
+ MessageFormatItem,
11
+ MessageFormatRepository,
12
+ MessageStorageEntry,
13
+ } from "../runtimes/adapters/thread-history/MessageFormatAdapter";
14
+ import { GenericThreadHistoryAdapter } from "../runtimes/adapters/thread-history/ThreadHistoryAdapter";
15
+ import { ReadonlyJSONObject } from "assistant-stream/utils";
16
+
17
+ class FormattedThreadHistoryAdapter<TMessage, TStorageFormat>
18
+ implements GenericThreadHistoryAdapter<TMessage>
19
+ {
20
+ constructor(
21
+ private parent: AssistantCloudThreadHistoryAdapter,
22
+ private formatAdapter: MessageFormatAdapter<TMessage, TStorageFormat>,
23
+ ) {}
24
+
25
+ async append(item: MessageFormatItem<TMessage>) {
26
+ // Encode the message using the format adapter
27
+ const encoded = this.formatAdapter.encode(item);
28
+ const messageId = this.formatAdapter.getId(item.message);
29
+
30
+ // Delegate to parent's internal append method with the encoded format
31
+ return this.parent._appendWithFormat(
32
+ item.parentId,
33
+ messageId,
34
+ this.formatAdapter.format,
35
+ encoded,
36
+ );
37
+ }
38
+
39
+ async load(): Promise<MessageFormatRepository<TMessage>> {
40
+ // Delegate to parent's internal load method with format filter
41
+ return this.parent._loadWithFormat(
42
+ this.formatAdapter.format,
43
+ (message: MessageStorageEntry<TStorageFormat>) =>
44
+ this.formatAdapter.decode(message),
45
+ );
46
+ }
47
+ }
8
48
 
9
49
  class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
10
50
  constructor(
@@ -14,6 +54,12 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
14
54
 
15
55
  private _getIdForLocalId: Record<string, string | Promise<string>> = {};
16
56
 
57
+ withFormat<TMessage, TStorageFormat>(
58
+ formatAdapter: MessageFormatAdapter<TMessage, TStorageFormat>,
59
+ ): GenericThreadHistoryAdapter<TMessage> {
60
+ return new FormattedThreadHistoryAdapter(this, formatAdapter);
61
+ }
62
+
17
63
  async append({ parentId, message }: ExportedMessageRepositoryItem) {
18
64
  const { remoteId } = await this.threadListItemRuntime.initialize();
19
65
  const task = this.cloudRef.current.threads.messages
@@ -49,6 +95,60 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
49
95
  };
50
96
  return payload;
51
97
  }
98
+
99
+ // Internal methods for FormattedThreadHistoryAdapter
100
+ async _appendWithFormat<T>(
101
+ parentId: string | null,
102
+ messageId: string,
103
+ format: string,
104
+ content: T,
105
+ ) {
106
+ const { remoteId } = await this.threadListItemRuntime.initialize();
107
+
108
+ const task = this.cloudRef.current.threads.messages
109
+ .create(remoteId, {
110
+ parent_id: parentId
111
+ ? ((await this._getIdForLocalId[parentId]) ?? parentId)
112
+ : null,
113
+ format,
114
+ content: content as ReadonlyJSONObject,
115
+ })
116
+ .then(({ message_id }) => {
117
+ this._getIdForLocalId[messageId] = message_id;
118
+ return message_id;
119
+ });
120
+
121
+ this._getIdForLocalId[messageId] = task;
122
+
123
+ return task.then(() => {});
124
+ }
125
+
126
+ async _loadWithFormat<TMessage, TStorageFormat>(
127
+ format: string,
128
+ decoder: (
129
+ message: MessageStorageEntry<TStorageFormat>,
130
+ ) => MessageFormatItem<TMessage>,
131
+ ): Promise<MessageFormatRepository<TMessage>> {
132
+ const remoteId = this.threadListItemRuntime.getState().remoteId;
133
+ if (!remoteId) return { messages: [] };
134
+
135
+ const { messages } =
136
+ await this.cloudRef.current.threads.messages.list(remoteId);
137
+
138
+ return {
139
+ messages: messages
140
+ .filter((m) => m.format === format)
141
+ .map((m) =>
142
+ decoder({
143
+ id: m.id,
144
+ parent_id: m.parent_id,
145
+ format: m.format,
146
+ content: m.content as TStorageFormat,
147
+ }),
148
+ )
149
+ .reverse(),
150
+ };
151
+ }
52
152
  }
53
153
 
54
154
  export const useAssistantCloudThreadHistoryAdapter = (
@@ -3,4 +3,4 @@ export * from "./feedback";
3
3
  export * from "./speech";
4
4
  export * from "./suggestion";
5
5
  export * from "./RuntimeAdapterProvider";
6
- export * from "./thread-history/ThreadHistoryAdapter";
6
+ export * from "./thread-history";
@@ -0,0 +1,25 @@
1
+ export interface MessageStorageEntry<TPayload> {
2
+ id: string;
3
+ parent_id: string | null;
4
+ format: string;
5
+ content: TPayload;
6
+ }
7
+
8
+ export interface MessageFormatItem<TMessage> {
9
+ parentId: string | null;
10
+ message: TMessage;
11
+ }
12
+
13
+ export interface MessageFormatRepository<TMessage> {
14
+ headId?: string | null;
15
+ messages: MessageFormatItem<TMessage>[];
16
+ }
17
+
18
+ export interface MessageFormatAdapter<TMessage, TStorageFormat> {
19
+ format: string;
20
+ encode(item: MessageFormatItem<TMessage>): TStorageFormat;
21
+ decode(
22
+ stored: MessageStorageEntry<TStorageFormat>,
23
+ ): MessageFormatItem<TMessage>;
24
+ getId(message: TMessage): string;
25
+ }
@@ -3,6 +3,16 @@ import {
3
3
  ExportedMessageRepository,
4
4
  ExportedMessageRepositoryItem,
5
5
  } from "../../utils/MessageRepository";
6
+ import {
7
+ MessageFormatAdapter,
8
+ MessageFormatItem,
9
+ MessageFormatRepository,
10
+ } from "./MessageFormatAdapter";
11
+
12
+ export type GenericThreadHistoryAdapter<TMessage> = {
13
+ load(): Promise<MessageFormatRepository<TMessage>>;
14
+ append(item: MessageFormatItem<TMessage>): Promise<void>;
15
+ };
6
16
 
7
17
  export type ThreadHistoryAdapter = {
8
18
  load(): Promise<ExportedMessageRepository & { unstable_resume?: boolean }>;
@@ -10,4 +20,7 @@ export type ThreadHistoryAdapter = {
10
20
  options: ChatModelRunOptions,
11
21
  ): AsyncGenerator<ChatModelRunResult, void, unknown>;
12
22
  append(item: ExportedMessageRepositoryItem): Promise<void>;
23
+ withFormat?<TMessage, TStorageFormat>(
24
+ formatAdapter: MessageFormatAdapter<TMessage, TStorageFormat>,
25
+ ): GenericThreadHistoryAdapter<TMessage>;
13
26
  };
@@ -0,0 +1,2 @@
1
+ export * from "./MessageFormatAdapter";
2
+ export * from "./ThreadHistoryAdapter";
@@ -150,7 +150,7 @@ export class ExternalStoreThreadRuntimeCore
150
150
  if (!store.convertMessage) return m;
151
151
 
152
152
  const isLast = idx === store.messages!.length - 1;
153
- const autoStatus = getAutoStatus(isLast, isRunning);
153
+ const autoStatus = getAutoStatus(isLast, isRunning, false);
154
154
 
155
155
  if (
156
156
  cache &&
@@ -6,8 +6,21 @@ const AUTO_STATUS_COMPLETE = Object.freeze({
6
6
  reason: "unknown",
7
7
  });
8
8
 
9
+ const AUTO_STATUS_PENDING = Object.freeze({
10
+ type: "requires-action",
11
+ reason: "tool-calls",
12
+ });
13
+
9
14
  export const isAutoStatus = (status: MessageStatus) =>
10
15
  status === AUTO_STATUS_RUNNING || status === AUTO_STATUS_COMPLETE;
11
16
 
12
- export const getAutoStatus = (isLast: boolean, isRunning: boolean) =>
13
- isLast && isRunning ? AUTO_STATUS_RUNNING : AUTO_STATUS_COMPLETE;
17
+ export const getAutoStatus = (
18
+ isLast: boolean,
19
+ isRunning: boolean,
20
+ hasPendingToolCalls: boolean,
21
+ ) =>
22
+ isLast && isRunning
23
+ ? AUTO_STATUS_RUNNING
24
+ : hasPendingToolCalls
25
+ ? AUTO_STATUS_PENDING
26
+ : AUTO_STATUS_COMPLETE;
@@ -231,9 +231,15 @@ export const convertExternalMessages = <T extends WeakKey>(
231
231
 
232
232
  return chunks.map((message, idx) => {
233
233
  const isLast = idx === chunks.length - 1;
234
- const autoStatus = getAutoStatus(isLast, isRunning);
234
+ const joined = joinExternalMessages(message.outputs);
235
+ const hasPendingToolCalls =
236
+ typeof joined.content === "object" &&
237
+ joined.content.some(
238
+ (c) => c.type === "tool-call" && c.result === undefined,
239
+ );
240
+ const autoStatus = getAutoStatus(isLast, isRunning, hasPendingToolCalls);
235
241
  const newMessage = fromThreadMessageLike(
236
- joinExternalMessages(message.outputs),
242
+ joined,
237
243
  idx.toString(),
238
244
  autoStatus,
239
245
  );
@@ -296,7 +302,18 @@ export const useExternalMessageConverter = <T extends WeakKey>({
296
302
  chunks,
297
303
  (cache, message, idx) => {
298
304
  const isLast = idx === chunks.length - 1;
299
- const autoStatus = getAutoStatus(isLast, isRunning);
305
+
306
+ const joined = joinExternalMessages(message.outputs);
307
+ const hasPendingToolCalls =
308
+ typeof joined.content === "object" &&
309
+ joined.content.some(
310
+ (c) => c.type === "tool-call" && c.result === undefined,
311
+ );
312
+ const autoStatus = getAutoStatus(
313
+ isLast,
314
+ isRunning,
315
+ hasPendingToolCalls,
316
+ );
300
317
 
301
318
  if (
302
319
  cache &&
@@ -311,7 +328,7 @@ export const useExternalMessageConverter = <T extends WeakKey>({
311
328
  }
312
329
 
313
330
  const newMessage = fromThreadMessageLike(
314
- joinExternalMessages(message.outputs),
331
+ joined,
315
332
  idx.toString(),
316
333
  autoStatus,
317
334
  );
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import {
2
4
  FC,
3
5
  PropsWithChildren,
@@ -2,3 +2,4 @@ export { useRemoteThreadListRuntime as unstable_useRemoteThreadListRuntime } fro
2
2
  export type { RemoteThreadListAdapter as unstable_RemoteThreadListAdapter } from "./types";
3
3
 
4
4
  export { InMemoryThreadListAdapter as unstable_InMemoryThreadListAdapter } from "./adapter/in-memory";
5
+ export { useCloudThreadListAdapter as unstable_useCloudThreadListAdapter } from "./adapter/cloud";
@@ -64,7 +64,11 @@ export const ExportedMessageRepository = {
64
64
  messages: readonly ThreadMessageLike[],
65
65
  ): ExportedMessageRepository => {
66
66
  const conv = messages.map((m) =>
67
- fromThreadMessageLike(m, generateId(), getAutoStatus(false, false)),
67
+ fromThreadMessageLike(
68
+ m,
69
+ generateId(),
70
+ getAutoStatus(false, false, false),
71
+ ),
68
72
  );
69
73
 
70
74
  return {