spectrum-ts 1.7.2 → 1.9.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/{chunk-VO43HJ5B.js → chunk-5NHNMN4H.js} +1 -1
- package/dist/{chunk-2SB6VN7J.js → chunk-N3ZKMTSG.js} +2 -2
- package/dist/{chunk-ZDNX3S3H.js → chunk-OM5VSKWD.js} +2 -2
- package/dist/{chunk-ET42EGIA.js → chunk-OR3VGVML.js} +1 -1
- package/dist/{chunk-VVXMZYDH.js → chunk-TN54TDTQ.js} +1 -1
- package/dist/{chunk-JWWIFSI7.js → chunk-XZSBR26X.js} +261 -89
- package/dist/index.d.ts +2 -0
- package/dist/index.js +155 -59
- package/dist/providers/imessage/index.js +3 -3
- package/dist/providers/index.js +6 -6
- package/dist/providers/terminal/index.js +3 -3
- package/dist/providers/whatsapp-business/index.js +2 -2
- package/package.json +2 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
asVoice
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-TN54TDTQ.js";
|
|
4
4
|
import {
|
|
5
5
|
UnsupportedError,
|
|
6
6
|
asAttachment,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
fromVCard,
|
|
11
11
|
reactionSchema,
|
|
12
12
|
toVCard
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-XZSBR26X.js";
|
|
14
14
|
|
|
15
15
|
// src/providers/terminal/index.ts
|
|
16
16
|
import { spawn } from "child_process";
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
asGroup,
|
|
3
3
|
asRichlink,
|
|
4
4
|
groupSchema
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-5NHNMN4H.js";
|
|
6
6
|
import {
|
|
7
7
|
asPoll,
|
|
8
8
|
asPollOption,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
text,
|
|
25
25
|
textSchema,
|
|
26
26
|
toVCard
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-XZSBR26X.js";
|
|
28
28
|
|
|
29
29
|
// src/providers/imessage/index.ts
|
|
30
30
|
import { createClient as createClient2, MessageEffect as MessageEffect2 } from "@photon-ai/advanced-imessage";
|
|
@@ -710,7 +710,125 @@ var UnsupportedError = class _UnsupportedError extends Error {
|
|
|
710
710
|
}
|
|
711
711
|
};
|
|
712
712
|
|
|
713
|
+
// src/platform/define.ts
|
|
714
|
+
import { withSpan as withSpan2 } from "@photon-ai/otel";
|
|
715
|
+
|
|
716
|
+
// src/utils/identifier.ts
|
|
717
|
+
import { sanitizeEmail, sanitizePhone } from "@photon-ai/otel";
|
|
718
|
+
var PHONE_LIKE = /^\+?[\d\s()\-.]{7,}$/;
|
|
719
|
+
var EMAIL_LIKE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
720
|
+
function classifyIdentifier(s) {
|
|
721
|
+
if (EMAIL_LIKE.test(s)) {
|
|
722
|
+
return { kind: "email", identifier: sanitizeEmail(s) };
|
|
723
|
+
}
|
|
724
|
+
if (PHONE_LIKE.test(s) && s.replace(/\D/g, "").length >= 7) {
|
|
725
|
+
return { kind: "phone", identifier: sanitizePhone(s) };
|
|
726
|
+
}
|
|
727
|
+
return { kind: "unknown", identifier: s };
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
// src/platform/build.ts
|
|
731
|
+
import { createLogger, withSpan } from "@photon-ai/otel";
|
|
732
|
+
|
|
733
|
+
// src/utils/telemetry.ts
|
|
734
|
+
var targetId = (target) => {
|
|
735
|
+
const id = target?.id;
|
|
736
|
+
return typeof id === "string" ? id : void 0;
|
|
737
|
+
};
|
|
738
|
+
var targetType = (target) => {
|
|
739
|
+
const type = target?.content?.type;
|
|
740
|
+
return typeof type === "string" ? type : void 0;
|
|
741
|
+
};
|
|
742
|
+
var replyOrEditAttrs = (content) => {
|
|
743
|
+
const target = content.target;
|
|
744
|
+
const inner = content.content;
|
|
745
|
+
const innerType = inner?.type;
|
|
746
|
+
return {
|
|
747
|
+
"spectrum.message.content.target.id": targetId(target),
|
|
748
|
+
"spectrum.message.content.target.type": targetType(target),
|
|
749
|
+
"spectrum.message.content.inner.type": typeof innerType === "string" ? innerType : void 0
|
|
750
|
+
};
|
|
751
|
+
};
|
|
752
|
+
var reactionAttrs = (content) => {
|
|
753
|
+
const target = content.target;
|
|
754
|
+
const emoji = content.emoji;
|
|
755
|
+
return {
|
|
756
|
+
"spectrum.message.content.target.id": targetId(target),
|
|
757
|
+
"spectrum.message.content.reaction.emoji": typeof emoji === "string" ? emoji : void 0
|
|
758
|
+
};
|
|
759
|
+
};
|
|
760
|
+
var groupAttrs = (content) => {
|
|
761
|
+
const items = content.items;
|
|
762
|
+
if (!Array.isArray(items)) {
|
|
763
|
+
return {};
|
|
764
|
+
}
|
|
765
|
+
const types = items.map((item) => {
|
|
766
|
+
const itemType = item?.content?.type;
|
|
767
|
+
return typeof itemType === "string" ? itemType : void 0;
|
|
768
|
+
}).filter((t) => t !== void 0);
|
|
769
|
+
return {
|
|
770
|
+
"spectrum.message.content.items.count": items.length,
|
|
771
|
+
"spectrum.message.content.items.types": types.length > 0 ? types.join(",") : void 0
|
|
772
|
+
};
|
|
773
|
+
};
|
|
774
|
+
var typingAttrs = (content) => {
|
|
775
|
+
const state = content.state;
|
|
776
|
+
return {
|
|
777
|
+
"spectrum.message.content.typing.state": typeof state === "string" ? state : void 0
|
|
778
|
+
};
|
|
779
|
+
};
|
|
780
|
+
var attachmentAttrs = (content) => {
|
|
781
|
+
const mime = content.mimeType;
|
|
782
|
+
const size = content.size;
|
|
783
|
+
return {
|
|
784
|
+
"spectrum.message.content.attachment.mime": typeof mime === "string" ? mime : void 0,
|
|
785
|
+
"spectrum.message.content.attachment.size": typeof size === "number" ? size : void 0
|
|
786
|
+
};
|
|
787
|
+
};
|
|
788
|
+
var voiceAttrs = (content) => {
|
|
789
|
+
const mime = content.mimeType;
|
|
790
|
+
const duration = content.duration;
|
|
791
|
+
const size = content.size;
|
|
792
|
+
return {
|
|
793
|
+
"spectrum.message.content.voice.mime": typeof mime === "string" ? mime : void 0,
|
|
794
|
+
"spectrum.message.content.voice.duration": typeof duration === "number" ? duration : void 0,
|
|
795
|
+
"spectrum.message.content.voice.size": typeof size === "number" ? size : void 0
|
|
796
|
+
};
|
|
797
|
+
};
|
|
798
|
+
var CONTENT_ATTR_HANDLERS = {
|
|
799
|
+
reply: replyOrEditAttrs,
|
|
800
|
+
edit: replyOrEditAttrs,
|
|
801
|
+
reaction: reactionAttrs,
|
|
802
|
+
group: groupAttrs,
|
|
803
|
+
typing: typingAttrs,
|
|
804
|
+
attachment: attachmentAttrs,
|
|
805
|
+
voice: voiceAttrs
|
|
806
|
+
};
|
|
807
|
+
function contentAttrs(content) {
|
|
808
|
+
const type = content?.type;
|
|
809
|
+
if (!(content && type)) {
|
|
810
|
+
return { "spectrum.message.content.type": void 0 };
|
|
811
|
+
}
|
|
812
|
+
const handler = CONTENT_ATTR_HANDLERS[type];
|
|
813
|
+
return {
|
|
814
|
+
"spectrum.message.content.type": type,
|
|
815
|
+
...handler ? handler(content) : {}
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
function senderAttrs(sender) {
|
|
819
|
+
const id = sender?.id;
|
|
820
|
+
if (typeof id !== "string" || id.length === 0) {
|
|
821
|
+
return {};
|
|
822
|
+
}
|
|
823
|
+
const { kind, identifier } = classifyIdentifier(id);
|
|
824
|
+
return {
|
|
825
|
+
"spectrum.message.sender.id": identifier,
|
|
826
|
+
"spectrum.message.sender.kind": kind
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
|
|
713
830
|
// src/platform/build.ts
|
|
831
|
+
var platformLog = createLogger("spectrum.platform");
|
|
714
832
|
var ANSI_YELLOW = "\x1B[33m";
|
|
715
833
|
var ANSI_RESET = "\x1B[0m";
|
|
716
834
|
var supportsAnsiColor = () => {
|
|
@@ -752,9 +870,14 @@ var warnUnsupported = (err, fallbackPlatform) => {
|
|
|
752
870
|
const platform = err.platform ?? fallbackPlatform;
|
|
753
871
|
const subject = err.kind === "content" ? `content type "${err.contentType ?? "unknown"}"` : `action "${err.action ?? "unknown"}"`;
|
|
754
872
|
const detail = err.detail ? `: ${err.detail}` : "";
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
873
|
+
platformLog.warn(
|
|
874
|
+
`${platform} does not support ${subject}${detail}; skipping.`,
|
|
875
|
+
{
|
|
876
|
+
"spectrum.provider": platform,
|
|
877
|
+
"spectrum.unsupported.kind": err.kind,
|
|
878
|
+
"spectrum.unsupported.content_type": err.contentType,
|
|
879
|
+
"spectrum.unsupported.action": err.action
|
|
880
|
+
}
|
|
758
881
|
);
|
|
759
882
|
};
|
|
760
883
|
var contentPlatform = (content) => {
|
|
@@ -879,38 +1002,49 @@ function buildSpace(params) {
|
|
|
879
1002
|
const { spaceRef, extras, actionCtx, definition, client, config, store } = params;
|
|
880
1003
|
let space;
|
|
881
1004
|
async function dispatchSend(item) {
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
1005
|
+
return withSpan(
|
|
1006
|
+
"spectrum.message.send",
|
|
1007
|
+
{
|
|
1008
|
+
"spectrum.provider": definition.name,
|
|
1009
|
+
"spectrum.space.id": spaceRef.id,
|
|
1010
|
+
"spectrum.message.fire_and_forget": isFireAndForget(item),
|
|
1011
|
+
...contentAttrs(item)
|
|
1012
|
+
},
|
|
1013
|
+
async () => {
|
|
1014
|
+
let raw;
|
|
1015
|
+
try {
|
|
1016
|
+
const platformError = unsupportedPlatformContentError(
|
|
1017
|
+
item,
|
|
1018
|
+
definition.name
|
|
1019
|
+
);
|
|
1020
|
+
if (platformError) {
|
|
1021
|
+
throw platformError;
|
|
1022
|
+
}
|
|
1023
|
+
raw = await definition.send({
|
|
1024
|
+
...actionCtx,
|
|
1025
|
+
content: item
|
|
1026
|
+
});
|
|
1027
|
+
} catch (err) {
|
|
1028
|
+
if (err instanceof UnsupportedError) {
|
|
1029
|
+
warnUnsupported(err, definition.name);
|
|
1030
|
+
return;
|
|
1031
|
+
}
|
|
1032
|
+
throw err;
|
|
1033
|
+
}
|
|
1034
|
+
if (!raw?.id) {
|
|
1035
|
+
if (isFireAndForget(item)) {
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
throw new Error(
|
|
1039
|
+
`Platform "${definition.name}" send did not return a message id`
|
|
1040
|
+
);
|
|
1041
|
+
}
|
|
1042
|
+
return wrapProviderMessage(
|
|
1043
|
+
raw,
|
|
1044
|
+
{ client, config, definition, space, spaceRef, store },
|
|
1045
|
+
"outbound"
|
|
1046
|
+
);
|
|
905
1047
|
}
|
|
906
|
-
throw new Error(
|
|
907
|
-
`Platform "${definition.name}" send did not return a message id`
|
|
908
|
-
);
|
|
909
|
-
}
|
|
910
|
-
return wrapProviderMessage(
|
|
911
|
-
raw,
|
|
912
|
-
{ client, config, definition, space, spaceRef, store },
|
|
913
|
-
"outbound"
|
|
914
1048
|
);
|
|
915
1049
|
}
|
|
916
1050
|
async function sendImpl(...content) {
|
|
@@ -936,29 +1070,39 @@ function buildSpace(params) {
|
|
|
936
1070
|
);
|
|
937
1071
|
return;
|
|
938
1072
|
}
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
1073
|
+
return withSpan(
|
|
1074
|
+
"spectrum.message.get",
|
|
1075
|
+
{
|
|
1076
|
+
"spectrum.provider": definition.name,
|
|
1077
|
+
"spectrum.space.id": spaceRef.id,
|
|
1078
|
+
"spectrum.message.id": id
|
|
1079
|
+
},
|
|
1080
|
+
async () => {
|
|
1081
|
+
let raw;
|
|
1082
|
+
try {
|
|
1083
|
+
raw = await getMessage({
|
|
1084
|
+
space: spaceRef,
|
|
1085
|
+
messageId: id,
|
|
1086
|
+
client,
|
|
1087
|
+
config,
|
|
1088
|
+
store
|
|
1089
|
+
});
|
|
1090
|
+
} catch (err) {
|
|
1091
|
+
if (err instanceof UnsupportedError) {
|
|
1092
|
+
warnUnsupported(err, definition.name);
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
throw err;
|
|
1096
|
+
}
|
|
1097
|
+
if (!raw) {
|
|
1098
|
+
return;
|
|
1099
|
+
}
|
|
1100
|
+
return wrapProviderMessage(
|
|
1101
|
+
raw,
|
|
1102
|
+
{ client, config, definition, space, spaceRef, store },
|
|
1103
|
+
"inbound"
|
|
1104
|
+
);
|
|
952
1105
|
}
|
|
953
|
-
throw err;
|
|
954
|
-
}
|
|
955
|
-
if (!raw) {
|
|
956
|
-
return;
|
|
957
|
-
}
|
|
958
|
-
return wrapProviderMessage(
|
|
959
|
-
raw,
|
|
960
|
-
{ client, config, definition, space, spaceRef, store },
|
|
961
|
-
"inbound"
|
|
962
1106
|
);
|
|
963
1107
|
}
|
|
964
1108
|
const platformActions = {};
|
|
@@ -1057,6 +1201,21 @@ function buildMessage(params) {
|
|
|
1057
1201
|
}
|
|
1058
1202
|
|
|
1059
1203
|
// src/platform/define.ts
|
|
1204
|
+
function classifySpaceIdentifier(args) {
|
|
1205
|
+
const stringArgs = args.filter((a) => typeof a === "string");
|
|
1206
|
+
if (stringArgs.length > 1) {
|
|
1207
|
+
return { kind: "group" };
|
|
1208
|
+
}
|
|
1209
|
+
const s = stringArgs[0];
|
|
1210
|
+
if (!s) {
|
|
1211
|
+
return { kind: "unknown" };
|
|
1212
|
+
}
|
|
1213
|
+
const { kind, identifier } = classifyIdentifier(s);
|
|
1214
|
+
if (kind === "unknown") {
|
|
1215
|
+
return { kind: "unknown" };
|
|
1216
|
+
}
|
|
1217
|
+
return { kind, identifier };
|
|
1218
|
+
}
|
|
1060
1219
|
function createPlatformInstance(def, runtime) {
|
|
1061
1220
|
const isPlatformUser = (value) => typeof value === "object" && value !== null && "__platform" in value && value.__platform === def.name;
|
|
1062
1221
|
const resolveUserID = async (userID) => {
|
|
@@ -1126,39 +1285,50 @@ function createPlatformInstance(def, runtime) {
|
|
|
1126
1285
|
};
|
|
1127
1286
|
},
|
|
1128
1287
|
async space(...args) {
|
|
1129
|
-
const
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1288
|
+
const { kind, identifier } = classifySpaceIdentifier(args);
|
|
1289
|
+
return withSpan2(
|
|
1290
|
+
"spectrum.space.resolve",
|
|
1291
|
+
{
|
|
1292
|
+
"spectrum.provider": def.name,
|
|
1293
|
+
"spectrum.space.identifier_kind": kind,
|
|
1294
|
+
"spectrum.space.identifier": identifier
|
|
1295
|
+
},
|
|
1296
|
+
async () => {
|
|
1297
|
+
const convertedArgs = await resolveStringUsers(args);
|
|
1298
|
+
const { users, params } = normalizeSpaceArgs(convertedArgs);
|
|
1299
|
+
let parsedParams = params;
|
|
1300
|
+
if (params !== void 0 && def.space.params) {
|
|
1301
|
+
parsedParams = def.space.params.parse(params);
|
|
1302
|
+
}
|
|
1303
|
+
const resolved = await def.space.resolve({
|
|
1304
|
+
input: { users, params: parsedParams },
|
|
1305
|
+
client: runtime.client,
|
|
1306
|
+
config: runtime.config,
|
|
1307
|
+
store: runtime.store
|
|
1308
|
+
});
|
|
1309
|
+
const parsedSpace = def.space.schema ? def.space.schema.parse(resolved) : resolved;
|
|
1310
|
+
const spaceRef = {
|
|
1311
|
+
...parsedSpace,
|
|
1312
|
+
id: parsedSpace.id,
|
|
1313
|
+
__platform: def.name
|
|
1314
|
+
};
|
|
1315
|
+
const actionCtx = {
|
|
1316
|
+
space: spaceRef,
|
|
1317
|
+
client: runtime.client,
|
|
1318
|
+
config: runtime.config,
|
|
1319
|
+
store: runtime.store
|
|
1320
|
+
};
|
|
1321
|
+
return buildSpace({
|
|
1322
|
+
spaceRef,
|
|
1323
|
+
extras: parsedSpace,
|
|
1324
|
+
actionCtx,
|
|
1325
|
+
definition: def,
|
|
1326
|
+
client: runtime.client,
|
|
1327
|
+
config: runtime.config,
|
|
1328
|
+
store: runtime.store
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
);
|
|
1162
1332
|
}
|
|
1163
1333
|
};
|
|
1164
1334
|
const eventProperties = {};
|
|
@@ -1282,6 +1452,8 @@ export {
|
|
|
1282
1452
|
reply,
|
|
1283
1453
|
typing,
|
|
1284
1454
|
UnsupportedError,
|
|
1455
|
+
contentAttrs,
|
|
1456
|
+
senderAttrs,
|
|
1285
1457
|
wrapProviderMessage,
|
|
1286
1458
|
buildSpace,
|
|
1287
1459
|
definePlatform
|
package/dist/index.d.ts
CHANGED
|
@@ -2739,11 +2739,13 @@ declare function Spectrum<const Providers extends PlatformProviderConfig[]>(opti
|
|
|
2739
2739
|
projectSecret: string;
|
|
2740
2740
|
providers: [...Providers];
|
|
2741
2741
|
options?: SpectrumOptions;
|
|
2742
|
+
telemetry?: boolean;
|
|
2742
2743
|
} | {
|
|
2743
2744
|
projectId?: never;
|
|
2744
2745
|
projectSecret?: never;
|
|
2745
2746
|
providers: [...Providers];
|
|
2746
2747
|
options?: SpectrumOptions;
|
|
2748
|
+
telemetry?: boolean;
|
|
2747
2749
|
}): Promise<SpectrumInstance<Providers>>;
|
|
2748
2750
|
|
|
2749
2751
|
type SubscriptionStatus = "active" | "canceled" | "past_due";
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
group,
|
|
3
3
|
richlink
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-5NHNMN4H.js";
|
|
5
5
|
import {
|
|
6
6
|
voice
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-TN54TDTQ.js";
|
|
8
8
|
import {
|
|
9
9
|
SpectrumCloudError,
|
|
10
10
|
broadcast,
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
attachment,
|
|
20
20
|
buildSpace,
|
|
21
21
|
contact,
|
|
22
|
+
contentAttrs,
|
|
22
23
|
custom,
|
|
23
24
|
definePlatform,
|
|
24
25
|
edit,
|
|
@@ -26,11 +27,12 @@ import {
|
|
|
26
27
|
reaction,
|
|
27
28
|
reply,
|
|
28
29
|
resolveContents,
|
|
30
|
+
senderAttrs,
|
|
29
31
|
text,
|
|
30
32
|
toVCard,
|
|
31
33
|
typing,
|
|
32
34
|
wrapProviderMessage
|
|
33
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-XZSBR26X.js";
|
|
34
36
|
|
|
35
37
|
// src/emoji/generated.ts
|
|
36
38
|
var GeneratedEmoji = {
|
|
@@ -1962,8 +1964,17 @@ var aliases = {
|
|
|
1962
1964
|
var Emoji = { ...GeneratedEmoji, ...aliases };
|
|
1963
1965
|
|
|
1964
1966
|
// src/spectrum.ts
|
|
1967
|
+
import {
|
|
1968
|
+
createLogger,
|
|
1969
|
+
setupOtel,
|
|
1970
|
+
withSpan
|
|
1971
|
+
} from "@photon-ai/otel";
|
|
1965
1972
|
import z from "zod";
|
|
1966
1973
|
|
|
1974
|
+
// src/build-env.ts
|
|
1975
|
+
var SPECTRUM_SDK_VERSION = "local";
|
|
1976
|
+
var SPECTRUM_BUILD_ENV = "development";
|
|
1977
|
+
|
|
1967
1978
|
// src/utils/store.ts
|
|
1968
1979
|
var isRecordObject = (value) => {
|
|
1969
1980
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
@@ -2020,6 +2031,8 @@ function createStore() {
|
|
|
2020
2031
|
}
|
|
2021
2032
|
|
|
2022
2033
|
// src/spectrum.ts
|
|
2034
|
+
var PHOTON_OTEL_ENDPOINT = "https://otlp.photon.codes";
|
|
2035
|
+
var lifecycleLog = createLogger("spectrum.lifecycle");
|
|
2023
2036
|
var ignoreCleanupError = () => void 0;
|
|
2024
2037
|
var spectrumOptionsSchema = z.object({
|
|
2025
2038
|
flattenGroups: z.boolean().optional()
|
|
@@ -2029,24 +2042,48 @@ var spectrumConfigSchema = z.union([
|
|
|
2029
2042
|
projectId: z.string().min(1),
|
|
2030
2043
|
projectSecret: z.string().min(1),
|
|
2031
2044
|
providers: z.array(z.custom()),
|
|
2032
|
-
options: spectrumOptionsSchema
|
|
2045
|
+
options: spectrumOptionsSchema,
|
|
2046
|
+
telemetry: z.boolean().optional()
|
|
2033
2047
|
}),
|
|
2034
2048
|
z.object({
|
|
2035
2049
|
projectId: z.undefined().optional(),
|
|
2036
2050
|
projectSecret: z.undefined().optional(),
|
|
2037
2051
|
providers: z.array(z.custom()),
|
|
2038
|
-
options: spectrumOptionsSchema
|
|
2052
|
+
options: spectrumOptionsSchema,
|
|
2053
|
+
telemetry: z.boolean().optional()
|
|
2039
2054
|
})
|
|
2040
2055
|
]);
|
|
2056
|
+
function bootstrapTelemetry(opts) {
|
|
2057
|
+
const headers = {};
|
|
2058
|
+
if (opts.projectId && opts.projectSecret) {
|
|
2059
|
+
const credential = `${opts.projectId}:${opts.projectSecret}`;
|
|
2060
|
+
headers.Authorization = `Basic ${btoa(credential)}`;
|
|
2061
|
+
}
|
|
2062
|
+
const resourceAttributes = {
|
|
2063
|
+
"deployment.environment": process.env.DEPLOYMENT_ENV ?? SPECTRUM_BUILD_ENV
|
|
2064
|
+
};
|
|
2065
|
+
if (opts.projectId) {
|
|
2066
|
+
resourceAttributes["spectrum.project_id"] = opts.projectId;
|
|
2067
|
+
}
|
|
2068
|
+
return setupOtel({
|
|
2069
|
+
serviceName: "spectrum-ts",
|
|
2070
|
+
serviceVersion: SPECTRUM_SDK_VERSION,
|
|
2071
|
+
endpoint: PHOTON_OTEL_ENDPOINT,
|
|
2072
|
+
headers,
|
|
2073
|
+
resourceAttributes
|
|
2074
|
+
});
|
|
2075
|
+
}
|
|
2041
2076
|
async function Spectrum(options) {
|
|
2042
2077
|
spectrumConfigSchema.parse(options);
|
|
2043
2078
|
const {
|
|
2044
2079
|
projectId,
|
|
2045
2080
|
projectSecret,
|
|
2046
2081
|
providers,
|
|
2047
|
-
options: runtimeOptions
|
|
2082
|
+
options: runtimeOptions,
|
|
2083
|
+
telemetry
|
|
2048
2084
|
} = options;
|
|
2049
2085
|
const flattenGroups = runtimeOptions?.flattenGroups ?? false;
|
|
2086
|
+
const otelHandle = telemetry ? bootstrapTelemetry({ projectId, projectSecret }) : void 0;
|
|
2050
2087
|
const platformStates = /* @__PURE__ */ new Map();
|
|
2051
2088
|
const messageBroadcasters = /* @__PURE__ */ new Map();
|
|
2052
2089
|
const customEventStreams = /* @__PURE__ */ new Map();
|
|
@@ -2079,32 +2116,46 @@ async function Spectrum(options) {
|
|
|
2079
2116
|
});
|
|
2080
2117
|
const bindSend = async function* () {
|
|
2081
2118
|
for await (const msg of raw) {
|
|
2082
|
-
const
|
|
2083
|
-
|
|
2084
|
-
__platform: definition.name
|
|
2085
|
-
};
|
|
2086
|
-
const actionCtx = { space: spaceRef, client, config, store };
|
|
2087
|
-
const space = buildSpace({
|
|
2088
|
-
spaceRef,
|
|
2089
|
-
extras: {},
|
|
2090
|
-
actionCtx,
|
|
2091
|
-
definition,
|
|
2092
|
-
client,
|
|
2093
|
-
config,
|
|
2094
|
-
store
|
|
2095
|
-
});
|
|
2096
|
-
const normalizedMessage = wrapProviderMessage(
|
|
2097
|
-
msg,
|
|
2119
|
+
const built = await withSpan(
|
|
2120
|
+
"spectrum.message.receive",
|
|
2098
2121
|
{
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
store
|
|
2122
|
+
"spectrum.provider": definition.name,
|
|
2123
|
+
"spectrum.message.id": msg.id,
|
|
2124
|
+
"spectrum.space.id": msg.space?.id,
|
|
2125
|
+
...contentAttrs(msg.content),
|
|
2126
|
+
...senderAttrs(msg.sender)
|
|
2105
2127
|
},
|
|
2106
|
-
|
|
2128
|
+
() => {
|
|
2129
|
+
const spaceRef = {
|
|
2130
|
+
...msg.space,
|
|
2131
|
+
__platform: definition.name
|
|
2132
|
+
};
|
|
2133
|
+
const actionCtx = { space: spaceRef, client, config, store };
|
|
2134
|
+
const space2 = buildSpace({
|
|
2135
|
+
spaceRef,
|
|
2136
|
+
extras: {},
|
|
2137
|
+
actionCtx,
|
|
2138
|
+
definition,
|
|
2139
|
+
client,
|
|
2140
|
+
config,
|
|
2141
|
+
store
|
|
2142
|
+
});
|
|
2143
|
+
const normalizedMessage2 = wrapProviderMessage(
|
|
2144
|
+
msg,
|
|
2145
|
+
{
|
|
2146
|
+
client,
|
|
2147
|
+
config,
|
|
2148
|
+
definition,
|
|
2149
|
+
space: space2,
|
|
2150
|
+
spaceRef,
|
|
2151
|
+
store
|
|
2152
|
+
},
|
|
2153
|
+
"inbound"
|
|
2154
|
+
);
|
|
2155
|
+
return { space: space2, normalizedMessage: normalizedMessage2 };
|
|
2156
|
+
}
|
|
2107
2157
|
);
|
|
2158
|
+
const { space, normalizedMessage } = built;
|
|
2108
2159
|
if (flattenGroups && normalizedMessage.content.type === "group") {
|
|
2109
2160
|
for (const item of normalizedMessage.content.items) {
|
|
2110
2161
|
yield [space, item];
|
|
@@ -2130,28 +2181,49 @@ async function Spectrum(options) {
|
|
|
2130
2181
|
}
|
|
2131
2182
|
return broadcaster;
|
|
2132
2183
|
};
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2184
|
+
await withSpan(
|
|
2185
|
+
"spectrum.init",
|
|
2186
|
+
{
|
|
2187
|
+
"spectrum.provider_count": providers.length,
|
|
2188
|
+
"spectrum.flatten_groups": flattenGroups
|
|
2189
|
+
},
|
|
2190
|
+
async () => {
|
|
2191
|
+
for (const provider of providers) {
|
|
2192
|
+
const providerConfig = provider;
|
|
2193
|
+
const def = providerConfig.__definition;
|
|
2194
|
+
const userConfig = def.config.parse(providerConfig.config);
|
|
2195
|
+
const store = createStore();
|
|
2196
|
+
const client = await withSpan(
|
|
2197
|
+
"spectrum.provider.create_client",
|
|
2198
|
+
{
|
|
2199
|
+
"spectrum.provider": def.name
|
|
2200
|
+
},
|
|
2201
|
+
() => def.lifecycle.createClient({
|
|
2202
|
+
config: userConfig,
|
|
2203
|
+
projectId,
|
|
2204
|
+
projectSecret,
|
|
2205
|
+
store
|
|
2206
|
+
})
|
|
2207
|
+
);
|
|
2208
|
+
const state = {
|
|
2209
|
+
client,
|
|
2210
|
+
config: userConfig,
|
|
2211
|
+
definition: def,
|
|
2212
|
+
store
|
|
2213
|
+
};
|
|
2214
|
+
platformStates.set(def.name, {
|
|
2215
|
+
...state,
|
|
2216
|
+
subscribeMessages: () => getOrCreateMessageBroadcast(state).subscribe()
|
|
2217
|
+
});
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
);
|
|
2221
|
+
const providerNames = providers.map((p) => p.__definition.name).join(",");
|
|
2222
|
+
lifecycleLog.info("Spectrum started", {
|
|
2223
|
+
providerCount: providers.length,
|
|
2224
|
+
providers: providerNames,
|
|
2225
|
+
telemetry: telemetry === true
|
|
2226
|
+
});
|
|
2155
2227
|
const createMessagesStream = () => stream((emit, end) => {
|
|
2156
2228
|
const merged = mergeStreams(
|
|
2157
2229
|
Array.from(
|
|
@@ -2185,7 +2257,15 @@ async function Spectrum(options) {
|
|
|
2185
2257
|
const providerEvents = producer({ client, config, store });
|
|
2186
2258
|
const annotatePlatform = async function* () {
|
|
2187
2259
|
for await (const value of providerEvents) {
|
|
2188
|
-
|
|
2260
|
+
const annotated = await withSpan(
|
|
2261
|
+
"spectrum.event",
|
|
2262
|
+
{
|
|
2263
|
+
"spectrum.provider": definition.name,
|
|
2264
|
+
"spectrum.event.name": eventName
|
|
2265
|
+
},
|
|
2266
|
+
() => ({ ...value, platform: definition.name })
|
|
2267
|
+
);
|
|
2268
|
+
yield annotated;
|
|
2189
2269
|
}
|
|
2190
2270
|
};
|
|
2191
2271
|
providerStreams.push(adaptIterable(annotatePlatform()));
|
|
@@ -2226,17 +2306,33 @@ async function Spectrum(options) {
|
|
|
2226
2306
|
process.off("SIGINT", handleSignal);
|
|
2227
2307
|
process.off("SIGTERM", handleSignal);
|
|
2228
2308
|
await Promise.allSettled(streamShutdowns);
|
|
2229
|
-
const clientShutdowns =
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
}
|
|
2235
|
-
|
|
2309
|
+
const clientShutdowns = [];
|
|
2310
|
+
for (const state of platformStates.values()) {
|
|
2311
|
+
const destroy = state.definition.lifecycle.destroyClient;
|
|
2312
|
+
if (!destroy) {
|
|
2313
|
+
continue;
|
|
2314
|
+
}
|
|
2315
|
+
clientShutdowns.push(
|
|
2316
|
+
withSpan(
|
|
2317
|
+
"spectrum.provider.destroy_client",
|
|
2318
|
+
{
|
|
2319
|
+
"spectrum.provider": state.definition.name
|
|
2320
|
+
},
|
|
2321
|
+
() => destroy({
|
|
2322
|
+
client: state.client,
|
|
2323
|
+
store: state.store
|
|
2324
|
+
})
|
|
2325
|
+
)
|
|
2326
|
+
);
|
|
2327
|
+
}
|
|
2236
2328
|
await Promise.allSettled(clientShutdowns);
|
|
2237
2329
|
customEventStreams.clear();
|
|
2238
2330
|
messageBroadcasters.clear();
|
|
2239
2331
|
platformStates.clear();
|
|
2332
|
+
lifecycleLog.info("Spectrum stopped", { providers: providerNames });
|
|
2333
|
+
if (otelHandle) {
|
|
2334
|
+
await otelHandle.shutdown();
|
|
2335
|
+
}
|
|
2240
2336
|
};
|
|
2241
2337
|
const handleSignal = () => {
|
|
2242
2338
|
setTimeout(() => process.exit(1), 3e3).unref();
|
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
background,
|
|
3
3
|
effect,
|
|
4
4
|
imessage
|
|
5
|
-
} from "../../chunk-
|
|
6
|
-
import "../../chunk-
|
|
5
|
+
} from "../../chunk-OM5VSKWD.js";
|
|
6
|
+
import "../../chunk-5NHNMN4H.js";
|
|
7
7
|
import "../../chunk-HWADNTQF.js";
|
|
8
|
-
import "../../chunk-
|
|
8
|
+
import "../../chunk-XZSBR26X.js";
|
|
9
9
|
export {
|
|
10
10
|
background,
|
|
11
11
|
effect,
|
package/dist/providers/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
imessage
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-OM5VSKWD.js";
|
|
4
|
+
import "../chunk-5NHNMN4H.js";
|
|
5
5
|
import {
|
|
6
6
|
terminal
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-N3ZKMTSG.js";
|
|
8
|
+
import "../chunk-TN54TDTQ.js";
|
|
9
9
|
import {
|
|
10
10
|
whatsappBusiness
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-OR3VGVML.js";
|
|
12
12
|
import "../chunk-HWADNTQF.js";
|
|
13
|
-
import "../chunk-
|
|
13
|
+
import "../chunk-XZSBR26X.js";
|
|
14
14
|
export {
|
|
15
15
|
imessage,
|
|
16
16
|
terminal,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
terminal
|
|
3
|
-
} from "../../chunk-
|
|
4
|
-
import "../../chunk-
|
|
5
|
-
import "../../chunk-
|
|
3
|
+
} from "../../chunk-N3ZKMTSG.js";
|
|
4
|
+
import "../../chunk-TN54TDTQ.js";
|
|
5
|
+
import "../../chunk-XZSBR26X.js";
|
|
6
6
|
export {
|
|
7
7
|
terminal
|
|
8
8
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spectrum-ts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@photon-ai/advanced-imessage": "^0.7.0",
|
|
27
27
|
"@photon-ai/imessage-kit": "^3.0.0",
|
|
28
|
+
"@photon-ai/otel": "^0.1.1",
|
|
28
29
|
"@photon-ai/whatsapp-business": "^0.1.1",
|
|
29
30
|
"@repeaterjs/repeater": "^3.0.6",
|
|
30
31
|
"better-grpc": "^0.3.2",
|