@assistant-ui/core 0.3.4 → 0.3.6

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 (147) hide show
  1. package/dist/index.d.ts +3 -3
  2. package/dist/index.js.map +1 -1
  3. package/dist/internal.js +1 -1
  4. package/dist/react/AssistantProvider.d.ts +3 -2
  5. package/dist/react/AssistantProvider.d.ts.map +1 -1
  6. package/dist/react/AssistantProvider.js +19 -26
  7. package/dist/react/AssistantProvider.js.map +1 -1
  8. package/dist/react/AssistantRuntimeProvider.d.ts +7 -2
  9. package/dist/react/AssistantRuntimeProvider.d.ts.map +1 -1
  10. package/dist/react/AssistantRuntimeProvider.js +9 -7
  11. package/dist/react/AssistantRuntimeProvider.js.map +1 -1
  12. package/dist/react/providers/AttachmentByIndexProvider.d.ts.map +1 -1
  13. package/dist/react/providers/AttachmentByIndexProvider.js +33 -39
  14. package/dist/react/providers/AttachmentByIndexProvider.js.map +1 -1
  15. package/dist/react/providers/ChainOfThoughtByIndicesProvider.d.ts.map +1 -1
  16. package/dist/react/providers/ChainOfThoughtByIndicesProvider.js +15 -20
  17. package/dist/react/providers/ChainOfThoughtByIndicesProvider.js.map +1 -1
  18. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.js +17 -20
  19. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.js.map +1 -1
  20. package/dist/react/providers/MessageByIdProvider.js +28 -38
  21. package/dist/react/providers/MessageByIdProvider.js.map +1 -1
  22. package/dist/react/providers/MessageByIndexProvider.js +28 -38
  23. package/dist/react/providers/MessageByIndexProvider.js.map +1 -1
  24. package/dist/react/providers/PartByIndexProvider.js +17 -20
  25. package/dist/react/providers/PartByIndexProvider.js.map +1 -1
  26. package/dist/react/providers/QueueItemByIndexProvider.js +21 -21
  27. package/dist/react/providers/QueueItemByIndexProvider.js.map +1 -1
  28. package/dist/react/providers/ReadonlyThreadProvider.js +24 -32
  29. package/dist/react/providers/ReadonlyThreadProvider.js.map +1 -1
  30. package/dist/react/providers/SuggestionByIndexProvider.js +17 -20
  31. package/dist/react/providers/SuggestionByIndexProvider.js.map +1 -1
  32. package/dist/react/providers/TextMessagePartProvider.d.ts.map +1 -1
  33. package/dist/react/providers/TextMessagePartProvider.js +16 -19
  34. package/dist/react/providers/TextMessagePartProvider.js.map +1 -1
  35. package/dist/react/providers/ThreadListItemByIndexProvider.js +17 -20
  36. package/dist/react/providers/ThreadListItemByIndexProvider.js.map +1 -1
  37. package/dist/react/providers/ThreadListItemRuntimeProvider.js +15 -18
  38. package/dist/react/providers/ThreadListItemRuntimeProvider.js.map +1 -1
  39. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +7 -3
  40. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  41. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +5 -2
  42. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  43. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +4 -3
  44. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  45. package/dist/react/runtimes/useLocalRuntime.d.ts +3 -1
  46. package/dist/react/runtimes/useLocalRuntime.d.ts.map +1 -1
  47. package/dist/react/runtimes/useLocalRuntime.js +4 -2
  48. package/dist/react/runtimes/useLocalRuntime.js.map +1 -1
  49. package/dist/runtime/api/composer-runtime.d.ts +5 -1
  50. package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
  51. package/dist/runtime/api/composer-runtime.js +8 -1
  52. package/dist/runtime/api/composer-runtime.js.map +1 -1
  53. package/dist/runtime/api/message-runtime.js +1 -1
  54. package/dist/runtime/api/message-runtime.js.map +1 -1
  55. package/dist/runtime/api/thread-runtime.d.ts +4 -2
  56. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  57. package/dist/runtime/base/base-composer-runtime-core.d.ts +2 -1
  58. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  59. package/dist/runtime/base/base-composer-runtime-core.js +1 -1
  60. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  61. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +3 -1
  62. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  63. package/dist/runtime/base/default-thread-composer-runtime-core.js +14 -3
  64. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  65. package/dist/runtime/interfaces/composer-runtime-core.d.ts +2 -1
  66. package/dist/runtime/interfaces/composer-runtime-core.d.ts.map +1 -1
  67. package/dist/runtime/interfaces/thread-runtime-core.d.ts +3 -1
  68. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  69. package/dist/runtime/queue/external-thread-queue-adapter.d.ts +19 -6
  70. package/dist/runtime/queue/external-thread-queue-adapter.d.ts.map +1 -1
  71. package/dist/runtime/queue/message-queue.d.ts +10 -1
  72. package/dist/runtime/queue/message-queue.d.ts.map +1 -1
  73. package/dist/runtime/queue/message-queue.js +138 -36
  74. package/dist/runtime/queue/message-queue.js.map +1 -1
  75. package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
  76. package/dist/runtime/utils/thread-message-like.js +2 -1
  77. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  78. package/dist/runtimes/external-store/external-store-adapter.d.ts +1 -1
  79. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +3 -1
  80. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  81. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +7 -6
  82. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  83. package/dist/runtimes/local/local-runtime-options.d.ts +13 -0
  84. package/dist/runtimes/local/local-runtime-options.d.ts.map +1 -1
  85. package/dist/runtimes/local/local-thread-runtime-core.d.ts +5 -1
  86. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  87. package/dist/runtimes/local/local-thread-runtime-core.js +30 -14
  88. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  89. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +1 -1
  90. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +1 -1
  91. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
  92. package/dist/runtimes/remote-thread-list/empty-thread-core.js +1 -1
  93. package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
  94. package/dist/runtimes/remote-thread-list/types.d.ts +6 -3
  95. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  96. package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
  97. package/dist/store/runtime-clients/composer-runtime-client.js +11 -4
  98. package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
  99. package/dist/store/scopes/composer.d.ts +7 -3
  100. package/dist/store/scopes/composer.d.ts.map +1 -1
  101. package/dist/store/scopes/queue-item.d.ts +10 -0
  102. package/dist/store/scopes/queue-item.d.ts.map +1 -1
  103. package/dist/store/scopes/queue-item.js.map +1 -1
  104. package/package.json +6 -6
  105. package/src/index.ts +5 -1
  106. package/src/react/AssistantProvider.tsx +20 -18
  107. package/src/react/AssistantRuntimeProvider.test.tsx +55 -1
  108. package/src/react/AssistantRuntimeProvider.tsx +12 -2
  109. package/src/react/providers/AttachmentByIndexProvider.tsx +15 -7
  110. package/src/react/providers/ChainOfThoughtByIndicesProvider.tsx +12 -4
  111. package/src/react/providers/ChainOfThoughtPartByIndexProvider.tsx +8 -4
  112. package/src/react/providers/MessageByIdProvider.tsx +8 -4
  113. package/src/react/providers/MessageByIndexProvider.tsx +8 -4
  114. package/src/react/providers/PartByIndexProvider.tsx +8 -4
  115. package/src/react/providers/QueueItemByIndexProvider.tsx +9 -5
  116. package/src/react/providers/ReadonlyThreadProvider.tsx +9 -4
  117. package/src/react/providers/SuggestionByIndexProvider.tsx +8 -4
  118. package/src/react/providers/TextMessagePartProvider.tsx +13 -4
  119. package/src/react/providers/ThreadListItemByIndexProvider.tsx +8 -4
  120. package/src/react/providers/ThreadListItemRuntimeProvider.tsx +8 -4
  121. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +23 -5
  122. package/src/react/runtimes/useLocalRuntime.ts +4 -0
  123. package/src/runtime/api/composer-runtime.ts +11 -2
  124. package/src/runtime/api/message-runtime.test.ts +25 -0
  125. package/src/runtime/api/message-runtime.ts +1 -1
  126. package/src/runtime/base/base-composer-runtime-core.ts +5 -1
  127. package/src/runtime/base/default-thread-composer-runtime-core.ts +27 -3
  128. package/src/runtime/interfaces/composer-runtime-core.ts +2 -1
  129. package/src/runtime/interfaces/thread-runtime-core.ts +3 -1
  130. package/src/runtime/queue/external-thread-queue-adapter.ts +19 -3
  131. package/src/runtime/queue/message-queue.ts +200 -38
  132. package/src/runtime/utils/thread-message-like.ts +2 -4
  133. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +10 -8
  134. package/src/runtimes/local/local-runtime-options.ts +15 -0
  135. package/src/runtimes/local/local-thread-runtime-core.test.ts +43 -0
  136. package/src/runtimes/local/local-thread-runtime-core.ts +48 -13
  137. package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +1 -1
  138. package/src/runtimes/remote-thread-list/empty-thread-core.ts +1 -1
  139. package/src/runtimes/remote-thread-list/types.ts +9 -2
  140. package/src/store/runtime-clients/composer-runtime-client.ts +13 -5
  141. package/src/store/scopes/composer.ts +6 -4
  142. package/src/store/scopes/queue-item.ts +8 -1
  143. package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-order.test.ts +31 -0
  144. package/src/tests/external-store-thread-runtime-core.test.ts +56 -13
  145. package/src/tests/framework-neutral-boundary.test.ts +221 -0
  146. package/src/tests/message-queue.test.ts +494 -34
  147. package/src/tests/thread-message-like.test.ts +66 -0
@@ -2,6 +2,7 @@ import { AppendMessage } from "../../types/message.js";
2
2
  import { AttachmentAdapter } from "../../adapters/attachment.js";
3
3
  import { Unsubscribe } from "../../types/unsubscribe.js";
4
4
  import { DictationAdapter } from "../../adapters/speech.js";
5
+ import { QueuePlacement } from "../queue/external-thread-queue-adapter.js";
5
6
  import { QueueItemState } from "../../store/scopes/queue-item.js";
6
7
  import { SendOptions, ThreadComposerRuntimeCore } from "../interfaces/composer-runtime-core.js";
7
8
  import { ThreadRuntimeCore } from "../interfaces/thread-runtime-core.js";
@@ -12,8 +13,9 @@ declare class DefaultThreadComposerRuntimeCore extends BaseComposerRuntimeCore i
12
13
  private _canCancel;
13
14
  get canCancel(): boolean;
14
15
  get canSend(): boolean;
16
+ private _queueCache;
15
17
  get queue(): readonly QueueItemState[];
16
- steerQueueItem(queueItemId: string): void;
18
+ moveQueueItem(queueItemId: string, placement: QueuePlacement): void;
17
19
  removeQueueItem(queueItemId: string): void;
18
20
  protected getAttachmentAdapter(): AttachmentAdapter | undefined;
19
21
  protected getDictationAdapter(): DictationAdapter | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"default-thread-composer-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/base/default-thread-composer-runtime-core.ts"],"mappings":";;;;;;;;;;cAea,yCACH,mCACG;UAEH;MACG;MAIA;MAIS,kBAAkB;EAItB,eAAe;EAIf,gBAAgB;YAItB,wBAAoB;YAIpB,uBAAmB;UAIrB;EAUN,YAAA,SAAS,KAAK;IACZ;MAEM,cAAc;MACd,YAAY;;;EAUf,WAVe;EA+BT,WACX,SAAS,KAAK,yCACd,UAAU,cAAW;EAoBV,gBAAY"}
