spectrum-ts 4.0.0 → 4.1.0

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.
@@ -1,5 +1,5 @@
1
1
  import z__default from 'zod';
2
- import { C as ContentBuilder } from './types-Be0T6E0e.js';
2
+ import { C as ContentBuilder } from './types-CyfLJXgu.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-CEpGtZLm.js';
1
+ import './attachment-CnivEhr6.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, e as Space, h as ContentInput } from './types-Be0T6E0e.js';
4
+ import { U as User, C as ContentBuilder, M as Message, S as Space, h as ContentInput } from './types-CyfLJXgu.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-CEpGtZLm.js';
2
- export { q as asContact, s as asCustom, u as asGroup, w as asPoll, x as asPollOption, y as asRichlink, z as asText, A as asVoice } from './authoring-CP3vRza8.js';
3
- export { d as ProviderMessageRecord, $ as asReaction } from './types-Be0T6E0e.js';
1
+ export { c as asAttachment } from './attachment-CnivEhr6.js';
2
+ export { q as asContact, s as asCustom, u as asGroup, w as asPoll, x as asPollOption, y as asRichlink, z as asText, A as asVoice } from './authoring-b9AhXgPI.js';
3
+ export { e as ProviderMessageRecord, $ as asReaction } from './types-CyfLJXgu.js';
4
4
  import 'zod';
5
5
  import 'vcf';
6
6
  import 'hotscript';
