spectrum-ts 1.18.0 → 2.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.
Files changed (36) hide show
  1. package/README.md +11 -1
  2. package/dist/{attachment-DfWSZS5L.d.ts → attachment-B4nSrKVd.d.ts} +1 -1
  3. package/dist/{authoring-C9uDdZ2F.d.ts → authoring-BjE5BvlO.d.ts} +2 -2
  4. package/dist/authoring.d.ts +3 -3
  5. package/dist/authoring.js +6 -3
  6. package/dist/chunk-34FQGGD7.js +34 -0
  7. package/dist/chunk-3B4QH4JG.js +35 -0
  8. package/dist/chunk-3GEJYGZK.js +84 -0
  9. package/dist/chunk-5LT5J3NR.js +695 -0
  10. package/dist/{chunk-MC6ZKFSG.js → chunk-5XEFJBN2.js} +25 -103
  11. package/dist/{chunk-JQN6CRSC.js → chunk-6BI4PFTP.js} +10 -39
  12. package/dist/{chunk-QGJFZMD5.js → chunk-6UZFVXQF.js} +17 -101
  13. package/dist/{chunk-YN6WOTBF.js → chunk-ATNAE7OR.js} +77 -7
  14. package/dist/{chunk-IPOFBAIM.js → chunk-NGC4DJIX.js} +23 -19
  15. package/dist/{chunk-5TIF3FIE.js → chunk-Q537JPTG.js} +8 -6
  16. package/dist/{chunk-5BKZJMZV.js → chunk-U3LXXT3W.js} +61 -32
  17. package/dist/chunk-U7AWXDH6.js +91 -0
  18. package/dist/{chunk-3OTECDNH.js → chunk-WXY5QP3M.js} +5 -3
  19. package/dist/index.d.ts +69 -124
  20. package/dist/index.js +350 -90
  21. package/dist/manifest.json +6 -0
  22. package/dist/providers/imessage/index.d.ts +2 -2
  23. package/dist/providers/imessage/index.js +8 -5
  24. package/dist/providers/index.d.ts +5 -2
  25. package/dist/providers/index.js +16 -8
  26. package/dist/providers/slack/index.d.ts +1 -1
  27. package/dist/providers/slack/index.js +4 -3
  28. package/dist/providers/telegram/index.d.ts +47 -0
  29. package/dist/providers/telegram/index.js +13 -0
  30. package/dist/providers/terminal/index.d.ts +17 -419
  31. package/dist/providers/terminal/index.js +5 -3
  32. package/dist/providers/whatsapp-business/index.d.ts +1 -1
  33. package/dist/providers/whatsapp-business/index.js +6 -4
  34. package/dist/types-BD0-kKyv.d.ts +82 -0
  35. package/dist/{types-DcQ5a7PK.d.ts → types-Bje8aq1k.d.ts} +34 -4
  36. package/package.json +2 -1
@@ -3,14 +3,19 @@ import {
3
3
  asVoice
4
4
  } from "./chunk-NNY6LMSC.js";
5
5
  import {
6
- asContact,
6
+ asContact
7
+ } from "./chunk-U7AWXDH6.js";
8
+ import {
9
+ stream
10
+ } from "./chunk-5XEFJBN2.js";
11
+ import {
7
12
  fromVCard,
8
13
  toVCard
9
- } from "./chunk-QGJFZMD5.js";
14
+ } from "./chunk-6UZFVXQF.js";
10
15
  import {
11
16
  UnsupportedError,
12
17
  definePlatform
13
- } from "./chunk-IPOFBAIM.js";
18
+ } from "./chunk-NGC4DJIX.js";
14
19
  import {
15
20
  asAttachment,
16
21
  asCustom,
@@ -694,7 +699,7 @@ function protocolToSpectrum(p) {
694
699
  }
695
700
  return cached;
696
701
  };