1
+ {"version":3,"file":"default-thread-composer-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/base/default-thread-composer-runtime-core.ts"],"mappings":";;;;;;;;;;;cAgBa,yCACH,mCACG;UAEH;MACG;MAIA;UAIH;MAQY,kBAAkB;EAgBtB,cACd,qBACA,WAAW;EAKG,gBAAgB;YAItB,wBAAoB;YAIpB,uBAAmB;UAIrB;EAUN,YAAA,SAAS,KAAK;IACZ;MAEM,cAAc;MACd,YAAY;;;EAUf,WAVe;EA+BT,WACX,SAAS,KAAK,yCACd,UAAU,cAAW;EAoBV,gBAAY"}
@@ -10,11 +10,22 @@ var DefaultThreadComposerRuntimeCore = class extends BaseComposerRuntimeCore {
10
10
  get canSend() {
11
11
  return !this.isEmpty && !this.runtime.isSendDisabled && !this._isSending;
12
12
  }
13
+ _queueCache;
13
14
  get queue() {
14
- return this.runtime.getQueueItems?.() ?? EMPTY_QUEUE_ITEMS;
15
+ const steer = this.runtime.getSteerQueueItems?.() ?? EMPTY_QUEUE_ITEMS;
16
+ const queue = this.runtime.getQueueItems?.() ?? EMPTY_QUEUE_ITEMS;
17
+ const cache = this._queueCache;
18
+ if (cache && cache.steer === steer && cache.queue === queue) return cache.flat;
19
+ const flat = steer.length === 0 ? queue : queue.length === 0 ? steer : [...steer, ...queue];
20
+ this._queueCache = {
21
+ steer,
22
+ queue,
23
+ flat
24
+ };
25
+ return flat;
15
26
  }
16
- steerQueueItem(queueItemId) {
17
- this.runtime.steerQueueItem?.(queueItemId);
27
+ moveQueueItem(queueItemId, placement) {
28
+ this.runtime.moveQueueItem?.(queueItemId, placement);
18
29
  }
19
30
  removeQueueItem(queueItemId) {
20
31
  this.runtime.removeQueueItem?.(queueItemId);
@@ -1 +1 @@
1
- {"version":3,"file":"default-thread-composer-runtime-core.js","names":["AppendMessage","AttachmentAdapter","DictationAdapter","SendOptions","ThreadComposerRuntimeCore","ThreadRuntimeCore","EMPTY_QUEUE_ITEMS","QueueItemState","BaseComposerRuntimeCore","gateInteractableComposerMetadata","DefaultThreadComposerRuntimeCore","_canCancel","canCancel","canSend","isEmpty","runtime","isSendDisabled","_isSending","queue","getQueueItems","steerQueueItem","queueItemId","removeQueueItem","getAttachmentAdapter","adapters","attachments","getDictationAdapter","dictation","Omit","constructor","connect","lastIsSendDisabled","lastQueue","subscribe","changed","capabilities","cancel","_notifySubscribers","handleSend","message","options","composerMetadata","getModelContext","unstable_composerMetadata","messages","enriched","enrichWithComposerMetadata","append","parentId","at","id","sourceId","startRun","steer","handleCancel","cancelRun"],"sources":["../../../src/runtime/base/default-thread-composer-runtime-core.ts"],"sourcesContent":["import type { AppendMessage } from \"../../types/message\";\nimport type { AttachmentAdapter } from \"../../adapters/attachment\";\nimport type { DictationAdapter } from \"../../adapters/speech\";\nimport type {\n SendOptions,\n ThreadComposerRuntimeCore,\n} from \"../interfaces/composer-runtime-core\";\nimport type { ThreadRuntimeCore } from \"../interfaces/thread-runtime-core\";\nimport {\n EMPTY_QUEUE_ITEMS,\n type QueueItemState,\n} from \"../../store/scopes/queue-item\";\nimport { BaseComposerRuntimeCore } from \"./base-composer-runtime-core\";\nimport { gateInteractableComposerMetadata } from \"../../model-context/interactable-composer-metadata\";\n\nexport class DefaultThreadComposerRuntimeCore\n extends BaseComposerRuntimeCore\n implements ThreadComposerRuntimeCore\n{\n private _canCancel = false;\n public get canCancel() {\n return this._canCancel;\n }\n\n public get canSend() {\n return !this.isEmpty && !this.runtime.isSendDisabled && !this._isSending;\n }\n\n public override get queue(): readonly QueueItemState[] {\n return this.runtime.getQueueItems?.() ?? EMPTY_QUEUE_ITEMS;\n }\n\n public override steerQueueItem(queueItemId: string): void {\n this.runtime.steerQueueItem?.(queueItemId);\n }\n\n public override removeQueueItem(queueItemId: string): void {\n this.runtime.removeQueueItem?.(queueItemId);\n }\n\n protected getAttachmentAdapter() {\n return this.runtime.adapters?.attachments;\n }\n\n protected getDictationAdapter() {\n return this.runtime.adapters?.dictation;\n }\n\n private runtime: Omit<ThreadRuntimeCore, \"composer\"> & {\n adapters?:\n | {\n attachments?: AttachmentAdapter | undefined;\n dictation?: DictationAdapter | undefined;\n }\n | undefined;\n };\n\n constructor(\n runtime: Omit<ThreadRuntimeCore, \"composer\"> & {\n adapters?:\n | {\n attachments?: AttachmentAdapter | undefined;\n dictation?: DictationAdapter | undefined;\n }\n | undefined;\n },\n ) {\n super();\n this.runtime = runtime;\n this.connect();\n }\n\n public connect() {\n let lastIsSendDisabled = this.runtime.isSendDisabled;\n let lastQueue = this.queue;\n return this.runtime.subscribe(() => {\n let changed = false;\n if (this.canCancel !== this.runtime.capabilities.cancel) {\n this._canCancel = this.runtime.capabilities.cancel;\n changed = true;\n }\n if (lastIsSendDisabled !== this.runtime.isSendDisabled) {\n lastIsSendDisabled = this.runtime.isSendDisabled;\n changed = true;\n }\n if (lastQueue !== this.queue) {\n lastQueue = this.queue;\n changed = true;\n }\n if (changed) this._notifySubscribers();\n });\n }\n\n public async handleSend(\n message: Omit<AppendMessage, \"parentId\" | \"sourceId\">,\n options?: SendOptions,\n ) {\n // Merge provider-contributed metadata onto the outgoing user message\n // (same metadata.custom append path quotes ride). The interactables gate\n // runs here because it needs thread history, unavailable to the provider.\n const composerMetadata = gateInteractableComposerMetadata(\n this.runtime.getModelContext().unstable_composerMetadata,\n this.runtime.messages,\n );\n const enriched = this.enrichWithComposerMetadata(message, composerMetadata);\n\n return this.runtime.append({\n ...(enriched as AppendMessage),\n parentId: this.runtime.messages.at(-1)?.id ?? null,\n sourceId: null,\n startRun: options?.startRun,\n steer: options?.steer,\n });\n }\n\n public async handleCancel() {\n this.runtime.cancelRun();\n }\n}\n"],"mappings":";;;;AAeA,IAAaU,mCAAb,cACUF,wBAEV;CACE,aAAqB;CACrB,IAAWI,YAAY;EACrB,OAAO,KAAKD;CACd;CAEA,IAAWE,UAAU;EACnB,OAAO,CAAC,KAAKC,WAAW,CAAC,KAAKC,QAAQC,kBAAkB,CAAC,KAAKC;CAChE;CAEA,IAAoBC,QAAmC;EACrD,OAAO,KAAKH,QAAQI,gBAAgB,KAAKb;CAC3C;CAEA,eAA+Be,aAA2B;EACxD,KAAKN,QAAQK,iBAAiBC,WAAW;CAC3C;CAEA,gBAAgCA,aAA2B;EACzD,KAAKN,QAAQO,kBAAkBD,WAAW;CAC5C;CAEA,uBAAiC;EAC/B,OAAO,KAAKN,QAAQS,UAAUC;CAChC;CAEA,sBAAgC;EAC9B,OAAO,KAAKV,QAAQS,UAAUG;CAChC;CAEA;CASAE,YACEd,SAQA;EACA,MAAM;EACN,KAAKA,UAAUA;EACf,KAAKe,QAAQ;CACf;CAEA,UAAiB;EACf,IAAIC,qBAAqB,KAAKhB,QAAQC;EACtC,IAAIgB,YAAY,KAAKd;EACrB,OAAO,KAAKH,QAAQkB,gBAAgB;GAClC,IAAIC,UAAU;GACd,IAAI,KAAKtB,cAAc,KAAKG,QAAQoB,aAAaC,QAAQ;IACvD,KAAKzB,aAAa,KAAKI,QAAQoB,aAAaC;IAC5CF,UAAU;GACZ;GACA,IAAIH,uBAAuB,KAAKhB,QAAQC,gBAAgB;IACtDe,qBAAqB,KAAKhB,QAAQC;IAClCkB,UAAU;GACZ;GACA,IAAIF,cAAc,KAAKd,OAAO;IAC5Bc,YAAY,KAAKd;IACjBgB,UAAU;GACZ;GACA,IAAIA,SAAS,KAAKG,mBAAmB;EACvC,CAAC;CACH;CAEA,MAAaC,WACXC,SACAC,SACA;EAIA,MAAMC,mBAAmBhC,iCACvB,KAAKM,QAAQ2B,gBAAgB,CAAC,CAACC,2BAC/B,KAAK5B,QAAQ6B,QACf;EACA,MAAMC,WAAW,KAAKC,2BAA2BP,SAASE,gBAAgB;EAE1E,OAAO,KAAK1B,QAAQgC,OAAO;GACzB,GAAIF;GACJG,UAAU,KAAKjC,QAAQ6B,SAASK,GAAG,EAAE,CAAC,EAAEC,MAAM;GAC9CC,UAAU;GACVC,UAAUZ,SAASY;GACnBC,OAAOb,SAASa;EAClB,CAAC;CACH;CAEA,MAAaC,eAAe;EAC1B,KAAKvC,QAAQwC,UAAU;CACzB;AACF"}
1
+ {"version":3,"file":"default-thread-composer-runtime-core.js","names":["AppendMessage","AttachmentAdapter","DictationAdapter","SendOptions","ThreadComposerRuntimeCore","ThreadRuntimeCore","QueuePlacement","EMPTY_QUEUE_ITEMS","QueueItemState","BaseComposerRuntimeCore","gateInteractableComposerMetadata","DefaultThreadComposerRuntimeCore","_canCancel","canCancel","canSend","isEmpty","runtime","isSendDisabled","_isSending","_queueCache","steer","queue","flat","getSteerQueueItems","getQueueItems","cache","length","moveQueueItem","queueItemId","placement","removeQueueItem","getAttachmentAdapter","adapters","attachments","getDictationAdapter","dictation","Omit","constructor","connect","lastIsSendDisabled","lastQueue","subscribe","changed","capabilities","cancel","_notifySubscribers","handleSend","message","options","composerMetadata","getModelContext","unstable_composerMetadata","messages","enriched","enrichWithComposerMetadata","append","parentId","at","id","sourceId","startRun","handleCancel","cancelRun"],"sources":["../../../src/runtime/base/default-thread-composer-runtime-core.ts"],"sourcesContent":["import type { AppendMessage } from \"../../types/message\";\nimport type { AttachmentAdapter } from \"../../adapters/attachment\";\nimport type { DictationAdapter } from \"../../adapters/speech\";\nimport type {\n SendOptions,\n ThreadComposerRuntimeCore,\n} from \"../interfaces/composer-runtime-core\";\nimport type { ThreadRuntimeCore } from \"../interfaces/thread-runtime-core\";\nimport type { QueuePlacement } from \"../queue/external-thread-queue-adapter\";\nimport {\n EMPTY_QUEUE_ITEMS,\n type QueueItemState,\n} from \"../../store/scopes/queue-item\";\nimport { BaseComposerRuntimeCore } from \"./base-composer-runtime-core\";\nimport { gateInteractableComposerMetadata } from \"../../model-context/interactable-composer-metadata\";\n\nexport class DefaultThreadComposerRuntimeCore\n extends BaseComposerRuntimeCore\n implements ThreadComposerRuntimeCore\n{\n private _canCancel = false;\n public get canCancel() {\n return this._canCancel;\n }\n\n public get canSend() {\n return !this.isEmpty && !this.runtime.isSendDisabled && !this._isSending;\n }\n\n private _queueCache:\n | {\n steer: readonly QueueItemState[];\n queue: readonly QueueItemState[];\n flat: readonly QueueItemState[];\n }\n | undefined;\n\n public override get queue(): readonly QueueItemState[] {\n const steer = this.runtime.getSteerQueueItems?.() ?? EMPTY_QUEUE_ITEMS;\n const queue = this.runtime.getQueueItems?.() ?? EMPTY_QUEUE_ITEMS;\n const cache = this._queueCache;\n if (cache && cache.steer === steer && cache.queue === queue)\n return cache.flat;\n const flat =\n steer.length === 0\n ? queue\n : queue.length === 0\n ? steer\n : [...steer, ...queue];\n this._queueCache = { steer, queue, flat };\n return flat;\n }\n\n public override moveQueueItem(\n queueItemId: string,\n placement: QueuePlacement,\n ): void {\n this.runtime.moveQueueItem?.(queueItemId, placement);\n }\n\n public override removeQueueItem(queueItemId: string): void {\n this.runtime.removeQueueItem?.(queueItemId);\n }\n\n protected getAttachmentAdapter() {\n return this.runtime.adapters?.attachments;\n }\n\n protected getDictationAdapter() {\n return this.runtime.adapters?.dictation;\n }\n\n private runtime: Omit<ThreadRuntimeCore, \"composer\"> & {\n adapters?:\n | {\n attachments?: AttachmentAdapter | undefined;\n dictation?: DictationAdapter | undefined;\n }\n | undefined;\n };\n\n constructor(\n runtime: Omit<ThreadRuntimeCore, \"composer\"> & {\n adapters?:\n | {\n attachments?: AttachmentAdapter | undefined;\n dictation?: DictationAdapter | undefined;\n }\n | undefined;\n },\n ) {\n super();\n this.runtime = runtime;\n this.connect();\n }\n\n public connect() {\n let lastIsSendDisabled = this.runtime.isSendDisabled;\n let lastQueue = this.queue;\n return this.runtime.subscribe(() => {\n let changed = false;\n if (this.canCancel !== this.runtime.capabilities.cancel) {\n this._canCancel = this.runtime.capabilities.cancel;\n changed = true;\n }\n if (lastIsSendDisabled !== this.runtime.isSendDisabled) {\n lastIsSendDisabled = this.runtime.isSendDisabled;\n changed = true;\n }\n if (lastQueue !== this.queue) {\n lastQueue = this.queue;\n changed = true;\n }\n if (changed) this._notifySubscribers();\n });\n }\n\n public async handleSend(\n message: Omit<AppendMessage, \"parentId\" | \"sourceId\">,\n options?: SendOptions,\n ) {\n // Merge provider-contributed metadata onto the outgoing user message\n // (same metadata.custom append path quotes ride). The interactables gate\n // runs here because it needs thread history, unavailable to the provider.\n const composerMetadata = gateInteractableComposerMetadata(\n this.runtime.getModelContext().unstable_composerMetadata,\n this.runtime.messages,\n );\n const enriched = this.enrichWithComposerMetadata(message, composerMetadata);\n\n return this.runtime.append({\n ...(enriched as AppendMessage),\n parentId: this.runtime.messages.at(-1)?.id ?? null,\n sourceId: null,\n startRun: options?.startRun,\n steer: options?.steer,\n });\n }\n\n public async handleCancel() {\n this.runtime.cancelRun();\n }\n}\n"],"mappings":";;;;AAgBA,IAAaW,mCAAb,cACUF,wBAEV;CACE,aAAqB;CACrB,IAAWI,YAAY;EACrB,OAAO,KAAKD;CACd;CAEA,IAAWE,UAAU;EACnB,OAAO,CAAC,KAAKC,WAAW,CAAC,KAAKC,QAAQC,kBAAkB,CAAC,KAAKC;CAChE;CAEA;CAQA,IAAoBG,QAAmC;EACrD,MAAMD,QAAQ,KAAKJ,QAAQO,qBAAqB,KAAKhB;EACrD,MAAMc,QAAQ,KAAKL,QAAQQ,gBAAgB,KAAKjB;EAChD,MAAMkB,QAAQ,KAAKN;EACnB,IAAIM,SAASA,MAAML,UAAUA,SAASK,MAAMJ,UAAUA,OACpD,OAAOI,MAAMH;EACf,MAAMA,OACJF,MAAMM,WAAW,IACbL,QACAA,MAAMK,WAAW,IACfN,QACA,CAAC,GAAGA,OAAO,GAAGC,KAAK;EAC3B,KAAKF,cAAc;GAAEC;GAAOC;GAAOC;EAAK;EACxC,OAAOA;CACT;CAEA,cACEM,aACAC,WACM;EACN,KAAKb,QAAQW,gBAAgBC,aAAaC,SAAS;CACrD;CAEA,gBAAgCD,aAA2B;EACzD,KAAKZ,QAAQc,kBAAkBF,WAAW;CAC5C;CAEA,uBAAiC;EAC/B,OAAO,KAAKZ,QAAQgB,UAAUC;CAChC;CAEA,sBAAgC;EAC9B,OAAO,KAAKjB,QAAQgB,UAAUG;CAChC;CAEA;CASAE,YACErB,SAQA;EACA,MAAM;EACN,KAAKA,UAAUA;EACf,KAAKsB,QAAQ;CACf;CAEA,UAAiB;EACf,IAAIC,qBAAqB,KAAKvB,QAAQC;EACtC,IAAIuB,YAAY,KAAKnB;EACrB,OAAO,KAAKL,QAAQyB,gBAAgB;GAClC,IAAIC,UAAU;GACd,IAAI,KAAK7B,cAAc,KAAKG,QAAQ2B,aAAaC,QAAQ;IACvD,KAAKhC,aAAa,KAAKI,QAAQ2B,aAAaC;IAC5CF,UAAU;GACZ;GACA,IAAIH,uBAAuB,KAAKvB,QAAQC,gBAAgB;IACtDsB,qBAAqB,KAAKvB,QAAQC;IAClCyB,UAAU;GACZ;GACA,IAAIF,cAAc,KAAKnB,OAAO;IAC5BmB,YAAY,KAAKnB;IACjBqB,UAAU;GACZ;GACA,IAAIA,SAAS,KAAKG,mBAAmB;EACvC,CAAC;CACH;CAEA,MAAaC,WACXC,SACAC,SACA;EAIA,MAAMC,mBAAmBvC,iCACvB,KAAKM,QAAQkC,gBAAgB,CAAC,CAACC,2BAC/B,KAAKnC,QAAQoC,QACf;EACA,MAAMC,WAAW,KAAKC,2BAA2BP,SAASE,gBAAgB;EAE1E,OAAO,KAAKjC,QAAQuC,OAAO;GACzB,GAAIF;GACJG,UAAU,KAAKxC,QAAQoC,SAASK,GAAG,EAAE,CAAC,EAAEC,MAAM;GAC9CC,UAAU;GACVC,UAAUZ,SAASY;GACnBxC,OAAO4B,SAAS5B;EAClB,CAAC;CACH;CAEA,MAAayC,eAAe;EAC1B,KAAK7C,QAAQ8C,UAAU;CACzB;AACF"}
@@ -3,6 +3,7 @@ import { Attachment, CreateAttachment } from "../../types/attachment.js";
3
3
  import { Unsubscribe } from "../../types/unsubscribe.js";
4
4
  import { DictationAdapter } from "../../adapters/speech.js";
5
5
  import { QuoteInfo } from "../../types/quote.js";
6
+ import { QueuePlacement } from "../queue/external-thread-queue-adapter.js";
6
7
  import { QueueItemState } from "../../store/scopes/queue-item.js";
7
8
  //#region src/runtime/interfaces/composer-runtime-core.d.ts
8
9
  type AttachmentAddErrorReason = "no-adapter" | "not-accepted" | "adapter-error";
@@ -59,7 +60,7 @@ type ComposerRuntimeCore = Readonly<{
59
60
  send: (options?: SendOptions) => void;
60
61
  cancel: () => void;
61
62
  queue: readonly QueueItemState[];
62
- steerQueueItem: (queueItemId: string) => void;
63
+ moveQueueItem: (queueItemId: string, placement: QueuePlacement) => void;
63
64
  removeQueueItem: (queueItemId: string) => void;
64
65
  dictation: DictationState | undefined;
65
66
  startDictation: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"composer-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/interfaces/composer-runtime-core.ts"],"mappings":";;;;;;;KAQY;KAKA;WACD,QAAQ;WACR;WACA;WACA,QAAQ;;KAGP;;;;;EAKV,MAAM;;;;;EAKN,eAAe;EACf,oBAAoB;;KAGV,iCAAiC;KAEjC,6BAA6B,UAAU,6BACjD,SAAS,4BAA4B;KAG3B;WACD,QAAQ,iBAAiB;WACzB;WACA;;KAGC;EACV;;EAEA;;KAGU,sBAAsB;EAChC;EAEA;EACA;EACA;EAEA,sBAAsB;EACtB;EAEA,gBAAgB,kBAAkB,OAAO,qBAAqB;EAC9D,mBAAmB,yBAAyB;EAE5C;EACA,UAAU;EAEV,MAAM;EACN,UAAU,MAAM;EAEhB,WAAW;EACX,eAAe,WAAW;EAE1B,OAAO;EACP,WAAW,OAAO;EAElB,aAAa;EACb,wBAAwB;EAExB,OAAO,UAAU;EACjB;EAEA,gBAAgB;EAChB,iBAAiB;EACjB,kBAAkB;EAElB,WAAW;EACX;EACA;EAEA,YAAY,yBAAyB;;;;;;EAOrC,cAAc,UAAU,0BACtB,OAAO,GACP,UAAU,6BAA6B,OACpC;;KAGK,4BAA4B;KAE5B,0BAA0B,sBACpC;EACE;EACA"}
1
+ {"version":3,"file":"composer-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/interfaces/composer-runtime-core.ts"],"mappings":";;;;;;;;KASY;KAKA;WACD,QAAQ;WACR;WACA;WACA,QAAQ;;KAGP;;;;;EAKV,MAAM;;;;;EAKN,eAAe;EACf,oBAAoB;;KAGV,iCAAiC;KAEjC,6BAA6B,UAAU,6BACjD,SAAS,4BAA4B;KAG3B;WACD,QAAQ,iBAAiB;WACzB;WACA;;KAGC;EACV;;EAEA;;KAGU,sBAAsB;EAChC;EAEA;EACA;EACA;EAEA,sBAAsB;EACtB;EAEA,gBAAgB,kBAAkB,OAAO,qBAAqB;EAC9D,mBAAmB,yBAAyB;EAE5C;EACA,UAAU;EAEV,MAAM;EACN,UAAU,MAAM;EAEhB,WAAW;EACX,eAAe,WAAW;EAE1B,OAAO;EACP,WAAW,OAAO;EAElB,aAAa;EACb,wBAAwB;EAExB,OAAO,UAAU;EACjB;EAEA,gBAAgB;EAChB,gBAAgB,qBAAqB,WAAW;EAChD,kBAAkB;EAElB,WAAW;EACX;EACA;EAEA,YAAY,yBAAyB;;;;;;EAOrC,cAAc,UAAU,0BACtB,OAAO,GACP,UAAU,6BAA6B,OACpC;;KAGK,4BAA4B;KAE5B,0BAA0B,sBACpC;EACE;EACA"}
@@ -6,6 +6,7 @@ import { ModelContext } from "../../model-context/types.js";
6
6
  import { ChatModelRunOptions, ChatModelRunResult } from "../utils/chat-model-adapter.js";
7
7
  import { ThreadMessageLike } from "../utils/thread-message-like.js";
8
8
  import { ExportedMessageRepository } from "../utils/message-repository.js";
9
+ import { QueuePlacement } from "../queue/external-thread-queue-adapter.js";
9
10
  import { QueueItemState } from "../../store/scopes/queue-item.js";
10
11
  import { EditComposerRuntimeCore, ThreadComposerRuntimeCore } from "./composer-runtime-core.js";
11
12
  import { ToolModelContentPart } from "assistant-stream";
@@ -141,7 +142,8 @@ type ThreadRuntimeCore = Readonly<{
141
142
  getEditComposer: (messageId: string) => EditComposerRuntimeCore | undefined;
142
143
  beginEdit: (messageId: string) => void;
143
144
  getQueueItems?: () => readonly QueueItemState[];
144
- steerQueueItem?: (queueItemId: string) => void;
145
+ getSteerQueueItems?: () => readonly QueueItemState[];
146
+ moveQueueItem?: (queueItemId: string, placement: QueuePlacement) => void;
145
147
  removeQueueItem?: (queueItemId: string) => void;
146
148
  speech: SpeechState | undefined;
147
149
  voice: VoiceSessionState | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"thread-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/interfaces/thread-runtime-core.ts"],"mappings":";;;;;;;;;;;;;KAoBY;WACD;WACA;WACA;WACA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;KAGC;EACV;EACA;EACA;EACA,QAAQ;EACR;EACA,WAAW;;;;;;;EAOX,wBAAwB;;KAGd;EACV;EACA;;KAGU;EACV;EACA;;EAEA;EACA;;KAGU;EACV;EACA;;KAGU;EACV;;KAGU;WACD;WACA,QAAQ,uBAAuB;;KAG9B;WACD,QAAQ,qBAAqB;WAC7B;WACA,MAAM,qBAAqB;;KAG1B;WACD;;KAGC;;;;;;;EAOV,UAAU;;;;;;;EAOV,QAAQ;;;;;;;;;EASR,YAAY;;;;;EAKZ,oBAAoB;;KAGV,+BAA+B;KAE/B,2BAA2B,UAAU,2BAC/C,SAAS,0BAA0B;KAGzB;EACV;EACA;EACA,WAAW;;KAGD,kBAAkB;EAC5B,UACE,SAAS,wBACN,eAAe;;KAGV,oBAAoB;EAC9B,iBAAiB;IAEX;IACA,SAAS;IACT;;EAIN,cAAc;EACd,iBAAiB;EAEjB,SAAS,SAAS;EAClB,gBAAgB,6BAA6B;EAC7C,WAAW,QAAQ;EACnB,YAAY,QAAQ;EACpB;EAEA,gBAAgB,SAAS;EACzB,iBAAiB,SAAS;EAC1B,wBAAwB,SAAS;EAEjC,QAAQ;EACR;EAEA;EACA;EACA;EACA;EAEA,iBAAiB,UAAU;EAE3B,uBAAuB;EAEvB,UAAU;EACV,kBAAkB,sBAAsB;EACxC,YAAY;EAEZ,+BAA+B;EAC/B,kBAAkB;EAClB,mBAAmB;EAEnB,QAAQ;EACR,OAAO;EAEP,cAAc,SAAS;EACvB;;;;;;EAMA;EACA;;;;;;;EAOA;EACA,mBAAmB;EACnB,OAAO;EACP,sBAAsB;EAEtB;EAEA,YAAY,yBAAyB;EAErC;EACA,uBAAuB,yBAAyB;EAEhD,OAAO,YAAY;EACnB,UAAU;EAEV;EACA,oBAAoB;EAEpB,MAAM,2BAA2B;;;;;;;;;;;;EAajC,gCAAgC;;;;;;EAOhC,YAAY,UAAU,wBACpB,OAAO,GACP,UAAU,2BAA2B,KACpC"}
