@carlonicora/nestjs-neo4jsonapi 2.7.2 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/graph.creator/services/graph.creator.service.d.ts +82 -0
- package/dist/agents/graph.creator/services/graph.creator.service.d.ts.map +1 -1
- package/dist/agents/graph.creator/services/graph.creator.service.js +43 -10
- package/dist/agents/graph.creator/services/graph.creator.service.js.map +1 -1
- package/dist/agents/index.d.ts +1 -1
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +7 -1
- package/dist/agents/index.js.map +1 -1
- package/dist/config/base.config.d.ts.map +1 -1
- package/dist/config/base.config.js +4 -0
- package/dist/config/base.config.js.map +1 -1
- package/dist/config/interfaces/config.ai.interface.d.ts +5 -0
- package/dist/config/interfaces/config.ai.interface.d.ts.map +1 -1
- package/dist/config/interfaces/config.prompts.interface.d.ts +15 -0
- package/dist/config/interfaces/config.prompts.interface.d.ts.map +1 -1
- package/dist/core/llm/index.d.ts +2 -0
- package/dist/core/llm/index.d.ts.map +1 -1
- package/dist/core/llm/index.js +2 -0
- package/dist/core/llm/index.js.map +1 -1
- package/dist/core/llm/interfaces/ai-candidate.interface.d.ts +32 -0
- package/dist/core/llm/interfaces/ai-candidate.interface.d.ts.map +1 -0
- package/dist/core/llm/interfaces/ai-candidate.interface.js +15 -0
- package/dist/core/llm/interfaces/ai-candidate.interface.js.map +1 -0
- package/dist/core/llm/llm.module.d.ts.map +1 -1
- package/dist/core/llm/llm.module.js +6 -1
- package/dist/core/llm/llm.module.js.map +1 -1
- package/dist/core/llm/services/ai-connection-resolver.service.d.ts +107 -0
- package/dist/core/llm/services/ai-connection-resolver.service.d.ts.map +1 -0
- package/dist/core/llm/services/ai-connection-resolver.service.js +329 -0
- package/dist/core/llm/services/ai-connection-resolver.service.js.map +1 -0
- package/dist/core/llm/services/embedder.service.d.ts +21 -0
- package/dist/core/llm/services/embedder.service.d.ts.map +1 -1
- package/dist/core/llm/services/embedder.service.js +52 -3
- package/dist/core/llm/services/embedder.service.js.map +1 -1
- package/dist/core/llm/services/llm.service.d.ts +65 -18
- package/dist/core/llm/services/llm.service.d.ts.map +1 -1
- package/dist/core/llm/services/llm.service.js +214 -70
- package/dist/core/llm/services/llm.service.js.map +1 -1
- package/dist/core/llm/services/model.service.d.ts +79 -2
- package/dist/core/llm/services/model.service.d.ts.map +1 -1
- package/dist/core/llm/services/model.service.js +289 -31
- package/dist/core/llm/services/model.service.js.map +1 -1
- package/dist/core/llm/services/vision.llm.service.d.ts +25 -1
- package/dist/core/llm/services/vision.llm.service.d.ts.map +1 -1
- package/dist/core/llm/services/vision.llm.service.js +74 -33
- package/dist/core/llm/services/vision.llm.service.js.map +1 -1
- package/dist/foundations/ai-connection/ai-connection.module.d.ts +5 -0
- package/dist/foundations/ai-connection/ai-connection.module.d.ts.map +1 -0
- package/dist/foundations/ai-connection/ai-connection.module.js +37 -0
- package/dist/foundations/ai-connection/ai-connection.module.js.map +1 -0
- package/dist/foundations/ai-connection/controllers/ai-connection.controller.d.ts +32 -0
- package/dist/foundations/ai-connection/controllers/ai-connection.controller.d.ts.map +1 -0
- package/dist/foundations/ai-connection/controllers/ai-connection.controller.js +162 -0
- package/dist/foundations/ai-connection/controllers/ai-connection.controller.js.map +1 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.post.dto.d.ts +41 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.post.dto.d.ts.map +1 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.post.dto.js +189 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.post.dto.js.map +1 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.put.dto.d.ts +42 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.put.dto.d.ts.map +1 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.put.dto.js +179 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.put.dto.js.map +1 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.reorder.dto.d.ts +8 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.reorder.dto.d.ts.map +1 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.reorder.dto.js +38 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.reorder.dto.js.map +1 -0
- package/dist/foundations/ai-connection/entities/ai-connection.d.ts +57 -0
- package/dist/foundations/ai-connection/entities/ai-connection.d.ts.map +1 -0
- package/dist/foundations/ai-connection/entities/ai-connection.js +73 -0
- package/dist/foundations/ai-connection/entities/ai-connection.js.map +1 -0
- package/dist/foundations/ai-connection/entities/ai-connection.meta.d.ts +3 -0
- package/dist/foundations/ai-connection/entities/ai-connection.meta.d.ts.map +1 -0
- package/dist/foundations/ai-connection/entities/ai-connection.meta.js +10 -0
- package/dist/foundations/ai-connection/entities/ai-connection.meta.js.map +1 -0
- package/dist/foundations/ai-connection/index.d.ts +12 -0
- package/dist/foundations/ai-connection/index.d.ts.map +1 -0
- package/dist/foundations/ai-connection/index.js +35 -0
- package/dist/foundations/ai-connection/index.js.map +1 -0
- package/dist/foundations/ai-connection/registry/ai-provider.registry.d.ts +54 -0
- package/dist/foundations/ai-connection/registry/ai-provider.registry.d.ts.map +1 -0
- package/dist/foundations/ai-connection/registry/ai-provider.registry.js +255 -0
- package/dist/foundations/ai-connection/registry/ai-provider.registry.js.map +1 -0
- package/dist/foundations/ai-connection/repositories/ai-connection.repository.d.ts +52 -0
- package/dist/foundations/ai-connection/repositories/ai-connection.repository.d.ts.map +1 -0
- package/dist/foundations/ai-connection/repositories/ai-connection.repository.js +85 -0
- package/dist/foundations/ai-connection/repositories/ai-connection.repository.js.map +1 -0
- package/dist/foundations/ai-connection/services/ai-connection-encryption.service.d.ts +52 -0
- package/dist/foundations/ai-connection/services/ai-connection-encryption.service.d.ts.map +1 -0
- package/dist/foundations/ai-connection/services/ai-connection-encryption.service.js +148 -0
- package/dist/foundations/ai-connection/services/ai-connection-encryption.service.js.map +1 -0
- package/dist/foundations/ai-connection/services/ai-connection.service.d.ts +79 -0
- package/dist/foundations/ai-connection/services/ai-connection.service.d.ts.map +1 -0
- package/dist/foundations/ai-connection/services/ai-connection.service.js +184 -0
- package/dist/foundations/ai-connection/services/ai-connection.service.js.map +1 -0
- package/dist/foundations/foundations.modules.d.ts.map +1 -1
- package/dist/foundations/foundations.modules.js +2 -0
- package/dist/foundations/foundations.modules.js.map +1 -1
- package/dist/foundations/index.d.ts +1 -0
- package/dist/foundations/index.d.ts.map +1 -1
- package/dist/foundations/index.js +1 -0
- package/dist/foundations/index.js.map +1 -1
- package/dist/foundations/tokenusage/services/tokenusage.service.d.ts +29 -0
- package/dist/foundations/tokenusage/services/tokenusage.service.d.ts.map +1 -1
- package/dist/foundations/tokenusage/services/tokenusage.service.js +15 -3
- package/dist/foundations/tokenusage/services/tokenusage.service.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from "./ai-connection.module";
|
|
2
|
+
export * from "./entities/ai-connection";
|
|
3
|
+
export * from "./entities/ai-connection.meta";
|
|
4
|
+
export * from "./dtos/ai-connection.post.dto";
|
|
5
|
+
export * from "./dtos/ai-connection.put.dto";
|
|
6
|
+
export * from "./dtos/ai-connection.reorder.dto";
|
|
7
|
+
export * from "./registry/ai-provider.registry";
|
|
8
|
+
export * from "./repositories/ai-connection.repository";
|
|
9
|
+
export * from "./services/ai-connection-encryption.service";
|
|
10
|
+
export * from "./services/ai-connection.service";
|
|
11
|
+
export * from "./controllers/ai-connection.controller";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/foundations/ai-connection/index.ts"],"names":[],"mappings":"AACA,cAAc,wBAAwB,CAAC;AAGvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAG9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AAGjD,cAAc,iCAAiC,CAAC;AAGhD,cAAc,yCAAyC,CAAC;AAGxD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,kCAAkC,CAAC;AAGjD,cAAc,wCAAwC,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
// Module
|
|
18
|
+
__exportStar(require("./ai-connection.module"), exports);
|
|
19
|
+
// Entities
|
|
20
|
+
__exportStar(require("./entities/ai-connection"), exports);
|
|
21
|
+
__exportStar(require("./entities/ai-connection.meta"), exports);
|
|
22
|
+
// DTOs
|
|
23
|
+
__exportStar(require("./dtos/ai-connection.post.dto"), exports);
|
|
24
|
+
__exportStar(require("./dtos/ai-connection.put.dto"), exports);
|
|
25
|
+
__exportStar(require("./dtos/ai-connection.reorder.dto"), exports);
|
|
26
|
+
// Registry
|
|
27
|
+
__exportStar(require("./registry/ai-provider.registry"), exports);
|
|
28
|
+
// Repositories
|
|
29
|
+
__exportStar(require("./repositories/ai-connection.repository"), exports);
|
|
30
|
+
// Services
|
|
31
|
+
__exportStar(require("./services/ai-connection-encryption.service"), exports);
|
|
32
|
+
__exportStar(require("./services/ai-connection.service"), exports);
|
|
33
|
+
// Controllers
|
|
34
|
+
__exportStar(require("./controllers/ai-connection.controller"), exports);
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/foundations/ai-connection/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,SAAS;AACT,yDAAuC;AAEvC,WAAW;AACX,2DAAyC;AACzC,gEAA8C;AAE9C,OAAO;AACP,gEAA8C;AAC9C,+DAA6C;AAC7C,mEAAiD;AAEjD,WAAW;AACX,kEAAgD;AAEhD,eAAe;AACf,0EAAwD;AAExD,WAAW;AACX,8EAA4D;AAC5D,mEAAiD;AAEjD,cAAc;AACd,yEAAuD"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { AiConnectionType } from "../../../core/llm/interfaces/ai-candidate.interface";
|
|
2
|
+
/**
|
|
3
|
+
* How the admin editor renders a provider field, and how the write-side
|
|
4
|
+
* validator interprets it.
|
|
5
|
+
*
|
|
6
|
+
* - `text` — free-form string input
|
|
7
|
+
* - `secret` — write-only value, encrypted at rest, never serialised back
|
|
8
|
+
* - `number` — numeric input
|
|
9
|
+
* - `boolean` — checkbox
|
|
10
|
+
* - `select` — closed set, constrained by {@link AiProviderFieldDescriptor.options}
|
|
11
|
+
*/
|
|
12
|
+
export type AiProviderFieldKind = "text" | "secret" | "number" | "boolean" | "select";
|
|
13
|
+
/**
|
|
14
|
+
* One configurable field of one provider. Structure only — no display text:
|
|
15
|
+
* the frontend derives its i18n keys from `field`.
|
|
16
|
+
*/
|
|
17
|
+
export interface AiProviderFieldDescriptor {
|
|
18
|
+
field: string;
|
|
19
|
+
kind: AiProviderFieldKind;
|
|
20
|
+
required?: boolean;
|
|
21
|
+
options?: string[];
|
|
22
|
+
default?: string | number | boolean;
|
|
23
|
+
}
|
|
24
|
+
/** The complete field set one provider exposes for one connection type. */
|
|
25
|
+
export interface AiProviderDescriptor {
|
|
26
|
+
provider: string;
|
|
27
|
+
fields: AiProviderFieldDescriptor[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The single source of truth for which providers each connection type accepts and
|
|
31
|
+
* which fields each provider exposes. Drives (a) write-side validation, (b) the
|
|
32
|
+
* admin editor form (served as top-level JSON:API `meta.providerRegistry`), and
|
|
33
|
+
* (c) resolver normalisation.
|
|
34
|
+
*/
|
|
35
|
+
export declare const AI_PROVIDER_REGISTRY: Record<AiConnectionType, AiProviderDescriptor[]>;
|
|
36
|
+
/**
|
|
37
|
+
* Write-side gate for an AiConnection: the provider must be legal for the type,
|
|
38
|
+
* every required field must be present, no unsupported field may be set, closed
|
|
39
|
+
* sets must be respected, and any URL must survive {@link validateAiUrl} (HTTPS or
|
|
40
|
+
* loopback, plus the optional AI_URL_ALLOWLIST).
|
|
41
|
+
*
|
|
42
|
+
* A PUT that keeps a stored secret sends no secret value, so the caller (the
|
|
43
|
+
* AiConnection service) merges stored secrets back in BEFORE calling this — the
|
|
44
|
+
* validator itself needs no special case.
|
|
45
|
+
*
|
|
46
|
+
* @throws {BadRequestException} on any registry violation.
|
|
47
|
+
* @throws {Error} when a url/directUrl fails {@link validateAiUrl}.
|
|
48
|
+
*/
|
|
49
|
+
export declare function validateAiConnectionAttributes(params: {
|
|
50
|
+
connectionType: string;
|
|
51
|
+
provider: string;
|
|
52
|
+
attributes: Record<string, unknown>;
|
|
53
|
+
}): void;
|
|
54
|
+
//# sourceMappingURL=ai-provider.registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-provider.registry.d.ts","sourceRoot":"","sources":["../../../../src/foundations/ai-connection/registry/ai-provider.registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qDAAqD,CAAC;AAGvF;;;;;;;;;GASG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEtF;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,mBAAmB,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;CACrC;AAED,2EAA2E;AAC3E,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,yBAAyB,EAAE,CAAC;CACrC;AAmMD;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,gBAAgB,EAAE,oBAAoB,EAAE,CAgBjF,CAAC;AAKF;;;;;;;;;;;;GAYG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE;IACrD,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC,GAAG,IAAI,CAgCP"}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AI_PROVIDER_REGISTRY = void 0;
|
|
4
|
+
exports.validateAiConnectionAttributes = validateAiConnectionAttributes;
|
|
5
|
+
const common_1 = require("@nestjs/common");
|
|
6
|
+
const model_service_1 = require("../../../core/llm/services/model.service");
|
|
7
|
+
/**
|
|
8
|
+
* `reasoning_effort` is the same closed set everywhere it is offered — it mirrors
|
|
9
|
+
* REASONING_EFFORTS in `model.service.ts`.
|
|
10
|
+
*/
|
|
11
|
+
const REASONING_EFFORT_FIELD = {
|
|
12
|
+
field: "reasoningEffort",
|
|
13
|
+
kind: "select",
|
|
14
|
+
options: ["none", "minimal", "low", "medium", "high"],
|
|
15
|
+
};
|
|
16
|
+
const MAX_OUTPUT_TOKENS_FIELD = { field: "maxOutputTokens", kind: "number" };
|
|
17
|
+
/**
|
|
18
|
+
* Per-connection cost overrides for token-billed modalities. A DB connection
|
|
19
|
+
* carries its own rates so token-usage costing reflects the connection that
|
|
20
|
+
* actually served the call (spec § Decisions — "Costs").
|
|
21
|
+
*/
|
|
22
|
+
const CHAT_COST_FIELDS = [
|
|
23
|
+
{ field: "inputCostPer1MTokens", kind: "number" },
|
|
24
|
+
{ field: "outputCostPer1MTokens", kind: "number" },
|
|
25
|
+
{ field: "cachedInputCostPer1MTokens", kind: "number" },
|
|
26
|
+
];
|
|
27
|
+
/**
|
|
28
|
+
* Providers that go through `ModelService.buildChatModel` — the `ai`, `aiLite`,
|
|
29
|
+
* `aiLarge`, `vision` and `audio` connection types all share this set.
|
|
30
|
+
*/
|
|
31
|
+
const CHAT_PROVIDERS = [
|
|
32
|
+
{
|
|
33
|
+
provider: "openrouter",
|
|
34
|
+
fields: [
|
|
35
|
+
{ field: "model", kind: "text", required: true },
|
|
36
|
+
{ field: "apiKey", kind: "secret", required: true },
|
|
37
|
+
{ field: "url", kind: "text", default: "https://openrouter.ai/api/v1" },
|
|
38
|
+
{ field: "region", kind: "text" },
|
|
39
|
+
{ field: "allowFallbacks", kind: "boolean", default: true },
|
|
40
|
+
REASONING_EFFORT_FIELD,
|
|
41
|
+
MAX_OUTPUT_TOKENS_FIELD,
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
provider: "azure",
|
|
46
|
+
fields: [
|
|
47
|
+
{ field: "instance", kind: "text", required: true },
|
|
48
|
+
{ field: "model", kind: "text", required: true },
|
|
49
|
+
{ field: "apiKey", kind: "secret", required: true },
|
|
50
|
+
{ field: "apiVersion", kind: "text", required: true },
|
|
51
|
+
REASONING_EFFORT_FIELD,
|
|
52
|
+
MAX_OUTPUT_TOKENS_FIELD,
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
provider: "vertex",
|
|
57
|
+
fields: [
|
|
58
|
+
{ field: "model", kind: "text", required: true },
|
|
59
|
+
{ field: "region", kind: "text", required: true },
|
|
60
|
+
{ field: "googleCredentialsBase64", kind: "secret", required: true },
|
|
61
|
+
MAX_OUTPUT_TOKENS_FIELD,
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
provider: "requesty",
|
|
66
|
+
fields: [
|
|
67
|
+
{ field: "model", kind: "text", required: true },
|
|
68
|
+
{ field: "apiKey", kind: "secret", required: true },
|
|
69
|
+
{ field: "url", kind: "text", required: true },
|
|
70
|
+
REASONING_EFFORT_FIELD,
|
|
71
|
+
MAX_OUTPUT_TOKENS_FIELD,
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
provider: "ollama",
|
|
76
|
+
fields: [
|
|
77
|
+
{ field: "model", kind: "text", required: true },
|
|
78
|
+
{ field: "url", kind: "text", default: "http://localhost:11434/v1" },
|
|
79
|
+
MAX_OUTPUT_TOKENS_FIELD,
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
provider: "llamacpp",
|
|
84
|
+
fields: [{ field: "url", kind: "text", default: "http://localhost:8033/v1" }],
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
provider: "custom",
|
|
88
|
+
fields: [
|
|
89
|
+
{ field: "model", kind: "text", required: true },
|
|
90
|
+
{ field: "url", kind: "text", required: true },
|
|
91
|
+
{ field: "apiKey", kind: "secret" },
|
|
92
|
+
REASONING_EFFORT_FIELD,
|
|
93
|
+
MAX_OUTPUT_TOKENS_FIELD,
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
];
|
|
97
|
+
/** Appends per-connection-type extra fields to every provider row of that type. */
|
|
98
|
+
const withExtras = (rows, extras) => rows.map((row) => ({ provider: row.provider, fields: [...row.fields, ...extras] }));
|
|
99
|
+
const EMBEDDER_COST_FIELDS = [{ field: "inputCostPer1MTokens", kind: "number" }];
|
|
100
|
+
/**
|
|
101
|
+
* Embedder providers mirror the `buildInnerEmbedder` switch in `model.service.ts`
|
|
102
|
+
* (`openrouter`, `requesty`, `openai`, `azure`, `vertex` — `local` throws there and
|
|
103
|
+
* is therefore not offered).
|
|
104
|
+
*/
|
|
105
|
+
const EMBEDDER_PROVIDERS = [
|
|
106
|
+
{
|
|
107
|
+
provider: "openrouter",
|
|
108
|
+
fields: [
|
|
109
|
+
{ field: "model", kind: "text", required: true },
|
|
110
|
+
{ field: "dimensions", kind: "number", required: true },
|
|
111
|
+
{ field: "apiKey", kind: "secret", required: true },
|
|
112
|
+
{ field: "url", kind: "text", required: true },
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
provider: "requesty",
|
|
117
|
+
fields: [
|
|
118
|
+
{ field: "model", kind: "text", required: true },
|
|
119
|
+
{ field: "dimensions", kind: "number", required: true },
|
|
120
|
+
{ field: "apiKey", kind: "secret", required: true },
|
|
121
|
+
{ field: "url", kind: "text", required: true },
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
provider: "openai",
|
|
126
|
+
fields: [
|
|
127
|
+
{ field: "model", kind: "text", required: true },
|
|
128
|
+
{ field: "dimensions", kind: "number", required: true },
|
|
129
|
+
{ field: "apiKey", kind: "secret", required: true },
|
|
130
|
+
],
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
provider: "azure",
|
|
134
|
+
fields: [
|
|
135
|
+
{ field: "model", kind: "text", required: true },
|
|
136
|
+
{ field: "dimensions", kind: "number", required: true },
|
|
137
|
+
{ field: "apiKey", kind: "secret", required: true },
|
|
138
|
+
{ field: "instance", kind: "text", required: true },
|
|
139
|
+
{ field: "apiVersion", kind: "text", required: true },
|
|
140
|
+
],
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
provider: "vertex",
|
|
144
|
+
fields: [
|
|
145
|
+
{ field: "model", kind: "text", required: true },
|
|
146
|
+
{ field: "dimensions", kind: "number", required: true },
|
|
147
|
+
{ field: "region", kind: "text", required: true },
|
|
148
|
+
{ field: "googleCredentialsBase64", kind: "secret", required: true },
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
];
|
|
152
|
+
/**
|
|
153
|
+
* SDK-based transcription providers, mirroring the `getTranscriber` switch in
|
|
154
|
+
* `model.service.ts` (`openai` / `azure` — anything else throws there).
|
|
155
|
+
*/
|
|
156
|
+
const TRANSCRIBER_PROVIDERS = [
|
|
157
|
+
{
|
|
158
|
+
provider: "openai",
|
|
159
|
+
fields: [
|
|
160
|
+
{ field: "apiKey", kind: "secret", required: true },
|
|
161
|
+
{ field: "model", kind: "text", required: true },
|
|
162
|
+
],
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
provider: "azure",
|
|
166
|
+
fields: [
|
|
167
|
+
{ field: "apiKey", kind: "secret", required: true },
|
|
168
|
+
{ field: "model", kind: "text", required: true },
|
|
169
|
+
{ field: "url", kind: "text", required: true },
|
|
170
|
+
{ field: "apiVersion", kind: "text", required: true },
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
];
|
|
174
|
+
/**
|
|
175
|
+
* Mistral Document AI (OCR). One generic row: the endpoint is fully described by
|
|
176
|
+
* url + apiVersion, so there is nothing provider-specific to branch on.
|
|
177
|
+
*/
|
|
178
|
+
const DOCUMENT_AI_PROVIDERS = [
|
|
179
|
+
{
|
|
180
|
+
provider: "custom",
|
|
181
|
+
fields: [
|
|
182
|
+
{ field: "apiKey", kind: "secret" },
|
|
183
|
+
{ field: "model", kind: "text" },
|
|
184
|
+
{ field: "url", kind: "text" },
|
|
185
|
+
{ field: "apiVersion", kind: "text" },
|
|
186
|
+
{ field: "costPerPage", kind: "number" },
|
|
187
|
+
],
|
|
188
|
+
},
|
|
189
|
+
];
|
|
190
|
+
/**
|
|
191
|
+
* The single source of truth for which providers each connection type accepts and
|
|
192
|
+
* which fields each provider exposes. Drives (a) write-side validation, (b) the
|
|
193
|
+
* admin editor form (served as top-level JSON:API `meta.providerRegistry`), and
|
|
194
|
+
* (c) resolver normalisation.
|
|
195
|
+
*/
|
|
196
|
+
exports.AI_PROVIDER_REGISTRY = {
|
|
197
|
+
ai: withExtras(CHAT_PROVIDERS, CHAT_COST_FIELDS),
|
|
198
|
+
aiLite: withExtras(CHAT_PROVIDERS, CHAT_COST_FIELDS),
|
|
199
|
+
aiLarge: withExtras(CHAT_PROVIDERS, CHAT_COST_FIELDS),
|
|
200
|
+
vision: withExtras(CHAT_PROVIDERS, CHAT_COST_FIELDS),
|
|
201
|
+
audio: withExtras(CHAT_PROVIDERS, [
|
|
202
|
+
...CHAT_COST_FIELDS,
|
|
203
|
+
{ field: "costPerMinute", kind: "number" },
|
|
204
|
+
{ field: "directUrl", kind: "text" },
|
|
205
|
+
{ field: "language", kind: "text" },
|
|
206
|
+
{ field: "directFormat", kind: "select", options: ["multipart", "json"] },
|
|
207
|
+
{ field: "directProvider", kind: "text" },
|
|
208
|
+
]),
|
|
209
|
+
embedder: withExtras(EMBEDDER_PROVIDERS, EMBEDDER_COST_FIELDS),
|
|
210
|
+
transcriber: TRANSCRIBER_PROVIDERS,
|
|
211
|
+
documentAi: DOCUMENT_AI_PROVIDERS,
|
|
212
|
+
};
|
|
213
|
+
/** Fields owned by the base entity, always allowed regardless of provider. */
|
|
214
|
+
const BASE_FIELDS = new Set(["name", "connectionType", "provider", "position", "enabled"]);
|
|
215
|
+
/**
|
|
216
|
+
* Write-side gate for an AiConnection: the provider must be legal for the type,
|
|
217
|
+
* every required field must be present, no unsupported field may be set, closed
|
|
218
|
+
* sets must be respected, and any URL must survive {@link validateAiUrl} (HTTPS or
|
|
219
|
+
* loopback, plus the optional AI_URL_ALLOWLIST).
|
|
220
|
+
*
|
|
221
|
+
* A PUT that keeps a stored secret sends no secret value, so the caller (the
|
|
222
|
+
* AiConnection service) merges stored secrets back in BEFORE calling this — the
|
|
223
|
+
* validator itself needs no special case.
|
|
224
|
+
*
|
|
225
|
+
* @throws {BadRequestException} on any registry violation.
|
|
226
|
+
* @throws {Error} when a url/directUrl fails {@link validateAiUrl}.
|
|
227
|
+
*/
|
|
228
|
+
function validateAiConnectionAttributes(params) {
|
|
229
|
+
const rows = exports.AI_PROVIDER_REGISTRY[params.connectionType];
|
|
230
|
+
if (!rows)
|
|
231
|
+
throw new common_1.BadRequestException(`Unknown connection type "${params.connectionType}"`);
|
|
232
|
+
const row = rows.find((r) => r.provider === params.provider);
|
|
233
|
+
if (!row)
|
|
234
|
+
throw new common_1.BadRequestException(`Provider "${params.provider}" is not available for connection type "${params.connectionType}"`);
|
|
235
|
+
const allowed = new Set([...BASE_FIELDS, ...row.fields.map((f) => f.field)]);
|
|
236
|
+
const present = (name) => {
|
|
237
|
+
const value = params.attributes[name];
|
|
238
|
+
return value !== undefined && value !== null && value !== "";
|
|
239
|
+
};
|
|
240
|
+
const missing = row.fields.filter((f) => f.required && !present(f.field)).map((f) => f.field);
|
|
241
|
+
if (missing.length)
|
|
242
|
+
throw new common_1.BadRequestException(`Missing required field(s) for ${params.provider}: ${missing.join(", ")}`);
|
|
243
|
+
const unknown = Object.keys(params.attributes).filter((key) => present(key) && !allowed.has(key));
|
|
244
|
+
if (unknown.length)
|
|
245
|
+
throw new common_1.BadRequestException(`Field(s) not supported by ${params.provider}: ${unknown.join(", ")}`);
|
|
246
|
+
for (const field of row.fields) {
|
|
247
|
+
if (field.options && present(field.field) && !field.options.includes(String(params.attributes[field.field])))
|
|
248
|
+
throw new common_1.BadRequestException(`"${params.attributes[field.field]}" is not a valid value for ${field.field}`);
|
|
249
|
+
}
|
|
250
|
+
for (const urlField of ["url", "directUrl"]) {
|
|
251
|
+
if (present(urlField))
|
|
252
|
+
(0, model_service_1.validateAiUrl)(String(params.attributes[urlField]), params.provider);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=ai-provider.registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-provider.registry.js","sourceRoot":"","sources":["../../../../src/foundations/ai-connection/registry/ai-provider.registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ClsService } from "nestjs-cls";
|
|
2
|
+
import { AbstractRepository } from "../../../core/neo4j/abstracts/abstract.repository";
|
|
3
|
+
import { Neo4jService } from "../../../core/neo4j/services/neo4j.service";
|
|
4
|
+
import { SecurityService } from "../../../core/security/services/security.service";
|
|
5
|
+
import { AiConnection, AiConnectionDescriptor } from "../entities/ai-connection";
|
|
6
|
+
/**
|
|
7
|
+
* AiConnectionRepository
|
|
8
|
+
*
|
|
9
|
+
* No `buildReturnStatement()` override is needed. The inherited implementation
|
|
10
|
+
* (abstract.repository.ts) skips the `company` relationship only for
|
|
11
|
+
* `isCompanyScoped` entities whose edge is `BELONGS_TO`; this descriptor is
|
|
12
|
+
* `isCompanyScoped: false` with a `CONFIGURES` edge, so the generic loop emits
|
|
13
|
+
* `OPTIONAL MATCH (aiConnection)-[:CONFIGURES]->(aiConnection_company:Company)`
|
|
14
|
+
* (optional because `required: false`) and returns `aiConnection_company` —
|
|
15
|
+
* exactly what the `companyId` computed field reads.
|
|
16
|
+
*/
|
|
17
|
+
export declare class AiConnectionRepository extends AbstractRepository<AiConnection, typeof AiConnectionDescriptor.relationships> {
|
|
18
|
+
protected readonly descriptor: import("../../..").EntityDescriptor<AiConnection, {
|
|
19
|
+
company: {
|
|
20
|
+
model: import("../../..").DataMeta;
|
|
21
|
+
direction: "out";
|
|
22
|
+
relationship: string;
|
|
23
|
+
cardinality: "one";
|
|
24
|
+
required: false;
|
|
25
|
+
dtoKey: string;
|
|
26
|
+
immutable: true;
|
|
27
|
+
};
|
|
28
|
+
}>;
|
|
29
|
+
constructor(neo4j: Neo4jService, securityService: SecurityService, clsService: ClsService);
|
|
30
|
+
/**
|
|
31
|
+
* Full-table system read for the resolver snapshot. Unpaginated by design:
|
|
32
|
+
* this is the resolver's boot/refresh scan over an admin-scale node set
|
|
33
|
+
* (spec § 2 — scale is trivial, tens of nodes), not a user-facing list.
|
|
34
|
+
*/
|
|
35
|
+
findAllForResolver(): Promise<AiConnection[]>;
|
|
36
|
+
/**
|
|
37
|
+
* The connections named by the reorder request, with their computed
|
|
38
|
+
* companyId — the service checks they all belong to one chain before
|
|
39
|
+
* renumbering.
|
|
40
|
+
*/
|
|
41
|
+
findByIds(params: {
|
|
42
|
+
ids: string[];
|
|
43
|
+
}): Promise<AiConnection[]>;
|
|
44
|
+
/**
|
|
45
|
+
* Renumbers one chain to the given order. Single parameterized statement —
|
|
46
|
+
* writeOne because the query contains SET (read transactions reject it).
|
|
47
|
+
*/
|
|
48
|
+
updatePositions(params: {
|
|
49
|
+
ids: string[];
|
|
50
|
+
}): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=ai-connection.repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-connection.repository.d.ts","sourceRoot":"","sources":["../../../../src/foundations/ai-connection/repositories/ai-connection.repository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mDAAmD,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,kDAAkD,CAAC;AACnF,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAGjF;;;;;;;;;;GAUG;AACH,qBACa,sBAAuB,SAAQ,kBAAkB,CAC5D,YAAY,EACZ,OAAO,sBAAsB,CAAC,aAAa,CAC5C;IACC,SAAS,CAAC,QAAQ,CAAC,UAAU;;;;;;;;;;OAA0B;gBAE3C,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU;IAIzF;;;;OAIG;IACG,kBAAkB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAUnD;;;;OAIG;IACG,SAAS,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAWnE;;;OAGG;IACG,eAAe,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAUhE"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.AiConnectionRepository = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const nestjs_cls_1 = require("nestjs-cls");
|
|
15
|
+
const abstract_repository_1 = require("../../../core/neo4j/abstracts/abstract.repository");
|
|
16
|
+
const neo4j_service_1 = require("../../../core/neo4j/services/neo4j.service");
|
|
17
|
+
const security_service_1 = require("../../../core/security/services/security.service");
|
|
18
|
+
const ai_connection_1 = require("../entities/ai-connection");
|
|
19
|
+
const ai_connection_meta_1 = require("../entities/ai-connection.meta");
|
|
20
|
+
/**
|
|
21
|
+
* AiConnectionRepository
|
|
22
|
+
*
|
|
23
|
+
* No `buildReturnStatement()` override is needed. The inherited implementation
|
|
24
|
+
* (abstract.repository.ts) skips the `company` relationship only for
|
|
25
|
+
* `isCompanyScoped` entities whose edge is `BELONGS_TO`; this descriptor is
|
|
26
|
+
* `isCompanyScoped: false` with a `CONFIGURES` edge, so the generic loop emits
|
|
27
|
+
* `OPTIONAL MATCH (aiConnection)-[:CONFIGURES]->(aiConnection_company:Company)`
|
|
28
|
+
* (optional because `required: false`) and returns `aiConnection_company` —
|
|
29
|
+
* exactly what the `companyId` computed field reads.
|
|
30
|
+
*/
|
|
31
|
+
let AiConnectionRepository = class AiConnectionRepository extends abstract_repository_1.AbstractRepository {
|
|
32
|
+
constructor(neo4j, securityService, clsService) {
|
|
33
|
+
super(neo4j, securityService, clsService);
|
|
34
|
+
this.descriptor = ai_connection_1.AiConnectionDescriptor;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Full-table system read for the resolver snapshot. Unpaginated by design:
|
|
38
|
+
* this is the resolver's boot/refresh scan over an admin-scale node set
|
|
39
|
+
* (spec § 2 — scale is trivial, tens of nodes), not a user-facing list.
|
|
40
|
+
*/
|
|
41
|
+
async findAllForResolver() {
|
|
42
|
+
const query = this.neo4j.initQuery({ serialiser: ai_connection_1.AiConnectionDescriptor.model });
|
|
43
|
+
query.query = `
|
|
44
|
+
${this.buildDefaultMatch()}
|
|
45
|
+
ORDER BY ${ai_connection_meta_1.aiConnectionMeta.nodeName}.connectionType ASC, ${ai_connection_meta_1.aiConnectionMeta.nodeName}.position ASC
|
|
46
|
+
${this.buildReturnStatement()}
|
|
47
|
+
`;
|
|
48
|
+
return this.neo4j.readMany(query);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The connections named by the reorder request, with their computed
|
|
52
|
+
* companyId — the service checks they all belong to one chain before
|
|
53
|
+
* renumbering.
|
|
54
|
+
*/
|
|
55
|
+
async findByIds(params) {
|
|
56
|
+
const query = this.neo4j.initQuery({ serialiser: ai_connection_1.AiConnectionDescriptor.model });
|
|
57
|
+
query.queryParams = { ...query.queryParams, ids: params.ids };
|
|
58
|
+
query.query = `
|
|
59
|
+
${this.buildDefaultMatch()}
|
|
60
|
+
WHERE ${ai_connection_meta_1.aiConnectionMeta.nodeName}.id IN $ids
|
|
61
|
+
${this.buildReturnStatement()}
|
|
62
|
+
`;
|
|
63
|
+
return this.neo4j.readMany(query);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Renumbers one chain to the given order. Single parameterized statement —
|
|
67
|
+
* writeOne because the query contains SET (read transactions reject it).
|
|
68
|
+
*/
|
|
69
|
+
async updatePositions(params) {
|
|
70
|
+
await this.neo4j.writeOne({
|
|
71
|
+
query: `
|
|
72
|
+
UNWIND range(0, size($ids) - 1) AS idx
|
|
73
|
+
MATCH (${ai_connection_meta_1.aiConnectionMeta.nodeName}:${ai_connection_meta_1.aiConnectionMeta.labelName} { id: $ids[idx] })
|
|
74
|
+
SET ${ai_connection_meta_1.aiConnectionMeta.nodeName}.position = idx
|
|
75
|
+
`,
|
|
76
|
+
queryParams: { ids: params.ids },
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
exports.AiConnectionRepository = AiConnectionRepository;
|
|
81
|
+
exports.AiConnectionRepository = AiConnectionRepository = __decorate([
|
|
82
|
+
(0, common_1.Injectable)(),
|
|
83
|
+
__metadata("design:paramtypes", [neo4j_service_1.Neo4jService, security_service_1.SecurityService, nestjs_cls_1.ClsService])
|
|
84
|
+
], AiConnectionRepository);
|
|
85
|
+
//# sourceMappingURL=ai-connection.repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-connection.repository.js","sourceRoot":"","sources":["../../../../src/foundations/ai-connection/repositories/ai-connection.repository.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,2CAAwC;AACxC,2FAAuF;AACvF,8EAA0E;AAC1E,uFAAmF;AACnF,6DAAiF;AACjF,uEAAkE;AAElE;;;;;;;;;;GAUG;AAEI,IAAM,sBAAsB,GAA5B,MAAM,sBAAuB,SAAQ,wCAG3C;IAGC,YAAY,KAAmB,EAAE,eAAgC,EAAE,UAAsB;QACvF,KAAK,CAAC,KAAK,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC;QAHzB,eAAU,GAAG,sCAAsB,CAAC;IAIvD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,kBAAkB;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,sCAAsB,CAAC,KAAK,EAAE,CAAC,CAAC;QACjF,KAAK,CAAC,KAAK,GAAG;QACV,IAAI,CAAC,iBAAiB,EAAE;iBACf,qCAAgB,CAAC,QAAQ,wBAAwB,qCAAgB,CAAC,QAAQ;QACnF,IAAI,CAAC,oBAAoB,EAAE;KAC9B,CAAC;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,SAAS,CAAC,MAAyB;QACvC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,sCAAsB,CAAC,KAAK,EAAE,CAAC,CAAC;QACjF,KAAK,CAAC,WAAW,GAAG,EAAE,GAAG,KAAK,CAAC,WAAW,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC;QAC9D,KAAK,CAAC,KAAK,GAAG;QACV,IAAI,CAAC,iBAAiB,EAAE;cAClB,qCAAgB,CAAC,QAAQ;QAC/B,IAAI,CAAC,oBAAoB,EAAE;KAC9B,CAAC;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,eAAe,CAAC,MAAyB;QAC7C,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;YACxB,KAAK,EAAE;;iBAEI,qCAAgB,CAAC,QAAQ,IAAI,qCAAgB,CAAC,SAAS;cAC1D,qCAAgB,CAAC,QAAQ;OAChC;YACD,WAAW,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE;SACjC,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AAvDY,wDAAsB;iCAAtB,sBAAsB;IADlC,IAAA,mBAAU,GAAE;qCAOQ,4BAAY,EAAmB,kCAAe,EAAc,uBAAU;GAN9E,sBAAsB,CAuDlC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Connection Encryption Service
|
|
3
|
+
*
|
|
4
|
+
* Provides AES-256-GCM encryption/decryption for AI connection secrets
|
|
5
|
+
* (`apiKey`, `googleCredentialsBase64`). Secrets are encrypted before storage in
|
|
6
|
+
* Neo4j and decrypted only when the resolver builds a candidate — they are never
|
|
7
|
+
* serialised back over the API.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors {@link TotpEncryptionService} (the in-package AES-256-GCM canonical),
|
|
10
|
+
* keyed from `encryption.key` (ENCRYPTION_KEY) instead of the TOTP key.
|
|
11
|
+
*
|
|
12
|
+
* Format: IV (12 bytes) + AuthTag (16 bytes) + Ciphertext (base64 encoded)
|
|
13
|
+
*/
|
|
14
|
+
export declare class AiConnectionEncryptionService {
|
|
15
|
+
private readonly algorithm;
|
|
16
|
+
private readonly ivLength;
|
|
17
|
+
private readonly authTagLength;
|
|
18
|
+
/**
|
|
19
|
+
* Whether a key is configured at all. Writing a secret without one must fail
|
|
20
|
+
* loudly at the admin API (fail-closed on write, fail-open on read).
|
|
21
|
+
*/
|
|
22
|
+
isConfigured(): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Get the encryption key from config.
|
|
25
|
+
* The key must be exactly 32 bytes (256 bits) for AES-256.
|
|
26
|
+
*/
|
|
27
|
+
private getKey;
|
|
28
|
+
/**
|
|
29
|
+
* Encrypt an AI connection secret using AES-256-GCM.
|
|
30
|
+
*
|
|
31
|
+
* @param plaintext - The secret to encrypt (API key or base64 GCP credentials)
|
|
32
|
+
* @returns The encrypted secret as a base64-encoded string containing IV, auth tag, and ciphertext
|
|
33
|
+
*/
|
|
34
|
+
encrypt(plaintext: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Decrypt an AI connection secret encrypted with AES-256-GCM.
|
|
37
|
+
*
|
|
38
|
+
* @param ciphertext - The base64-encoded encrypted secret (IV + AuthTag + Ciphertext)
|
|
39
|
+
* @returns The decrypted secret
|
|
40
|
+
* @throws Error if decryption fails (invalid key, corrupted data, or tampered data)
|
|
41
|
+
*/
|
|
42
|
+
decrypt(ciphertext: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Verify that the encryption system is properly configured.
|
|
45
|
+
* Performs a round-trip encryption/decryption test.
|
|
46
|
+
*
|
|
47
|
+
* @returns true if encryption is working correctly
|
|
48
|
+
* @throws Error if encryption is not properly configured
|
|
49
|
+
*/
|
|
50
|
+
verify(): boolean;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=ai-connection-encryption.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-connection-encryption.service.d.ts","sourceRoot":"","sources":["../../../../src/foundations/ai-connection/services/ai-connection-encryption.service.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AACH,qBACa,6BAA6B;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAC3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAM;IAC/B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAM;IAEpC;;;OAGG;IACH,YAAY,IAAI,OAAO;IAIvB;;;OAGG;IACH,OAAO,CAAC,MAAM;IAwBd;;;;;OAKG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAelC;;;;;;OAMG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAiBnC;;;;;;OAMG;IACH,MAAM,IAAI,OAAO;CAMlB"}
|