@spectrum-ts/core 8.2.2 → 9.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/dist/authoring.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { At as asReply, Cn as asCustom, Ct as asText, Et as asRichlink, Ft as renameSchema, H as ProviderMessageRecord, Hn as PhotoInput, Jt as asMarkdown, Lt as asRead, Mt as replySchema, Nn as asContact, Sn as reactionSchema, U as ProviderUserRecord, Un as buildPhotoAction, Ut as asPoll, Vn as avatarSchema, Wn as photoActionSchema, Wt as asPollOption, _n as removeMemberSchema, _t as asVoice, bn as asReaction, hn as leaveSpaceSchema, pn as addMemberSchema, q as ManagedStream, r as asAttachment, rn as groupSchema, tn as asGroup } from "./attachment-Bn3rw5jW.js";
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { FetchSpanOptions, LogAttrs, LogAttrs as LogAttrs$1, LogLevel, PhotonLogger, SanitizeUrlOptions, createLogger, sanitizeEmail, sanitizeErrorMessage, sanitizePhone, sanitizeUrl, setLogLevel } from "@photon-ai/otel";
|
|
4
4
|
import { Token } from "marked";
|
|
@@ -123,4 +123,4 @@ declare const resumableOrderedStream: <TLive, TMissed, TOutput>(options: Resumab
|
|
|
123
123
|
*/
|
|
124
124
|
declare function errorAttrs(error: unknown, prefix?: string): LogAttrs$1;
|
|
125
125
|
//#endregion
|
|
126
|
-
export { type CloseableAsyncIterable, type LogAttrs, type LogLevel, type PhotoInput, type PhotonLogger, type ProviderMessageRecord, type ResumableStreamItem, type SanitizeUrlOptions, asAttachment, asContact, asCustom, asGroup, asMarkdown, asPoll, asPollOption, asReaction, asRead, asReply, asRichlink, asText, asVoice, buildPhotoAction, createLogger, ensureM4a, errorAttrs, groupSchema, messageEffectSchema, photoActionSchema, reactionSchema, renderInlineTokens, replySchema, resumableOrderedStream, sanitizeEmail, sanitizeErrorMessage, sanitizePhone, sanitizeUrl, setLogLevel, tracedFetch };
|
|
126
|
+
export { type CloseableAsyncIterable, type LogAttrs, type LogLevel, type PhotoInput, type PhotonLogger, type ProviderMessageRecord, type ProviderUserRecord, type ResumableStreamItem, type SanitizeUrlOptions, addMemberSchema, asAttachment, asContact, asCustom, asGroup, asMarkdown, asPoll, asPollOption, asReaction, asRead, asReply, asRichlink, asText, asVoice, avatarSchema, buildPhotoAction, createLogger, ensureM4a, errorAttrs, groupSchema, leaveSpaceSchema, messageEffectSchema, photoActionSchema, reactionSchema, removeMemberSchema, renameSchema, renderInlineTokens, replySchema, resumableOrderedStream, sanitizeEmail, sanitizeErrorMessage, sanitizePhone, sanitizeUrl, setLogLevel, tracedFetch };
|
package/dist/authoring.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as addMemberSchema, B as groupSchema, E as asPollOption, F as asMarkdown, H as asText, L as markdownSchema, M as leaveSpaceSchema, P as removeMemberSchema, R as asGroup, S as asReaction, T as asPoll, W as textSchema, Y as asContact, _ as replySchema, at as attachmentSchema, b as asRead, d as asVoice, et as avatarSchema, h as asReply, i as stream, l as renderInlineTokens, nt as photoActionSchema, o as errorAttrs, p as asRichlink, q as asCustom, rt as asAttachment, st as tracedFetch, tt as buildPhotoAction, w as reactionSchema, y as renameSchema } from "./stream-DxI5ZiE2.js";
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { createLogger, createLogger as createLogger$1, sanitizeEmail, sanitizeErrorMessage, sanitizePhone, sanitizeUrl, setLogLevel } from "@photon-ai/otel";
|
|
4
4
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
@@ -422,4 +422,4 @@ const resumableOrderedStream = (options) => stream((emit, end) => {
|
|
|
422
422
|
};
|
|
423
423
|
});
|
|
424
424
|
//#endregion
|
|
425
|
-
export { asAttachment, asContact, asCustom, asGroup, asMarkdown, asPoll, asPollOption, asReaction, asRead, asReply, asRichlink, asText, asVoice, buildPhotoAction, createLogger, ensureM4a, errorAttrs, groupSchema, messageEffectSchema, photoActionSchema, reactionSchema, renderInlineTokens, replySchema, resumableOrderedStream, sanitizeEmail, sanitizeErrorMessage, sanitizePhone, sanitizeUrl, setLogLevel, tracedFetch };
|
|
425
|
+
export { addMemberSchema, asAttachment, asContact, asCustom, asGroup, asMarkdown, asPoll, asPollOption, asReaction, asRead, asReply, asRichlink, asText, asVoice, avatarSchema, buildPhotoAction, createLogger, ensureM4a, errorAttrs, groupSchema, leaveSpaceSchema, messageEffectSchema, photoActionSchema, reactionSchema, removeMemberSchema, renameSchema, renderInlineTokens, replySchema, resumableOrderedStream, sanitizeEmail, sanitizeErrorMessage, sanitizePhone, sanitizeUrl, setLogLevel, tracedFetch };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
export { type AgentSender, type AnyPlatformDef, type App, type AppLayout, type AppUrl, type Attachment, type AttachmentInput, type Avatar, type AvatarInput, type Broadcaster, type CloudPlatform, type Contact, type ContactAddress, type ContactDetails, type ContactEmail, type ContactInput, type ContactName, type ContactOrg, type ContactPhone, type Content, type ContentBuilder, type ContentInput, type DedicatedTokenData, type DeltaExtractor, type Edit, Emoji, type EmojiKey, type EventProducer, type FusorClient, type FusorEvent, type FusorMessages, type FusorMessagesCtx, type FusorMessagesReturn, type FusorReply, type FusorRespond, type FusorTokenData, type FusorVerify, type FusorVerifyRequest, type Group, type ImessageInfoData, type ManagedStream, type Markdown, type Message, type Platform, type PlatformDef, type PlatformInstance, type PlatformMessage, type PlatformProviderConfig, type PlatformRuntime, type PlatformSpace, type PlatformStatus, type PlatformUser, type PlatformsData, type Poll, type PollChoice, type PollChoiceInput, type PollOption, type ProjectData, type ProjectProfile, type ProviderMessage, type Reaction, type ReactionBuilder, type Read, type Rename, type Reply, type Richlink, type SchemaMessage, type SharedTokenData, type SlackTeamMeta, type SlackTokenData, type Space, type SpaceNamespace, Spectrum, SpectrumCloudError, type SpectrumInstance, type Store, type StreamText, type StreamTextSource, type SubscriptionData, type SubscriptionStatus, type TextStreamOptions, type TokenData, type Typing, type Unsend, UnsupportedError, type UnsupportedKind, type User, type Voice, type WebhookHandler, type WebhookRawRequest, type WebhookRawResult, app, appLayoutSchema, attachment, avatar, broadcast, cloud, contact, custom, definePlatform, edit, fromVCard, fusor, fusorEvent, group, isFusorClient, isFusorEvent, markdown, mergeStreams, option, poll, reaction, read, rename, reply, resolveContents, richlink, stream, text, toVCard, typing, unsend, voice };
|
|
1
|
+
import { $ as DedicatedTokenData, $t as TextStreamOptions, A as isFusorEvent, An as ContactName, B as PlatformUser, Bn as avatar, Bt as PollChoice, C as FusorVerify, D as WebhookRawResult, Dn as ContactDetails, Dt as richlink, E as WebhookRawRequest, En as ContactAddress, F as PlatformInstance, Fn as AgentSender, G as SpaceNamespace, Gn as App, Gt as option, Ht as PollOption, I as PlatformMessage, In as User, It as Read, J as broadcast, Jn as app, K as Broadcaster, Kn as AppLayout, Kt as poll, L as PlatformProviderConfig, Ln as Avatar, M as EventProducer, Mn as ContactPhone, N as Platform, Nt as Rename, O as FusorEvent, On as ContactEmail, Ot as resolveContents, P as PlatformDef, Pn as contact, Pt as rename, Q as CloudPlatform, Qt as StreamTextSource, R as PlatformRuntime, Rn as AvatarData, Rt as read, S as FusorRespond, St as typing, T as WebhookHandler, Tn as Contact, Tt as Richlink, V as ProviderMessage, Vt as PollChoiceInput, W as SchemaMessage, X as stream, Xt as DeltaExtractor, Y as mergeStreams, Yn as appLayoutSchema, Yt as markdown, Z as Store, Zt as StreamText, _ as FusorClient, a as Content, an as edit, at as ProjectProfile, b as FusorMessagesReturn, bt as unsend, c as fromVCard, cn as AddMember, ct as SlackTokenData, d as UnsupportedKind, dn as RemoveMember, dt as SubscriptionStatus, en as Group, et as FusorTokenData, f as Spectrum, fn as addMember, ft as TokenData, g as isFusorClient, gn as removeMember, gt as Voice, h as fusor, ht as EmojiKey, i as attachment, in as Edit, it as ProjectData, j as AnyPlatformDef, jn as ContactOrg, jt as reply, k as fusorEvent, kn as ContactInput, kt as Reply, l as toVCard, ln as LeaveSpace, lt as SpectrumCloudError, m as definePlatform, mn as leaveSpace, mt as Emoji, n as AttachmentInput, nn as group, nt as PlatformStatus, o as ContentBuilder, on as Message, ot as SharedTokenData, p as SpectrumInstance, pt as cloud, q as ManagedStream, qn as AppUrl, qt as Markdown, rt as PlatformsData, s as ContentInput, sn as Space, st as SlackTeamMeta, t as Attachment, tt as ImessageInfoData, u as UnsupportedError, un as MemberInput, ut as SubscriptionData, v as FusorMessages, vn as Reaction, vt as voice, w as FusorVerifyRequest, wn as custom, wt as text, x as FusorReply, xn as reaction, xt as Typing, y as FusorMessagesCtx, yn as ReactionBuilder, yt as Unsend, z as PlatformSpace, zn as AvatarInput, zt as Poll } from "./attachment-Bn3rw5jW.js";
|
|
2
|
+
export { type AddMember, type AgentSender, type AnyPlatformDef, type App, type AppLayout, type AppUrl, type Attachment, type AttachmentInput, type Avatar, type AvatarData, type AvatarInput, type Broadcaster, type CloudPlatform, type Contact, type ContactAddress, type ContactDetails, type ContactEmail, type ContactInput, type ContactName, type ContactOrg, type ContactPhone, type Content, type ContentBuilder, type ContentInput, type DedicatedTokenData, type DeltaExtractor, type Edit, Emoji, type EmojiKey, type EventProducer, type FusorClient, type FusorEvent, type FusorMessages, type FusorMessagesCtx, type FusorMessagesReturn, type FusorReply, type FusorRespond, type FusorTokenData, type FusorVerify, type FusorVerifyRequest, type Group, type ImessageInfoData, type LeaveSpace, type ManagedStream, type Markdown, type MemberInput, type Message, type Platform, type PlatformDef, type PlatformInstance, type PlatformMessage, type PlatformProviderConfig, type PlatformRuntime, type PlatformSpace, type PlatformStatus, type PlatformUser, type PlatformsData, type Poll, type PollChoice, type PollChoiceInput, type PollOption, type ProjectData, type ProjectProfile, type ProviderMessage, type Reaction, type ReactionBuilder, type Read, type RemoveMember, type Rename, type Reply, type Richlink, type SchemaMessage, type SharedTokenData, type SlackTeamMeta, type SlackTokenData, type Space, type SpaceNamespace, Spectrum, SpectrumCloudError, type SpectrumInstance, type Store, type StreamText, type StreamTextSource, type SubscriptionData, type SubscriptionStatus, type TextStreamOptions, type TokenData, type Typing, type Unsend, UnsupportedError, type UnsupportedKind, type User, type Voice, type WebhookHandler, type WebhookRawRequest, type WebhookRawResult, addMember, app, appLayoutSchema, attachment, avatar, broadcast, cloud, contact, custom, definePlatform, edit, fromVCard, fusor, fusorEvent, group, isFusorClient, isFusorEvent, leaveSpace, markdown, mergeStreams, option, poll, reaction, read, removeMember, rename, reply, resolveContents, richlink, stream, text, toVCard, typing, unsend, voice };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $ as avatar, A as addMemberSchema, C as reaction, D as option, F as asMarkdown, G as StreamConsumedError, H as asText, I as markdown, J as custom, K as drainStreamText, M as leaveSpaceSchema, N as removeMember, O as poll, P as removeMemberSchema, Q as toVCard, U as text, V as resolveContents, X as contact, Y as asContact, Z as fromVCard, a as contentAttrs, c as markdownToPlainText, et as avatarSchema, f as voice, g as reply, i as stream, it as attachment, j as leaveSpace, k as addMember, m as richlink, n as createAsyncQueue, o as errorAttrs, ot as fetchUrlBytes, q as asCustom, r as mergeStreams, rt as asAttachment, s as senderAttrs, st as tracedFetch, t as broadcast, u as classifyIdentifier, v as rename, x as read, y as renameSchema, z as group } from "./stream-DxI5ZiE2.js";
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import ogs from "open-graph-scraper";
|
|
4
4
|
import { createLogger, setLogLevel, setupOtel, withSpan } from "@photon-ai/otel";
|
|
@@ -161,30 +161,6 @@ function app(url) {
|
|
|
161
161
|
return { build: async () => asApp(url) };
|
|
162
162
|
}
|
|
163
163
|
//#endregion
|
|
164
|
-
//#region src/content/avatar.ts
|
|
165
|
-
/**
|
|
166
|
-
* Set or clear the chat avatar (group icon). Universal content — providers
|
|
167
|
-
* dispatch by `content.type === "avatar"` in their `send` action and decide
|
|
168
|
-
* their own support story (e.g. iMessage only supports it for remote group
|
|
169
|
-
* chats).
|
|
170
|
-
*
|
|
171
|
-
* `space.send(avatar(...))` is the canonical form; `space.avatar(...)` is
|
|
172
|
-
* universal sugar that delegates here. Per-platform constraints (e.g.
|
|
173
|
-
* group-only, remote-only) surface as `UnsupportedError` from the provider's
|
|
174
|
-
* `send` action so the canonical and sugar forms share one error path.
|
|
175
|
-
*/
|
|
176
|
-
const avatarSchema = z.object({
|
|
177
|
-
type: z.literal("avatar"),
|
|
178
|
-
action: photoActionSchema
|
|
179
|
-
});
|
|
180
|
-
function avatar(input, options) {
|
|
181
|
-
const action = buildPhotoAction(input, options, "avatar");
|
|
182
|
-
return { build: async () => avatarSchema.parse({
|
|
183
|
-
type: "avatar",
|
|
184
|
-
action
|
|
185
|
-
}) };
|
|
186
|
-
}
|
|
187
|
-
//#endregion
|
|
188
164
|
//#region src/content/edit.ts
|
|
189
165
|
const isMessage$1 = (v) => typeof v === "object" && v !== null && "id" in v && "content" in v;
|
|
190
166
|
const isContent = (v) => typeof v === "object" && v !== null && "type" in v && typeof v.type === "string";
|
|
@@ -198,7 +174,8 @@ const isContent = (v) => typeof v === "object" && v !== null && "type" in v && t
|
|
|
198
174
|
* (no new message id is produced; the existing message mutates in place).
|
|
199
175
|
*
|
|
200
176
|
* Edit cannot wrap `edit`, `reply`, `reaction`, `group`, `typing`, `rename`,
|
|
201
|
-
* `avatar`, `unsend`, or `read`
|
|
177
|
+
* `avatar`, `addMember`, `removeMember`, `leaveSpace`, `unsend`, or `read`
|
|
178
|
+
* content.
|
|
202
179
|
*/
|
|
203
180
|
const editSchema = z.object({
|
|
204
181
|
type: z.literal("edit"),
|
|
@@ -222,7 +199,7 @@ function edit(content, target) {
|
|
|
222
199
|
if (target.direction !== "outbound") throw new Error(`edit() target must be an outbound message (got direction "${target.direction}", message id "${target.id}")`);
|
|
223
200
|
const [resolved] = await resolveContents([content]);
|
|
224
201
|
if (!resolved) throw new Error("edit() requires content");
|
|
225
|
-
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") throw new Error(`edit() cannot wrap "${resolved.type}" content`);
|
|
202
|
+
if (resolved.type === "edit" || resolved.type === "reply" || resolved.type === "reaction" || resolved.type === "group" || resolved.type === "typing" || resolved.type === "rename" || resolved.type === "avatar" || resolved.type === "addMember" || resolved.type === "removeMember" || resolved.type === "leaveSpace" || resolved.type === "unsend" || resolved.type === "read") throw new Error(`edit() cannot wrap "${resolved.type}" content`);
|
|
226
203
|
return asEdit({
|
|
227
204
|
content: resolved,
|
|
228
205
|
target
|
|
@@ -230,31 +207,6 @@ function edit(content, target) {
|
|
|
230
207
|
} };
|
|
231
208
|
}
|
|
232
209
|
//#endregion
|
|
233
|
-
//#region src/content/rename.ts
|
|
234
|
-
/**
|
|
235
|
-
* Rename the current chat. Universal content — providers dispatch by
|
|
236
|
-
* `content.type === "rename"` in their `send` action and decide their own
|
|
237
|
-
* support story (e.g. iMessage only supports it for remote group chats).
|
|
238
|
-
*
|
|
239
|
-
* `space.send(rename("New Name"))` is the canonical form; `space.rename(...)`
|
|
240
|
-
* is universal sugar that delegates here.
|
|
241
|
-
*
|
|
242
|
-
* Throws at build time if `displayName` is empty. Per-platform constraints
|
|
243
|
-
* (e.g. group-only, remote-only) surface as `UnsupportedError` from the
|
|
244
|
-
* provider's `send` action so the canonical and sugar forms share one
|
|
245
|
-
* error path.
|
|
246
|
-
*/
|
|
247
|
-
const renameSchema = z.object({
|
|
248
|
-
type: z.literal("rename"),
|
|
249
|
-
displayName: z.string().min(1, "rename() displayName must be non-empty")
|
|
250
|
-
});
|
|
251
|
-
function rename(displayName) {
|
|
252
|
-
return { build: async () => renameSchema.parse({
|
|
253
|
-
type: "rename",
|
|
254
|
-
displayName
|
|
255
|
-
}) };
|
|
256
|
-
}
|
|
257
|
-
//#endregion
|
|
258
210
|
//#region src/content/typing.ts
|
|
259
211
|
/**
|
|
260
212
|
* A `typing` content value carries a typing-indicator signal — either
|
|
@@ -2344,6 +2296,9 @@ const FIRE_AND_FORGET_TYPES = new Set([
|
|
|
2344
2296
|
"edit",
|
|
2345
2297
|
"rename",
|
|
2346
2298
|
"avatar",
|
|
2299
|
+
"addMember",
|
|
2300
|
+
"removeMember",
|
|
2301
|
+
"leaveSpace",
|
|
2347
2302
|
"unsend",
|
|
2348
2303
|
"read"
|
|
2349
2304
|
]);
|
|
@@ -2356,13 +2311,22 @@ const RESERVED_SPACE_KEYS = new Set([
|
|
|
2356
2311
|
"unsend",
|
|
2357
2312
|
"read",
|
|
2358
2313
|
"getMessage",
|
|
2314
|
+
"getMembers",
|
|
2315
|
+
"getAvatar",
|
|
2359
2316
|
"rename",
|
|
2360
2317
|
"avatar",
|
|
2318
|
+
"add",
|
|
2319
|
+
"remove",
|
|
2320
|
+
"leave",
|
|
2361
2321
|
"startTyping",
|
|
2362
2322
|
"stopTyping",
|
|
2363
2323
|
"responding"
|
|
2364
2324
|
]);
|
|
2365
|
-
const PLATFORM_WISE_ACTION_KEYS = new Set([
|
|
2325
|
+
const PLATFORM_WISE_ACTION_KEYS = new Set([
|
|
2326
|
+
"getMessage",
|
|
2327
|
+
"getMembers",
|
|
2328
|
+
"getAvatar"
|
|
2329
|
+
]);
|
|
2366
2330
|
const RESERVED_MESSAGE_KEYS = new Set([
|
|
2367
2331
|
"content",
|
|
2368
2332
|
"direction",
|
|
@@ -2691,6 +2655,38 @@ function buildSpace(params) {
|
|
|
2691
2655
|
}, "inbound");
|
|
2692
2656
|
});
|
|
2693
2657
|
}
|
|
2658
|
+
async function getMembersImpl() {
|
|
2659
|
+
const getMembers = definition.actions?.getMembers;
|
|
2660
|
+
if (!getMembers) throw UnsupportedError.action("getMembers", definition.name);
|
|
2661
|
+
return withSpan("spectrum.space.members.get", {
|
|
2662
|
+
"spectrum.provider": definition.name,
|
|
2663
|
+
"spectrum.space.id": spaceRef.id
|
|
2664
|
+
}, async () => {
|
|
2665
|
+
const raw = await getMembers({
|
|
2666
|
+
client,
|
|
2667
|
+
config,
|
|
2668
|
+
store
|
|
2669
|
+
}, spaceRef);
|
|
2670
|
+
if (!Array.isArray(raw)) throw new Error(`${definition.name} getMembers() must resolve an array of member records (got ${raw === null ? "null" : typeof raw})`);
|
|
2671
|
+
return raw.map((member) => ({
|
|
2672
|
+
...member,
|
|
2673
|
+
id: member.id,
|
|
2674
|
+
__platform: definition.name
|
|
2675
|
+
}));
|
|
2676
|
+
});
|
|
2677
|
+
}
|
|
2678
|
+
async function getAvatarImpl() {
|
|
2679
|
+
const getAvatar = definition.actions?.getAvatar;
|
|
2680
|
+
if (!getAvatar) throw UnsupportedError.action("getAvatar", definition.name);
|
|
2681
|
+
return withSpan("spectrum.space.avatar.get", {
|
|
2682
|
+
"spectrum.provider": definition.name,
|
|
2683
|
+
"spectrum.space.id": spaceRef.id
|
|
2684
|
+
}, async () => await getAvatar({
|
|
2685
|
+
client,
|
|
2686
|
+
config,
|
|
2687
|
+
store
|
|
2688
|
+
}, spaceRef));
|
|
2689
|
+
}
|
|
2694
2690
|
const platformActions = {};
|
|
2695
2691
|
const declaredActions = definition.space.actions;
|
|
2696
2692
|
if (declaredActions) for (const [name, factory] of Object.entries(declaredActions)) {
|
|
@@ -2717,6 +2713,8 @@ function buildSpace(params) {
|
|
|
2717
2713
|
await space.send(read(message));
|
|
2718
2714
|
},
|
|
2719
2715
|
getMessage: getMessageImpl,
|
|
2716
|
+
getMembers: getMembersImpl,
|
|
2717
|
+
getAvatar: getAvatarImpl,
|
|
2720
2718
|
rename: async (displayName) => {
|
|
2721
2719
|
await space.send(rename(displayName));
|
|
2722
2720
|
},
|
|
@@ -2728,6 +2726,15 @@ function buildSpace(params) {
|
|
|
2728
2726
|
if (!options?.mimeType) throw new Error("space.avatar(Buffer) requires options.mimeType — pass { mimeType: '...' }");
|
|
2729
2727
|
await space.send(avatar(input, { mimeType: options.mimeType }));
|
|
2730
2728
|
}),
|
|
2729
|
+
add: async (users) => {
|
|
2730
|
+
await space.send(addMember(users));
|
|
2731
|
+
},
|
|
2732
|
+
remove: async (users) => {
|
|
2733
|
+
await space.send(removeMember(users));
|
|
2734
|
+
},
|
|
2735
|
+
leave: async () => {
|
|
2736
|
+
await space.send(leaveSpace());
|
|
2737
|
+
},
|
|
2731
2738
|
startTyping: async () => {
|
|
2732
2739
|
await space.send(typing("start"));
|
|
2733
2740
|
},
|
|
@@ -3020,7 +3027,7 @@ function definePlatform(name, rawDef) {
|
|
|
3020
3027
|
}
|
|
3021
3028
|
//#endregion
|
|
3022
3029
|
//#region src/build-env.ts
|
|
3023
|
-
const SPECTRUM_SDK_VERSION = "
|
|
3030
|
+
const SPECTRUM_SDK_VERSION = "9.0.0";
|
|
3024
3031
|
//#endregion
|
|
3025
3032
|
//#region src/utils/provider-packages.ts
|
|
3026
3033
|
const OFFICIAL_PROVIDER_PACKAGES = {
|
|
@@ -3780,9 +3787,41 @@ const mapContent = (content, platform, spaceRef, ctx) => {
|
|
|
3780
3787
|
case "reply": return deserializeReply(raw, platform, spaceRef, ctx);
|
|
3781
3788
|
case "group": return deserializeGroup(raw, platform, spaceRef, ctx);
|
|
3782
3789
|
case "attachment": return deserializeAttachment(raw, platform, spaceRef, ctx);
|
|
3790
|
+
case "addMember": return addMemberSchema.parse({
|
|
3791
|
+
type: "addMember",
|
|
3792
|
+
members: memberStrings(raw.members)
|
|
3793
|
+
});
|
|
3794
|
+
case "removeMember": return removeMemberSchema.parse({
|
|
3795
|
+
type: "removeMember",
|
|
3796
|
+
members: memberStrings(raw.members)
|
|
3797
|
+
});
|
|
3798
|
+
case "leaveSpace": return leaveSpaceSchema.parse({ type: "leaveSpace" });
|
|
3799
|
+
case "rename": return renameSchema.parse({
|
|
3800
|
+
type: "rename",
|
|
3801
|
+
displayName: asString(raw.displayName)
|
|
3802
|
+
});
|
|
3803
|
+
case "avatar": return deserializeAvatar(raw, platform);
|
|
3783
3804
|
default: return asCustom(content);
|
|
3784
3805
|
}
|
|
3785
3806
|
};
|
|
3807
|
+
const memberStrings = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
|
|
3808
|
+
const deserializeAvatar = (raw, platform) => {
|
|
3809
|
+
const action = isRecord(raw.action) ? raw.action : {};
|
|
3810
|
+
if (action.kind === "clear") return avatarSchema.parse({
|
|
3811
|
+
type: "avatar",
|
|
3812
|
+
action: { kind: "clear" }
|
|
3813
|
+
});
|
|
3814
|
+
if (action.kind !== "set") throw new Error(`unknown avatar action kind: ${String(action.kind)}`);
|
|
3815
|
+
const unavailable = () => Promise.reject(UnsupportedError.action("getAvatar", platform, "avatar bytes are not delivered over the Spectrum webhook — fetch the current icon via space.getAvatar()"));
|
|
3816
|
+
return avatarSchema.parse({
|
|
3817
|
+
type: "avatar",
|
|
3818
|
+
action: {
|
|
3819
|
+
kind: "set",
|
|
3820
|
+
mimeType: asString(action.mimeType) || DEFAULT_MIME_TYPE,
|
|
3821
|
+
read: unavailable
|
|
3822
|
+
}
|
|
3823
|
+
});
|
|
3824
|
+
};
|
|
3786
3825
|
const deserializeAttachment = (raw, platform, spaceRef, ctx) => {
|
|
3787
3826
|
const id = asString(raw.id);
|
|
3788
3827
|
const bytes = ctx.resolveAttachment?.(platform, spaceRef, id);
|
|
@@ -4564,4 +4603,4 @@ async function Spectrum(options) {
|
|
|
4564
4603
|
} });
|
|
4565
4604
|
}
|
|
4566
4605
|
//#endregion
|
|
4567
|
-
export { Emoji, Spectrum, SpectrumCloudError, UnsupportedError, app, appLayoutSchema, attachment, avatar, broadcast, cloud, contact, custom, definePlatform, edit, fromVCard, fusor, fusorEvent, group, isFusorClient, isFusorEvent, markdown, mergeStreams, option, poll, reaction, read, rename, reply, resolveContents, richlink, stream, text, toVCard, typing, unsend, voice };
|
|
4606
|
+
export { Emoji, Spectrum, SpectrumCloudError, UnsupportedError, addMember, app, appLayoutSchema, attachment, avatar, broadcast, cloud, contact, custom, definePlatform, edit, fromVCard, fusor, fusorEvent, group, isFusorClient, isFusorEvent, leaveSpace, markdown, mergeStreams, option, poll, reaction, read, removeMember, rename, reply, resolveContents, richlink, stream, text, toVCard, typing, unsend, voice };
|
|
@@ -202,6 +202,36 @@ const buildPhotoAction = (input, options, contentLabel) => {
|
|
|
202
202
|
};
|
|
203
203
|
};
|
|
204
204
|
//#endregion
|
|
205
|
+
//#region src/content/avatar.ts
|
|
206
|
+
/**
|
|
207
|
+
* Set or clear the chat avatar (group icon). Universal content — providers
|
|
208
|
+
* dispatch by `content.type === "avatar"` in their `send` action and decide
|
|
209
|
+
* their own support story (e.g. iMessage only supports it for remote group
|
|
210
|
+
* chats).
|
|
211
|
+
*
|
|
212
|
+
* `space.send(avatar(...))` is the canonical form; `space.avatar(...)` is
|
|
213
|
+
* universal sugar that delegates here. Per-platform constraints (e.g.
|
|
214
|
+
* group-only, remote-only) surface as `UnsupportedError` from the provider's
|
|
215
|
+
* `send` action so the canonical and sugar forms share one error path.
|
|
216
|
+
*
|
|
217
|
+
* Bidirectional: providers also surface platform icon changes as inbound
|
|
218
|
+
* `Message`s carrying this content — `action.kind === "set"` arrives with
|
|
219
|
+
* the fetched icon behind `read()`, `"clear"` mirrors icon removal.
|
|
220
|
+
* `message.sender` is the user who changed it (may be `undefined` when the
|
|
221
|
+
* platform recorded no actor).
|
|
222
|
+
*/
|
|
223
|
+
const avatarSchema = z.object({
|
|
224
|
+
type: z.literal("avatar"),
|
|
225
|
+
action: photoActionSchema
|
|
226
|
+
});
|
|
227
|
+
function avatar(input, options) {
|
|
228
|
+
const action = buildPhotoAction(input, options, "avatar");
|
|
229
|
+
return { build: async () => avatarSchema.parse({
|
|
230
|
+
type: "avatar",
|
|
231
|
+
action
|
|
232
|
+
}) };
|
|
233
|
+
}
|
|
234
|
+
//#endregion
|
|
205
235
|
//#region src/utils/vcard.ts
|
|
206
236
|
const asPropertyArray = (prop) => {
|
|
207
237
|
if (!prop) return [];
|
|
@@ -758,6 +788,68 @@ function markdown(source, options) {
|
|
|
758
788
|
return streamTextBuilder("markdown", source, options);
|
|
759
789
|
}
|
|
760
790
|
//#endregion
|
|
791
|
+
//#region src/content/membership.ts
|
|
792
|
+
/**
|
|
793
|
+
* Group-membership management content. Universal content — providers
|
|
794
|
+
* dispatch by `content.type` in their `send` action and decide their own
|
|
795
|
+
* support story (e.g. iMessage only supports it for remote group chats;
|
|
796
|
+
* on a DM it surfaces an `UnsupportedError` telling the caller to create
|
|
797
|
+
* a group via `space.create` instead).
|
|
798
|
+
*
|
|
799
|
+
* `space.send(addMember(users))` is the canonical form; `space.add(...)`,
|
|
800
|
+
* `space.remove(...)`, and `space.leave()` are universal sugar that
|
|
801
|
+
* delegate here. All three are fire-and-forget — no `Message` is produced.
|
|
802
|
+
*
|
|
803
|
+
* Bidirectional: providers also surface platform membership events as
|
|
804
|
+
* inbound `Message`s carrying this content. `message.sender` is the acting
|
|
805
|
+
* user — who added/removed the members — and may be `undefined` when the
|
|
806
|
+
* platform recorded no actor. For `leaveSpace` the sender is the leaver
|
|
807
|
+
* (the content carries no `members`). The agent's own actions are
|
|
808
|
+
* suppressed: `space.add(...)` does not echo back as an inbound event.
|
|
809
|
+
*
|
|
810
|
+
* Members are id strings (or `User`s, normalized to their `id`) in the same
|
|
811
|
+
* platform handle format `space.create` accepts. No async resolution happens
|
|
812
|
+
* in the builder — ids reach the provider verbatim.
|
|
813
|
+
*/
|
|
814
|
+
const addMemberSchema = z.object({
|
|
815
|
+
type: z.literal("addMember"),
|
|
816
|
+
members: z.array(z.string()).min(1, "addMember() requires at least one member")
|
|
817
|
+
});
|
|
818
|
+
const removeMemberSchema = z.object({
|
|
819
|
+
type: z.literal("removeMember"),
|
|
820
|
+
members: z.array(z.string()).min(1, "removeMember() requires at least one member")
|
|
821
|
+
});
|
|
822
|
+
const leaveSpaceSchema = z.object({ type: z.literal("leaveSpace") });
|
|
823
|
+
const toMemberIds = (users) => (Array.isArray(users) ? users : [users]).map((u) => typeof u === "string" ? u : u.id);
|
|
824
|
+
/**
|
|
825
|
+
* Build an `AddMember` content value inviting `users` into the current
|
|
826
|
+
* group chat. Accepts a single `User` or id string, or an array of either
|
|
827
|
+
* — batches land in one provider call.
|
|
828
|
+
*/
|
|
829
|
+
function addMember(users) {
|
|
830
|
+
return { build: async () => addMemberSchema.parse({
|
|
831
|
+
type: "addMember",
|
|
832
|
+
members: toMemberIds(users)
|
|
833
|
+
}) };
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* Build a `RemoveMember` content value removing `users` from the current
|
|
837
|
+
* group chat. Accepts the same input shapes as `addMember`.
|
|
838
|
+
*/
|
|
839
|
+
function removeMember(users) {
|
|
840
|
+
return { build: async () => removeMemberSchema.parse({
|
|
841
|
+
type: "removeMember",
|
|
842
|
+
members: toMemberIds(users)
|
|
843
|
+
}) };
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* Build a `LeaveSpace` content value making the agent's own account leave
|
|
847
|
+
* the current group chat.
|
|
848
|
+
*/
|
|
849
|
+
function leaveSpace() {
|
|
850
|
+
return { build: async () => leaveSpaceSchema.parse({ type: "leaveSpace" }) };
|
|
851
|
+
}
|
|
852
|
+
//#endregion
|
|
761
853
|
//#region src/content/poll.ts
|
|
762
854
|
const pollChoiceSchema = z.object({ title: z.string().nonempty() });
|
|
763
855
|
const pollSchema = z.object({
|
|
@@ -891,6 +983,35 @@ function read(target) {
|
|
|
891
983
|
} };
|
|
892
984
|
}
|
|
893
985
|
//#endregion
|
|
986
|
+
//#region src/content/rename.ts
|
|
987
|
+
/**
|
|
988
|
+
* Rename the current chat. Universal content — providers dispatch by
|
|
989
|
+
* `content.type === "rename"` in their `send` action and decide their own
|
|
990
|
+
* support story (e.g. iMessage only supports it for remote group chats).
|
|
991
|
+
*
|
|
992
|
+
* `space.send(rename("New Name"))` is the canonical form; `space.rename(...)`
|
|
993
|
+
* is universal sugar that delegates here.
|
|
994
|
+
*
|
|
995
|
+
* Bidirectional: providers also surface platform rename events as inbound
|
|
996
|
+
* `Message`s carrying this content; `message.sender` is the user who renamed
|
|
997
|
+
* the chat (may be `undefined` when the platform recorded no actor).
|
|
998
|
+
*
|
|
999
|
+
* Throws at build time if `displayName` is empty. Per-platform constraints
|
|
1000
|
+
* (e.g. group-only, remote-only) surface as `UnsupportedError` from the
|
|
1001
|
+
* provider's `send` action so the canonical and sugar forms share one
|
|
1002
|
+
* error path.
|
|
1003
|
+
*/
|
|
1004
|
+
const renameSchema = z.object({
|
|
1005
|
+
type: z.literal("rename"),
|
|
1006
|
+
displayName: z.string().min(1, "rename() displayName must be non-empty")
|
|
1007
|
+
});
|
|
1008
|
+
function rename(displayName) {
|
|
1009
|
+
return { build: async () => renameSchema.parse({
|
|
1010
|
+
type: "rename",
|
|
1011
|
+
displayName
|
|
1012
|
+
}) };
|
|
1013
|
+
}
|
|
1014
|
+
//#endregion
|
|
894
1015
|
//#region src/content/reply.ts
|
|
895
1016
|
const isMessage = (v) => typeof v === "object" && v !== null && "id" in v && "content" in v;
|
|
896
1017
|
const isContent = (v) => typeof v === "object" && v !== null && "type" in v && typeof v.type === "string";
|
|
@@ -902,7 +1023,8 @@ const isContent = (v) => typeof v === "object" && v !== null && "type" in v && t
|
|
|
902
1023
|
* `reply` like any other content type and route to a threaded send.
|
|
903
1024
|
*
|
|
904
1025
|
* Reply cannot wrap `reply`, `edit`, `reaction`, `group`, `typing`,
|
|
905
|
-
* `rename`, `avatar`, `
|
|
1026
|
+
* `rename`, `avatar`, `addMember`, `removeMember`, `leaveSpace`, `unsend`,
|
|
1027
|
+
* or `read` content.
|
|
906
1028
|
*/
|
|
907
1029
|
const replySchema = z.object({
|
|
908
1030
|
type: z.literal("reply"),
|
|
@@ -918,7 +1040,7 @@ function reply(content, target) {
|
|
|
918
1040
|
if (!target) throw new Error("reply() target is undefined — the targeted message was never sent (space.send resolves undefined when a platform skips unsupported content)");
|
|
919
1041
|
const [resolved] = await resolveContents([content]);
|
|
920
1042
|
if (!resolved) throw new Error("reply() requires content");
|
|
921
|
-
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") throw new Error(`reply() cannot wrap "${resolved.type}" content`);
|
|
1043
|
+
if (resolved.type === "reply" || resolved.type === "edit" || resolved.type === "reaction" || resolved.type === "group" || resolved.type === "typing" || resolved.type === "rename" || resolved.type === "avatar" || resolved.type === "addMember" || resolved.type === "removeMember" || resolved.type === "leaveSpace" || resolved.type === "unsend" || resolved.type === "read") throw new Error(`reply() cannot wrap "${resolved.type}" content`);
|
|
922
1044
|
return asReply({
|
|
923
1045
|
content: resolved,
|
|
924
1046
|
target
|
|
@@ -1454,4 +1576,4 @@ function broadcast(source) {
|
|
|
1454
1576
|
};
|
|
1455
1577
|
}
|
|
1456
1578
|
//#endregion
|
|
1457
|
-
export {
|
|
1579
|
+
export { avatar as $, addMemberSchema as A, groupSchema as B, reaction as C, option as D, asPollOption as E, asMarkdown as F, StreamConsumedError as G, asText as H, markdown as I, custom as J, drainStreamText as K, markdownSchema as L, leaveSpaceSchema as M, removeMember as N, poll as O, removeMemberSchema as P, toVCard as Q, asGroup as R, asReaction as S, asPoll as T, text as U, resolveContents as V, textSchema as W, contact as X, asContact as Y, fromVCard as Z, replySchema as _, contentAttrs as a, attachmentSchema as at, asRead as b, markdownToPlainText as c, asVoice as d, avatarSchema as et, voice as f, reply as g, asReply as h, stream as i, attachment as it, leaveSpace as j, addMember as k, renderInlineTokens as l, richlink as m, createAsyncQueue as n, photoActionSchema as nt, errorAttrs as o, fetchUrlBytes as ot, asRichlink as p, asCustom as q, mergeStreams as r, asAttachment as rt, senderAttrs as s, tracedFetch as st, broadcast as t, buildPhotoAction as tt, classifyIdentifier as u, rename as v, reactionSchema as w, read as x, renameSchema as y, group as z };
|