@flutchai/flutch-sdk 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +237 -17
- package/dist/index.cjs +965 -384
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +88 -20
- package/dist/index.d.ts +88 -20
- package/dist/index.js +965 -385
- package/dist/index.js.map +1 -1
- package/package.json +3 -4
package/dist/index.cjs
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
require('reflect-metadata');
|
|
4
4
|
var common = require('@nestjs/common');
|
|
5
5
|
var swagger = require('@nestjs/swagger');
|
|
6
|
-
var
|
|
6
|
+
var fs = require('fs');
|
|
7
|
+
var path2 = require('path');
|
|
8
|
+
var os = require('os');
|
|
7
9
|
var crypto = require('crypto');
|
|
8
10
|
var promClient = require('prom-client');
|
|
9
11
|
var core = require('@nestjs/core');
|
|
@@ -40,7 +42,9 @@ function _interopNamespace(e) {
|
|
|
40
42
|
return Object.freeze(n);
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
var
|
|
45
|
+
var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
|
|
46
|
+
var path2__namespace = /*#__PURE__*/_interopNamespace(path2);
|
|
47
|
+
var os__namespace = /*#__PURE__*/_interopNamespace(os);
|
|
44
48
|
var net__namespace = /*#__PURE__*/_interopNamespace(net);
|
|
45
49
|
var LangGraph__namespace = /*#__PURE__*/_interopNamespace(LangGraph);
|
|
46
50
|
var axios2__default = /*#__PURE__*/_interopDefault(axios2);
|
|
@@ -459,12 +463,21 @@ var init_ui_endpoints_discovery = __esm({
|
|
|
459
463
|
this.endpointRegistry = endpointRegistry;
|
|
460
464
|
}
|
|
461
465
|
logger = new common.Logger(exports.UIEndpointsDiscoveryService.name);
|
|
466
|
+
async onModuleInit() {
|
|
467
|
+
await this.discoverUIEndpoints();
|
|
468
|
+
}
|
|
462
469
|
/**
|
|
463
470
|
* Discover and register all UI endpoint classes
|
|
464
471
|
* Called automatically during module initialization
|
|
465
472
|
*/
|
|
466
473
|
async discoverUIEndpoints() {
|
|
467
474
|
this.logger.log("Starting UI endpoints discovery...");
|
|
475
|
+
if (!this.discoveryService) {
|
|
476
|
+
this.logger.warn(
|
|
477
|
+
"DiscoveryService not available, skipping UI endpoints discovery"
|
|
478
|
+
);
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
468
481
|
const providers = this.discoveryService.getProviders();
|
|
469
482
|
let registeredCount = 0;
|
|
470
483
|
let totalEndpoints = 0;
|
|
@@ -516,7 +529,9 @@ var init_ui_endpoints_discovery = __esm({
|
|
|
516
529
|
}
|
|
517
530
|
};
|
|
518
531
|
exports.UIEndpointsDiscoveryService = __decorateClass([
|
|
519
|
-
common.Injectable()
|
|
532
|
+
common.Injectable(),
|
|
533
|
+
__decorateParam(0, common.Optional()),
|
|
534
|
+
__decorateParam(1, common.Optional())
|
|
520
535
|
], exports.UIEndpointsDiscoveryService);
|
|
521
536
|
}
|
|
522
537
|
});
|
|
@@ -711,6 +726,523 @@ var init_agent_ui = __esm({
|
|
|
711
726
|
init_ui_dispatch_controller();
|
|
712
727
|
}
|
|
713
728
|
});
|
|
729
|
+
|
|
730
|
+
// src/service-discovery/file-based.discovery.ts
|
|
731
|
+
var file_based_discovery_exports = {};
|
|
732
|
+
__export(file_based_discovery_exports, {
|
|
733
|
+
FileBasedDiscovery: () => exports.FileBasedDiscovery
|
|
734
|
+
});
|
|
735
|
+
exports.FileBasedDiscovery = void 0;
|
|
736
|
+
var init_file_based_discovery = __esm({
|
|
737
|
+
"src/service-discovery/file-based.discovery.ts"() {
|
|
738
|
+
exports.FileBasedDiscovery = class {
|
|
739
|
+
logger = new common.Logger(exports.FileBasedDiscovery.name);
|
|
740
|
+
servicesDir;
|
|
741
|
+
constructor() {
|
|
742
|
+
this.servicesDir = path2__namespace.join(os__namespace.homedir(), ".flutch", "services");
|
|
743
|
+
this.ensureServicesDirectory();
|
|
744
|
+
this.cleanupStaleServices();
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Register service
|
|
748
|
+
*/
|
|
749
|
+
async registerService(name, address, port, metadata, graphTypes = []) {
|
|
750
|
+
const registration = {
|
|
751
|
+
name,
|
|
752
|
+
address,
|
|
753
|
+
port,
|
|
754
|
+
metadata,
|
|
755
|
+
pid: process.pid,
|
|
756
|
+
timestamp: Date.now(),
|
|
757
|
+
graphTypes
|
|
758
|
+
};
|
|
759
|
+
const serviceFile = path2__namespace.join(
|
|
760
|
+
this.servicesDir,
|
|
761
|
+
`${name}-${process.pid}.json`
|
|
762
|
+
);
|
|
763
|
+
try {
|
|
764
|
+
await fs__namespace.promises.writeFile(
|
|
765
|
+
serviceFile,
|
|
766
|
+
JSON.stringify(registration, null, 2)
|
|
767
|
+
);
|
|
768
|
+
this.logger.log(`Registered service: ${name} at ${address}:${port}`);
|
|
769
|
+
process.on("exit", () => this.unregisterService(name));
|
|
770
|
+
process.on("SIGINT", () => {
|
|
771
|
+
this.unregisterService(name);
|
|
772
|
+
process.exit(0);
|
|
773
|
+
});
|
|
774
|
+
process.on("SIGTERM", () => {
|
|
775
|
+
this.unregisterService(name);
|
|
776
|
+
process.exit(0);
|
|
777
|
+
});
|
|
778
|
+
} catch (error) {
|
|
779
|
+
this.logger.error(`Failed to register service ${name}: ${error.message}`);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* Unregister service
|
|
784
|
+
*/
|
|
785
|
+
async unregisterService(name) {
|
|
786
|
+
const serviceFile = path2__namespace.join(
|
|
787
|
+
this.servicesDir,
|
|
788
|
+
`${name}-${process.pid}.json`
|
|
789
|
+
);
|
|
790
|
+
try {
|
|
791
|
+
if (fs__namespace.existsSync(serviceFile)) {
|
|
792
|
+
await fs__namespace.promises.unlink(serviceFile);
|
|
793
|
+
this.logger.log(`Unregistered service: ${name}`);
|
|
794
|
+
}
|
|
795
|
+
} catch (error) {
|
|
796
|
+
this.logger.error(
|
|
797
|
+
`Failed to unregister service ${name}: ${error.message}`
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* Get list of services by graph type
|
|
803
|
+
*/
|
|
804
|
+
async getServices(graphType) {
|
|
805
|
+
try {
|
|
806
|
+
const files = await fs__namespace.promises.readdir(this.servicesDir);
|
|
807
|
+
const services = [];
|
|
808
|
+
for (const file of files) {
|
|
809
|
+
if (!file.endsWith(".json")) continue;
|
|
810
|
+
try {
|
|
811
|
+
const serviceFile = path2__namespace.join(this.servicesDir, file);
|
|
812
|
+
const content = await fs__namespace.promises.readFile(serviceFile, "utf-8");
|
|
813
|
+
const registration = JSON.parse(content);
|
|
814
|
+
if (!this.isProcessAlive(registration.pid)) {
|
|
815
|
+
await fs__namespace.promises.unlink(serviceFile);
|
|
816
|
+
continue;
|
|
817
|
+
}
|
|
818
|
+
if (registration.graphTypes.includes(graphType) || registration.metadata.graphTypes?.includes(graphType)) {
|
|
819
|
+
services.push({
|
|
820
|
+
name: registration.name,
|
|
821
|
+
address: registration.address,
|
|
822
|
+
port: registration.port,
|
|
823
|
+
metadata: registration.metadata
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
} catch (error) {
|
|
827
|
+
this.logger.warn(
|
|
828
|
+
`Failed to parse service file ${file}: ${error.message}`
|
|
829
|
+
);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
return services;
|
|
833
|
+
} catch (error) {
|
|
834
|
+
this.logger.error(`Failed to get services: ${error.message}`);
|
|
835
|
+
return [];
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* Find service by name
|
|
840
|
+
*/
|
|
841
|
+
async findServiceByName(serviceName) {
|
|
842
|
+
try {
|
|
843
|
+
const files = await fs__namespace.promises.readdir(this.servicesDir);
|
|
844
|
+
for (const file of files) {
|
|
845
|
+
if (!file.endsWith(".json")) continue;
|
|
846
|
+
try {
|
|
847
|
+
const serviceFile = path2__namespace.join(this.servicesDir, file);
|
|
848
|
+
const content = await fs__namespace.promises.readFile(serviceFile, "utf-8");
|
|
849
|
+
const registration = JSON.parse(content);
|
|
850
|
+
if (registration.name === serviceName && this.isProcessAlive(registration.pid)) {
|
|
851
|
+
return {
|
|
852
|
+
name: registration.name,
|
|
853
|
+
address: registration.address,
|
|
854
|
+
port: registration.port,
|
|
855
|
+
metadata: registration.metadata
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
} catch (error) {
|
|
859
|
+
this.logger.warn(
|
|
860
|
+
`Failed to parse service file ${file}: ${error.message}`
|
|
861
|
+
);
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
return null;
|
|
865
|
+
} catch (error) {
|
|
866
|
+
this.logger.error(
|
|
867
|
+
`Failed to find service ${serviceName}: ${error.message}`
|
|
868
|
+
);
|
|
869
|
+
return null;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* Ensure services directory exists
|
|
874
|
+
*/
|
|
875
|
+
ensureServicesDirectory() {
|
|
876
|
+
try {
|
|
877
|
+
const amelieDir = path2__namespace.join(os__namespace.homedir(), ".flutch");
|
|
878
|
+
if (!fs__namespace.existsSync(amelieDir)) {
|
|
879
|
+
fs__namespace.mkdirSync(amelieDir, { recursive: true });
|
|
880
|
+
}
|
|
881
|
+
if (!fs__namespace.existsSync(this.servicesDir)) {
|
|
882
|
+
fs__namespace.mkdirSync(this.servicesDir, { recursive: true });
|
|
883
|
+
}
|
|
884
|
+
} catch (error) {
|
|
885
|
+
this.logger.error(
|
|
886
|
+
`Failed to create services directory: ${error.message}`
|
|
887
|
+
);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Cleanup stale services
|
|
892
|
+
*/
|
|
893
|
+
async cleanupStaleServices() {
|
|
894
|
+
try {
|
|
895
|
+
const files = await fs__namespace.promises.readdir(this.servicesDir);
|
|
896
|
+
for (const file of files) {
|
|
897
|
+
if (!file.endsWith(".json")) continue;
|
|
898
|
+
try {
|
|
899
|
+
const serviceFile = path2__namespace.join(this.servicesDir, file);
|
|
900
|
+
const content = await fs__namespace.promises.readFile(serviceFile, "utf-8");
|
|
901
|
+
const registration = JSON.parse(content);
|
|
902
|
+
if (!this.isProcessAlive(registration.pid)) {
|
|
903
|
+
await fs__namespace.promises.unlink(serviceFile);
|
|
904
|
+
this.logger.debug(`Cleaned up stale service: ${registration.name}`);
|
|
905
|
+
}
|
|
906
|
+
} catch (error) {
|
|
907
|
+
try {
|
|
908
|
+
await fs__namespace.promises.unlink(path2__namespace.join(this.servicesDir, file));
|
|
909
|
+
} catch {
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
} catch (error) {
|
|
914
|
+
this.logger.error(`Failed to cleanup stale services: ${error.message}`);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* Check if process is still alive
|
|
919
|
+
*/
|
|
920
|
+
isProcessAlive(pid) {
|
|
921
|
+
try {
|
|
922
|
+
process.kill(pid, 0);
|
|
923
|
+
return true;
|
|
924
|
+
} catch (error) {
|
|
925
|
+
return false;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
};
|
|
929
|
+
exports.FileBasedDiscovery = __decorateClass([
|
|
930
|
+
common.Injectable()
|
|
931
|
+
], exports.FileBasedDiscovery);
|
|
932
|
+
}
|
|
933
|
+
});
|
|
934
|
+
|
|
935
|
+
// src/core/builder-registry.service.ts
|
|
936
|
+
var builder_registry_service_exports = {};
|
|
937
|
+
__export(builder_registry_service_exports, {
|
|
938
|
+
BuilderRegistryService: () => exports.BuilderRegistryService
|
|
939
|
+
});
|
|
940
|
+
exports.BuilderRegistryService = void 0;
|
|
941
|
+
var init_builder_registry_service = __esm({
|
|
942
|
+
"src/core/builder-registry.service.ts"() {
|
|
943
|
+
exports.BuilderRegistryService = class {
|
|
944
|
+
builders = [];
|
|
945
|
+
registerBuilder(builder) {
|
|
946
|
+
const existingBuilder = this.builders.find(
|
|
947
|
+
(b) => b.graphType === builder.graphType
|
|
948
|
+
);
|
|
949
|
+
if (!existingBuilder) {
|
|
950
|
+
this.builders.push(builder);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
getBuilders() {
|
|
954
|
+
return this.builders;
|
|
955
|
+
}
|
|
956
|
+
};
|
|
957
|
+
exports.BuilderRegistryService = __decorateClass([
|
|
958
|
+
common.Injectable()
|
|
959
|
+
], exports.BuilderRegistryService);
|
|
960
|
+
}
|
|
961
|
+
});
|
|
962
|
+
|
|
963
|
+
// src/utils/graph-type.utils.ts
|
|
964
|
+
exports.GraphTypeUtils = void 0;
|
|
965
|
+
var init_graph_type_utils = __esm({
|
|
966
|
+
"src/utils/graph-type.utils.ts"() {
|
|
967
|
+
exports.GraphTypeUtils = class {
|
|
968
|
+
/**
|
|
969
|
+
* Parse full graph type
|
|
970
|
+
* @param fullType - full graph type
|
|
971
|
+
* @returns object with type components
|
|
972
|
+
*/
|
|
973
|
+
static parse(fullType) {
|
|
974
|
+
if (fullType.includes("::")) {
|
|
975
|
+
const [baseType, version] = fullType.split("::");
|
|
976
|
+
const [companyId, name] = baseType.split(".");
|
|
977
|
+
return { companyId, name, version };
|
|
978
|
+
}
|
|
979
|
+
const parts = fullType.split(".");
|
|
980
|
+
if (parts.length === 1) {
|
|
981
|
+
return { companyId: "global", name: parts[0] };
|
|
982
|
+
}
|
|
983
|
+
return { companyId: parts[0], name: parts[1] };
|
|
984
|
+
}
|
|
985
|
+
/**
|
|
986
|
+
* Build full type from components
|
|
987
|
+
* @param companyId - company ID
|
|
988
|
+
* @param name - graph name
|
|
989
|
+
* @param version - version (optional)
|
|
990
|
+
* @returns full graph type
|
|
991
|
+
*/
|
|
992
|
+
static build(companyId, name, version) {
|
|
993
|
+
const base = `${companyId}.${name}`;
|
|
994
|
+
return version ? `${base}::${version}` : base;
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* Normalize graph type for backward compatibility
|
|
998
|
+
* @param graphType - graph type in any format
|
|
999
|
+
* @returns normalized type
|
|
1000
|
+
*/
|
|
1001
|
+
static normalize(graphType) {
|
|
1002
|
+
const { companyId, name, version } = this.parse(graphType);
|
|
1003
|
+
return this.build(companyId, name, version);
|
|
1004
|
+
}
|
|
1005
|
+
/**
|
|
1006
|
+
* Get base type without version
|
|
1007
|
+
* @param graphType - full graph type
|
|
1008
|
+
* @returns base type
|
|
1009
|
+
*/
|
|
1010
|
+
static getBaseType(graphType) {
|
|
1011
|
+
if (graphType.includes("::")) {
|
|
1012
|
+
return graphType.split("::")[0];
|
|
1013
|
+
}
|
|
1014
|
+
const { companyId, name } = this.parse(graphType);
|
|
1015
|
+
return `${companyId}.${name}`;
|
|
1016
|
+
}
|
|
1017
|
+
/**
|
|
1018
|
+
* Extract version from graph type
|
|
1019
|
+
* @param graphType - full graph type
|
|
1020
|
+
* @returns version or undefined
|
|
1021
|
+
*/
|
|
1022
|
+
static getVersion(graphType) {
|
|
1023
|
+
return graphType.includes("::") ? graphType.split("::")[1] : void 0;
|
|
1024
|
+
}
|
|
1025
|
+
/**
|
|
1026
|
+
* Validate version (basic semver check)
|
|
1027
|
+
* @param version - version to check
|
|
1028
|
+
* @returns true if version is valid
|
|
1029
|
+
*/
|
|
1030
|
+
static isValidVersion(version) {
|
|
1031
|
+
const semverRegex = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?$/;
|
|
1032
|
+
return semverRegex.test(version);
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* Check if type is system (global)
|
|
1036
|
+
* @param graphType - graph type
|
|
1037
|
+
* @returns true if graph is system
|
|
1038
|
+
*/
|
|
1039
|
+
static isSystemGraph(graphType) {
|
|
1040
|
+
const { companyId } = this.parse(graphType);
|
|
1041
|
+
return companyId === "global";
|
|
1042
|
+
}
|
|
1043
|
+
/**
|
|
1044
|
+
* Compare versions (simple comparison for sorting)
|
|
1045
|
+
* @param a - first version
|
|
1046
|
+
* @param b - second version
|
|
1047
|
+
* @returns -1, 0, 1 for sorting
|
|
1048
|
+
*/
|
|
1049
|
+
static compareVersions(a, b) {
|
|
1050
|
+
const parseVersion = (v) => {
|
|
1051
|
+
const [main, prerelease] = v.split("-");
|
|
1052
|
+
const [major, minor, patch] = main.split(".").map(Number);
|
|
1053
|
+
return { major, minor, patch, prerelease };
|
|
1054
|
+
};
|
|
1055
|
+
const versionA = parseVersion(a);
|
|
1056
|
+
const versionB = parseVersion(b);
|
|
1057
|
+
if (versionA.major !== versionB.major) {
|
|
1058
|
+
return versionA.major - versionB.major;
|
|
1059
|
+
}
|
|
1060
|
+
if (versionA.minor !== versionB.minor) {
|
|
1061
|
+
return versionA.minor - versionB.minor;
|
|
1062
|
+
}
|
|
1063
|
+
if (versionA.patch !== versionB.patch) {
|
|
1064
|
+
return versionA.patch - versionB.patch;
|
|
1065
|
+
}
|
|
1066
|
+
if (versionA.prerelease && !versionB.prerelease) return -1;
|
|
1067
|
+
if (!versionA.prerelease && versionB.prerelease) return 1;
|
|
1068
|
+
if (versionA.prerelease && versionB.prerelease) {
|
|
1069
|
+
return versionA.prerelease.localeCompare(versionB.prerelease);
|
|
1070
|
+
}
|
|
1071
|
+
return 0;
|
|
1072
|
+
}
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
});
|
|
1076
|
+
|
|
1077
|
+
// src/graph/versioning/versioned-graph.service.ts
|
|
1078
|
+
var versioned_graph_service_exports = {};
|
|
1079
|
+
__export(versioned_graph_service_exports, {
|
|
1080
|
+
VersionedGraphService: () => exports.VersionedGraphService
|
|
1081
|
+
});
|
|
1082
|
+
exports.VersionedGraphService = void 0;
|
|
1083
|
+
var init_versioned_graph_service = __esm({
|
|
1084
|
+
"src/graph/versioning/versioned-graph.service.ts"() {
|
|
1085
|
+
init_graph_type_utils();
|
|
1086
|
+
exports.VersionedGraphService = class {
|
|
1087
|
+
logger = new common.Logger(exports.VersionedGraphService.name);
|
|
1088
|
+
versionConfigs = /* @__PURE__ */ new Map();
|
|
1089
|
+
constructor() {
|
|
1090
|
+
}
|
|
1091
|
+
/**
|
|
1092
|
+
* Register versioning configuration
|
|
1093
|
+
*/
|
|
1094
|
+
registerVersioning(config) {
|
|
1095
|
+
this.versionConfigs.set(config.baseGraphType, config);
|
|
1096
|
+
this.logger.log(
|
|
1097
|
+
`Registered versioning for ${config.baseGraphType} with ${config.versions.length} versions`
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
/**
|
|
1101
|
+
* Resolve graph version
|
|
1102
|
+
*/
|
|
1103
|
+
async resolveVersion(graphType, options = {}) {
|
|
1104
|
+
const parsed = exports.GraphTypeUtils.parse(graphType);
|
|
1105
|
+
const baseType = exports.GraphTypeUtils.getBaseType(graphType);
|
|
1106
|
+
const requestedVersion = exports.GraphTypeUtils.getVersion(graphType) || options.requestedVersion;
|
|
1107
|
+
const config = this.versionConfigs.get(baseType);
|
|
1108
|
+
if (!config) {
|
|
1109
|
+
throw new Error(`No versioning configuration found for ${baseType}`);
|
|
1110
|
+
}
|
|
1111
|
+
const route = this.findBestVersionRoute(config, requestedVersion, options);
|
|
1112
|
+
if (!route) {
|
|
1113
|
+
throw new Error(
|
|
1114
|
+
`No compatible version found for ${graphType} with options: ${JSON.stringify(options)}`
|
|
1115
|
+
);
|
|
1116
|
+
}
|
|
1117
|
+
const fullGraphType = exports.GraphTypeUtils.build(
|
|
1118
|
+
parsed.companyId,
|
|
1119
|
+
parsed.name,
|
|
1120
|
+
route.version
|
|
1121
|
+
);
|
|
1122
|
+
return {
|
|
1123
|
+
version: route.version,
|
|
1124
|
+
builderClass: route.builderClass,
|
|
1125
|
+
fullGraphType
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Create builder for specified version
|
|
1130
|
+
*/
|
|
1131
|
+
async createVersionedBuilder(graphType, moduleRef, options = {}) {
|
|
1132
|
+
const resolution = await this.resolveVersion(graphType, options);
|
|
1133
|
+
try {
|
|
1134
|
+
if (!moduleRef) {
|
|
1135
|
+
throw new Error(
|
|
1136
|
+
"ModuleRef is not available - falling back to direct instantiation"
|
|
1137
|
+
);
|
|
1138
|
+
}
|
|
1139
|
+
const builder = await moduleRef.create(resolution.builderClass);
|
|
1140
|
+
this.logger.debug(
|
|
1141
|
+
`Created versioned builder for ${resolution.fullGraphType}`
|
|
1142
|
+
);
|
|
1143
|
+
return builder;
|
|
1144
|
+
} catch (error) {
|
|
1145
|
+
this.logger.error(
|
|
1146
|
+
`Failed to create builder for ${resolution.fullGraphType}: ${error.message}`
|
|
1147
|
+
);
|
|
1148
|
+
throw new Error(`Failed to create versioned builder: ${error.message}`);
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
/**
|
|
1152
|
+
* Get all available versions for a graph
|
|
1153
|
+
*/
|
|
1154
|
+
getAvailableVersions(baseGraphType) {
|
|
1155
|
+
const config = this.versionConfigs.get(baseGraphType);
|
|
1156
|
+
if (!config) {
|
|
1157
|
+
return [];
|
|
1158
|
+
}
|
|
1159
|
+
return config.versions.map((route) => route.version).sort((a, b) => exports.GraphTypeUtils.compareVersions(b, a));
|
|
1160
|
+
}
|
|
1161
|
+
/**
|
|
1162
|
+
* Check version support
|
|
1163
|
+
*/
|
|
1164
|
+
isVersionSupported(graphType, options = {}) {
|
|
1165
|
+
try {
|
|
1166
|
+
const baseType = exports.GraphTypeUtils.getBaseType(graphType);
|
|
1167
|
+
const requestedVersion = exports.GraphTypeUtils.getVersion(graphType);
|
|
1168
|
+
const config = this.versionConfigs.get(baseType);
|
|
1169
|
+
if (!config) {
|
|
1170
|
+
return false;
|
|
1171
|
+
}
|
|
1172
|
+
const route = this.findBestVersionRoute(
|
|
1173
|
+
config,
|
|
1174
|
+
requestedVersion,
|
|
1175
|
+
options
|
|
1176
|
+
);
|
|
1177
|
+
return route !== null;
|
|
1178
|
+
} catch {
|
|
1179
|
+
return false;
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
/**
|
|
1183
|
+
* Find best version
|
|
1184
|
+
*/
|
|
1185
|
+
findBestVersionRoute(config, requestedVersion, options = {}) {
|
|
1186
|
+
const { strict = false } = options;
|
|
1187
|
+
let candidates = [...config.versions];
|
|
1188
|
+
if (requestedVersion) {
|
|
1189
|
+
const exactMatch = candidates.find(
|
|
1190
|
+
(route) => route.version === requestedVersion
|
|
1191
|
+
);
|
|
1192
|
+
if (exactMatch) {
|
|
1193
|
+
return exactMatch;
|
|
1194
|
+
}
|
|
1195
|
+
if (strict) {
|
|
1196
|
+
return null;
|
|
1197
|
+
}
|
|
1198
|
+
const compatibleVersions = candidates.filter(
|
|
1199
|
+
(route) => this.isVersionCompatible(requestedVersion, route.version)
|
|
1200
|
+
);
|
|
1201
|
+
if (compatibleVersions.length > 0) {
|
|
1202
|
+
return compatibleVersions.sort(
|
|
1203
|
+
(a, b) => exports.GraphTypeUtils.compareVersions(b.version, a.version)
|
|
1204
|
+
)[0];
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
const defaultRoute = candidates.find((route) => route.isDefault);
|
|
1208
|
+
if (defaultRoute) {
|
|
1209
|
+
return defaultRoute;
|
|
1210
|
+
}
|
|
1211
|
+
if (config.defaultVersionStrategy === "latest" || !config.defaultVersionStrategy) {
|
|
1212
|
+
const sortedVersions = candidates.sort(
|
|
1213
|
+
(a, b) => exports.GraphTypeUtils.compareVersions(b.version, a.version)
|
|
1214
|
+
);
|
|
1215
|
+
return sortedVersions[0] || null;
|
|
1216
|
+
}
|
|
1217
|
+
return null;
|
|
1218
|
+
}
|
|
1219
|
+
/**
|
|
1220
|
+
* Check version compatibility (simplified semantics)
|
|
1221
|
+
*/
|
|
1222
|
+
isVersionCompatible(requested, available) {
|
|
1223
|
+
try {
|
|
1224
|
+
const requestedParts = requested.split(".").map(Number);
|
|
1225
|
+
const availableParts = available.split(".").map(Number);
|
|
1226
|
+
if (requestedParts[0] !== availableParts[0]) {
|
|
1227
|
+
return false;
|
|
1228
|
+
}
|
|
1229
|
+
return exports.GraphTypeUtils.compareVersions(available, requested) >= 0;
|
|
1230
|
+
} catch {
|
|
1231
|
+
return false;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
/**
|
|
1235
|
+
* Get versioning configuration information
|
|
1236
|
+
*/
|
|
1237
|
+
getVersioningInfo(baseGraphType) {
|
|
1238
|
+
return this.versionConfigs.get(baseGraphType) || null;
|
|
1239
|
+
}
|
|
1240
|
+
};
|
|
1241
|
+
exports.VersionedGraphService = __decorateClass([
|
|
1242
|
+
common.Injectable()
|
|
1243
|
+
], exports.VersionedGraphService);
|
|
1244
|
+
}
|
|
1245
|
+
});
|
|
714
1246
|
var CallbackStore = class {
|
|
715
1247
|
constructor(redis) {
|
|
716
1248
|
this.redis = redis;
|
|
@@ -2552,7 +3084,7 @@ var _AbstractGraphBuilder = class _AbstractGraphBuilder {
|
|
|
2552
3084
|
/**
|
|
2553
3085
|
* Path to root graph manifest (defaults to graph.manifest.json in root)
|
|
2554
3086
|
*/
|
|
2555
|
-
manifestPath =
|
|
3087
|
+
manifestPath = path2__namespace.join(
|
|
2556
3088
|
process.cwd(),
|
|
2557
3089
|
"graph.manifest.json"
|
|
2558
3090
|
);
|
|
@@ -2632,10 +3164,10 @@ var _AbstractGraphBuilder = class _AbstractGraphBuilder {
|
|
|
2632
3164
|
return null;
|
|
2633
3165
|
}
|
|
2634
3166
|
try {
|
|
2635
|
-
const
|
|
2636
|
-
const
|
|
2637
|
-
const manifestFullPath =
|
|
2638
|
-
const manifestContent = await
|
|
3167
|
+
const fs2 = await import('fs/promises');
|
|
3168
|
+
const path3 = await import('path');
|
|
3169
|
+
const manifestFullPath = path3.resolve(this.manifestPath);
|
|
3170
|
+
const manifestContent = await fs2.readFile(manifestFullPath, "utf-8");
|
|
2639
3171
|
const manifest = JSON.parse(manifestContent);
|
|
2640
3172
|
this.manifest = manifest;
|
|
2641
3173
|
return manifest;
|
|
@@ -2654,10 +3186,10 @@ var _AbstractGraphBuilder = class _AbstractGraphBuilder {
|
|
|
2654
3186
|
return null;
|
|
2655
3187
|
}
|
|
2656
3188
|
try {
|
|
2657
|
-
const
|
|
2658
|
-
const
|
|
2659
|
-
const manifestFullPath =
|
|
2660
|
-
const manifestContent =
|
|
3189
|
+
const fs2 = __require("fs");
|
|
3190
|
+
const path3 = __require("path");
|
|
3191
|
+
const manifestFullPath = path3.resolve(this.manifestPath);
|
|
3192
|
+
const manifestContent = fs2.readFileSync(manifestFullPath, "utf-8");
|
|
2661
3193
|
const manifest = JSON.parse(manifestContent);
|
|
2662
3194
|
this.manifest = manifest;
|
|
2663
3195
|
return manifest;
|
|
@@ -2697,12 +3229,12 @@ var _AbstractGraphBuilder = class _AbstractGraphBuilder {
|
|
|
2697
3229
|
let configSchema = null;
|
|
2698
3230
|
if (versionConfig.configSchemaPath) {
|
|
2699
3231
|
try {
|
|
2700
|
-
const
|
|
2701
|
-
const schemaPath =
|
|
3232
|
+
const fs2 = await import('fs/promises');
|
|
3233
|
+
const schemaPath = path2__namespace.resolve(
|
|
2702
3234
|
process.cwd(),
|
|
2703
3235
|
versionConfig.configSchemaPath
|
|
2704
3236
|
);
|
|
2705
|
-
const schemaContent = await
|
|
3237
|
+
const schemaContent = await fs2.readFile(schemaPath, "utf-8");
|
|
2706
3238
|
const schemaData = JSON.parse(schemaContent);
|
|
2707
3239
|
configSchema = schemaData.schema;
|
|
2708
3240
|
} catch (error) {
|
|
@@ -3167,6 +3699,20 @@ exports.UniversalGraphService = __decorateClass([
|
|
|
3167
3699
|
__decorateParam(2, common.Inject("GRAPH_ENGINE")),
|
|
3168
3700
|
__decorateParam(3, common.Inject(exports.EndpointRegistry))
|
|
3169
3701
|
], exports.UniversalGraphService);
|
|
3702
|
+
function setupRedisMock() {
|
|
3703
|
+
if (process.env.NODE_ENV === "development" && !process.env.KUBERNETES_SERVICE_HOST) {
|
|
3704
|
+
console.log("[REDIS_MOCK] Intercepting ioredis requires for development");
|
|
3705
|
+
const Module2 = __require("module");
|
|
3706
|
+
const originalRequire = Module2.prototype.require;
|
|
3707
|
+
Module2.prototype.require = function(...args) {
|
|
3708
|
+
if (args[0] === "ioredis") {
|
|
3709
|
+
console.log("[REDIS_MOCK] Redirecting ioredis to ioredis-mock");
|
|
3710
|
+
return originalRequire.apply(this, ["ioredis-mock"]);
|
|
3711
|
+
}
|
|
3712
|
+
return originalRequire.apply(this, args);
|
|
3713
|
+
};
|
|
3714
|
+
}
|
|
3715
|
+
}
|
|
3170
3716
|
async function isPortAvailable(port) {
|
|
3171
3717
|
return new Promise((resolve2) => {
|
|
3172
3718
|
const server = net__namespace.createServer();
|
|
@@ -3188,10 +3734,110 @@ async function findAvailablePort(startPort) {
|
|
|
3188
3734
|
`No available ports found in range ${startPort}-${startPort + 99}`
|
|
3189
3735
|
);
|
|
3190
3736
|
}
|
|
3737
|
+
async function registerWithServiceDiscovery(AppModule, port, logger2, app) {
|
|
3738
|
+
try {
|
|
3739
|
+
logger2.debug(
|
|
3740
|
+
"[SERVICE_DISCOVERY] Starting service discovery registration..."
|
|
3741
|
+
);
|
|
3742
|
+
const { FileBasedDiscovery: FileBasedDiscovery2 } = await Promise.resolve().then(() => (init_file_based_discovery(), file_based_discovery_exports));
|
|
3743
|
+
logger2.debug(
|
|
3744
|
+
"[SERVICE_DISCOVERY] FileBasedDiscovery imported successfully"
|
|
3745
|
+
);
|
|
3746
|
+
const discovery = new FileBasedDiscovery2();
|
|
3747
|
+
logger2.debug("[SERVICE_DISCOVERY] FileBasedDiscovery instance created");
|
|
3748
|
+
const serviceName = AppModule.name.replace("Module", "").toLowerCase();
|
|
3749
|
+
let graphTypes = [];
|
|
3750
|
+
try {
|
|
3751
|
+
if (app) {
|
|
3752
|
+
const { BuilderRegistryService: BuilderRegistryService2 } = await Promise.resolve().then(() => (init_builder_registry_service(), builder_registry_service_exports));
|
|
3753
|
+
const builderRegistry = app.get(BuilderRegistryService2, {
|
|
3754
|
+
strict: false
|
|
3755
|
+
});
|
|
3756
|
+
logger2.debug(
|
|
3757
|
+
`BuilderRegistryService found in DI: ${!!builderRegistry}`
|
|
3758
|
+
);
|
|
3759
|
+
if (builderRegistry) {
|
|
3760
|
+
const builders = builderRegistry.getBuilders();
|
|
3761
|
+
logger2.debug(`Found ${builders.length} builders in registry`);
|
|
3762
|
+
const baseGraphTypes = builders.map((builder) => builder.graphType);
|
|
3763
|
+
logger2.debug(`Base graph types: [${baseGraphTypes.join(", ")}]`);
|
|
3764
|
+
try {
|
|
3765
|
+
logger2.debug("Attempting to import VersionedGraphService...");
|
|
3766
|
+
const { VersionedGraphService: VersionedGraphService2 } = await Promise.resolve().then(() => (init_versioned_graph_service(), versioned_graph_service_exports));
|
|
3767
|
+
logger2.debug("VersionedGraphService imported successfully");
|
|
3768
|
+
const versionedService = app.get(VersionedGraphService2, {
|
|
3769
|
+
strict: false
|
|
3770
|
+
});
|
|
3771
|
+
logger2.debug(
|
|
3772
|
+
`VersionedGraphService found in DI: ${!!versionedService}`
|
|
3773
|
+
);
|
|
3774
|
+
if (versionedService) {
|
|
3775
|
+
const allVersionedTypes = [];
|
|
3776
|
+
for (const baseType of baseGraphTypes) {
|
|
3777
|
+
logger2.debug(`Getting versions for base type: ${baseType}`);
|
|
3778
|
+
const versions = versionedService.getAvailableVersions(baseType);
|
|
3779
|
+
logger2.debug(
|
|
3780
|
+
`Found ${versions.length} versions for ${baseType}: [${versions.join(", ")}]`
|
|
3781
|
+
);
|
|
3782
|
+
if (versions.length > 0) {
|
|
3783
|
+
allVersionedTypes.push(baseType);
|
|
3784
|
+
versions.forEach((version) => {
|
|
3785
|
+
allVersionedTypes.push(`${baseType}::${version}`);
|
|
3786
|
+
});
|
|
3787
|
+
} else {
|
|
3788
|
+
allVersionedTypes.push(baseType);
|
|
3789
|
+
}
|
|
3790
|
+
}
|
|
3791
|
+
graphTypes = allVersionedTypes;
|
|
3792
|
+
logger2.debug(
|
|
3793
|
+
`Found ${baseGraphTypes.length} base types with ${graphTypes.length} total versioned types: ${graphTypes.join(", ")}`
|
|
3794
|
+
);
|
|
3795
|
+
} else {
|
|
3796
|
+
graphTypes = baseGraphTypes;
|
|
3797
|
+
logger2.debug(
|
|
3798
|
+
`VersionedGraphService not found in DI container, using base types: ${graphTypes.join(", ")}`
|
|
3799
|
+
);
|
|
3800
|
+
}
|
|
3801
|
+
} catch (error) {
|
|
3802
|
+
graphTypes = baseGraphTypes;
|
|
3803
|
+
logger2.debug(
|
|
3804
|
+
`Failed to get versioned types, using base types: ${error.message}`
|
|
3805
|
+
);
|
|
3806
|
+
logger2.debug(`Stack trace: ${error.stack}`);
|
|
3807
|
+
}
|
|
3808
|
+
}
|
|
3809
|
+
}
|
|
3810
|
+
} catch (error) {
|
|
3811
|
+
logger2.debug(`Failed to get graph types from builders: ${error.message}`);
|
|
3812
|
+
}
|
|
3813
|
+
if (graphTypes.length === 0) {
|
|
3814
|
+
logger2.debug("No builders found, using service name as graph type");
|
|
3815
|
+
graphTypes = [serviceName];
|
|
3816
|
+
}
|
|
3817
|
+
await discovery.registerService(
|
|
3818
|
+
serviceName,
|
|
3819
|
+
"localhost",
|
|
3820
|
+
port,
|
|
3821
|
+
{
|
|
3822
|
+
graphTypes,
|
|
3823
|
+
environment: "development",
|
|
3824
|
+
startTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3825
|
+
version: process.env.npm_package_version || "1.0.0"
|
|
3826
|
+
},
|
|
3827
|
+
graphTypes
|
|
3828
|
+
);
|
|
3829
|
+
logger2.log(
|
|
3830
|
+
`\u{1F4E1} Service registered with discovery: ${serviceName} (types: ${graphTypes.join(", ")})`
|
|
3831
|
+
);
|
|
3832
|
+
} catch (error) {
|
|
3833
|
+
logger2.warn(`Failed to register with service discovery: ${error.message}`);
|
|
3834
|
+
}
|
|
3835
|
+
}
|
|
3191
3836
|
async function bootstrap(AppModule, options = {}) {
|
|
3837
|
+
setupRedisMock();
|
|
3192
3838
|
const app = await core.NestFactory.create(AppModule);
|
|
3193
3839
|
const logger2 = new common.Logger("Bootstrap");
|
|
3194
|
-
const requestedPort = options.port || parseInt(process.env.PORT || "
|
|
3840
|
+
const requestedPort = options.port || parseInt(process.env.PORT || "3100", 10);
|
|
3195
3841
|
const port = await findAvailablePort(requestedPort);
|
|
3196
3842
|
const globalPrefix = options.globalPrefix;
|
|
3197
3843
|
if (port !== requestedPort) {
|
|
@@ -3212,63 +3858,27 @@ async function bootstrap(AppModule, options = {}) {
|
|
|
3212
3858
|
credentials: true
|
|
3213
3859
|
});
|
|
3214
3860
|
const config = new swagger.DocumentBuilder().setTitle("Graph Service API").setDescription("API for graph service microservice").setVersion("1.0").addBearerAuth().build();
|
|
3215
|
-
const document = swagger.SwaggerModule.createDocument(app, config);
|
|
3216
|
-
swagger.SwaggerModule.setup("api/docs", app, document);
|
|
3217
|
-
await app.listen(port);
|
|
3218
|
-
const baseUrl = globalPrefix ? `http://localhost:${port}/${globalPrefix}` : `http://localhost:${port}`;
|
|
3219
|
-
logger2.log(`\u{1F680} Graph service is running on: ${baseUrl}`);
|
|
3220
|
-
logger2.log(`\u{1F4DA} API Documentation: http://localhost:${port}/api/docs`);
|
|
3221
|
-
if (process.env.NODE_ENV !== "production")
|
|
3222
|
-
|
|
3223
|
-
}
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
);
|
|
3230
|
-
if (!existingBuilder) {
|
|
3231
|
-
this.builders.push(builder);
|
|
3232
|
-
}
|
|
3233
|
-
}
|
|
3234
|
-
getBuilders() {
|
|
3235
|
-
return this.builders;
|
|
3236
|
-
}
|
|
3237
|
-
};
|
|
3238
|
-
exports.BuilderRegistryService = __decorateClass([
|
|
3239
|
-
common.Injectable()
|
|
3240
|
-
], exports.BuilderRegistryService);
|
|
3241
|
-
var GraphEngineType = /* @__PURE__ */ ((GraphEngineType2) => {
|
|
3242
|
-
GraphEngineType2["LANGGRAPH"] = "langgraph";
|
|
3243
|
-
GraphEngineType2["LANGFLOW"] = "langflow";
|
|
3244
|
-
GraphEngineType2["FLOWISE"] = "flowise";
|
|
3245
|
-
return GraphEngineType2;
|
|
3246
|
-
})(GraphEngineType || {});
|
|
3247
|
-
exports.GraphEngineFactory = class GraphEngineFactory {
|
|
3248
|
-
constructor(langgraph) {
|
|
3249
|
-
this.langgraph = langgraph;
|
|
3250
|
-
}
|
|
3251
|
-
/**
|
|
3252
|
-
* Get engine for the specified type
|
|
3253
|
-
*/
|
|
3254
|
-
getEngine(engineType) {
|
|
3255
|
-
switch (engineType) {
|
|
3256
|
-
case "langgraph" /* LANGGRAPH */:
|
|
3257
|
-
return this.langgraph;
|
|
3258
|
-
// Will add other types in the future
|
|
3259
|
-
// case GraphEngineType.LANGFLOW:
|
|
3260
|
-
// return new LangFlowEngine();
|
|
3261
|
-
// case GraphEngineType.FLOWISE:
|
|
3262
|
-
// return new FlowiseEngine();
|
|
3263
|
-
default:
|
|
3264
|
-
throw new Error(`Unsupported graph engine type: ${engineType}`);
|
|
3265
|
-
}
|
|
3861
|
+
const document = swagger.SwaggerModule.createDocument(app, config);
|
|
3862
|
+
swagger.SwaggerModule.setup("api/docs", app, document);
|
|
3863
|
+
await app.listen(port);
|
|
3864
|
+
const baseUrl = globalPrefix ? `http://localhost:${port}/${globalPrefix}` : `http://localhost:${port}`;
|
|
3865
|
+
logger2.log(`\u{1F680} Graph service is running on: ${baseUrl}`);
|
|
3866
|
+
logger2.log(`\u{1F4DA} API Documentation: http://localhost:${port}/api/docs`);
|
|
3867
|
+
if (process.env.NODE_ENV !== "production") {
|
|
3868
|
+
logger2.debug(
|
|
3869
|
+
`Attempting service discovery registration (NODE_ENV: ${process.env.NODE_ENV || "undefined"})`
|
|
3870
|
+
);
|
|
3871
|
+
await registerWithServiceDiscovery(AppModule, port, logger2, app);
|
|
3872
|
+
} else {
|
|
3873
|
+
logger2.debug(
|
|
3874
|
+
`Skipping service discovery registration (NODE_ENV: ${process.env.NODE_ENV})`
|
|
3875
|
+
);
|
|
3266
3876
|
}
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3877
|
+
return app;
|
|
3878
|
+
}
|
|
3879
|
+
|
|
3880
|
+
// src/core/index.ts
|
|
3881
|
+
init_builder_registry_service();
|
|
3272
3882
|
|
|
3273
3883
|
// src/messages/attachments.ts
|
|
3274
3884
|
var AttachmentType = /* @__PURE__ */ ((AttachmentType2) => {
|
|
@@ -3650,274 +4260,8 @@ ${result.errors.join("\n")}`
|
|
|
3650
4260
|
}
|
|
3651
4261
|
};
|
|
3652
4262
|
|
|
3653
|
-
// src/
|
|
3654
|
-
|
|
3655
|
-
/**
|
|
3656
|
-
* Parse full graph type
|
|
3657
|
-
* @param fullType - full graph type
|
|
3658
|
-
* @returns object with type components
|
|
3659
|
-
*/
|
|
3660
|
-
static parse(fullType) {
|
|
3661
|
-
if (fullType.includes("::")) {
|
|
3662
|
-
const [baseType, version] = fullType.split("::");
|
|
3663
|
-
const [companyId, name] = baseType.split(".");
|
|
3664
|
-
return { companyId, name, version };
|
|
3665
|
-
}
|
|
3666
|
-
const parts = fullType.split(".");
|
|
3667
|
-
if (parts.length === 1) {
|
|
3668
|
-
return { companyId: "global", name: parts[0] };
|
|
3669
|
-
}
|
|
3670
|
-
return { companyId: parts[0], name: parts[1] };
|
|
3671
|
-
}
|
|
3672
|
-
/**
|
|
3673
|
-
* Build full type from components
|
|
3674
|
-
* @param companyId - company ID
|
|
3675
|
-
* @param name - graph name
|
|
3676
|
-
* @param version - version (optional)
|
|
3677
|
-
* @returns full graph type
|
|
3678
|
-
*/
|
|
3679
|
-
static build(companyId, name, version) {
|
|
3680
|
-
const base = `${companyId}.${name}`;
|
|
3681
|
-
return version ? `${base}::${version}` : base;
|
|
3682
|
-
}
|
|
3683
|
-
/**
|
|
3684
|
-
* Normalize graph type for backward compatibility
|
|
3685
|
-
* @param graphType - graph type in any format
|
|
3686
|
-
* @returns normalized type
|
|
3687
|
-
*/
|
|
3688
|
-
static normalize(graphType) {
|
|
3689
|
-
const { companyId, name, version } = this.parse(graphType);
|
|
3690
|
-
return this.build(companyId, name, version);
|
|
3691
|
-
}
|
|
3692
|
-
/**
|
|
3693
|
-
* Get base type without version
|
|
3694
|
-
* @param graphType - full graph type
|
|
3695
|
-
* @returns base type
|
|
3696
|
-
*/
|
|
3697
|
-
static getBaseType(graphType) {
|
|
3698
|
-
if (graphType.includes("::")) {
|
|
3699
|
-
return graphType.split("::")[0];
|
|
3700
|
-
}
|
|
3701
|
-
const { companyId, name } = this.parse(graphType);
|
|
3702
|
-
return `${companyId}.${name}`;
|
|
3703
|
-
}
|
|
3704
|
-
/**
|
|
3705
|
-
* Extract version from graph type
|
|
3706
|
-
* @param graphType - full graph type
|
|
3707
|
-
* @returns version or undefined
|
|
3708
|
-
*/
|
|
3709
|
-
static getVersion(graphType) {
|
|
3710
|
-
return graphType.includes("::") ? graphType.split("::")[1] : void 0;
|
|
3711
|
-
}
|
|
3712
|
-
/**
|
|
3713
|
-
* Validate version (basic semver check)
|
|
3714
|
-
* @param version - version to check
|
|
3715
|
-
* @returns true if version is valid
|
|
3716
|
-
*/
|
|
3717
|
-
static isValidVersion(version) {
|
|
3718
|
-
const semverRegex = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?$/;
|
|
3719
|
-
return semverRegex.test(version);
|
|
3720
|
-
}
|
|
3721
|
-
/**
|
|
3722
|
-
* Check if type is system (global)
|
|
3723
|
-
* @param graphType - graph type
|
|
3724
|
-
* @returns true if graph is system
|
|
3725
|
-
*/
|
|
3726
|
-
static isSystemGraph(graphType) {
|
|
3727
|
-
const { companyId } = this.parse(graphType);
|
|
3728
|
-
return companyId === "global";
|
|
3729
|
-
}
|
|
3730
|
-
/**
|
|
3731
|
-
* Compare versions (simple comparison for sorting)
|
|
3732
|
-
* @param a - first version
|
|
3733
|
-
* @param b - second version
|
|
3734
|
-
* @returns -1, 0, 1 for sorting
|
|
3735
|
-
*/
|
|
3736
|
-
static compareVersions(a, b) {
|
|
3737
|
-
const parseVersion = (v) => {
|
|
3738
|
-
const [main, prerelease] = v.split("-");
|
|
3739
|
-
const [major, minor, patch] = main.split(".").map(Number);
|
|
3740
|
-
return { major, minor, patch, prerelease };
|
|
3741
|
-
};
|
|
3742
|
-
const versionA = parseVersion(a);
|
|
3743
|
-
const versionB = parseVersion(b);
|
|
3744
|
-
if (versionA.major !== versionB.major) {
|
|
3745
|
-
return versionA.major - versionB.major;
|
|
3746
|
-
}
|
|
3747
|
-
if (versionA.minor !== versionB.minor) {
|
|
3748
|
-
return versionA.minor - versionB.minor;
|
|
3749
|
-
}
|
|
3750
|
-
if (versionA.patch !== versionB.patch) {
|
|
3751
|
-
return versionA.patch - versionB.patch;
|
|
3752
|
-
}
|
|
3753
|
-
if (versionA.prerelease && !versionB.prerelease) return -1;
|
|
3754
|
-
if (!versionA.prerelease && versionB.prerelease) return 1;
|
|
3755
|
-
if (versionA.prerelease && versionB.prerelease) {
|
|
3756
|
-
return versionA.prerelease.localeCompare(versionB.prerelease);
|
|
3757
|
-
}
|
|
3758
|
-
return 0;
|
|
3759
|
-
}
|
|
3760
|
-
};
|
|
3761
|
-
|
|
3762
|
-
// src/graph/versioning/versioned-graph.service.ts
|
|
3763
|
-
exports.VersionedGraphService = class VersionedGraphService {
|
|
3764
|
-
logger = new common.Logger(exports.VersionedGraphService.name);
|
|
3765
|
-
versionConfigs = /* @__PURE__ */ new Map();
|
|
3766
|
-
constructor() {
|
|
3767
|
-
}
|
|
3768
|
-
/**
|
|
3769
|
-
* Register versioning configuration
|
|
3770
|
-
*/
|
|
3771
|
-
registerVersioning(config) {
|
|
3772
|
-
this.versionConfigs.set(config.baseGraphType, config);
|
|
3773
|
-
this.logger.log(
|
|
3774
|
-
`Registered versioning for ${config.baseGraphType} with ${config.versions.length} versions`
|
|
3775
|
-
);
|
|
3776
|
-
}
|
|
3777
|
-
/**
|
|
3778
|
-
* Resolve graph version
|
|
3779
|
-
*/
|
|
3780
|
-
async resolveVersion(graphType, options = {}) {
|
|
3781
|
-
const parsed = GraphTypeUtils.parse(graphType);
|
|
3782
|
-
const baseType = GraphTypeUtils.getBaseType(graphType);
|
|
3783
|
-
const requestedVersion = GraphTypeUtils.getVersion(graphType) || options.requestedVersion;
|
|
3784
|
-
const config = this.versionConfigs.get(baseType);
|
|
3785
|
-
if (!config) {
|
|
3786
|
-
throw new Error(`No versioning configuration found for ${baseType}`);
|
|
3787
|
-
}
|
|
3788
|
-
const route = this.findBestVersionRoute(config, requestedVersion, options);
|
|
3789
|
-
if (!route) {
|
|
3790
|
-
throw new Error(
|
|
3791
|
-
`No compatible version found for ${graphType} with options: ${JSON.stringify(options)}`
|
|
3792
|
-
);
|
|
3793
|
-
}
|
|
3794
|
-
const fullGraphType = GraphTypeUtils.build(
|
|
3795
|
-
parsed.companyId,
|
|
3796
|
-
parsed.name,
|
|
3797
|
-
route.version
|
|
3798
|
-
);
|
|
3799
|
-
return {
|
|
3800
|
-
version: route.version,
|
|
3801
|
-
builderClass: route.builderClass,
|
|
3802
|
-
fullGraphType
|
|
3803
|
-
};
|
|
3804
|
-
}
|
|
3805
|
-
/**
|
|
3806
|
-
* Create builder for specified version
|
|
3807
|
-
*/
|
|
3808
|
-
async createVersionedBuilder(graphType, moduleRef, options = {}) {
|
|
3809
|
-
const resolution = await this.resolveVersion(graphType, options);
|
|
3810
|
-
try {
|
|
3811
|
-
if (!moduleRef) {
|
|
3812
|
-
throw new Error(
|
|
3813
|
-
"ModuleRef is not available - falling back to direct instantiation"
|
|
3814
|
-
);
|
|
3815
|
-
}
|
|
3816
|
-
const builder = await moduleRef.create(resolution.builderClass);
|
|
3817
|
-
this.logger.debug(
|
|
3818
|
-
`Created versioned builder for ${resolution.fullGraphType}`
|
|
3819
|
-
);
|
|
3820
|
-
return builder;
|
|
3821
|
-
} catch (error) {
|
|
3822
|
-
this.logger.error(
|
|
3823
|
-
`Failed to create builder for ${resolution.fullGraphType}: ${error.message}`
|
|
3824
|
-
);
|
|
3825
|
-
throw new Error(`Failed to create versioned builder: ${error.message}`);
|
|
3826
|
-
}
|
|
3827
|
-
}
|
|
3828
|
-
/**
|
|
3829
|
-
* Get all available versions for a graph
|
|
3830
|
-
*/
|
|
3831
|
-
getAvailableVersions(baseGraphType) {
|
|
3832
|
-
const config = this.versionConfigs.get(baseGraphType);
|
|
3833
|
-
if (!config) {
|
|
3834
|
-
return [];
|
|
3835
|
-
}
|
|
3836
|
-
return config.versions.map((route) => route.version).sort((a, b) => GraphTypeUtils.compareVersions(b, a));
|
|
3837
|
-
}
|
|
3838
|
-
/**
|
|
3839
|
-
* Check version support
|
|
3840
|
-
*/
|
|
3841
|
-
isVersionSupported(graphType, options = {}) {
|
|
3842
|
-
try {
|
|
3843
|
-
const baseType = GraphTypeUtils.getBaseType(graphType);
|
|
3844
|
-
const requestedVersion = GraphTypeUtils.getVersion(graphType);
|
|
3845
|
-
const config = this.versionConfigs.get(baseType);
|
|
3846
|
-
if (!config) {
|
|
3847
|
-
return false;
|
|
3848
|
-
}
|
|
3849
|
-
const route = this.findBestVersionRoute(
|
|
3850
|
-
config,
|
|
3851
|
-
requestedVersion,
|
|
3852
|
-
options
|
|
3853
|
-
);
|
|
3854
|
-
return route !== null;
|
|
3855
|
-
} catch {
|
|
3856
|
-
return false;
|
|
3857
|
-
}
|
|
3858
|
-
}
|
|
3859
|
-
/**
|
|
3860
|
-
* Find best version
|
|
3861
|
-
*/
|
|
3862
|
-
findBestVersionRoute(config, requestedVersion, options = {}) {
|
|
3863
|
-
const { strict = false } = options;
|
|
3864
|
-
let candidates = [...config.versions];
|
|
3865
|
-
if (requestedVersion) {
|
|
3866
|
-
const exactMatch = candidates.find(
|
|
3867
|
-
(route) => route.version === requestedVersion
|
|
3868
|
-
);
|
|
3869
|
-
if (exactMatch) {
|
|
3870
|
-
return exactMatch;
|
|
3871
|
-
}
|
|
3872
|
-
if (strict) {
|
|
3873
|
-
return null;
|
|
3874
|
-
}
|
|
3875
|
-
const compatibleVersions = candidates.filter(
|
|
3876
|
-
(route) => this.isVersionCompatible(requestedVersion, route.version)
|
|
3877
|
-
);
|
|
3878
|
-
if (compatibleVersions.length > 0) {
|
|
3879
|
-
return compatibleVersions.sort(
|
|
3880
|
-
(a, b) => GraphTypeUtils.compareVersions(b.version, a.version)
|
|
3881
|
-
)[0];
|
|
3882
|
-
}
|
|
3883
|
-
}
|
|
3884
|
-
const defaultRoute = candidates.find((route) => route.isDefault);
|
|
3885
|
-
if (defaultRoute) {
|
|
3886
|
-
return defaultRoute;
|
|
3887
|
-
}
|
|
3888
|
-
if (config.defaultVersionStrategy === "latest" || !config.defaultVersionStrategy) {
|
|
3889
|
-
const sortedVersions = candidates.sort(
|
|
3890
|
-
(a, b) => GraphTypeUtils.compareVersions(b.version, a.version)
|
|
3891
|
-
);
|
|
3892
|
-
return sortedVersions[0] || null;
|
|
3893
|
-
}
|
|
3894
|
-
return null;
|
|
3895
|
-
}
|
|
3896
|
-
/**
|
|
3897
|
-
* Check version compatibility (simplified semantics)
|
|
3898
|
-
*/
|
|
3899
|
-
isVersionCompatible(requested, available) {
|
|
3900
|
-
try {
|
|
3901
|
-
const requestedParts = requested.split(".").map(Number);
|
|
3902
|
-
const availableParts = available.split(".").map(Number);
|
|
3903
|
-
if (requestedParts[0] !== availableParts[0]) {
|
|
3904
|
-
return false;
|
|
3905
|
-
}
|
|
3906
|
-
return GraphTypeUtils.compareVersions(available, requested) >= 0;
|
|
3907
|
-
} catch {
|
|
3908
|
-
return false;
|
|
3909
|
-
}
|
|
3910
|
-
}
|
|
3911
|
-
/**
|
|
3912
|
-
* Get versioning configuration information
|
|
3913
|
-
*/
|
|
3914
|
-
getVersioningInfo(baseGraphType) {
|
|
3915
|
-
return this.versionConfigs.get(baseGraphType) || null;
|
|
3916
|
-
}
|
|
3917
|
-
};
|
|
3918
|
-
exports.VersionedGraphService = __decorateClass([
|
|
3919
|
-
common.Injectable()
|
|
3920
|
-
], exports.VersionedGraphService);
|
|
4263
|
+
// src/graph/versioning/index.ts
|
|
4264
|
+
init_versioned_graph_service();
|
|
3921
4265
|
var logger = new common.Logger("ApiCallTracer");
|
|
3922
4266
|
var DEFAULT_TRACER_OPTIONS = {
|
|
3923
4267
|
maxStringLength: 5e3,
|
|
@@ -4061,8 +4405,36 @@ function sanitizeTraceError(error, options) {
|
|
|
4061
4405
|
raw: sanitizeTraceData(error, 0, /* @__PURE__ */ new WeakSet(), options)
|
|
4062
4406
|
};
|
|
4063
4407
|
}
|
|
4064
|
-
|
|
4065
|
-
|
|
4408
|
+
var GraphEngineType = /* @__PURE__ */ ((GraphEngineType2) => {
|
|
4409
|
+
GraphEngineType2["LANGGRAPH"] = "langgraph";
|
|
4410
|
+
GraphEngineType2["LANGFLOW"] = "langflow";
|
|
4411
|
+
GraphEngineType2["FLOWISE"] = "flowise";
|
|
4412
|
+
return GraphEngineType2;
|
|
4413
|
+
})(GraphEngineType || {});
|
|
4414
|
+
exports.GraphEngineFactory = class GraphEngineFactory {
|
|
4415
|
+
constructor(langgraph) {
|
|
4416
|
+
this.langgraph = langgraph;
|
|
4417
|
+
}
|
|
4418
|
+
/**
|
|
4419
|
+
* Get engine for the specified type
|
|
4420
|
+
*/
|
|
4421
|
+
getEngine(engineType) {
|
|
4422
|
+
switch (engineType) {
|
|
4423
|
+
case "langgraph" /* LANGGRAPH */:
|
|
4424
|
+
return this.langgraph;
|
|
4425
|
+
// Will add other types in the future
|
|
4426
|
+
// case GraphEngineType.LANGFLOW:
|
|
4427
|
+
// return new LangFlowEngine();
|
|
4428
|
+
// case GraphEngineType.FLOWISE:
|
|
4429
|
+
// return new FlowiseEngine();
|
|
4430
|
+
default:
|
|
4431
|
+
throw new Error(`Unsupported graph engine type: ${engineType}`);
|
|
4432
|
+
}
|
|
4433
|
+
}
|
|
4434
|
+
};
|
|
4435
|
+
exports.GraphEngineFactory = __decorateClass([
|
|
4436
|
+
common.Injectable()
|
|
4437
|
+
], exports.GraphEngineFactory);
|
|
4066
4438
|
exports.EventProcessor = class EventProcessor {
|
|
4067
4439
|
logger = new common.Logger(exports.EventProcessor.name);
|
|
4068
4440
|
/**
|
|
@@ -4076,7 +4448,9 @@ exports.EventProcessor = class EventProcessor {
|
|
|
4076
4448
|
llmCalls: [],
|
|
4077
4449
|
traceEvents: [],
|
|
4078
4450
|
traceStartedAt: null,
|
|
4079
|
-
traceCompletedAt: null
|
|
4451
|
+
traceCompletedAt: null,
|
|
4452
|
+
currentReasoningSteps: [],
|
|
4453
|
+
currentToolUse: null
|
|
4080
4454
|
};
|
|
4081
4455
|
}
|
|
4082
4456
|
/**
|
|
@@ -4104,6 +4478,51 @@ exports.EventProcessor = class EventProcessor {
|
|
|
4104
4478
|
}
|
|
4105
4479
|
return [];
|
|
4106
4480
|
}
|
|
4481
|
+
/**
|
|
4482
|
+
* Groups tool_use and input_json_delta into proper structure
|
|
4483
|
+
* tool_use.input → output (tool execution result)
|
|
4484
|
+
* input_json_delta.input → output (tool execution result, accumulated)
|
|
4485
|
+
*/
|
|
4486
|
+
mapReasoningSteps(rawSteps) {
|
|
4487
|
+
const steps = [];
|
|
4488
|
+
let currentToolUse = null;
|
|
4489
|
+
for (const raw of rawSteps) {
|
|
4490
|
+
if (raw.type === "tool_use" || raw.type === "tool_call") {
|
|
4491
|
+
if (currentToolUse) {
|
|
4492
|
+
steps.push(currentToolUse);
|
|
4493
|
+
}
|
|
4494
|
+
currentToolUse = {
|
|
4495
|
+
index: raw.index || 0,
|
|
4496
|
+
type: "tool_use",
|
|
4497
|
+
name: raw.name,
|
|
4498
|
+
id: raw.id,
|
|
4499
|
+
input: "",
|
|
4500
|
+
// Parameters (IN) - filled separately or empty
|
|
4501
|
+
output: raw.input || ""
|
|
4502
|
+
// Result (OUT) - comes in tool_use.input
|
|
4503
|
+
};
|
|
4504
|
+
} else if (raw.type === "input_json_delta") {
|
|
4505
|
+
if (currentToolUse) {
|
|
4506
|
+
currentToolUse.output = (currentToolUse.output || "") + (raw.input || "");
|
|
4507
|
+
}
|
|
4508
|
+
} else {
|
|
4509
|
+
if (currentToolUse) {
|
|
4510
|
+
steps.push(currentToolUse);
|
|
4511
|
+
currentToolUse = null;
|
|
4512
|
+
}
|
|
4513
|
+
steps.push({
|
|
4514
|
+
index: raw.index || 0,
|
|
4515
|
+
type: raw.type,
|
|
4516
|
+
text: raw.text || "",
|
|
4517
|
+
metadata: raw.metadata
|
|
4518
|
+
});
|
|
4519
|
+
}
|
|
4520
|
+
}
|
|
4521
|
+
if (currentToolUse) {
|
|
4522
|
+
steps.push(currentToolUse);
|
|
4523
|
+
}
|
|
4524
|
+
return steps;
|
|
4525
|
+
}
|
|
4107
4526
|
/**
|
|
4108
4527
|
* Process a LangGraph stream event
|
|
4109
4528
|
* Mutates accumulator to collect data from different channels
|
|
@@ -4126,8 +4545,44 @@ exports.EventProcessor = class EventProcessor {
|
|
|
4126
4545
|
if (event.event === "on_chat_model_stream" && event.metadata?.stream_channel === "processing" /* PROCESSING */ && event.data?.chunk?.content) {
|
|
4127
4546
|
const chunk = event.data.chunk.content;
|
|
4128
4547
|
const blocks = this.normalizeContentBlocks(chunk);
|
|
4129
|
-
|
|
4130
|
-
|
|
4548
|
+
for (const block of blocks) {
|
|
4549
|
+
if (block.type === "tool_use" || block.type === "tool_call") {
|
|
4550
|
+
if (acc.currentToolUse) {
|
|
4551
|
+
acc.currentReasoningSteps.push(acc.currentToolUse);
|
|
4552
|
+
}
|
|
4553
|
+
acc.currentToolUse = {
|
|
4554
|
+
index: acc.currentReasoningSteps.length,
|
|
4555
|
+
type: "tool_use",
|
|
4556
|
+
name: block.name,
|
|
4557
|
+
id: block.id,
|
|
4558
|
+
input: block.input || "",
|
|
4559
|
+
output: ""
|
|
4560
|
+
};
|
|
4561
|
+
if (onPartial) {
|
|
4562
|
+
onPartial(
|
|
4563
|
+
JSON.stringify({
|
|
4564
|
+
processing_delta: {
|
|
4565
|
+
type: "step_started",
|
|
4566
|
+
step: acc.currentToolUse
|
|
4567
|
+
}
|
|
4568
|
+
})
|
|
4569
|
+
);
|
|
4570
|
+
}
|
|
4571
|
+
} else if (block.type === "input_json_delta") {
|
|
4572
|
+
if (acc.currentToolUse && onPartial) {
|
|
4573
|
+
const chunk2 = block.input || "";
|
|
4574
|
+
acc.currentToolUse.output += chunk2;
|
|
4575
|
+
onPartial(
|
|
4576
|
+
JSON.stringify({
|
|
4577
|
+
processing_delta: {
|
|
4578
|
+
type: "output_chunk",
|
|
4579
|
+
stepId: acc.currentToolUse.id,
|
|
4580
|
+
chunk: chunk2
|
|
4581
|
+
}
|
|
4582
|
+
})
|
|
4583
|
+
);
|
|
4584
|
+
}
|
|
4585
|
+
}
|
|
4131
4586
|
}
|
|
4132
4587
|
return;
|
|
4133
4588
|
}
|
|
@@ -4164,29 +4619,59 @@ exports.EventProcessor = class EventProcessor {
|
|
|
4164
4619
|
);
|
|
4165
4620
|
}
|
|
4166
4621
|
if (event.metadata?.stream_channel === "processing" /* PROCESSING */) {
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
[];
|
|
4171
|
-
let steps;
|
|
4172
|
-
if (Array.isArray(stepsRaw)) {
|
|
4173
|
-
steps = stepsRaw;
|
|
4174
|
-
} else if (typeof stepsRaw === "string" && stepsRaw.trim().length > 0) {
|
|
4175
|
-
steps = [
|
|
4176
|
-
{
|
|
4177
|
-
index: 0,
|
|
4178
|
-
type: "text",
|
|
4179
|
-
text: stepsRaw.trim()
|
|
4180
|
-
}
|
|
4181
|
-
];
|
|
4182
|
-
} else {
|
|
4183
|
-
steps = [];
|
|
4622
|
+
if (acc.currentToolUse) {
|
|
4623
|
+
acc.currentReasoningSteps.push(acc.currentToolUse);
|
|
4624
|
+
acc.currentToolUse = null;
|
|
4184
4625
|
}
|
|
4185
|
-
if (
|
|
4626
|
+
if (acc.currentReasoningSteps.length > 0) {
|
|
4186
4627
|
acc.reasoningChains.push({
|
|
4187
|
-
steps,
|
|
4628
|
+
steps: acc.currentReasoningSteps,
|
|
4188
4629
|
isComplete: true
|
|
4189
4630
|
});
|
|
4631
|
+
if (onPartial) {
|
|
4632
|
+
onPartial(
|
|
4633
|
+
JSON.stringify({
|
|
4634
|
+
processing_delta: {
|
|
4635
|
+
type: "chain_completed"
|
|
4636
|
+
}
|
|
4637
|
+
})
|
|
4638
|
+
);
|
|
4639
|
+
}
|
|
4640
|
+
acc.currentReasoningSteps = [];
|
|
4641
|
+
} else {
|
|
4642
|
+
const stepsRaw = output?.content || // AIMessageChunk object (direct)
|
|
4643
|
+
output?.kwargs?.content || // Serialized LangChain format
|
|
4644
|
+
event.data?.chunk?.content || // Older version
|
|
4645
|
+
[];
|
|
4646
|
+
let steps;
|
|
4647
|
+
if (Array.isArray(stepsRaw)) {
|
|
4648
|
+
steps = this.mapReasoningSteps(stepsRaw);
|
|
4649
|
+
} else if (typeof stepsRaw === "string" && stepsRaw.trim().length > 0) {
|
|
4650
|
+
steps = [
|
|
4651
|
+
{
|
|
4652
|
+
index: 0,
|
|
4653
|
+
type: "text",
|
|
4654
|
+
text: stepsRaw.trim()
|
|
4655
|
+
}
|
|
4656
|
+
];
|
|
4657
|
+
} else {
|
|
4658
|
+
steps = [];
|
|
4659
|
+
}
|
|
4660
|
+
if (steps.length > 0) {
|
|
4661
|
+
acc.reasoningChains.push({
|
|
4662
|
+
steps,
|
|
4663
|
+
isComplete: true
|
|
4664
|
+
});
|
|
4665
|
+
if (onPartial) {
|
|
4666
|
+
onPartial(
|
|
4667
|
+
JSON.stringify({
|
|
4668
|
+
processing_delta: {
|
|
4669
|
+
type: "chain_completed"
|
|
4670
|
+
}
|
|
4671
|
+
})
|
|
4672
|
+
);
|
|
4673
|
+
}
|
|
4674
|
+
}
|
|
4190
4675
|
}
|
|
4191
4676
|
}
|
|
4192
4677
|
return;
|
|
@@ -4595,12 +5080,11 @@ exports.LangGraphEngine = class LangGraphEngine {
|
|
|
4595
5080
|
}
|
|
4596
5081
|
};
|
|
4597
5082
|
exports.LangGraphEngine = __decorateClass([
|
|
4598
|
-
common.Injectable()
|
|
4599
|
-
__decorateParam(0, common.Inject())
|
|
5083
|
+
common.Injectable()
|
|
4600
5084
|
], exports.LangGraphEngine);
|
|
4601
5085
|
|
|
4602
5086
|
// src/core/universal-graph.module.ts
|
|
4603
|
-
|
|
5087
|
+
init_builder_registry_service();
|
|
4604
5088
|
init_agent_ui();
|
|
4605
5089
|
function createMetaBuilder(config, versionedGraphService, moduleRef, callbackRegistry, endpointRegistry) {
|
|
4606
5090
|
const className = `${config.baseGraphType.replace(/\./g, "")}VersionRouter`;
|
|
@@ -4669,6 +5153,8 @@ function createMetaBuilder(config, versionedGraphService, moduleRef, callbackReg
|
|
|
4669
5153
|
exports.UniversalGraphModule = class UniversalGraphModule {
|
|
4670
5154
|
static forRoot(options) {
|
|
4671
5155
|
const providers = [
|
|
5156
|
+
// Discovery services from @nestjs/core
|
|
5157
|
+
core.MetadataScanner,
|
|
4672
5158
|
// Event processor for stream handling
|
|
4673
5159
|
exports.EventProcessor,
|
|
4674
5160
|
// Graph engines
|
|
@@ -4698,14 +5184,8 @@ exports.UniversalGraphModule = class UniversalGraphModule {
|
|
|
4698
5184
|
provide: CallbackRegistry,
|
|
4699
5185
|
useClass: CallbackRegistry
|
|
4700
5186
|
},
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
useClass: exports.EndpointRegistry
|
|
4704
|
-
},
|
|
4705
|
-
{
|
|
4706
|
-
provide: exports.UIEndpointsDiscoveryService,
|
|
4707
|
-
useClass: exports.UIEndpointsDiscoveryService
|
|
4708
|
-
},
|
|
5187
|
+
exports.EndpointRegistry,
|
|
5188
|
+
exports.UIEndpointsDiscoveryService,
|
|
4709
5189
|
{
|
|
4710
5190
|
provide: exports.CallbackACL,
|
|
4711
5191
|
useClass: exports.CallbackACL
|
|
@@ -4782,14 +5262,6 @@ exports.UniversalGraphModule = class UniversalGraphModule {
|
|
|
4782
5262
|
},
|
|
4783
5263
|
inject: [CallbackRegistry]
|
|
4784
5264
|
},
|
|
4785
|
-
{
|
|
4786
|
-
provide: "UI_ENDPOINTS_DISCOVERY",
|
|
4787
|
-
useFactory: async (discoveryService) => {
|
|
4788
|
-
await discoveryService.discoverUIEndpoints();
|
|
4789
|
-
return true;
|
|
4790
|
-
},
|
|
4791
|
-
inject: [exports.UIEndpointsDiscoveryService]
|
|
4792
|
-
},
|
|
4793
5265
|
{
|
|
4794
5266
|
provide: "GRAPH_ENGINE",
|
|
4795
5267
|
useFactory: (factory) => {
|
|
@@ -5209,6 +5681,94 @@ var McpToolFilter = class _McpToolFilter {
|
|
|
5209
5681
|
}
|
|
5210
5682
|
}
|
|
5211
5683
|
};
|
|
5684
|
+
exports.McpRuntimeHttpClient = class McpRuntimeHttpClient {
|
|
5685
|
+
logger = new common.Logger(exports.McpRuntimeHttpClient.name);
|
|
5686
|
+
httpClient;
|
|
5687
|
+
baseUrl;
|
|
5688
|
+
constructor(mcpRuntimeUrl) {
|
|
5689
|
+
this.baseUrl = mcpRuntimeUrl || process.env.MCP_RUNTIME_URL || "http://localhost:3004";
|
|
5690
|
+
this.httpClient = axios2__default.default.create({
|
|
5691
|
+
baseURL: this.baseUrl,
|
|
5692
|
+
timeout: 3e4
|
|
5693
|
+
// 30 seconds
|
|
5694
|
+
});
|
|
5695
|
+
this.logger.log(
|
|
5696
|
+
`MCP Runtime HTTP Client initialized with URL: ${this.baseUrl}`
|
|
5697
|
+
);
|
|
5698
|
+
}
|
|
5699
|
+
/**
|
|
5700
|
+
* Get all available tools from MCP Runtime
|
|
5701
|
+
*/
|
|
5702
|
+
async getTools() {
|
|
5703
|
+
try {
|
|
5704
|
+
this.logger.debug("Fetching available tools from MCP runtime");
|
|
5705
|
+
const response = await this.httpClient.get("/tools/list");
|
|
5706
|
+
const tools = Array.isArray(response.data) ? response.data : [];
|
|
5707
|
+
this.logger.log(`Retrieved ${tools.length} tools from MCP runtime`);
|
|
5708
|
+
return tools;
|
|
5709
|
+
} catch (error) {
|
|
5710
|
+
this.logger.error("Failed to fetch tools from MCP runtime:", error);
|
|
5711
|
+
throw new Error(`Failed to fetch tools: ${error.message}`);
|
|
5712
|
+
}
|
|
5713
|
+
}
|
|
5714
|
+
/**
|
|
5715
|
+
* Execute a tool by name with given arguments
|
|
5716
|
+
*/
|
|
5717
|
+
async executeTool(name, args, context) {
|
|
5718
|
+
try {
|
|
5719
|
+
this.logger.debug(`Executing tool: ${name} with args:`, args);
|
|
5720
|
+
const payload = {
|
|
5721
|
+
name,
|
|
5722
|
+
arguments: args || {}
|
|
5723
|
+
};
|
|
5724
|
+
if (context) {
|
|
5725
|
+
payload.context = context;
|
|
5726
|
+
}
|
|
5727
|
+
const response = await this.httpClient.post("/tools/execute", payload);
|
|
5728
|
+
this.logger.log(`Tool ${name} executed successfully`);
|
|
5729
|
+
return response.data;
|
|
5730
|
+
} catch (error) {
|
|
5731
|
+
this.logger.error(`Failed to execute tool ${name}:`, error);
|
|
5732
|
+
if (error.response) {
|
|
5733
|
+
return {
|
|
5734
|
+
success: false,
|
|
5735
|
+
error: error.response.data.message || error.response.data.error || "Tool execution failed"
|
|
5736
|
+
};
|
|
5737
|
+
}
|
|
5738
|
+
return {
|
|
5739
|
+
success: false,
|
|
5740
|
+
error: error.message || "Unknown error occurred"
|
|
5741
|
+
};
|
|
5742
|
+
}
|
|
5743
|
+
}
|
|
5744
|
+
/**
|
|
5745
|
+
* Get tool execution statistics from MCP Runtime
|
|
5746
|
+
*/
|
|
5747
|
+
async getToolStats() {
|
|
5748
|
+
try {
|
|
5749
|
+
const response = await this.httpClient.get("/tools/stats");
|
|
5750
|
+
return response.data;
|
|
5751
|
+
} catch (error) {
|
|
5752
|
+
this.logger.error("Failed to fetch tool stats:", error);
|
|
5753
|
+
return null;
|
|
5754
|
+
}
|
|
5755
|
+
}
|
|
5756
|
+
/**
|
|
5757
|
+
* Health check for MCP Runtime service
|
|
5758
|
+
*/
|
|
5759
|
+
async isHealthy() {
|
|
5760
|
+
try {
|
|
5761
|
+
const response = await this.httpClient.get("/", { timeout: 5e3 });
|
|
5762
|
+
return response.status === 200;
|
|
5763
|
+
} catch (error) {
|
|
5764
|
+
this.logger.warn("MCP Runtime health check failed:", error.message);
|
|
5765
|
+
return false;
|
|
5766
|
+
}
|
|
5767
|
+
}
|
|
5768
|
+
};
|
|
5769
|
+
exports.McpRuntimeHttpClient = __decorateClass([
|
|
5770
|
+
common.Injectable()
|
|
5771
|
+
], exports.McpRuntimeHttpClient);
|
|
5212
5772
|
|
|
5213
5773
|
// src/models/enums.ts
|
|
5214
5774
|
var ModelProvider = /* @__PURE__ */ ((ModelProvider2) => {
|
|
@@ -6370,6 +6930,28 @@ exports.RetrieverService = __decorateClass([
|
|
|
6370
6930
|
common.Injectable()
|
|
6371
6931
|
], exports.RetrieverService);
|
|
6372
6932
|
|
|
6933
|
+
// src/utils/index.ts
|
|
6934
|
+
init_graph_type_utils();
|
|
6935
|
+
|
|
6936
|
+
// src/service-discovery/index.ts
|
|
6937
|
+
init_file_based_discovery();
|
|
6938
|
+
exports.StaticDiscovery = class StaticDiscovery {
|
|
6939
|
+
constructor(services) {
|
|
6940
|
+
this.services = services;
|
|
6941
|
+
}
|
|
6942
|
+
/**
|
|
6943
|
+
* Get list of services by category
|
|
6944
|
+
*/
|
|
6945
|
+
async getServices(category) {
|
|
6946
|
+
return this.services.filter(
|
|
6947
|
+
(service) => service.category === category || service.metadata?.category === category
|
|
6948
|
+
);
|
|
6949
|
+
}
|
|
6950
|
+
};
|
|
6951
|
+
exports.StaticDiscovery = __decorateClass([
|
|
6952
|
+
common.Injectable()
|
|
6953
|
+
], exports.StaticDiscovery);
|
|
6954
|
+
|
|
6373
6955
|
exports.AbstractGraphBuilder = AbstractGraphBuilder;
|
|
6374
6956
|
exports.AttachmentType = AttachmentType;
|
|
6375
6957
|
exports.BaseGraphServiceController = exports.GraphController;
|
|
@@ -6385,7 +6967,6 @@ exports.GraphEngineType = GraphEngineType;
|
|
|
6385
6967
|
exports.GraphManifestSchema = GraphManifestSchema;
|
|
6386
6968
|
exports.GraphManifestValidator = GraphManifestValidator;
|
|
6387
6969
|
exports.GraphServiceTokens = GraphServiceTokens;
|
|
6388
|
-
exports.GraphTypeUtils = GraphTypeUtils;
|
|
6389
6970
|
exports.IdempotencyStatus = IdempotencyStatus;
|
|
6390
6971
|
exports.McpConverter = McpConverter;
|
|
6391
6972
|
exports.McpToolFilter = McpToolFilter;
|