spectrum-ts 1.16.1 → 1.17.1

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 (29) hide show
  1. package/dist/{attachment-Bz66JIjW.d.ts → attachment-DfWSZS5L.d.ts} +1 -1
  2. package/dist/{authoring-e7xyaumK.d.ts → authoring-C9uDdZ2F.d.ts} +2 -2
  3. package/dist/authoring.d.ts +3 -3
  4. package/dist/authoring.js +6 -5
  5. package/dist/{chunk-KO67KDBD.js → chunk-2D27WW5B.js} +2 -0
  6. package/dist/{chunk-FTLJVVH7.js → chunk-2ILTJC35.js} +1 -0
  7. package/dist/{chunk-UFAZMTKC.js → chunk-3OTECDNH.js} +4 -3
  8. package/dist/{chunk-6NGVREPQ.js → chunk-5BKZJMZV.js} +5 -4
  9. package/dist/{chunk-753K5YPL.js → chunk-5TIF3FIE.js} +6 -5
  10. package/dist/{chunk-32H3VVUE.js → chunk-IPOFBAIM.js} +2 -1
  11. package/dist/{chunk-LJM5D2T5.js → chunk-JQN6CRSC.js} +2 -1
  12. package/dist/{chunk-VNMOZFWV.js → chunk-MC6ZKFSG.js} +5 -0
  13. package/dist/{chunk-5QSNQ6YN.js → chunk-NNY6LMSC.js} +2 -1
  14. package/dist/{chunk-RNGEA4UW.js → chunk-QGJFZMD5.js} +2 -1
  15. package/dist/{chunk-PIULC4CM.js → chunk-YJMPSD3S.js} +83 -16
  16. package/dist/index.d.ts +15 -74
  17. package/dist/index.js +23 -71
  18. package/dist/providers/imessage/index.d.ts +2 -2
  19. package/dist/providers/imessage/index.js +8 -7
  20. package/dist/providers/index.d.ts +2 -2
  21. package/dist/providers/index.js +12 -11
  22. package/dist/providers/slack/index.d.ts +1 -1
  23. package/dist/providers/slack/index.js +5 -4
  24. package/dist/providers/terminal/index.d.ts +1 -1
  25. package/dist/providers/terminal/index.js +6 -5
  26. package/dist/providers/whatsapp-business/index.d.ts +1 -1
  27. package/dist/providers/whatsapp-business/index.js +7 -6
  28. package/dist/{types-Dqv4Ffqg.d.ts → types-DcQ5a7PK.d.ts} +88 -2
  29. package/package.json +3 -1
@@ -1,5 +1,5 @@
1
1
  import z__default from 'zod';
2
- import { C as ContentBuilder } from './types-Dqv4Ffqg.js';
2
+ import { C as ContentBuilder } from './types-DcQ5a7PK.js';
3
3
 
4
4
  declare const attachmentSchema: z__default.ZodObject<{
5
5
  type: z__default.ZodLiteral<"attachment">;
@@ -1,7 +1,7 @@
1
- import './attachment-Bz66JIjW.js';
1
+ import './attachment-DfWSZS5L.js';
2
2
  import vCard from 'vcf';
3
3
  import z__default from 'zod';
4
- import { U as User, C as ContentBuilder, M as Message, b as Space, c as ContentInput } from './types-Dqv4Ffqg.js';
4
+ import { U as User, C as ContentBuilder, M as Message, b as Space, c as ContentInput } from './types-DcQ5a7PK.js';
5
5
 
6
6
  declare const nameSchema: z__default.ZodObject<{
7
7
  formatted: z__default.ZodOptional<z__default.ZodString>;
@@ -1,6 +1,6 @@
1
- export { c as asAttachment } from './attachment-Bz66JIjW.js';
2
- export { s as asContact, u as asCustom, w as asGroup, x as asPoll, y as asPollOption, z as asReaction, A as asRichlink, B as asText, D as asVoice } from './authoring-e7xyaumK.js';
3
- export { f as ProviderMessageRecord } from './types-Dqv4Ffqg.js';
1
+ export { c as asAttachment } from './attachment-DfWSZS5L.js';
2
+ export { s as asContact, u as asCustom, w as asGroup, x as asPoll, y as asPollOption, z as asReaction, A as asRichlink, B as asText, D as asVoice } from './authoring-C9uDdZ2F.js';
3
+ export { f as ProviderMessageRecord } from './types-DcQ5a7PK.js';
4
4
  import 'zod';
5
5
  import 'vcf';
6
6
  import 'hotscript';
package/dist/authoring.js CHANGED
@@ -1,23 +1,24 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
1
2
  import {
2
3
  asGroup,
3
4
  asRichlink
4
- } from "./chunk-LJM5D2T5.js";
5
+ } from "./chunk-JQN6CRSC.js";
5
6
  import {
6
7
  asVoice
7
- } from "./chunk-5QSNQ6YN.js";
8
+ } from "./chunk-NNY6LMSC.js";
8
9
  import {
9
10
  asPoll,
10
11
  asPollOption
11
- } from "./chunk-KO67KDBD.js";
12
+ } from "./chunk-2D27WW5B.js";
12
13
  import {
13
14
  asContact
14
- } from "./chunk-RNGEA4UW.js";
15
+ } from "./chunk-QGJFZMD5.js";
15
16
  import {
16
17
  asAttachment,
17
18
  asCustom,
18
19
  asReaction,
19
20
  asText
20
- } from "./chunk-FTLJVVH7.js";
21
+ } from "./chunk-2ILTJC35.js";
21
22
  export {
22
23
  asAttachment,
23
24
  asContact,
@@ -1,3 +1,5 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
2
+
1
3
  // src/content/poll.ts
2
4
  import z from "zod";
3
5
  var pollChoiceSchema = z.object({
@@ -1,3 +1,4 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
1
2
  var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -1,18 +1,19 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
1
2
  import {
2
3
  cloud,
3
4
  mergeStreams,
4
5
  stream
5
- } from "./chunk-VNMOZFWV.js";
6
+ } from "./chunk-MC6ZKFSG.js";
6
7
  import {
7
8
  UnsupportedError,
8
9
  definePlatform
9
- } from "./chunk-32H3VVUE.js";
10
+ } from "./chunk-IPOFBAIM.js";
10
11
  import {
11
12
  asAttachment,
12
13
  asCustom,
13
14
  asReaction,
14
15
  asText
15
- } from "./chunk-FTLJVVH7.js";
16
+ } from "./chunk-2ILTJC35.js";
16
17
 
17
18
  // src/providers/slack/index.ts
18
19
  import { createClient as createClient2, staticTokens } from "@photon-ai/slack";
@@ -1,20 +1,21 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
1
2
  import {
2
3
  asVoice
3
- } from "./chunk-5QSNQ6YN.js";
4
+ } from "./chunk-NNY6LMSC.js";
4
5
  import {
5
6
  asContact,
6
7
  fromVCard,
7
8
  toVCard
8
- } from "./chunk-RNGEA4UW.js";
9
+ } from "./chunk-QGJFZMD5.js";
9
10
  import {
10
11
  UnsupportedError,
11
12
  definePlatform
12
- } from "./chunk-32H3VVUE.js";
13
+ } from "./chunk-IPOFBAIM.js";
13
14
  import {
14
15
  asAttachment,
15
16
  asCustom,
16
17
  reactionSchema
17
- } from "./chunk-FTLJVVH7.js";
18
+ } from "./chunk-2ILTJC35.js";
18
19
 
