spectrum-ts 4.1.0 → 5.0.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/README.md +29 -67
- package/dist/authoring.d.ts +1 -6
- package/dist/authoring.js +2 -36
- package/dist/elysia.d.ts +1 -0
- package/dist/elysia.js +2 -0
- package/dist/express.d.ts +1 -0
- package/dist/express.js +2 -0
- package/dist/hono.d.ts +1 -0
- package/dist/hono.js +2 -0
- package/dist/index.d.ts +1 -2837
- package/dist/index.js +2 -3373
- package/dist/manifest.json +5 -5
- package/dist/providers/imessage/index.d.ts +1 -222
- package/dist/providers/imessage/index.js +2 -25
- package/dist/providers/index.d.ts +6 -19
- package/dist/providers/index.js +6 -34
- package/dist/providers/slack/index.d.ts +1 -46
- package/dist/providers/slack/index.js +2 -11
- package/dist/providers/telegram/index.d.ts +1 -45
- package/dist/providers/telegram/index.js +2 -13
- package/dist/providers/terminal/index.d.ts +1 -119
- package/dist/providers/terminal/index.js +2 -13
- package/dist/providers/whatsapp-business/index.d.ts +1 -27
- package/dist/providers/whatsapp-business/index.js +2 -14
- package/package.json +23 -26
- package/dist/attachment-CnivEhr6.d.ts +0 -29
- package/dist/authoring-b9AhXgPI.d.ts +0 -304
- package/dist/chunk-2D27WW5B.js +0 -63
- package/dist/chunk-34FQGGD7.js +0 -34
- package/dist/chunk-3GEJYGZK.js +0 -84
- package/dist/chunk-3KWFP4L2.js +0 -864
- package/dist/chunk-5XEFJBN2.js +0 -197
- package/dist/chunk-6UZFVXQF.js +0 -374
- package/dist/chunk-A37PM5N2.js +0 -91
- package/dist/chunk-B52VPQO3.js +0 -1379
- package/dist/chunk-DMT6BFJV.js +0 -2980
- package/dist/chunk-FAIFTUV2.js +0 -139
- package/dist/chunk-IM5ADDZS.js +0 -887
- package/dist/chunk-LZXPLXZF.js +0 -35
- package/dist/chunk-U3QQ56YZ.js +0 -929
- package/dist/chunk-UXAKIXVM.js +0 -409
- package/dist/chunk-WXLQNANA.js +0 -539
- package/dist/chunk-ZR3TKZMT.js +0 -129
- package/dist/read-C4uvozGX.d.ts +0 -53
- package/dist/types-BIta6Kxi.d.ts +0 -82
- package/dist/types-CyfLJXgu.d.ts +0 -1530
package/dist/chunk-UXAKIXVM.js
DELETED
|
@@ -1,409 +0,0 @@
|
|
|
1
|
-
import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
|
|
2
|
-
|
|
3
|
-
// src/content/attachment.ts
|
|
4
|
-
import { randomUUID } from "crypto";
|
|
5
|
-
import { createReadStream } from "fs";
|
|
6
|
-
import { readFile, stat } from "fs/promises";
|
|
7
|
-
import { basename } from "path";
|
|
8
|
-
import { Readable } from "stream";
|
|
9
|
-
import { lookup as lookupMimeType } from "mime-types";
|
|
10
|
-
import z2 from "zod";
|
|
11
|
-
|
|
12
|
-
// src/utils/io.ts
|
|
13
|
-
import z from "zod";
|
|
14
|
-
var readSchema = z.function({
|
|
15
|
-
input: [],
|
|
16
|
-
output: z.promise(z.instanceof(Buffer))
|
|
17
|
-
});
|
|
18
|
-
var streamSchema = z.function({
|
|
19
|
-
input: [],
|
|
20
|
-
output: z.promise(z.instanceof(ReadableStream))
|
|
21
|
-
});
|
|
22
|
-
var bufferToStream = (buf) => new ReadableStream({
|
|
23
|
-
start(controller) {
|
|
24
|
-
controller.enqueue(buf);
|
|
25
|
-
controller.close();
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
var DEFAULT_FETCH_TIMEOUT_MS = 1e4;
|
|
29
|
-
var fetchUrlBytes = async (url, options) => {
|
|
30
|
-
const controller = new AbortController();
|
|
31
|
-
const timer = setTimeout(
|
|
32
|
-
() => controller.abort(),
|
|
33
|
-
options?.timeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS
|
|
34
|
-
);
|
|
35
|
-
try {
|
|
36
|
-
const res = await fetch(url, {
|
|
37
|
-
signal: controller.signal,
|
|
38
|
-
headers: options?.headers
|
|
39
|
-
});
|
|
40
|
-
if (!res.ok) {
|
|
41
|
-
throw new Error(`URL fetch ${url.toString()} returned ${res.status}`);
|
|
42
|
-
}
|
|
43
|
-
const data = Buffer.from(await res.arrayBuffer());
|
|
44
|
-
const mimeType = res.headers.get("content-type") ?? void 0;
|
|
45
|
-
return { data, mimeType };
|
|
46
|
-
} finally {
|
|
47
|
-
clearTimeout(timer);
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
// src/content/attachment.ts
|
|
52
|
-
var DEFAULT_ATTACHMENT_NAME = "attachment";
|
|
53
|
-
var attachmentSchema = z2.object({
|
|
54
|
-
type: z2.literal("attachment"),
|
|
55
|
-
id: z2.string().nonempty(),
|
|
56
|
-
name: z2.string().nonempty(),
|
|
57
|
-
mimeType: z2.string().nonempty(),
|
|
58
|
-
size: z2.number().int().nonnegative().optional(),
|
|
59
|
-
read: readSchema,
|
|
60
|
-
stream: streamSchema
|
|
61
|
-
});
|
|
62
|
-
var resolveAttachmentName = (input, name) => {
|
|
63
|
-
if (name) {
|
|
64
|
-
return name;
|
|
65
|
-
}
|
|
66
|
-
if (input instanceof URL) {
|
|
67
|
-
return basename(input.pathname) || DEFAULT_ATTACHMENT_NAME;
|
|
68
|
-
}
|
|
69
|
-
if (typeof input === "string") {
|
|
70
|
-
return basename(input);
|
|
71
|
-
}
|
|
72
|
-
return DEFAULT_ATTACHMENT_NAME;
|
|
73
|
-
};
|
|
74
|
-
var resolveAttachmentMimeType = (name, mimeType) => {
|
|
75
|
-
if (mimeType) {
|
|
76
|
-
return mimeType;
|
|
77
|
-
}
|
|
78
|
-
const resolvedMimeType = lookupMimeType(name);
|
|
79
|
-
if (!resolvedMimeType) {
|
|
80
|
-
throw new Error(
|
|
81
|
-
`Unable to resolve MIME type for attachment "${name}". Pass options.mimeType explicitly.`
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
return resolvedMimeType;
|
|
85
|
-
};
|
|
86
|
-
var asAttachment = (input) => {
|
|
87
|
-
let cached;
|
|
88
|
-
const read = () => {
|
|
89
|
-
cached ??= input.read().catch((err) => {
|
|
90
|
-
cached = void 0;
|
|
91
|
-
throw err;
|
|
92
|
-
});
|
|
93
|
-
return cached;
|
|
94
|
-
};
|
|
95
|
-
const stream = input.stream ?? (async () => bufferToStream(await read()));
|
|
96
|
-
return attachmentSchema.parse({
|
|
97
|
-
type: "attachment",
|
|
98
|
-
id: input.id ?? randomUUID(),
|
|
99
|
-
name: input.name,
|
|
100
|
-
mimeType: input.mimeType,
|
|
101
|
-
size: input.size,
|
|
102
|
-
read,
|
|
103
|
-
stream
|
|
104
|
-
});
|
|
105
|
-
};
|
|
106
|
-
function attachment(input, options) {
|
|
107
|
-
return {
|
|
108
|
-
build: async () => {
|
|
109
|
-
const id = options?.id;
|
|
110
|
-
const name = resolveAttachmentName(input, options?.name);
|
|
111
|
-
const mimeType = resolveAttachmentMimeType(name, options?.mimeType);
|
|
112
|
-
if (input instanceof URL) {
|
|
113
|
-
return asAttachment({
|
|
114
|
-
id,
|
|
115
|
-
name,
|
|
116
|
-
mimeType,
|
|
117
|
-
read: async () => (await fetchUrlBytes(input)).data
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
if (typeof input === "string") {
|
|
121
|
-
const stats = await stat(input);
|
|
122
|
-
return asAttachment({
|
|
123
|
-
id,
|
|
124
|
-
name,
|
|
125
|
-
mimeType,
|
|
126
|
-
size: stats.size,
|
|
127
|
-
read: () => readFile(input),
|
|
128
|
-
stream: async () => Readable.toWeb(
|
|
129
|
-
createReadStream(input)
|
|
130
|
-
)
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
return asAttachment({
|
|
134
|
-
id,
|
|
135
|
-
name,
|
|
136
|
-
mimeType,
|
|
137
|
-
size: input.byteLength,
|
|
138
|
-
read: async () => input,
|
|
139
|
-
stream: async () => bufferToStream(input)
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// src/content/custom.ts
|
|
146
|
-
import z3 from "zod";
|
|
147
|
-
var customSchema = z3.object({
|
|
148
|
-
type: z3.literal("custom"),
|
|
149
|
-
raw: z3.unknown()
|
|
150
|
-
});
|
|
151
|
-
var asCustom = (raw) => customSchema.parse({ type: "custom", raw });
|
|
152
|
-
function custom(raw) {
|
|
153
|
-
return {
|
|
154
|
-
build: async () => asCustom(raw)
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// src/content/text.ts
|
|
159
|
-
import z5 from "zod";
|
|
160
|
-
|
|
161
|
-
// src/content/stream-text.ts
|
|
162
|
-
import z4 from "zod";
|
|
163
|
-
var streamTextSchema = z4.object({
|
|
164
|
-
type: z4.literal("streamText"),
|
|
165
|
-
// A single-consumption producer of normalized text deltas. The builder
|
|
166
|
-
// closes over the normalized source; the platform driver calls it once.
|
|
167
|
-
// Kept opaque to Zod via `z.custom` (same approach as `attachment.read`).
|
|
168
|
-
stream: z4.custom(
|
|
169
|
-
(v) => typeof v === "function",
|
|
170
|
-
{
|
|
171
|
-
message: "streamText.stream must be a function returning AsyncIterable<string>"
|
|
172
|
-
}
|
|
173
|
-
),
|
|
174
|
-
// How platforms should interpret the accumulated text; absent = plain.
|
|
175
|
-
format: z4.enum(["plain", "markdown"]).optional()
|
|
176
|
-
});
|
|
177
|
-
var asRecord = (value) => typeof value === "object" && value !== null ? value : void 0;
|
|
178
|
-
var SKIP_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
179
|
-
"message_start",
|
|
180
|
-
"message_delta",
|
|
181
|
-
"message_stop",
|
|
182
|
-
"content_block_start",
|
|
183
|
-
"content_block_stop",
|
|
184
|
-
"ping"
|
|
185
|
-
]);
|
|
186
|
-
var fromOpenAIResponses = (obj) => {
|
|
187
|
-
const type = obj.type;
|
|
188
|
-
if (typeof type !== "string" || !type.startsWith("response.")) {
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
if (type === "response.output_text.delta" && typeof obj.delta === "string") {
|
|
192
|
-
return obj.delta;
|
|
193
|
-
}
|
|
194
|
-
return null;
|
|
195
|
-
};
|
|
196
|
-
var fromAnthropicDelta = (obj) => {
|
|
197
|
-
if (obj.type !== "content_block_delta") {
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
const delta = asRecord(obj.delta);
|
|
201
|
-
if (delta?.type === "text_delta" && typeof delta.text === "string") {
|
|
202
|
-
return delta.text;
|
|
203
|
-
}
|
|
204
|
-
return null;
|
|
205
|
-
};
|
|
206
|
-
var fromAiSdkPart = (obj) => {
|
|
207
|
-
if (obj.type !== "text-delta") {
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
if (typeof obj.textDelta === "string") {
|
|
211
|
-
return obj.textDelta;
|
|
212
|
-
}
|
|
213
|
-
return typeof obj.text === "string" ? obj.text : null;
|
|
214
|
-
};
|
|
215
|
-
var fromOpenAIChat = (obj) => {
|
|
216
|
-
if (!Array.isArray(obj.choices)) {
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
const delta = asRecord(asRecord(obj.choices[0])?.delta);
|
|
220
|
-
const content = delta?.content;
|
|
221
|
-
return typeof content === "string" ? content : null;
|
|
222
|
-
};
|
|
223
|
-
var fromControlEvent = (obj) => typeof obj.type === "string" && SKIP_EVENT_TYPES.has(obj.type) ? null : void 0;
|
|
224
|
-
var OBJECT_EXTRACTORS = [
|
|
225
|
-
fromOpenAIResponses,
|
|
226
|
-
fromAnthropicDelta,
|
|
227
|
-
fromAiSdkPart,
|
|
228
|
-
fromOpenAIChat,
|
|
229
|
-
fromControlEvent
|
|
230
|
-
];
|
|
231
|
-
var defaultExtract = (chunk) => {
|
|
232
|
-
if (typeof chunk === "string") {
|
|
233
|
-
return chunk;
|
|
234
|
-
}
|
|
235
|
-
const record = asRecord(chunk);
|
|
236
|
-
if (!record) {
|
|
237
|
-
throw new Error(
|
|
238
|
-
`text stream: cannot extract a text delta from a ${typeof chunk} chunk. Pass { extract } to map your stream's chunks to text.`
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
for (const extractor of OBJECT_EXTRACTORS) {
|
|
242
|
-
const result = extractor(record);
|
|
243
|
-
if (result !== void 0) {
|
|
244
|
-
return result;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
throw new Error(
|
|
248
|
-
`text stream: unrecognized chunk shape (type=${String(record.type)}). Pass an { extract } function to map your provider's chunk to a text delta.`
|
|
249
|
-
);
|
|
250
|
-
};
|
|
251
|
-
var isReadableStream = (value) => typeof value?.getReader === "function";
|
|
252
|
-
var isAsyncIterable = (value) => typeof value?.[Symbol.asyncIterator] === "function";
|
|
253
|
-
async function* readableToAsync(source) {
|
|
254
|
-
if (isAsyncIterable(source)) {
|
|
255
|
-
yield* source;
|
|
256
|
-
return;
|
|
257
|
-
}
|
|
258
|
-
const reader = source.getReader();
|
|
259
|
-
try {
|
|
260
|
-
while (true) {
|
|
261
|
-
const { done, value } = await reader.read();
|
|
262
|
-
if (done) {
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
yield value;
|
|
266
|
-
}
|
|
267
|
-
} finally {
|
|
268
|
-
reader.releaseLock();
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
var resolveChunkIterable = (source) => {
|
|
272
|
-
const textStream = source.textStream;
|
|
273
|
-
if (textStream != null) {
|
|
274
|
-
if (isReadableStream(textStream)) {
|
|
275
|
-
return readableToAsync(textStream);
|
|
276
|
-
}
|
|
277
|
-
if (isAsyncIterable(textStream)) {
|
|
278
|
-
return textStream;
|
|
279
|
-
}
|
|
280
|
-
throw new Error(
|
|
281
|
-
"text stream: `.textStream` must be an AsyncIterable or a ReadableStream."
|
|
282
|
-
);
|
|
283
|
-
}
|
|
284
|
-
if (isReadableStream(source)) {
|
|
285
|
-
return readableToAsync(source);
|
|
286
|
-
}
|
|
287
|
-
if (isAsyncIterable(source)) {
|
|
288
|
-
return source;
|
|
289
|
-
}
|
|
290
|
-
throw new Error(
|
|
291
|
-
"text stream: source must be an AsyncIterable, a ReadableStream, or an object with a `.textStream` (e.g. the AI SDK streamText() result)."
|
|
292
|
-
);
|
|
293
|
-
};
|
|
294
|
-
var StreamConsumedError = class extends Error {
|
|
295
|
-
constructor() {
|
|
296
|
-
super(
|
|
297
|
-
"text stream: this source has already been consumed \u2014 a stream can only be sent once."
|
|
298
|
-
);
|
|
299
|
-
this.name = "StreamConsumedError";
|
|
300
|
-
}
|
|
301
|
-
};
|
|
302
|
-
var normalize = (source, options) => {
|
|
303
|
-
const extract = options?.extract ? options.extract : defaultExtract;
|
|
304
|
-
let consumed = false;
|
|
305
|
-
return async function* normalized() {
|
|
306
|
-
if (consumed) {
|
|
307
|
-
throw new StreamConsumedError();
|
|
308
|
-
}
|
|
309
|
-
consumed = true;
|
|
310
|
-
for await (const chunk of resolveChunkIterable(source)) {
|
|
311
|
-
const delta = extract(chunk);
|
|
312
|
-
if (delta) {
|
|
313
|
-
yield delta;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
};
|
|
317
|
-
};
|
|
318
|
-
var asStreamText = (input) => streamTextSchema.parse({
|
|
319
|
-
type: "streamText",
|
|
320
|
-
stream: input.stream,
|
|
321
|
-
...input.format ? { format: input.format } : {}
|
|
322
|
-
});
|
|
323
|
-
var drainStreamText = async (content) => {
|
|
324
|
-
let full = "";
|
|
325
|
-
for await (const delta of content.stream()) {
|
|
326
|
-
full += delta;
|
|
327
|
-
}
|
|
328
|
-
return full;
|
|
329
|
-
};
|
|
330
|
-
var streamTextBuilder = (kind, source, options) => {
|
|
331
|
-
if (typeof source.build === "function") {
|
|
332
|
-
throw new Error(
|
|
333
|
-
`${kind}(): pass the stream source itself (an AsyncIterable, a ReadableStream, or an SDK result with .textStream), not another content builder.`
|
|
334
|
-
);
|
|
335
|
-
}
|
|
336
|
-
return {
|
|
337
|
-
build: async () => asStreamText({
|
|
338
|
-
stream: normalize(source, options),
|
|
339
|
-
format: kind === "markdown" ? "markdown" : void 0
|
|
340
|
-
})
|
|
341
|
-
};
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
// src/content/text.ts
|
|
345
|
-
var textSchema = z5.object({
|
|
346
|
-
type: z5.literal("text"),
|
|
347
|
-
text: z5.string().nonempty()
|
|
348
|
-
});
|
|
349
|
-
var asText = (text2) => textSchema.parse({ type: "text", text: text2 });
|
|
350
|
-
function text(source, options) {
|
|
351
|
-
if (typeof source === "string") {
|
|
352
|
-
return { build: async () => asText(source) };
|
|
353
|
-
}
|
|
354
|
-
return streamTextBuilder("text", source, options);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
// src/content/resolve.ts
|
|
358
|
-
var resolveContents = (items) => Promise.all(
|
|
359
|
-
items.map((c) => typeof c === "string" ? text(c).build() : c.build())
|
|
360
|
-
);
|
|
361
|
-
|
|
362
|
-
// src/content/reaction.ts
|
|
363
|
-
import z6 from "zod";
|
|
364
|
-
var isMessage = (v) => typeof v === "object" && v !== null && "id" in v && "content" in v;
|
|
365
|
-
var reactionSchema = z6.object({
|
|
366
|
-
type: z6.literal("reaction"),
|
|
367
|
-
emoji: z6.string().min(1),
|
|
368
|
-
target: z6.custom(isMessage, {
|
|
369
|
-
message: "reaction target must be a Message"
|
|
370
|
-
})
|
|
371
|
-
});
|
|
372
|
-
var asReaction = (input) => reactionSchema.parse({ type: "reaction", ...input });
|
|
373
|
-
function reaction(emoji, target) {
|
|
374
|
-
return {
|
|
375
|
-
build: async () => {
|
|
376
|
-
if (!target) {
|
|
377
|
-
throw new Error(
|
|
378
|
-
"reaction() target is undefined \u2014 the targeted message was never sent (space.send resolves undefined when a platform skips unsupported content)"
|
|
379
|
-
);
|
|
380
|
-
}
|
|
381
|
-
if (target.content.type === "reaction") {
|
|
382
|
-
throw new Error('reaction() cannot target "reaction" content');
|
|
383
|
-
}
|
|
384
|
-
return asReaction({ emoji, target });
|
|
385
|
-
}
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
export {
|
|
390
|
-
readSchema,
|
|
391
|
-
streamSchema,
|
|
392
|
-
bufferToStream,
|
|
393
|
-
fetchUrlBytes,
|
|
394
|
-
attachmentSchema,
|
|
395
|
-
asAttachment,
|
|
396
|
-
attachment,
|
|
397
|
-
asCustom,
|
|
398
|
-
custom,
|
|
399
|
-
StreamConsumedError,
|
|
400
|
-
drainStreamText,
|
|
401
|
-
streamTextBuilder,
|
|
402
|
-
textSchema,
|
|
403
|
-
asText,
|
|
404
|
-
text,
|
|
405
|
-
resolveContents,
|
|
406
|
-
reactionSchema,
|
|
407
|
-
asReaction,
|
|
408
|
-
reaction
|
|
409
|
-
};
|