spectrum-ts 0.2.2 → 0.3.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,3 +1,16 @@
1
+ // src/content/custom.ts
2
+ import z from "zod";
3
+ var customSchema = z.object({
4
+ type: z.literal("custom"),
5
+ raw: z.unknown()
6
+ });
7
+ var asCustom = (raw) => customSchema.parse({ type: "custom", raw });
8
+ function custom(raw) {
9
+ return {
10
+ build: async () => asCustom(raw)
11
+ };
12
+ }
13
+
1
14
  // src/utils/stream.ts
2
15
  import { Repeater } from "@repeaterjs/repeater";
3
16
  function stream(setup) {
@@ -53,6 +66,8 @@ function mergeStreams(streams) {
53
66
  }
54
67
 
55
68
  export {
69
+ asCustom,
70
+ custom,
56
71
  stream,
57
72
  mergeStreams
58
73
  };
@@ -1,3 +1,21 @@
1
+ // src/content/text.ts
2
+ import z from "zod";
3
+ var textSchema = z.object({
4
+ type: z.literal("text"),
5
+ text: z.string().nonempty()
6
+ });
7
+ var asText = (text2) => textSchema.parse({ type: "text", text: text2 });
8
+ function text(text2) {
9
+ return {
10
+ build: async () => asText(text2)
11
+ };
12
+ }
13
+
14
+ // src/content/resolve.ts
15
+ var resolveContents = (items) => Promise.all(
16
+ items.map((c) => typeof c === "string" ? text(c).build() : c.build())
17
+ );
18
+
1
19
  // src/platform/define.ts
2
20
  function createPlatformInstance(def, runtime) {
3
21
  const isPlatformUser = (value) => {
@@ -69,11 +87,13 @@ function createPlatformInstance(def, runtime) {
69
87
  ...parsedSpace,
70
88
  ...spaceRef,
71
89
  send: async (...content) => {
72
- const built = await Promise.all(content.map((c) => c.build()));
73
- await def.actions.send({
74
- ...typingCtx,
75
- content: built
76
- });
90
+ const built = await resolveContents(content);
91
+ for (const item of built) {
92
+ await def.actions.send({
93
+ ...typingCtx,
94
+ content: item
95
+ });
96
+ }
77
97
  },
78
98
  startTyping: async () => {
79
99
  await def.actions.startTyping?.(typingCtx);
@@ -172,5 +192,8 @@ function definePlatform(name, def) {
172
192
  }
173
193
 
174
194
  export {
195
+ asText,
196
+ text,
197
+ resolveContents,
175
198
  definePlatform
176
199
  };
@@ -0,0 +1,44 @@
1
+ // src/content/attachment.ts
2
+ import { readFile } from "fs/promises";
3
+ import { basename } from "path";
4
+ import { lookup as lookupMimeType } from "mime-types";
5
+ import z from "zod";
6
+ var DEFAULT_ATTACHMENT_NAME = "attachment";
7
+ var attachmentSchema = z.object({
8
+ type: z.literal("attachment"),
9
+ data: z.instanceof(Buffer),
10
+ mimeType: z.string().nonempty(),
11
+ name: z.string().nonempty()
12
+ });
13
+ var resolveAttachmentName = (input, name) => name || (typeof input === "string" ? basename(input) : DEFAULT_ATTACHMENT_NAME);
14
+ var resolveAttachmentMimeType = (name, mimeType) => {
15
+ if (mimeType) {
16
+ return mimeType;
17
+ }
18
+ const resolvedMimeType = lookupMimeType(name);
19
+ if (!resolvedMimeType) {
20
+ throw new Error(
21
+ `Unable to resolve MIME type for attachment "${name}". Pass options.mimeType explicitly.`
22
+ );
23
+ }
24
+ return resolvedMimeType;
25
+ };
26
+ var asAttachment = (input) => attachmentSchema.parse({ type: "attachment", ...input });
27
+ function attachment(input, options) {
28
+ return {
29
+ build: async () => {
30
+ const data = typeof input === "string" ? await readFile(input) : input;
31
+ const name = resolveAttachmentName(input, options?.name);
32
+ return asAttachment({
33
+ data,
34
+ mimeType: resolveAttachmentMimeType(name, options?.mimeType),
35
+ name
36
+ });
37
+ }
38
+ };
39
+ }
40
+
41
+ export {
42
+ asAttachment,
43
+ attachment
44
+ };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,20 @@
1
+ import { C as ContentBuilder, a as ContentInput, b as Content, P as ProviderMessage, c as PlatformDef, d as Platform, e as PlatformProviderConfig, S as SpectrumLike, f as CustomEventStreams, g as Space, M as Message } from './types-DuE2hXuJ.js';
2
+ export { A as AnyPlatformDef, E as EventProducer, h as PlatformInstance, i as PlatformMessage, j as PlatformSpace, k as PlatformUser, l as SchemaMessage, U as User } from './types-DuE2hXuJ.js';
1
3
  import z__default from 'zod';
2
- import { P as ProviderMessage, a as PlatformDef, b as Platform, c as PlatformProviderConfig, S as SpectrumLike, C as CustomEventStreams, d as Space, M as Message, e as ContentBuilder } from './types-DPrSH21Q.js';
3
- export { A as AnyPlatformDef, f as Content, E as EventProducer, g as PlatformInstance, h as PlatformMessage, i as PlatformSpace, j as PlatformUser, k as SchemaMessage, U as User, l as attachment, m as custom, t as text } from './types-DPrSH21Q.js';
4
4
  export { M as ManagedStream, m as mergeStreams, s as stream } from './stream-DGy4geUK.js';
5
5
  import 'hotscript';
6
6
 
7
+ declare function attachment(input: string | Buffer, options?: {
8
+ mimeType?: string;
9
+ name?: string;
10
+ }): ContentBuilder;
11
+
12
+ declare function custom(raw: unknown): ContentBuilder;
13
+
14
+ declare const resolveContents: (items: readonly ContentInput[]) => Promise<Content[]>;
15
+
16
+ declare function text(text: string): ContentBuilder;
17
+
7
18
  declare function definePlatform<_Name extends string, _ConfigSchema extends z__default.ZodType<object>, _UserSchema extends z__default.ZodType<object> | undefined, _SpaceSchema extends z__default.ZodType<object> | undefined, _SpaceParamsSchema extends z__default.ZodType<object> | undefined, _Client, _ResolvedUser extends {
8
19
  id: string;
9
20
  }, _ResolvedSpace extends {
@@ -25,7 +36,7 @@ declare function definePlatform<_Name extends string, _ConfigSchema extends z__d
25
36
  type SpectrumInstance<Providers extends PlatformProviderConfig[] = PlatformProviderConfig[]> = SpectrumLike<Providers> & CustomEventStreams<Providers> & {
26
37
  readonly messages: AsyncIterable<[Space, Message]>;
27
38
  stop(): Promise<void>;
28
- send(space: Space, ...content: [ContentBuilder, ...ContentBuilder[]]): Promise<void>;
39
+ send(space: Space, ...content: [ContentInput, ...ContentInput[]]): Promise<void>;
29
40
  responding<T>(space: Space, fn: () => T | Promise<T>): Promise<T>;
30
41
  };
31
42
  declare function Spectrum<const Providers extends PlatformProviderConfig[]>(options: {
@@ -75,4 +86,4 @@ declare const cloud: {
75
86
  togglePlatform: (projectId: string, projectSecret: string, platform: CloudPlatform, enabled: boolean) => Promise<PlatformsData>;
76
87
  };
77
88
 
78
- export { type CloudPlatform, ContentBuilder, type DedicatedTokenData, type ImessageInfoData, Message, Platform, PlatformDef, PlatformProviderConfig, type PlatformStatus, type PlatformsData, type SharedTokenData, Space, Spectrum, SpectrumCloudError, type SpectrumInstance, type SubscriptionData, type SubscriptionStatus, type TokenData, cloud, definePlatform };
89
+ export { type CloudPlatform, Content, ContentBuilder, ContentInput, type DedicatedTokenData, type ImessageInfoData, Message, Platform, PlatformDef, PlatformProviderConfig, type PlatformStatus, type PlatformsData, type SharedTokenData, Space, Spectrum, SpectrumCloudError, type SpectrumInstance, type SubscriptionData, type SubscriptionStatus, type TokenData, attachment, cloud, custom, definePlatform, resolveContents, text };
package/dist/index.js CHANGED
@@ -3,12 +3,18 @@ import {
3
3
  cloud
4
4
  } from "./chunk-HXM64ENV.js";
5
5
  import {
6
+ attachment
7
+ } from "./chunk-ZRSCHSLZ.js";
8
+ import {
9
+ custom,
6
10
  mergeStreams,
7
11
  stream
8
- } from "./chunk-3TBRO2J7.js";
12
+ } from "./chunk-V2PK557T.js";
9
13
  import {
10
- definePlatform
11
- } from "./chunk-LIRM7SBA.js";
14
+ definePlatform,
15
+ resolveContents,
16
+ text
17
+ } from "./chunk-XEEDIGVK.js";
12
18
 
13
19
  // src/spectrum.ts
14
20
  import z from "zod";
@@ -93,11 +99,13 @@ async function Spectrum(options) {
93
99
  const space = {
94
100
  ...spaceRef,
95
101
  send: async (...content) => {
96
- const resolved = await Promise.all(content.map((c) => c.build()));
97
- await definition.actions.send({
98
- ...typingCtx,
99
- content: resolved
100
- });
102
+ const resolved = await resolveContents(content);
103
+ for (const item of resolved) {
104
+ await definition.actions.send({
105
+ ...typingCtx,
106
+ content: item
107
+ });
108
+ }
101
109
  },
102
110
  startTyping: async () => {
103
111
  await definition.actions.startTyping?.(typingCtx);
@@ -136,14 +144,16 @@ async function Spectrum(options) {
136
144
  if (!definition.actions.replyToMessage) {
137
145
  return;
138
146
  }
139
- const resolved = await Promise.all(content.map((c) => c.build()));
140
- await definition.actions.replyToMessage({
141
- space: spaceRef,
142
- messageId: msg.id,
143
- content: resolved,
144
- client,
145
- config
146
- });
147
+ const resolved = await resolveContents(content);
148
+ for (const item of resolved) {
149
+ await definition.actions.replyToMessage({
150
+ space: spaceRef,
151
+ messageId: msg.id,
152
+ content: item,
153
+ client,
154
+ config
155
+ });
156
+ }
147
157
  },
148
158
  sender: {
149
159
  ...msg.sender,
@@ -281,66 +291,6 @@ async function Spectrum(options) {
281
291
  }
282
292
  });
283
293
  }
284
-
285
- // src/types/content.ts
286
- import { readFile } from "fs/promises";
287
- import { basename } from "path";
288
- import { lookup as lookupMimeType } from "mime-types";
289
- import z2 from "zod";
290
- var DEFAULT_ATTACHMENT_NAME = "attachment";
291
- var contentSchema = z2.discriminatedUnion("type", [
292
- z2.object({
293
- type: z2.literal("plain_text"),
294
- text: z2.string().nonempty()
295
- }),
296
- z2.object({
297
- type: z2.literal("custom"),
298
- raw: z2.json()
299
- }),
300
- z2.object({
301
- type: z2.literal("attachment"),
302
- data: z2.instanceof(Buffer),
303
- mimeType: z2.string().nonempty(),
304
- name: z2.string().nonempty()
305
- })
306
- ]);
307
- function text(text2) {
308
- return {
309
- build: () => Promise.resolve({ type: "plain_text", text: text2 })
310
- };
311
- }
312
- function custom(raw) {
313
- return {
314
- build: () => Promise.resolve({ type: "custom", raw })
315
- };
316
- }
317
- var resolveAttachmentName = (input, name) => name || (typeof input === "string" ? basename(input) : DEFAULT_ATTACHMENT_NAME);
318
- var resolveAttachmentMimeType = (name, mimeType) => {
319
- if (mimeType) {
320
- return mimeType;
321
- }
322
- const resolvedMimeType = lookupMimeType(name);
323
- if (!resolvedMimeType) {
324
- throw new Error(
325
- `Unable to resolve MIME type for attachment "${name}". Pass options.mimeType explicitly.`
326
- );
327
- }
328
- return resolvedMimeType;
329
- };
330
- function attachment(input, options) {
331
- return {
332
- build: async () => {
333
- const data = typeof input === "string" ? await readFile(input) : input;
334
- const name = resolveAttachmentName(input, options?.name);
335
- return {
336
- data,
337
- mimeType: resolveAttachmentMimeType(name, options?.mimeType),
338
- name,
339
- type: "attachment"
340
- };
341
- }
342
- };
343
- }
344
294
  export {
345
295
  Spectrum,
346
296
  SpectrumCloudError,
@@ -349,6 +299,7 @@ export {
349
299
  custom,
350
300
  definePlatform,
351
301
  mergeStreams,
302
+ resolveContents,
352
303
  stream,
353
304
  text
354
305
  };
@@ -3,7 +3,7 @@ import { AdvancedIMessage } from '@photon-ai/advanced-imessage';
3
3
  import { IMessageSDK } from '@photon-ai/imessage-kit';
4
4
  import * as z from 'zod';
5
5
  import z__default from 'zod';
6
- import { k as SchemaMessage, b as Platform, a as PlatformDef, P as ProviderMessage } from '../../types-DPrSH21Q.js';
6
+ import { l as SchemaMessage, d as Platform, c as PlatformDef, P as ProviderMessage } from '../../types-DuE2hXuJ.js';
7
7
  import * as zod_v4_core from 'zod/v4/core';
8
8
  import 'hotscript';
9
9
 
@@ -2,12 +2,14 @@ import {
2
2
  cloud
3
3
  } from "../../chunk-HXM64ENV.js";
4
4
  import {
5
+ asCustom,
5
6
  mergeStreams,
6
7
  stream
7
- } from "../../chunk-3TBRO2J7.js";
8
+ } from "../../chunk-V2PK557T.js";
8
9
  import {
10
+ asText,
9
11
  definePlatform
10
- } from "../../chunk-LIRM7SBA.js";
12
+ } from "../../chunk-XEEDIGVK.js";
11
13
 
12
14
  // src/providers/imessage/index.ts
13
15
  import { createClient as createClient2, directChat } from "@photon-ai/advanced-imessage";
@@ -104,15 +106,15 @@ import { unlink, writeFile } from "fs/promises";
104
106
  import { tmpdir } from "os";
105
107
  import { join } from "path";
106
108
  var toSpace = (message) => ({
107
- id: `${message.isGroupChat ? "any;+;" : "any;-;"}${message.chatId}`,
108
- type: message.isGroupChat ? "group" : "dm"
109
+ id: message.chatId,
110
+ type: message.chatKind === "group" ? "group" : "dm"
109
111
  });
110
112
  var toMessage = (message) => ({
111
- id: message.guid,
112
- content: [{ type: "plain_text", text: message.text ?? "" }],
113
- sender: { id: message.sender ?? "" },
113
+ id: message.id,
114
+ content: { type: "text", text: message.text ?? "" },
115
+ sender: { id: message.participant ?? "" },
114
116
  space: toSpace(message),
115
- timestamp: message.date ?? /* @__PURE__ */ new Date()
117
+ timestamp: message.createdAt
116
118
  });
117
119
  var messages = (client) => stream((emit) => {
118
120
  client.startWatching({
@@ -122,14 +124,14 @@ var messages = (client) => stream((emit) => {
122
124
  });
123
125
  var send = async (client, spaceId, content) => {
124
126
  switch (content.type) {
125
- case "plain_text":
127
+ case "text":
126
128
  await client.send(spaceId, content.text);
127
129
  break;
128
130
  case "attachment": {
129
131
  const tmp = join(tmpdir(), `spectrum-${Date.now()}-${content.name}`);
130
132
  await writeFile(tmp, content.data);
131
133
  try {
132
- await client.send(spaceId, { files: [tmp] });
134
+ await client.send(spaceId, { attachments: [tmp] });
133
135
  } finally {
134
136
  await unlink(tmp).catch(() => {
135
137
  });
@@ -150,16 +152,19 @@ import {
150
152
  var TAPBACK_NAMES = new Set(
151
153
  Object.values(Reaction).filter((r) => r !== "emoji" && r !== "sticker")
152
154
  );
153
- var toMessage2 = (event) => ({
154
- id: event.message.guid,
155
- content: [{ type: "plain_text", text: event.message.text ?? "" }],
156
- sender: { id: event.message.sender?.address ?? "" },
157
- space: {
158
- id: event.chatGuid,
159
- type: event.chatGuid.includes(";+;") ? "group" : "dm"
160
- },
161
- timestamp: event.timestamp
162
- });
155
+ var toMessage2 = (event) => {
156
+ const text = event.message.text;
157
+ return {
158
+ id: event.message.guid,
159
+ content: text ? asText(text) : asCustom(event.message),
160
+ sender: { id: event.message.sender?.address ?? "" },
161
+ space: {
162
+ id: event.chatGuid,
163
+ type: event.chatGuid.includes(";+;") ? "group" : "dm"
164
+ },
165
+ timestamp: event.timestamp
166
+ };
167
+ };
163
168
  var clientStream = (client) => {
164
169
  const sub = client.messages.subscribe("message.received");
165
170
  return stream((emit, end) => {
@@ -197,7 +202,7 @@ var send2 = async (clients, spaceId, content) => {
197
202
  return;
198
203
  }
199
204
  switch (content.type) {
200
- case "plain_text":
205
+ case "text":
201
206
  await remote.messages.send(chatGuid(spaceId), content.text);
202
207
  break;
203
208
  case "attachment": {
@@ -212,7 +217,7 @@ var send2 = async (clients, spaceId, content) => {
212
217
  break;
213
218
  }
214
219
  default:
215
- break;
220
+ throw new Error(`Unsupported iMessage content type: ${content.type}`);
216
221
  }
217
222
  };
218
223
  var replyToMessage = async (clients, spaceId, msgId, content) => {
@@ -223,7 +228,7 @@ var replyToMessage = async (clients, spaceId, msgId, content) => {
223
228
  const chat = chatGuid(spaceId);
224
229
  const replyTo = messageGuid(msgId);
225
230
  switch (content.type) {
226
- case "plain_text":
231
+ case "text":
227
232
  await remote.messages.send(chat, content.text, { replyTo });
228
233
  break;
229
234
  case "attachment": {
@@ -239,7 +244,7 @@ var replyToMessage = async (clients, spaceId, msgId, content) => {
239
244
  break;
240
245
  }
241
246
  default:
242
- break;
247
+ throw new Error(`Unsupported iMessage content type: ${content.type}`);
243
248
  }
244
249
  };
245
250
  var reactToMessage = async (clients, spaceId, msgId, reaction) => {
@@ -352,12 +357,10 @@ var imessage = definePlatform("iMessage", {
352
357
  },
353
358
  actions: {
354
359
  send: async ({ space, content, client }) => {
355
- for (const item of content) {
356
- if (isLocal(client)) {
357
- await send(client, space.id, item);
358
- } else {
359
- await send2(client, space.id, item);
360
- }
360
+ if (isLocal(client)) {
361
+ await send(client, space.id, content);
362
+ } else {
363
+ await send2(client, space.id, content);
361
364
  }
362
365
  },
363
366
  startTyping: async ({ space, client }) => {
@@ -382,9 +385,7 @@ var imessage = definePlatform("iMessage", {
382
385
  if (isLocal(client)) {
383
386
  return;
384
387
  }
385
- for (const item of content) {
386
- await replyToMessage(client, space.id, messageId, item);
387
- }
388
+ await replyToMessage(client, space.id, messageId, content);
388
389
  }
389
390
  }
390
391
  });
@@ -1,4 +1,4 @@
1
- import { b as Platform, a as PlatformDef, P as ProviderMessage } from '../../types-DPrSH21Q.js';
1
+ import { d as Platform, c as PlatformDef, P as ProviderMessage } from '../../types-DuE2hXuJ.js';
2
2
  import * as node_readline from 'node:readline';
3
3
  import z__default from 'zod';
4
4
  import 'hotscript';
@@ -18,9 +18,9 @@ declare const terminal: Platform<PlatformDef<"terminal", z__default.ZodObject<{}
18
18
  }): AsyncGenerator<{
19
19
  id: `${string}-${string}-${string}-${string}-${string}`;
20
20
  content: {
21
- type: "plain_text";
21
+ type: "text";
22
22
  text: string;
23
- }[];
23
+ };
24
24
  sender: {
25
25
  id: string;
26
26
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  definePlatform
3
- } from "../../chunk-LIRM7SBA.js";
3
+ } from "../../chunk-XEEDIGVK.js";
4
4
 
5
5
  // src/providers/terminal/index.ts
6
6
  import { createInterface } from "readline";
@@ -39,7 +39,7 @@ var terminal = definePlatform("terminal", {
39
39
  for await (const line of client) {
40
40
  yield {
41
41
  id: crypto.randomUUID(),
42
- content: [{ type: "plain_text", text: line }],
42
+ content: { type: "text", text: line },
43
43
  sender: { id: "terminal-user" },
44
44
  space: { id: "terminal" },
45
45
  timestamp: /* @__PURE__ */ new Date()
@@ -49,9 +49,8 @@ var terminal = definePlatform("terminal", {
49
49
  },
50
50
  actions: {
51
51
  send: async ({ content }) => {
52
- const outputs = content.filter((c) => c.type === "plain_text").map((c) => c.text);
53
- for (const output of outputs) {
54
- console.log(output);
52
+ if (content.type === "text") {
53
+ console.log(content.text);
55
54
  }
56
55
  }
57
56
  }
@@ -1,7 +1,7 @@
1
1
  import { M as ManagedStream } from '../../stream-DGy4geUK.js';
2
2
  import * as z from 'zod';
3
3
  import z__default from 'zod';
4
- import { k as SchemaMessage, b as Platform, a as PlatformDef, P as ProviderMessage } from '../../types-DPrSH21Q.js';
4
+ import { l as SchemaMessage, d as Platform, c as PlatformDef, P as ProviderMessage } from '../../types-DuE2hXuJ.js';
5
5
  import * as zod_v4_core from 'zod/v4/core';
6
6
  import { WhatsAppClient } from '@photon-ai/whatsapp-business';
7
7
  import 'hotscript';