19
20
  // src/providers/terminal/index.ts
20
21
  import { spawn } from "child_process";
@@ -1,24 +1,25 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
1
2
  import {
2
3
  asPollOption
3
- } from "./chunk-KO67KDBD.js";
4
+ } from "./chunk-2D27WW5B.js";
4
5
  import {
5
6
  cloud,
6
7
  mergeStreams,
7
8
  stream
8
- } from "./chunk-VNMOZFWV.js";
9
+ } from "./chunk-MC6ZKFSG.js";
9
10
  import {
10
11
  asContact
11
- } from "./chunk-RNGEA4UW.js";
12
+ } from "./chunk-QGJFZMD5.js";
12
13
  import {
13
14
  UnsupportedError,
14
15
  definePlatform
15
- } from "./chunk-32H3VVUE.js";
16
+ } from "./chunk-IPOFBAIM.js";
16
17
  import {
17
18
  asAttachment,
18
19
  asCustom,
19
20
  asReaction,
20
21
  asText
21
- } from "./chunk-FTLJVVH7.js";
22
+ } from "./chunk-2ILTJC35.js";
22
23
 
23
24
  // src/providers/whatsapp-business/index.ts
24
25
  import { createClient as createClient2 } from "@photon-ai/whatsapp-business";
@@ -1,9 +1,10 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
1
2
  import {
2
3
  fetchUrlBytes,
3
4
  reaction,
4
5
  readSchema,
5
6
  resolveContents
6
- } from "./chunk-FTLJVVH7.js";
7
+ } from "./chunk-2ILTJC35.js";
7
8
 
8
9
  // src/content/avatar.ts
9
10
  import z2 from "zod";
@@ -1,10 +1,11 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
1
2
  import {
2
3
  bufferToStream,
3
4
  fetchUrlBytes,
4
5
  readSchema,
5
6
  resolveContents,
6
7
  streamSchema
7
- } from "./chunk-FTLJVVH7.js";
8
+ } from "./chunk-2ILTJC35.js";
8
9
 
9
10
  // src/content/group.ts
10
11
  import z from "zod";
@@ -1,3 +1,5 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
2
+
1
3
  // src/utils/cloud.ts
2
4
  var SPECTRUM_CLOUD_URL = process.env.SPECTRUM_CLOUD_URL ?? "https://spectrum.photon.codes";
3
5
  var SpectrumCloudError = class extends Error {
@@ -44,6 +46,9 @@ var request = async (path, init) => {
44
46
  };
45
47
  var basicAuth = (projectId, projectSecret) => `Basic ${btoa(`${projectId}:${projectSecret}`)}`;
46
48
  var cloud = {
49
+ getProject: (projectId, projectSecret) => request(`/projects/${projectId}/`, {
50
+ headers: { Authorization: basicAuth(projectId, projectSecret) }
51
+ }),
47
52
  getSubscription: (projectId) => request(`/projects/${projectId}/billing/subscription`),
48
53
  issueImessageTokens: (projectId, projectSecret) => request(`/projects/${projectId}/imessage/tokens`, {
49
54
  method: "POST",
@@ -1,9 +1,10 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
1
2
  import {
2
3
  bufferToStream,
3
4
  fetchUrlBytes,
4
5
  readSchema,
5
6
  streamSchema
6
- } from "./chunk-FTLJVVH7.js";
7
+ } from "./chunk-2ILTJC35.js";
7
8
 
8
9
  // src/content/voice.ts
9
10
  import { createReadStream } from "fs";
@@ -1,6 +1,7 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
1
2
  import {
2
3
  readSchema
3
- } from "./chunk-FTLJVVH7.js";
4
+ } from "./chunk-2ILTJC35.js";
4
5
 
5
6
  // src/utils/vcard.ts
6
7
  import vCard from "vcf";
@@ -1,28 +1,29 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
1
2
  import {
2
3
  asGroup,
3
4
  asRichlink,
4
5
  groupSchema
5
- } from "./chunk-LJM5D2T5.js";
6
+ } from "./chunk-JQN6CRSC.js";
6
7
  import {
7
8
  asPoll,
8
9
  asPollOption
9
- } from "./chunk-KO67KDBD.js";
10
+ } from "./chunk-2D27WW5B.js";
10
11
  import {
11
12
  cloud,
12
13
  mergeStreams,
13
14
  stream
14
- } from "./chunk-VNMOZFWV.js";
15
+ } from "./chunk-MC6ZKFSG.js";
15
16
  import {
16
17
  asContact,
17
18
  fromVCard,
18
19
  toVCard
19
- } from "./chunk-RNGEA4UW.js";
20
+ } from "./chunk-QGJFZMD5.js";
20
21
  import {
21
22
  UnsupportedError,
22
23
  buildPhotoAction,
23
24
  definePlatform,
24
25
  photoActionSchema
25
- } from "./chunk-32H3VVUE.js";
26
+ } from "./chunk-IPOFBAIM.js";
26
27
  import {
27
28
  asAttachment,
28
29
  asCustom,
@@ -31,7 +32,7 @@ import {
31
32
  reactionSchema,
32
33
  text,
33
34
  textSchema
34
- } from "./chunk-FTLJVVH7.js";
35
+ } from "./chunk-2ILTJC35.js";
35
36
 
36
37
  // src/providers/imessage/index.ts
37
38
  import { createClient as createClient2, MessageEffect as MessageEffect2 } from "@photon-ai/advanced-imessage";
@@ -1650,6 +1651,53 @@ var resumableOrderedStream = (options) => stream((emit, end) => {
1650
1651
  };
1651
1652
  });
1652
1653
 
1654
+ // src/providers/imessage/remote/contact-share.ts
1655
+ import { sanitizeErrorMessage } from "@photon-ai/otel";
1656
+ import { LRUCache } from "lru-cache";
1657
+ var SHARE_TTL_MS = 24 * 60 * 60 * 1e3;
1658
+ var MAX_TRACKED_CHATS = 1e4;
1659
+ var ContactShareTracker = class {
1660
+ cache = new LRUCache({
1661
+ max: MAX_TRACKED_CHATS,
1662
+ ttl: SHARE_TTL_MS,
1663
+ ttlAutopurge: false
1664
+ });
1665
+ /**
1666
+ * Best-effort share. The cache is set eagerly so that a burst of inbound
1667
+ * messages for the same chat coalesces to a single API call. On failure the
1668
+ * entry is evicted so the next inbound retries — transient errors don't
1669
+ * permanently mute the feature for a chat. Never awaits and never throws:
1670
+ * the receive stream must not crash on share failures.
1671
+ */
1672
+ maybeShare(client, chatGuid) {
1673
+ if (this.cache.has(chatGuid)) {
1674
+ return;
1675
+ }
1676
+ this.cache.set(chatGuid, true);
1677
+ const safeChatGuid = sanitizeErrorMessage(chatGuid);
1678
+ client.chats.shareContactInfo(chatGuid).then(() => {
1679
+ console.info(
1680
+ `[spectrum-ts][imessage][contact-share] shared contact info to ${safeChatGuid}`
1681
+ );
1682
+ }).catch((error) => {
1683
+ this.cache.delete(chatGuid);
1684
+ console.warn(
1685
+ `[spectrum-ts][imessage][contact-share] failed to share contact info to ${safeChatGuid}`,
1686
+ error
1687
+ );
1688
+ });
1689
+ }
1690
+ };
1691
+ var trackers = /* @__PURE__ */ new WeakMap();
1692
+ var getContactShareTracker = (owner) => {
1693
+ let tracker = trackers.get(owner);
1694
+ if (!tracker) {
1695
+ tracker = new ContactShareTracker();
1696
+ trackers.set(owner, tracker);
1697
+ }
1698
+ return tracker;
1699
+ };
1700
+
1653
1701
  // src/providers/imessage/remote/polls.ts