@@ -15,7 +15,7 @@ import {
15
15
  import {
16
16
  UnsupportedError,
17
17
  definePlatform
18
- } from "./chunk-OGTHPDG7.js";
18
+ } from "./chunk-B52VPQO3.js";
19
19
  import {
20
20
  asAttachment,
21
21
  asCustom,
@@ -644,6 +644,10 @@ var send = async (clients, spaceId, content) => {
644
644
  if (content.type === "typing") {
645
645
  return;
646
646
  }
647
+ if (content.type === "read") {
648
+ await primary(clients).messages.markRead(content.target.id);
649
+ return;
650
+ }
647
651
  const client = primary(clients);
648
652
  switch (content.type) {
649
653
  case "text":
@@ -46,10 +46,10 @@ var resolveMimeType = (input, mimeType, contentLabel) => {
46
46
  `Unable to resolve MIME type for ${contentLabel}. Pass options.mimeType explicitly.`
47
47
  );
48
48
  };
49
- var cachedRead = (read) => {
49
+ var cachedRead = (read2) => {
50
50
  let cached;
51
51
  return () => {
52
- cached ??= read().catch((err) => {
52
+ cached ??= read2().catch((err) => {
53
53
  cached = void 0;
54
54
  throw err;
55
55
  });
@@ -61,16 +61,16 @@ var buildPhotoAction = (input, options, contentLabel) => {
61
61
  return { kind: "clear" };
62
62
  }
63
63
  const mimeType = resolveMimeType(input, options?.mimeType, contentLabel);
64
- let read;
64
+ let read2;
65
65
  if (input instanceof URL) {
66
- read = cachedRead(async () => (await fetchUrlBytes(input)).data);
66
+ read2 = cachedRead(async () => (await fetchUrlBytes(input)).data);
67
67
  } else if (typeof input === "string") {
68
- read = cachedRead(() => readFile(input));
68
+ read2 = cachedRead(() => readFile(input));
69
69
  } else {
70
70
  const snapshot = Buffer.from(input);
71
- read = cachedRead(async () => snapshot);
71
+ read2 = cachedRead(async () => snapshot);
72
72
  }
73
- return { kind: "set", read, mimeType };
73
+ return { kind: "set", read: read2, mimeType };
74
74
  };
75
75
 
76
76
  // src/content/avatar.ts
@@ -116,7 +116,7 @@ function edit(content, target) {
116
116
  if (!resolved) {
117
117
  throw new Error("edit() requires content");
118
118
  }
119
- if (resolved.type === "edit" || resolved.type === "reply" || resolved.type === "reaction" || resolved.type === "group" || resolved.type === "typing" || resolved.type === "rename" || resolved.type === "avatar" || resolved.type === "unsend") {
119
+ if (resolved.type === "edit" || resolved.type === "reply" || resolved.type === "reaction" || resolved.type === "group" || resolved.type === "typing" || resolved.type === "rename" || resolved.type === "avatar" || resolved.type === "unsend" || resolved.type === "read") {
120
120
  throw new Error(`edit() cannot wrap "${resolved.type}" content`);
121
121
  }
122
122
  return asEdit({ content: resolved, target });
@@ -138,11 +138,34 @@ function markdown(source, options) {
138
138
  return streamTextBuilder("markdown", source, options);
139
139
  }
140
140
 
141
- // src/content/rename.ts
141
+ // src/content/read.ts
142
142
  import z5 from "zod";
143
- var renameSchema = z5.object({
144
- type: z5.literal("rename"),
145
- displayName: z5.string().min(1, "rename() displayName must be non-empty")
143
+ var isMessage2 = (v) => typeof v === "object" && v !== null && "id" in v && "content" in v;
144
+ var readSchema2 = z5.object({
145
+ type: z5.literal("read"),
146
+ target: z5.custom(isMessage2, {
147
+ message: "read target must be a Message"
148
+ })
149
+ });
150
+ var asRead = (input) => readSchema2.parse({ type: "read", ...input });
151
+ function read(target) {
152
+ return {
153
+ build: async () => {
154
+ if (target.direction !== "inbound") {
155
+ throw new Error(
156
+ `read() target must be an inbound message (got direction "${target.direction}", message id "${target.id}")`
157
+ );
158
+ }
159
+ return asRead({ target });
160
+ }
161
+ };
162
+ }
163
+
164
+ // src/content/rename.ts
165
+ import z6 from "zod";
166
+ var renameSchema = z6.object({
167
+ type: z6.literal("rename"),
168
+ displayName: z6.string().min(1, "rename() displayName must be non-empty")
146
169
  });
147
170
  function rename(displayName) {
148
171
  return {
@@ -151,15 +174,15 @@ function rename(displayName) {
151
174
  }
152
175
 
153
176
  // src/content/reply.ts
154
- import z6 from "zod";
155
- var isMessage2 = (v) => typeof v === "object" && v !== null && "id" in v && "content" in v;
177
+ import z7 from "zod";
178
+ var isMessage3 = (v) => typeof v === "object" && v !== null && "id" in v && "content" in v;
156
179
  var isContent2 = (v) => typeof v === "object" && v !== null && "type" in v && typeof v.type === "string";
157
- var replySchema = z6.object({
158
- type: z6.literal("reply"),
159
- content: z6.custom(isContent2, {
180
+ var replySchema = z7.object({
181
+ type: z7.literal("reply"),
182
+ content: z7.custom(isContent2, {
160
183
  message: "reply content must be a Content value"
161
184
  }),
162
- target: z6.custom(isMessage2, {
185
+ target: z7.custom(isMessage3, {
163
186
  message: "reply target must be a Message"
164
187
  })
165
188
  });
@@ -176,7 +199,7 @@ function reply(content, target) {
176
199
  if (!resolved) {
177
200
  throw new Error("reply() requires content");
178
201
  }
179
- if (resolved.type === "reply" || resolved.type === "edit" || resolved.type === "reaction" || resolved.type === "group" || resolved.type === "typing" || resolved.type === "rename" || resolved.type === "avatar" || resolved.type === "unsend") {
202
+ if (resolved.type === "reply" || resolved.type === "edit" || resolved.type === "reaction" || resolved.type === "group" || resolved.type === "typing" || resolved.type === "rename" || resolved.type === "avatar" || resolved.type === "unsend" || resolved.type === "read") {
180
203
  throw new Error(`reply() cannot wrap "${resolved.type}" content`);
181
204
  }
182
205
  return asReply({ content: resolved, target });
@@ -185,10 +208,10 @@ function reply(content, target) {
185
208
  }
186
209
 
187
210
  // src/content/typing.ts
188
- import z7 from "zod";
189
- var typingSchema = z7.object({
190
- type: z7.literal("typing"),
191
- state: z7.enum(["start", "stop"])
211
+ import z8 from "zod";
212
+ var typingSchema = z8.object({
213
+ type: z8.literal("typing"),
214
+ state: z8.enum(["start", "stop"])
192
215
  });
193
216
  function typing(state = "start") {
194
217
  return {
@@ -197,11 +220,11 @@ function typing(state = "start") {
197
220
  }
198
221
 
199
222
  // src/content/unsend.ts
200
- import z8 from "zod";
201
- var isMessage3 = (v) => typeof v === "object" && v !== null && "id" in v && "content" in v;
202
- var unsendSchema = z8.object({
203
- type: z8.literal("unsend"),
204
- target: z8.custom(isMessage3, {
223
+ import z9 from "zod";
224
+ var isMessage4 = (v) => typeof v === "object" && v !== null && "id" in v && "content" in v;
225
+ var unsendSchema = z9.object({
226
+ type: z9.literal("unsend"),
227
+ target: z9.custom(isMessage4, {
205
228
  message: "unsend target must be a Message"
206
229
  })
207
230
  });
@@ -545,7 +568,8 @@ var FIRE_AND_FORGET_TYPES = /* @__PURE__ */ new Set([
545
568
  "edit",
546
569
  "rename",
547
570
  "avatar",
548
- "unsend"
571
+ "unsend",
572
+ "read"
549
573
  ]);
550
574
  var isFireAndForget = (item) => FIRE_AND_FORGET_TYPES.has(item.type) || item.__fireAndForget === true;
551
575
  var RESERVED_SPACE_KEYS = /* @__PURE__ */ new Set([
@@ -554,6 +578,7 @@ var RESERVED_SPACE_KEYS = /* @__PURE__ */ new Set([
554
578
  "send",
555
579
  "edit",
556
580
  "unsend",
581
+ "read",
557
582
  "getMessage",
558
583
  "rename",
559
584
  "avatar",
@@ -569,6 +594,7 @@ var RESERVED_MESSAGE_KEYS = /* @__PURE__ */ new Set([
569
594
  "id",
570
595
  "platform",
571
596
  "react",
597
+ "read",
572
598
  "reply",
573
599
  "sender",
574
600
  "space",
@@ -938,6 +964,9 @@ function buildSpace(params) {
938
964
  unsend: async (message) => {
939
965
  await space.send(unsend(message));
940
966
  },
967
+ read: async (message) => {
968
+ await space.send(read(message));
969
+ },
941
970
  getMessage: getMessageImpl,
942
971
  rename: async (displayName) => {
943
972
  await space.send(rename(displayName));
@@ -1010,6 +1039,15 @@ function buildMessage(params) {
1010
1039
  }
1011
1040
  await space.send(unsend(target));
1012
1041
  };
1042
+ const read2 = async () => {
1043
+ const target = requireBuiltMessage("read");
1044
+ if (target.direction !== "inbound") {
1045
+ throw new Error(
1046
+ `cannot mark message ${target.id} as read: only inbound messages can be marked read (direction: "${target.direction}")`
1047
+ );
1048
+ }
1049
+ await space.send(read(target));
1050
+ };
1013
1051
  const buildSenderWithPlatform = () => {
1014
1052
  if (params.sender === void 0) {
1015
1053
  return;
@@ -1046,6 +1084,7 @@ function buildMessage(params) {
1046
1084
  direction: params.direction,
1047
1085
  platform: definition.name,
1048
1086
  react,
1087
+ read: read2,
1049
1088
  reply: reply2,
1050
1089
  edit: edit2,
1051
1090
  unsend: unsend2,
@@ -1325,6 +1364,7 @@ export {
1325
1364
  markdownSchema,
1326
1365
  asMarkdown,
1327
1366
  markdown,
1367
+ read,
1328
1368
  rename,
1329
1369
  reply,
1330
1370
  typing,
@@ -30,7 +30,7 @@ import {
30
30
  definePlatform,
31
31
  markdownSchema,
32
32
  photoActionSchema
33
- } from "./chunk-OGTHPDG7.js";
33
+ } from "./chunk-B52VPQO3.js";
34
34
  import {
35
35
  asAttachment,
36
36
  asCustom,
@@ -172,68 +172,38 @@ function effect(input, messageEffect) {
172
172
  };
173
173
  }
174
174
 
175
- // src/providers/imessage/content/read.ts
176
- import z4 from "zod";
177
- var isMessage = (v) => typeof v === "object" && v !== null && "id" in v && "content" in v;
178
- var readSchema = z4.object({
179
- type: z4.literal("read"),
180
- __platform: z4.literal("iMessage"),
181
- __fireAndForget: z4.literal(true),
182
- target: z4.custom(isMessage, {
183
- message: "read target must be a Message"
184
- })
185
- });
186
- var isRead = (v) => readSchema.safeParse(v).success;
187
- function read(target) {
188
- return {
189
- build: async () => {
190
- if (target.direction !== "inbound") {
191
- throw new Error(
192
- `read() target must be an inbound message (got direction "${target.direction}", message id "${target.id}")`
193
- );
194
- }
195
- return readSchema.parse({
196
- type: "read",
197
- __platform: "iMessage",
198
- __fireAndForget: true,
199
- target
200
- });
201
- }
202
- };
203
- }
204
-
205
175
  // src/providers/imessage/auth.ts
206
176
  import { createClient } from "@photon-ai/advanced-imessage";
207
177
 
208
178
  // src/providers/imessage/types.ts
209
179
  import { IMessageSDK } from "@photon-ai/imessage-kit";
210
- import z5 from "zod";
180
+ import z4 from "zod";
211
181
  var SHARED_PHONE = "shared";
212
182
  var isLocal = (client) => client instanceof IMessageSDK;
213
- var clientEntry = z5.object({
214
- address: z5.string(),
215
- token: z5.string(),
216
- phone: z5.string()
183
+ var clientEntry = z4.object({
184
+ address: z4.string(),
185
+ token: z4.string(),
186
+ phone: z4.string()
217
187
  });
218
- var configSchema = z5.union([
219
- z5.object({ local: z5.literal(true) }),
220
- z5.object({
221
- local: z5.literal(false).optional().default(false),
222
- clients: clientEntry.or(z5.array(clientEntry)).optional()
188
+ var configSchema = z4.union([
189
+ z4.object({ local: z4.literal(true) }),
190
+ z4.object({
191
+ local: z4.literal(false).optional().default(false),
192
+ clients: clientEntry.or(z4.array(clientEntry)).optional()
223
193
  })
224
194
  ]);
225
- var userSchema = z5.object({});
226
- var spaceSchema = z5.object({
227
- id: z5.string(),
228
- type: z5.enum(["dm", "group"]),
229
- phone: z5.string()
195
+ var userSchema = z4.object({});
196
+ var spaceSchema = z4.object({
197
+ id: z4.string(),
198
+ type: z4.enum(["dm", "group"]),
199
+ phone: z4.string()
230
200
  });
231
- var spaceParamsSchema = z5.object({
232
- phone: z5.string().optional()
201
+ var spaceParamsSchema = z4.object({
202
+ phone: z4.string().optional()
233
203
  });
234
- var messageSchema = z5.object({
235
- partIndex: z5.number().int().nonnegative().optional(),
236
- parentId: z5.string().optional()
204
+ var messageSchema = z4.object({
205
+ partIndex: z4.number().int().nonnegative().optional(),
206
+ parentId: z4.string().optional()
237
207
  });
238
208
 
239
209
  // src/providers/imessage/auth.ts
@@ -2852,23 +2822,11 @@ var imessage = definePlatform("iMessage", {
2852
2822
  // local-mode iMessage is identical to the canonical form.
2853
2823
  background: async (space, input, opts) => {
2854
2824
  await space.send(background(input, opts));
2855
- },
2856
- // Sugar: `space.read(message)` → `space.send(read(message))`.
2857
- read: async (space, message) => {
2858
- await space.send(read(message));
2859
2825
  }
2860
2826
  }
2861
2827
  },
2862
2828
  message: {
2863
- schema: messageSchema,
2864
- actions: {
2865
- // Sugar: `message.read()` → `message.space.send(read(self))`.
2866
- // `buildMessage` injects the message as the first argument; callers
2867
- // pass nothing.
2868
- read: async (message) => {
2869
- await message.space.send(read(message));
2870
- }
2871
- }
2829
+ schema: messageSchema
2872
2830
  },
2873
2831
  messages: ({ client, projectConfig }) => isLocal(client) ? messages2(client) : messages4(client, projectConfig),
2874
2832
  send: async ({ space, content, client }) => {
@@ -2941,12 +2899,12 @@ var imessage = definePlatform("iMessage", {
2941
2899
  await handleAvatar(client, space, content);
2942
2900
  return;
2943
2901
  }
2944
- if (isBackground(content)) {
2945
- await handleBackground(client, space, content);
2902
+ if (content.type === "read") {
2903
+ await handleRead(client, space);
2946
2904
  return;
2947
2905
  }
2948
- if (isRead(content)) {
2949
- await handleRead(client, space);
2906
+ if (isBackground(content)) {
2907
+ await handleBackground(client, space, content);
2950
2908
  return;
2951
2909
  }
2952
2910
  if (isCustomizedMiniApp(content)) {
@@ -3018,6 +2976,5 @@ export {
3018
2976
  background,
3019
2977
  customizedMiniApp,
3020
2978
  effect,
3021
- read,
3022
2979
  imessage
3023
2980
  };
@@ -15,7 +15,7 @@ import {
15
15
  import {
16
16
  UnsupportedError,
17
17
  definePlatform
18
- } from "./chunk-OGTHPDG7.js";
18
+ } from "./chunk-B52VPQO3.js";
19
19
  import {
20
20
  asAttachment,
21
21
  asCustom,
@@ -16,7 +16,7 @@ import {
16
16
  asMarkdown,
17
17
  definePlatform,
18
18
  renderInlineTokens
19
- } from "./chunk-OGTHPDG7.js";
19
+ } from "./chunk-B52VPQO3.js";
20
20
  import {
21
21
  asAttachment,
22
22
  asCustom,
@@ -793,6 +793,8 @@ var send = async ({
793
793
  return await sendReaction(client, space, content);
794
794
  case "typing":
795
795
  return await sendTyping(client, space, content.state);
796
+ case "read":
797
+ return;
796
798
  case "edit":
797
799
  return await sendEdit(client, space, content);
798
800
  case "group":
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  UnsupportedError,
11
11
  definePlatform
12
- } from "./chunk-OGTHPDG7.js";
12
+ } from "./chunk-B52VPQO3.js";
13
13
  import {
14
14
  asAttachment,
15
15
  asCustom,
@@ -350,6 +350,9 @@ var send = async (client, space, content) => {
350
350
  if (content.type === "typing") {
351
351
  return;
352
352
  }
353
+ if (content.type === "read") {
354
+ return;
355
+ }
353
356
  return await sendContent(client, space, content);
354
357
  };
355
358
  var sendContent = async (client, space, content, threadTs) => {
package/dist/index.d.ts CHANGED
@@ -1,12 +1,13 @@
1
- export { A as Attachment, a as AttachmentInput, b as attachment } from './attachment-CEpGtZLm.js';
1
+ export { A as Attachment, a as AttachmentInput, b as attachment } from './attachment-CnivEhr6.js';
2
2
  import z__default from 'zod';
3
- import { P as PhotoInput } from './photo-content-BJKnqgN-.js';
4
- import { C as ContentBuilder, M as Message, U as User, e as Space, h as ContentInput, i as Content, g as ProviderMessage, E as EventProducer, j as SpaceActionFn, k as MessageActionFn, I as InstanceActionFn, l as CreateClientContext, c as Store, a as PlatformDef, P as Platform, m as PlatformProviderConfig, n as SpectrumLike, o as CustomEventStreams, A as AgentSender, b as ProjectData } from './types-Be0T6E0e.js';
5
- export { p as AnyPlatformDef, B as Broadcaster, q as CloudPlatform, D as DedicatedTokenData, F as FusorTokenData, r as ImessageInfoData, s as ManagedStream, t as PlatformInstance, u as PlatformMessage, v as PlatformRuntime, w as PlatformSpace, x as PlatformStatus, y as PlatformUser, z as PlatformsData, G as ProjectProfile, R as Reaction, H as ReactionBuilder, S as SchemaMessage, J as SharedTokenData, K as SlackTeamMeta, L as SlackTokenData, N as SpaceNamespace, O as SpectrumCloudError, Q as SubscriptionData, T as SubscriptionStatus, V as TokenData, W as broadcast, X as cloud, Y as mergeStreams, Z as reaction, _ as stream } from './types-Be0T6E0e.js';
6
- import { S as StreamTextSource, T as TextStreamOptions, C as ContactInput, a as Contact } from './authoring-CP3vRza8.js';
7
- export { b as ContactAddress, c as ContactDetails, d as ContactEmail, e as ContactName, f as ContactOrg, g as ContactPhone, D as DeltaExtractor, G as Group, P as Poll, h as PollChoice, i as PollChoiceInput, j as PollOption, R as Richlink, k as StreamText, V as Voice, l as contact, m as custom, n as group, o as option, p as poll, r as richlink, t as text, v as voice } from './authoring-CP3vRza8.js';
8
- import { a as FusorVerify, F as FusorClient, b as FusorMessages, W as WebhookHandler, c as WebhookRawRequest, d as WebhookRawResult } from './types-CDYXH2R7.js';
9
- export { e as FusorEvent, f as FusorMessagesCtx, g as FusorMessagesReturn, h as FusorReply, i as FusorRespond, j as FusorVerifyRequest, k as fusorEvent, l as isFusorEvent } from './types-CDYXH2R7.js';
3
+ import { P as PhotoInput } from './read-C4uvozGX.js';
4
+ export { R as Read, r as read } from './read-C4uvozGX.js';
5
+ import { C as ContentBuilder, M as Message, U as User, S as Space, h as ContentInput, i as Content, g as ProviderMessage, E as EventProducer, j as SpaceActionFn, k as MessageActionFn, I as InstanceActionFn, l as CreateClientContext, d as Store, b as PlatformDef, P as Platform, m as PlatformProviderConfig, n as SpectrumLike, o as CustomEventStreams, A as AgentSender, c as ProjectData } from './types-CyfLJXgu.js';
6
+ export { p as AnyPlatformDef, B as Broadcaster, q as CloudPlatform, D as DedicatedTokenData, F as FusorTokenData, r as ImessageInfoData, s as ManagedStream, t as PlatformInstance, u as PlatformMessage, v as PlatformRuntime, w as PlatformSpace, x as PlatformStatus, y as PlatformUser, z as PlatformsData, G as ProjectProfile, R as Reaction, H as ReactionBuilder, a as SchemaMessage, J as SharedTokenData, K as SlackTeamMeta, L as SlackTokenData, N as SpaceNamespace, O as SpectrumCloudError, Q as SubscriptionData, T as SubscriptionStatus, V as TokenData, W as broadcast, X as cloud, Y as mergeStreams, Z as reaction, _ as stream } from './types-CyfLJXgu.js';
7
+ import { S as StreamTextSource, T as TextStreamOptions, C as ContactInput, a as Contact } from './authoring-b9AhXgPI.js';
8
+ export { b as ContactAddress, c as ContactDetails, d as ContactEmail, e as ContactName, f as ContactOrg, g as ContactPhone, D as DeltaExtractor, G as Group, P as Poll, h as PollChoice, i as PollChoiceInput, j as PollOption, R as Richlink, k as StreamText, V as Voice, l as contact, m as custom, n as group, o as option, p as poll, r as richlink, t as text, v as voice } from './authoring-b9AhXgPI.js';
9
+ import { a as FusorVerify, F as FusorClient, b as FusorMessages, W as WebhookHandler, c as WebhookRawRequest, d as WebhookRawResult } from './types-BIta6Kxi.js';
10
+ export { e as FusorEvent, f as FusorMessagesCtx, g as FusorMessagesReturn, h as FusorReply, i as FusorRespond, j as FusorVerifyRequest, k as fusorEvent, l as isFusorEvent } from './types-BIta6Kxi.js';
10
11
  import 'hotscript';
11
12
  import 'vcf';
12
13
 
@@ -67,7 +68,7 @@ declare function avatar(input: Buffer, options: {
67
68
  * (no new message id is produced; the existing message mutates in place).
68
69
  *
69
70
  * Edit cannot wrap `edit`, `reply`, `reaction`, `group`, `typing`, `rename`,
70
- * `avatar`, or `unsend` content.
71
+ * `avatar`, `unsend`, or `read` content.
71
72
  */
72
73
  declare const editSchema: z__default.ZodObject<{
73
74
  type: z__default.ZodLiteral<"edit">;
@@ -427,7 +428,7 @@ declare function rename(displayName: string): ContentBuilder;
427
428
  * `reply` like any other content type and route to a threaded send.
428
429
  *
429
430
  * Reply cannot wrap `reply`, `edit`, `reaction`, `group`, `typing`,
430
- * `rename`, `avatar`, or `unsend` content.
431
+ * `rename`, `avatar`, `unsend`, or `read` content.
431
432
  */
432
433
  declare const replySchema: z__default.ZodObject<{
433
434
  type: z__default.ZodLiteral<"reply">;
package/dist/index.js CHANGED
@@ -44,13 +44,14 @@ import {
44
44
  definePlatform,
45
45
  edit,
46
46
  markdown,
47
+ read,
47
48
  rename,
48
49
  reply,
49
50
  senderAttrs,
50
51
  typing,
51
52
  unsend,
52
53
  wrapProviderMessage
53
- } from "./chunk-OGTHPDG7.js";
54
+ } from "./chunk-B52VPQO3.js";
54
55
  import {
55
56
  attachment,
56
57
  custom,
@@ -3358,6 +3359,7 @@ export {
3358
3359
  option,
3359
3360
  poll,
3360
3361
  reaction,
3362
+ read,
3361
3363
  rename,
3362
3364
  reply,
3363
3365
  resolveContents,
@@ -1,9 +1,10 @@
1
- import { C as ContentBuilder, h as ContentInput, M as Message, S as SchemaMessage, P as Platform, a as PlatformDef, e as Space, c as Store } from '../../types-Be0T6E0e.js';
1
+ import { C as ContentBuilder, h as ContentInput, a as SchemaMessage, P as Platform, b as PlatformDef, S as Space, d as Store } from '../../types-CyfLJXgu.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-CEpGtZLm.js';
6
- import { P as PhotoInput } from '../../photo-content-BJKnqgN-.js';
5
+ import { A as Attachment } from '../../attachment-CnivEhr6.js';
6
+ import { P as PhotoInput } from '../../read-C4uvozGX.js';
7
+ export { r as read } from '../../read-C4uvozGX.js';
7
8
  import { MessageEffect, AdvancedIMessage } from '@photon-ai/advanced-imessage';
8
9
  import { IMessageSDK } from '@photon-ai/imessage-kit';
9
10
  import 'hotscript';
@@ -114,26 +115,6 @@ declare function customizedMiniApp(input: CustomizedMiniAppInput): ContentBuilde
114
115
  type IMessageMessageEffect = MessageEffect;
115
116
  declare function effect(input: ContentInput, messageEffect: IMessageMessageEffect): ContentBuilder;
116
117
 
117
- /**
118
- * Mark the chat containing `target` as read. iMessage-only, remote-only.
119
- *
120
- * Implemented via `chats.markRead(chatGuid)`, which marks **every unread
121
- * message in the chat** as read — there is no per-message read receipt in
122
- * the SDK. `target` is used only to identify the chat (and to give
123
- * `message.read()` something to pass), so passing any message from a chat
124
- * marks the whole chat as read.
125
- *
126
- * `space.send(read(message))` is the canonical form; `space.read(message)`
127
- * and `message.read()` are sugar attached via the iMessage platform's
128
- * `space.actions` / `message.actions` slots.
129
- *
130
- * `Read` is intentionally not a member of the universal `Content` union —
131
- * the `as unknown as Content` cast keeps the builder shape compatible with
132
- * the framework's `ContentBuilder.build(): Promise<Content>` signature. The
133
- * framework treats it as a fire-and-forget control signal at runtime.
134
- */
135
- declare function read(target: Message): ContentBuilder;
136
-
137
118
  interface RemoteClient {
138
119
  client: AdvancedIMessage;
139
120
  phone: string;
@@ -189,10 +170,7 @@ declare const imessage: Platform<PlatformDef<"iMessage", z.ZodUnion<readonly [z.
189
170
  background: (space: Space, input: BackgroundInput, opts?: {
190
171
  mimeType?: string;
191
172
  }) => Promise<void>;
192
- read: (space: Space, message: Message) => Promise<void>;
193
- }, {
194
- read: (message: Message) => Promise<void>;
195
- }, {
173
+ }, Record<never, never>, {
196
174
  getMessage: ({ client }: {
197
175
  client: IMessageClient;
198
176
  config: {
@@ -241,4 +219,4 @@ declare const imessage: Platform<PlatformDef<"iMessage", z.ZodUnion<readonly [z.
241
219
  };
242
220
  }>;
243
221
 
244
- export { type BackgroundInput, type CustomizedMiniApp, type CustomizedMiniAppInput, type CustomizedMiniAppLayout, type IMessageMessageEffect, background, customizedMiniApp, effect, imessage, read };
222
+ export { type BackgroundInput, type CustomizedMiniApp, type CustomizedMiniAppInput, type CustomizedMiniAppLayout, type IMessageMessageEffect, background, customizedMiniApp, effect, imessage };
@@ -3,9 +3,8 @@ import {
3
3
  background,
4
4
  customizedMiniApp,
5
5
  effect,
6
- imessage,
7
- read
8
- } from "../../chunk-W5HNZ7YT.js";
6
+ imessage
7
+ } from "../../chunk-DMT6BFJV.js";
9
8
  import "../../chunk-ZR3TKZMT.js";
10
9
  import "../../chunk-LZXPLXZF.js";
11
10
  import "../../chunk-2D27WW5B.js";
@@ -13,7 +12,9 @@ import "../../chunk-3GEJYGZK.js";
13
12
  import "../../chunk-A37PM5N2.js";
14
13
  import "../../chunk-5XEFJBN2.js";
15
14
  import "../../chunk-6UZFVXQF.js";
16
- import "../../chunk-OGTHPDG7.js";
15
+ import {
16
+ read
17
+ } from "../../chunk-B52VPQO3.js";
17
18
  import "../../chunk-UXAKIXVM.js";
18
19
  export {
19
20
  background,
@@ -3,17 +3,17 @@ export { slack } from './slack/index.js';
3
3
  export { telegram } from './telegram/index.js';
4
4
  export { terminal } from './terminal/index.js';
5
5
  export { whatsappBusiness } from './whatsapp-business/index.js';
6
- import '../types-Be0T6E0e.js';
6
+ import '../types-CyfLJXgu.js';
7
7
  import 'hotscript';
8
8
  import 'zod';
9
9
  import 'zod/v4/core';
10
- import '../attachment-CEpGtZLm.js';
11
- import '../photo-content-BJKnqgN-.js';
10
+ import '../attachment-CnivEhr6.js';
11
+ import '../read-C4uvozGX.js';
12
12
  import '@photon-ai/advanced-imessage';
13
13
  import '@photon-ai/imessage-kit';
14
14
  import '@photon-ai/slack';
15
15
  import '@photon-ai/telegram-ts';
16
- import '../types-CDYXH2R7.js';
16
+ import '../types-BIta6Kxi.js';
17
17
  import 'node:child_process';
18
18
  import 'node:net';
19
19
  import '@photon-ai/whatsapp-business';
@@ -1,29 +1,29 @@
1
1
  import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
2
2
  import {
3
3
  imessage
4
- } from "../chunk-W5HNZ7YT.js";
4
+ } from "../chunk-DMT6BFJV.js";
5
5
  import "../chunk-ZR3TKZMT.js";
6
6
  import {
7
7
  slack
8
- } from "../chunk-VEF6FUE7.js";
8
+ } from "../chunk-WXLQNANA.js";
9
9
  import {
10
10
  telegram
11
- } from "../chunk-57NECZQZ.js";
11
+ } from "../chunk-U3QQ56YZ.js";
12
12
  import "../chunk-34FQGGD7.js";
13
13
  import "../chunk-LZXPLXZF.js";
14
14
  import {
15
15
  terminal
16
- } from "../chunk-PV4AVMNN.js";
16
+ } from "../chunk-IM5ADDZS.js";
17
17
  import "../chunk-FAIFTUV2.js";
18
18
  import {
19
19
  whatsappBusiness
20
- } from "../chunk-5VCWWPFW.js";
20
+ } from "../chunk-3KWFP4L2.js";
21
21
  import "../chunk-2D27WW5B.js";
22
22
  import "../chunk-3GEJYGZK.js";
23
23
  import "../chunk-A37PM5N2.js";
24
24
  import "../chunk-5XEFJBN2.js";
25
25
  import "../chunk-6UZFVXQF.js";
26
- import "../chunk-OGTHPDG7.js";
26
+ import "../chunk-B52VPQO3.js";
27
27
  import "../chunk-UXAKIXVM.js";
28
28
  export {
29
29
  imessage,
@@ -1,4 +1,4 @@
1
- import { S as SchemaMessage, P as Platform, a as PlatformDef } from '../../types-Be0T6E0e.js';
1
+ import { a as SchemaMessage, P as Platform, b as PlatformDef } from '../../types-CyfLJXgu.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,10 +1,10 @@
1
1
  import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
2
2
  import {
3
3
  slack
4
- } from "../../chunk-VEF6FUE7.js";
4
+ } from "../../chunk-WXLQNANA.js";
5
5
  import "../../chunk-3GEJYGZK.js";
6
6
  import "../../chunk-5XEFJBN2.js";
7
- import "../../chunk-OGTHPDG7.js";
7
+ import "../../chunk-B52VPQO3.js";
8
8
  import "../../chunk-UXAKIXVM.js";
9
9
  export {
10
10
  slack
@@ -1,9 +1,9 @@
1
- import { P as Platform, a as PlatformDef, g as ProviderMessage } from '../../types-Be0T6E0e.js';
1
+ import { P as Platform, b as PlatformDef, g as ProviderMessage } from '../../types-CyfLJXgu.js';
2
2
  import * as _photon_ai_telegram_ts from '@photon-ai/telegram-ts';
3
3
  import * as zod_v4_core from 'zod/v4/core';
4
4
  import * as z from 'zod';
5
5
  import z__default from 'zod';
6
- import { F as FusorClient } from '../../types-CDYXH2R7.js';
6
+ import { F as FusorClient } from '../../types-BIta6Kxi.js';
7
7
  import 'hotscript';
8
8
 
9
9
  interface TelegramSpace {
@@ -1,12 +1,12 @@
1
1
  import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
2
2
  import {
3
3
  telegram
4
- } from "../../chunk-57NECZQZ.js";
4
+ } from "../../chunk-U3QQ56YZ.js";
5
5
  import "../../chunk-34FQGGD7.js";
6
6
  import "../../chunk-LZXPLXZF.js";
7
7
  import "../../chunk-FAIFTUV2.js";
8
8
  import "../../chunk-6UZFVXQF.js";
9
- import "../../chunk-OGTHPDG7.js";
9
+ import "../../chunk-B52VPQO3.js";
10
10
  import "../../chunk-UXAKIXVM.js";
11
11
  export {
12
12
  telegram
@@ -1,4 +1,4 @@
1
- import { P as Platform, a as PlatformDef, f as contentSchema } from '../../types-Be0T6E0e.js';
1
+ import { P as Platform, b as PlatformDef, f as contentSchema } from '../../types-CyfLJXgu.js';
2
2
  import { ChildProcess } from 'node:child_process';
3
3
  import z__default from 'zod';
4
4
  import { Socket } from 'node:net';
@@ -1,12 +1,12 @@
1
1
  import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
2
2
  import {
3
3
  terminal
4
- } from "../../chunk-PV4AVMNN.js";
4
+ } from "../../chunk-IM5ADDZS.js";
5
5
  import "../../chunk-FAIFTUV2.js";
6
6
  import "../../chunk-A37PM5N2.js";
7
7
  import "../../chunk-5XEFJBN2.js";
8
8
  import "../../chunk-6UZFVXQF.js";
9
- import "../../chunk-OGTHPDG7.js";
9
+ import "../../chunk-B52VPQO3.js";
10
10
  import "../../chunk-UXAKIXVM.js";
11
11
  export {
12
12
  terminal
@@ -1,4 +1,4 @@
1
- import { S as SchemaMessage, P as Platform, a as PlatformDef } from '../../types-Be0T6E0e.js';
1
+ import { a as SchemaMessage, P as Platform, b as PlatformDef } from '../../types-CyfLJXgu.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,13 +1,13 @@
1
1
  import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
2
2
  import {
3
3
  whatsappBusiness
4
- } from "../../chunk-5VCWWPFW.js";
4
+ } from "../../chunk-3KWFP4L2.js";
5
5
  import "../../chunk-2D27WW5B.js";
6
6
  import "../../chunk-3GEJYGZK.js";
7
7
  import "../../chunk-A37PM5N2.js";
8
8
  import "../../chunk-5XEFJBN2.js";
9
9
  import "../../chunk-6UZFVXQF.js";
10
- import "../../chunk-OGTHPDG7.js";
10
+ import "../../chunk-B52VPQO3.js";
11
11
  import "../../chunk-UXAKIXVM.js";
12
12
  export {
13
13
  whatsappBusiness
@@ -0,0 +1,53 @@
1
+ import z__default from 'zod';
2
+ import { M as Message, U as User, S as Space, C as ContentBuilder } from './types-CyfLJXgu.js';
3
+
4
+ /**
5
+ * Shared building blocks for photo-style content (chat background, group
6
+ * avatar/icon, …) whose builders all share the same `set | clear` shape and
7
+ * the same `"clear"` reserved-string sentinel.
8
+ *
9
+ * Keeping the action schema and `buildPhotoAction` factory here means both
10
+ * `background()` and `avatar()` parse against the same structural definition
11
+ * and any DX fix (mime inference, read caching, sentinel docs) lands once.
12
+ */
13
+ declare const CLEAR_SENTINEL: "clear";
14
+ type PhotoInput = typeof CLEAR_SENTINEL | string | Buffer | URL;
15
+
16
+ /**
17
+ * A `read` marks the conversation as read **up to** `target`, surfacing a
18
+ * read receipt to the sender where the platform supports one.
19
+ *
20
+ * `space.send(read(message))` is the canonical outbound API;
21
+ * `message.read()` and `space.read(message)` are sugar that delegate here.
22
+ * Reads are fire-and-forget — providers handle them inside their `send`
23
+ * action and the resolved value is `undefined`.
24
+ *
25
+ * Granularity is per-platform:
26
+ *
27
+ * - WhatsApp Business: per-message receipt via `markRead(target.id)`, which
28
+ * also marks every earlier message in the conversation as read.
29
+ * - iMessage (remote): chat-level `chats.markRead(chatGuid)` — `target` only
30
+ * identifies the chat, and **every** unread message in it is marked read.
31
+ * Local mode rejects with `UnsupportedError` (warned and skipped).
32
+ * - Telegram / Slack: silently no-op. Neither surfaces read state for bot
33
+ * conversations (Telegram bot chats are effectively auto-read), so the
34
+ * signal is vacuously satisfied — same best-effort contract as `typing`.
35
+ */
36
+ declare const readSchema: z__default.ZodObject<{
37
+ type: z__default.ZodLiteral<"read">;
38
+ target: z__default.ZodCustom<Message<string, User, Space<unknown>>, Message<string, User, Space<unknown>>>;
39
+ }, z__default.core.$strip>;
40
+ type Read = z__default.infer<typeof readSchema>;
41
+ /**
42
+ * Construct a `read` content value marking the conversation read up to
43
+ * `target`.
44
+ *
45
+ * Only inbound messages (those received from a user) can be marked read;
46
+ * calling this with an outbound target throws at build time so the misuse
47
+ * surfaces before the send pipeline runs. The target is required (not
48
+ * `Message | undefined` like `unsend`): read targets come from the inbound
49
+ * stream, never from a chainable `send()` result.
50
+ */
51
+ declare function read(target: Message): ContentBuilder;
52
+
53
+ export { type PhotoInput as P, type Read as R, read as r };
@@ -1,4 +1,4 @@
1
- import { b as ProjectData, c as Store, d as ProviderMessageRecord, e as Space, M as Message } from './types-Be0T6E0e.js';
1
+ import { c as ProjectData, d as Store, e as ProviderMessageRecord, S as Space, M as Message } from './types-CyfLJXgu.js';
2
2
 
3
3
  declare const FUSOR_EVENT_BRAND: unique symbol;
4
4
  interface FusorEvent<TName extends string = string, TData = unknown> {
@@ -741,6 +741,9 @@ declare const contentSchema: z__default.ZodDiscriminatedUnion<[z__default.ZodObj
741
741
  }, z__default.core.$strip>, z__default.ZodObject<{
742
742
  type: z__default.ZodLiteral<"unsend">;
743
743
  target: z__default.ZodCustom<Message<string, User, Space<unknown>>, Message<string, User, Space<unknown>>>;
744
+ }, z__default.core.$strip>, z__default.ZodObject<{
745
+ type: z__default.ZodLiteral<"read">;
746
+ target: z__default.ZodCustom<Message<string, User, Space<unknown>>, Message<string, User, Space<unknown>>>;
744
747
  }, z__default.core.$strip>], "type">;
745
748
  type Content = z__default.infer<typeof contentSchema>;
746
749
  interface ContentBuilder {
@@ -832,6 +835,19 @@ interface Space<_Def = unknown> {
832
835
  */
833
836
  getMessage(id: string): Promise<Message | undefined>;
834
837
  readonly id: string;
838
+ /**
839
+ * Mark the conversation as read up to `message`, surfacing a read receipt
840
+ * to the sender where the platform supports one. Sugar for
841
+ * `send(read(message))`. Fire-and-forget; only inbound messages can be
842
+ * marked read.
843
+ *
844
+ * Granularity is per-platform: WhatsApp Business issues a receipt for
845
+ * `message` and everything before it; iMessage (remote) marks the whole
846
+ * chat read. Platforms with no read-receipt concept for bot conversations
847
+ * (Telegram, Slack) silently no-op, so the signal is best-effort
848
+ * everywhere — same contract as `startTyping()`.
849
+ */
850
+ read(message: Message): Promise<void>;
835
851
  /**
836
852
  * Rename the current chat. Sugar for `send(rename(displayName))`.
837
853
  *
@@ -882,6 +898,15 @@ interface Message<TPlatform extends string = string, TSender extends User = User
882
898
  react(reaction: string): Promise<(Message<TPlatform, AgentSender, TSpace> & {
883
899
  content: Reaction;
884
900
  }) | undefined>;
901
+ /**
902
+ * Mark this message (and everything before it in the conversation) as
903
+ * read. Sugar for `space.send(read(this))`. Reads are fire-and-forget;
904
+ * per-platform granularity and support (e.g. iMessage marks the whole
905
+ * chat; Telegram/Slack silently no-op) surface from the provider's send
906
+ * action. Only inbound messages can be marked read; calling this on an
907
+ * outbound message throws.
908
+ */
909
+ read(): Promise<void>;
885
910
  reply(content: ContentInput): Promise<Message<TPlatform, AgentSender, TSpace> | undefined>;
886
911
  reply(...content: [ContentInput, ContentInput, ...ContentInput[]]): Promise<Message<TPlatform, AgentSender, TSpace>[]>;
887
912
  sender: TSender | undefined;
@@ -1502,4 +1527,4 @@ interface Platform<Def extends AnyPlatformDef> {
1502
1527
  (message: Message): PlatformMessage<Def>;
1503
1528
  }
1504
1529
 
1505
- export { asReaction as $, 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 ProjectProfile as G, type ReactionBuilder as H, type InstanceActionFn as I, type SharedTokenData as J, type SlackTeamMeta as K, type SlackTokenData as L, type Message as M, type SpaceNamespace as N, SpectrumCloudError as O, type Platform as P, type SubscriptionData as Q, type Reaction as R, type SchemaMessage as S, type SubscriptionStatus as T, type User as U, type TokenData as V, broadcast as W, cloud as X, mergeStreams as Y, reaction as Z, stream as _, type PlatformDef as a, type ProjectData as b, type Store as c, type ProviderMessageRecord as d, type Space as e, contentSchema as f, type ProviderMessage as g, type ContentInput as h, type Content as i, type SpaceActionFn as j, type MessageActionFn as k, type CreateClientContext as l, type PlatformProviderConfig as m, type SpectrumLike as n, type CustomEventStreams as o, type AnyPlatformDef as p, type CloudPlatform as q, type ImessageInfoData as r, type ManagedStream as s, type PlatformInstance as t, type PlatformMessage as u, type PlatformRuntime as v, type PlatformSpace as w, type PlatformStatus as x, type PlatformUser as y, type PlatformsData as z };
1530
+ export { asReaction as $, 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 ProjectProfile as G, type ReactionBuilder as H, type InstanceActionFn as I, type SharedTokenData as J, type SlackTeamMeta as K, type SlackTokenData as L, type Message as M, type SpaceNamespace as N, SpectrumCloudError as O, type Platform as P, type SubscriptionData as Q, type Reaction as R, type Space as S, type SubscriptionStatus as T, type User as U, type TokenData as V, broadcast as W, cloud as X, mergeStreams as Y, reaction as Z, stream as _, type SchemaMessage as a, type PlatformDef as b, type ProjectData as c, type Store as d, type ProviderMessageRecord as e, contentSchema as f, type ProviderMessage as g, type ContentInput as h, type Content as i, type SpaceActionFn as j, type MessageActionFn as k, type CreateClientContext as l, type PlatformProviderConfig as m, type SpectrumLike as n, type CustomEventStreams as o, type AnyPlatformDef as p, type CloudPlatform as q, type ImessageInfoData as r, type ManagedStream as s, type PlatformInstance as t, type PlatformMessage as u, type PlatformRuntime as v, type PlatformSpace as w, type PlatformStatus as x, type PlatformUser as y, type PlatformsData as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spectrum-ts",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "description": "Bring agents to any interface — unified messaging SDK for TypeScript.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,13 +0,0 @@
1
- /**
2
- * Shared building blocks for photo-style content (chat background, group
3
- * avatar/icon, …) whose builders all share the same `set | clear` shape and
4
- * the same `"clear"` reserved-string sentinel.
5
- *
6
- * Keeping the action schema and `buildPhotoAction` factory here means both
7
- * `background()` and `avatar()` parse against the same structural definition
8
- * and any DX fix (mime inference, read caching, sentinel docs) lands once.
9
- */
10
- declare const CLEAR_SENTINEL: "clear";
11
- type PhotoInput = typeof CLEAR_SENTINEL | string | Buffer | URL;
12
-
13
- export type { PhotoInput as P };