1
+ {"version":3,"file":"thread-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/interfaces/thread-runtime-core.ts"],"mappings":";;;;;;;;;;;;;;KAqBY;WACD;WACA;WACA;WACA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;KAGC;EACV;EACA;EACA;EACA,QAAQ;EACR;EACA,WAAW;;;;;;;EAOX,wBAAwB;;KAGd;EACV;EACA;;KAGU;EACV;EACA;;EAEA;EACA;;KAGU;EACV;EACA;;KAGU;EACV;;KAGU;WACD;WACA,QAAQ,uBAAuB;;KAG9B;WACD,QAAQ,qBAAqB;WAC7B;WACA,MAAM,qBAAqB;;KAG1B;WACD;;KAGC;;;;;;;EAOV,UAAU;;;;;;;EAOV,QAAQ;;;;;;;;;EASR,YAAY;;;;;EAKZ,oBAAoB;;KAGV,+BAA+B;KAE/B,2BAA2B,UAAU,2BAC/C,SAAS,0BAA0B;KAGzB;EACV;EACA;EACA,WAAW;;KAGD,kBAAkB;EAC5B,UACE,SAAS,wBACN,eAAe;;KAGV,oBAAoB;EAC9B,iBAAiB;IAEX;IACA,SAAS;IACT;;EAIN,cAAc;EACd,iBAAiB;EAEjB,SAAS,SAAS;EAClB,gBAAgB,6BAA6B;EAC7C,WAAW,QAAQ;EACnB,YAAY,QAAQ;EACpB;EAEA,gBAAgB,SAAS;EACzB,iBAAiB,SAAS;EAC1B,wBAAwB,SAAS;EAEjC,QAAQ;EACR;EAEA;EACA;EACA;EACA;EAEA,iBAAiB,UAAU;EAE3B,uBAAuB;EAEvB,UAAU;EACV,kBAAkB,sBAAsB;EACxC,YAAY;EAEZ,+BAA+B;EAC/B,oCAAoC;EACpC,iBAAiB,qBAAqB,WAAW;EACjD,mBAAmB;EAEnB,QAAQ;EACR,OAAO;EAEP,cAAc,SAAS;EACvB;;;;;;EAMA;EACA;;;;;;;EAOA;EACA,mBAAmB;EACnB,OAAO;EACP,sBAAsB;EAEtB;EAEA,YAAY,yBAAyB;EAErC;EACA,uBAAuB,yBAAyB;EAEhD,OAAO,YAAY;EACnB,UAAU;EAEV;EACA,oBAAoB;EAEpB,MAAM,2BAA2B;;;;;;;;;;;;EAajC,gCAAgC;;;;;;EAOhC,YAAY,UAAU,wBACpB,OAAO,GACP,UAAU,2BAA2B,KACpC"}
@@ -1,19 +1,32 @@
1
1
  import { AppendMessage } from "../../types/message.js";