1654
1702
  var isVotedPollEvent = (event) => event.delta.type === "voted";
1655
1703
  var isUnvotedPollEvent = (event) => event.delta.type === "unvoted";
@@ -1789,11 +1837,15 @@ var isRetryableIMessageStreamError = (error) => {
1789
1837
  return false;
1790
1838
  };
1791
1839
  var isEventFromCurrentAccount = (event, phone) => event.isFromMe || phone !== SHARED_PHONE && event.actor?.address !== void 0 && event.actor.address === phone;
1792
- var toMessageItem = async (client, event, phone, cursor) => {
1840
+ var toMessageItem = async (client, event, phone, cursor, onInbound) => {
1793
1841
  if (event.type === "message.received") {
1794
1842
  if (event.message.isFromMe) {
1795
1843
  return { cursor, id: event.message.guid, values: [] };
1796
1844
  }
1845
+ const inboundChatGuid = event.message.chatGuids?.[0];
1846
+ if (inboundChatGuid) {
1847
+ onInbound?.(inboundChatGuid);
1848
+ }
1797
1849
  const cache = getMessageCache(client);
1798
1850
  return {
1799
1851
  cursor,
@@ -1884,11 +1936,17 @@ var withClose = (source, cursor) => Object.assign(afterCursor(source, cursor), {
1884
1936
  await source.close?.();
1885
1937
  }
1886
1938
  });
1887
- var messageStream = (client, phone) => resumableOrderedStream({
1939
+ var messageStream = (client, phone, onInbound) => resumableOrderedStream({
1888
1940
  fetchMissed: (cursor) => catchUpEvents(client, cursor, isMessageEvent),
1889
1941
  isRetryableError: isRetryableIMessageStreamError,
1890
- processLive: (event) => toMessageItem(client, event, phone, String(event.sequence)),
1891
- processMissed: (event) => event.type === "catchup.complete" ? Promise.resolve(toCatchUpCompleteItem(event)) : toMessageItem(client, event, phone, String(event.sequence)),
1942
+ processLive: (event) => toMessageItem(client, event, phone, String(event.sequence), onInbound),
1943
+ processMissed: (event) => event.type === "catchup.complete" ? Promise.resolve(toCatchUpCompleteItem(event)) : toMessageItem(
1944
+ client,
1945
+ event,
1946
+ phone,
1947
+ String(event.sequence),
1948
+ onInbound
1949
+ ),
1892
1950
  subscribeLive: (cursor) => withClose(client.messages.subscribeEvents(), cursor)
1893
1951
  });
1894
1952
  var pollStream = (client, pollCache, phone) => resumableOrderedStream({
@@ -1898,14 +1956,23 @@ var pollStream = (client, pollCache, phone) => resumableOrderedStream({
1898
1956
  processMissed: (event) => event.type === "catchup.complete" ? Promise.resolve(toCatchUpCompleteItem(event)) : toPollItem(client, pollCache, event, phone, String(event.sequence)),
1899
1957
  subscribeLive: (cursor) => withClose(client.polls.subscribeEvents(), cursor)
1900
1958
  });
1901
- var clientStream = (client, pollCache, phone) => mergeStreams([
1902
- messageStream(client, phone),
1959
+ var clientStream = (client, pollCache, phone, onInbound) => mergeStreams([
1960
+ messageStream(client, phone, onInbound),
1903
1961
  pollStream(client, pollCache, phone)
1904
1962
  ]);
1905
- var messages3 = (clients) => {
1963
+ var messages3 = (clients, projectConfig) => {
1906
1964
  const pollCache = getPollCache(clients);
1965
+ const shareEnabled = projectConfig?.profile?.imessageSynced === true;
1966
+ const tracker = shareEnabled ? getContactShareTracker(clients) : void 0;
1907
1967
  return mergeStreams(
1908
- clients.map((entry) => clientStream(entry.client, pollCache, entry.phone))
1968
+ clients.map(
1969
+ (entry) => clientStream(
1970
+ entry.client,
1971
+ pollCache,
1972
+ entry.phone,
1973
+ tracker ? (chatGuid) => tracker.maybeShare(entry.client, chatGuid) : void 0
1974
+ )
1975
+ )
1909
1976
  );
1910
1977
  };
1911
1978
 
@@ -1918,7 +1985,7 @@ var stopTyping = async (remote, spaceId) => {
1918
1985
  };
1919
1986
 
1920
1987
  // src/providers/imessage/remote/api.ts
1921
- var messages4 = (clients) => messages3(clients);
1988
+ var messages4 = (clients, projectConfig) => messages3(clients, projectConfig);
1922
1989
  var setBackground2 = async (remote, spaceId, content) => setBackground(remote, spaceId, content);
1923
1990
  var setDisplayName2 = async (remote, spaceId, content) => setDisplayName(remote, spaceId, content);
1924
1991
  var setIcon2 = async (remote, spaceId, content) => setIcon(remote, spaceId, content);
@@ -2159,7 +2226,7 @@ var imessage = definePlatform("iMessage", {
2159
2226
  }
2160
2227
  }
2161
2228
  },
2162
- messages: ({ client }) => isLocal(client) ? messages2(client) : messages4(client),
2229
+ messages: ({ client, projectConfig }) => isLocal(client) ? messages2(client) : messages4(client, projectConfig),
2163
2230
  send: async ({ space, content, client }) => {
2164
2231
  if (content.type === "reply") {
2165
2232
  if (isLocal(client)) {
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- export { A as Attachment, a as AttachmentInput, b as attachment } from './attachment-Bz66JIjW.js';
1
+ export { A as Attachment, a as AttachmentInput, b as attachment } from './attachment-DfWSZS5L.js';
2
2
  import z__default from 'zod';
3
3
  import { P as PhotoInput } from './photo-content-BJKnqgN-.js';
4
- import { C as ContentBuilder, M as Message, U as User, b as Space, c as ContentInput, e as Content, f as ProviderMessageRecord, g as SpaceActionFn, h as MessageActionFn, i as CreateClientContext, d as Store, P as Platform, a as PlatformDef, j as ProviderMessage, E as EventProducer, I as InstanceActionFn, k as PlatformProviderConfig, l as SpectrumLike, m as CustomEventStreams, A as AgentSender } from './types-Dqv4Ffqg.js';
5
- export { n as AnyPlatformDef, B as Broadcaster, o as ManagedStream, p as PlatformInstance, q as PlatformMessage, r as PlatformRuntime, s as PlatformSpace, t as PlatformUser, S as SchemaMessage, u as broadcast, v as mergeStreams, w as stream } from './types-Dqv4Ffqg.js';
6
- import { C as ContactInput, a as Contact } from './authoring-e7xyaumK.js';
7
- export { b as ContactAddress, c as ContactDetails, d as ContactEmail, e as ContactName, f as ContactOrg, g as ContactPhone, G as Group, P as Poll, h as PollChoice, i as PollChoiceInput, j as PollOption, R as Reaction, k as Richlink, V as Voice, l as contact, m as custom, n as group, o as option, p as poll, r as reaction, q as richlink, t as text, v as voice } from './authoring-e7xyaumK.js';
4
+ import { C as ContentBuilder, M as Message, U as User, b as Space, c as ContentInput, e as Content, f as ProviderMessageRecord, g as SpaceActionFn, h as MessageActionFn, i as CreateClientContext, d as Store, P as Platform, a as PlatformDef, j as ProviderMessage, E as EventProducer, I as InstanceActionFn, k as PlatformProviderConfig, l as SpectrumLike, m as CustomEventStreams, A as AgentSender, n as ProjectData } from './types-DcQ5a7PK.js';
5
+ export { o as AnyPlatformDef, B as Broadcaster, p as CloudPlatform, D as DedicatedTokenData, F as FusorTokenData, q as ImessageInfoData, r as ManagedStream, s as PlatformInstance, t as PlatformMessage, u as PlatformRuntime, v as PlatformSpace, w as PlatformStatus, x as PlatformUser, y as PlatformsData, z as ProjectProfile, S as SchemaMessage, G as SharedTokenData, H as SlackTeamMeta, J as SlackTokenData, K as SpectrumCloudError, L as SubscriptionData, N as SubscriptionStatus, T as TokenData, O as broadcast, Q as cloud, R as mergeStreams, V as stream } from './types-DcQ5a7PK.js';
6
+ import { C as ContactInput, a as Contact } from './authoring-C9uDdZ2F.js';
7
+ export { b as ContactAddress, c as ContactDetails, d as ContactEmail, e as ContactName, f as ContactOrg, g as ContactPhone, G as Group, P as Poll, h as PollChoice, i as PollChoiceInput, j as PollOption, R as Reaction, k as Richlink, V as Voice, l as contact, m as custom, n as group, o as option, p as poll, r as reaction, q as richlink, t as text, v as voice } from './authoring-C9uDdZ2F.js';
8
8
  import 'hotscript';
9
9
  import 'vcf';
10
10
 
@@ -2645,13 +2645,14 @@ type WebhookHandler = (space: Space, message: Message) => void | Promise<void>;
2645
2645
  /**
2646
2646
  * Raw webhook input for HTTP servers without Web `Request`/`Response` (Express,
2647
2647
  * raw Node). `body` MUST be the exact bytes fusor POSTed — never a re-encoded
2648
- * JSON/text body — so the protobuf decode and the fusor-origin signature check
2649
- * (HMAC over the raw bytes) work. `headers` carry the `X-Spectrum-*` signature
2650
- * headers fusor sets on signed deliveries.
2648
+ * JSON/text body — so the protobuf decode works. `headers` are accepted (so the
2649
+ * natural `{ headers: req.headers, body: req.body }` shape keeps working) but are
2650
+ * not read: inbound authenticity is established by the per-platform `verify()`,
2651
+ * which reads the inner request reconstructed from the envelope.
2651
2652
  */
2652
2653
  interface WebhookRawRequest {
2653
2654
  body: Uint8Array | ArrayBuffer;
2654
- headers: Record<string, string>;
2655
+ headers?: Record<string, string>;
2655
2656
  }
2656
2657
  /** Raw webhook result, written back by the caller as the HTTP response. */
2657
2658
  interface WebhookRawResult {
@@ -2802,77 +2803,17 @@ declare function Spectrum<const Providers extends PlatformProviderConfig[]>(opti
2802
2803
  providers: [...Providers];
2803
2804
  options?: SpectrumOptions;
2804
2805
  telemetry?: boolean;
2805
- webhookSecret?: string;
2806
- } | {
2806
+ }): Promise<SpectrumInstance<Providers> & {
2807
+ readonly config: ProjectData;
2808
+ }>;
2809
+ declare function Spectrum<const Providers extends PlatformProviderConfig[]>(options: {
2807
2810
  projectId?: never;
2808
2811
  projectSecret?: never;
2809
2812
  providers: [...Providers];
2810
2813
  options?: SpectrumOptions;
2811
2814
  telemetry?: boolean;
2812
- webhookSecret?: string;
2813
2815
  }): Promise<SpectrumInstance<Providers>>;
2814
2816
 
2815
- type SubscriptionStatus = "active" | "canceled" | "past_due";
2816
- interface SubscriptionData {
2817
- status: SubscriptionStatus | null;
2818
- tier: string;
2819
- }
2820
- interface SharedTokenData {
2821
- expiresIn: number;
2822
- token: string;
2823
- type: "shared";
2824
- }
2825
- interface DedicatedTokenData {
2826
- auth: Record<string, string>;
2827
- expiresIn: number;
2828
- numbers: Record<string, string | null>;
2829
- type: "dedicated";
2830
- }
2831
- type TokenData = SharedTokenData | DedicatedTokenData;
2832
- type CloudPlatform = "imessage" | "whatsapp_business" | "slack";
2833
- interface PlatformStatus {
2834
- enabled: boolean;
2835
- }
2836
- type PlatformsData = Record<CloudPlatform, PlatformStatus>;
2837
- interface ImessageInfoData {
2838
- type: "shared" | "dedicated";
2839
- }
2840
- interface WhatsappBusinessTokenData {
2841
- auth: Record<string, string>;
2842
- expiresIn: number;
2843
- numbers: Record<string, string | null>;
2844
- }
2845
- interface SlackTeamMeta {
2846
- appId: string;
2847
- botUserId: string;
2848
- grantedScopes: string[];
2849
- teamName: string;
2850
- }
2851
- interface SlackTokenData {
2852
- auth: Record<string, string>;
2853
- expiresIn: number;
2854
- teams: Record<string, SlackTeamMeta>;
2855
- }
2856
- interface FusorTokenData {
2857
- expiresIn: number;
2858
- token: string;
2859
- }
2860
- declare class SpectrumCloudError extends Error {
2861
- readonly status: number;
2862
- readonly code: string;
2863
- constructor(status: number, code: string, message: string);
2864
- }
2865
- declare const cloud: {
2866
- getSubscription: (projectId: string) => Promise<SubscriptionData>;
2867
- issueImessageTokens: (projectId: string, projectSecret: string) => Promise<TokenData>;
2868
- getImessageInfo: (projectId: string) => Promise<ImessageInfoData>;
2869
- issueWhatsappBusinessTokens: (projectId: string, projectSecret: string) => Promise<WhatsappBusinessTokenData>;
2870
- issueSlackTokens: (projectId: string, projectSecret: string) => Promise<SlackTokenData>;
2871
- issueFusorToken: (projectId: string, projectSecret: string) => Promise<FusorTokenData>;
2872
- getPlatforms: (projectId: string) => Promise<PlatformsData>;
2873
- togglePlatform: (projectId: string, projectSecret: string, platform: CloudPlatform, enabled: boolean) => Promise<PlatformsData>;
2874
- };
2875
-
2876
2817
  type UnsupportedKind = "content" | "action";
2877
2818
  interface UnsupportedErrorOptions {
2878
2819
  action?: string;
@@ -2896,4 +2837,4 @@ declare class UnsupportedError extends Error {
2896
2837
  declare const fromVCard: (vcf: string) => ContactInput;
2897
2838
  declare const toVCard: (contact: Contact) => Promise<string>;
2898
2839
 
2899
- export { AgentSender, type Avatar, type AvatarInput, type CloudPlatform, Contact, ContactInput, Content, ContentBuilder, ContentInput, type DedicatedTokenData, type Edit, Emoji, type EmojiKey, EventProducer, type FusorClient, type FusorMessages, type FusorMessagesCtx, type FusorMessagesReturn, type FusorReply, type FusorRespond, type FusorTokenData, type FusorVerify, type FusorVerifyRequest, type ImessageInfoData, Message, Platform, PlatformDef, PlatformProviderConfig, type PlatformStatus, type PlatformsData, ProviderMessage, type Rename, type Reply, type SharedTokenData, type SlackTeamMeta, type SlackTokenData, Space, Spectrum, SpectrumCloudError, type SpectrumInstance, type SubscriptionData, type SubscriptionStatus, type TokenData, type Typing, UnsupportedError, type UnsupportedKind, User, type WebhookHandler, type WebhookRawRequest, type WebhookRawResult, avatar, cloud, defineFusorPlatform, definePlatform, edit, fromVCard, fusor, isFusorClient, rename, reply, resolveContents, toVCard, typing };
2840
+ export { AgentSender, type Avatar, type AvatarInput, Contact, ContactInput, Content, ContentBuilder, ContentInput, type Edit, Emoji, type EmojiKey, EventProducer, type FusorClient, type FusorMessages, type FusorMessagesCtx, type FusorMessagesReturn, type FusorReply, type FusorRespond, type FusorVerify, type FusorVerifyRequest, Message, Platform, PlatformDef, PlatformProviderConfig, ProjectData, ProviderMessage, type Rename, type Reply, Space, Spectrum, type SpectrumInstance, type Typing, UnsupportedError, type UnsupportedKind, User, type WebhookHandler, type WebhookRawRequest, type WebhookRawResult, avatar, defineFusorPlatform, definePlatform, edit, fromVCard, fusor, isFusorClient, rename, reply, resolveContents, toVCard, typing };
package/dist/index.js CHANGED
@@ -1,14 +1,15 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
1
2
  import {
2
3
  group,
3
4
  richlink
4
- } from "./chunk-LJM5D2T5.js";
5
+ } from "./chunk-JQN6CRSC.js";
5
6
  import {
6
7
  voice
7
- } from "./chunk-5QSNQ6YN.js";
8
+ } from "./chunk-NNY6LMSC.js";
8
9
  import {
9
10
  option,
10
11
  poll
11
- } from "./chunk-KO67KDBD.js";
12
+ } from "./chunk-2D27WW5B.js";
12
13
  import {
13
14
  SpectrumCloudError,
14
15
  broadcast,
@@ -16,12 +17,12 @@ import {
16
17
  createAsyncQueue,
17
18
  mergeStreams,
18
19
  stream
19
- } from "./chunk-VNMOZFWV.js";
20
+ } from "./chunk-MC6ZKFSG.js";
20
21
  import {
21
22
  contact,
22
23
  fromVCard,
23
24
  toVCard
24
- } from "./chunk-RNGEA4UW.js";
25
+ } from "./chunk-QGJFZMD5.js";
25
26
  import {
26
27
  UnsupportedError,
27
28
  avatar,
@@ -35,7 +36,7 @@ import {
35
36
  senderAttrs,
36
37
  typing,
37
38
  wrapProviderMessage
38
- } from "./chunk-32H3VVUE.js";
39
+ } from "./chunk-IPOFBAIM.js";
39
40
  import {
40
41
  __commonJS,
41
42
  __esm,
@@ -48,7 +49,7 @@ import {
48
49
  reaction,
49
50
  resolveContents,
50
51
  text
51
- } from "./chunk-FTLJVVH7.js";
52
+ } from "./chunk-2ILTJC35.js";
52
53
 
53
54
  // ../../node_modules/@grpc/grpc-js/build/src/constants.js
54
55
  var require_constants = __commonJS({
@@ -27500,33 +27501,6 @@ var FusorCore = class {
27500
27501
  }
27501
27502
  };
27502
27503
 
27503
- // src/fusor/origin.ts
27504
- import { createHmac, timingSafeEqual } from "crypto";
27505
- var SIGNATURE_HEADER = "x-spectrum-signature";
27506
- var TIMESTAMP_HEADER = "x-spectrum-timestamp";
27507
- var SIGNATURE_PREFIX = "v0=";
27508
- var stripPrefix = (value) => value.startsWith(SIGNATURE_PREFIX) ? value.slice(SIGNATURE_PREFIX.length) : value;
27509
- var safeEqualHex = (a, b) => {
27510
- const left = Buffer.from(a, "hex");
27511
- const right = Buffer.from(b, "hex");
27512
- if (left.length === 0 || left.length !== right.length) {
27513
- return false;
27514
- }
27515
- return timingSafeEqual(left, right);
27516
- };
27517
- var verifyFusorSignature = (secret, headers, body) => {
27518
- const timestamp = headers[TIMESTAMP_HEADER];
27519
- const signature = headers[SIGNATURE_HEADER];
27520
- if (!(timestamp && signature)) {
27521
- throw new Error("fusor webhook is missing X-Spectrum-* signature headers");
27522
- }
27523
- const base = Buffer.concat([Buffer.from(`v0:${timestamp}:`, "utf8"), body]);
27524
- const expected = SIGNATURE_PREFIX + createHmac("sha256", secret).update(base).digest("hex");
27525
- if (!safeEqualHex(stripPrefix(expected), stripPrefix(signature))) {
27526
- throw new Error("fusor webhook signature mismatch");
27527
- }
27528
- };
27529
-
27530
27504
  // src/utils/store.ts
27531
27505
  var isRecordObject = (value) => {
27532
27506
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
@@ -27595,16 +27569,14 @@ var spectrumConfigSchema = z.union([
27595
27569
  projectSecret: z.string().min(1),
27596
27570
  providers: z.array(z.custom()),
27597
27571
  options: spectrumOptionsSchema,
27598
- telemetry: z.boolean().optional(),
27599
- webhookSecret: z.string().min(1).optional()
27572
+ telemetry: z.boolean().optional()
27600
27573
  }),
27601
27574
  z.object({
27602
27575
  projectId: z.undefined().optional(),
27603
27576
  projectSecret: z.undefined().optional(),
27604
27577
  providers: z.array(z.custom()),
27605
27578
  options: spectrumOptionsSchema,
27606
- telemetry: z.boolean().optional(),
27607
- webhookSecret: z.string().min(1).optional()
27579
+ telemetry: z.boolean().optional()
27608
27580
  })
27609
27581
  ]);
27610
27582
  function bootstrapTelemetry(opts) {
@@ -27634,11 +27606,11 @@ async function Spectrum(options) {
27634
27606
  projectSecret,
27635
27607
  providers,
27636
27608
  options: runtimeOptions,
27637
- telemetry,
27638
- webhookSecret
27609
+ telemetry
27639
27610
  } = options;
27640
27611
  const flattenGroups = runtimeOptions?.flattenGroups ?? false;
27641
27612
  const otelHandle = telemetry ? bootstrapTelemetry({ projectId, projectSecret }) : void 0;
27613
+ const projectConfig = projectId !== void 0 && projectSecret !== void 0 ? await cloud.getProject(projectId, projectSecret) : void 0;
27642
27614
  const platformStates = /* @__PURE__ */ new Map();
27643
27615
  const fusorMessageSources = /* @__PURE__ */ new Map();
27644
27616
  const messageBroadcasters = /* @__PURE__ */ new Map();
@@ -27719,6 +27691,7 @@ async function Spectrum(options) {
27719
27691
  const raw = fusorSource ? fusorSource.iterable : definition.messages({
27720
27692
  client,
27721
27693
  config,
27694
+ projectConfig,
27722
27695
  store
27723
27696
  });
27724
27697
  const bindSend = async function* () {
@@ -27859,7 +27832,12 @@ async function Spectrum(options) {
27859
27832
  if (!producer) {
27860
27833
  continue;
27861
27834
  }
27862
- const providerEvents = producer({ client, config, store });
27835
+ const providerEvents = producer({
27836
+ client,
27837
+ config,
27838
+ projectConfig,
27839
+ store
27840
+ });
27863
27841
  const annotatePlatform = async function* () {
27864
27842
  for await (const value of providerEvents) {
27865
27843
  const annotated = await withSpan(
@@ -27995,23 +27973,14 @@ async function Spectrum(options) {
27995
27973
  };
27996
27974
  const readWebhookInput = async (request) => {
27997
27975
  if (typeof Request !== "undefined" && request instanceof Request) {
27998
- const headers2 = {};
27999
- request.headers.forEach((value, key) => {
28000
- headers2[key.toLowerCase()] = value;
28001
- });
28002
27976
  return {
28003
27977
  asWeb: true,
28004
- bodyBytes: new Uint8Array(await request.arrayBuffer()),
28005
- headers: headers2
27978
+ bodyBytes: new Uint8Array(await request.arrayBuffer())
28006
27979
  };
28007
27980
  }
28008
27981
  const raw = request;
28009
27982
  const bodyBytes = raw.body instanceof ArrayBuffer ? new Uint8Array(raw.body) : raw.body;
28010
- const headers = {};
28011
- for (const [key, value] of Object.entries(raw.headers ?? {})) {
28012
- headers[key.toLowerCase()] = value;
28013
- }
28014
- return { asWeb: false, bodyBytes, headers };
27983
+ return { asWeb: false, bodyBytes };
28015
27984
  };
28016
27985
  const deliverWebhookMessages = async (collected, runtime, handler, event) => {
28017
27986
  for (const record of collected) {
@@ -28033,12 +28002,6 @@ async function Spectrum(options) {
28033
28002
  }
28034
28003
  }
28035
28004
  };
28036
- const assertFusorOrigin = (bodyBytes, headers) => {
28037
- if (!webhookSecret) {
28038
- return;
28039
- }
28040
- verifyFusorSignature(webhookSecret, headers, bodyBytes);
28041
- };
28042
28005
  const decodeWebhookEvent = (bodyBytes) => {
28043
28006
  try {
28044
28007
  return RawInboundEvent2.decode(bodyBytes);
@@ -28089,19 +28052,7 @@ async function Spectrum(options) {
28089
28052
  "spectrum.webhook() requires at least one fusor provider; none are configured"
28090
28053
  );
28091
28054
  }
28092
- const { asWeb, bodyBytes, headers } = await readWebhookInput(request);
28093
- try {
28094
- assertFusorOrigin(bodyBytes, headers);
28095
- } catch (error) {
28096
- lifecycleLog.warn("spectrum.webhook: fusor origin verification failed", {
28097
- error: error instanceof Error ? error.message : String(error)
28098
- });
28099
- return buildWebhookResult(asWeb, {
28100
- status: 401,
28101
- headers: {},
28102
- body: new Uint8Array(0)
28103
- });
28104
- }
28055
+ const { asWeb, bodyBytes } = await readWebhookInput(request);
28105
28056
  const event = decodeWebhookEvent(bodyBytes);
28106
28057
  if (!event) {
28107
28058
  return buildWebhookResult(asWeb, {
@@ -28116,6 +28067,7 @@ async function Spectrum(options) {
28116
28067
  const base = {
28117
28068
  __providers: providers,
28118
28069
  __internal: { platforms: platformStates },
28070
+ config: projectConfig,
28119
28071
  messages,
28120
28072
  stop: stopOnce,
28121
28073
  webhook: handleWebhook,
@@ -1,8 +1,8 @@
1
- import { C as ContentBuilder, c as ContentInput, M as Message, S as SchemaMessage, P as Platform, a as PlatformDef, b as Space, d as Store } from '../../types-Dqv4Ffqg.js';
1
+ import { C as ContentBuilder, c as ContentInput, M as Message, S as SchemaMessage, P as Platform, a as PlatformDef, b as Space, d as Store } from '../../types-DcQ5a7PK.js';
2
2
  import * as zod_v4_core from 'zod/v4/core';
3
3
  import * as z from 'zod';
4
4
  import z__default from 'zod';
5
- import { A as Attachment } from '../../attachment-Bz66JIjW.js';
5
+ import { A as Attachment } from '../../attachment-DfWSZS5L.js';
6
6
  import { P as PhotoInput } from '../../photo-content-BJKnqgN-.js';
7
7
  import { MessageEffect, AdvancedIMessage } from '@photon-ai/advanced-imessage';
8
8
  import { IMessageSDK } from '@photon-ai/imessage-kit';
@@ -1,15 +1,16 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
1
2
  import {
2
3
  background,
3
4
  effect,
4
5
  imessage,
5
6
  read
6
- } from "../../chunk-PIULC4CM.js";
7
- import "../../chunk-LJM5D2T5.js";
8
- import "../../chunk-KO67KDBD.js";
9
- import "../../chunk-VNMOZFWV.js";
10
- import "../../chunk-RNGEA4UW.js";
11
- import "../../chunk-32H3VVUE.js";
12
- import "../../chunk-FTLJVVH7.js";
7
+ } from "../../chunk-YJMPSD3S.js";
8
+ import "../../chunk-JQN6CRSC.js";
9
+ import "../../chunk-2D27WW5B.js";
10
+ import "../../chunk-MC6ZKFSG.js";
11
+ import "../../chunk-QGJFZMD5.js";
12
+ import "../../chunk-IPOFBAIM.js";
13
+ import "../../chunk-2ILTJC35.js";
13
14
  export {
14
15
  background,
15
16
  effect,
@@ -2,11 +2,11 @@ export { imessage } from './imessage/index.js';
2
2
  export { slack } from './slack/index.js';
3
3
  export { terminal } from './terminal/index.js';
4
4
  export { whatsappBusiness } from './whatsapp-business/index.js';
5
- import '../types-Dqv4Ffqg.js';
5
+ import '../types-DcQ5a7PK.js';
6
6
  import 'hotscript';
7
7
  import 'zod';
8
8
  import 'zod/v4/core';
9
- import '../attachment-Bz66JIjW.js';
9
+ import '../attachment-DfWSZS5L.js';
10
10
  import '../photo-content-BJKnqgN-.js';
11
11
  import '@photon-ai/advanced-imessage';
12
12
  import '@photon-ai/imessage-kit';
@@ -1,22 +1,23 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
1
2
  import {
2
3
  imessage
3
- } from "../chunk-PIULC4CM.js";
4
- import "../chunk-LJM5D2T5.js";
4
+ } from "../chunk-YJMPSD3S.js";
5
+ import "../chunk-JQN6CRSC.js";
5
6
  import {
6
7
  slack
7
- } from "../chunk-UFAZMTKC.js";
8
+ } from "../chunk-3OTECDNH.js";
8
9
  import {
9
10
  terminal
10
- } from "../chunk-6NGVREPQ.js";
11
- import "../chunk-5QSNQ6YN.js";
11
+ } from "../chunk-5BKZJMZV.js";
12
+ import "../chunk-NNY6LMSC.js";
12
13
  import {
13
14
  whatsappBusiness
14
- } from "../chunk-753K5YPL.js";
15
- import "../chunk-KO67KDBD.js";
16
- import "../chunk-VNMOZFWV.js";
17
- import "../chunk-RNGEA4UW.js";
18
- import "../chunk-32H3VVUE.js";
19
- import "../chunk-FTLJVVH7.js";
15
+ } from "../chunk-5TIF3FIE.js";
16
+ import "../chunk-2D27WW5B.js";
17
+ import "../chunk-MC6ZKFSG.js";
18
+ import "../chunk-QGJFZMD5.js";
19
+ import "../chunk-IPOFBAIM.js";
20
+ import "../chunk-2ILTJC35.js";
20
21
  export {
21
22
  imessage,
22
23
  slack,
@@ -1,4 +1,4 @@
1
- import { S as SchemaMessage, P as Platform, a as PlatformDef } from '../../types-Dqv4Ffqg.js';
1
+ import { S as SchemaMessage, P as Platform, a as PlatformDef } from '../../types-DcQ5a7PK.js';
2
2
  import * as z from 'zod';
3
3
  import z__default from 'zod';
4
4
  import * as _photon_ai_slack from '@photon-ai/slack';
@@ -1,9 +1,10 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
1
2
  import {
2
3
  slack
3
- } from "../../chunk-UFAZMTKC.js";
4
- import "../../chunk-VNMOZFWV.js";
5
- import "../../chunk-32H3VVUE.js";
6
- import "../../chunk-FTLJVVH7.js";
4
+ } from "../../chunk-3OTECDNH.js";
5
+ import "../../chunk-MC6ZKFSG.js";
6
+ import "../../chunk-IPOFBAIM.js";
7
+ import "../../chunk-2ILTJC35.js";
7
8
  export {
8
9
  slack
9
10
  };
@@ -1,4 +1,4 @@
1
- import { P as Platform, a as PlatformDef, M as Message, U as User, b as Space } from '../../types-Dqv4Ffqg.js';
1
+ import { P as Platform, a as PlatformDef, M as Message, U as User, b as Space } from '../../types-DcQ5a7PK.js';
2
2
  import { ChildProcess } from 'node:child_process';
3
3
  import z__default from 'zod';
4
4
  import { Socket } from 'node:net';
@@ -1,10 +1,11 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
1
2
  import {
2
3
  terminal
3
- } from "../../chunk-6NGVREPQ.js";
4
- import "../../chunk-5QSNQ6YN.js";
5
- import "../../chunk-RNGEA4UW.js";
6
- import "../../chunk-32H3VVUE.js";
7
- import "../../chunk-FTLJVVH7.js";
4
+ } from "../../chunk-5BKZJMZV.js";
5
+ import "../../chunk-NNY6LMSC.js";
6
+ import "../../chunk-QGJFZMD5.js";
7
+ import "../../chunk-IPOFBAIM.js";
8
+ import "../../chunk-2ILTJC35.js";
8
9
  export {
9
10
  terminal
10
11
  };
@@ -1,4 +1,4 @@
1
- import { S as SchemaMessage, P as Platform, a as PlatformDef } from '../../types-Dqv4Ffqg.js';
1
+ import { S as SchemaMessage, P as Platform, a as PlatformDef } from '../../types-DcQ5a7PK.js';
2
2
  import { WhatsAppClient } from '@photon-ai/whatsapp-business';
3
3
  import * as z from 'zod';
4
4
  import z__default from 'zod';
@@ -1,11 +1,12 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
1
2
  import {
2
3
  whatsappBusiness
3
- } from "../../chunk-753K5YPL.js";
4
- import "../../chunk-KO67KDBD.js";
5
- import "../../chunk-VNMOZFWV.js";
6
- import "../../chunk-RNGEA4UW.js";
7
- import "../../chunk-32H3VVUE.js";
8
- import "../../chunk-FTLJVVH7.js";
4
+ } from "../../chunk-5TIF3FIE.js";
5
+ import "../../chunk-2D27WW5B.js";
6
+ import "../../chunk-MC6ZKFSG.js";
7
+ import "../../chunk-QGJFZMD5.js";
8
+ import "../../chunk-IPOFBAIM.js";
9
+ import "../../chunk-2ILTJC35.js";
9
10
  export {
10
11
  whatsappBusiness
11
12
  };
@@ -762,6 +762,85 @@ interface Message<TPlatform extends string = string, TSender extends User = User
762
762
  timestamp: Date;
763
763
  }
764
764
 
765
+ type SubscriptionStatus = "active" | "canceled" | "past_due";
766
+ interface SubscriptionData {
767
+ status: SubscriptionStatus | null;
768
+ tier: string;
769
+ }
770
+ interface SharedTokenData {
771
+ expiresIn: number;
772
+ token: string;
773
+ type: "shared";
774
+ }
775
+ interface DedicatedTokenData {
776
+ auth: Record<string, string>;
777
+ expiresIn: number;
778
+ numbers: Record<string, string | null>;
779
+ type: "dedicated";
780
+ }
781
+ type TokenData = SharedTokenData | DedicatedTokenData;
782
+ type CloudPlatform = "imessage" | "whatsapp_business" | "slack";
783
+ interface PlatformStatus {
784
+ enabled: boolean;
785
+ }
786
+ type PlatformsData = Record<CloudPlatform, PlatformStatus>;
787
+ interface ImessageInfoData {
788
+ type: "shared" | "dedicated";
789
+ }
790
+ interface WhatsappBusinessTokenData {
791
+ auth: Record<string, string>;
792
+ expiresIn: number;
793
+ numbers: Record<string, string | null>;
794
+ }
795
+ interface SlackTeamMeta {
796
+ appId: string;
797
+ botUserId: string;
798
+ grantedScopes: string[];
799
+ teamName: string;
800
+ }
801
+ interface SlackTokenData {
802
+ auth: Record<string, string>;
803
+ expiresIn: number;
804
+ teams: Record<string, SlackTeamMeta>;
805
+ }
806
+ interface FusorTokenData {
807
+ expiresIn: number;
808
+ token: string;
809
+ }
810
+ /**
811
+ * Per-project profile bag — a flexible record of project-level settings
812
+ * defined in Spectrum Cloud. Concrete fields depend on the project; consumers
813
+ * read them as `app.config.profile.<key>`.
814
+ */
815
+ interface ProjectProfile {
816
+ [key: string]: unknown;
817
+ }
818
+ /**
819
+ * The project record returned by `GET /projects/{projectId}/`. Populated on
820
+ * `app.config` when `Spectrum()` is called with `projectId` + `projectSecret`.
821
+ */
822
+ interface ProjectData {
823
+ id: string;
824
+ name: string;
825
+ profile: ProjectProfile;
826
+ }
827
+ declare class SpectrumCloudError extends Error {
828
+ readonly status: number;
829
+ readonly code: string;
830
+ constructor(status: number, code: string, message: string);
831
+ }
832
+ declare const cloud: {
833
+ getProject: (projectId: string, projectSecret: string) => Promise<ProjectData>;
834
+ getSubscription: (projectId: string) => Promise<SubscriptionData>;
835
+ issueImessageTokens: (projectId: string, projectSecret: string) => Promise<TokenData>;
836
+ getImessageInfo: (projectId: string) => Promise<ImessageInfoData>;
837
+ issueWhatsappBusinessTokens: (projectId: string, projectSecret: string) => Promise<WhatsappBusinessTokenData>;
838
+ issueSlackTokens: (projectId: string, projectSecret: string) => Promise<SlackTokenData>;
839
+ issueFusorToken: (projectId: string, projectSecret: string) => Promise<FusorTokenData>;
840
+ getPlatforms: (projectId: string) => Promise<PlatformsData>;
841
+ togglePlatform: (projectId: string, projectSecret: string, platform: CloudPlatform, enabled: boolean) => Promise<PlatformsData>;
842
+ };
843
+
765
844
  /**
766
845
  * A small per-platform key-value bag, modeled after Swift's `UserDefaults`.
767
846
  * Untyped writes; typed reads return `undefined` on missing key OR type
@@ -891,6 +970,13 @@ type InputSchema<TSchema> = TSchema extends z__default.ZodType<object> ? z__defa
891
970
  type EventProducer<TPayload = unknown, TClient = unknown, TConfig = unknown> = (ctx: {
892
971
  client: NoInferClient<TClient>;
893
972
  config: TConfig;
973
+ /**
974
+ * Spectrum Cloud project metadata, fetched once at `Spectrum()` init.
975
+ * `undefined` when the instance was created without `projectId`/`projectSecret`
976
+ * (local-only setups). Providers read project-level toggles from
977
+ * `projectConfig.profile.<key>` — e.g. iMessage's `imessageSynced` flag.
978
+ */
979
+ projectConfig: ProjectData | undefined;
894
980
  store: Store;
895
981
  }) => AsyncIterable<TPayload>;
896
982
  type ProviderMessage<TSender extends ResolvedUser = ResolvedUser, TSpace extends ResolvedSpace = ResolvedSpace, TExtra extends object = Record<never, never>> = {
@@ -925,7 +1011,7 @@ type ProviderMessageRecord = {
925
1011
  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;
926
1012
  type SchemaMessage<TUserSchema extends z__default.ZodType | undefined = undefined, TSpaceSchema extends z__default.ZodType | undefined = undefined> = ProviderMessage<MergeSchema<TUserSchema, ResolvedUser>, MergeSchema<TSpaceSchema, ResolvedSpace>>;
927
1013
  type InferEventPayload<T> = T extends (ctx: never) => AsyncIterable<infer P> ? P : never;
928
- type ReservedNames = "stop" | "send" | "__internal" | "__providers";
1014
+ type ReservedNames = "stop" | "send" | "config" | "__internal" | "__providers";
929
1015
  interface CreateClientContext<_ConfigSchema extends z__default.ZodType<object>> {
930
1016
  config: z__default.infer<_ConfigSchema>;
931
1017
  projectId: string | undefined;
@@ -1237,4 +1323,4 @@ interface Platform<Def extends AnyPlatformDef> {
1237
1323
  (message: Message): PlatformMessage<Def>;
1238
1324
  }
1239
1325
 
1240
- export { type AgentSender as A, type Broadcaster as B, type ContentBuilder as C, type EventProducer as E, type InstanceActionFn as I, type Message as M, type Platform as P, type SchemaMessage as S, type User as U, type PlatformDef as a, type Space as b, type ContentInput as c, type Store as d, type Content as e, type ProviderMessageRecord as f, type SpaceActionFn as g, type MessageActionFn as h, type CreateClientContext as i, type ProviderMessage as j, type PlatformProviderConfig as k, type SpectrumLike as l, type CustomEventStreams as m, type AnyPlatformDef as n, type ManagedStream as o, type PlatformInstance as p, type PlatformMessage as q, type PlatformRuntime as r, type PlatformSpace as s, type PlatformUser as t, broadcast as u, mergeStreams as v, stream as w };
1326
+ export { type AgentSender as A, type Broadcaster as B, type ContentBuilder as C, type DedicatedTokenData as D, type EventProducer as E, type FusorTokenData as F, type SharedTokenData as G, type SlackTeamMeta as H, type InstanceActionFn as I, type SlackTokenData as J, SpectrumCloudError as K, type SubscriptionData as L, type Message as M, type SubscriptionStatus as N, broadcast as O, type Platform as P, cloud as Q, mergeStreams as R, type SchemaMessage as S, type TokenData as T, type User as U, stream as V, type PlatformDef as a, type Space as b, type ContentInput as c, type Store as d, type Content as e, type ProviderMessageRecord as f, type SpaceActionFn as g, type MessageActionFn as h, type CreateClientContext as i, type ProviderMessage as j, type PlatformProviderConfig as k, type SpectrumLike as l, type CustomEventStreams as m, type ProjectData as n, type AnyPlatformDef as o, type CloudPlatform as p, type ImessageInfoData as q, type ManagedStream as r, type PlatformInstance as s, type PlatformMessage as t, type PlatformRuntime as u, type PlatformSpace as v, type PlatformStatus as w, type PlatformUser as x, type PlatformsData as y, type ProjectProfile as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spectrum-ts",
3
- "version": "1.16.1",
3
+ "version": "1.17.1",
4
4
  "description": "Bring agents to any interface — unified messaging SDK for TypeScript.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -45,6 +45,8 @@
45
45
  "@photon-ai/whatsapp-business": "^0.1.1",
46
46
  "@photon-ai/proto": "^0.2.4",
47
47
  "@repeaterjs/repeater": "^3.0.6",
48
+ "better-grpc": "^0.3.2",
49
+ "lru-cache": "^11.0.0",
48
50
  "mime-types": "^3.0.1",
49
51
  "nice-grpc": "^2.1.16",
50
52
  "nice-grpc-common": "^2.0.2",