697
- const stream = async () => {
702
+ const stream2 = async () => {
698
703
  if (path) {
699
704
  const [{ createReadStream }, { Readable }] = await Promise.all([
700
705
  import("fs"),
@@ -718,7 +723,7 @@ function protocolToSpectrum(p) {
718
723
  mimeType: p.mimeType,
719
724
  size: p.size,
720
725
  read: readBytes,
721
- stream
726
+ stream: stream2
722
727
  });
723
728
  }
724
729
  return asVoice({
@@ -726,7 +731,7 @@ function protocolToSpectrum(p) {
726
731
  mimeType: p.mimeType,
727
732
  size: p.size,
728
733
  read: readBytes,
729
- stream
734
+ stream: stream2
730
735
  });
731
736
  }
732
737
  if (p.type === "contact") {
@@ -784,33 +789,57 @@ var terminal = definePlatform("Terminal", {
784
789
  return { id };
785
790
  }
786
791
  },
787
- async *messages({ client }) {
788
- for await (const evt of client.events) {
789
- if (evt.kind === "message") {
790
- const msg = evt.value;
791
- client.knownChats.add(msg.spaceId);
792
- yield {
793
- id: msg.id,
794
- content: protocolToSpectrum(msg.content),
795
- sender: { id: msg.senderId },
796
- space: { id: msg.spaceId },
797
- timestamp: parseTimestamp(msg.timestamp),
798
- // replyTo is a terminal-specific extra — agents inspect via a
799
- // cast until Spectrum's message model grows first-class support.
800
- ...msg.replyTo ? { replyTo: msg.replyTo } : {}
801
- };
802
- continue;
803
- }
804
- const r = evt.value;
805
- client.knownChats.add(r.spaceId);
806
- yield {
807
- id: `reaction:${r.messageId}:${r.reaction}:${r.timestamp}`,
808
- content: reactionContentFromProtocol(r),
809
- sender: { id: r.senderId },
810
- space: { id: r.spaceId },
811
- timestamp: parseTimestamp(r.timestamp)
792
+ // Return a ManagedStream (not a native async generator): a native generator
793
+ // parked on an in-flight `client.events.next()` cannot be force-cancelled —
794
+ // a `.return()` queues behind the pending `next()` and never reaches the
795
+ // event queue, which would deadlock `Spectrum.stop()`. Driving the queue with
796
+ // an explicit pump lets cleanup call the queue iterator's `return()` directly
797
+ // (synchronous close + drain), so the stream tears down promptly on stop()
798
+ // without waiting for destroyClient.
799
+ messages({ client }) {
800
+ return stream((emit, end) => {
801
+ const iterator = client.events[Symbol.asyncIterator]();
802
+ const pump = (async () => {
803
+ try {
804
+ let result = await iterator.next();
805
+ while (!result.done) {
806
+ const evt = result.value;
807
+ if (evt.kind === "message") {
808
+ const msg = evt.value;
809
+ client.knownChats.add(msg.spaceId);
810
+ await emit({
811
+ id: msg.id,
812
+ content: protocolToSpectrum(msg.content),
813
+ sender: { id: msg.senderId },
814
+ space: { id: msg.spaceId },
815
+ timestamp: parseTimestamp(msg.timestamp),
816
+ // replyTo is a terminal-specific extra — agents inspect via a
817
+ // cast until Spectrum's message model grows first-class support.
818
+ ...msg.replyTo ? { replyTo: msg.replyTo } : {}
819
+ });
820
+ } else {
821
+ const r = evt.value;
822
+ client.knownChats.add(r.spaceId);
823
+ await emit({
824
+ id: `reaction:${r.messageId}:${r.reaction}:${r.timestamp}`,
825
+ content: reactionContentFromProtocol(r),
826
+ sender: { id: r.senderId },
827
+ space: { id: r.spaceId },
828
+ timestamp: parseTimestamp(r.timestamp)
829
+ });
830
+ }
831
+ result = await iterator.next();
832
+ }
833
+ end();
834
+ } catch (error) {
835
+ end(error);
836
+ }
837
+ })();
838
+ return async () => {
839
+ await iterator.return?.();
840
+ await pump.catch(() => void 0);
812
841
  };
813
- }
842
+ });
814
843
  },
815
844
  send: async ({ client, content, space }) => {
816
845
  if (content.type === "reply") {
@@ -0,0 +1,91 @@
1
+ import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
2
+ import {
3
+ fromVCard
4
+ } from "./chunk-6UZFVXQF.js";
5
+ import {
6
+ readSchema
7
+ } from "./chunk-2ILTJC35.js";
8
+
9
+ // src/content/contact.ts
10
+ import vCard from "vcf";
11
+ import z from "zod";
12
+ var userRefSchema = z.object({
13
+ __platform: z.string(),
14
+ id: z.string()
15
+ });
16
+ var nameSchema = z.object({
17
+ formatted: z.string().optional(),
18
+ first: z.string().optional(),
19
+ last: z.string().optional(),
20
+ middle: z.string().optional(),
21
+ prefix: z.string().optional(),
22
+ suffix: z.string().optional()
23
+ });
24
+ var phoneTypeSchema = z.enum(["mobile", "home", "work", "other"]);
25
+ var emailTypeSchema = z.enum(["home", "work", "other"]);
26
+ var addressTypeSchema = z.enum(["home", "work", "other"]);
27
+ var phoneSchema = z.object({
28
+ value: z.string(),
29
+ type: phoneTypeSchema.optional()
30
+ });
31
+ var emailSchema = z.object({
32
+ value: z.string(),
33
+ type: emailTypeSchema.optional()
34
+ });
35
+ var addressSchema = z.object({
36
+ street: z.string().optional(),
37
+ city: z.string().optional(),
38
+ region: z.string().optional(),
39
+ postalCode: z.string().optional(),
40
+ country: z.string().optional(),
41
+ type: addressTypeSchema.optional()
42
+ });
43
+ var orgSchema = z.object({
44
+ name: z.string().optional(),
45
+ title: z.string().optional(),
46
+ department: z.string().optional()
47
+ });
48
+ var photoSchema = z.object({
49
+ mimeType: z.string(),
50
+ read: readSchema
51
+ });
52
+ var contactSchema = z.object({
53
+ type: z.literal("contact"),
54
+ user: userRefSchema.optional(),
55
+ name: nameSchema.optional(),
56
+ phones: z.array(phoneSchema).optional(),
57
+ emails: z.array(emailSchema).optional(),
58
+ addresses: z.array(addressSchema).optional(),
59
+ org: orgSchema.optional(),
60
+ urls: z.array(z.string()).optional(),
61
+ birthday: z.string().optional(),
62
+ note: z.string().optional(),
63
+ photo: photoSchema.optional(),
64
+ raw: z.unknown().optional()
65
+ });
66
+ var asContact = (input) => contactSchema.parse({ type: "contact", ...input });
67
+ var isUser = (value) => typeof value === "object" && value !== null && "__platform" in value && "id" in value && typeof value.__platform === "string" && typeof value.id === "string";
68
+ function contact(input, details) {
69
+ return {
70
+ build: async () => {
71
+ if (typeof input === "string") {
72
+ return asContact(fromVCard(input));
73
+ }
74
+ if (input instanceof vCard) {
75
+ return asContact(fromVCard(input.toString()));
76
+ }
77
+ if (isUser(input)) {
78
+ return asContact({
79
+ user: { __platform: input.__platform, id: input.id },
80
+ ...details
81
+ });
82
+ }
83
+ return asContact(input);
84
+ }
85
+ };
86
+ }
87
+
88
+ export {
89
+ asContact,
90
+ contact
91
+ };
@@ -1,13 +1,15 @@
1
1
  import { createRequire as __spectrumCreateRequire } from "node:module"; const require = __spectrumCreateRequire(import.meta.url);
2
2
  import {
3
- cloud,
3
+ cloud
4
+ } from "./chunk-3GEJYGZK.js";
5
+ import {
4
6
  mergeStreams,
5
7
  stream
6
- } from "./chunk-MC6ZKFSG.js";
8
+ } from "./chunk-5XEFJBN2.js";
7
9
  import {
8
10
  UnsupportedError,
9
11
  definePlatform
10
- } from "./chunk-IPOFBAIM.js";
12
+ } from "./chunk-NGC4DJIX.js";
11
13
  import {
12
14
  asAttachment,
13
15
  asCustom,
package/dist/index.d.ts CHANGED
@@ -1,10 +1,12 @@
1
- export { A as Attachment, a as AttachmentInput, b as attachment } from './attachment-DfWSZS5L.js';
1
+ export { A as Attachment, a as AttachmentInput, b as attachment } from './attachment-B4nSrKVd.js';
2
2
  import z__default from 'zod';
3
3
  import { P as PhotoInput } from './photo-content-BJKnqgN-.js';
4
- import { C as ContentBuilder, M as Message, U as User, b as Space, c as ContentInput, e as Content, f as ProviderMessageRecord, g as SpaceActionFn, h as MessageActionFn, i as CreateClientContext, d as Store, P as Platform, a as PlatformDef, j as ProviderMessage, E as EventProducer, I as InstanceActionFn, k as PlatformProviderConfig, l as SpectrumLike, m as CustomEventStreams, A as AgentSender, n as ProjectData } from './types-DcQ5a7PK.js';
5
- export { o as AnyPlatformDef, B as Broadcaster, p as CloudPlatform, D as DedicatedTokenData, F as FusorTokenData, q as ImessageInfoData, r as ManagedStream, s as PlatformInstance, t as PlatformMessage, u as PlatformRuntime, v as PlatformSpace, w as PlatformStatus, x as PlatformUser, y as PlatformsData, z as ProjectProfile, S as SchemaMessage, G as SharedTokenData, H as SlackTeamMeta, J as SlackTokenData, K as SpectrumCloudError, L as SubscriptionData, N as SubscriptionStatus, T as TokenData, O as broadcast, Q as cloud, R as mergeStreams, V as stream } from './types-DcQ5a7PK.js';
6
- import { C as ContactInput, a as Contact } from './authoring-C9uDdZ2F.js';
7
- export { b as ContactAddress, c as ContactDetails, d as ContactEmail, e as ContactName, f as ContactOrg, g as ContactPhone, G as Group, P as Poll, h as PollChoice, i as PollChoiceInput, j as PollOption, R as Reaction, k as Richlink, V as Voice, l as contact, m as custom, n as group, o as option, p as poll, r as reaction, q as richlink, t as text, v as voice } from './authoring-C9uDdZ2F.js';
4
+ import { C as ContentBuilder, M as Message, U as User, e as Space, h as ContentInput, i as Content, g as ProviderMessage, E as EventProducer, j as SpaceActionFn, k as MessageActionFn, I as InstanceActionFn, l as CreateClientContext, c as Store, a as PlatformDef, P as Platform, m as PlatformProviderConfig, n as SpectrumLike, o as CustomEventStreams, A as AgentSender, b as ProjectData } from './types-Bje8aq1k.js';
5
+ export { p as AnyPlatformDef, B as Broadcaster, q as CloudPlatform, D as DedicatedTokenData, F as FusorTokenData, r as ImessageInfoData, s as ManagedStream, t as PlatformInstance, u as PlatformMessage, v as PlatformRuntime, w as PlatformSpace, x as PlatformStatus, y as PlatformUser, z as PlatformsData, G as ProjectProfile, S as SchemaMessage, H as SharedTokenData, J as SlackTeamMeta, K as SlackTokenData, L as SpectrumCloudError, N as SubscriptionData, O as SubscriptionStatus, T as TokenData, Q as broadcast, R as cloud, V as mergeStreams, W as stream } from './types-Bje8aq1k.js';
6
+ import { C as ContactInput, a as Contact } from './authoring-BjE5BvlO.js';
7
+ export { b as ContactAddress, c as ContactDetails, d as ContactEmail, e as ContactName, f as ContactOrg, g as ContactPhone, G as Group, P as Poll, h as PollChoice, i as PollChoiceInput, j as PollOption, R as Reaction, k as Richlink, V as Voice, l as contact, m as custom, n as group, o as option, p as poll, r as reaction, q as richlink, t as text, v as voice } from './authoring-BjE5BvlO.js';
8
+ import { a as FusorVerify, F as FusorClient, b as FusorMessages, W as WebhookHandler, c as WebhookRawRequest, d as WebhookRawResult } from './types-BD0-kKyv.js';
9
+ export { e as FusorEvent, f as FusorMessagesCtx, g as FusorMessagesReturn, h as FusorReply, i as FusorRespond, j as FusorVerifyRequest, k as fusorEvent, l as isFusorEvent } from './types-BD0-kKyv.js';
8
10
  import 'hotscript';
9
11
  import 'vcf';
10
12
 
@@ -89,6 +91,9 @@ declare const editSchema: z__default.ZodObject<{
89
91
  read: z__default.core.$InferOuterFunctionType<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>>>;
90
92
  stream: z__default.core.$InferOuterFunctionType<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>>>;
91
93
  size?: number | undefined;
94
+ } | {
95
+ type: "streamText";
96
+ stream: () => AsyncIterable<string>;
92
97
  } | {
93
98
  type: "custom";
94
99
  raw: unknown;
@@ -221,6 +226,9 @@ declare const editSchema: z__default.ZodObject<{
221
226
  read: z__default.core.$InferOuterFunctionType<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>>>;
222
227
  stream: z__default.core.$InferOuterFunctionType<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>>>;
223
228
  size?: number | undefined;
229
+ } | {
230
+ type: "streamText";
231
+ stream: () => AsyncIterable<string>;
224
232
  } | {
225
233
  type: "custom";
226
234
  raw: unknown;
@@ -398,6 +406,9 @@ declare const replySchema: z__default.ZodObject<{
398
406
  read: z__default.core.$InferOuterFunctionType<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>>>;
399
407
  stream: z__default.core.$InferOuterFunctionType<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>>>;
400
408
  size?: number | undefined;
409
+ } | {
410
+ type: "streamText";
411
+ stream: () => AsyncIterable<string>;
401
412
  } | {
402
413
  type: "custom";
403
414
  raw: unknown;
@@ -530,6 +541,9 @@ declare const replySchema: z__default.ZodObject<{
530
541
  read: z__default.core.$InferOuterFunctionType<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>>>;
531
542
  stream: z__default.core.$InferOuterFunctionType<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>>>;
532
543
  size?: number | undefined;
544
+ } | {
545
+ type: "streamText";
546
+ stream: () => AsyncIterable<string>;
533
547
  } | {
534
548
  type: "custom";
535
549
  raw: unknown;
@@ -650,6 +664,49 @@ declare function reply(content: ContentInput, target: Message): ContentBuilder;
650
664
 
651
665
  declare const resolveContents: (items: readonly ContentInput[]) => Promise<Content[]>;
652
666
 
667
+ /**
668
+ * Maps one chunk emitted by a stream to the incremental text it carries.
669
+ * Return a string to emit, or `null`/`undefined` to skip the chunk (e.g. for
670
+ * control events that carry no text).
671
+ */
672
+ type DeltaExtractor<T> = (chunk: T) => string | null | undefined;
673
+ /**
674
+ * Anything `streamText()` accepts as a source. The builder normalizes all of
675
+ * these to an internal `AsyncIterable<string>` of text deltas:
676
+ *
677
+ * - the Vercel AI SDK `streamText()` result (its `.textStream` is picked up
678
+ * automatically — pass either the whole result or `.textStream` directly),
679
+ * - a raw `AsyncIterable<T>` (e.g. an OpenAI / Anthropic streaming response),
680
+ * - a raw `ReadableStream<T>` of chunks.
681
+ */
682
+ type StreamTextSource<T = unknown> = {
683
+ textStream: AsyncIterable<string> | ReadableStream<string>;
684
+ } | AsyncIterable<T> | ReadableStream<T>;
685
+ interface StreamTextOptions<T = unknown> {
686
+ /**
687
+ * Map each chunk to its incremental text. Omit to rely on built-in
688
+ * auto-detection of the common SDK shapes (OpenAI chat/responses, Anthropic
689
+ * messages, AI SDK text streams, and plain strings).
690
+ */
691
+ extract?: DeltaExtractor<T>;
692
+ }
693
+ declare const streamTextSchema: z__default.ZodObject<{
694
+ type: z__default.ZodLiteral<"streamText">;
695
+ stream: z__default.ZodCustom<() => AsyncIterable<string>, () => AsyncIterable<string>>;
696
+ }, z__default.core.$strip>;
697
+ type StreamText = z__default.infer<typeof streamTextSchema>;
698
+ /**
699
+ * Wrap a streaming LLM text response so it can be sent like any other content.
700
+ *
701
+ * Delivery is platform-specific — iMessage (remote) sends the first chunk as a
702
+ * real message and then edits it in place as more text arrives. Platforms that
703
+ * can't stream reject it (the send is warn-and-skipped).
704
+ *
705
+ * Accepts whatever the popular SDKs return; pass `options.extract` for any
706
+ * chunk shape the built-in detection doesn't recognize.
707
+ */
708
+ declare function streamText<T = unknown>(source: StreamTextSource<T>, options?: StreamTextOptions<T>): ContentBuilder;
709
+
653
710
  /**
654
711
  * A `typing` content value carries a typing-indicator signal — either
655
712
  * `"start"` or `"stop"`. Like `reaction`, it's fire-and-forget: providers
@@ -2601,66 +2658,6 @@ declare const Emoji: {
2601
2658
  };
2602
2659
  type EmojiKey = keyof typeof Emoji;
2603
2660
 
2604
- interface FusorVerifyRequest {
2605
- headers: Record<string, string>;
2606
- method: string;
2607
- path: string;
2608
- rawBody: Uint8Array;
2609
- }
2610
- type FusorVerify<TPayload = unknown> = (req: FusorVerifyRequest) => TPayload | Promise<TPayload>;
2611
- interface FusorReply {
2612
- body?: string | Uint8Array;
2613
- headers?: Record<string, string>;
2614
- status?: number;
2615
- }
2616
- type FusorRespond = (reply: FusorReply) => void;
2617
- interface FusorMessagesCtx<TPayload> {
2618
- payload: TPayload;
2619
- respond: FusorRespond;
2620
- }
2621
- type FusorMessagesReturn = ProviderMessageRecord | ProviderMessageRecord[] | undefined;
2622
- type FusorMessages<TPayload> = (ctx: FusorMessagesCtx<TPayload>) => FusorMessagesReturn | Promise<FusorMessagesReturn>;
2623
- declare const FUSOR_BRAND: unique symbol;
2624
- interface FusorClient<TPayload = unknown> {
2625
- readonly platform: string;
2626
- readonly verify: FusorVerify<TPayload>;
2627
- readonly [FUSOR_BRAND]: true;
2628
- }
2629
- /**
2630
- * Request-scoped handler invoked once per inbound message that
2631
- * `spectrum.webhook()` resolves. Receives the same fully-built `[space,
2632
- * message]` pair that `spectrum.messages` yields.
2633
- *
2634
- * Runs **fire-and-forget**: it is dispatched after the HTTP response (the
2635
- * platform's `respond()` reply) has already been computed, so its outcome never
2636
- * affects the response, and a throw is caught + logged rather than surfaced —
2637
- * mirroring the body of a `for await (… of spectrum.messages)` loop.
2638
- *
2639
- * On a long-running server the event loop keeps the handler alive. On
2640
- * serverless/edge runtimes the function may be frozen once the response is
2641
- * returned, so keeping background work alive is the caller's responsibility —
2642
- * the usual pattern is to enqueue the work and process it in a separate worker.
2643
- */
2644
- type WebhookHandler = (space: Space, message: Message) => void | Promise<void>;
2645
- /**
2646
- * Raw webhook input for HTTP servers without Web `Request`/`Response` (Express,
2647
- * raw Node). `body` MUST be the exact bytes fusor POSTed — never a re-encoded
2648
- * JSON/text body — so the protobuf decode works. `headers` are accepted (so the
2649
- * natural `{ headers: req.headers, body: req.body }` shape keeps working) but are
2650
- * not read: inbound authenticity is established by the per-platform `verify()`,
2651
- * which reads the inner request reconstructed from the envelope.
2652
- */
2653
- interface WebhookRawRequest {
2654
- body: Uint8Array | ArrayBuffer;
2655
- headers?: Record<string, string>;
2656
- }
2657
- /** Raw webhook result, written back by the caller as the HTTP response. */
2658
- interface WebhookRawResult {
2659
- body: Uint8Array;
2660
- headers: Record<string, string>;
2661
- status: number;
2662
- }
2663
-
2664
2661
  declare function fusor<TPayload>(platform: string, verify: FusorVerify<TPayload>): FusorClient<TPayload>;
2665
2662
  declare function isFusorClient(value: unknown): value is FusorClient;
2666
2663
 
@@ -2682,12 +2679,13 @@ declare function definePlatform<_Name extends string, _ConfigSchema extends z__d
2682
2679
  } & Omit<PlatformDef<_Name, _ConfigSchema, _UserSchema, _SpaceSchema, _SpaceParamsSchema, _Client, _ResolvedUser, _ResolvedSpace, _MessageSchema, _MessageType, _Events, _SpaceActions, _MessageActions, _Actions>, "lifecycle" | "name"> & {
2683
2680
  static?: _Static;
2684
2681
  }): Platform<PlatformDef<_Name, _ConfigSchema, _UserSchema, _SpaceSchema, _SpaceParamsSchema, _Client, _ResolvedUser, _ResolvedSpace, _MessageSchema, _MessageType, _Events, _SpaceActions, _MessageActions, _Actions>> & Readonly<_Static>;
2685
- declare function defineFusorPlatform<_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, _TPayload, _ResolvedUser extends {
2682
+ 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, _TPayload, _ResolvedUser extends {
2686
2683
  id: string;
2687
2684
  }, _ResolvedSpace extends {
2688
2685
  id: string;
2689
- }, _MessageSchema extends z__default.ZodType<object> | undefined = undefined, _Static extends Record<string, unknown> = Record<never, never>, _SpaceActions extends Record<string, SpaceActionFn> = Record<never, never>, _MessageActions extends Record<string, MessageActionFn> = Record<never, never>>(name: _Name, def: {
2690
- config: _ConfigSchema;
2686
+ }, _MessageSchema extends z__default.ZodType<object> | undefined = undefined, _FusorEvents extends (Record<string, z__default.ZodType<object>> & {
2687
+ messages?: never;
2688
+ }) | undefined = undefined, _Static extends Record<string, unknown> = Record<never, never>, _SpaceActions extends Record<string, SpaceActionFn> = Record<never, never>, _MessageActions extends Record<string, MessageActionFn> = Record<never, never>>(name: _Name, def: Omit<PlatformDef<_Name, _ConfigSchema, _UserSchema, _SpaceSchema, _SpaceParamsSchema, FusorClient<_TPayload>, _ResolvedUser, _ResolvedSpace, _MessageSchema, ProviderMessage<_ResolvedUser, _ResolvedSpace, _MessageSchema extends z__default.ZodType<object> ? z__default.infer<_MessageSchema> : Record<never, never>>, _FusorEvents, _SpaceActions, _MessageActions>, "lifecycle" | "name" | "messages"> & {
2691
2689
  lifecycle: {
2692
2690
  createClient: (ctx: CreateClientContext<_ConfigSchema>) => Promise<FusorClient<_TPayload>>;
2693
2691
  destroyClient?: (ctx: {
@@ -2695,62 +2693,9 @@ declare function defineFusorPlatform<_Name extends string, _ConfigSchema extends
2695
2693
  store: Store;
2696
2694
  }) => Promise<void>;
2697
2695
  };
2698
- user: {
2699
- schema?: _UserSchema;
2700
- resolve: (_: {
2701
- input: {
2702
- userID: string;
2703
- };
2704
- client: FusorClient<_TPayload>;
2705
- config: z__default.infer<_ConfigSchema>;
2706
- store: Store;
2707
- }) => Promise<_ResolvedUser>;
2708
- };
2709
- space: {
2710
- schema?: _SpaceSchema;
2711
- params?: _SpaceParamsSchema;
2712
- resolve: (_: {
2713
- input: {
2714
- users: (_ResolvedUser & {
2715
- __platform: _Name;
2716
- })[];
2717
- params?: _SpaceParamsSchema extends z__default.ZodType<object> ? z__default.infer<_SpaceParamsSchema> : undefined;
2718
- };
2719
- client: FusorClient<_TPayload>;
2720
- config: z__default.infer<_ConfigSchema>;
2721
- store: Store;
2722
- }) => Promise<_ResolvedSpace>;
2723
- actions?: _SpaceActions;
2724
- };
2725
- message?: {
2726
- schema?: _MessageSchema;
2727
- actions?: _MessageActions;
2728
- };
2729
- messages: FusorMessages<_TPayload>;
2730
- send: (_: {
2731
- space: _ResolvedSpace & {
2732
- id: string;
2733
- __platform: _Name;
2734
- };
2735
- content: Content;
2736
- client: FusorClient<_TPayload>;
2737
- config: z__default.infer<_ConfigSchema>;
2738
- store: Store;
2739
- }) => Promise<ProviderMessageRecord | undefined>;
2740
- actions?: {
2741
- getMessage?: (_: {
2742
- space: _ResolvedSpace & {
2743
- id: string;
2744
- __platform: _Name;
2745
- };
2746
- messageId: string;
2747
- client: FusorClient<_TPayload>;
2748
- config: z__default.infer<_ConfigSchema>;
2749
- store: Store;
2750
- }) => Promise<unknown>;
2751
- };
2696
+ messages: FusorMessages<_TPayload, z__default.infer<_ConfigSchema>>;
2752
2697
  static?: _Static;
2753
- }): Platform<PlatformDef<_Name, _ConfigSchema, _UserSchema, _SpaceSchema, _SpaceParamsSchema, FusorClient<_TPayload>, _ResolvedUser, _ResolvedSpace, _MessageSchema, ProviderMessage<_ResolvedUser, _ResolvedSpace, _MessageSchema extends z__default.ZodType<object> ? z__default.infer<_MessageSchema> : Record<never, never>>, undefined, _SpaceActions, _MessageActions>> & Readonly<_Static>;
2698
+ }): Platform<PlatformDef<_Name, _ConfigSchema, _UserSchema, _SpaceSchema, _SpaceParamsSchema, FusorClient<_TPayload>, _ResolvedUser, _ResolvedSpace, _MessageSchema, ProviderMessage<_ResolvedUser, _ResolvedSpace, _MessageSchema extends z__default.ZodType<object> ? z__default.infer<_MessageSchema> : Record<never, never>>, _FusorEvents, _SpaceActions, _MessageActions>> & Readonly<_Static>;
2754
2699
 
2755
2700
  type SpectrumInstance<Providers extends PlatformProviderConfig[] = PlatformProviderConfig[]> = SpectrumLike<Providers> & CustomEventStreams<Providers> & {
2756
2701
  readonly messages: AsyncIterable<[Space, Message]>;
@@ -2837,4 +2782,4 @@ declare class UnsupportedError extends Error {
2837
2782
  declare const fromVCard: (vcf: string) => ContactInput;
2838
2783
  declare const toVCard: (contact: Contact) => Promise<string>;
2839
2784
 
2840
- export { AgentSender, type Avatar, type AvatarInput, Contact, ContactInput, Content, ContentBuilder, ContentInput, type Edit, Emoji, type EmojiKey, EventProducer, type FusorClient, type FusorMessages, type FusorMessagesCtx, type FusorMessagesReturn, type FusorReply, type FusorRespond, type FusorVerify, type FusorVerifyRequest, Message, Platform, PlatformDef, PlatformProviderConfig, ProjectData, ProviderMessage, type Rename, type Reply, Space, Spectrum, type SpectrumInstance, type Typing, UnsupportedError, type UnsupportedKind, User, type WebhookHandler, type WebhookRawRequest, type WebhookRawResult, avatar, defineFusorPlatform, definePlatform, edit, fromVCard, fusor, isFusorClient, rename, reply, resolveContents, toVCard, typing };
2785
+ export { AgentSender, type Avatar, type AvatarInput, Contact, ContactInput, Content, ContentBuilder, ContentInput, type DeltaExtractor, type Edit, Emoji, type EmojiKey, EventProducer, FusorClient, FusorMessages, FusorVerify, Message, Platform, PlatformDef, PlatformProviderConfig, ProjectData, ProviderMessage, type Rename, type Reply, Space, Spectrum, type SpectrumInstance, type StreamText, type StreamTextOptions, type StreamTextSource, type Typing, UnsupportedError, type UnsupportedKind, User, WebhookHandler, WebhookRawRequest, WebhookRawResult, avatar, definePlatform, edit, fromVCard, fusor, isFusorClient, rename, reply, resolveContents, streamText, toVCard, typing };