2
2
  import { QueueItemState } from "../../store/scopes/queue-item.js";
3
3
  //#region src/runtime/queue/external-thread-queue-adapter.d.ts
4
+ type QueuePlacement = {
5
+ readonly lane?: "queue" | "steer";
6
+ readonly insertAfter?: string | null;
7
+ readonly insertBefore?: string | null;
8
+ };
4
9
  /**
5
10
  * The queue surface a runtime exposes so the composer can stay usable during a
6
11
  * run and render the pending messages.
7
12
  */
8
13
  type ExternalThreadQueueAdapter = {
9
14
  items: readonly QueueItemState[];
10
- enqueue: (message: AppendMessage, options: {
11
- steer: boolean;
12
- }) => void;
13
- steer: (queueItemId: string) => void;
15
+ steerItems: readonly QueueItemState[];
16
+ /** Send a message into the queue lane, processed in order. */
17
+ enqueue: (message: AppendMessage) => void;
18
+ /** Send a message into the steer lane, processed next. */
19
+ steer: (message: AppendMessage) => void;
20
+ /**
21
+ * Move a queued message between lanes or within a lane. An unanchored move
22
+ * into the steer lane mid-run interrupts — cancels the live run and
23
+ * dispatches the item — when the runtime supports cancellation; a move with
24
+ * `insertAfter`/`insertBefore` only places the item and never interrupts.
25
+ */
26
+ move: (queueItemId: string, placement: QueuePlacement) => void;
27
+ edit: (queueItemId: string, message: AppendMessage) => void;
14
28
  remove: (queueItemId: string) => void;
15
- clear: (reason: "edit" | "reload" | "cancel-run") => void;
16
29
  };
17
30
  //#endregion
18
- export { ExternalThreadQueueAdapter };
31
+ export { ExternalThreadQueueAdapter, QueuePlacement };
19
32
  //# sourceMappingURL=external-thread-queue-adapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"external-thread-queue-adapter.d.ts","names":[],"sources":["../../../src/runtime/queue/external-thread-queue-adapter.ts"],"mappings":";;;;;;;KAOY;EACV,gBAAgB;EAChB,UAAU,SAAS,eAAe;IAAW;;EAC7C,QAAQ;EACR,SAAS;EACT,QAAQ"}
1
+ {"version":3,"file":"external-thread-queue-adapter.d.ts","names":[],"sources":["../../../src/runtime/queue/external-thread-queue-adapter.ts"],"mappings":";;;KAGY;WACD;WACA;WACA;;;;;;KAOC;EACV,gBAAgB;EAChB,qBAAqB;;EAErB,UAAU,SAAS;;EAEnB,QAAQ,SAAS;;;;;;;EAOjB,OAAO,qBAAqB,WAAW;EACvC,OAAO,qBAAqB,SAAS;EACrC,SAAS"}
@@ -5,7 +5,7 @@ type MessageQueueDriver = {
5
5
  run: (message: AppendMessage, options: {
6
6
  steer: boolean;
7
7
  }) => void;
8
- /** When omitted, `steer` degrades to "process next" instead of interrupting. */
8
+ /** When omitted, steering degrades to "process next" instead of interrupting. */
9
9
  cancel?: (() => void) | undefined;
10
10
  };
