spectrum-ts 4.2.0 → 5.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.
Files changed (46) hide show
  1. package/README.md +29 -67
  2. package/dist/authoring.d.ts +1 -6
  3. package/dist/authoring.js +2 -36
  4. package/dist/elysia.d.ts +1 -94
  5. package/dist/elysia.js +2 -15
  6. package/dist/express.d.ts +1 -62
  7. package/dist/express.js +2 -19
  8. package/dist/hono.d.ts +1 -64
  9. package/dist/hono.js +2 -11
  10. package/dist/index.d.ts +1 -2851
  11. package/dist/index.js +2 -3763
  12. package/dist/manifest.json +5 -5
  13. package/dist/providers/imessage/index.d.ts +1 -222
  14. package/dist/providers/imessage/index.js +2 -25
  15. package/dist/providers/index.d.ts +6 -19
  16. package/dist/providers/index.js +6 -34
  17. package/dist/providers/slack/index.d.ts +1 -46
  18. package/dist/providers/slack/index.js +2 -11
  19. package/dist/providers/telegram/index.d.ts +1 -45
  20. package/dist/providers/telegram/index.js +2 -13
  21. package/dist/providers/terminal/index.d.ts +1 -119
  22. package/dist/providers/terminal/index.js +2 -13
  23. package/dist/providers/whatsapp-business/index.d.ts +1 -27
  24. package/dist/providers/whatsapp-business/index.js +2 -14
  25. package/package.json +11 -38
  26. package/dist/attachment-CnivEhr6.d.ts +0 -29
  27. package/dist/authoring-b9AhXgPI.d.ts +0 -304
  28. package/dist/chunk-2D27WW5B.js +0 -63
  29. package/dist/chunk-34FQGGD7.js +0 -34
  30. package/dist/chunk-3GEJYGZK.js +0 -84
  31. package/dist/chunk-5XEFJBN2.js +0 -197
  32. package/dist/chunk-6UZFVXQF.js +0 -374
  33. package/dist/chunk-A37PM5N2.js +0 -91
  34. package/dist/chunk-ARL2NOBO.js +0 -887
  35. package/dist/chunk-B52VPQO3.js +0 -1379
  36. package/dist/chunk-DMPDLSFU.js +0 -864
  37. package/dist/chunk-FAIFTUV2.js +0 -139
  38. package/dist/chunk-LZXPLXZF.js +0 -35
  39. package/dist/chunk-N6THJDZV.js +0 -929
  40. package/dist/chunk-NLMQ75LH.js +0 -2980
  41. package/dist/chunk-UXAKIXVM.js +0 -409
  42. package/dist/chunk-WXLQNANA.js +0 -539
  43. package/dist/chunk-ZR3TKZMT.js +0 -129
  44. package/dist/read-C4uvozGX.d.ts +0 -53
  45. package/dist/types-CyfLJXgu.d.ts +0 -1530
  46. package/dist/types-ZgFTj5hJ.d.ts +0 -87
