@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.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
|
-
import { Injectable, Post, UseGuards, Req, Controller, Inject, Get, Body, Res, Param, Logger, Module, UnauthorizedException, Headers, NotFoundException, InternalServerErrorException, ForbiddenException, ValidationPipe, HttpException, HttpStatus } from '@nestjs/common';
|
|
2
|
+
import { Injectable, Post, UseGuards, Req, Controller, Inject, Get, Body, Res, Param, Logger, Module, UnauthorizedException, Optional, Headers, NotFoundException, InternalServerErrorException, ForbiddenException, ValidationPipe, HttpException, HttpStatus } from '@nestjs/common';
|
|
3
3
|
import { ApiOperation, ApiResponse, ApiTags, ApiParam, DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
|
4
|
-
import * as
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import * as path2 from 'path';
|
|
6
|
+
import * as os from 'os';
|
|
5
7
|
import { randomBytes, createHash, randomUUID } from 'crypto';
|
|
6
8
|
import { Registry, collectDefaultMetrics, Counter, Histogram, Gauge } from 'prom-client';
|
|
7
|
-
import { NestFactory, ModuleRef, DiscoveryModule } from '@nestjs/core';
|
|
9
|
+
import { NestFactory, MetadataScanner, ModuleRef, DiscoveryModule } from '@nestjs/core';
|
|
8
10
|
import * as net from 'net';
|
|
9
11
|
import { ConfigModule } from '@nestjs/config';
|
|
10
12
|
import * as LangGraph from '@langchain/langgraph';
|
|
@@ -432,12 +434,21 @@ var init_ui_endpoints_discovery = __esm({
|
|
|
432
434
|
this.endpointRegistry = endpointRegistry;
|
|
433
435
|
}
|
|
434
436
|
logger = new Logger(UIEndpointsDiscoveryService.name);
|
|
437
|
+
async onModuleInit() {
|
|
438
|
+
await this.discoverUIEndpoints();
|
|
439
|
+
}
|
|
435
440
|
/**
|
|
436
441
|
* Discover and register all UI endpoint classes
|
|
437
442
|
* Called automatically during module initialization
|
|
438
443
|
*/
|
|
439
444
|
async discoverUIEndpoints() {
|
|
440
445
|
this.logger.log("Starting UI endpoints discovery...");
|
|
446
|
+
if (!this.discoveryService) {
|
|
447
|
+
this.logger.warn(
|
|
448
|
+
"DiscoveryService not available, skipping UI endpoints discovery"
|
|
449
|
+
);
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
441
452
|
const providers = this.discoveryService.getProviders();
|
|
442
453
|
let registeredCount = 0;
|
|
443
454
|
let totalEndpoints = 0;
|
|
@@ -489,7 +500,9 @@ var init_ui_endpoints_discovery = __esm({
|
|
|
489
500
|
}
|
|
490
501
|
};
|
|
491
502
|
UIEndpointsDiscoveryService = __decorateClass([
|
|
492
|
-
Injectable()
|
|
503
|
+
Injectable(),
|
|
504
|
+
__decorateParam(0, Optional()),
|
|
505
|
+
__decorateParam(1, Optional())
|
|
493
506
|
], UIEndpointsDiscoveryService);
|
|
494
507
|
}
|
|
495
508
|
});
|
|
@@ -684,6 +697,523 @@ var init_agent_ui = __esm({
|
|
|
684
697
|
init_ui_dispatch_controller();
|
|
685
698
|
}
|
|
686
699
|
});
|
|
700
|
+
|
|
701
|
+
// src/service-discovery/file-based.discovery.ts
|
|
702
|
+
var file_based_discovery_exports = {};
|
|
703
|
+
__export(file_based_discovery_exports, {
|
|
704
|
+
FileBasedDiscovery: () => FileBasedDiscovery
|
|
705
|
+
});
|
|
706
|
+
var FileBasedDiscovery;
|
|
707
|
+
var init_file_based_discovery = __esm({
|
|
708
|
+
"src/service-discovery/file-based.discovery.ts"() {
|
|
709
|
+
FileBasedDiscovery = class {
|
|
710
|
+
logger = new Logger(FileBasedDiscovery.name);
|
|
711
|
+
servicesDir;
|
|
712
|
+
constructor() {
|
|
713
|
+
this.servicesDir = path2.join(os.homedir(), ".flutch", "services");
|
|
714
|
+
this.ensureServicesDirectory();
|
|
715
|
+
this.cleanupStaleServices();
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Register service
|
|
719
|
+
*/
|
|
720
|
+
async registerService(name, address, port, metadata, graphTypes = []) {
|
|
721
|
+
const registration = {
|
|
722
|
+
name,
|
|
723
|
+
address,
|
|
724
|
+
port,
|
|
725
|
+
metadata,
|
|
726
|
+
pid: process.pid,
|
|
727
|
+
timestamp: Date.now(),
|
|
728
|
+
graphTypes
|
|
729
|
+
};
|
|
730
|
+
const serviceFile = path2.join(
|
|
731
|
+
this.servicesDir,
|
|
732
|
+
`${name}-${process.pid}.json`
|
|
733
|
+
);
|
|
734
|
+
try {
|
|
735
|
+
await fs.promises.writeFile(
|
|
736
|
+
serviceFile,
|
|
737
|
+
JSON.stringify(registration, null, 2)
|
|
738
|
+
);
|
|
739
|
+
this.logger.log(`Registered service: ${name} at ${address}:${port}`);
|
|
740
|
+
process.on("exit", () => this.unregisterService(name));
|
|
741
|
+
process.on("SIGINT", () => {
|
|
742
|
+
this.unregisterService(name);
|
|
743
|
+
process.exit(0);
|
|
744
|
+
});
|
|
745
|
+
process.on("SIGTERM", () => {
|
|
746
|
+
this.unregisterService(name);
|
|
747
|
+
process.exit(0);
|
|
748
|
+
});
|
|
749
|
+
} catch (error) {
|
|
750
|
+
this.logger.error(`Failed to register service ${name}: ${error.message}`);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Unregister service
|
|
755
|
+
*/
|
|
756
|
+
async unregisterService(name) {
|
|
757
|
+
const serviceFile = path2.join(
|
|
758
|
+
this.servicesDir,
|
|
759
|
+
`${name}-${process.pid}.json`
|
|
760
|
+
);
|
|
761
|
+
try {
|
|
762
|
+
if (fs.existsSync(serviceFile)) {
|
|
763
|
+
await fs.promises.unlink(serviceFile);
|
|
764
|
+
this.logger.log(`Unregistered service: ${name}`);
|
|
765
|
+
}
|
|
766
|
+
} catch (error) {
|
|
767
|
+
this.logger.error(
|
|
768
|
+
`Failed to unregister service ${name}: ${error.message}`
|
|
769
|
+
);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* Get list of services by graph type
|
|
774
|
+
*/
|
|
775
|
+
async getServices(graphType) {
|
|
776
|
+
try {
|
|
777
|
+
const files = await fs.promises.readdir(this.servicesDir);
|
|
778
|
+
const services = [];
|
|
779
|
+
for (const file of files) {
|
|
780
|
+
if (!file.endsWith(".json")) continue;
|
|
781
|
+
try {
|
|
782
|
+
const serviceFile = path2.join(this.servicesDir, file);
|
|
783
|
+
const content = await fs.promises.readFile(serviceFile, "utf-8");
|
|
784
|
+
const registration = JSON.parse(content);
|
|
785
|
+
if (!this.isProcessAlive(registration.pid)) {
|
|
786
|
+
await fs.promises.unlink(serviceFile);
|
|
787
|
+
continue;
|
|
788
|
+
}
|
|
789
|
+
if (registration.graphTypes.includes(graphType) || registration.metadata.graphTypes?.includes(graphType)) {
|
|
790
|
+
services.push({
|
|
791
|
+
name: registration.name,
|
|
792
|
+
address: registration.address,
|
|
793
|
+
port: registration.port,
|
|
794
|
+
metadata: registration.metadata
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
} catch (error) {
|
|
798
|
+
this.logger.warn(
|
|
799
|
+
`Failed to parse service file ${file}: ${error.message}`
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
return services;
|
|
804
|
+
} catch (error) {
|
|
805
|
+
this.logger.error(`Failed to get services: ${error.message}`);
|
|
806
|
+
return [];
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
/**
|
|
810
|
+
* Find service by name
|
|
811
|
+
*/
|
|
812
|
+
async findServiceByName(serviceName) {
|
|
813
|
+
try {
|
|
814
|
+
const files = await fs.promises.readdir(this.servicesDir);
|
|
815
|
+
for (const file of files) {
|
|
816
|
+
if (!file.endsWith(".json")) continue;
|
|
817
|
+
try {
|
|
818
|
+
const serviceFile = path2.join(this.servicesDir, file);
|
|
819
|
+
const content = await fs.promises.readFile(serviceFile, "utf-8");
|
|
820
|
+
const registration = JSON.parse(content);
|
|
821
|
+
if (registration.name === serviceName && this.isProcessAlive(registration.pid)) {
|
|
822
|
+
return {
|
|
823
|
+
name: registration.name,
|
|
824
|
+
address: registration.address,
|
|
825
|
+
port: registration.port,
|
|
826
|
+
metadata: registration.metadata
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
} catch (error) {
|
|
830
|
+
this.logger.warn(
|
|
831
|
+
`Failed to parse service file ${file}: ${error.message}`
|
|
832
|
+
);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
return null;
|
|
836
|
+
} catch (error) {
|
|
837
|
+
this.logger.error(
|
|
838
|
+
`Failed to find service ${serviceName}: ${error.message}`
|
|
839
|
+
);
|
|
840
|
+
return null;
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* Ensure services directory exists
|
|
845
|
+
*/
|
|
846
|
+
ensureServicesDirectory() {
|
|
847
|
+
try {
|
|
848
|
+
const amelieDir = path2.join(os.homedir(), ".flutch");
|
|
849
|
+
if (!fs.existsSync(amelieDir)) {
|
|
850
|
+
fs.mkdirSync(amelieDir, { recursive: true });
|
|
851
|
+
}
|
|
852
|
+
if (!fs.existsSync(this.servicesDir)) {
|
|
853
|
+
fs.mkdirSync(this.servicesDir, { recursive: true });
|
|
854
|
+
}
|
|
855
|
+
} catch (error) {
|
|
856
|
+
this.logger.error(
|
|
857
|
+
`Failed to create services directory: ${error.message}`
|
|
858
|
+
);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* Cleanup stale services
|
|
863
|
+
*/
|
|
864
|
+
async cleanupStaleServices() {
|
|
865
|
+
try {
|
|
866
|
+
const files = await fs.promises.readdir(this.servicesDir);
|
|
867
|
+
for (const file of files) {
|
|
868
|
+
if (!file.endsWith(".json")) continue;
|
|
869
|
+
try {
|
|
870
|
+
const serviceFile = path2.join(this.servicesDir, file);
|
|
871
|
+
const content = await fs.promises.readFile(serviceFile, "utf-8");
|
|
872
|
+
const registration = JSON.parse(content);
|
|
873
|
+
if (!this.isProcessAlive(registration.pid)) {
|
|
874
|
+
await fs.promises.unlink(serviceFile);
|
|
875
|
+
this.logger.debug(`Cleaned up stale service: ${registration.name}`);
|
|
876
|
+
}
|
|
877
|
+
} catch (error) {
|
|
878
|
+
try {
|
|
879
|
+
await fs.promises.unlink(path2.join(this.servicesDir, file));
|
|
880
|
+
} catch {
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
} catch (error) {
|
|
885
|
+
this.logger.error(`Failed to cleanup stale services: ${error.message}`);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Check if process is still alive
|
|
890
|
+
*/
|
|
891
|
+
isProcessAlive(pid) {
|
|
892
|
+
try {
|
|
893
|
+
process.kill(pid, 0);
|
|
894
|
+
return true;
|
|
895
|
+
} catch (error) {
|
|
896
|
+
return false;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
FileBasedDiscovery = __decorateClass([
|
|
901
|
+
Injectable()
|
|
902
|
+
], FileBasedDiscovery);
|
|
903
|
+
}
|
|
904
|
+
});
|
|
905
|
+
|
|
906
|
+
// src/core/builder-registry.service.ts
|
|
907
|
+
var builder_registry_service_exports = {};
|
|
908
|
+
__export(builder_registry_service_exports, {
|
|
909
|
+
BuilderRegistryService: () => BuilderRegistryService
|
|
910
|
+
});
|
|
911
|
+
var BuilderRegistryService;
|
|
912
|
+
var init_builder_registry_service = __esm({
|
|
913
|
+
"src/core/builder-registry.service.ts"() {
|
|
914
|
+
BuilderRegistryService = class {
|
|
915
|
+
builders = [];
|
|
916
|
+
registerBuilder(builder) {
|
|
917
|
+
const existingBuilder = this.builders.find(
|
|
918
|
+
(b) => b.graphType === builder.graphType
|
|
919
|
+
);
|
|
920
|
+
if (!existingBuilder) {
|
|
921
|
+
this.builders.push(builder);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
getBuilders() {
|
|
925
|
+
return this.builders;
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
BuilderRegistryService = __decorateClass([
|
|
929
|
+
Injectable()
|
|
930
|
+
], BuilderRegistryService);
|
|
931
|
+
}
|
|
932
|
+
});
|
|
933
|
+
|
|
934
|
+
// src/utils/graph-type.utils.ts
|
|
935
|
+
var GraphTypeUtils;
|
|
936
|
+
var init_graph_type_utils = __esm({
|
|
937
|
+
"src/utils/graph-type.utils.ts"() {
|
|
938
|
+
GraphTypeUtils = class {
|
|
939
|
+
/**
|
|
940
|
+
* Parse full graph type
|
|
941
|
+
* @param fullType - full graph type
|
|
942
|
+
* @returns object with type components
|
|
943
|
+
*/
|
|
944
|
+
static parse(fullType) {
|
|
945
|
+
if (fullType.includes("::")) {
|
|
946
|
+
const [baseType, version] = fullType.split("::");
|
|
947
|
+
const [companyId, name] = baseType.split(".");
|
|
948
|
+
return { companyId, name, version };
|
|
949
|
+
}
|
|
950
|
+
const parts = fullType.split(".");
|
|
951
|
+
if (parts.length === 1) {
|
|
952
|
+
return { companyId: "global", name: parts[0] };
|
|
953
|
+
}
|
|
954
|
+
return { companyId: parts[0], name: parts[1] };
|
|
955
|
+
}
|
|
956
|
+
/**
|
|
957
|
+
* Build full type from components
|
|
958
|
+
* @param companyId - company ID
|
|
959
|
+
* @param name - graph name
|
|
960
|
+
* @param version - version (optional)
|
|
961
|
+
* @returns full graph type
|
|
962
|
+
*/
|
|
963
|
+
static build(companyId, name, version) {
|
|
964
|
+
const base = `${companyId}.${name}`;
|
|
965
|
+
return version ? `${base}::${version}` : base;
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* Normalize graph type for backward compatibility
|
|
969
|
+
* @param graphType - graph type in any format
|
|
970
|
+
* @returns normalized type
|
|
971
|
+
*/
|
|
972
|
+
static normalize(graphType) {
|
|
973
|
+
const { companyId, name, version } = this.parse(graphType);
|
|
974
|
+
return this.build(companyId, name, version);
|
|
975
|
+
}
|
|
976
|
+
/**
|
|
977
|
+
* Get base type without version
|
|
978
|
+
* @param graphType - full graph type
|
|
979
|
+
* @returns base type
|
|
980
|
+
*/
|
|
981
|
+
static getBaseType(graphType) {
|
|
982
|
+
if (graphType.includes("::")) {
|
|
983
|
+
return graphType.split("::")[0];
|
|
984
|
+
}
|
|
985
|
+
const { companyId, name } = this.parse(graphType);
|
|
986
|
+
return `${companyId}.${name}`;
|
|
987
|
+
}
|
|
988
|
+
/**
|
|
989
|
+
* Extract version from graph type
|
|
990
|
+
* @param graphType - full graph type
|
|
991
|
+
* @returns version or undefined
|
|
992
|
+
*/
|
|
993
|
+
static getVersion(graphType) {
|
|
994
|
+
return graphType.includes("::") ? graphType.split("::")[1] : void 0;
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* Validate version (basic semver check)
|
|
998
|
+
* @param version - version to check
|
|
999
|
+
* @returns true if version is valid
|
|
1000
|
+
*/
|
|
1001
|
+
static isValidVersion(version) {
|
|
1002
|
+
const semverRegex = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?$/;
|
|
1003
|
+
return semverRegex.test(version);
|
|
1004
|
+
}
|
|
1005
|
+
/**
|
|
1006
|
+
* Check if type is system (global)
|
|
1007
|
+
* @param graphType - graph type
|
|
1008
|
+
* @returns true if graph is system
|
|
1009
|
+
*/
|
|
1010
|
+
static isSystemGraph(graphType) {
|
|
1011
|
+
const { companyId } = this.parse(graphType);
|
|
1012
|
+
return companyId === "global";
|
|
1013
|
+
}
|
|
1014
|
+
/**
|
|
1015
|
+
* Compare versions (simple comparison for sorting)
|
|
1016
|
+
* @param a - first version
|
|
1017
|
+
* @param b - second version
|
|
1018
|
+
* @returns -1, 0, 1 for sorting
|
|
1019
|
+
*/
|
|
1020
|
+
static compareVersions(a, b) {
|
|
1021
|
+
const parseVersion = (v) => {
|
|
1022
|
+
const [main, prerelease] = v.split("-");
|
|
1023
|
+
const [major, minor, patch] = main.split(".").map(Number);
|
|
1024
|
+
return { major, minor, patch, prerelease };
|
|
1025
|
+
};
|
|
1026
|
+
const versionA = parseVersion(a);
|
|
1027
|
+
const versionB = parseVersion(b);
|
|
1028
|
+
if (versionA.major !== versionB.major) {
|
|
1029
|
+
return versionA.major - versionB.major;
|
|
1030
|
+
}
|
|
1031
|
+
if (versionA.minor !== versionB.minor) {
|
|
1032
|
+
return versionA.minor - versionB.minor;
|
|
1033
|
+
}
|
|
1034
|
+
if (versionA.patch !== versionB.patch) {
|
|
1035
|
+
return versionA.patch - versionB.patch;
|
|
1036
|
+
}
|
|
1037
|
+
if (versionA.prerelease && !versionB.prerelease) return -1;
|
|
1038
|
+
if (!versionA.prerelease && versionB.prerelease) return 1;
|
|
1039
|
+
if (versionA.prerelease && versionB.prerelease) {
|
|
1040
|
+
return versionA.prerelease.localeCompare(versionB.prerelease);
|
|
1041
|
+
}
|
|
1042
|
+
return 0;
|
|
1043
|
+
}
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
});
|
|
1047
|
+
|
|
1048
|
+
// src/graph/versioning/versioned-graph.service.ts
|
|
1049
|
+
var versioned_graph_service_exports = {};
|
|
1050
|
+
__export(versioned_graph_service_exports, {
|
|
1051
|
+
VersionedGraphService: () => VersionedGraphService
|
|
1052
|
+
});
|
|
1053
|
+
var VersionedGraphService;
|
|
1054
|
+
var init_versioned_graph_service = __esm({
|
|
1055
|
+
"src/graph/versioning/versioned-graph.service.ts"() {
|
|
1056
|
+
init_graph_type_utils();
|
|
1057
|
+
VersionedGraphService = class {
|
|
1058
|
+
logger = new Logger(VersionedGraphService.name);
|
|
1059
|
+
versionConfigs = /* @__PURE__ */ new Map();
|
|
1060
|
+
constructor() {
|
|
1061
|
+
}
|
|
1062
|
+
/**
|
|
1063
|
+
* Register versioning configuration
|
|
1064
|
+
*/
|
|
1065
|
+
registerVersioning(config) {
|
|
1066
|
+
this.versionConfigs.set(config.baseGraphType, config);
|
|
1067
|
+
this.logger.log(
|
|
1068
|
+
`Registered versioning for ${config.baseGraphType} with ${config.versions.length} versions`
|
|
1069
|
+
);
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Resolve graph version
|
|
1073
|
+
*/
|
|
1074
|
+
async resolveVersion(graphType, options = {}) {
|
|
1075
|
+
const parsed = GraphTypeUtils.parse(graphType);
|
|
1076
|
+
const baseType = GraphTypeUtils.getBaseType(graphType);
|
|
1077
|
+
const requestedVersion = GraphTypeUtils.getVersion(graphType) || options.requestedVersion;
|
|
1078
|
+
const config = this.versionConfigs.get(baseType);
|
|
1079
|
+
if (!config) {
|
|
1080
|
+
throw new Error(`No versioning configuration found for ${baseType}`);
|
|
1081
|
+
}
|
|
1082
|
+
const route = this.findBestVersionRoute(config, requestedVersion, options);
|
|
1083
|
+
if (!route) {
|
|
1084
|
+
throw new Error(
|
|
1085
|
+
`No compatible version found for ${graphType} with options: ${JSON.stringify(options)}`
|
|
1086
|
+
);
|
|
1087
|
+
}
|
|
1088
|
+
const fullGraphType = GraphTypeUtils.build(
|
|
1089
|
+
parsed.companyId,
|
|
1090
|
+
parsed.name,
|
|
1091
|
+
route.version
|
|
1092
|
+
);
|
|
1093
|
+
return {
|
|
1094
|
+
version: route.version,
|
|
1095
|
+
builderClass: route.builderClass,
|
|
1096
|
+
fullGraphType
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
/**
|
|
1100
|
+
* Create builder for specified version
|
|
1101
|
+
*/
|
|
1102
|
+
async createVersionedBuilder(graphType, moduleRef, options = {}) {
|
|
1103
|
+
const resolution = await this.resolveVersion(graphType, options);
|
|
1104
|
+
try {
|
|
1105
|
+
if (!moduleRef) {
|
|
1106
|
+
throw new Error(
|
|
1107
|
+
"ModuleRef is not available - falling back to direct instantiation"
|
|
1108
|
+
);
|
|
1109
|
+
}
|
|
1110
|
+
const builder = await moduleRef.create(resolution.builderClass);
|
|
1111
|
+
this.logger.debug(
|
|
1112
|
+
`Created versioned builder for ${resolution.fullGraphType}`
|
|
1113
|
+
);
|
|
1114
|
+
return builder;
|
|
1115
|
+
} catch (error) {
|
|
1116
|
+
this.logger.error(
|
|
1117
|
+
`Failed to create builder for ${resolution.fullGraphType}: ${error.message}`
|
|
1118
|
+
);
|
|
1119
|
+
throw new Error(`Failed to create versioned builder: ${error.message}`);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
/**
|
|
1123
|
+
* Get all available versions for a graph
|
|
1124
|
+
*/
|
|
1125
|
+
getAvailableVersions(baseGraphType) {
|
|
1126
|
+
const config = this.versionConfigs.get(baseGraphType);
|
|
1127
|
+
if (!config) {
|
|
1128
|
+
return [];
|
|
1129
|
+
}
|
|
1130
|
+
return config.versions.map((route) => route.version).sort((a, b) => GraphTypeUtils.compareVersions(b, a));
|
|
1131
|
+
}
|
|
1132
|
+
/**
|
|
1133
|
+
* Check version support
|
|
1134
|
+
*/
|
|
1135
|
+
isVersionSupported(graphType, options = {}) {
|
|
1136
|
+
try {
|
|
1137
|
+
const baseType = GraphTypeUtils.getBaseType(graphType);
|
|
1138
|
+
const requestedVersion = GraphTypeUtils.getVersion(graphType);
|
|
1139
|
+
const config = this.versionConfigs.get(baseType);
|
|
1140
|
+
if (!config) {
|
|
1141
|
+
return false;
|
|
1142
|
+
}
|
|
1143
|
+
const route = this.findBestVersionRoute(
|
|
1144
|
+
config,
|
|
1145
|
+
requestedVersion,
|
|
1146
|
+
options
|
|
1147
|
+
);
|
|
1148
|
+
return route !== null;
|
|
1149
|
+
} catch {
|
|
1150
|
+
return false;
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
/**
|
|
1154
|
+
* Find best version
|
|
1155
|
+
*/
|
|
1156
|
+
findBestVersionRoute(config, requestedVersion, options = {}) {
|
|
1157
|
+
const { strict = false } = options;
|
|
1158
|
+
let candidates = [...config.versions];
|
|
1159
|
+
if (requestedVersion) {
|
|
1160
|
+
const exactMatch = candidates.find(
|
|
1161
|
+
(route) => route.version === requestedVersion
|
|
1162
|
+
);
|
|
1163
|
+
if (exactMatch) {
|
|
1164
|
+
return exactMatch;
|
|
1165
|
+
}
|
|
1166
|
+
if (strict) {
|
|
1167
|
+
return null;
|
|
1168
|
+
}
|
|
1169
|
+
const compatibleVersions = candidates.filter(
|
|
1170
|
+
(route) => this.isVersionCompatible(requestedVersion, route.version)
|
|
1171
|
+
);
|
|
1172
|
+
if (compatibleVersions.length > 0) {
|
|
1173
|
+
return compatibleVersions.sort(
|
|
1174
|
+
(a, b) => GraphTypeUtils.compareVersions(b.version, a.version)
|
|
1175
|
+
)[0];
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
const defaultRoute = candidates.find((route) => route.isDefault);
|
|
1179
|
+
if (defaultRoute) {
|
|
1180
|
+
return defaultRoute;
|
|
1181
|
+
}
|
|
1182
|
+
if (config.defaultVersionStrategy === "latest" || !config.defaultVersionStrategy) {
|
|
1183
|
+
const sortedVersions = candidates.sort(
|
|
1184
|
+
(a, b) => GraphTypeUtils.compareVersions(b.version, a.version)
|
|
1185
|
+
);
|
|
1186
|
+
return sortedVersions[0] || null;
|
|
1187
|
+
}
|
|
1188
|
+
return null;
|
|
1189
|
+
}
|
|
1190
|
+
/**
|
|
1191
|
+
* Check version compatibility (simplified semantics)
|
|
1192
|
+
*/
|
|
1193
|
+
isVersionCompatible(requested, available) {
|
|
1194
|
+
try {
|
|
1195
|
+
const requestedParts = requested.split(".").map(Number);
|
|
1196
|
+
const availableParts = available.split(".").map(Number);
|
|
1197
|
+
if (requestedParts[0] !== availableParts[0]) {
|
|
1198
|
+
return false;
|
|
1199
|
+
}
|
|
1200
|
+
return GraphTypeUtils.compareVersions(available, requested) >= 0;
|
|
1201
|
+
} catch {
|
|
1202
|
+
return false;
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
/**
|
|
1206
|
+
* Get versioning configuration information
|
|
1207
|
+
*/
|
|
1208
|
+
getVersioningInfo(baseGraphType) {
|
|
1209
|
+
return this.versionConfigs.get(baseGraphType) || null;
|
|
1210
|
+
}
|
|
1211
|
+
};
|
|
1212
|
+
VersionedGraphService = __decorateClass([
|
|
1213
|
+
Injectable()
|
|
1214
|
+
], VersionedGraphService);
|
|
1215
|
+
}
|
|
1216
|
+
});
|
|
687
1217
|
var CallbackStore = class {
|
|
688
1218
|
constructor(redis) {
|
|
689
1219
|
this.redis = redis;
|
|
@@ -2525,7 +3055,7 @@ var _AbstractGraphBuilder = class _AbstractGraphBuilder {
|
|
|
2525
3055
|
/**
|
|
2526
3056
|
* Path to root graph manifest (defaults to graph.manifest.json in root)
|
|
2527
3057
|
*/
|
|
2528
|
-
manifestPath =
|
|
3058
|
+
manifestPath = path2.join(
|
|
2529
3059
|
process.cwd(),
|
|
2530
3060
|
"graph.manifest.json"
|
|
2531
3061
|
);
|
|
@@ -2605,10 +3135,10 @@ var _AbstractGraphBuilder = class _AbstractGraphBuilder {
|
|
|
2605
3135
|
return null;
|
|
2606
3136
|
}
|
|
2607
3137
|
try {
|
|
2608
|
-
const
|
|
2609
|
-
const
|
|
2610
|
-
const manifestFullPath =
|
|
2611
|
-
const manifestContent = await
|
|
3138
|
+
const fs2 = await import('fs/promises');
|
|
3139
|
+
const path3 = await import('path');
|
|
3140
|
+
const manifestFullPath = path3.resolve(this.manifestPath);
|
|
3141
|
+
const manifestContent = await fs2.readFile(manifestFullPath, "utf-8");
|
|
2612
3142
|
const manifest = JSON.parse(manifestContent);
|
|
2613
3143
|
this.manifest = manifest;
|
|
2614
3144
|
return manifest;
|
|
@@ -2627,10 +3157,10 @@ var _AbstractGraphBuilder = class _AbstractGraphBuilder {
|
|
|
2627
3157
|
return null;
|
|
2628
3158
|
}
|
|
2629
3159
|
try {
|
|
2630
|
-
const
|
|
2631
|
-
const
|
|
2632
|
-
const manifestFullPath =
|
|
2633
|
-
const manifestContent =
|
|
3160
|
+
const fs2 = __require("fs");
|
|
3161
|
+
const path3 = __require("path");
|
|
3162
|
+
const manifestFullPath = path3.resolve(this.manifestPath);
|
|
3163
|
+
const manifestContent = fs2.readFileSync(manifestFullPath, "utf-8");
|
|
2634
3164
|
const manifest = JSON.parse(manifestContent);
|
|
2635
3165
|
this.manifest = manifest;
|
|
2636
3166
|
return manifest;
|
|
@@ -2670,12 +3200,12 @@ var _AbstractGraphBuilder = class _AbstractGraphBuilder {
|
|
|
2670
3200
|
let configSchema = null;
|
|
2671
3201
|
if (versionConfig.configSchemaPath) {
|
|
2672
3202
|
try {
|
|
2673
|
-
const
|
|
2674
|
-
const schemaPath =
|
|
3203
|
+
const fs2 = await import('fs/promises');
|
|
3204
|
+
const schemaPath = path2.resolve(
|
|
2675
3205
|
process.cwd(),
|
|
2676
3206
|
versionConfig.configSchemaPath
|
|
2677
3207
|
);
|
|
2678
|
-
const schemaContent = await
|
|
3208
|
+
const schemaContent = await fs2.readFile(schemaPath, "utf-8");
|
|
2679
3209
|
const schemaData = JSON.parse(schemaContent);
|
|
2680
3210
|
configSchema = schemaData.schema;
|
|
2681
3211
|
} catch (error) {
|
|
@@ -3140,6 +3670,20 @@ UniversalGraphService = __decorateClass([
|
|
|
3140
3670
|
__decorateParam(2, Inject("GRAPH_ENGINE")),
|
|
3141
3671
|
__decorateParam(3, Inject(EndpointRegistry))
|
|
3142
3672
|
], UniversalGraphService);
|
|
3673
|
+
function setupRedisMock() {
|
|
3674
|
+
if (process.env.NODE_ENV === "development" && !process.env.KUBERNETES_SERVICE_HOST) {
|
|
3675
|
+
console.log("[REDIS_MOCK] Intercepting ioredis requires for development");
|
|
3676
|
+
const Module2 = __require("module");
|
|
3677
|
+
const originalRequire = Module2.prototype.require;
|
|
3678
|
+
Module2.prototype.require = function(...args) {
|
|
3679
|
+
if (args[0] === "ioredis") {
|
|
3680
|
+
console.log("[REDIS_MOCK] Redirecting ioredis to ioredis-mock");
|
|
3681
|
+
return originalRequire.apply(this, ["ioredis-mock"]);
|
|
3682
|
+
}
|
|
3683
|
+
return originalRequire.apply(this, args);
|
|
3684
|
+
};
|
|
3685
|
+
}
|
|
3686
|
+
}
|
|
3143
3687
|
async function isPortAvailable(port) {
|
|
3144
3688
|
return new Promise((resolve2) => {
|
|
3145
3689
|
const server = net.createServer();
|
|
@@ -3161,10 +3705,110 @@ async function findAvailablePort(startPort) {
|
|
|
3161
3705
|
`No available ports found in range ${startPort}-${startPort + 99}`
|
|
3162
3706
|
);
|
|
3163
3707
|
}
|
|
3708
|
+
async function registerWithServiceDiscovery(AppModule, port, logger2, app) {
|
|
3709
|
+
try {
|
|
3710
|
+
logger2.debug(
|
|
3711
|
+
"[SERVICE_DISCOVERY] Starting service discovery registration..."
|
|
3712
|
+
);
|
|
3713
|
+
const { FileBasedDiscovery: FileBasedDiscovery2 } = await Promise.resolve().then(() => (init_file_based_discovery(), file_based_discovery_exports));
|
|
3714
|
+
logger2.debug(
|
|
3715
|
+
"[SERVICE_DISCOVERY] FileBasedDiscovery imported successfully"
|
|
3716
|
+
);
|
|
3717
|
+
const discovery = new FileBasedDiscovery2();
|
|
3718
|
+
logger2.debug("[SERVICE_DISCOVERY] FileBasedDiscovery instance created");
|
|
3719
|
+
const serviceName = AppModule.name.replace("Module", "").toLowerCase();
|
|
3720
|
+
let graphTypes = [];
|
|
3721
|
+
try {
|
|
3722
|
+
if (app) {
|
|
3723
|
+
const { BuilderRegistryService: BuilderRegistryService2 } = await Promise.resolve().then(() => (init_builder_registry_service(), builder_registry_service_exports));
|
|
3724
|
+
const builderRegistry = app.get(BuilderRegistryService2, {
|
|
3725
|
+
strict: false
|
|
3726
|
+
});
|
|
3727
|
+
logger2.debug(
|
|
3728
|
+
`BuilderRegistryService found in DI: ${!!builderRegistry}`
|
|
3729
|
+
);
|
|
3730
|
+
if (builderRegistry) {
|
|
3731
|
+
const builders = builderRegistry.getBuilders();
|
|
3732
|
+
logger2.debug(`Found ${builders.length} builders in registry`);
|
|
3733
|
+
const baseGraphTypes = builders.map((builder) => builder.graphType);
|
|
3734
|
+
logger2.debug(`Base graph types: [${baseGraphTypes.join(", ")}]`);
|
|
3735
|
+
try {
|
|
3736
|
+
logger2.debug("Attempting to import VersionedGraphService...");
|
|
3737
|
+
const { VersionedGraphService: VersionedGraphService2 } = await Promise.resolve().then(() => (init_versioned_graph_service(), versioned_graph_service_exports));
|
|
3738
|
+
logger2.debug("VersionedGraphService imported successfully");
|
|
3739
|
+
const versionedService = app.get(VersionedGraphService2, {
|
|
3740
|
+
strict: false
|
|
3741
|
+
});
|
|
3742
|
+
logger2.debug(
|
|
3743
|
+
`VersionedGraphService found in DI: ${!!versionedService}`
|
|
3744
|
+
);
|
|
3745
|
+
if (versionedService) {
|
|
3746
|
+
const allVersionedTypes = [];
|
|
3747
|
+
for (const baseType of baseGraphTypes) {
|
|
3748
|
+
logger2.debug(`Getting versions for base type: ${baseType}`);
|
|
3749
|
+
const versions = versionedService.getAvailableVersions(baseType);
|
|
3750
|
+
logger2.debug(
|
|
3751
|
+
`Found ${versions.length} versions for ${baseType}: [${versions.join(", ")}]`
|
|
3752
|
+
);
|
|
3753
|
+
if (versions.length > 0) {
|
|
3754
|
+
allVersionedTypes.push(baseType);
|
|
3755
|
+
versions.forEach((version) => {
|
|
3756
|
+
allVersionedTypes.push(`${baseType}::${version}`);
|
|
3757
|
+
});
|
|
3758
|
+
} else {
|
|
3759
|
+
allVersionedTypes.push(baseType);
|
|
3760
|
+
}
|
|
3761
|
+
}
|
|
3762
|
+
graphTypes = allVersionedTypes;
|
|
3763
|
+
logger2.debug(
|
|
3764
|
+
`Found ${baseGraphTypes.length} base types with ${graphTypes.length} total versioned types: ${graphTypes.join(", ")}`
|
|
3765
|
+
);
|
|
3766
|
+
} else {
|
|
3767
|
+
graphTypes = baseGraphTypes;
|
|
3768
|
+
logger2.debug(
|
|
3769
|
+
`VersionedGraphService not found in DI container, using base types: ${graphTypes.join(", ")}`
|
|
3770
|
+
);
|
|
3771
|
+
}
|
|
3772
|
+
} catch (error) {
|
|
3773
|
+
graphTypes = baseGraphTypes;
|
|
3774
|
+
logger2.debug(
|
|
3775
|
+
`Failed to get versioned types, using base types: ${error.message}`
|
|
3776
|
+
);
|
|
3777
|
+
logger2.debug(`Stack trace: ${error.stack}`);
|
|
3778
|
+
}
|
|
3779
|
+
}
|
|
3780
|
+
}
|
|
3781
|
+
} catch (error) {
|
|
3782
|
+
logger2.debug(`Failed to get graph types from builders: ${error.message}`);
|
|
3783
|
+
}
|
|
3784
|
+
if (graphTypes.length === 0) {
|
|
3785
|
+
logger2.debug("No builders found, using service name as graph type");
|
|
3786
|
+
graphTypes = [serviceName];
|
|
3787
|
+
}
|
|
3788
|
+
await discovery.registerService(
|
|
3789
|
+
serviceName,
|
|
3790
|
+
"localhost",
|
|
3791
|
+
port,
|
|
3792
|
+
{
|
|
3793
|
+
graphTypes,
|
|
3794
|
+
environment: "development",
|
|
3795
|
+
startTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3796
|
+
version: process.env.npm_package_version || "1.0.0"
|
|
3797
|
+
},
|
|
3798
|
+
graphTypes
|
|
3799
|
+
);
|
|
3800
|
+
logger2.log(
|
|
3801
|
+
`\u{1F4E1} Service registered with discovery: ${serviceName} (types: ${graphTypes.join(", ")})`
|
|
3802
|
+
);
|
|
3803
|
+
} catch (error) {
|
|
3804
|
+
logger2.warn(`Failed to register with service discovery: ${error.message}`);
|
|
3805
|
+
}
|
|
3806
|
+
}
|
|
3164
3807
|
async function bootstrap(AppModule, options = {}) {
|
|
3808
|
+
setupRedisMock();
|
|
3165
3809
|
const app = await NestFactory.create(AppModule);
|
|
3166
3810
|
const logger2 = new Logger("Bootstrap");
|
|
3167
|
-
const requestedPort = options.port || parseInt(process.env.PORT || "
|
|
3811
|
+
const requestedPort = options.port || parseInt(process.env.PORT || "3100", 10);
|
|
3168
3812
|
const port = await findAvailablePort(requestedPort);
|
|
3169
3813
|
const globalPrefix = options.globalPrefix;
|
|
3170
3814
|
if (port !== requestedPort) {
|
|
@@ -3185,63 +3829,27 @@ async function bootstrap(AppModule, options = {}) {
|
|
|
3185
3829
|
credentials: true
|
|
3186
3830
|
});
|
|
3187
3831
|
const config = new DocumentBuilder().setTitle("Graph Service API").setDescription("API for graph service microservice").setVersion("1.0").addBearerAuth().build();
|
|
3188
|
-
const document = SwaggerModule.createDocument(app, config);
|
|
3189
|
-
SwaggerModule.setup("api/docs", app, document);
|
|
3190
|
-
await app.listen(port);
|
|
3191
|
-
const baseUrl = globalPrefix ? `http://localhost:${port}/${globalPrefix}` : `http://localhost:${port}`;
|
|
3192
|
-
logger2.log(`\u{1F680} Graph service is running on: ${baseUrl}`);
|
|
3193
|
-
logger2.log(`\u{1F4DA} API Documentation: http://localhost:${port}/api/docs`);
|
|
3194
|
-
if (process.env.NODE_ENV !== "production")
|
|
3195
|
-
|
|
3196
|
-
}
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
);
|
|
3203
|
-
if (!existingBuilder) {
|
|
3204
|
-
this.builders.push(builder);
|
|
3205
|
-
}
|
|
3206
|
-
}
|
|
3207
|
-
getBuilders() {
|
|
3208
|
-
return this.builders;
|
|
3209
|
-
}
|
|
3210
|
-
};
|
|
3211
|
-
BuilderRegistryService = __decorateClass([
|
|
3212
|
-
Injectable()
|
|
3213
|
-
], BuilderRegistryService);
|
|
3214
|
-
var GraphEngineType = /* @__PURE__ */ ((GraphEngineType2) => {
|
|
3215
|
-
GraphEngineType2["LANGGRAPH"] = "langgraph";
|
|
3216
|
-
GraphEngineType2["LANGFLOW"] = "langflow";
|
|
3217
|
-
GraphEngineType2["FLOWISE"] = "flowise";
|
|
3218
|
-
return GraphEngineType2;
|
|
3219
|
-
})(GraphEngineType || {});
|
|
3220
|
-
var GraphEngineFactory = class {
|
|
3221
|
-
constructor(langgraph) {
|
|
3222
|
-
this.langgraph = langgraph;
|
|
3223
|
-
}
|
|
3224
|
-
/**
|
|
3225
|
-
* Get engine for the specified type
|
|
3226
|
-
*/
|
|
3227
|
-
getEngine(engineType) {
|
|
3228
|
-
switch (engineType) {
|
|
3229
|
-
case "langgraph" /* LANGGRAPH */:
|
|
3230
|
-
return this.langgraph;
|
|
3231
|
-
// Will add other types in the future
|
|
3232
|
-
// case GraphEngineType.LANGFLOW:
|
|
3233
|
-
// return new LangFlowEngine();
|
|
3234
|
-
// case GraphEngineType.FLOWISE:
|
|
3235
|
-
// return new FlowiseEngine();
|
|
3236
|
-
default:
|
|
3237
|
-
throw new Error(`Unsupported graph engine type: ${engineType}`);
|
|
3238
|
-
}
|
|
3832
|
+
const document = SwaggerModule.createDocument(app, config);
|
|
3833
|
+
SwaggerModule.setup("api/docs", app, document);
|
|
3834
|
+
await app.listen(port);
|
|
3835
|
+
const baseUrl = globalPrefix ? `http://localhost:${port}/${globalPrefix}` : `http://localhost:${port}`;
|
|
3836
|
+
logger2.log(`\u{1F680} Graph service is running on: ${baseUrl}`);
|
|
3837
|
+
logger2.log(`\u{1F4DA} API Documentation: http://localhost:${port}/api/docs`);
|
|
3838
|
+
if (process.env.NODE_ENV !== "production") {
|
|
3839
|
+
logger2.debug(
|
|
3840
|
+
`Attempting service discovery registration (NODE_ENV: ${process.env.NODE_ENV || "undefined"})`
|
|
3841
|
+
);
|
|
3842
|
+
await registerWithServiceDiscovery(AppModule, port, logger2, app);
|
|
3843
|
+
} else {
|
|
3844
|
+
logger2.debug(
|
|
3845
|
+
`Skipping service discovery registration (NODE_ENV: ${process.env.NODE_ENV})`
|
|
3846
|
+
);
|
|
3239
3847
|
}
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3848
|
+
return app;
|
|
3849
|
+
}
|
|
3850
|
+
|
|
3851
|
+
// src/core/index.ts
|
|
3852
|
+
init_builder_registry_service();
|
|
3245
3853
|
|
|
3246
3854
|
// src/messages/attachments.ts
|
|
3247
3855
|
var AttachmentType = /* @__PURE__ */ ((AttachmentType2) => {
|
|
@@ -3623,274 +4231,8 @@ ${result.errors.join("\n")}`
|
|
|
3623
4231
|
}
|
|
3624
4232
|
};
|
|
3625
4233
|
|
|
3626
|
-
// src/
|
|
3627
|
-
|
|
3628
|
-
/**
|
|
3629
|
-
* Parse full graph type
|
|
3630
|
-
* @param fullType - full graph type
|
|
3631
|
-
* @returns object with type components
|
|
3632
|
-
*/
|
|
3633
|
-
static parse(fullType) {
|
|
3634
|
-
if (fullType.includes("::")) {
|
|
3635
|
-
const [baseType, version] = fullType.split("::");
|
|
3636
|
-
const [companyId, name] = baseType.split(".");
|
|
3637
|
-
return { companyId, name, version };
|
|
3638
|
-
}
|
|
3639
|
-
const parts = fullType.split(".");
|
|
3640
|
-
if (parts.length === 1) {
|
|
3641
|
-
return { companyId: "global", name: parts[0] };
|
|
3642
|
-
}
|
|
3643
|
-
return { companyId: parts[0], name: parts[1] };
|
|
3644
|
-
}
|
|
3645
|
-
/**
|
|
3646
|
-
* Build full type from components
|
|
3647
|
-
* @param companyId - company ID
|
|
3648
|
-
* @param name - graph name
|
|
3649
|
-
* @param version - version (optional)
|
|
3650
|
-
* @returns full graph type
|
|
3651
|
-
*/
|
|
3652
|
-
static build(companyId, name, version) {
|
|
3653
|
-
const base = `${companyId}.${name}`;
|
|
3654
|
-
return version ? `${base}::${version}` : base;
|
|
3655
|
-
}
|
|
3656
|
-
/**
|
|
3657
|
-
* Normalize graph type for backward compatibility
|
|
3658
|
-
* @param graphType - graph type in any format
|
|
3659
|
-
* @returns normalized type
|
|
3660
|
-
*/
|
|
3661
|
-
static normalize(graphType) {
|
|
3662
|
-
const { companyId, name, version } = this.parse(graphType);
|
|
3663
|
-
return this.build(companyId, name, version);
|
|
3664
|
-
}
|
|
3665
|
-
/**
|
|
3666
|
-
* Get base type without version
|
|
3667
|
-
* @param graphType - full graph type
|
|
3668
|
-
* @returns base type
|
|
3669
|
-
*/
|
|
3670
|
-
static getBaseType(graphType) {
|
|
3671
|
-
if (graphType.includes("::")) {
|
|
3672
|
-
return graphType.split("::")[0];
|
|
3673
|
-
}
|
|
3674
|
-
const { companyId, name } = this.parse(graphType);
|
|
3675
|
-
return `${companyId}.${name}`;
|
|
3676
|
-
}
|
|
3677
|
-
/**
|
|
3678
|
-
* Extract version from graph type
|
|
3679
|
-
* @param graphType - full graph type
|
|
3680
|
-
* @returns version or undefined
|
|
3681
|
-
*/
|
|
3682
|
-
static getVersion(graphType) {
|
|
3683
|
-
return graphType.includes("::") ? graphType.split("::")[1] : void 0;
|
|
3684
|
-
}
|
|
3685
|
-
/**
|
|
3686
|
-
* Validate version (basic semver check)
|
|
3687
|
-
* @param version - version to check
|
|
3688
|
-
* @returns true if version is valid
|
|
3689
|
-
*/
|
|
3690
|
-
static isValidVersion(version) {
|
|
3691
|
-
const semverRegex = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?$/;
|
|
3692
|
-
return semverRegex.test(version);
|
|
3693
|
-
}
|
|
3694
|
-
/**
|
|
3695
|
-
* Check if type is system (global)
|
|
3696
|
-
* @param graphType - graph type
|
|
3697
|
-
* @returns true if graph is system
|
|
3698
|
-
*/
|
|
3699
|
-
static isSystemGraph(graphType) {
|
|
3700
|
-
const { companyId } = this.parse(graphType);
|
|
3701
|
-
return companyId === "global";
|
|
3702
|
-
}
|
|
3703
|
-
/**
|
|
3704
|
-
* Compare versions (simple comparison for sorting)
|
|
3705
|
-
* @param a - first version
|
|
3706
|
-
* @param b - second version
|
|
3707
|
-
* @returns -1, 0, 1 for sorting
|
|
3708
|
-
*/
|
|
3709
|
-
static compareVersions(a, b) {
|
|
3710
|
-
const parseVersion = (v) => {
|
|
3711
|
-
const [main, prerelease] = v.split("-");
|
|
3712
|
-
const [major, minor, patch] = main.split(".").map(Number);
|
|
3713
|
-
return { major, minor, patch, prerelease };
|
|
3714
|
-
};
|
|
3715
|
-
const versionA = parseVersion(a);
|
|
3716
|
-
const versionB = parseVersion(b);
|
|
3717
|
-
if (versionA.major !== versionB.major) {
|
|
3718
|
-
return versionA.major - versionB.major;
|
|
3719
|
-
}
|
|
3720
|
-
if (versionA.minor !== versionB.minor) {
|
|
3721
|
-
return versionA.minor - versionB.minor;
|
|
3722
|
-
}
|
|
3723
|
-
if (versionA.patch !== versionB.patch) {
|
|
3724
|
-
return versionA.patch - versionB.patch;
|
|
3725
|
-
}
|
|
3726
|
-
if (versionA.prerelease && !versionB.prerelease) return -1;
|
|
3727
|
-
if (!versionA.prerelease && versionB.prerelease) return 1;
|
|
3728
|
-
if (versionA.prerelease && versionB.prerelease) {
|
|
3729
|
-
return versionA.prerelease.localeCompare(versionB.prerelease);
|
|
3730
|
-
}
|
|
3731
|
-
return 0;
|
|
3732
|
-
}
|
|
3733
|
-
};
|
|
3734
|
-
|
|
3735
|
-
// src/graph/versioning/versioned-graph.service.ts
|
|
3736
|
-
var VersionedGraphService = class {
|
|
3737
|
-
logger = new Logger(VersionedGraphService.name);
|
|
3738
|
-
versionConfigs = /* @__PURE__ */ new Map();
|
|
3739
|
-
constructor() {
|
|
3740
|
-
}
|
|
3741
|
-
/**
|
|
3742
|
-
* Register versioning configuration
|
|
3743
|
-
*/
|
|
3744
|
-
registerVersioning(config) {
|
|
3745
|
-
this.versionConfigs.set(config.baseGraphType, config);
|
|
3746
|
-
this.logger.log(
|
|
3747
|
-
`Registered versioning for ${config.baseGraphType} with ${config.versions.length} versions`
|
|
3748
|
-
);
|
|
3749
|
-
}
|
|
3750
|
-
/**
|
|
3751
|
-
* Resolve graph version
|
|
3752
|
-
*/
|
|
3753
|
-
async resolveVersion(graphType, options = {}) {
|
|
3754
|
-
const parsed = GraphTypeUtils.parse(graphType);
|
|
3755
|
-
const baseType = GraphTypeUtils.getBaseType(graphType);
|
|
3756
|
-
const requestedVersion = GraphTypeUtils.getVersion(graphType) || options.requestedVersion;
|
|
3757
|
-
const config = this.versionConfigs.get(baseType);
|
|
3758
|
-
if (!config) {
|
|
3759
|
-
throw new Error(`No versioning configuration found for ${baseType}`);
|
|
3760
|
-
}
|
|
3761
|
-
const route = this.findBestVersionRoute(config, requestedVersion, options);
|
|
3762
|
-
if (!route) {
|
|
3763
|
-
throw new Error(
|
|
3764
|
-
`No compatible version found for ${graphType} with options: ${JSON.stringify(options)}`
|
|
3765
|
-
);
|
|
3766
|
-
}
|
|
3767
|
-
const fullGraphType = GraphTypeUtils.build(
|
|
3768
|
-
parsed.companyId,
|
|
3769
|
-
parsed.name,
|
|
3770
|
-
route.version
|
|
3771
|
-
);
|
|
3772
|
-
return {
|
|
3773
|
-
version: route.version,
|
|
3774
|
-
builderClass: route.builderClass,
|
|
3775
|
-
fullGraphType
|
|
3776
|
-
};
|
|
3777
|
-
}
|
|
3778
|
-
/**
|
|
3779
|
-
* Create builder for specified version
|
|
3780
|
-
*/
|
|
3781
|
-
async createVersionedBuilder(graphType, moduleRef, options = {}) {
|
|
3782
|
-
const resolution = await this.resolveVersion(graphType, options);
|
|
3783
|
-
try {
|
|
3784
|
-
if (!moduleRef) {
|
|
3785
|
-
throw new Error(
|
|
3786
|
-
"ModuleRef is not available - falling back to direct instantiation"
|
|
3787
|
-
);
|
|
3788
|
-
}
|
|
3789
|
-
const builder = await moduleRef.create(resolution.builderClass);
|
|
3790
|
-
this.logger.debug(
|
|
3791
|
-
`Created versioned builder for ${resolution.fullGraphType}`
|
|
3792
|
-
);
|
|
3793
|
-
return builder;
|
|
3794
|
-
} catch (error) {
|
|
3795
|
-
this.logger.error(
|
|
3796
|
-
`Failed to create builder for ${resolution.fullGraphType}: ${error.message}`
|
|
3797
|
-
);
|
|
3798
|
-
throw new Error(`Failed to create versioned builder: ${error.message}`);
|
|
3799
|
-
}
|
|
3800
|
-
}
|
|
3801
|
-
/**
|
|
3802
|
-
* Get all available versions for a graph
|
|
3803
|
-
*/
|
|
3804
|
-
getAvailableVersions(baseGraphType) {
|
|
3805
|
-
const config = this.versionConfigs.get(baseGraphType);
|
|
3806
|
-
if (!config) {
|
|
3807
|
-
return [];
|
|
3808
|
-
}
|
|
3809
|
-
return config.versions.map((route) => route.version).sort((a, b) => GraphTypeUtils.compareVersions(b, a));
|
|
3810
|
-
}
|
|
3811
|
-
/**
|
|
3812
|
-
* Check version support
|
|
3813
|
-
*/
|
|
3814
|
-
isVersionSupported(graphType, options = {}) {
|
|
3815
|
-
try {
|
|
3816
|
-
const baseType = GraphTypeUtils.getBaseType(graphType);
|
|
3817
|
-
const requestedVersion = GraphTypeUtils.getVersion(graphType);
|
|
3818
|
-
const config = this.versionConfigs.get(baseType);
|
|
3819
|
-
if (!config) {
|
|
3820
|
-
return false;
|
|
3821
|
-
}
|
|
3822
|
-
const route = this.findBestVersionRoute(
|
|
3823
|
-
config,
|
|
3824
|
-
requestedVersion,
|
|
3825
|
-
options
|
|
3826
|
-
);
|
|
3827
|
-
return route !== null;
|
|
3828
|
-
} catch {
|
|
3829
|
-
return false;
|
|
3830
|
-
}
|
|
3831
|
-
}
|
|
3832
|
-
/**
|
|
3833
|
-
* Find best version
|
|
3834
|
-
*/
|
|
3835
|
-
findBestVersionRoute(config, requestedVersion, options = {}) {
|
|
3836
|
-
const { strict = false } = options;
|
|
3837
|
-
let candidates = [...config.versions];
|
|
3838
|
-
if (requestedVersion) {
|
|
3839
|
-
const exactMatch = candidates.find(
|
|
3840
|
-
(route) => route.version === requestedVersion
|
|
3841
|
-
);
|
|
3842
|
-
if (exactMatch) {
|
|
3843
|
-
return exactMatch;
|
|
3844
|
-
}
|
|
3845
|
-
if (strict) {
|
|
3846
|
-
return null;
|
|
3847
|
-
}
|
|
3848
|
-
const compatibleVersions = candidates.filter(
|
|
3849
|
-
(route) => this.isVersionCompatible(requestedVersion, route.version)
|
|
3850
|
-
);
|
|
3851
|
-
if (compatibleVersions.length > 0) {
|
|
3852
|
-
return compatibleVersions.sort(
|
|
3853
|
-
(a, b) => GraphTypeUtils.compareVersions(b.version, a.version)
|
|
3854
|
-
)[0];
|
|
3855
|
-
}
|
|
3856
|
-
}
|
|
3857
|
-
const defaultRoute = candidates.find((route) => route.isDefault);
|
|
3858
|
-
if (defaultRoute) {
|
|
3859
|
-
return defaultRoute;
|
|
3860
|
-
}
|
|
3861
|
-
if (config.defaultVersionStrategy === "latest" || !config.defaultVersionStrategy) {
|
|
3862
|
-
const sortedVersions = candidates.sort(
|
|
3863
|
-
(a, b) => GraphTypeUtils.compareVersions(b.version, a.version)
|
|
3864
|
-
);
|
|
3865
|
-
return sortedVersions[0] || null;
|
|
3866
|
-
}
|
|
3867
|
-
return null;
|
|
3868
|
-
}
|
|
3869
|
-
/**
|
|
3870
|
-
* Check version compatibility (simplified semantics)
|
|
3871
|
-
*/
|
|
3872
|
-
isVersionCompatible(requested, available) {
|
|
3873
|
-
try {
|
|
3874
|
-
const requestedParts = requested.split(".").map(Number);
|
|
3875
|
-
const availableParts = available.split(".").map(Number);
|
|
3876
|
-
if (requestedParts[0] !== availableParts[0]) {
|
|
3877
|
-
return false;
|
|
3878
|
-
}
|
|
3879
|
-
return GraphTypeUtils.compareVersions(available, requested) >= 0;
|
|
3880
|
-
} catch {
|
|
3881
|
-
return false;
|
|
3882
|
-
}
|
|
3883
|
-
}
|
|
3884
|
-
/**
|
|
3885
|
-
* Get versioning configuration information
|
|
3886
|
-
*/
|
|
3887
|
-
getVersioningInfo(baseGraphType) {
|
|
3888
|
-
return this.versionConfigs.get(baseGraphType) || null;
|
|
3889
|
-
}
|
|
3890
|
-
};
|
|
3891
|
-
VersionedGraphService = __decorateClass([
|
|
3892
|
-
Injectable()
|
|
3893
|
-
], VersionedGraphService);
|
|
4234
|
+
// src/graph/versioning/index.ts
|
|
4235
|
+
init_versioned_graph_service();
|
|
3894
4236
|
var logger = new Logger("ApiCallTracer");
|
|
3895
4237
|
var DEFAULT_TRACER_OPTIONS = {
|
|
3896
4238
|
maxStringLength: 5e3,
|
|
@@ -4034,8 +4376,36 @@ function sanitizeTraceError(error, options) {
|
|
|
4034
4376
|
raw: sanitizeTraceData(error, 0, /* @__PURE__ */ new WeakSet(), options)
|
|
4035
4377
|
};
|
|
4036
4378
|
}
|
|
4037
|
-
|
|
4038
|
-
|
|
4379
|
+
var GraphEngineType = /* @__PURE__ */ ((GraphEngineType2) => {
|
|
4380
|
+
GraphEngineType2["LANGGRAPH"] = "langgraph";
|
|
4381
|
+
GraphEngineType2["LANGFLOW"] = "langflow";
|
|
4382
|
+
GraphEngineType2["FLOWISE"] = "flowise";
|
|
4383
|
+
return GraphEngineType2;
|
|
4384
|
+
})(GraphEngineType || {});
|
|
4385
|
+
var GraphEngineFactory = class {
|
|
4386
|
+
constructor(langgraph) {
|
|
4387
|
+
this.langgraph = langgraph;
|
|
4388
|
+
}
|
|
4389
|
+
/**
|
|
4390
|
+
* Get engine for the specified type
|
|
4391
|
+
*/
|
|
4392
|
+
getEngine(engineType) {
|
|
4393
|
+
switch (engineType) {
|
|
4394
|
+
case "langgraph" /* LANGGRAPH */:
|
|
4395
|
+
return this.langgraph;
|
|
4396
|
+
// Will add other types in the future
|
|
4397
|
+
// case GraphEngineType.LANGFLOW:
|
|
4398
|
+
// return new LangFlowEngine();
|
|
4399
|
+
// case GraphEngineType.FLOWISE:
|
|
4400
|
+
// return new FlowiseEngine();
|
|
4401
|
+
default:
|
|
4402
|
+
throw new Error(`Unsupported graph engine type: ${engineType}`);
|
|
4403
|
+
}
|
|
4404
|
+
}
|
|
4405
|
+
};
|
|
4406
|
+
GraphEngineFactory = __decorateClass([
|
|
4407
|
+
Injectable()
|
|
4408
|
+
], GraphEngineFactory);
|
|
4039
4409
|
var EventProcessor = class {
|
|
4040
4410
|
logger = new Logger(EventProcessor.name);
|
|
4041
4411
|
/**
|
|
@@ -4049,7 +4419,9 @@ var EventProcessor = class {
|
|
|
4049
4419
|
llmCalls: [],
|
|
4050
4420
|
traceEvents: [],
|
|
4051
4421
|
traceStartedAt: null,
|
|
4052
|
-
traceCompletedAt: null
|
|
4422
|
+
traceCompletedAt: null,
|
|
4423
|
+
currentReasoningSteps: [],
|
|
4424
|
+
currentToolUse: null
|
|
4053
4425
|
};
|
|
4054
4426
|
}
|
|
4055
4427
|
/**
|
|
@@ -4077,6 +4449,51 @@ var EventProcessor = class {
|
|
|
4077
4449
|
}
|
|
4078
4450
|
return [];
|
|
4079
4451
|
}
|
|
4452
|
+
/**
|
|
4453
|
+
* Groups tool_use and input_json_delta into proper structure
|
|
4454
|
+
* tool_use.input → output (tool execution result)
|
|
4455
|
+
* input_json_delta.input → output (tool execution result, accumulated)
|
|
4456
|
+
*/
|
|
4457
|
+
mapReasoningSteps(rawSteps) {
|
|
4458
|
+
const steps = [];
|
|
4459
|
+
let currentToolUse = null;
|
|
4460
|
+
for (const raw of rawSteps) {
|
|
4461
|
+
if (raw.type === "tool_use" || raw.type === "tool_call") {
|
|
4462
|
+
if (currentToolUse) {
|
|
4463
|
+
steps.push(currentToolUse);
|
|
4464
|
+
}
|
|
4465
|
+
currentToolUse = {
|
|
4466
|
+
index: raw.index || 0,
|
|
4467
|
+
type: "tool_use",
|
|
4468
|
+
name: raw.name,
|
|
4469
|
+
id: raw.id,
|
|
4470
|
+
input: "",
|
|
4471
|
+
// Parameters (IN) - filled separately or empty
|
|
4472
|
+
output: raw.input || ""
|
|
4473
|
+
// Result (OUT) - comes in tool_use.input
|
|
4474
|
+
};
|
|
4475
|
+
} else if (raw.type === "input_json_delta") {
|
|
4476
|
+
if (currentToolUse) {
|
|
4477
|
+
currentToolUse.output = (currentToolUse.output || "") + (raw.input || "");
|
|
4478
|
+
}
|
|
4479
|
+
} else {
|
|
4480
|
+
if (currentToolUse) {
|
|
4481
|
+
steps.push(currentToolUse);
|
|
4482
|
+
currentToolUse = null;
|
|
4483
|
+
}
|
|
4484
|
+
steps.push({
|
|
4485
|
+
index: raw.index || 0,
|
|
4486
|
+
type: raw.type,
|
|
4487
|
+
text: raw.text || "",
|
|
4488
|
+
metadata: raw.metadata
|
|
4489
|
+
});
|
|
4490
|
+
}
|
|
4491
|
+
}
|
|
4492
|
+
if (currentToolUse) {
|
|
4493
|
+
steps.push(currentToolUse);
|
|
4494
|
+
}
|
|
4495
|
+
return steps;
|
|
4496
|
+
}
|
|
4080
4497
|
/**
|
|
4081
4498
|
* Process a LangGraph stream event
|
|
4082
4499
|
* Mutates accumulator to collect data from different channels
|
|
@@ -4099,8 +4516,44 @@ var EventProcessor = class {
|
|
|
4099
4516
|
if (event.event === "on_chat_model_stream" && event.metadata?.stream_channel === "processing" /* PROCESSING */ && event.data?.chunk?.content) {
|
|
4100
4517
|
const chunk = event.data.chunk.content;
|
|
4101
4518
|
const blocks = this.normalizeContentBlocks(chunk);
|
|
4102
|
-
|
|
4103
|
-
|
|
4519
|
+
for (const block of blocks) {
|
|
4520
|
+
if (block.type === "tool_use" || block.type === "tool_call") {
|
|
4521
|
+
if (acc.currentToolUse) {
|
|
4522
|
+
acc.currentReasoningSteps.push(acc.currentToolUse);
|
|
4523
|
+
}
|
|
4524
|
+
acc.currentToolUse = {
|
|
4525
|
+
index: acc.currentReasoningSteps.length,
|
|
4526
|
+
type: "tool_use",
|
|
4527
|
+
name: block.name,
|
|
4528
|
+
id: block.id,
|
|
4529
|
+
input: block.input || "",
|
|
4530
|
+
output: ""
|
|
4531
|
+
};
|
|
4532
|
+
if (onPartial) {
|
|
4533
|
+
onPartial(
|
|
4534
|
+
JSON.stringify({
|
|
4535
|
+
processing_delta: {
|
|
4536
|
+
type: "step_started",
|
|
4537
|
+
step: acc.currentToolUse
|
|
4538
|
+
}
|
|
4539
|
+
})
|
|
4540
|
+
);
|
|
4541
|
+
}
|
|
4542
|
+
} else if (block.type === "input_json_delta") {
|
|
4543
|
+
if (acc.currentToolUse && onPartial) {
|
|
4544
|
+
const chunk2 = block.input || "";
|
|
4545
|
+
acc.currentToolUse.output += chunk2;
|
|
4546
|
+
onPartial(
|
|
4547
|
+
JSON.stringify({
|
|
4548
|
+
processing_delta: {
|
|
4549
|
+
type: "output_chunk",
|
|
4550
|
+
stepId: acc.currentToolUse.id,
|
|
4551
|
+
chunk: chunk2
|
|
4552
|
+
}
|
|
4553
|
+
})
|
|
4554
|
+
);
|
|
4555
|
+
}
|
|
4556
|
+
}
|
|
4104
4557
|
}
|
|
4105
4558
|
return;
|
|
4106
4559
|
}
|
|
@@ -4137,29 +4590,59 @@ var EventProcessor = class {
|
|
|
4137
4590
|
);
|
|
4138
4591
|
}
|
|
4139
4592
|
if (event.metadata?.stream_channel === "processing" /* PROCESSING */) {
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
[];
|
|
4144
|
-
let steps;
|
|
4145
|
-
if (Array.isArray(stepsRaw)) {
|
|
4146
|
-
steps = stepsRaw;
|
|
4147
|
-
} else if (typeof stepsRaw === "string" && stepsRaw.trim().length > 0) {
|
|
4148
|
-
steps = [
|
|
4149
|
-
{
|
|
4150
|
-
index: 0,
|
|
4151
|
-
type: "text",
|
|
4152
|
-
text: stepsRaw.trim()
|
|
4153
|
-
}
|
|
4154
|
-
];
|
|
4155
|
-
} else {
|
|
4156
|
-
steps = [];
|
|
4593
|
+
if (acc.currentToolUse) {
|
|
4594
|
+
acc.currentReasoningSteps.push(acc.currentToolUse);
|
|
4595
|
+
acc.currentToolUse = null;
|
|
4157
4596
|
}
|
|
4158
|
-
if (
|
|
4597
|
+
if (acc.currentReasoningSteps.length > 0) {
|
|
4159
4598
|
acc.reasoningChains.push({
|
|
4160
|
-
steps,
|
|
4599
|
+
steps: acc.currentReasoningSteps,
|
|
4161
4600
|
isComplete: true
|
|
4162
4601
|
});
|
|
4602
|
+
if (onPartial) {
|
|
4603
|
+
onPartial(
|
|
4604
|
+
JSON.stringify({
|
|
4605
|
+
processing_delta: {
|
|
4606
|
+
type: "chain_completed"
|
|
4607
|
+
}
|
|
4608
|
+
})
|
|
4609
|
+
);
|
|
4610
|
+
}
|
|
4611
|
+
acc.currentReasoningSteps = [];
|
|
4612
|
+
} else {
|
|
4613
|
+
const stepsRaw = output?.content || // AIMessageChunk object (direct)
|
|
4614
|
+
output?.kwargs?.content || // Serialized LangChain format
|
|
4615
|
+
event.data?.chunk?.content || // Older version
|
|
4616
|
+
[];
|
|
4617
|
+
let steps;
|
|
4618
|
+
if (Array.isArray(stepsRaw)) {
|
|
4619
|
+
steps = this.mapReasoningSteps(stepsRaw);
|
|
4620
|
+
} else if (typeof stepsRaw === "string" && stepsRaw.trim().length > 0) {
|
|
4621
|
+
steps = [
|
|
4622
|
+
{
|
|
4623
|
+
index: 0,
|
|
4624
|
+
type: "text",
|
|
4625
|
+
text: stepsRaw.trim()
|
|
4626
|
+
}
|
|
4627
|
+
];
|
|
4628
|
+
} else {
|
|
4629
|
+
steps = [];
|
|
4630
|
+
}
|
|
4631
|
+
if (steps.length > 0) {
|
|
4632
|
+
acc.reasoningChains.push({
|
|
4633
|
+
steps,
|
|
4634
|
+
isComplete: true
|
|
4635
|
+
});
|
|
4636
|
+
if (onPartial) {
|
|
4637
|
+
onPartial(
|
|
4638
|
+
JSON.stringify({
|
|
4639
|
+
processing_delta: {
|
|
4640
|
+
type: "chain_completed"
|
|
4641
|
+
}
|
|
4642
|
+
})
|
|
4643
|
+
);
|
|
4644
|
+
}
|
|
4645
|
+
}
|
|
4163
4646
|
}
|
|
4164
4647
|
}
|
|
4165
4648
|
return;
|
|
@@ -4568,12 +5051,11 @@ var LangGraphEngine = class {
|
|
|
4568
5051
|
}
|
|
4569
5052
|
};
|
|
4570
5053
|
LangGraphEngine = __decorateClass([
|
|
4571
|
-
Injectable()
|
|
4572
|
-
__decorateParam(0, Inject())
|
|
5054
|
+
Injectable()
|
|
4573
5055
|
], LangGraphEngine);
|
|
4574
5056
|
|
|
4575
5057
|
// src/core/universal-graph.module.ts
|
|
4576
|
-
|
|
5058
|
+
init_builder_registry_service();
|
|
4577
5059
|
init_agent_ui();
|
|
4578
5060
|
function createMetaBuilder(config, versionedGraphService, moduleRef, callbackRegistry, endpointRegistry) {
|
|
4579
5061
|
const className = `${config.baseGraphType.replace(/\./g, "")}VersionRouter`;
|
|
@@ -4642,6 +5124,8 @@ function createMetaBuilder(config, versionedGraphService, moduleRef, callbackReg
|
|
|
4642
5124
|
var UniversalGraphModule = class {
|
|
4643
5125
|
static forRoot(options) {
|
|
4644
5126
|
const providers = [
|
|
5127
|
+
// Discovery services from @nestjs/core
|
|
5128
|
+
MetadataScanner,
|
|
4645
5129
|
// Event processor for stream handling
|
|
4646
5130
|
EventProcessor,
|
|
4647
5131
|
// Graph engines
|
|
@@ -4671,14 +5155,8 @@ var UniversalGraphModule = class {
|
|
|
4671
5155
|
provide: CallbackRegistry,
|
|
4672
5156
|
useClass: CallbackRegistry
|
|
4673
5157
|
},
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
useClass: EndpointRegistry
|
|
4677
|
-
},
|
|
4678
|
-
{
|
|
4679
|
-
provide: UIEndpointsDiscoveryService,
|
|
4680
|
-
useClass: UIEndpointsDiscoveryService
|
|
4681
|
-
},
|
|
5158
|
+
EndpointRegistry,
|
|
5159
|
+
UIEndpointsDiscoveryService,
|
|
4682
5160
|
{
|
|
4683
5161
|
provide: CallbackACL,
|
|
4684
5162
|
useClass: CallbackACL
|
|
@@ -4755,14 +5233,6 @@ var UniversalGraphModule = class {
|
|
|
4755
5233
|
},
|
|
4756
5234
|
inject: [CallbackRegistry]
|
|
4757
5235
|
},
|
|
4758
|
-
{
|
|
4759
|
-
provide: "UI_ENDPOINTS_DISCOVERY",
|
|
4760
|
-
useFactory: async (discoveryService) => {
|
|
4761
|
-
await discoveryService.discoverUIEndpoints();
|
|
4762
|
-
return true;
|
|
4763
|
-
},
|
|
4764
|
-
inject: [UIEndpointsDiscoveryService]
|
|
4765
|
-
},
|
|
4766
5236
|
{
|
|
4767
5237
|
provide: "GRAPH_ENGINE",
|
|
4768
5238
|
useFactory: (factory) => {
|
|
@@ -5182,6 +5652,94 @@ var McpToolFilter = class _McpToolFilter {
|
|
|
5182
5652
|
}
|
|
5183
5653
|
}
|
|
5184
5654
|
};
|
|
5655
|
+
var McpRuntimeHttpClient = class {
|
|
5656
|
+
logger = new Logger(McpRuntimeHttpClient.name);
|
|
5657
|
+
httpClient;
|
|
5658
|
+
baseUrl;
|
|
5659
|
+
constructor(mcpRuntimeUrl) {
|
|
5660
|
+
this.baseUrl = mcpRuntimeUrl || process.env.MCP_RUNTIME_URL || "http://localhost:3004";
|
|
5661
|
+
this.httpClient = axios2.create({
|
|
5662
|
+
baseURL: this.baseUrl,
|
|
5663
|
+
timeout: 3e4
|
|
5664
|
+
// 30 seconds
|
|
5665
|
+
});
|
|
5666
|
+
this.logger.log(
|
|
5667
|
+
`MCP Runtime HTTP Client initialized with URL: ${this.baseUrl}`
|
|
5668
|
+
);
|
|
5669
|
+
}
|
|
5670
|
+
/**
|
|
5671
|
+
* Get all available tools from MCP Runtime
|
|
5672
|
+
*/
|
|
5673
|
+
async getTools() {
|
|
5674
|
+
try {
|
|
5675
|
+
this.logger.debug("Fetching available tools from MCP runtime");
|
|
5676
|
+
const response = await this.httpClient.get("/tools/list");
|
|
5677
|
+
const tools = Array.isArray(response.data) ? response.data : [];
|
|
5678
|
+
this.logger.log(`Retrieved ${tools.length} tools from MCP runtime`);
|
|
5679
|
+
return tools;
|
|
5680
|
+
} catch (error) {
|
|
5681
|
+
this.logger.error("Failed to fetch tools from MCP runtime:", error);
|
|
5682
|
+
throw new Error(`Failed to fetch tools: ${error.message}`);
|
|
5683
|
+
}
|
|
5684
|
+
}
|
|
5685
|
+
/**
|
|
5686
|
+
* Execute a tool by name with given arguments
|
|
5687
|
+
*/
|
|
5688
|
+
async executeTool(name, args, context) {
|
|
5689
|
+
try {
|
|
5690
|
+
this.logger.debug(`Executing tool: ${name} with args:`, args);
|
|
5691
|
+
const payload = {
|
|
5692
|
+
name,
|
|
5693
|
+
arguments: args || {}
|
|
5694
|
+
};
|
|
5695
|
+
if (context) {
|
|
5696
|
+
payload.context = context;
|
|
5697
|
+
}
|
|
5698
|
+
const response = await this.httpClient.post("/tools/execute", payload);
|
|
5699
|
+
this.logger.log(`Tool ${name} executed successfully`);
|
|
5700
|
+
return response.data;
|
|
5701
|
+
} catch (error) {
|
|
5702
|
+
this.logger.error(`Failed to execute tool ${name}:`, error);
|
|
5703
|
+
if (error.response) {
|
|
5704
|
+
return {
|
|
5705
|
+
success: false,
|
|
5706
|
+
error: error.response.data.message || error.response.data.error || "Tool execution failed"
|
|
5707
|
+
};
|
|
5708
|
+
}
|
|
5709
|
+
return {
|
|
5710
|
+
success: false,
|
|
5711
|
+
error: error.message || "Unknown error occurred"
|
|
5712
|
+
};
|
|
5713
|
+
}
|
|
5714
|
+
}
|
|
5715
|
+
/**
|
|
5716
|
+
* Get tool execution statistics from MCP Runtime
|
|
5717
|
+
*/
|
|
5718
|
+
async getToolStats() {
|
|
5719
|
+
try {
|
|
5720
|
+
const response = await this.httpClient.get("/tools/stats");
|
|
5721
|
+
return response.data;
|
|
5722
|
+
} catch (error) {
|
|
5723
|
+
this.logger.error("Failed to fetch tool stats:", error);
|
|
5724
|
+
return null;
|
|
5725
|
+
}
|
|
5726
|
+
}
|
|
5727
|
+
/**
|
|
5728
|
+
* Health check for MCP Runtime service
|
|
5729
|
+
*/
|
|
5730
|
+
async isHealthy() {
|
|
5731
|
+
try {
|
|
5732
|
+
const response = await this.httpClient.get("/", { timeout: 5e3 });
|
|
5733
|
+
return response.status === 200;
|
|
5734
|
+
} catch (error) {
|
|
5735
|
+
this.logger.warn("MCP Runtime health check failed:", error.message);
|
|
5736
|
+
return false;
|
|
5737
|
+
}
|
|
5738
|
+
}
|
|
5739
|
+
};
|
|
5740
|
+
McpRuntimeHttpClient = __decorateClass([
|
|
5741
|
+
Injectable()
|
|
5742
|
+
], McpRuntimeHttpClient);
|
|
5185
5743
|
|
|
5186
5744
|
// src/models/enums.ts
|
|
5187
5745
|
var ModelProvider = /* @__PURE__ */ ((ModelProvider2) => {
|
|
@@ -6343,6 +6901,28 @@ RetrieverService = __decorateClass([
|
|
|
6343
6901
|
Injectable()
|
|
6344
6902
|
], RetrieverService);
|
|
6345
6903
|
|
|
6346
|
-
|
|
6904
|
+
// src/utils/index.ts
|
|
6905
|
+
init_graph_type_utils();
|
|
6906
|
+
|
|
6907
|
+
// src/service-discovery/index.ts
|
|
6908
|
+
init_file_based_discovery();
|
|
6909
|
+
var StaticDiscovery = class {
|
|
6910
|
+
constructor(services) {
|
|
6911
|
+
this.services = services;
|
|
6912
|
+
}
|
|
6913
|
+
/**
|
|
6914
|
+
* Get list of services by category
|
|
6915
|
+
*/
|
|
6916
|
+
async getServices(category) {
|
|
6917
|
+
return this.services.filter(
|
|
6918
|
+
(service) => service.category === category || service.metadata?.category === category
|
|
6919
|
+
);
|
|
6920
|
+
}
|
|
6921
|
+
};
|
|
6922
|
+
StaticDiscovery = __decorateClass([
|
|
6923
|
+
Injectable()
|
|
6924
|
+
], StaticDiscovery);
|
|
6925
|
+
|
|
6926
|
+
export { AbstractGraphBuilder, AttachmentType, GraphController as BaseGraphServiceController, UniversalGraphModule as BaseGraphServiceModule, BuilderRegistryService, Callback, CallbackACL, CallbackAuditAction, CallbackAuditor, CallbackController, CallbackMetrics, CallbackPatchService, CallbackRateLimiter, CallbackRegistry, CallbackStore, CallbackTokenGuard, ChatFeature, DEFAULT_TRACER_OPTIONS, ENDPOINT_METADATA_KEY, Endpoint, EndpointRegistry, EventProcessor, FileBasedDiscovery, GraphController, GraphEngineFactory, GraphEngineType, GraphManifestSchema, GraphManifestValidator, GraphServiceTokens, GraphTypeUtils, IdempotencyManager, IdempotencyStatus, LangGraphEngine, McpConverter, McpRuntimeHttpClient, McpToolFilter, ModelInitializer, ModelProvider, ModelType, RetrieverSearchType, RetrieverService, SmartCallbackRouter, StaticDiscovery, StreamChannel, TelegramPatchHandler, UIDispatchController, UIEndpoint, UIEndpointsDiscoveryService, UniversalCallbackService, UniversalGraphModule, UniversalGraphService, VersionedGraphService, VoyageAIRerank, WebPatchHandler, WithCallbacks, WithEndpoints, WithUIEndpoints, bootstrap, createEndpointDescriptors, findCallbackMethod, findEndpointMethod, getCallbackMetadata, getEndpointMetadata, getUIEndpointClassMetadata, getUIEndpointMethodsMetadata, hasCallbacks, hasUIEndpoints, prepareModelWithTools, registerFinanceExampleCallback, registerUIEndpointsFromClass, sanitizeTraceData, traceApiCall };
|
|
6347
6927
|
//# sourceMappingURL=index.js.map
|
|
6348
6928
|
//# sourceMappingURL=index.js.map
|