11
11
  type MessageQueueController = {
@@ -14,6 +14,15 @@ type MessageQueueController = {
14
14
  notifyBusy: () => void;
15
15
  /** Advances to the next pending message; call on the run's falling edge. */
16
16
  notifyIdle: () => void;
17
+ /**
18
+ * Pauses queue advance for a user-initiated cancel, so the cancelled run's
19
+ * settle keeps the pending items instead of dispatching the next one; the
20
+ * next explicit send or run start re-arms draining. Call before aborting
21
+ * the run.
22
+ */
23
+ notifyCancelled: () => void;
24
+ /** Empties both lanes without dispatching. */
25
+ clear: () => void;
17
26
  subscribe: (callback: () => void) => () => void;
18
27
  };
19
28
  declare const createMessageQueue: (driver: MessageQueueDriver) => MessageQueueController;
@@ -1 +1 @@
1
- {"version":3,"file":"message-queue.d.ts","names":[],"sources":["../../../src/runtime/queue/message-queue.ts"],"mappings":";;;KASY;EACV,MAAM,SAAS,eAAe;IAAW;;;EAEzC;;KAGU;WACD,SAAS;;EAElB;;EAEA;EACA,YAAY;;cAGD,qBACX,QAAQ,uBACP"}
1
+ {"version":3,"file":"message-queue.d.ts","names":[],"sources":["../../../src/runtime/queue/message-queue.ts"],"mappings":";;;KAgBY;EACV,MAAM,SAAS,eAAe;IAAW;;;EAEzC;;KAGU;WACD,SAAS;;EAElB;;EAEA;;;;;;;EAOA;;EAEA;EACA,YAAY;;cAgCD,qBACX,QAAQ,uBACP"}
@@ -2,77 +2,165 @@ import { generateId } from "../../utils/id.js";
2
2
  import { getThreadMessageText } from "../../utils/text.js";
3
3
  import { EMPTY_QUEUE_ITEMS } from "../../store/scopes/queue-item.js";
4
4
  //#region src/runtime/queue/message-queue.ts
5
+ const getQueueItemParts = (message) => {
6
+ const source = [...message.content, ...(message.attachments ?? []).flatMap((attachment) => (attachment.content ?? []).filter((part) => part.type !== "text"))];
7
+ const parts = [];
8
+ for (const part of source) if (part.type === "file" || part.type === "text") parts.push(part);
9
+ else if (part.type === "image") parts.push({
10
+ type: "file",
11
+ data: part.image,
12
+ mimeType: "image/*",
13
+ ...part.filename !== void 0 && { filename: part.filename }
14
+ });
15
+ return parts;
16
+ };
5
17
  const createMessageQueue = (driver) => {
6
- let items = EMPTY_QUEUE_ITEMS;
18
+ let lanes = {
19
+ queue: EMPTY_QUEUE_ITEMS,
20
+ steer: EMPTY_QUEUE_ITEMS
21
+ };
7
22
  const messages = /* @__PURE__ */ new Map();
8
23
  const subscribers = /* @__PURE__ */ new Set();
9
24
  let running = false;
25
+ let paused = false;
10
26
  let suppressIdle = 0;
27
+ let cancelSettles = 0;
11
28
  const notify = () => {
12
29
  for (const callback of subscribers) callback();
13
30
  };
14
- const setItems = (next) => {
15
- items = next;
16
- adapter.items = next;
31
+ const setLanes = (next) => {
32
+ lanes = next;
33
+ adapter.items = next.queue;
34
+ adapter.steerItems = next.steer;
17
35
  notify();
18
36
  };
37
+ const toItem = (id, message) => ({
38
+ id,
39
+ prompt: getThreadMessageText(message),
40
+ parts: getQueueItemParts(message)
41
+ });
42
+ const laneOf = (queueItemId) => {
43
+ if (lanes.steer.some((item) => item.id === queueItemId)) return "steer";
44
+ if (lanes.queue.some((item) => item.id === queueItemId)) return "queue";
45
+ };
19
46
  const advance = () => {
20
- if (running || items.length === 0) return;
21
- const head = items[0];
47
+ if (running || paused) return;
48
+ const lane = lanes.steer.length > 0 ? "steer" : "queue";
49
+ const head = lanes[lane][0];
50
+ if (!head) return;
22
51
  const message = messages.get(head.id);
23
52
  messages.delete(head.id);
24
- setItems(items.slice(1));
53
+ setLanes({
54
+ ...lanes,
55
+ [lane]: lanes[lane].slice(1)
56
+ });
25
57
  if (!message) return;
26
58
  running = true;
27
59
  driver.run(message, { steer: false });
28
60
  };
29
- const enqueue = (message, { steer }) => {
61
+ const interrupt = (message) => {
62
+ paused = false;
63
+ suppressIdle += Math.max(cancelSettles, 1);
64
+ cancelSettles = 0;
65
+ driver.cancel();
66
+ running = true;
67
+ driver.run(message, { steer: true });
68
+ };
69
+ const push = (lane, message) => {
70
+ paused = false;
30
71
  const id = generateId();
31
- const prompt = getThreadMessageText(message);
32
72
  messages.set(id, message);
33
- setItems([...items, {
34
- id,
35
- prompt
36
- }]);
37
- if (steer) steerItem(id);
38
- else advance();
73
+ setLanes({
74
+ ...lanes,
75
+ [lane]: [...lanes[lane], toItem(id, message)]
76
+ });
77
+ advance();
78
+ };
79
+ const enqueue = (message) => {
80
+ push("queue", message);
81
+ };
82
+ const steer = (message) => {
83
+ if (running && driver.cancel) {
84
+ interrupt(message);
85
+ return;
86
+ }
87
+ push("steer", message);
39
88
  };
40
- const steerItem = (queueItemId) => {
41
- if (!messages.has(queueItemId)) return;
42
- if (driver.cancel && running) {
89
+ const move = (queueItemId, placement) => {
90
+ const fromLane = laneOf(queueItemId);
91
+ if (!fromLane) throw new Error(`Unknown queue item "${queueItemId}".`);
92
+ const toLane = placement.lane ?? fromLane;
93
+ const item = lanes[fromLane].find((i) => i.id === queueItemId);
94
+ const dest = (toLane === fromLane ? lanes[fromLane] : lanes[toLane]).filter((i) => i.id !== queueItemId);
95
+ const anchorIndex = (anchor) => {
96
+ if (anchor === queueItemId) throw new Error(`Queue item "${queueItemId}" cannot anchor itself.`);
97
+ const index = dest.findIndex((i) => i.id === anchor);
98
+ if (index === -1) throw new Error(`Unknown anchor "${anchor}" in lane "${toLane}".`);
99
+ return index;
100
+ };
101
+ const { insertAfter, insertBefore } = placement;
102
+ let index;
103
+ if (insertAfter === void 0 && insertBefore === void 0) index = toLane === fromLane ? lanes[fromLane].findIndex((i) => i.id === queueItemId) : dest.length;
104
+ else if (insertAfter !== void 0 && insertBefore !== void 0) {
105
+ const after = insertAfter === null ? -1 : anchorIndex(insertAfter);
106
+ if ((insertBefore === null ? dest.length : anchorIndex(insertBefore)) !== after + 1) throw new Error(`insertAfter "${insertAfter}" and insertBefore "${insertBefore}" are not adjacent in lane "${toLane}".`);
107
+ index = after + 1;
108
+ } else if (insertAfter !== void 0) index = insertAfter === null ? 0 : anchorIndex(insertAfter) + 1;
109
+ else index = insertBefore === null ? dest.length : anchorIndex(insertBefore);
110
+ if (insertAfter === void 0 && insertBefore === void 0 && toLane === "steer" && fromLane !== "steer" && running && driver.cancel) {
43
111
  const message = messages.get(queueItemId);
44
112
  messages.delete(queueItemId);
45
- setItems(items.filter((item) => item.id !== queueItemId));
46
- suppressIdle++;
47
- driver.cancel();
48
- running = true;
49
- driver.run(message, { steer: true });
113
+ setLanes({
114
+ queue: lanes.queue.filter((i) => i.id !== queueItemId),
115
+ steer: lanes.steer
116
+ });
117
+ interrupt(message);
50
118
  return;
51
119
  }
52
- const target = items.find((item) => item.id === queueItemId);
53
- if (!target) return;
54
- setItems([target, ...items.filter((item) => item.id !== queueItemId)]);
120
+ const nextDest = [
121
+ ...dest.slice(0, index),
122
+ item,
123
+ ...dest.slice(index)
124
+ ];
125
+ const next = {
126
+ ...lanes,
127
+ [toLane]: nextDest
128
+ };
129
+ if (toLane !== fromLane) next[fromLane] = lanes[fromLane].filter((i) => i.id !== queueItemId);
130
+ setLanes(next);
55
131
  advance();
56
132
  };
133
+ const edit = (queueItemId, message) => {
134
+ const lane = laneOf(queueItemId);
135
+ if (!lane) throw new Error(`Unknown queue item "${queueItemId}".`);
136
+ messages.set(queueItemId, message);
137
+ setLanes({
138
+ ...lanes,
139
+ [lane]: lanes[lane].map((item) => item.id === queueItemId ? toItem(queueItemId, message) : item)
140
+ });
141
+ };
57
142
  const remove = (queueItemId) => {
58
143
  if (!messages.delete(queueItemId)) return;
59
- setItems(items.filter((item) => item.id !== queueItemId));
60
- };
61
- const clear = () => {
62
- if (items.length === 0) return;
63
- messages.clear();
64
- setItems(EMPTY_QUEUE_ITEMS);
144
+ setLanes({
145
+ queue: lanes.queue.filter((item) => item.id !== queueItemId),
146
+ steer: lanes.steer.filter((item) => item.id !== queueItemId)
147
+ });
65
148
  };
66
149
  const adapter = {
67
- items,
150
+ items: lanes.queue,
151
+ steerItems: lanes.steer,
68
152
  enqueue,
69
- steer: steerItem,
70
- remove,
71
- clear
153
+ steer,
154
+ move,
155
+ edit,
156
+ remove
72
157
  };
73
158
  return {
74
159
  adapter,
75
160
  notifyBusy: () => {
161
+ paused = false;
162
+ suppressIdle += cancelSettles;
163
+ cancelSettles = 0;
76
164
  running = true;
77
165
  },
78
166
  notifyIdle: () => {
@@ -80,9 +168,23 @@ const createMessageQueue = (driver) => {
80
168
  suppressIdle--;
81
169
  return;
82
170
  }
171
+ if (cancelSettles > 0) cancelSettles--;
83
172
  running = false;
84
173
  advance();
85
174
  },
175
+ notifyCancelled: () => {
176
+ if (running && cancelSettles === 0) {
177
+ paused = true;
178
+ cancelSettles = 1;
179
+ }
180
+ },
181
+ clear: () => {
182
+ messages.clear();
183
+ setLanes({
184
+ queue: EMPTY_QUEUE_ITEMS,
185
+ steer: EMPTY_QUEUE_ITEMS
186
+ });
187
+ },
86
188
  subscribe: (callback) => {
87
189
  subscribers.add(callback);
88
190
  return () => {
@@ -1 +1 @@
1
- {"version":3,"file":"message-queue.js","names":["AppendMessage","EMPTY_QUEUE_ITEMS","QueueItemState","generateId","getThreadMessageText","ExternalThreadQueueAdapter","MessageQueueDriver","run","message","options","steer","cancel","MessageQueueController","adapter","notifyBusy","notifyIdle","subscribe","callback","createMessageQueue","driver","items","messages","Map","subscribers","Set","running","suppressIdle","notify","setItems","next","advance","length","head","get","id","delete","slice","enqueue","prompt","set","steerItem","queueItemId","has","filter","item","target","find","remove","clear","add"],"sources":["../../../src/runtime/queue/message-queue.ts"],"sourcesContent":["import type { AppendMessage } from \"../../types/message\";\nimport {\n EMPTY_QUEUE_ITEMS,\n type QueueItemState,\n} from \"../../store/scopes/queue-item\";\nimport { generateId } from \"../../utils/id\";\nimport { getThreadMessageText } from \"../../utils/text\";\nimport type { ExternalThreadQueueAdapter } from \"./external-thread-queue-adapter\";\n\nexport type MessageQueueDriver = {\n run: (message: AppendMessage, options: { steer: boolean }) => void;\n /** When omitted, `steer` degrades to \"process next\" instead of interrupting. */\n cancel?: (() => void) | undefined;\n};\n\nexport type MessageQueueController = {\n readonly adapter: ExternalThreadQueueAdapter;\n /** Mark a run as in flight so concurrent sends buffer; call on the rising edge. */\n notifyBusy: () => void;\n /** Advances to the next pending message; call on the run's falling edge. */\n notifyIdle: () => void;\n subscribe: (callback: () => void) => () => void;\n};\n\nexport const createMessageQueue = (\n driver: MessageQueueDriver,\n): MessageQueueController => {\n let items: readonly QueueItemState[] = EMPTY_QUEUE_ITEMS;\n const messages = new Map<string, AppendMessage>();\n const subscribers = new Set<() => void>();\n\n let running = false;\n // swallow the cancelled run's settle when steering so it does not double-advance\n let suppressIdle = 0;\n\n const notify = () => {\n for (const callback of subscribers) callback();\n };\n\n const setItems = (next: readonly QueueItemState[]) => {\n items = next;\n adapter.items = next;\n notify();\n };\n\n const advance = () => {\n if (running || items.length === 0) return;\n const head = items[0]!;\n const message = messages.get(head.id);\n messages.delete(head.id);\n setItems(items.slice(1));\n if (!message) return;\n running = true;\n driver.run(message, { steer: false });\n };\n\n const enqueue = (message: AppendMessage, { steer }: { steer: boolean }) => {\n const id = generateId();\n const prompt = getThreadMessageText(message);\n messages.set(id, message);\n setItems([...items, { id, prompt }]);\n if (steer) {\n steerItem(id);\n } else {\n advance();\n }\n };\n\n const steerItem = (queueItemId: string) => {\n if (!messages.has(queueItemId)) return;\n\n if (driver.cancel && running) {\n const message = messages.get(queueItemId)!;\n messages.delete(queueItemId);\n setItems(items.filter((item) => item.id !== queueItemId));\n suppressIdle++;\n driver.cancel();\n running = true;\n driver.run(message, { steer: true });\n return;\n }\n\n const target = items.find((item) => item.id === queueItemId);\n if (!target) return;\n setItems([target, ...items.filter((item) => item.id !== queueItemId)]);\n advance();\n };\n\n const remove = (queueItemId: string) => {\n if (!messages.delete(queueItemId)) return;\n setItems(items.filter((item) => item.id !== queueItemId));\n };\n\n const clear = () => {\n if (items.length === 0) return;\n messages.clear();\n setItems(EMPTY_QUEUE_ITEMS);\n };\n\n const adapter: ExternalThreadQueueAdapter = {\n items,\n enqueue,\n steer: steerItem,\n remove,\n clear,\n };\n\n return {\n adapter,\n notifyBusy: () => {\n running = true;\n },\n notifyIdle: () => {\n if (suppressIdle > 0) {\n suppressIdle--;\n return;\n }\n running = false;\n advance();\n },\n subscribe: (callback) => {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n },\n };\n};\n"],"mappings":";;;;AAwBA,MAAakB,sBACXC,WAC2B;CAC3B,IAAIC,QAAmCnB;CACvC,MAAMoB,2BAAW,IAAIC,IAA2B;CAChD,MAAMC,8BAAc,IAAIC,IAAgB;CAExC,IAAIC,UAAU;CAEd,IAAIC,eAAe;CAEnB,MAAMC,eAAe;EACnB,KAAK,MAAMV,YAAYM,aAAaN,SAAS;CAC/C;CAEA,MAAMW,YAAYC,SAAoC;EACpDT,QAAQS;EACRhB,QAAQO,QAAQS;EAChBF,OAAO;CACT;CAEA,MAAMG,gBAAgB;EACpB,IAAIL,WAAWL,MAAMW,WAAW,GAAG;EACnC,MAAMC,OAAOZ,MAAM;EACnB,MAAMZ,UAAUa,SAASY,IAAID,KAAKE,EAAE;EACpCb,SAASc,OAAOH,KAAKE,EAAE;EACvBN,SAASR,MAAMgB,MAAM,CAAC,CAAC;EACvB,IAAI,CAAC5B,SAAS;EACdiB,UAAU;EACVN,OAAOZ,IAAIC,SAAS,EAAEE,OAAO,MAAM,CAAC;CACtC;CAEA,MAAM2B,WAAW7B,SAAwB,EAAEE,YAAgC;EACzE,MAAMwB,KAAK/B,WAAW;EACtB,MAAMmC,SAASlC,qBAAqBI,OAAO;EAC3Ca,SAASkB,IAAIL,IAAI1B,OAAO;EACxBoB,SAAS,CAAC,GAAGR,OAAO;GAAEc;GAAII;EAAO,CAAC,CAAC;EACnC,IAAI5B,OACF8B,UAAUN,EAAE;OAEZJ,QAAQ;CAEZ;CAEA,MAAMU,aAAaC,gBAAwB;EACzC,IAAI,CAACpB,SAASqB,IAAID,WAAW,GAAG;EAEhC,IAAItB,OAAOR,UAAUc,SAAS;GAC5B,MAAMjB,UAAUa,SAASY,IAAIQ,WAAW;GACxCpB,SAASc,OAAOM,WAAW;GAC3Bb,SAASR,MAAMuB,QAAQC,SAASA,KAAKV,OAAOO,WAAW,CAAC;GACxDf;GACAP,OAAOR,OAAO;GACdc,UAAU;GACVN,OAAOZ,IAAIC,SAAS,EAAEE,OAAO,KAAK,CAAC;GACnC;EACF;EAEA,MAAMmC,SAASzB,MAAM0B,MAAMF,SAASA,KAAKV,OAAOO,WAAW;EAC3D,IAAI,CAACI,QAAQ;EACbjB,SAAS,CAACiB,QAAQ,GAAGzB,MAAMuB,QAAQC,SAASA,KAAKV,OAAOO,WAAW,CAAC,CAAC;EACrEX,QAAQ;CACV;CAEA,MAAMiB,UAAUN,gBAAwB;EACtC,IAAI,CAACpB,SAASc,OAAOM,WAAW,GAAG;EACnCb,SAASR,MAAMuB,QAAQC,SAASA,KAAKV,OAAOO,WAAW,CAAC;CAC1D;CAEA,MAAMO,cAAc;EAClB,IAAI5B,MAAMW,WAAW,GAAG;EACxBV,SAAS2B,MAAM;EACfpB,SAAS3B,iBAAiB;CAC5B;CAEA,MAAMY,UAAsC;EAC1CO;EACAiB;EACA3B,OAAO8B;EACPO;EACAC;CACF;CAEA,OAAO;EACLnC;EACAC,kBAAkB;GAChBW,UAAU;EACZ;EACAV,kBAAkB;GAChB,IAAIW,eAAe,GAAG;IACpBA;IACA;GACF;GACAD,UAAU;GACVK,QAAQ;EACV;EACAd,YAAYC,aAAa;GACvBM,YAAY0B,IAAIhC,QAAQ;GACxB,aAAa;IACXM,YAAYY,OAAOlB,QAAQ;GAC7B;EACF;CACF;AACF"}
1
+ {"version":3,"file":"message-queue.js","names":["AppendMessage","FileMessagePart","TextMessagePart","EMPTY_QUEUE_ITEMS","QueueItemState","generateId","getThreadMessageText","ExternalThreadQueueAdapter","QueuePlacement","MessageQueueDriver","run","message","options","steer","cancel","MessageQueueController","adapter","notifyBusy","notifyIdle","notifyCancelled","clear","subscribe","callback","Lane","getQueueItemParts","source","content","attachments","flatMap","attachment","filter","part","type","parts","push","data","image","mimeType","filename","undefined","createMessageQueue","driver","lanes","Record","queue","messages","Map","subscribers","Set","running","paused","suppressIdle","cancelSettles","notify","setLanes","next","items","steerItems","toItem","id","prompt","laneOf","queueItemId","some","item","advance","lane","length","head","get","delete","slice","interrupt","Math","max","set","enqueue","move","placement","fromLane","Error","toLane","find","i","dest","anchorIndex","anchor","index","findIndex","insertAfter","insertBefore","after","before","nextDest","edit","map","remove","add"],"sources":["../../../src/runtime/queue/message-queue.ts"],"sourcesContent":["import type {\n AppendMessage,\n FileMessagePart,\n TextMessagePart,\n} from \"../../types/message\";\nimport {\n EMPTY_QUEUE_ITEMS,\n type QueueItemState,\n} from \"../../store/scopes/queue-item\";\nimport { generateId } from \"../../utils/id\";\nimport { getThreadMessageText } from \"../../utils/text\";\nimport type {\n ExternalThreadQueueAdapter,\n QueuePlacement,\n} from \"./external-thread-queue-adapter\";\n\nexport type MessageQueueDriver = {\n run: (message: AppendMessage, options: { steer: boolean }) => void;\n /** When omitted, steering degrades to \"process next\" instead of interrupting. */\n cancel?: (() => void) | undefined;\n};\n\nexport type MessageQueueController = {\n readonly adapter: ExternalThreadQueueAdapter;\n /** Mark a run as in flight so concurrent sends buffer; call on the rising edge. */\n notifyBusy: () => void;\n /** Advances to the next pending message; call on the run's falling edge. */\n notifyIdle: () => void;\n /**\n * Pauses queue advance for a user-initiated cancel, so the cancelled run's\n * settle keeps the pending items instead of dispatching the next one; the\n * next explicit send or run start re-arms draining. Call before aborting\n * the run.\n */\n notifyCancelled: () => void;\n /** Empties both lanes without dispatching. */\n clear: () => void;\n subscribe: (callback: () => void) => () => void;\n};\n\ntype Lane = \"queue\" | \"steer\";\n\nconst getQueueItemParts = (\n message: AppendMessage,\n): readonly (FileMessagePart | TextMessagePart)[] => {\n // attachment-derived text is the file body, not user-authored prose;\n // project only the file/image content of attachments\n const source = [\n ...message.content,\n ...(message.attachments ?? []).flatMap((attachment) =>\n (attachment.content ?? []).filter((part) => part.type !== \"text\"),\n ),\n ];\n const parts: (FileMessagePart | TextMessagePart)[] = [];\n for (const part of source) {\n if (part.type === \"file\" || part.type === \"text\") {\n parts.push(part);\n } else if (part.type === \"image\") {\n parts.push({\n type: \"file\",\n data: part.image,\n mimeType: \"image/*\",\n ...(part.filename !== undefined && { filename: part.filename }),\n });\n }\n }\n return parts;\n};\n\nexport const createMessageQueue = (\n driver: MessageQueueDriver,\n): MessageQueueController => {\n let lanes: Record<Lane, readonly QueueItemState[]> = {\n queue: EMPTY_QUEUE_ITEMS,\n steer: EMPTY_QUEUE_ITEMS,\n };\n const messages = new Map<string, AppendMessage>();\n const subscribers = new Set<() => void>();\n\n let running = false;\n let paused = false;\n // swallow the cancelled run's settle when steering so it does not double-advance\n let suppressIdle = 0;\n // settles from cancelled runs that must drop `running` without advancing\n let cancelSettles = 0;\n\n const notify = () => {\n for (const callback of subscribers) callback();\n };\n\n const setLanes = (next: Record<Lane, readonly QueueItemState[]>) => {\n lanes = next;\n adapter.items = next.queue;\n adapter.steerItems = next.steer;\n notify();\n };\n\n const toItem = (id: string, message: AppendMessage): QueueItemState => ({\n id,\n prompt: getThreadMessageText(message),\n parts: getQueueItemParts(message),\n });\n\n const laneOf = (queueItemId: string): Lane | undefined => {\n if (lanes.steer.some((item) => item.id === queueItemId)) return \"steer\";\n if (lanes.queue.some((item) => item.id === queueItemId)) return \"queue\";\n return undefined;\n };\n\n const advance = () => {\n if (running || paused) return;\n const lane: Lane = lanes.steer.length > 0 ? \"steer\" : \"queue\";\n const head = lanes[lane][0];\n if (!head) return;\n const message = messages.get(head.id);\n messages.delete(head.id);\n setLanes({ ...lanes, [lane]: lanes[lane].slice(1) });\n if (!message) return;\n running = true;\n driver.run(message, { steer: false });\n };\n\n const interrupt = (message: AppendMessage) => {\n paused = false;\n // the interrupted run settles exactly once, whether or not it was\n // already cancel-notified\n suppressIdle += Math.max(cancelSettles, 1);\n cancelSettles = 0;\n driver.cancel!();\n running = true;\n driver.run(message, { steer: true });\n };\n\n const push = (lane: Lane, message: AppendMessage) => {\n paused = false;\n const id = generateId();\n messages.set(id, message);\n setLanes({ ...lanes, [lane]: [...lanes[lane], toItem(id, message)] });\n advance();\n };\n\n const enqueue = (message: AppendMessage) => {\n push(\"queue\", message);\n };\n\n const steer = (message: AppendMessage) => {\n if (running && driver.cancel) {\n interrupt(message);\n return;\n }\n push(\"steer\", message);\n };\n\n const move = (queueItemId: string, placement: QueuePlacement) => {\n const fromLane = laneOf(queueItemId);\n if (!fromLane) throw new Error(`Unknown queue item \"${queueItemId}\".`);\n const toLane = placement.lane ?? fromLane;\n\n const item = lanes[fromLane].find((i) => i.id === queueItemId)!;\n const dest = (toLane === fromLane ? lanes[fromLane] : lanes[toLane]).filter(\n (i) => i.id !== queueItemId,\n );\n\n const anchorIndex = (anchor: string) => {\n if (anchor === queueItemId)\n throw new Error(`Queue item \"${queueItemId}\" cannot anchor itself.`);\n const index = dest.findIndex((i) => i.id === anchor);\n if (index === -1)\n throw new Error(`Unknown anchor \"${anchor}\" in lane \"${toLane}\".`);\n return index;\n };\n\n const { insertAfter, insertBefore } = placement;\n let index: number;\n if (insertAfter === undefined && insertBefore === undefined) {\n index =\n toLane === fromLane\n ? lanes[fromLane].findIndex((i) => i.id === queueItemId)\n : dest.length;\n } else if (insertAfter !== undefined && insertBefore !== undefined) {\n const after = insertAfter === null ? -1 : anchorIndex(insertAfter);\n const before =\n insertBefore === null ? dest.length : anchorIndex(insertBefore);\n if (before !== after + 1)\n throw new Error(\n `insertAfter \"${insertAfter}\" and insertBefore \"${insertBefore}\" are not adjacent in lane \"${toLane}\".`,\n );\n index = after + 1;\n } else if (insertAfter !== undefined) {\n index = insertAfter === null ? 0 : anchorIndex(insertAfter) + 1;\n } else {\n index = insertBefore === null ? dest.length : anchorIndex(insertBefore!);\n }\n\n // placement and immediate dispatch cannot coexist: an anchored move into\n // the steer lane places without interrupting; only an unanchored one\n // cancels the live run and dispatches\n if (\n insertAfter === undefined &&\n insertBefore === undefined &&\n toLane === \"steer\" &&\n fromLane !== \"steer\" &&\n running &&\n driver.cancel\n ) {\n const message = messages.get(queueItemId)!;\n messages.delete(queueItemId);\n setLanes({\n queue: lanes.queue.filter((i) => i.id !== queueItemId),\n steer: lanes.steer,\n });\n interrupt(message);\n return;\n }\n\n const nextDest = [...dest.slice(0, index), item, ...dest.slice(index)];\n const next = { ...lanes, [toLane]: nextDest };\n if (toLane !== fromLane)\n next[fromLane] = lanes[fromLane].filter((i) => i.id !== queueItemId);\n setLanes(next);\n advance();\n };\n\n const edit = (queueItemId: string, message: AppendMessage) => {\n const lane = laneOf(queueItemId);\n if (!lane) throw new Error(`Unknown queue item \"${queueItemId}\".`);\n messages.set(queueItemId, message);\n setLanes({\n ...lanes,\n [lane]: lanes[lane].map((item) =>\n item.id === queueItemId ? toItem(queueItemId, message) : item,\n ),\n });\n };\n\n const remove = (queueItemId: string) => {\n if (!messages.delete(queueItemId)) return;\n setLanes({\n queue: lanes.queue.filter((item) => item.id !== queueItemId),\n steer: lanes.steer.filter((item) => item.id !== queueItemId),\n });\n };\n\n const adapter: ExternalThreadQueueAdapter = {\n items: lanes.queue,\n steerItems: lanes.steer,\n enqueue,\n steer,\n move,\n edit,\n remove,\n };\n\n return {\n adapter,\n notifyBusy: () => {\n paused = false;\n // a cancelled run's settle that is still outstanding belongs to a run\n // this new one replaces; swallow it entirely\n suppressIdle += cancelSettles;\n cancelSettles = 0;\n running = true;\n },\n notifyIdle: () => {\n if (suppressIdle > 0) {\n suppressIdle--;\n return;\n }\n if (cancelSettles > 0) cancelSettles--;\n running = false;\n advance();\n },\n notifyCancelled: () => {\n if (running && cancelSettles === 0) {\n paused = true;\n cancelSettles = 1;\n }\n },\n clear: () => {\n messages.clear();\n setLanes({ queue: EMPTY_QUEUE_ITEMS, steer: EMPTY_QUEUE_ITEMS });\n },\n subscribe: (callback) => {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n },\n };\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"thread-message-like.d.ts","names":[],"sources":["../../../src/runtime/utils/thread-message-like.ts"],"mappings":";;;;KAgCK;WACM;WACA;;KAGC;WACD;WACA,4BAGD,kBACA,uBACA,oBACA,mBACA,kBACA,kBACA,0BACA,4BACA;aAEW;aACA;aACA;aACA,OAAO;aACP;aACA;aACA;aACA;aACA;aACA,oBAAoB;aACpB;MAAc;MAAe;;aAC7B,SAAS;aACT,mBAAmB;aACnB;eACE;eACA;eACA;eACA;eACA,mBAAmB;eACnB;eACA;;;WAIZ;WACA,YAAY;WACZ,SAAS;WACT,wBACK,KAAK;aACJ,mBAAmB,wBAAwB;;WAGjD;aAEM,iBAAiB;aACjB,gCACI;aAEJ,yBAAyB;aACzB,iBAAiB;aACjB,SAAS;aACT;eAA+B;;aAC/B;aACA,SAAS;;;;;;cAgBb,wBACX,MAAM,mBACN,oBACA,gBAAgB,kBACf"}
1
+ {"version":3,"file":"thread-message-like.d.ts","names":[],"sources":["../../../src/runtime/utils/thread-message-like.ts"],"mappings":";;;;KAiCK;WACM;WACA;;KAGC;WACD;WACA,4BAGD,kBACA,uBACA,oBACA,mBACA,kBACA,kBACA,0BACA,4BACA;aAEW;aACA;aACA;aACA,OAAO;aACP;aACA;aACA;aACA;aACA;aACA,oBAAoB;aACpB;MAAc;MAAe;;aAC7B,SAAS;aACT,mBAAmB;aACnB;eACE;eACA;eACA;eACA;eACA,mBAAmB;eACnB;eACA;;;WAIZ;WACA,YAAY;WACZ,SAAS;WACT,wBACK,KAAK;aACJ,mBAAmB,wBAAwB;;WAGjD;aAEM,iBAAiB;aACjB,gCACI;aAEJ,yBAAyB;aACzB,iBAAiB;aACjB,SAAS;aACT;eAA+B;;aAC/B;aACA,SAAS;;;;;;cAgBb,wBACX,MAAM,mBACN,oBACA,gBAAgB,kBACf"}
@@ -1,4 +1,5 @@
1
1
  import { generateId } from "../../utils/id.js";
2
+ import { parseDataUrl } from "../../utils/data-url.js";
2
3
  import { parsePartialJsonObject } from "assistant-stream/utils";
3
4
  //#region src/runtime/utils/thread-message-like.ts
4
5
  const convertDataPrefixedPart = (type, data) => {
@@ -24,7 +25,7 @@ const fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
24
25
  }] : like.content;
25
26
  const sanitizeImageContent = ({ image, ...rest }) => {
26
27
  if (typeof image !== "string") return null;
27
- if (image.match(/^data:image\/(png|jpeg|jpg|gif|webp|svg\+xml);base64,(.*)$/i)) return {
28
+ if (parseDataUrl(image)?.mimeType.startsWith("image/")) return {
28
29
  ...rest,
29
30
  image
30
31
  };
@@ -1 +1 @@
1
- {"version":3,"file":"thread-message-like.js","names":["parsePartialJsonObject","generateId","ReasoningMessagePart","SourceMessagePart","ThreadStep","MessageStatus","ImageMessagePart","ThreadMessage","ThreadAssistantMessagePart","ThreadAssistantMessage","ThreadUserMessagePart","ThreadUserMessage","ThreadSystemMessage","FileMessagePart","DataMessagePart","GenerativeUIMessagePart","Unstable_AudioMessagePart","CompleteAttachment","MessageTiming","PartProviderMetadata","TextMessagePart","ToolApprovalOption","ToolCallTiming","ReadonlyJSONObject","ReadonlyJSONValue","DataPrefixedPart","type","data","ThreadMessageLike","role","content","toolCallId","toolName","args","argsText","artifact","result","isError","parentId","messages","interrupt","payload","timing","providerMetadata","approval","id","approved","reason","isAutomatic","options","optionId","resolution","createdAt","Date","status","attachments","Omit","metadata","unstable_state","unstable_annotations","unstable_data","steps","submittedFeedback","isOptimistic","custom","Record","convertDataPrefixedPart","startsWith","undefined","name","substring","fromThreadMessageLike","like","fallbackId","fallbackStatus","common","const","text","sanitizeImageContent","image","rest","dataUri","match","test","console","warn","length","Error","map","part","trim","basePart","commonProps","JSON","stringify","converted","filter","c","att","unsupportedRole"],"sources":["../../../src/runtime/utils/thread-message-like.ts"],"sourcesContent":["import { parsePartialJsonObject } from \"assistant-stream/utils\";\nimport { generateId } from \"../../utils/id\";\nimport type {\n ReasoningMessagePart,\n SourceMessagePart,\n ThreadStep,\n MessageStatus,\n ImageMessagePart,\n ThreadMessage,\n ThreadAssistantMessagePart,\n ThreadAssistantMessage,\n ThreadUserMessagePart,\n ThreadUserMessage,\n ThreadSystemMessage,\n FileMessagePart,\n DataMessagePart,\n GenerativeUIMessagePart,\n Unstable_AudioMessagePart,\n} from \"../../types/message\";\nimport type { CompleteAttachment } from \"../../types/attachment\";\nimport type {\n MessageTiming,\n PartProviderMetadata,\n TextMessagePart,\n ToolApprovalOption,\n ToolCallTiming,\n} from \"../../types/message\";\nimport type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"assistant-stream/utils\";\n\ntype DataPrefixedPart = {\n readonly type: `data-${string}`;\n readonly data: any;\n};\n\nexport type ThreadMessageLike = {\n readonly role: \"assistant\" | \"user\" | \"system\";\n readonly content:\n | string\n | readonly (\n | TextMessagePart\n | ReasoningMessagePart\n | SourceMessagePart\n | ImageMessagePart\n | FileMessagePart\n | DataMessagePart\n | GenerativeUIMessagePart\n | Unstable_AudioMessagePart\n | DataPrefixedPart\n | {\n readonly type: \"tool-call\";\n readonly toolCallId?: string;\n readonly toolName: string;\n readonly args?: ReadonlyJSONObject;\n readonly argsText?: string;\n readonly artifact?: any;\n readonly result?: any | undefined;\n readonly isError?: boolean | undefined;\n readonly parentId?: string | undefined;\n readonly messages?: readonly ThreadMessage[] | undefined;\n readonly interrupt?: { type: \"human\"; payload: unknown };\n readonly timing?: ToolCallTiming;\n readonly providerMetadata?: PartProviderMetadata;\n readonly approval?: {\n readonly id: string;\n readonly approved?: boolean;\n readonly reason?: string;\n readonly isAutomatic?: boolean;\n readonly options?: readonly ToolApprovalOption[];\n readonly optionId?: string;\n readonly resolution?: \"cancelled\" | \"expired\";\n };\n }\n )[];\n readonly id?: string | undefined;\n readonly createdAt?: Date | undefined;\n readonly status?: MessageStatus | undefined;\n readonly attachments?:\n | readonly (Omit<CompleteAttachment, \"content\"> & {\n readonly content: readonly (ThreadUserMessagePart | DataPrefixedPart)[];\n })[]\n | undefined;\n readonly metadata?:\n | {\n readonly unstable_state?: ReadonlyJSONValue;\n readonly unstable_annotations?:\n | readonly ReadonlyJSONValue[]\n | undefined;\n readonly unstable_data?: readonly ReadonlyJSONValue[] | undefined;\n readonly steps?: readonly ThreadStep[] | undefined;\n readonly timing?: MessageTiming | undefined;\n readonly submittedFeedback?: { readonly type: \"positive\" | \"negative\" };\n readonly isOptimistic?: boolean | undefined;\n readonly custom?: Record<string, unknown> | undefined;\n }\n | undefined;\n};\n\nconst convertDataPrefixedPart = (\n type: string,\n data: unknown,\n): DataMessagePart | undefined => {\n if (!type.startsWith(\"data-\")) return undefined;\n return { type: \"data\", name: type.substring(5), data };\n};\n\n/**\n * @deprecated This API is experimental and may change without notice.\n */\nexport const fromThreadMessageLike = (\n like: ThreadMessageLike,\n fallbackId: string,\n fallbackStatus: MessageStatus,\n): ThreadMessage => {\n const { role, id, createdAt, attachments, status, metadata } = like;\n const common = {\n id: id ?? fallbackId,\n createdAt: createdAt ?? new Date(),\n };\n\n const content =\n typeof like.content === \"string\"\n ? [{ type: \"text\" as const, text: like.content }]\n : like.content;\n\n const sanitizeImageContent = ({\n image,\n ...rest\n }: ImageMessagePart): ImageMessagePart | null => {\n if (typeof image !== \"string\") return null;\n const dataUri = image.match(\n /^data:image\\/(png|jpeg|jpg|gif|webp|svg\\+xml);base64,(.*)$/i,\n );\n if (dataUri) {\n return { ...rest, image };\n }\n if (/^(https:\\/\\/|blob:)/i.test(image)) {\n return { ...rest, image };\n }\n console.warn(`Invalid image data format detected`);\n return null;\n };\n\n if (role !== \"user\" && attachments?.length)\n throw new Error(\"attachments are only supported for user messages\");\n\n if (role !== \"assistant\" && status)\n throw new Error(\"status is only supported for assistant messages\");\n\n if (role !== \"assistant\" && metadata?.steps)\n throw new Error(\"metadata.steps is only supported for assistant messages\");\n\n switch (role) {\n case \"assistant\":\n return {\n ...common,\n role,\n content: content\n .map((part): ThreadAssistantMessagePart | null => {\n const type = part.type;\n switch (type) {\n case \"text\":\n case \"reasoning\":\n if (!part.text?.trim()) return null;\n return part;\n\n case \"file\":\n case \"source\":\n return part;\n\n case \"image\":\n return sanitizeImageContent(part);\n\n case \"data\":\n return part;\n\n case \"generative-ui\":\n return part;\n\n case \"tool-call\": {\n const { parentId, messages, ...basePart } = part;\n const commonProps = {\n ...basePart,\n toolCallId: part.toolCallId ?? `tool-${generateId()}`,\n ...(parentId !== undefined && { parentId }),\n ...(messages !== undefined && { messages }),\n };\n\n if (part.args) {\n return {\n ...commonProps,\n args: part.args,\n argsText: part.argsText ?? JSON.stringify(part.args),\n };\n }\n return {\n ...commonProps,\n args: parsePartialJsonObject(part.argsText ?? \"\") ?? {},\n argsText: part.argsText ?? \"\",\n };\n }\n\n default: {\n const converted = convertDataPrefixedPart(\n type,\n (part as DataPrefixedPart).data,\n );\n if (converted) return converted;\n throw new Error(\n `Unsupported assistant message part type: ${type}`,\n );\n }\n }\n })\n .filter((c) => !!c),\n status: status ?? fallbackStatus,\n metadata: {\n unstable_state: metadata?.unstable_state ?? null,\n unstable_annotations: metadata?.unstable_annotations ?? [],\n unstable_data: metadata?.unstable_data ?? [],\n custom: metadata?.custom ?? {},\n steps: metadata?.steps ?? [],\n ...(metadata?.timing && { timing: metadata.timing }),\n ...(metadata?.submittedFeedback && {\n submittedFeedback: metadata.submittedFeedback,\n }),\n ...(metadata?.isOptimistic && { isOptimistic: true }),\n },\n } satisfies ThreadAssistantMessage;\n\n case \"user\":\n return {\n ...common,\n role,\n content: content.map((part): ThreadUserMessagePart => {\n const type = part.type;\n switch (type) {\n case \"text\":\n case \"image\":\n case \"audio\":\n case \"file\":\n case \"data\":\n return part;\n\n default: {\n const converted = convertDataPrefixedPart(\n type,\n (part as DataPrefixedPart).data,\n );\n if (converted) return converted;\n throw new Error(`Unsupported user message part type: ${type}`);\n }\n }\n }),\n attachments: (attachments ?? []).map((att) => ({\n ...att,\n content: att.content.map((part): ThreadUserMessagePart => {\n const converted = convertDataPrefixedPart(\n part.type,\n (part as DataPrefixedPart).data,\n );\n return converted ?? (part as ThreadUserMessagePart);\n }),\n })),\n metadata: {\n custom: metadata?.custom ?? {},\n ...(metadata?.isOptimistic && { isOptimistic: true }),\n },\n } satisfies ThreadUserMessage;\n\n case \"system\":\n if (content.length !== 1 || content[0]!.type !== \"text\")\n throw new Error(\n \"System messages must have exactly one text message part.\",\n );\n\n return {\n ...common,\n role,\n content: content as [TextMessagePart],\n metadata: {\n custom: metadata?.custom ?? {},\n },\n } satisfies ThreadSystemMessage;\n\n default: {\n const unsupportedRole: never = role;\n throw new Error(`Unknown message role: ${unsupportedRole}`);\n }\n }\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"thread-message-like.js","names":["parsePartialJsonObject","generateId","parseDataUrl","ReasoningMessagePart","SourceMessagePart","ThreadStep","MessageStatus","ImageMessagePart","ThreadMessage","ThreadAssistantMessagePart","ThreadAssistantMessage","ThreadUserMessagePart","ThreadUserMessage","ThreadSystemMessage","FileMessagePart","DataMessagePart","GenerativeUIMessagePart","Unstable_AudioMessagePart","CompleteAttachment","MessageTiming","PartProviderMetadata","TextMessagePart","ToolApprovalOption","ToolCallTiming","ReadonlyJSONObject","ReadonlyJSONValue","DataPrefixedPart","type","data","ThreadMessageLike","role","content","toolCallId","toolName","args","argsText","artifact","result","isError","parentId","messages","interrupt","payload","timing","providerMetadata","approval","id","approved","reason","isAutomatic","options","optionId","resolution","createdAt","Date","status","attachments","Omit","metadata","unstable_state","unstable_annotations","unstable_data","steps","submittedFeedback","isOptimistic","custom","Record","convertDataPrefixedPart","startsWith","undefined","name","substring","fromThreadMessageLike","like","fallbackId","fallbackStatus","common","const","text","sanitizeImageContent","image","rest","mimeType","test","console","warn","length","Error","map","part","trim","basePart","commonProps","JSON","stringify","converted","filter","c","att","unsupportedRole"],"sources":["../../../src/runtime/utils/thread-message-like.ts"],"sourcesContent":["import { parsePartialJsonObject } from \"assistant-stream/utils\";\nimport { generateId } from \"../../utils/id\";\nimport { parseDataUrl } from \"../../utils/data-url\";\nimport type {\n ReasoningMessagePart,\n SourceMessagePart,\n ThreadStep,\n MessageStatus,\n ImageMessagePart,\n ThreadMessage,\n ThreadAssistantMessagePart,\n ThreadAssistantMessage,\n ThreadUserMessagePart,\n ThreadUserMessage,\n ThreadSystemMessage,\n FileMessagePart,\n DataMessagePart,\n GenerativeUIMessagePart,\n Unstable_AudioMessagePart,\n} from \"../../types/message\";\nimport type { CompleteAttachment } from \"../../types/attachment\";\nimport type {\n MessageTiming,\n PartProviderMetadata,\n TextMessagePart,\n ToolApprovalOption,\n ToolCallTiming,\n} from \"../../types/message\";\nimport type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"assistant-stream/utils\";\n\ntype DataPrefixedPart = {\n readonly type: `data-${string}`;\n readonly data: any;\n};\n\nexport type ThreadMessageLike = {\n readonly role: \"assistant\" | \"user\" | \"system\";\n readonly content:\n | string\n | readonly (\n | TextMessagePart\n | ReasoningMessagePart\n | SourceMessagePart\n | ImageMessagePart\n | FileMessagePart\n | DataMessagePart\n | GenerativeUIMessagePart\n | Unstable_AudioMessagePart\n | DataPrefixedPart\n | {\n readonly type: \"tool-call\";\n readonly toolCallId?: string;\n readonly toolName: string;\n readonly args?: ReadonlyJSONObject;\n readonly argsText?: string;\n readonly artifact?: any;\n readonly result?: any | undefined;\n readonly isError?: boolean | undefined;\n readonly parentId?: string | undefined;\n readonly messages?: readonly ThreadMessage[] | undefined;\n readonly interrupt?: { type: \"human\"; payload: unknown };\n readonly timing?: ToolCallTiming;\n readonly providerMetadata?: PartProviderMetadata;\n readonly approval?: {\n readonly id: string;\n readonly approved?: boolean;\n readonly reason?: string;\n readonly isAutomatic?: boolean;\n readonly options?: readonly ToolApprovalOption[];\n readonly optionId?: string;\n readonly resolution?: \"cancelled\" | \"expired\";\n };\n }\n )[];\n readonly id?: string | undefined;\n readonly createdAt?: Date | undefined;\n readonly status?: MessageStatus | undefined;\n readonly attachments?:\n | readonly (Omit<CompleteAttachment, \"content\"> & {\n readonly content: readonly (ThreadUserMessagePart | DataPrefixedPart)[];\n })[]\n | undefined;\n readonly metadata?:\n | {\n readonly unstable_state?: ReadonlyJSONValue;\n readonly unstable_annotations?:\n | readonly ReadonlyJSONValue[]\n | undefined;\n readonly unstable_data?: readonly ReadonlyJSONValue[] | undefined;\n readonly steps?: readonly ThreadStep[] | undefined;\n readonly timing?: MessageTiming | undefined;\n readonly submittedFeedback?: { readonly type: \"positive\" | \"negative\" };\n readonly isOptimistic?: boolean | undefined;\n readonly custom?: Record<string, unknown> | undefined;\n }\n | undefined;\n};\n\nconst convertDataPrefixedPart = (\n type: string,\n data: unknown,\n): DataMessagePart | undefined => {\n if (!type.startsWith(\"data-\")) return undefined;\n return { type: \"data\", name: type.substring(5), data };\n};\n\n/**\n * @deprecated This API is experimental and may change without notice.\n */\nexport const fromThreadMessageLike = (\n like: ThreadMessageLike,\n fallbackId: string,\n fallbackStatus: MessageStatus,\n): ThreadMessage => {\n const { role, id, createdAt, attachments, status, metadata } = like;\n const common = {\n id: id ?? fallbackId,\n createdAt: createdAt ?? new Date(),\n };\n\n const content =\n typeof like.content === \"string\"\n ? [{ type: \"text\" as const, text: like.content }]\n : like.content;\n\n const sanitizeImageContent = ({\n image,\n ...rest\n }: ImageMessagePart): ImageMessagePart | null => {\n if (typeof image !== \"string\") return null;\n if (parseDataUrl(image)?.mimeType.startsWith(\"image/\")) {\n return { ...rest, image };\n }\n if (/^(https:\\/\\/|blob:)/i.test(image)) {\n return { ...rest, image };\n }\n console.warn(`Invalid image data format detected`);\n return null;\n };\n\n if (role !== \"user\" && attachments?.length)\n throw new Error(\"attachments are only supported for user messages\");\n\n if (role !== \"assistant\" && status)\n throw new Error(\"status is only supported for assistant messages\");\n\n if (role !== \"assistant\" && metadata?.steps)\n throw new Error(\"metadata.steps is only supported for assistant messages\");\n\n switch (role) {\n case \"assistant\":\n return {\n ...common,\n role,\n content: content\n .map((part): ThreadAssistantMessagePart | null => {\n const type = part.type;\n switch (type) {\n case \"text\":\n case \"reasoning\":\n if (!part.text?.trim()) return null;\n return part;\n\n case \"file\":\n case \"source\":\n return part;\n\n case \"image\":\n return sanitizeImageContent(part);\n\n case \"data\":\n return part;\n\n case \"generative-ui\":\n return part;\n\n case \"tool-call\": {\n const { parentId, messages, ...basePart } = part;\n const commonProps = {\n ...basePart,\n toolCallId: part.toolCallId ?? `tool-${generateId()}`,\n ...(parentId !== undefined && { parentId }),\n ...(messages !== undefined && { messages }),\n };\n\n if (part.args) {\n return {\n ...commonProps,\n args: part.args,\n argsText: part.argsText ?? JSON.stringify(part.args),\n };\n }\n return {\n ...commonProps,\n args: parsePartialJsonObject(part.argsText ?? \"\") ?? {},\n argsText: part.argsText ?? \"\",\n };\n }\n\n default: {\n const converted = convertDataPrefixedPart(\n type,\n (part as DataPrefixedPart).data,\n );\n if (converted) return converted;\n throw new Error(\n `Unsupported assistant message part type: ${type}`,\n );\n }\n }\n })\n .filter((c) => !!c),\n status: status ?? fallbackStatus,\n metadata: {\n unstable_state: metadata?.unstable_state ?? null,\n unstable_annotations: metadata?.unstable_annotations ?? [],\n unstable_data: metadata?.unstable_data ?? [],\n custom: metadata?.custom ?? {},\n steps: metadata?.steps ?? [],\n ...(metadata?.timing && { timing: metadata.timing }),\n ...(metadata?.submittedFeedback && {\n submittedFeedback: metadata.submittedFeedback,\n }),\n ...(metadata?.isOptimistic && { isOptimistic: true }),\n },\n } satisfies ThreadAssistantMessage;\n\n case \"user\":\n return {\n ...common,\n role,\n content: content.map((part): ThreadUserMessagePart => {\n const type = part.type;\n switch (type) {\n case \"text\":\n case \"image\":\n case \"audio\":\n case \"file\":\n case \"data\":\n return part;\n\n default: {\n const converted = convertDataPrefixedPart(\n type,\n (part as DataPrefixedPart).data,\n );\n if (converted) return converted;\n throw new Error(`Unsupported user message part type: ${type}`);\n }\n }\n }),\n attachments: (attachments ?? []).map((att) => ({\n ...att,\n content: att.content.map((part): ThreadUserMessagePart => {\n const converted = convertDataPrefixedPart(\n part.type,\n (part as DataPrefixedPart).data,\n );\n return converted ?? (part as ThreadUserMessagePart);\n }),\n })),\n metadata: {\n custom: metadata?.custom ?? {},\n ...(metadata?.isOptimistic && { isOptimistic: true }),\n },\n } satisfies ThreadUserMessage;\n\n case \"system\":\n if (content.length !== 1 || content[0]!.type !== \"text\")\n throw new Error(\n \"System messages must have exactly one text message part.\",\n );\n\n return {\n ...common,\n role,\n content: content as [TextMessagePart],\n metadata: {\n custom: metadata?.custom ?? {},\n },\n } satisfies ThreadSystemMessage;\n\n default: {\n const unsupportedRole: never = role;\n throw new Error(`Unknown message role: ${unsupportedRole}`);\n }\n }\n};\n"],"mappings":"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"}
@@ -5,9 +5,9 @@ import { DictationAdapter, SpeechSynthesisAdapter } from "../../adapters/speech.
5
5
  import { RealtimeVoiceAdapter } from "../../adapters/voice.js";
6
6
  import { ThreadMessageLike } from "../../runtime/utils/thread-message-like.js";
7
7
  import { ExportedMessageRepository } from "../../runtime/utils/message-repository.js";
8
+ import { ExternalThreadQueueAdapter } from "../../runtime/queue/external-thread-queue-adapter.js";
8
9
  import { AddToolResultOptions, RespondToToolApprovalOptions, ResumeRunConfig, StartRunConfig, ThreadSuggestion } from "../../runtime/interfaces/thread-runtime-core.js";
9
10
  import { ToolExecutionStatus } from "../tool-invocations/ToolInvocationTracker.js";
10
- import { ExternalThreadQueueAdapter } from "../../runtime/queue/external-thread-queue-adapter.js";
11
11
  import { ReadonlyJSONValue } from "assistant-stream/utils";
12
12
  //#region src/runtimes/external-store/external-store-adapter.d.ts
13
13
  type ExternalStoreThreadData<TState extends "regular" | "archived"> = {