@@ -1,539 +0,0 @@
1
- import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
2
- import {
3
- cloud
4
- } from "./chunk-3GEJYGZK.js";
5
- import {
6
- mergeStreams,
7
- stream
8
- } from "./chunk-5XEFJBN2.js";
9
- import {
10
- UnsupportedError,
11
- definePlatform
12
- } from "./chunk-B52VPQO3.js";
13
- import {
14
- asAttachment,
15
- asCustom,
16
- asReaction,
17
- asText
18
- } from "./chunk-UXAKIXVM.js";
19
-
20
- // src/providers/slack/index.ts
21
- import { createClient as createClient2, staticTokens } from "@photon-ai/slack";
22
-
23
- // src/providers/slack/auth.ts
24
- import {
25
- createClient
26
- } from "@photon-ai/slack";
27
- var RENEWAL_RATIO = 0.8;
28
- var EXPIRY_BUFFER_MS = 3e4;
29
- var RETRY_DELAY_MS = 3e4;
30
- var cloudAuthState = /* @__PURE__ */ new WeakMap();
31
- var toTeamMetadata = (meta) => ({
32
- appId: meta.appId,
33
- botUserId: meta.botUserId,
34
- grantedScopes: meta.grantedScopes,
35
- teamName: meta.teamName
36
- });
37
- async function createCloudClients(projectId, projectSecret, endpoint) {
38
- let tokenData = await cloud.issueSlackTokens(projectId, projectSecret);
39
- let tokenExpiresAt = Date.now() + tokenData.expiresIn * 1e3;
40
- let disposed = false;
41
- let renewalTimer;
42
- const clearRenewalTimer = () => {
43
- if (renewalTimer !== void 0) {
44
- clearTimeout(renewalTimer);
45
- renewalTimer = void 0;
46
- }
47
- };
48
- const refreshTokens = async () => {
49
- tokenData = await cloud.issueSlackTokens(projectId, projectSecret);
50
- tokenExpiresAt = Date.now() + tokenData.expiresIn * 1e3;
51
- };
52
- const scheduleRetry = () => {
53
- if (disposed) {
54
- return;
55
- }
56
- clearRenewalTimer();
57
- renewalTimer = setTimeout(async () => {
58
- if (disposed) {
59
- return;
60
- }
61
- try {
62
- await refreshTokens();
63
- scheduleRenewal();
64
- } catch (retryErr) {
65
- console.warn(
66
- `[spectrum-ts] Slack token refresh failed; retrying in ${RETRY_DELAY_MS}ms.`,
67
- retryErr
68
- );
69
- scheduleRetry();
70
- }
71
- }, RETRY_DELAY_MS);
72
- renewalTimer?.unref?.();
73
- };
74
- const scheduleRenewal = () => {
75
- if (disposed) {
76
- return;
77
- }
78
- clearRenewalTimer();
79
- const ttlMs = tokenData.expiresIn * 1e3;
80
- const renewInMs = Math.max(ttlMs * RENEWAL_RATIO, 5e3);
81
- renewalTimer = setTimeout(async () => {
82
- try {
83
- await refreshTokens();
84
- scheduleRenewal();
85
- } catch (err) {
86
- console.warn(
87
- `[spectrum-ts] Slack token refresh failed; retrying in ${RETRY_DELAY_MS}ms.`,
88
- err
89
- );
90
- scheduleRetry();
91
- }
92
- }, renewInMs);
93
- renewalTimer?.unref?.();
94
- };
95
- const refreshIfNeeded = async () => {
96
- if (Date.now() < tokenExpiresAt - EXPIRY_BUFFER_MS) {
97
- return;
98
- }
99
- await refreshTokens();
100
- scheduleRenewal();
101
- };
102
- scheduleRenewal();
103
- const tokenProvider = {
104
- async getAccessToken(teamId) {
105
- await refreshIfNeeded();
106
- const token = tokenData.auth[teamId];
107
- if (!token) {
108
- throw new Error(
109
- `Slack team ${teamId} has no active installation in this project`
110
- );
111
- }
112
- return token;
113
- },
114
- invalidate(_teamId) {
115
- tokenExpiresAt = 0;
116
- },
117
- async listTeams() {
118
- await refreshIfNeeded();
119
- const entries = Object.entries(
120
- tokenData.teams
121
- ).map(([teamId, meta]) => [teamId, toTeamMetadata(meta)]);
122
- return new Map(entries);
123
- }
124
- };
125
- const client = createClient({
126
- spectrumSlackEndpoint: endpoint,
127
- tokenProvider
128
- });
129
- cloudAuthState.set(client, {
130
- dispose: async () => {
131
- disposed = true;
132
- clearRenewalTimer();
133
- }
134
- });
135
- return client;
136
- }
137
- async function disposeCloudAuth(client) {
138
- const auth = cloudAuthState.get(client);
139
- if (!auth) {
140
- return;
141
- }
142
- await auth.dispose();
143
- cloudAuthState.delete(client);
144
- }
145
-
146
- // src/providers/slack/messages.ts
147
- var toRecord = (result, space, content) => ({
148
- id: result.ts,
149
- content,
150
- space: { id: result.channel, teamId: space.teamId },
151
- timestamp: tsToDate(result.ts),
152
- ts: result.ts,
153
- isFromMe: true
154
- });
155
- var toUploadRecord = (result, space, content) => {
156
- const shareTs = result.shares.find((s) => s.channel === space.id)?.ts;
157
- return {
158
- id: shareTs ?? result.file.id,
159
- content,
160
- space: { id: space.id, teamId: space.teamId },
161
- timestamp: shareTs ? tsToDate(shareTs) : /* @__PURE__ */ new Date(),
162
- ts: shareTs,
163
- isFromMe: true
164
- };
165
- };
166
- var tsToDate = (ts) => {
167
- if (!ts) {
168
- return /* @__PURE__ */ new Date();
169
- }
170
- const seconds = Number.parseFloat(ts);
171
- if (!Number.isFinite(seconds)) {
172
- return /* @__PURE__ */ new Date();
173
- }
174
- return new Date(seconds * 1e3);
175
- };
176
- var lazySlackFile = (client, teamId, file) => asAttachment({
177
- id: file.id,
178
- name: file.name,
179
- mimeType: file.mimeType,
180
- size: file.size,
181
- read: async () => {
182
- const { bytes } = await client.team(teamId).files.getContentBuffer(file.id);
183
- return Buffer.from(bytes);
184
- },
185
- stream: async () => {
186
- const { content } = await client.team(teamId).files.getContent(file.id);
187
- return new ReadableStream({
188
- async start(controller) {
189
- try {
190
- for await (const chunk of content) {
191
- controller.enqueue(chunk);
192
- }
193
- controller.close();
194
- } catch (err) {
195
- controller.error(err);
196
- }
197
- }
198
- });
199
- }
200
- });
201
- var toMessages = (client, event) => {
202
- if (event.type === "message") {
203
- return messageToMessages(client, event.teamId, event.message);
204
- }
205
- if (event.type === "reaction") {
206
- return [reactionToMessage(event.teamId, event.reaction)];
207
- }
208
- if (event.type === "mention") {
209
- return [
210
- {
211
- id: event.mention.ts,
212
- content: asText(event.mention.text),
213
- sender: { id: event.mention.user },
214
- space: { id: event.mention.channel, teamId: event.teamId },
215
- timestamp: tsToDate(event.mention.ts),
216
- ts: event.mention.ts,
217
- isFromMe: event.mention.isFromMe
218
- }
219
- ];
220
- }
221
- return [];
222
- };
223
- var messageToMessages = (client, teamId, msg) => {
224
- const base = {
225
- sender: { id: msg.user },
226
- space: { id: msg.channel, teamId },
227
- timestamp: tsToDate(msg.ts),
228
- ts: msg.ts,
229
- threadTs: msg.threadTs,
230
- subtype: msg.subtype,
231
- isFromMe: msg.isFromMe
232
- };
233
- const results = [];
234
- if (msg.text) {
235
- results.push({
236
- ...base,
237
- id: msg.files.length > 0 ? `${msg.ts}:text` : msg.ts,
238
- content: asText(msg.text)
239
- });
240
- }
241
- for (const [index, file] of msg.files.entries()) {
242
- const singleFile = msg.files.length === 1 && !msg.text;
243
- results.push({
244
- ...base,
245
- id: singleFile ? msg.ts : `${msg.ts}:file:${index}`,
246
- content: lazySlackFile(client, teamId, file)
247
- });
248
- }
249
- if (results.length === 0) {
250
- results.push({
251
- ...base,
252
- id: msg.ts,
253
- content: asCustom({ slack_type: "empty" })
254
- });
255
- }
256
- return results;
257
- };
258
- var reactionToMessage = (teamId, reaction) => {
259
- const stubTarget = {
260
- id: reaction.itemTs,
261
- content: asCustom({ slack_type: "reaction-target", stub: true }),
262
- sender: { id: "" },
263
- space: { id: reaction.itemChannel, teamId }
264
- };
265
- return {
266
- id: `${reaction.itemTs}:reaction:${reaction.user}:${reaction.name}`,
267
- content: asReaction({
268
- emoji: reaction.name,
269
- // Cast through unknown: stub is a partial Message; core's
270
- // wrapProviderMessage inflates the missing react/reply/edit methods.
271
- target: stubTarget
272
- }),
273
- sender: { id: reaction.user },
274
- space: { id: reaction.itemChannel, teamId },
275
- timestamp: /* @__PURE__ */ new Date(),
276
- ts: reaction.itemTs,
277
- subtype: reaction.removed ? "reaction_removed" : "reaction_added",
278
- isFromMe: reaction.isFromMe
279
- };
280
- };
281
- var teamStream = (client, teamId) => {
282
- const eventStream = client.team(teamId).events.subscribe();
283
- return stream((emit, end) => {
284
- const pump = (async () => {
285
- try {
286
- for await (const event of eventStream) {
287
- for (const m of toMessages(client, event)) {
288
- await emit(m);
289
- }
290
- }
291
- end();
292
- } catch (e) {
293
- end(e);
294
- }
295
- })();
296
- return async () => {
297
- await eventStream.close();
298
- await pump;
299
- };
300
- });
301
- };
302
- var messages = (client, resolveTeamIds) => stream(async (emit, end) => {
303
- let teamIds;
304
- try {
305
- teamIds = await resolveTeamIds();
306
- } catch (err) {
307
- end(err);
308
- return;
309
- }
310
- const merged = mergeStreams(teamIds.map((id) => teamStream(client, id)));
311
- const pump = (async () => {
312
- try {
313
- for await (const value of merged) {
314
- await emit(value);
315
- }
316
- end();
317
- } catch (e) {
318
- end(e);
319
- }
320
- })();
321
- return async () => {
322
- await merged.close();
323
- await pump;
324
- };
325
- });
326
- var mimeToMediaName = (mimeType, fallback) => {
327
- const slash = mimeType.indexOf("/");
328
- if (slash < 0) {
329
- return fallback;
330
- }
331
- return `${fallback}.${mimeType.slice(slash + 1)}`;
332
- };
333
- var send = async (client, space, content) => {
334
- if (content.type === "reply") {
335
- return await replyToMessage(
336
- client,
337
- space,
338
- content.target.ts ?? content.target.id,
339
- content.content
340
- );
341
- }
342
- if (content.type === "reaction") {
343
- return await reactToMessage(
344
- client,
345
- space,
346
- content.target.ts ?? content.target.id,
347
- content
348
- );
349
- }
350
- if (content.type === "typing") {
351
- return;
352
- }
353
- if (content.type === "read") {
354
- return;
355
- }
356
- return await sendContent(client, space, content);
357
- };
358
- var sendContent = async (client, space, content, threadTs) => {
359
- const team = client.team(space.teamId);
360
- switch (content.type) {
361
- case "text": {
362
- const result = await team.messages.send({
363
- channel: space.id,
364
- text: content.text,
365
- threadTs
366
- });
367
- return toRecord(result, space, content);
368
- }
369
- case "attachment": {
370
- const result = await team.files.upload({
371
- channel: space.id,
372
- content: await content.read(),
373
- filename: content.name,
374
- mimeType: content.mimeType,
375
- threadTs
376
- });
377
- return toUploadRecord(result, space, content);
378
- }
379
- case "voice": {
380
- const result = await team.files.upload({
381
- channel: space.id,
382
- content: await content.read(),
383
- filename: content.name ?? mimeToMediaName(content.mimeType, "voice"),
384
- mimeType: content.mimeType,
385
- threadTs
386
- });
387
- return toUploadRecord(result, space, content);
388
- }
389
- default:
390
- throw UnsupportedError.content(content.type);
391
- }
392
- };
393
- var reactToMessage = async (client, space, targetTs, content) => {
394
- await client.team(space.teamId).messages.send({
395
- channel: space.id,
396
- reaction: {
397
- emoji: content.emoji,
398
- itemChannel: space.id,
399
- itemTs: targetTs
400
- }
401
- });
402
- return {
403
- id: `${targetTs}:reaction:self:${content.emoji}`,
404
- content,
405
- space: { id: space.id, teamId: space.teamId },
406
- timestamp: /* @__PURE__ */ new Date(),
407
- ts: targetTs,
408
- isFromMe: true
409
- };
410
- };
411
- var replyToMessage = async (client, space, targetTs, content) => await sendContent(client, space, content, targetTs);
412
-
413
- // src/providers/slack/types.ts
414
- import z from "zod";
415
- var teamMetadataSchema = z.object({
416
- appId: z.string(),
417
- botUserId: z.string(),
418
- grantedScopes: z.array(z.string()),
419
- teamName: z.string()
420
- });
421
- var directConfig = z.object({
422
- endpoint: z.string().optional(),
423
- teams: z.record(z.string(), teamMetadataSchema).optional(),
424
- tokens: z.record(z.string(), z.string().min(1)).refine((t) => Object.keys(t).length > 0, {
425
- message: "at least one token entry is required"
426
- })
427
- });
428
- var cloudConfig = z.object({}).strict();
429
- var configSchema = z.union([directConfig, cloudConfig]);
430
- var isCloudConfig = (config) => !("tokens" in config);
431
- var userSchema = z.object({});
432
- var spaceSchema = z.object({
433
- id: z.string(),
434
- teamId: z.string()
435
- });
436
- var spaceParamsSchema = z.object({
437
- teamId: z.string()
438
- });
439
- var messageSchema = z.object({
440
- isFromMe: z.boolean(),
441
- subtype: z.string().optional(),
442
- threadTs: z.string().optional(),
443
- ts: z.string().optional()
444
- });
445
-
446
- // src/providers/slack/index.ts
447
- var slack = definePlatform("Slack", {
448
- config: configSchema,
449
- lifecycle: {
450
- createClient: async ({
451
- config,
452
- projectId,
453
- projectSecret
454
- }) => {
455
- if (!isCloudConfig(config)) {
456
- return createClient2({
457
- spectrumSlackEndpoint: config.endpoint,
458
- tokenProvider: staticTokens({
459
- tokens: config.tokens,
460
- teams: config.teams
461
- })
462
- });
463
- }
464
- if (!(projectId && projectSecret)) {
465
- throw new Error(
466
- "Slack cloud mode requires projectId and projectSecret. Either pass credentials to Spectrum(), or provide direct credentials: slack.config({ tokens: { T012ABCDE: 'jwt...' } })"
467
- );
468
- }
469
- return await createCloudClients(
470
- projectId,
471
- projectSecret,
472
- process.env.SPECTRUM_SLACK_ENDPOINT
473
- );
474
- },
475
- destroyClient: async ({ client }) => {
476
- await disposeCloudAuth(client);
477
- await client.close();
478
- }
479
- },
480
- user: {
481
- schema: userSchema,
482
- resolve: async ({ input }) => ({ id: input.userID })
483
- },
484
- space: {
485
- schema: spaceSchema,
486
- params: spaceParamsSchema,
487
- create: async ({ input }) => {
488
- const teamId = input.params?.teamId;
489
- if (!teamId) {
490
- throw new Error(
491
- "Slack space creation requires a teamId param. Pass it via space.create(user, { teamId })."
492
- );
493
- }
494
- if (input.users.length > 1) {
495
- throw UnsupportedError.action(
496
- "space.create",
497
- "Slack",
498
- "group DMs require an explicit channel id (Slack's conversations.open is not exposed); use space.get(channelId, { teamId })"
499
- );
500
- }
501
- const user = input.users[0];
502
- if (!user) {
503
- throw new Error("Slack space creation requires a user");
504
- }
505
- return { id: user.id, teamId };
506
- },
507
- get: async ({ input }) => {
508
- const teamId = input.params?.teamId;
509
- if (!teamId) {
510
- throw new Error(
511
- "Slack spaces require a teamId param. Pass it via space.get(channelId, { teamId })."
512
- );
513
- }
514
- return { id: input.id, teamId };
515
- }
516
- },
517
- message: {
518
- schema: messageSchema
519
- },
520
- // Discover the team list at subscribe time from the live `TokenProvider`.
521
- // Direct mode: `staticTokens.listTeams` returns whatever `teams` metadata
522
- // the caller passed (we fall back to the `tokens` keys when absent).
523
- // Cloud mode: our renewing provider returns the live `auth` snapshot.
524
- messages: ({ client, config }) => messages(client, async () => {
525
- const teams = await client.teams();
526
- if (teams.size > 0) {
527
- return Array.from(teams.keys());
528
- }
529
- if (isCloudConfig(config)) {
530
- return [];
531
- }
532
- return Object.keys(config.tokens);
533
- }),
534
- send: async ({ space, content, client }) => await send(client, { id: space.id, teamId: space.teamId }, content)
535
- });
536
-
537
- export {
538
- slack
539
- };
@@ -1,129 +0,0 @@
1
- import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
2
- import {
3
- bufferToStream,
4
- fetchUrlBytes,
5
- readSchema,
6
- streamSchema
7
- } from "./chunk-UXAKIXVM.js";
8
-
9
- // src/content/richlink.ts
10
- import z from "zod";
11
-
12
- // src/utils/link-metadata.ts
13
- import ogs from "open-graph-scraper";
14
- var DEFAULT_TIMEOUT_MS = 5e3;
15
- var USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15 spectrum-ts/richlink";
16
- var normaliseImageUrl = (raw, base) => {
17
- try {
18
- return new URL(raw, base).toString();
19
- } catch {
20
- return;
21
- }
22
- };
23
- var cleanString = (v) => {
24
- if (typeof v !== "string") {
25
- return;
26
- }
27
- const trimmed = v.trim();
28
- return trimmed.length > 0 ? trimmed : void 0;
29
- };
30
- var fetchLinkMetadata = async (url) => {
31
- try {
32
- const result = await ogs({
33
- url,
34
- timeout: DEFAULT_TIMEOUT_MS,
35
- fetchOptions: { headers: { "User-Agent": USER_AGENT } }
36
- });
37
- if (result.error) {
38
- return {};
39
- }
40
- const {
41
- ogTitle,
42
- ogDescription,
43
- ogImage,
44
- twitterTitle,
45
- twitterDescription,
46
- twitterImage
47
- } = result.result;
48
- const title = cleanString(ogTitle) ?? cleanString(twitterTitle);
49
- const summary = cleanString(ogDescription) ?? cleanString(twitterDescription);
50
- const imageCandidate = ogImage?.[0] ?? twitterImage?.[0];
51
- const resolved = imageCandidate ? normaliseImageUrl(imageCandidate.url, url) : void 0;
52
- const image = imageCandidate && resolved ? {
53
- url: resolved,
54
- mimeType: "type" in imageCandidate && typeof imageCandidate.type === "string" ? imageCandidate.type : void 0
55
- } : void 0;
56
- return { title, summary, image };
57
- } catch {
58
- return {};
59
- }
60
- };
61
- var fetchImage = (url) => fetchUrlBytes(new URL(url), {
62
- timeoutMs: DEFAULT_TIMEOUT_MS,
63
- headers: { "User-Agent": USER_AGENT }
64
- });
65
-
66
- // src/content/richlink.ts
67
- var richlinkCoverSchema = z.object({
68
- mimeType: z.string().min(1).optional(),
69
- read: readSchema,
70
- stream: streamSchema
71
- });
72
- var optionalStringAccessor = z.function({
73
- input: [],
74
- output: z.promise(z.string().min(1).optional())
75
- });
76
- var coverAccessor = z.function({
77
- input: [],
78
- output: z.promise(richlinkCoverSchema.optional())
79
- });
80
- var richlinkSchema = z.object({
81
- type: z.literal("richlink"),
82
- url: z.url(),
83
- title: optionalStringAccessor,
84
- summary: optionalStringAccessor,
85
- cover: coverAccessor
86
- });
87
- var memoize = (factory) => {
88
- let cached;
89
- return () => {
90
- cached ??= factory();
91
- return cached;
92
- };
93
- };
94
- var buildCover = (image) => {
95
- const read = memoize(
96
- () => fetchImage(image.url).then((r) => r.data).catch(() => Buffer.alloc(0))
97
- );
98
- return {
99
- mimeType: image.mimeType,
100
- read,
101
- stream: async () => bufferToStream(await read())
102
- };
103
- };
104
- var asRichlink = (input) => {
105
- const getMetadata = memoize(() => fetchLinkMetadata(input.url));
106
- const getCover = memoize(async () => {
107
- const { image } = await getMetadata();
108
- return image ? buildCover(image) : void 0;
109
- });
110
- const title = async () => (await getMetadata()).title;
111
- const summary = async () => (await getMetadata()).summary;
112
- return richlinkSchema.parse({
113
- type: "richlink",
114
- url: input.url,
115
- title,
116
- summary,
117
- cover: getCover
118
- });
119
- };
120
- function richlink(url) {
121
- return {
122
- build: async () => asRichlink({ url })
123
- };
124
- }
125
-
126
- export {
127
- asRichlink,
128
- richlink
129
- };
@@ -1,53 +0,0 @@
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 };