spectrum-ts 1.1.1 → 1.1.2

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.
@@ -672,29 +672,36 @@ var extractExtras = (raw, definition) => {
672
672
  const extra = Object.fromEntries(entries);
673
673
  return definition.message?.schema ? definition.message.schema.parse(extra) : extra;
674
674
  };
675
- function wrapProviderMessage(raw, ctx) {
676
- const wrappedContent = wrapNestedContent(raw.content, ctx);
677
- return buildMessage({
675
+ function wrapProviderMessage(raw, ctx, direction) {
676
+ const wrappedContent = wrapNestedContent(raw.content, ctx, direction);
677
+ const base = {
678
678
  id: raw.id,
679
679
  content: wrappedContent,
680
- sender: raw.sender,
681
680
  timestamp: raw.timestamp ?? /* @__PURE__ */ new Date(),
682
681
  extras: extractExtras(raw, ctx.definition),
683
682
  spaceRef: ctx.spaceRef,
684
683
  space: ctx.space,
685
684
  definition: ctx.definition,
686
685
  client: ctx.client,
687
- config: ctx.config,
688
- direction: "inbound"
689
- });
686
+ config: ctx.config
687
+ };
688
+ if (direction === "inbound") {
689
+ if (!raw.sender) {
690
+ throw new Error(
691
+ `Inbound provider message missing sender (platform "${ctx.definition.name}", id "${raw.id}")`
692
+ );
693
+ }
694
+ return buildMessage({ ...base, sender: raw.sender, direction: "inbound" });
695
+ }
696
+ return buildMessage({ ...base, sender: raw.sender, direction: "outbound" });
690
697
  }
691
- var wrapNestedContent = (content, ctx) => {
698
+ var wrapNestedContent = (content, ctx, direction) => {
692
699
  if (content.type === "reaction") {
693
700
  const target = content.target;
694
701
  if (isRawProviderRecord(target)) {
695
702
  return {
696
703
  ...content,
697
- target: wrapProviderMessage(target, ctx)
704
+ target: wrapProviderMessage(target, ctx, "inbound")
698
705
  };
699
706
  }
700
707
  return content;
@@ -702,7 +709,10 @@ var wrapNestedContent = (content, ctx) => {
702
709
  if (content.type === "group") {
703
710
  const items = content.items.map((item) => {
704
711
  const raw = item;
705
- return isRawProviderRecord(raw) ? wrapProviderMessage(raw, ctx) : item;
712
+ if (!isRawProviderRecord(raw)) {
713
+ return item;
714
+ }
715
+ return direction === "inbound" ? wrapProviderMessage(raw, ctx, "inbound") : wrapProviderMessage(raw, ctx, "outbound");
706
716
  });
707
717
  return { ...content, items };
708
718
  }
@@ -739,9 +749,9 @@ function buildSpace(params) {
739
749
  }
740
750
  }
741
751
  async function dispatchSend(item) {
742
- let sendResult;
752
+ let raw;
743
753
  try {
744
- sendResult = await definition.actions.send({
754
+ raw = await definition.actions.send({
745
755
  ...typingCtx,
746
756
  content: item
747
757
  });
@@ -752,46 +762,16 @@ function buildSpace(params) {
752
762
  }
753
763
  throw err;
754
764
  }
755
- if (!sendResult?.id) {
765
+ if (!raw?.id) {
756
766
  throw new Error(
757
767
  `Platform "${definition.name}" send did not return a message id`
758
768
  );
759
769
  }
760
- const outboundContent = item.type === "group" && sendResult.groupMembers ? {
761
- ...item,
762
- items: item.items.map((stub, idx) => {
763
- const member = sendResult?.groupMembers?.[idx];
764
- if (!member?.id) {
765
- return stub;
766
- }
767
- return buildMessage({
768
- id: member.id,
769
- content: stub.content,
770
- sender: member.sender,
771
- timestamp: member.timestamp ?? /* @__PURE__ */ new Date(),
772
- extras: {},
773
- spaceRef,
774
- space,
775
- definition,
776
- client,
777
- config,
778
- direction: "outbound"
779
- });
780
- })
781
- } : item;
782
- return buildMessage({
783
- id: sendResult.id,
784
- content: outboundContent,
785
- sender: sendResult.sender,
786
- timestamp: sendResult.timestamp ?? /* @__PURE__ */ new Date(),
787
- extras: {},
788
- spaceRef,
789
- space,
790
- definition,
791
- client,
792
- config,
793
- direction: "outbound"
794
- });
770
+ return wrapProviderMessage(
771
+ raw,
772
+ { client, config, definition, space, spaceRef },
773
+ "outbound"
774
+ );
795
775
  }
796
776
  async function sendImpl(...content) {
797
777
  const resolved = await resolveContents(content);
@@ -837,13 +817,11 @@ function buildSpace(params) {
837
817
  if (!raw) {
838
818
  return;
839
819
  }
840
- return wrapProviderMessage(raw, {
841
- client,
842
- config,
843
- definition,
844
- space,
845
- spaceRef
846
- });
820
+ return wrapProviderMessage(
821
+ raw,
822
+ { client, config, definition, space, spaceRef },
823
+ "inbound"
824
+ );
847
825
  }
848
826
  space = {
849
827
  ...extras,
@@ -912,9 +890,9 @@ function buildMessage(params) {
912
890
  return self;
913
891
  };
914
892
  const dispatchReplyItem = async (item, target, replyToMessage) => {
915
- let sendResult;
893
+ let raw;
916
894
  try {
917
- sendResult = await replyToMessage({
895
+ raw = await replyToMessage({
918
896
  space: spaceRef,
919
897
  messageId: params.id,
920
898
  target,
@@ -929,24 +907,16 @@ function buildMessage(params) {
929
907
  }
930
908
  throw err;
931
909
  }
932
- if (!sendResult?.id) {
910
+ if (!raw?.id) {
933
911
  throw new Error(
934
912
  `Platform "${definition.name}" reply did not return a message id`
935
913
  );
936
914
  }
937
- return buildMessage({
938
- id: sendResult.id,
939
- content: item,
940
- sender: sendResult.sender,
941
- timestamp: sendResult.timestamp ?? /* @__PURE__ */ new Date(),
942
- extras: {},
943
- spaceRef,
944
- space,
945
- definition,
946
- client,
947
- config,
948
- direction: "outbound"
949
- });
915
+ return wrapProviderMessage(
916
+ raw,
917
+ { client, config, definition, space, spaceRef },
918
+ "outbound"
919
+ );
950
920
  };
951
921
  async function reply(...content) {
952
922
  const replyToMessage = definition.actions.replyToMessage;
@@ -1146,6 +1116,14 @@ function createPlatformInstance(def, runtime) {
1146
1116
  });
1147
1117
  }
1148
1118
  }
1119
+ let messagesIterable;
1120
+ Object.defineProperty(base, "messages", {
1121
+ enumerable: true,
1122
+ get() {
1123
+ messagesIterable ??= runtime.subscribeMessages();
1124
+ return messagesIterable;
1125
+ }
1126
+ });
1149
1127
  return Object.assign(base, eventProperties);
1150
1128
  }
1151
1129
  function definePlatform(name, def) {
@@ -108,6 +108,87 @@ function mergeStreams(streams) {
108
108
  };
109
109
  });
110
110
  }
111
+ function broadcast(source) {
112
+ const consumers = /* @__PURE__ */ new Set();
113
+ let pumping = false;
114
+ let terminated = false;
115
+ let terminalError;
116
+ let pumpPromise;
117
+ let closed = false;
118
+ const startPump = () => {
119
+ if (pumping || terminated) {
120
+ return;
121
+ }
122
+ pumping = true;
123
+ pumpPromise = (async () => {
124
+ try {
125
+ for await (const value of source) {
126
+ for (const consumer of consumers) {
127
+ consumer.deliveries = consumer.deliveries.then(
128
+ () => consumer.emit(value).catch(() => {
129
+ })
130
+ );
131
+ }
132
+ }
133
+ terminated = true;
134
+ await Promise.allSettled(
135
+ Array.from(consumers, (consumer) => consumer.deliveries)
136
+ );
137
+ for (const consumer of consumers) {
138
+ consumer.end();
139
+ }
140
+ consumers.clear();
141
+ } catch (error) {
142
+ terminated = true;
143
+ terminalError = error;
144
+ for (const consumer of consumers) {
145
+ consumer.end(error);
146
+ }
147
+ consumers.clear();
148
+ }
149
+ })();
150
+ };
151
+ return {
152
+ subscribe() {
153
+ return stream((emit, end) => {
154
+ if (terminated) {
155
+ end(terminalError);
156
+ return;
157
+ }
158
+ const consumer = {
159
+ emit,
160
+ end,
161
+ deliveries: Promise.resolve()
162
+ };
163
+ consumers.add(consumer);
164
+ startPump();
165
+ return () => {
166
+ consumers.delete(consumer);
167
+ };
168
+ });
169
+ },
170
+ async close() {
171
+ if (closed) {
172
+ return;
173
+ }
174
+ closed = true;
175
+ try {
176
+ await source.close();
177
+ if (pumpPromise) {
178
+ await pumpPromise;
179
+ }
180
+ } finally {
181
+ if (!terminated) {
182
+ terminated = true;
183
+ for (const consumer of consumers) {
184
+ consumer.end();
185
+ }
186
+ consumers.clear();
187
+ }
188
+ }
189
+ }
190
+ };
191
+ }
111
192
 
112
193
  // src/utils/cloud.ts
113
194
  var SPECTRUM_CLOUD_URL = `https://${process.env.SPECTRUM_CLOUD_URL ?? "spectrum.photon.codes"}`;
@@ -183,6 +264,7 @@ export {
183
264
  poll,
184
265
  stream,
185
266
  mergeStreams,
267
+ broadcast,
186
268
  SpectrumCloudError,
187
269
  cloud
188
270
  };
@@ -2,7 +2,7 @@ import {
2
2
  bufferToStream,
3
3
  readSchema,
4
4
  streamSchema
5
- } from "./chunk-7D6FHYKT.js";
5
+ } from "./chunk-5GQ2OMFY.js";
6
6
 
7
7
  // src/content/voice.ts
8
8
  import { createReadStream } from "fs";
@@ -3,7 +3,7 @@ import {
3
3
  readSchema,
4
4
  resolveContents,
5
5
  streamSchema
6
- } from "./chunk-7D6FHYKT.js";
6
+ } from "./chunk-5GQ2OMFY.js";
7
7
 
8
8
  // src/content/group.ts
9
9
  import z from "zod";
@@ -163,6 +163,7 @@ function richlink(url) {
163
163
 
164
164
  export {
165
165
  groupSchema,
166
+ asGroup,
166
167
  group,
167
168
  asRichlink,
168
169
  richlink
package/dist/index.d.ts CHANGED
@@ -1,8 +1,7 @@
1
- import { C as ContentBuilder, U as User, M as Message, a as ContentInput, b as Content, P as ProviderMessage, c as PlatformDef, d as Platform, e as PlatformProviderConfig, S as SpectrumLike, f as CustomEventStreams, g as Space, I as InboundMessage, O as OutboundMessage } from './types-BZhWdyLk.js';
2
- export { A as AnyPlatformDef, E as EventProducer, h as PlatformInstance, i as PlatformMessage, j as PlatformSpace, k as PlatformUser, l as SchemaMessage } from './types-BZhWdyLk.js';
1
+ import { C as ContentBuilder, U as User, M as Message, a as ContentInput, b as Content, P as ProviderMessage, c as PlatformDef, d as Platform, e as PlatformProviderConfig, S as SpectrumLike, f as CustomEventStreams, g as Space, I as InboundMessage, O as OutboundMessage } from './types-GhOtIIqj.js';
2
+ export { A as AnyPlatformDef, B as Broadcaster, E as EventProducer, h as InboundPlatformMessage, i as ManagedStream, j as PlatformInstance, k as PlatformMessage, l as PlatformRuntime, m as PlatformSpace, n as PlatformUser, o as SchemaMessage, p as broadcast, q as mergeStreams, s as stream } from './types-GhOtIIqj.js';
3
3
  import vCard from 'vcf';
4
4
  import z__default from 'zod';
5
- export { M as ManagedStream, m as mergeStreams, s as stream } from './stream-B55k7W8-.js';
6
5
  import 'hotscript';
7
6
 
8
7
  declare function attachment(input: string | Buffer, options?: {
package/dist/index.js CHANGED
@@ -1,18 +1,19 @@
1
1
  import {
2
2
  group,
3
3
  richlink
4
- } from "./chunk-TY3RT4OB.js";
4
+ } from "./chunk-UWUPCIB4.js";
5
5
  import {
6
6
  voice
7
- } from "./chunk-7VSE6V3Q.js";
7
+ } from "./chunk-QZ5DJ7VR.js";
8
8
  import {
9
9
  SpectrumCloudError,
10
+ broadcast,
10
11
  cloud,
11
12
  mergeStreams,
12
13
  option,
13
14
  poll,
14
15
  stream
15
- } from "./chunk-PXX7ISZ6.js";
16
+ } from "./chunk-FF2R4EP3.js";
16
17
  import {
17
18
  UnsupportedError,
18
19
  attachment,
@@ -26,7 +27,7 @@ import {
26
27
  text,
27
28
  toVCard,
28
29
  wrapProviderMessage
29
- } from "./chunk-7D6FHYKT.js";
30
+ } from "./chunk-5GQ2OMFY.js";
30
31
 
31
32
  // src/emoji/generated.ts
32
33
  var GeneratedEmoji = {
@@ -1986,23 +1987,9 @@ async function Spectrum(options) {
1986
1987
  } = options;
1987
1988
  const flattenGroups = runtimeOptions?.flattenGroups ?? false;
1988
1989
  const platformStates = /* @__PURE__ */ new Map();
1990
+ const messageBroadcasters = /* @__PURE__ */ new Map();
1989
1991
  const customEventStreams = /* @__PURE__ */ new Map();
1990
1992
  let stopped = false;
1991
- for (const provider of providers) {
1992
- const providerConfig = provider;
1993
- const def = providerConfig.__definition;
1994
- const userConfig = def.config.parse(providerConfig.config);
1995
- const client = await def.lifecycle.createClient({
1996
- config: userConfig,
1997
- projectId,
1998
- projectSecret
1999
- });
2000
- platformStates.set(def.name, {
2001
- client,
2002
- config: userConfig,
2003
- definition: def
2004
- });
2005
- }
2006
1993
  const adaptIterable = (iterable) => {
2007
1994
  return stream((emit, end) => {
2008
1995
  const iterator = iterable[Symbol.asyncIterator]();
@@ -2045,13 +2032,17 @@ async function Spectrum(options) {
2045
2032
  client,
2046
2033
  config
2047
2034
  });
2048
- const normalizedMessage = wrapProviderMessage(msg, {
2049
- client,
2050
- config,
2051
- definition,
2052
- space,
2053
- spaceRef
2054
- });
2035
+ const normalizedMessage = wrapProviderMessage(
2036
+ msg,
2037
+ {
2038
+ client,
2039
+ config,
2040
+ definition,
2041
+ space,
2042
+ spaceRef
2043
+ },
2044
+ "inbound"
2045
+ );
2055
2046
  if (flattenGroups && normalizedMessage.content.type === "group") {
2056
2047
  for (const item of normalizedMessage.content.items) {
2057
2048
  yield [space, item];
@@ -2063,10 +2054,46 @@ async function Spectrum(options) {
2063
2054
  };
2064
2055
  return adaptIterable(bindSend());
2065
2056
  };
2057
+ const getOrCreateMessageBroadcast = (state) => {
2058
+ if (stopped) {
2059
+ throw new Error(
2060
+ `Spectrum instance has been stopped; cannot subscribe to "${state.definition.name}" messages`
2061
+ );
2062
+ }
2063
+ const name = state.definition.name;
2064
+ let broadcaster = messageBroadcasters.get(name);
2065
+ if (!broadcaster) {
2066
+ broadcaster = broadcast(createProviderMessagesStream(state));
2067
+ messageBroadcasters.set(name, broadcaster);
2068
+ }
2069
+ return broadcaster;
2070
+ };
2071
+ for (const provider of providers) {
2072
+ const providerConfig = provider;
2073
+ const def = providerConfig.__definition;
2074
+ const userConfig = def.config.parse(providerConfig.config);
2075
+ const client = await def.lifecycle.createClient({
2076
+ config: userConfig,
2077
+ projectId,
2078
+ projectSecret
2079
+ });
2080
+ const state = {
2081
+ client,
2082
+ config: userConfig,
2083
+ definition: def
2084
+ };
2085
+ platformStates.set(def.name, {
2086
+ ...state,
2087
+ subscribeMessages: () => getOrCreateMessageBroadcast(state).subscribe()
2088
+ });
2089
+ }
2066
2090
  const createMessagesStream = () => {
2067
2091
  return stream((emit, end) => {
2068
2092
  const merged = mergeStreams(
2069
- Array.from(platformStates.values(), createProviderMessagesStream)
2093
+ Array.from(
2094
+ platformStates.values(),
2095
+ (runtime) => runtime.subscribeMessages()
2096
+ )
2070
2097
  );
2071
2098
  const pump = (async () => {
2072
2099
  try {
@@ -2130,6 +2157,10 @@ async function Spectrum(options) {
2130
2157
  ...Array.from(
2131
2158
  customEventStreams.values(),
2132
2159
  (eventStream) => eventStream.close()
2160
+ ),
2161
+ ...Array.from(
2162
+ messageBroadcasters.values(),
2163
+ (broadcaster) => broadcaster.close()
2133
2164
  )
2134
2165
  ];
2135
2166
  process.off("SIGINT", handleSignal);
@@ -2143,6 +2174,7 @@ async function Spectrum(options) {
2143
2174
  );
2144
2175
  await Promise.allSettled(clientShutdowns);
2145
2176
  customEventStreams.clear();
2177
+ messageBroadcasters.clear();
2146
2178
  platformStates.clear();
2147
2179
  };
2148
2180
  const handleSignal = () => {
@@ -2200,6 +2232,7 @@ export {
2200
2232
  SpectrumCloudError,
2201
2233
  UnsupportedError,
2202
2234
  attachment,
2235
+ broadcast,
2203
2236
  cloud,
2204
2237
  contact,
2205
2238
  custom,
@@ -1,5 +1,4 @@
1
- import { M as ManagedStream } from '../../stream-B55k7W8-.js';
2
- import { l as SchemaMessage, d as Platform, c as PlatformDef, P as ProviderMessage } from '../../types-BZhWdyLk.js';
1
+ import { o as SchemaMessage, d as Platform, c as PlatformDef, P as ProviderMessage, i as ManagedStream } from '../../types-GhOtIIqj.js';
3
2
  import * as zod_v4_core from 'zod/v4/core';
4
3
  import * as z from 'zod';
5
4
  import z__default from 'zod';
@@ -1,14 +1,15 @@
1
1
  import {
2
+ asGroup,
2
3
  asRichlink,
3
4
  groupSchema
4
- } from "../../chunk-TY3RT4OB.js";
5
+ } from "../../chunk-UWUPCIB4.js";
5
6
  import {
6
7
  asPoll,
7
8
  asPollOption,
8
9
  cloud,
9
10
  mergeStreams,
10
11
  stream
11
- } from "../../chunk-PXX7ISZ6.js";
12
+ } from "../../chunk-FF2R4EP3.js";
12
13
  import {
13
14
  UnsupportedError,
14
15
  asAttachment,
@@ -19,7 +20,7 @@ import {
19
20
  fromVCard,
20
21
  reactionSchema,
21
22
  toVCard
22
- } from "../../chunk-7D6FHYKT.js";
23
+ } from "../../chunk-5GQ2OMFY.js";
23
24
 
24
25
  // src/providers/imessage/index.ts
25
26
  import { createClient as createClient2, directChat } from "@photon-ai/advanced-imessage";
@@ -232,8 +233,10 @@ var unsupportedRemoteContent = (type, detail) => UnsupportedError.content(type,
232
233
  var unsupportedLocalContent = (type) => UnsupportedError.content(type, LOCAL_IMESSAGE_PLATFORM);
233
234
 
234
235
  // src/providers/imessage/local/send.ts
235
- var synthSendResult = () => ({
236
+ var synthRecord = (spaceId, content) => ({
236
237
  id: crypto.randomUUID(),
238
+ content,
239
+ space: { id: spaceId },
237
240
  timestamp: /* @__PURE__ */ new Date()
238
241
  });
239
242
  var sendTempFile = async (client, spaceId, name, data) => {
@@ -252,10 +255,10 @@ var send = async (client, spaceId, content) => {
252
255
  switch (content.type) {
253
256
  case "text":
254
257
  await client.send({ to: spaceId, text: content.text });
255
- return synthSendResult();
258
+ return synthRecord(spaceId, content);
256
259
  case "attachment":
257
260
  await sendTempFile(client, spaceId, content.name, await content.read());
258
- return synthSendResult();
261
+ return synthRecord(spaceId, content);
259
262
  case "contact": {
260
263
  const vcf = await toVCard(content);
261
264
  await sendTempFile(
@@ -264,7 +267,7 @@ var send = async (client, spaceId, content) => {
264
267
  vcardFileName(content),
265
268
  Buffer.from(vcf, "utf8")
266
269
  );
267
- return synthSendResult();
270
+ return synthRecord(spaceId, content);
268
271
  }
269
272
  case "poll":
270
273
  throw unsupportedLocalContent("poll");
@@ -927,20 +930,12 @@ var ensureM4a = async (buffer, mimeType) => {
927
930
 
928
931
  // src/providers/imessage/remote/send.ts
929
932
  var GROUP_ITEM_ALLOWED = /* @__PURE__ */ new Set([
933
+ "text",
930
934
  "attachment",
931
935
  "contact",
932
936
  "voice"
933
937
  ]);
934
- var PartialGroupSendError = class extends Error {
935
- cause;
936
- groupMembers;
937
- constructor(groupMembers, cause) {
938
- super("iMessage group send failed after one or more items were sent");
939
- this.name = "PartialGroupSendError";
940
- this.cause = cause;
941
- this.groupMembers = groupMembers;
942
- }
943
- };
938
+ var MAX_GROUP_TEXT_ITEMS = 1;
944
939
  var toDate = (value) => {
945
940
  if (value instanceof Date) {
946
941
  return value;
@@ -951,15 +946,19 @@ var toDate = (value) => {
951
946
  }
952
947
  };
953
948
  var receiptTimestamp = (receipt) => toDate(receipt.timestamp) ?? toDate(receipt.date) ?? toDate(receipt.dateCreated) ?? /* @__PURE__ */ new Date();
954
- var toSendResult = (receipt) => {
949
+ var receiptGuid = (receipt) => {
955
950
  if (typeof receipt.guid !== "string" || receipt.guid.length === 0) {
956
951
  throw new Error("iMessage send receipt is missing a message guid");
957
952
  }
958
- return {
959
- id: receipt.guid,
960
- timestamp: receiptTimestamp(receipt)
961
- };
953
+ return receipt.guid;
962
954
  };
955
+ var outboundRecord = (spaceId, id, content, timestamp, extras) => ({
956
+ id,
957
+ content,
958
+ space: { id: spaceId },
959
+ timestamp,
960
+ ...extras
961
+ });
963
962
  var withReply = (options, replyTo) => replyTo ? { ...options, replyTo } : options;
964
963
  var replyOptions = (replyTo) => replyTo ? { replyTo } : void 0;
965
964
  var sendVCardAttachment = (remote, name, vcf) => remote.attachments.upload({
@@ -969,8 +968,9 @@ var sendVCardAttachment = (remote, name, vcf) => remote.attachments.upload({
969
968
  });
970
969
  var sendContactAttachment = async (remote, content) => {
971
970
  const vcf = await toVCard(content);
972
- const upload = await sendVCardAttachment(remote, vcardFileName(content), vcf);
973
- return upload.guid;
971
+ const name = vcardFileName(content);
972
+ const upload = await sendVCardAttachment(remote, name, vcf);
973
+ return { guid: upload.guid, name };
974
974
  };
975
975
  var uploadAttachment = async (remote, content) => {
976
976
  const attachment = await remote.attachments.upload({
@@ -978,53 +978,86 @@ var uploadAttachment = async (remote, content) => {
978
978
  fileName: content.name,
979
979
  mimeType: content.mimeType
980
980
  });
981
- return attachment.guid;
981
+ return { guid: attachment.guid, name: content.name };
982
982
  };
983
983
  var uploadVoice = async (remote, content) => {
984
984
  const { buffer } = await ensureM4a(await content.read(), content.mimeType);
985
+ const name = content.name ?? "voice.m4a";
985
986
  const attachment = await remote.attachments.upload({
986
987
  data: buffer,
987
- fileName: content.name ?? "voice.m4a",
988
+ fileName: name,
988
989
  mimeType: "audio/x-m4a"
989
990
  });
990
- return attachment.guid;
991
+ return { guid: attachment.guid, name };
991
992
  };
992
- var sendContent = async (remote, chat, content, replyTo) => {
993
+ var sendContent = async (remote, spaceId, chat, content, replyTo) => {
993
994
  switch (content.type) {
994
- case "text":
995
- return toSendResult(
996
- await remote.messages.send(chat, content.text, withReply({}, replyTo))
995
+ case "text": {
996
+ const receipt = await remote.messages.send(
997
+ chat,
998
+ content.text,
999
+ withReply({}, replyTo)
997
1000
  );
998
- case "richlink":
999
- return toSendResult(
1000
- await remote.messages.send(
1001
- chat,
1002
- content.url,
1003
- withReply({ richLink: true }, replyTo)
1004
- )
1001
+ return outboundRecord(
1002
+ spaceId,
1003
+ receiptGuid(receipt),
1004
+ content,
1005
+ receiptTimestamp(receipt)
1005
1006
  );
1006
- case "attachment":
1007
- return toSendResult(
1008
- await remote.messages.send(chat, "", {
1009
- attachment: await uploadAttachment(remote, content),
1010
- ...replyOptions(replyTo)
1011
- })
1007
+ }
1008
+ case "richlink": {
1009
+ const receipt = await remote.messages.send(
1010
+ chat,
1011
+ content.url,
1012
+ withReply({ richLink: true }, replyTo)
1012
1013
  );
1013
- case "contact":
1014
- return toSendResult(
1015
- await remote.messages.send(chat, "", {
1016
- attachment: await sendContactAttachment(remote, content),
1017
- ...replyOptions(replyTo)
1018
- })
1014
+ return outboundRecord(
1015
+ spaceId,
1016
+ receiptGuid(receipt),
1017
+ content,
1018
+ receiptTimestamp(receipt)
1019
1019
  );
1020
- case "voice":
1021
- return toSendResult(
1022
- await remote.messages.send(chat, "", {
1023
- attachment: await uploadVoice(remote, content),
1024
- audioMessage: true,
1025
- ...replyOptions(replyTo)
1026
- })
1020
+ }
1021
+ case "attachment": {
1022
+ const { guid } = await uploadAttachment(remote, content);
1023
+ const receipt = await remote.messages.send(chat, "", {
1024
+ attachment: guid,
1025
+ ...replyOptions(replyTo)
1026
+ });
1027
+ return outboundRecord(
1028
+ spaceId,
1029
+ receiptGuid(receipt),
1030
+ content,
1031
+ receiptTimestamp(receipt)
1027
1032
  );
1033
+ }
1034
+ case "contact": {
1035
+ const { guid } = await sendContactAttachment(remote, content);
1036
+ const receipt = await remote.messages.send(chat, "", {
1037
+ attachment: guid,
1038
+ ...replyOptions(replyTo)
1039
+ });
1040
+ return outboundRecord(
1041
+ spaceId,
1042
+ receiptGuid(receipt),
1043
+ content,
1044
+ receiptTimestamp(receipt)
1045
+ );
1046
+ }
1047
+ case "voice": {
1048
+ const { guid } = await uploadVoice(remote, content);
1049
+ const receipt = await remote.messages.send(chat, "", {
1050
+ attachment: guid,
1051
+ audioMessage: true,
1052
+ ...replyOptions(replyTo)
1053
+ });
1054
+ return outboundRecord(
1055
+ spaceId,
1056
+ receiptGuid(receipt),
1057
+ content,
1058
+ receiptTimestamp(receipt)
1059
+ );
1060
+ }
1028
1061
  case "poll":
1029
1062
  if (replyTo) {
1030
1063
  throw unsupportedRemoteContent(
@@ -1032,18 +1065,24 @@ var sendContent = async (remote, chat, content, replyTo) => {
1032
1065
  "polls cannot be sent as replies"
1033
1066
  );
1034
1067
  }
1035
- return toSendResult(
1036
- await remote.polls.create(
1037
- chat,
1038
- content.title,
1039
- content.options.map((option) => option.title)
1040
- )
1068
+ return outboundRecord(
1069
+ spaceId,
1070
+ receiptGuid(
1071
+ await remote.polls.create(
1072
+ chat,
1073
+ content.title,
1074
+ content.options.map((option) => option.title)
1075
+ )
1076
+ ),
1077
+ content,
1078
+ /* @__PURE__ */ new Date()
1041
1079
  );
1042
1080
  default:
1043
1081
  throw unsupportedRemoteContent(content.type);
1044
1082
  }
1045
1083
  };
1046
1084
  var validateGroupContent = (content) => {
1085
+ let textCount = 0;
1047
1086
  for (const sub of content.items) {
1048
1087
  const itemType = sub.content.type;
1049
1088
  if (!GROUP_ITEM_ALLOWED.has(itemType)) {
@@ -1052,32 +1091,69 @@ var validateGroupContent = (content) => {
1052
1091
  `"${itemType}" items are not supported inside a group`
1053
1092
  );
1054
1093
  }
1094
+ if (itemType === "text" && ++textCount > MAX_GROUP_TEXT_ITEMS) {
1095
+ throw unsupportedRemoteContent(
1096
+ "group",
1097
+ `groups can contain at most ${MAX_GROUP_TEXT_ITEMS} text item`
1098
+ );
1099
+ }
1100
+ }
1101
+ };
1102
+ var resolvePart = async (remote, content) => {
1103
+ switch (content.type) {
1104
+ case "text":
1105
+ return { text: content.text };
1106
+ case "attachment": {
1107
+ const { guid, name } = await uploadAttachment(remote, content);
1108
+ return { attachmentGuid: guid, attachmentName: name };
1109
+ }
1110
+ case "contact": {
1111
+ const { guid, name } = await sendContactAttachment(remote, content);
1112
+ return { attachmentGuid: guid, attachmentName: name };
1113
+ }
1114
+ case "voice": {
1115
+ const { guid, name } = await uploadVoice(remote, content);
1116
+ return { attachmentGuid: guid, attachmentName: name };
1117
+ }
1118
+ default:
1119
+ throw unsupportedRemoteContent(content.type);
1055
1120
  }
1056
1121
  };
1057
1122
  var send3 = async (remote, spaceId, content) => {
1058
1123
  const chat = chatGuid2(spaceId);
1059
1124
  if (content.type === "group") {
1060
1125
  validateGroupContent(content);
1061
- const groupMembers = [];
1062
- try {
1063
- for (const sub of content.items) {
1064
- groupMembers.push(await sendContent(remote, chat, sub.content));
1065
- }
1066
- } catch (err) {
1067
- throw new PartialGroupSendError(groupMembers, err);
1068
- }
1069
- const first = groupMembers[0];
1070
- if (!first) {
1071
- throw new Error("Empty group");
1072
- }
1073
- return { ...first, groupMembers };
1126
+ const resolved = await Promise.all(
1127
+ content.items.map((sub) => resolvePart(remote, sub.content))
1128
+ );
1129
+ const receipt = await remote.messages.sendMultipart(
1130
+ chat,
1131
+ resolved.map((part, idx) => ({ ...part, partIndex: idx }))
1132
+ );
1133
+ const parentGuid = receiptGuid(receipt);
1134
+ const timestamp = receiptTimestamp(receipt);
1135
+ const items = content.items.map(
1136
+ (sub, idx) => outboundRecord(
1137
+ spaceId,
1138
+ formatChildId(idx, parentGuid),
1139
+ sub.content,
1140
+ timestamp,
1141
+ { partIndex: idx, parentId: parentGuid }
1142
+ )
1143
+ );
1144
+ return outboundRecord(
1145
+ spaceId,
1146
+ parentGuid,
1147
+ asGroup({ items }),
1148
+ timestamp
1149
+ );
1074
1150
  }
1075
- return sendContent(remote, chat, content);
1151
+ return sendContent(remote, spaceId, chat, content);
1076
1152
  };
1077
1153
  var replyToMessage = async (remote, spaceId, msgId, content) => {
1078
1154
  const chat = chatGuid2(spaceId);
1079
1155
  const replyTo = messageGuid3(msgId);
1080
- return sendContent(remote, chat, content, replyTo);
1156
+ return sendContent(remote, spaceId, chat, content, replyTo);
1081
1157
  };
1082
1158
  var editMessage = async (remote, spaceId, msgId, content) => {
1083
1159
  if (content.type !== "text") {
@@ -1,4 +1,4 @@
1
- import { d as Platform, c as PlatformDef, P as ProviderMessage, M as Message } from '../../types-BZhWdyLk.js';
1
+ import { d as Platform, c as PlatformDef, P as ProviderMessage, M as Message } from '../../types-GhOtIIqj.js';
2
2
  import z__default from 'zod';
3
3
  import 'hotscript';
4
4
 
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  asVoice
3
- } from "../../chunk-7VSE6V3Q.js";
3
+ } from "../../chunk-QZ5DJ7VR.js";
4
4
  import {
5
5
  UnsupportedError,
6
6
  asAttachment,
@@ -10,7 +10,7 @@ import {
10
10
  fromVCard,
11
11
  reactionSchema,
12
12
  toVCard
13
- } from "../../chunk-7D6FHYKT.js";
13
+ } from "../../chunk-5GQ2OMFY.js";
14
14
 
15
15
  // src/providers/terminal/index.ts
16
16
  import { spawn } from "child_process";
@@ -601,6 +601,14 @@ function parseTimestamp(s) {
601
601
  const t = Date.parse(s);
602
602
  return Number.isNaN(t) ? /* @__PURE__ */ new Date() : new Date(t);
603
603
  }
604
+ function buildOutboundRecord(result, content, spaceId) {
605
+ return {
606
+ id: result.id,
607
+ content,
608
+ space: { id: spaceId },
609
+ timestamp: parseTimestamp(result.timestamp)
610
+ };
611
+ }
604
612
  function reactionTargetFromProtocol(reaction) {
605
613
  const target = {
606
614
  id: reaction.messageId,
@@ -810,7 +818,7 @@ var terminal = definePlatform("terminal", {
810
818
  "send",
811
819
  { spaceId: space.id, content: proto }
812
820
  );
813
- return { id: result.id, timestamp: parseTimestamp(result.timestamp) };
821
+ return buildOutboundRecord(result, content, space.id);
814
822
  },
815
823
  startTyping: async ({ client, space }) => {
816
824
  const c = client;
@@ -835,7 +843,7 @@ var terminal = definePlatform("terminal", {
835
843
  "replyToMessage",
836
844
  { spaceId: space.id, messageId, content: proto }
837
845
  );
838
- return { id: result.id, timestamp: parseTimestamp(result.timestamp) };
846
+ return buildOutboundRecord(result, content, space.id);
839
847
  }
840
848
  }
841
849
  });
@@ -1,8 +1,7 @@
1
- import { M as ManagedStream } from '../../stream-B55k7W8-.js';
1
+ import { o as SchemaMessage, d as Platform, c as PlatformDef, P as ProviderMessage, i as ManagedStream } from '../../types-GhOtIIqj.js';
2
2
  import { WhatsAppClient } from '@photon-ai/whatsapp-business';
3
3
  import * as z from 'zod';
4
4
  import z__default from 'zod';
5
- import { l as SchemaMessage, d as Platform, c as PlatformDef, P as ProviderMessage } from '../../types-BZhWdyLk.js';
6
5
  import * as zod_v4_core from 'zod/v4/core';
7
6
  import 'hotscript';
8
7
 
@@ -3,7 +3,7 @@ import {
3
3
  cloud,
4
4
  mergeStreams,
5
5
  stream
6
- } from "../../chunk-PXX7ISZ6.js";
6
+ } from "../../chunk-FF2R4EP3.js";
7
7
  import {
8
8
  UnsupportedError,
9
9
  asAttachment,
@@ -12,7 +12,7 @@ import {
12
12
  asReaction,
13
13
  asText,
14
14
  definePlatform
15
- } from "../../chunk-7D6FHYKT.js";
15
+ } from "../../chunk-5GQ2OMFY.js";
16
16
 
17
17
  // src/providers/whatsapp-business/index.ts
18
18
  import { createClient as createClient2 } from "@photon-ai/whatsapp-business";
@@ -266,8 +266,11 @@ var primary = (clients) => {
266
266
  }
267
267
  return client;
268
268
  };
269
- var toSendResult = (result) => ({
270
- id: result.messageId
269
+ var toRecord = (result, spaceId, content) => ({
270
+ id: result.messageId,
271
+ content,
272
+ space: { id: spaceId },
273
+ timestamp: /* @__PURE__ */ new Date()
271
274
  });
272
275
  var MAX_POLL_CACHE_SIZE = 1e3;
273
276
  var OPTION_ID_PREFIX = "opt_";
@@ -622,8 +625,10 @@ var send = async (clients, spaceId, content) => {
622
625
  const client = primary(clients);
623
626
  switch (content.type) {
624
627
  case "text":
625
- return toSendResult(
626
- await client.messages.send({ to: spaceId, text: content.text })
628
+ return toRecord(
629
+ await client.messages.send({ to: spaceId, text: content.text }),
630
+ spaceId,
631
+ content
627
632
  );
628
633
  case "attachment": {
629
634
  const { mediaId } = await client.media.upload({
@@ -633,19 +638,23 @@ var send = async (clients, spaceId, content) => {
633
638
  });
634
639
  const mediaType = mimeToMediaType(content.mimeType);
635
640
  const mediaPayload = mediaType === "document" ? { id: mediaId, filename: content.name } : { id: mediaId };
636
- return toSendResult(
641
+ return toRecord(
637
642
  await client.messages.send({
638
643
  to: spaceId,
639
644
  [mediaType]: mediaPayload
640
- })
645
+ }),
646
+ spaceId,
647
+ content
641
648
  );
642
649
  }
643
650
  case "contact":
644
- return toSendResult(
651
+ return toRecord(
645
652
  await client.messages.send({
646
653
  to: spaceId,
647
654
  contacts: [contactToWa(content)]
648
- })
655
+ }),
656
+ spaceId,
657
+ content
649
658
  );
650
659
  case "voice": {
651
660
  const { mediaId } = await client.media.upload({
@@ -653,11 +662,13 @@ var send = async (clients, spaceId, content) => {
653
662
  mimeType: content.mimeType,
654
663
  filename: voiceFilename(content)
655
664
  });
656
- return toSendResult(
665
+ return toRecord(
657
666
  await client.messages.send({
658
667
  to: spaceId,
659
668
  audio: { id: mediaId }
660
- })
669
+ }),
670
+ spaceId,
671
+ content
661
672
  );
662
673
  }
663
674
  case "poll": {
@@ -666,7 +677,7 @@ var send = async (clients, spaceId, content) => {
666
677
  interactive: pollToInteractive(content)
667
678
  });
668
679
  cachePoll(client, result.messageId, content);
669
- return toSendResult(result);
680
+ return toRecord(result, spaceId, content);
670
681
  }
671
682
  default:
672
683
  throw UnsupportedError.content(content.type);
@@ -682,12 +693,14 @@ var replyToMessage = async (clients, spaceId, messageId, content) => {
682
693
  const client = primary(clients);
683
694
  switch (content.type) {
684
695
  case "text":
685
- return toSendResult(
696
+ return toRecord(
686
697
  await client.messages.send({
687
698
  to: spaceId,
688
699
  replyTo: messageId,
689
700
  text: content.text
690
- })
701
+ }),
702
+ spaceId,
703
+ content
691
704
  );
692
705
  case "attachment": {
693
706
  const { mediaId } = await client.media.upload({
@@ -697,21 +710,25 @@ var replyToMessage = async (clients, spaceId, messageId, content) => {
697
710
  });
698
711
  const mediaType = mimeToMediaType(content.mimeType);
699
712
  const mediaPayload = mediaType === "document" ? { id: mediaId, filename: content.name } : { id: mediaId };
700
- return toSendResult(
713
+ return toRecord(
701
714
  await client.messages.send({
702
715
  to: spaceId,
703
716
  replyTo: messageId,
704
717
  [mediaType]: mediaPayload
705
- })
718
+ }),
719
+ spaceId,
720
+ content
706
721
  );
707
722
  }
708
723
  case "contact":
709
- return toSendResult(
724
+ return toRecord(
710
725
  await client.messages.send({
711
726
  to: spaceId,
712
727
  replyTo: messageId,
713
728
  contacts: [contactToWa(content)]
714
- })
729
+ }),
730
+ spaceId,
731
+ content
715
732
  );
716
733
  case "voice": {
717
734
  const { mediaId } = await client.media.upload({
@@ -719,12 +736,14 @@ var replyToMessage = async (clients, spaceId, messageId, content) => {
719
736
  mimeType: content.mimeType,
720
737
  filename: voiceFilename(content)
721
738
  });
722
- return toSendResult(
739
+ return toRecord(
723
740
  await client.messages.send({
724
741
  to: spaceId,
725
742
  replyTo: messageId,
726
743
  audio: { id: mediaId }
727
- })
744
+ }),
745
+ spaceId,
746
+ content
728
747
  );
729
748
  }
730
749
  case "poll": {
@@ -734,7 +753,7 @@ var replyToMessage = async (clients, spaceId, messageId, content) => {
734
753
  interactive: pollToInteractive(content)
735
754
  });
736
755
  cachePoll(client, result.messageId, content);
737
- return toSendResult(result);
756
+ return toRecord(result, spaceId, content);
738
757
  }
739
758
  default:
740
759
  throw UnsupportedError.content(content.type);
@@ -166,6 +166,18 @@ interface OutboundMessage<TPlatform extends string = string, TSender extends Use
166
166
  }
167
167
  type Message<TPlatform extends string = string, TSender extends User = User, TSpace extends Space = Space> = InboundMessage<TPlatform, TSender, TSpace> | OutboundMessage<TPlatform, TSender, TSpace>;
168
168
 
169
+ interface ManagedStream<T> extends AsyncIterable<T> {
170
+ close(): Promise<void>;
171
+ }
172
+ type StreamCleanup = void | (() => void | Promise<void>);
173
+ declare function stream<T>(setup: (emit: (value: T) => Promise<void>, end: (error?: unknown) => void) => StreamCleanup | Promise<StreamCleanup>): ManagedStream<T>;
174
+ declare function mergeStreams<T>(streams: readonly ManagedStream<T>[]): ManagedStream<T>;
175
+ interface Broadcaster<T> {
176
+ close(): Promise<void>;
177
+ subscribe(): ManagedStream<T>;
178
+ }
179
+ declare function broadcast<T>(source: ManagedStream<T>): Broadcaster<T>;
180
+
169
181
  type ResolvedSpace = Pick<Space, "id">;
170
182
  type SpaceRef = Pick<Space, "id" | "__platform">;
171
183
  type ResolvedUser = Pick<User, "id">;
@@ -187,19 +199,28 @@ type ProviderMessage<TSender extends ResolvedUser = ResolvedUser, TSpace extends
187
199
  space: TSpace;
188
200
  timestamp?: Date;
189
201
  } & TExtra;
190
- interface SendResult<TSender extends ResolvedUser = ResolvedUser> {
191
- /**
192
- * Per-item send receipts returned when the dispatched content was a
193
- * `group`. Providers that iterate native sends to emulate a group
194
- * (e.g. iMessage) populate this so the platform build layer can
195
- * replace the outbound group's placeholder items with real Messages
196
- * that carry each item's own id.
197
- */
198
- groupMembers?: SendResult<TSender>[];
202
+ /**
203
+ * A message a provider produced — used for both inbound (`events.messages`,
204
+ * `getMessage`) and outbound (`send`, `replyToMessage`) flows. Providers
205
+ * return their native record shape (including platform extras like
206
+ * `partIndex`/`parentId` for iMessage) and the platform `wrapProviderMessage`
207
+ * pipeline turns it into a fully-built Message.
208
+ *
209
+ * `sender` is optional because outbound sends often can't synthesize one
210
+ * (the SDK doesn't surface the bot's own handle); inbound providers are
211
+ * expected to populate it.
212
+ */
213
+ type ProviderMessageRecord = {
199
214
  id: string;
200
- sender?: TSender;
215
+ content: Content;
216
+ sender?: {
217
+ id: string;
218
+ } & Record<string, unknown>;
219
+ space: {
220
+ id: string;
221
+ } & Record<string, unknown>;
201
222
  timestamp?: Date;
202
- }
223
+ } & Record<string, unknown>;
203
224
  type MergeSchema<TSchema extends z__default.ZodType | undefined, TBase extends object> = TSchema extends z__default.ZodType ? string extends keyof z__default.infer<TSchema> ? TBase : Omit<z__default.infer<TSchema>, keyof TBase> & TBase : TBase;
204
225
  type SchemaMessage<TUserSchema extends z__default.ZodType | undefined = undefined, TSpaceSchema extends z__default.ZodType | undefined = undefined> = ProviderMessage<MergeSchema<TUserSchema, ResolvedUser>, MergeSchema<TSpaceSchema, ResolvedSpace>>;
205
226
  type InferEventPayload<T> = T extends (ctx: never) => AsyncIterable<infer P> ? P : never;
@@ -215,7 +236,7 @@ interface PlatformDef<_Name extends string = string, _ConfigSchema extends z__de
215
236
  content: Content;
216
237
  client: _Client;
217
238
  config: z__default.infer<_ConfigSchema>;
218
- }) => Promise<SendResult<_ResolvedUser>>;
239
+ }) => Promise<ProviderMessageRecord>;
219
240
  startTyping?: (_: {
220
241
  space: _ResolvedSpace & SpaceRef;
221
242
  client: _Client;
@@ -240,7 +261,7 @@ interface PlatformDef<_Name extends string = string, _ConfigSchema extends z__de
240
261
  content: Content;
241
262
  client: _Client;
242
263
  config: z__default.infer<_ConfigSchema>;
243
- }) => Promise<SendResult<_ResolvedUser>>;
264
+ }) => Promise<ProviderMessageRecord>;
244
265
  editMessage?: (_: {
245
266
  space: _ResolvedSpace & SpaceRef;
246
267
  messageId: string;
@@ -298,11 +319,11 @@ interface PlatformDef<_Name extends string = string, _ConfigSchema extends z__de
298
319
  }
299
320
  interface AnyPlatformDef {
300
321
  actions: {
301
- send: (_: any) => Promise<SendResult>;
322
+ send: (_: any) => Promise<ProviderMessageRecord>;
302
323
  startTyping?: (_: any) => Promise<void>;
303
324
  stopTyping?: (_: any) => Promise<void>;
304
325
  reactToMessage?: (_: any) => Promise<void>;
305
- replyToMessage?: (_: any) => Promise<SendResult>;
326
+ replyToMessage?: (_: any) => Promise<ProviderMessageRecord>;
306
327
  editMessage?: (_: any) => Promise<void>;
307
328
  getMessage?: (_: any) => Promise<any>;
308
329
  };
@@ -380,20 +401,27 @@ type SpaceVarargArgs<Def extends AnyPlatformDef> = [
380
401
  type SpaceArgs<Def extends AnyPlatformDef> = SpaceArrayArgs<Def> | SpaceVarargArgs<Def>;
381
402
  type PlatformSpace<Def extends AnyPlatformDef> = Omit<SpaceShapeOf<Def>, keyof Space> & Space;
382
403
  type PlatformMessage<Def extends AnyPlatformDef> = Omit<SchemaInfer<Def["message"]>, keyof Message> & Message<Def["name"], PlatformUser<Def>, PlatformSpace<Def>>;
404
+ type InboundPlatformMessage<Def extends AnyPlatformDef> = Omit<SchemaInfer<Def["message"]>, keyof InboundMessage> & InboundMessage<Def["name"], PlatformUser<Def>, PlatformSpace<Def>>;
383
405
  type PlatformUser<Def extends AnyPlatformDef> = Omit<ResolvedUserOf<Def>, keyof User> & User;
384
406
  type PlatformInstance<Def extends AnyPlatformDef> = {
407
+ readonly messages: AsyncIterable<[
408
+ PlatformSpace<Def>,
409
+ InboundPlatformMessage<Def>
410
+ ]>;
385
411
  space(...args: SpaceArgs<Def>): Promise<PlatformSpace<Def>>;
386
412
  user(userID: string): Promise<PlatformUser<Def>>;
387
413
  } & {
388
414
  [K in Exclude<keyof Def["events"], "messages" | symbol | number> as K extends ReservedNames ? never : K]: AsyncIterable<InferEventPayload<Def["events"][K]>>;
389
415
  };
416
+ interface PlatformRuntime {
417
+ client: unknown;
418
+ config: unknown;
419
+ definition: AnyPlatformDef;
420
+ subscribeMessages: () => ManagedStream<[Space, InboundMessage]>;
421
+ }
390
422
  interface SpectrumLike<Providers extends PlatformProviderConfig[] = PlatformProviderConfig[]> {
391
423
  readonly __internal: {
392
- platforms: Map<string, {
393
- client: unknown;
394
- config: unknown;
395
- definition: AnyPlatformDef;
396
- }>;
424
+ platforms: Map<string, PlatformRuntime>;
397
425
  };
398
426
  readonly __providers: Providers;
399
427
  }
@@ -404,4 +432,4 @@ interface Platform<Def extends AnyPlatformDef> {
404
432
  (message: Message): PlatformMessage<Def>;
405
433
  }
406
434
 
407
- export type { AnyPlatformDef as A, ContentBuilder as C, EventProducer as E, InboundMessage as I, Message as M, OutboundMessage as O, ProviderMessage as P, SpectrumLike as S, User as U, ContentInput as a, Content as b, PlatformDef as c, Platform as d, PlatformProviderConfig as e, CustomEventStreams as f, Space as g, PlatformInstance as h, PlatformMessage as i, PlatformSpace as j, PlatformUser as k, SchemaMessage as l };
435
+ export { type AnyPlatformDef as A, type Broadcaster as B, type ContentBuilder as C, type EventProducer as E, type InboundMessage as I, type Message as M, type OutboundMessage as O, type ProviderMessage as P, type SpectrumLike as S, type User as U, type ContentInput as a, type Content as b, type PlatformDef as c, type Platform as d, type PlatformProviderConfig as e, type CustomEventStreams as f, type Space as g, type InboundPlatformMessage as h, type ManagedStream as i, type PlatformInstance as j, type PlatformMessage as k, type PlatformRuntime as l, type PlatformSpace as m, type PlatformUser as n, type SchemaMessage as o, broadcast as p, mergeStreams as q, stream as s };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spectrum-ts",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -19,7 +19,7 @@
19
19
  }
20
20
  },
21
21
  "dependencies": {
22
- "@photon-ai/advanced-imessage": "^0.5.1",
22
+ "@photon-ai/advanced-imessage": "^0.6.0",
23
23
  "@photon-ai/imessage-kit": "^3.0.0",
24
24
  "@photon-ai/whatsapp-business": "^0.1.1",
25
25
  "@repeaterjs/repeater": "^3.0.6",
@@ -1,8 +0,0 @@
1
- interface ManagedStream<T> extends AsyncIterable<T> {
2
- close(): Promise<void>;
3
- }
4
- type StreamCleanup = void | (() => void | Promise<void>);
5
- declare function stream<T>(setup: (emit: (value: T) => Promise<void>, end: (error?: unknown) => void) => StreamCleanup | Promise<StreamCleanup>): ManagedStream<T>;
6
- declare function mergeStreams<T>(streams: readonly ManagedStream<T>[]): ManagedStream<T>;
7
-
8
- export { type ManagedStream as M, mergeStreams as m, stream as s };