spectrum-ts 0.4.0 → 0.6.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.
package/dist/index.js CHANGED
@@ -4,18 +4,133 @@ import {
4
4
  } from "./chunk-HXM64ENV.js";
5
5
  import {
6
6
  attachment,
7
+ bufferToStream,
8
+ contact,
7
9
  custom,
10
+ fromVCard,
8
11
  mergeStreams,
9
- stream
10
- } from "./chunk-5XW4CAWS.js";
12
+ readSchema,
13
+ stream,
14
+ streamSchema,
15
+ toVCard
16
+ } from "./chunk-UZWRB3FZ.js";
11
17
  import {
18
+ buildMessage,
19
+ buildSpace,
12
20
  definePlatform,
13
21
  resolveContents,
14
22
  text
15
- } from "./chunk-XEEDIGVK.js";
23
+ } from "./chunk-XZTTLPHE.js";
16
24
 
17
- // src/spectrum.ts
25
+ // src/content/voice.ts
26
+ import { createReadStream } from "fs";
27
+ import { readFile, stat } from "fs/promises";
28
+ import { basename } from "path";
29
+ import { Readable } from "stream";
30
+ import { lookup as lookupMimeType } from "mime-types";
18
31
  import z from "zod";
32
+ var AUDIO_MIME_PATTERN = /^audio\//i;
33
+ var audioMimeSchema = z.string().nonempty().regex(AUDIO_MIME_PATTERN, "voice content requires an audio/* MIME type");
34
+ var voiceSchema = z.object({
35
+ type: z.literal("voice"),
36
+ name: z.string().nonempty().optional(),
37
+ mimeType: audioMimeSchema,
38
+ duration: z.number().nonnegative().optional(),
39
+ size: z.number().int().nonnegative().optional(),
40
+ read: readSchema,
41
+ stream: streamSchema
42
+ });
43
+ var resolveVoiceName = (input, name) => {
44
+ if (name) {
45
+ return name;
46
+ }
47
+ if (typeof input === "string") {
48
+ return basename(input);
49
+ }
50
+ return void 0;
51
+ };
52
+ var resolveVoiceMimeType = (name, mimeType) => {
53
+ if (mimeType) {
54
+ if (!AUDIO_MIME_PATTERN.test(mimeType)) {
55
+ throw new Error(
56
+ `voice content requires an audio/* MIME type, got "${mimeType}".`
57
+ );
58
+ }
59
+ return mimeType;
60
+ }
61
+ if (name) {
62
+ const resolved = lookupMimeType(name);
63
+ if (resolved && AUDIO_MIME_PATTERN.test(resolved)) {
64
+ return resolved;
65
+ }
66
+ if (resolved) {
67
+ throw new Error(
68
+ `Resolved non-audio MIME type "${resolved}" from name "${name}". Pass options.mimeType explicitly with an audio/* type.`
69
+ );
70
+ }
71
+ }
72
+ throw new Error(
73
+ "Unable to resolve MIME type for voice content. Pass options.mimeType explicitly."
74
+ );
75
+ };
76
+ var asVoice = (input) => {
77
+ let cached;
78
+ const read = () => {
79
+ cached ??= input.read().catch((err) => {
80
+ cached = void 0;
81
+ throw err;
82
+ });
83
+ return cached;
84
+ };
85
+ const stream2 = input.stream ?? (async () => bufferToStream(await read()));
86
+ return voiceSchema.parse({
87
+ type: "voice",
88
+ name: input.name,
89
+ mimeType: input.mimeType,
90
+ duration: input.duration,
91
+ size: input.size,
92
+ read,
93
+ stream: stream2
94
+ });
95
+ };
96
+ function voice(input, options) {
97
+ return {
98
+ build: async () => {
99
+ const name = resolveVoiceName(input, options?.name);
100
+ const mimeHint = typeof input === "string" ? basename(input) : name;
101
+ const mimeType = resolveVoiceMimeType(mimeHint, options?.mimeType);
102
+ if (typeof input === "string") {
103
+ const stats = await stat(input);
104
+ if (!stats.isFile()) {
105
+ throw new Error(
106
+ `voice content path "${input}" is not a regular file.`
107
+ );
108
+ }
109
+ return asVoice({
110
+ name,
111
+ mimeType,
112
+ duration: options?.duration,
113
+ size: stats.size,
114
+ read: () => readFile(input),
115
+ stream: async () => Readable.toWeb(
116
+ createReadStream(input)
117
+ )
118
+ });
119
+ }
120
+ return asVoice({
121
+ name,
122
+ mimeType,
123
+ duration: options?.duration,
124
+ size: input.byteLength,
125
+ read: async () => input,
126
+ stream: async () => bufferToStream(input)
127
+ });
128
+ }
129
+ };
130
+ }
131
+
132
+ // src/spectrum.ts
133
+ import z2 from "zod";
19
134
  var providerMessageCoreKeys = /* @__PURE__ */ new Set([
20
135
  "content",
21
136
  "id",
@@ -23,16 +138,16 @@ var providerMessageCoreKeys = /* @__PURE__ */ new Set([
23
138
  "space",
24
139
  "timestamp"
25
140
  ]);
26
- var spectrumConfigSchema = z.union([
27
- z.object({
28
- projectId: z.string().min(1),
29
- projectSecret: z.string().min(1),
30
- providers: z.array(z.custom())
141
+ var spectrumConfigSchema = z2.union([
142
+ z2.object({
143
+ projectId: z2.string().min(1),
144
+ projectSecret: z2.string().min(1),
145
+ providers: z2.array(z2.custom())
31
146
  }),
32
- z.object({
33
- projectId: z.undefined().optional(),
34
- projectSecret: z.undefined().optional(),
35
- providers: z.array(z.custom())
147
+ z2.object({
148
+ projectId: z2.undefined().optional(),
149
+ projectSecret: z2.undefined().optional(),
150
+ providers: z2.array(z2.custom())
36
151
  })
37
152
  ]);
38
153
  async function Spectrum(options) {
@@ -94,72 +209,27 @@ async function Spectrum(options) {
94
209
  __platform: definition.name
95
210
  };
96
211
  const typingCtx = { space: spaceRef, client, config };
97
- const space = {
98
- ...spaceRef,
99
- send: async (...content) => {
100
- const resolved = await resolveContents(content);
101
- for (const item of resolved) {
102
- await definition.actions.send({
103
- ...typingCtx,
104
- content: item
105
- });
106
- }
107
- },
108
- startTyping: async () => {
109
- await definition.actions.startTyping?.(typingCtx);
110
- },
111
- stopTyping: async () => {
112
- await definition.actions.stopTyping?.(typingCtx);
113
- },
114
- responding: async (fn) => {
115
- await definition.actions.startTyping?.(typingCtx);
116
- try {
117
- return await fn();
118
- } finally {
119
- await definition.actions.stopTyping?.(typingCtx).catch(() => {
120
- });
121
- }
122
- }
123
- };
124
- const normalizedMessage = {
125
- ...parsedExtra,
212
+ const space = buildSpace({
213
+ spaceRef,
214
+ extras: {},
215
+ typingCtx,
216
+ definition,
217
+ client,
218
+ config
219
+ });
220
+ const normalizedMessage = buildMessage({
126
221
  id: msg.id,
127
222
  content: msg.content,
128
- platform: definition.name,
129
- react: async (reaction) => {
130
- if (!definition.actions.reactToMessage) {
131
- return;
132
- }
133
- await definition.actions.reactToMessage({
134
- space: spaceRef,
135
- messageId: msg.id,
136
- reaction,
137
- client,
138
- config
139
- });
140
- },
141
- reply: async (...content) => {
142
- if (!definition.actions.replyToMessage) {
143
- return;
144
- }
145
- const resolved = await resolveContents(content);
146
- for (const item of resolved) {
147
- await definition.actions.replyToMessage({
148
- space: spaceRef,
149
- messageId: msg.id,
150
- content: item,
151
- client,
152
- config
153
- });
154
- }
155
- },
156
- sender: {
157
- ...msg.sender,
158
- __platform: definition.name
159
- },
223
+ sender: msg.sender,
224
+ timestamp: msg.timestamp ?? /* @__PURE__ */ new Date(),
225
+ extras: parsedExtra,
226
+ spaceRef,
160
227
  space,
161
- timestamp: msg.timestamp ?? /* @__PURE__ */ new Date()
162
- };
228
+ definition,
229
+ client,
230
+ config,
231
+ direction: "inbound"
232
+ });
163
233
  yield [space, normalizedMessage];
164
234
  }
165
235
  };
@@ -270,8 +340,13 @@ async function Spectrum(options) {
270
340
  __internal: { platforms: platformStates },
271
341
  messages,
272
342
  stop: stopOnce,
273
- send: async (space, ...content) => {
274
- await space.send(...content);
343
+ send: (async (space, ...content) => {
344
+ return content.length === 1 ? await space.send(content[0]) : await space.send(
345
+ ...content
346
+ );
347
+ }),
348
+ edit: async (message, newContent) => {
349
+ await message.edit(newContent);
275
350
  },
276
351
  responding: async (space, fn) => {
277
352
  return space.responding(fn);
@@ -294,10 +369,14 @@ export {
294
369
  SpectrumCloudError,
295
370
  attachment,
296
371
  cloud,
372
+ contact,
297
373
  custom,
298
374
  definePlatform,
375
+ fromVCard,
299
376
  mergeStreams,
300
377
  resolveContents,
301
378
  stream,
302
- text
379
+ text,
380
+ toVCard,
381
+ voice
303
382
  };
@@ -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 { l as SchemaMessage, d as Platform, c as PlatformDef, P as ProviderMessage } from '../../types-BdWMydUJ.js';
6
+ import { l as SchemaMessage, d as Platform, c as PlatformDef, P as ProviderMessage } from '../../types-DZMHfgYQ.js';
7
7
  import * as zod_v4_core from 'zod/v4/core';
8
8
  import 'hotscript';
9
9