@123toto/ai-app-assistant-server 0.1.1 → 0.2.1
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 +18 -14
- package/dist/{ai-sdk-QImICd56.d.cts → ai-sdk-qU3KgNu-.d.cts} +2 -2
- package/dist/{ai-sdk-QImICd56.d.ts → ai-sdk-qU3KgNu-.d.ts} +2 -2
- package/dist/ai-sdk.d.cts +1 -1
- package/dist/ai-sdk.d.ts +1 -1
- package/dist/{chunk-OA7OXUK7.js → chunk-Z4IVCZ5M.js} +15 -15
- package/dist/chunk-Z4IVCZ5M.js.map +1 -0
- package/dist/express.cjs +8 -8
- package/dist/express.cjs.map +1 -1
- package/dist/express.d.cts +11 -11
- package/dist/express.d.ts +11 -11
- package/dist/express.js +7 -7
- package/dist/express.js.map +1 -1
- package/dist/index.cjs +200 -168
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -33
- package/dist/index.d.ts +33 -33
- package/dist/index.js +175 -143
- package/dist/index.js.map +1 -1
- package/dist/{managed-server-7iurKxF1.d.cts → managed-server-CGmvVYsF.d.ts} +153 -148
- package/dist/{managed-server-CrZumvVU.d.ts → managed-server-CQb-RK-i.d.cts} +153 -148
- package/dist/nest.cjs +31 -31
- package/dist/nest.cjs.map +1 -1
- package/dist/nest.d.cts +12 -12
- package/dist/nest.d.ts +12 -12
- package/dist/nest.js +28 -28
- package/dist/nest.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-OA7OXUK7.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -20,55 +20,55 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
AiAppAssistantConfigurationConflictError: () => AiAppAssistantConfigurationConflictError,
|
|
24
|
+
AiAppAssistantConfigurationManager: () => AiAppAssistantConfigurationManager,
|
|
25
|
+
AiAppAssistantManagementError: () => AiAppAssistantManagementError,
|
|
26
|
+
AiAppAssistantRequestError: () => AiAppAssistantRequestError,
|
|
27
27
|
AiModelDiscoveryError: () => AiModelDiscoveryError,
|
|
28
28
|
AiSdkConfigurationError: () => AiSdkConfigurationError,
|
|
29
29
|
AiSdkGenerationError: () => AiSdkGenerationError,
|
|
30
30
|
PROTOCOL_VERSION: () => import_ai_app_assistant_contracts6.PROTOCOL_VERSION,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
31
|
+
aiAppAssistantAccessRuleSchema: () => import_ai_app_assistant_contracts6.aiAppAssistantAccessRuleSchema,
|
|
32
|
+
aiAppAssistantConfigurationInputSchema: () => import_ai_app_assistant_contracts6.aiAppAssistantConfigurationInputSchema,
|
|
33
|
+
aiAppAssistantConfigurationOptionsSchema: () => import_ai_app_assistant_contracts6.aiAppAssistantConfigurationOptionsSchema,
|
|
34
|
+
aiAppAssistantConfigurationSaveResultSchema: () => import_ai_app_assistant_contracts6.aiAppAssistantConfigurationSaveResultSchema,
|
|
35
|
+
aiAppAssistantConnectionResultSchema: () => import_ai_app_assistant_contracts6.aiAppAssistantConnectionResultSchema,
|
|
36
|
+
aiAppAssistantConnectionTestInputSchema: () => import_ai_app_assistant_contracts6.aiAppAssistantConnectionTestInputSchema,
|
|
37
|
+
aiAppAssistantCredentialsSchema: () => import_ai_app_assistant_contracts6.aiAppAssistantCredentialsSchema,
|
|
38
|
+
aiAppAssistantManagedConfigurationViewSchema: () => import_ai_app_assistant_contracts6.aiAppAssistantManagedConfigurationViewSchema,
|
|
39
|
+
aiAppAssistantModelInfoSchema: () => import_ai_app_assistant_contracts6.aiAppAssistantModelInfoSchema,
|
|
40
|
+
aiAppAssistantProviderInfoSchema: () => import_ai_app_assistant_contracts6.aiAppAssistantProviderInfoSchema,
|
|
41
|
+
aiAppAssistantProviderSchema: () => import_ai_app_assistant_contracts6.aiAppAssistantProviderSchema,
|
|
42
|
+
aiAppAssistantRequestSchema: () => import_ai_app_assistant_contracts6.aiAppAssistantRequestSchema,
|
|
43
|
+
aiAppAssistantResponseSchema: () => import_ai_app_assistant_contracts6.aiAppAssistantResponseSchema,
|
|
44
|
+
aiAppAssistantTransportEventSchema: () => import_ai_app_assistant_contracts6.aiAppAssistantTransportEventSchema,
|
|
45
45
|
createAes256GcmSecretProtector: () => createAes256GcmSecretProtector,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
createAiAppAssistant: () => createAiAppAssistant,
|
|
47
|
+
createAiAppAssistantConfigurationRepository: () => createAiAppAssistantConfigurationRepository,
|
|
48
|
+
createAiAppAssistantDeploymentDefaults: () => createAiAppAssistantDeploymentDefaults,
|
|
49
|
+
createAiAppAssistantFailureEvent: () => createAiAppAssistantFailureEvent,
|
|
50
|
+
createAiAppAssistantFetchHandlers: () => createAiAppAssistantFetchHandlers,
|
|
51
|
+
createAiAppAssistantNodeHttpListener: () => createAiAppAssistantNodeHttpListener,
|
|
52
|
+
createAiAppAssistantServer: () => createAiAppAssistantServer,
|
|
52
53
|
createAiSdkGenerator: () => createAiSdkGenerator,
|
|
53
54
|
createDisabledSecretProtector: () => createDisabledSecretProtector,
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
createMemoryAiDocsTelemetryStore: () => createMemoryAiDocsTelemetryStore,
|
|
55
|
+
createManagedAiAppAssistantFetchHandlers: () => createManagedAiAppAssistantFetchHandlers,
|
|
56
|
+
createManagedAiAppAssistantRuntime: () => createManagedAiAppAssistantRuntime,
|
|
57
|
+
createManagedAiAppAssistantServer: () => createManagedAiAppAssistantServer,
|
|
58
|
+
createMemoryAiAppAssistantQuotaStore: () => createMemoryAiAppAssistantQuotaStore,
|
|
59
|
+
createMemoryAiAppAssistantStore: () => createMemoryAiAppAssistantStore,
|
|
60
|
+
createMemoryAiAppAssistantTelemetryStore: () => createMemoryAiAppAssistantTelemetryStore,
|
|
61
61
|
createOpenAiCompatibleGenerator: () => createOpenAiCompatibleGenerator,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
createPollingAiAppAssistantConfigurationSynchronizer: () => createPollingAiAppAssistantConfigurationSynchronizer,
|
|
63
|
+
createRedisAiAppAssistantQuotaStore: () => createRedisAiAppAssistantQuotaStore,
|
|
64
|
+
createRedisAiAppAssistantStore: () => createRedisAiAppAssistantStore,
|
|
65
|
+
createRedisAiAppAssistantTelemetryStore: () => createRedisAiAppAssistantTelemetryStore,
|
|
66
66
|
filterOpenApiContext: () => filterOpenApiContext,
|
|
67
67
|
listAiModels: () => listAiModels,
|
|
68
68
|
listAiProviders: () => listAiProviders,
|
|
69
69
|
normalizeAiSdkGenerationError: () => normalizeAiSdkGenerationError,
|
|
70
70
|
testAiSdkConnection: () => testAiSdkConnection,
|
|
71
|
-
|
|
71
|
+
validateAndSaveAiAppAssistantConfiguration: () => validateAndSaveAiAppAssistantConfiguration
|
|
72
72
|
});
|
|
73
73
|
module.exports = __toCommonJS(index_exports);
|
|
74
74
|
|
|
@@ -139,7 +139,7 @@ function round(value) {
|
|
|
139
139
|
var FALLBACK_CONTEXT_WINDOW_TOKENS = 128e3;
|
|
140
140
|
var FALLBACK_OUTPUT_TOKENS = 8e3;
|
|
141
141
|
var FALLBACK_CHARACTERS_PER_TOKEN = 2;
|
|
142
|
-
function
|
|
142
|
+
function createAiAppAssistant(options) {
|
|
143
143
|
const minimumEvidence = clampInteger(
|
|
144
144
|
options.policies?.minimumEvidence ?? 1,
|
|
145
145
|
1,
|
|
@@ -147,7 +147,7 @@ function createDocsAssistant(options) {
|
|
|
147
147
|
);
|
|
148
148
|
const documents = prepareDocuments(options.documents ?? []);
|
|
149
149
|
const prepare = (request) => {
|
|
150
|
-
const validated = import_ai_app_assistant_contracts.
|
|
150
|
+
const validated = import_ai_app_assistant_contracts.aiAppAssistantRequestSchema.parse(request);
|
|
151
151
|
return { validated, bundle: prepareBundle(validated, documents, options) };
|
|
152
152
|
};
|
|
153
153
|
const finalize = (validated, bundle, generatedInput, startedAt) => {
|
|
@@ -291,7 +291,7 @@ function prepareBundle(request, documents, options) {
|
|
|
291
291
|
content: boundEvidence(
|
|
292
292
|
request.selectedElementHtml,
|
|
293
293
|
selectedLimit,
|
|
294
|
-
"
|
|
294
|
+
"AI_APP_ASSISTANT_SELECTED_ELEMENT_TRUNCATED"
|
|
295
295
|
),
|
|
296
296
|
relevance: 1
|
|
297
297
|
});
|
|
@@ -306,7 +306,7 @@ function prepareBundle(request, documents, options) {
|
|
|
306
306
|
for (const document of documents) {
|
|
307
307
|
if (remainingDocuments <= 0) break;
|
|
308
308
|
const limit = Math.min(documentLimit, remainingDocuments);
|
|
309
|
-
const content = boundEvidence(document.content, limit, "
|
|
309
|
+
const content = boundEvidence(document.content, limit, "AI_APP_ASSISTANT_DOCUMENT_TRUNCATED");
|
|
310
310
|
remainingDocuments -= content.length;
|
|
311
311
|
items.push({
|
|
312
312
|
source: "document",
|
|
@@ -333,7 +333,7 @@ function serializeDocumentationContent(content) {
|
|
|
333
333
|
function boundHtml(content, maxChars, alreadyTruncated) {
|
|
334
334
|
const limit = optionalBound(maxChars, 1e3, 8e6);
|
|
335
335
|
return alreadyTruncated ? `${content.slice(0, limit)}
|
|
336
|
-
<!--
|
|
336
|
+
<!-- AI_APP_ASSISTANT_HTML_TRUNCATED -->` : boundEvidence(content, limit, "AI_APP_ASSISTANT_HTML_TRUNCATED");
|
|
337
337
|
}
|
|
338
338
|
function boundEvidence(content, limit, marker) {
|
|
339
339
|
if (content.length <= limit) return content;
|
|
@@ -379,28 +379,28 @@ function insufficientResponse(requestId, model, durationMs) {
|
|
|
379
379
|
// src/http.ts
|
|
380
380
|
var import_ai_app_assistant_contracts2 = require("@123toto/ai-app-assistant-contracts");
|
|
381
381
|
var import_zod = require("zod");
|
|
382
|
-
var
|
|
382
|
+
var AiAppAssistantRequestError = class extends Error {
|
|
383
383
|
constructor(status, code, message) {
|
|
384
384
|
super(message);
|
|
385
385
|
this.status = status;
|
|
386
386
|
this.code = code;
|
|
387
|
-
this.name = "
|
|
387
|
+
this.name = "AiAppAssistantRequestError";
|
|
388
388
|
}
|
|
389
389
|
status;
|
|
390
390
|
code;
|
|
391
391
|
};
|
|
392
|
-
function
|
|
392
|
+
function createAiAppAssistantFetchHandlers(options) {
|
|
393
393
|
const prepare = async (request) => {
|
|
394
394
|
assertPost(request);
|
|
395
395
|
const raw = await readJson(request, options.maxBodyBytes ?? 86e5);
|
|
396
|
-
const validated = import_ai_app_assistant_contracts2.
|
|
396
|
+
const validated = import_ai_app_assistant_contracts2.aiAppAssistantRequestSchema.parse(raw);
|
|
397
397
|
if (!options.resolveContext && !options.authorize && !options.allowAnonymous) {
|
|
398
|
-
throw new
|
|
398
|
+
throw new AiAppAssistantRequestError(401, "unauthorized", "Authentication is required");
|
|
399
399
|
}
|
|
400
400
|
const context = options.resolveContext ? await options.resolveContext(request) : void 0;
|
|
401
401
|
await options.authorize?.(context, request);
|
|
402
402
|
const input = options.transformRequest ? await options.transformRequest(validated, context) : validated;
|
|
403
|
-
return { input: import_ai_app_assistant_contracts2.
|
|
403
|
+
return { input: import_ai_app_assistant_contracts2.aiAppAssistantRequestSchema.parse(input), context };
|
|
404
404
|
};
|
|
405
405
|
const present = async (response, context) => options.transformResponse ? options.transformResponse(response, context) : response;
|
|
406
406
|
const ask = async (request) => {
|
|
@@ -463,27 +463,27 @@ function createAiDocsFetchHandlers(options) {
|
|
|
463
463
|
}
|
|
464
464
|
function assertPost(request) {
|
|
465
465
|
if (request.method !== "POST") {
|
|
466
|
-
throw new
|
|
466
|
+
throw new AiAppAssistantRequestError(405, "method_not_allowed", "Only POST is supported");
|
|
467
467
|
}
|
|
468
468
|
}
|
|
469
469
|
async function readJson(request, maxBodyBytes) {
|
|
470
470
|
const contentLength = Number(request.headers.get("content-length"));
|
|
471
471
|
if (Number.isFinite(contentLength) && contentLength > maxBodyBytes) {
|
|
472
|
-
throw new
|
|
472
|
+
throw new AiAppAssistantRequestError(413, "request_too_large", "Request body is too large");
|
|
473
473
|
}
|
|
474
474
|
const text = await request.text();
|
|
475
475
|
if (new TextEncoder().encode(text).byteLength > maxBodyBytes) {
|
|
476
|
-
throw new
|
|
476
|
+
throw new AiAppAssistantRequestError(413, "request_too_large", "Request body is too large");
|
|
477
477
|
}
|
|
478
478
|
try {
|
|
479
479
|
return JSON.parse(text);
|
|
480
480
|
} catch {
|
|
481
|
-
throw new
|
|
481
|
+
throw new AiAppAssistantRequestError(400, "invalid_json", "Request body must be valid JSON");
|
|
482
482
|
}
|
|
483
483
|
}
|
|
484
484
|
async function mapError(error, request, customMapper) {
|
|
485
485
|
if (customMapper) return customMapper(error, request);
|
|
486
|
-
if (error instanceof
|
|
486
|
+
if (error instanceof AiAppAssistantRequestError) {
|
|
487
487
|
return jsonResponse({ error: error.code, message: error.message }, error.status);
|
|
488
488
|
}
|
|
489
489
|
if (error instanceof import_zod.ZodError) {
|
|
@@ -506,15 +506,15 @@ function jsonResponse(value, status = 200) {
|
|
|
506
506
|
}
|
|
507
507
|
|
|
508
508
|
// src/node-http.ts
|
|
509
|
-
function
|
|
509
|
+
function createAiAppAssistantNodeHttpListener(handlers, options = {}) {
|
|
510
510
|
return async (request, response) => {
|
|
511
511
|
try {
|
|
512
512
|
const webRequest = await toRequest(request, options);
|
|
513
513
|
const handle = handlers.handle;
|
|
514
514
|
await writeResponse(response, await handle(webRequest, request));
|
|
515
515
|
} catch (error) {
|
|
516
|
-
const status = error instanceof
|
|
517
|
-
const code = error instanceof
|
|
516
|
+
const status = error instanceof AiAppAssistantRequestError ? error.status : 500;
|
|
517
|
+
const code = error instanceof AiAppAssistantRequestError ? error.code : "assistant_error";
|
|
518
518
|
response.statusCode = status;
|
|
519
519
|
response.setHeader("content-type", "application/json; charset=utf-8");
|
|
520
520
|
response.end(JSON.stringify({ error: code }));
|
|
@@ -544,7 +544,7 @@ async function readBody(request, maxBodyBytes) {
|
|
|
544
544
|
const bytes = typeof chunk === "string" ? Buffer.from(chunk) : new Uint8Array(chunk);
|
|
545
545
|
size += bytes.byteLength;
|
|
546
546
|
if (size > maxBodyBytes) {
|
|
547
|
-
throw new
|
|
547
|
+
throw new AiAppAssistantRequestError(413, "request_too_large", "Request body is too large");
|
|
548
548
|
}
|
|
549
549
|
chunks.push(bytes);
|
|
550
550
|
}
|
|
@@ -1097,22 +1097,22 @@ function serializeEvidence(bundle, kind) {
|
|
|
1097
1097
|
}
|
|
1098
1098
|
|
|
1099
1099
|
// src/server.ts
|
|
1100
|
-
function
|
|
1100
|
+
function createAiAppAssistantServer(options) {
|
|
1101
1101
|
const generator = options.generator ?? createGenerator(options);
|
|
1102
|
-
const assistant =
|
|
1102
|
+
const assistant = createAiAppAssistant({
|
|
1103
1103
|
generator,
|
|
1104
1104
|
...options.documents ? { documents: options.documents } : {},
|
|
1105
1105
|
...options.policies ? { policies: options.policies } : {}
|
|
1106
1106
|
});
|
|
1107
1107
|
return {
|
|
1108
1108
|
assistant,
|
|
1109
|
-
fetch:
|
|
1109
|
+
fetch: createAiAppAssistantFetchHandlers({ assistant, ...options.http }),
|
|
1110
1110
|
options: Object.freeze({ ...options })
|
|
1111
1111
|
};
|
|
1112
1112
|
}
|
|
1113
1113
|
function createGenerator(options) {
|
|
1114
1114
|
if (!options.model?.trim()) {
|
|
1115
|
-
throw new TypeError("
|
|
1115
|
+
throw new TypeError("createAiAppAssistantServer requires either generator or model");
|
|
1116
1116
|
}
|
|
1117
1117
|
const generatorOptions = {
|
|
1118
1118
|
model: options.model,
|
|
@@ -1130,10 +1130,10 @@ var import_node_crypto3 = require("crypto");
|
|
|
1130
1130
|
// src/configuration.ts
|
|
1131
1131
|
var import_node_crypto = require("crypto");
|
|
1132
1132
|
var import_zod3 = require("zod");
|
|
1133
|
-
var
|
|
1133
|
+
var AiAppAssistantConfigurationConflictError = class extends Error {
|
|
1134
1134
|
constructor() {
|
|
1135
|
-
super("AI
|
|
1136
|
-
this.name = "
|
|
1135
|
+
super("AI App Assistant configuration changed concurrently; retry the operation");
|
|
1136
|
+
this.name = "AiAppAssistantConfigurationConflictError";
|
|
1137
1137
|
}
|
|
1138
1138
|
};
|
|
1139
1139
|
var accessRuleSchema = import_zod3.z.discriminatedUnion("mode", [
|
|
@@ -1177,8 +1177,8 @@ var persistedConfigurationSchema = import_zod3.z.object({
|
|
|
1177
1177
|
maxConversationTurns: import_zod3.z.number().int().min(1).max(10).optional(),
|
|
1178
1178
|
administration: administrationSchema.optional()
|
|
1179
1179
|
});
|
|
1180
|
-
function
|
|
1181
|
-
const key = options.key?.trim() || "ai-
|
|
1180
|
+
function createAiAppAssistantConfigurationRepository(options) {
|
|
1181
|
+
const key = options.key?.trim() || "ai-app-assistant:configuration";
|
|
1182
1182
|
const deserialize = async (serialized) => {
|
|
1183
1183
|
if (!serialized) return void 0;
|
|
1184
1184
|
const stored = persistedConfigurationSchema.parse(JSON.parse(serialized));
|
|
@@ -1236,14 +1236,14 @@ function createAiDocsConfigurationRepository(options) {
|
|
|
1236
1236
|
return toConfigurationView(normalized);
|
|
1237
1237
|
}
|
|
1238
1238
|
}
|
|
1239
|
-
throw new
|
|
1239
|
+
throw new AiAppAssistantConfigurationConflictError();
|
|
1240
1240
|
},
|
|
1241
1241
|
async clear() {
|
|
1242
1242
|
await options.store.delete(key);
|
|
1243
1243
|
}
|
|
1244
1244
|
};
|
|
1245
1245
|
}
|
|
1246
|
-
async function
|
|
1246
|
+
async function validateAndSaveAiAppAssistantConfiguration(repository, configuration, options) {
|
|
1247
1247
|
const normalized = normalizeConfiguration(configuration);
|
|
1248
1248
|
const connection = await testAiSdkConnection({
|
|
1249
1249
|
model: `${normalized.provider}:${normalized.model}`,
|
|
@@ -1263,7 +1263,7 @@ function createAes256GcmSecretProtector(base64Key) {
|
|
|
1263
1263
|
if (key.length !== 32) {
|
|
1264
1264
|
throw new TypeError("The secret protection key must contain exactly 32 base64-encoded bytes");
|
|
1265
1265
|
}
|
|
1266
|
-
const additionalData = Buffer.from("ai-
|
|
1266
|
+
const additionalData = Buffer.from("ai-app-assistant-configuration:v1", "utf8");
|
|
1267
1267
|
return {
|
|
1268
1268
|
protect(secret) {
|
|
1269
1269
|
const iv = (0, import_node_crypto.randomBytes)(12);
|
|
@@ -1293,7 +1293,7 @@ function createDisabledSecretProtector() {
|
|
|
1293
1293
|
};
|
|
1294
1294
|
return { protect: unavailable2, unprotect: unavailable2 };
|
|
1295
1295
|
}
|
|
1296
|
-
function
|
|
1296
|
+
function createMemoryAiAppAssistantStore() {
|
|
1297
1297
|
const values = /* @__PURE__ */ new Map();
|
|
1298
1298
|
return {
|
|
1299
1299
|
async get(key) {
|
|
@@ -1313,8 +1313,8 @@ function createMemoryAiDocsStore() {
|
|
|
1313
1313
|
}
|
|
1314
1314
|
};
|
|
1315
1315
|
}
|
|
1316
|
-
function
|
|
1317
|
-
const prefix = options?.prefix ?? "ai-
|
|
1316
|
+
function createRedisAiAppAssistantStore(client, options) {
|
|
1317
|
+
const prefix = options?.prefix ?? "ai-app-assistant:";
|
|
1318
1318
|
const namespaced = (key) => `${prefix}${key}`;
|
|
1319
1319
|
return {
|
|
1320
1320
|
get: (key) => client.get(namespaced(key)),
|
|
@@ -1392,7 +1392,7 @@ function toConfigurationView(configuration) {
|
|
|
1392
1392
|
|
|
1393
1393
|
// src/quota.ts
|
|
1394
1394
|
var import_node_crypto2 = require("crypto");
|
|
1395
|
-
function
|
|
1395
|
+
function createMemoryAiAppAssistantQuotaStore() {
|
|
1396
1396
|
const counters = /* @__PURE__ */ new Map();
|
|
1397
1397
|
return {
|
|
1398
1398
|
async consume(subject, policy) {
|
|
@@ -1409,8 +1409,8 @@ function createMemoryAiDocsQuotaStore() {
|
|
|
1409
1409
|
}
|
|
1410
1410
|
};
|
|
1411
1411
|
}
|
|
1412
|
-
function
|
|
1413
|
-
const prefix = options?.prefix ?? "ai-
|
|
1412
|
+
function createRedisAiAppAssistantQuotaStore(client, options) {
|
|
1413
|
+
const prefix = options?.prefix ?? "ai-app-assistant:quota:";
|
|
1414
1414
|
return {
|
|
1415
1415
|
async consume(subject, policy) {
|
|
1416
1416
|
const normalized = normalizePolicy(policy);
|
|
@@ -1581,19 +1581,19 @@ function isRecord(value) {
|
|
|
1581
1581
|
}
|
|
1582
1582
|
|
|
1583
1583
|
// src/management.ts
|
|
1584
|
-
var
|
|
1584
|
+
var AiAppAssistantManagementError = class extends Error {
|
|
1585
1585
|
constructor(status, code, message, details) {
|
|
1586
1586
|
super(message);
|
|
1587
1587
|
this.status = status;
|
|
1588
1588
|
this.code = code;
|
|
1589
1589
|
this.details = details;
|
|
1590
|
-
this.name = "
|
|
1590
|
+
this.name = "AiAppAssistantManagementError";
|
|
1591
1591
|
}
|
|
1592
1592
|
status;
|
|
1593
1593
|
code;
|
|
1594
1594
|
details;
|
|
1595
1595
|
};
|
|
1596
|
-
var
|
|
1596
|
+
var AiAppAssistantConfigurationManager = class {
|
|
1597
1597
|
#repository;
|
|
1598
1598
|
#quotaStore;
|
|
1599
1599
|
#options;
|
|
@@ -1607,7 +1607,11 @@ var AiDocsConfigurationManager = class {
|
|
|
1607
1607
|
constructor(options) {
|
|
1608
1608
|
this.#options = options;
|
|
1609
1609
|
this.#repository = options.repository;
|
|
1610
|
-
this.#quotaStore = options.quotaStore ??
|
|
1610
|
+
this.#quotaStore = options.quotaStore ?? createMemoryAiAppAssistantQuotaStore();
|
|
1611
|
+
}
|
|
1612
|
+
/** Returns the current state of the host-controlled global kill switch. */
|
|
1613
|
+
isEnabled() {
|
|
1614
|
+
return typeof this.#options.enabled === "function" ? this.#options.enabled() : this.#options.enabled ?? true;
|
|
1611
1615
|
}
|
|
1612
1616
|
/** Returns the built-in provider catalogue; no credentials are exposed. */
|
|
1613
1617
|
listProviders() {
|
|
@@ -1615,6 +1619,7 @@ var AiDocsConfigurationManager = class {
|
|
|
1615
1619
|
}
|
|
1616
1620
|
/** Discovers models with an explicit key or the currently configured secret. */
|
|
1617
1621
|
async listModels(input) {
|
|
1622
|
+
this.assertEnabled();
|
|
1618
1623
|
const apiKey = await this.resolveApiKey(input.provider, input.apiKey);
|
|
1619
1624
|
if (this.#options.listModels) {
|
|
1620
1625
|
return this.#options.listModels({ ...input, ...apiKey ? { apiKey } : {} });
|
|
@@ -1640,7 +1645,10 @@ var AiDocsConfigurationManager = class {
|
|
|
1640
1645
|
let connected = event.connectionValidated;
|
|
1641
1646
|
if (event.reloadRequired) {
|
|
1642
1647
|
this.#recentConnectionValidation = void 0;
|
|
1643
|
-
if (
|
|
1648
|
+
if (!this.isEnabled()) {
|
|
1649
|
+
connected = false;
|
|
1650
|
+
this.#runtimeConnection = { status: "disabled", checkedAt: this.now() };
|
|
1651
|
+
} else if (connected) {
|
|
1644
1652
|
const configuration = await this.getRuntimeConfiguration();
|
|
1645
1653
|
this.#runtimeConnection = configuration ? {
|
|
1646
1654
|
status: "connected",
|
|
@@ -1670,6 +1678,7 @@ var AiDocsConfigurationManager = class {
|
|
|
1670
1678
|
}
|
|
1671
1679
|
/** Tests credentials and briefly caches a successful result for the next save. */
|
|
1672
1680
|
async testConnection(input) {
|
|
1681
|
+
this.assertEnabled();
|
|
1673
1682
|
const apiKey = await this.resolveApiKey(input.provider, input.apiKey);
|
|
1674
1683
|
const connection = this.#options.testConnection ? await this.#options.testConnection({ ...input, ...apiKey ? { apiKey } : {} }) : await testAiSdkConnection({
|
|
1675
1684
|
model: `${input.provider}:${input.model}`,
|
|
@@ -1698,6 +1707,10 @@ var AiDocsConfigurationManager = class {
|
|
|
1698
1707
|
/** Checks the effective stored/deployment connection used by live questions. */
|
|
1699
1708
|
async validateRuntimeConnection() {
|
|
1700
1709
|
this.#lastReconnectAttempt = Date.now();
|
|
1710
|
+
if (!this.isEnabled()) {
|
|
1711
|
+
this.#runtimeConnection = { status: "disabled", checkedAt: this.now() };
|
|
1712
|
+
return false;
|
|
1713
|
+
}
|
|
1701
1714
|
const configuration = await this.getRuntimeConfiguration();
|
|
1702
1715
|
if (!configuration || configuration.provider !== "ollama" && !configuration.apiKey) {
|
|
1703
1716
|
this.#runtimeConnection = {
|
|
@@ -1730,7 +1743,7 @@ var AiDocsConfigurationManager = class {
|
|
|
1730
1743
|
async save(rawInput, actor) {
|
|
1731
1744
|
const input = normalizeInput(rawInput);
|
|
1732
1745
|
if (input.apiKey && !this.#options.apiKeyStorageAvailable) {
|
|
1733
|
-
throw new
|
|
1746
|
+
throw new AiAppAssistantManagementError(
|
|
1734
1747
|
503,
|
|
1735
1748
|
"secret_storage_unavailable",
|
|
1736
1749
|
"Secure API key storage is not configured"
|
|
@@ -1740,6 +1753,7 @@ var AiDocsConfigurationManager = class {
|
|
|
1740
1753
|
const initialActive = this.effectiveConfiguration(initial);
|
|
1741
1754
|
const initialApiKey = input.apiKey ?? (initialActive?.provider === input.provider ? initialActive.apiKey : void 0) ?? this.resolveDefaultApiKey(input.provider);
|
|
1742
1755
|
const initialConnectionChanged = connectionChanged(initialActive, input);
|
|
1756
|
+
if (!this.isEnabled() && initialConnectionChanged) throw disabled();
|
|
1743
1757
|
let connection = initialConnectionChanged ? await this.validateConnectionForSave(input, initialApiKey) : this.lastKnownConnection(input.provider, input.model);
|
|
1744
1758
|
if (initialConnectionChanged && !connection.success) {
|
|
1745
1759
|
return { saved: false, connection, reloadRequired: false };
|
|
@@ -1804,8 +1818,8 @@ var AiDocsConfigurationManager = class {
|
|
|
1804
1818
|
if (error instanceof ConnectionRejectedError) {
|
|
1805
1819
|
return { saved: false, connection: error.connection, reloadRequired: false };
|
|
1806
1820
|
}
|
|
1807
|
-
if (error instanceof
|
|
1808
|
-
throw new
|
|
1821
|
+
if (error instanceof AiAppAssistantConfigurationConflictError) {
|
|
1822
|
+
throw new AiAppAssistantManagementError(409, "conflict", error.message);
|
|
1809
1823
|
}
|
|
1810
1824
|
throw error;
|
|
1811
1825
|
}
|
|
@@ -1836,7 +1850,7 @@ var AiDocsConfigurationManager = class {
|
|
|
1836
1850
|
try {
|
|
1837
1851
|
await persist((previous) => {
|
|
1838
1852
|
if (!previous?.apiKey) {
|
|
1839
|
-
throw new
|
|
1853
|
+
throw new AiAppAssistantManagementError(400, "not_configured", "No manually configured API key is available to revoke");
|
|
1840
1854
|
}
|
|
1841
1855
|
const owner = previous.administration?.keyCreatedBy;
|
|
1842
1856
|
if (owner && owner.id !== actor.id) {
|
|
@@ -1870,8 +1884,8 @@ var AiDocsConfigurationManager = class {
|
|
|
1870
1884
|
};
|
|
1871
1885
|
});
|
|
1872
1886
|
} catch (error) {
|
|
1873
|
-
if (error instanceof
|
|
1874
|
-
throw new
|
|
1887
|
+
if (error instanceof AiAppAssistantConfigurationConflictError) {
|
|
1888
|
+
throw new AiAppAssistantManagementError(409, "conflict", error.message);
|
|
1875
1889
|
}
|
|
1876
1890
|
throw error;
|
|
1877
1891
|
}
|
|
@@ -1968,6 +1982,7 @@ var AiDocsConfigurationManager = class {
|
|
|
1968
1982
|
}
|
|
1969
1983
|
/** Combines configuration, provider health and application access rules. */
|
|
1970
1984
|
async canUse(identity) {
|
|
1985
|
+
if (!this.isEnabled()) return false;
|
|
1971
1986
|
const configuration = await this.getRuntimeConfiguration();
|
|
1972
1987
|
if (!configuration || configuration.provider !== "ollama" && !configuration.apiKey) return false;
|
|
1973
1988
|
if (!await this.ensureRuntimeConnection()) return false;
|
|
@@ -1986,12 +2001,13 @@ var AiDocsConfigurationManager = class {
|
|
|
1986
2001
|
}
|
|
1987
2002
|
/** Enforces access and quota immediately before any model call. */
|
|
1988
2003
|
async assertCanAsk(identity) {
|
|
2004
|
+
this.assertEnabled();
|
|
1989
2005
|
if (!await this.canUse(identity)) {
|
|
1990
2006
|
throw forbidden("AI assistant access is not enabled for this user");
|
|
1991
2007
|
}
|
|
1992
2008
|
const quota = await this.consumeQuota(identity);
|
|
1993
2009
|
if (!quota.allowed) {
|
|
1994
|
-
throw new
|
|
2010
|
+
throw new AiAppAssistantManagementError(
|
|
1995
2011
|
429,
|
|
1996
2012
|
"quota_reached",
|
|
1997
2013
|
"AI assistant quota reached",
|
|
@@ -2001,6 +2017,7 @@ var AiDocsConfigurationManager = class {
|
|
|
2001
2017
|
}
|
|
2002
2018
|
/** Retries a failed provider lazily, with a shared backoff across requests. */
|
|
2003
2019
|
async ensureRuntimeConnection() {
|
|
2020
|
+
if (!this.isEnabled()) return false;
|
|
2004
2021
|
if (this.#runtimeConnection.status === "connected") return true;
|
|
2005
2022
|
const intervalMs = Math.max(1e3, this.#options.reconnectIntervalMs ?? 3e4);
|
|
2006
2023
|
if (Date.now() - this.#lastReconnectAttempt < intervalMs) return false;
|
|
@@ -2108,6 +2125,9 @@ var AiDocsConfigurationManager = class {
|
|
|
2108
2125
|
now() {
|
|
2109
2126
|
return (this.#options.now?.() ?? /* @__PURE__ */ new Date()).toISOString();
|
|
2110
2127
|
}
|
|
2128
|
+
assertEnabled() {
|
|
2129
|
+
if (!this.isEnabled()) throw disabled();
|
|
2130
|
+
}
|
|
2111
2131
|
async publishAndEmit(event) {
|
|
2112
2132
|
await this.#options.synchronizer?.publish(event);
|
|
2113
2133
|
await this.emit(event);
|
|
@@ -2116,8 +2136,8 @@ var AiDocsConfigurationManager = class {
|
|
|
2116
2136
|
await Promise.all([...this.#listeners].map((listener) => listener(event)));
|
|
2117
2137
|
}
|
|
2118
2138
|
};
|
|
2119
|
-
function
|
|
2120
|
-
const key = options.key?.trim() || "ai-
|
|
2139
|
+
function createPollingAiAppAssistantConfigurationSynchronizer(store, options = {}) {
|
|
2140
|
+
const key = options.key?.trim() || "ai-app-assistant:configuration-revision";
|
|
2121
2141
|
const intervalMs = Math.max(250, Math.round(options.intervalMs ?? 2e3));
|
|
2122
2142
|
let current;
|
|
2123
2143
|
return {
|
|
@@ -2229,11 +2249,18 @@ function configurationChanges(previous, input, allowModelChangesByOthers) {
|
|
|
2229
2249
|
return changes;
|
|
2230
2250
|
}
|
|
2231
2251
|
function forbidden(message) {
|
|
2232
|
-
return new
|
|
2252
|
+
return new AiAppAssistantManagementError(403, "forbidden", message);
|
|
2253
|
+
}
|
|
2254
|
+
function disabled() {
|
|
2255
|
+
return new AiAppAssistantManagementError(
|
|
2256
|
+
503,
|
|
2257
|
+
"assistant_disabled",
|
|
2258
|
+
"AI assistant is disabled"
|
|
2259
|
+
);
|
|
2233
2260
|
}
|
|
2234
2261
|
|
|
2235
2262
|
// src/telemetry.ts
|
|
2236
|
-
function
|
|
2263
|
+
function createMemoryAiAppAssistantTelemetryStore(options) {
|
|
2237
2264
|
const recentFailureLimit = normalizeLimit(options?.recentFailureLimit, 100);
|
|
2238
2265
|
const aggregate = emptySummary();
|
|
2239
2266
|
const failures = [];
|
|
@@ -2259,8 +2286,8 @@ function createMemoryAiDocsTelemetryStore(options) {
|
|
|
2259
2286
|
}
|
|
2260
2287
|
};
|
|
2261
2288
|
}
|
|
2262
|
-
function
|
|
2263
|
-
const prefix = options?.prefix ?? "ai-
|
|
2289
|
+
function createRedisAiAppAssistantTelemetryStore(client, options) {
|
|
2290
|
+
const prefix = options?.prefix ?? "ai-app-assistant:telemetry:";
|
|
2264
2291
|
const summaryKey = `${prefix}summary`;
|
|
2265
2292
|
const failuresKey = `${prefix}failures`;
|
|
2266
2293
|
const recentFailureLimit = normalizeLimit(options?.recentFailureLimit, 100);
|
|
@@ -2320,7 +2347,7 @@ function createRedisAiDocsTelemetryStore(client, options) {
|
|
|
2320
2347
|
}
|
|
2321
2348
|
};
|
|
2322
2349
|
}
|
|
2323
|
-
function
|
|
2350
|
+
function createAiAppAssistantFailureEvent(input) {
|
|
2324
2351
|
const failure = input.error instanceof AiSdkGenerationError ? input.error : normalizeAiSdkGenerationError(input.error, 1);
|
|
2325
2352
|
return {
|
|
2326
2353
|
outcome: "failure",
|
|
@@ -2388,7 +2415,7 @@ function redisPairs(value) {
|
|
|
2388
2415
|
}
|
|
2389
2416
|
|
|
2390
2417
|
// src/managed-runtime.ts
|
|
2391
|
-
function
|
|
2418
|
+
function createManagedAiAppAssistantRuntime(options) {
|
|
2392
2419
|
let assistant;
|
|
2393
2420
|
let activeGenerator;
|
|
2394
2421
|
let documents = [...options.documents ?? []];
|
|
@@ -2400,6 +2427,11 @@ function createManagedAiDocsRuntime(options) {
|
|
|
2400
2427
|
return reloadQueue;
|
|
2401
2428
|
});
|
|
2402
2429
|
const rebuild = async (event) => {
|
|
2430
|
+
if (!options.configuration.isEnabled()) {
|
|
2431
|
+
assistant = void 0;
|
|
2432
|
+
activeGenerator = void 0;
|
|
2433
|
+
return;
|
|
2434
|
+
}
|
|
2403
2435
|
const connected = event.connectionValidated || await options.configuration.validateRuntimeConnection();
|
|
2404
2436
|
const configuration = await options.configuration.getRuntimeConfiguration();
|
|
2405
2437
|
if (!connected || !configuration) {
|
|
@@ -2419,7 +2451,7 @@ function createManagedAiDocsRuntime(options) {
|
|
|
2419
2451
|
...options.maxRetries !== void 0 ? { maxRetries: options.maxRetries } : {}
|
|
2420
2452
|
});
|
|
2421
2453
|
activeGenerator = generator;
|
|
2422
|
-
assistant =
|
|
2454
|
+
assistant = createAiAppAssistant({
|
|
2423
2455
|
generator,
|
|
2424
2456
|
documents,
|
|
2425
2457
|
...options.policies ? { policies: options.policies } : {}
|
|
@@ -2461,7 +2493,7 @@ function createManagedAiDocsRuntime(options) {
|
|
|
2461
2493
|
async setDocuments(nextDocuments) {
|
|
2462
2494
|
documents = [...nextDocuments];
|
|
2463
2495
|
if (!activeGenerator) return;
|
|
2464
|
-
assistant =
|
|
2496
|
+
assistant = createAiAppAssistant({
|
|
2465
2497
|
generator: activeGenerator,
|
|
2466
2498
|
documents,
|
|
2467
2499
|
...options.policies ? { policies: options.policies } : {}
|
|
@@ -2487,7 +2519,7 @@ function createManagedAiDocsRuntime(options) {
|
|
|
2487
2519
|
}, identity);
|
|
2488
2520
|
return response;
|
|
2489
2521
|
} catch (error) {
|
|
2490
|
-
await observe(
|
|
2522
|
+
await observe(createAiAppAssistantFailureEvent({
|
|
2491
2523
|
error,
|
|
2492
2524
|
requestId: input.requestId,
|
|
2493
2525
|
operation: "answer",
|
|
@@ -2529,7 +2561,7 @@ function createManagedAiDocsRuntime(options) {
|
|
|
2529
2561
|
yield event;
|
|
2530
2562
|
}
|
|
2531
2563
|
} catch (error) {
|
|
2532
|
-
await observe(
|
|
2564
|
+
await observe(createAiAppAssistantFailureEvent({
|
|
2533
2565
|
error,
|
|
2534
2566
|
requestId: input.requestId,
|
|
2535
2567
|
operation: "stream",
|
|
@@ -2543,7 +2575,7 @@ function createManagedAiDocsRuntime(options) {
|
|
|
2543
2575
|
};
|
|
2544
2576
|
}
|
|
2545
2577
|
function unavailable() {
|
|
2546
|
-
return new
|
|
2578
|
+
return new AiAppAssistantManagementError(
|
|
2547
2579
|
503,
|
|
2548
2580
|
"not_configured",
|
|
2549
2581
|
"AI assistant is not configured or connected"
|
|
@@ -2553,17 +2585,17 @@ function unavailable() {
|
|
|
2553
2585
|
// src/managed-http.ts
|
|
2554
2586
|
var import_ai_app_assistant_contracts4 = require("@123toto/ai-app-assistant-contracts");
|
|
2555
2587
|
var import_zod4 = require("zod");
|
|
2556
|
-
function
|
|
2588
|
+
function createManagedAiAppAssistantFetchHandlers(options) {
|
|
2557
2589
|
const identity = async (request, nativeContext) => {
|
|
2558
2590
|
if (options.resolveIdentity) return options.resolveIdentity(request, nativeContext);
|
|
2559
2591
|
if (options.allowAnonymous) {
|
|
2560
2592
|
return { id: "anonymous", label: "Anonymous", roles: [] };
|
|
2561
2593
|
}
|
|
2562
|
-
throw new
|
|
2594
|
+
throw new AiAppAssistantManagementError(401, "unauthorized", "Authentication is required");
|
|
2563
2595
|
};
|
|
2564
2596
|
const admin = async (request, resolved, nativeContext) => {
|
|
2565
2597
|
if (!options.authorizeAdministration) {
|
|
2566
|
-
throw new
|
|
2598
|
+
throw new AiAppAssistantManagementError(403, "forbidden", "Administration access is not configured");
|
|
2567
2599
|
}
|
|
2568
2600
|
await options.authorizeAdministration(resolved, request, nativeContext);
|
|
2569
2601
|
};
|
|
@@ -2577,13 +2609,13 @@ function createManagedAiDocsFetchHandlers(options) {
|
|
|
2577
2609
|
return json(await options.runtime.configuration.getAccess(currentIdentity));
|
|
2578
2610
|
}
|
|
2579
2611
|
if (request.method === "POST" && path.endsWith("/ask/stream")) {
|
|
2580
|
-
const input = import_ai_app_assistant_contracts4.
|
|
2612
|
+
const input = import_ai_app_assistant_contracts4.aiAppAssistantRequestSchema.parse(await readJson2(request, options.maxBodyBytes));
|
|
2581
2613
|
const generation = options.runtime.stream(input, currentIdentity, request.signal);
|
|
2582
2614
|
const first = await generation.next();
|
|
2583
2615
|
return streamResponse(generation, first, input.requestId);
|
|
2584
2616
|
}
|
|
2585
2617
|
if (request.method === "POST" && path.endsWith("/ask")) {
|
|
2586
|
-
const input = import_ai_app_assistant_contracts4.
|
|
2618
|
+
const input = import_ai_app_assistant_contracts4.aiAppAssistantRequestSchema.parse(await readJson2(request, options.maxBodyBytes));
|
|
2587
2619
|
return json(await options.runtime.answer(input, currentIdentity));
|
|
2588
2620
|
}
|
|
2589
2621
|
await admin(request, currentIdentity, nativeContext);
|
|
@@ -2617,22 +2649,22 @@ function createManagedAiDocsFetchHandlers(options) {
|
|
|
2617
2649
|
return json({ roles, users });
|
|
2618
2650
|
}
|
|
2619
2651
|
if (request.method === "POST" && path.endsWith("/models")) {
|
|
2620
|
-
const input = import_ai_app_assistant_contracts4.
|
|
2652
|
+
const input = import_ai_app_assistant_contracts4.aiAppAssistantCredentialsSchema.parse(await readJson2(request, options.maxBodyBytes));
|
|
2621
2653
|
return json(await options.runtime.configuration.listModels(input));
|
|
2622
2654
|
}
|
|
2623
2655
|
if (request.method === "POST" && path.endsWith("/configuration/test")) {
|
|
2624
|
-
const input = import_ai_app_assistant_contracts4.
|
|
2656
|
+
const input = import_ai_app_assistant_contracts4.aiAppAssistantConnectionTestInputSchema.parse(await readJson2(request, options.maxBodyBytes));
|
|
2625
2657
|
return json(await options.runtime.configuration.testConnection(input));
|
|
2626
2658
|
}
|
|
2627
2659
|
if (request.method === "PUT" && path.endsWith("/configuration")) {
|
|
2628
|
-
const input = import_ai_app_assistant_contracts4.
|
|
2660
|
+
const input = import_ai_app_assistant_contracts4.aiAppAssistantConfigurationInputSchema.parse(await readJson2(request, options.maxBodyBytes));
|
|
2629
2661
|
const { reloadRequired: _reloadRequired, ...result } = await options.runtime.configuration.save(input, currentIdentity);
|
|
2630
2662
|
return json(result);
|
|
2631
2663
|
}
|
|
2632
2664
|
if (request.method === "DELETE" && path.endsWith("/configuration/api-key")) {
|
|
2633
2665
|
return json(await options.runtime.configuration.revokeApiKey(currentIdentity));
|
|
2634
2666
|
}
|
|
2635
|
-
return json({ error: "not_found", message: "AI
|
|
2667
|
+
return json({ error: "not_found", message: "AI App Assistant endpoint not found" }, 404);
|
|
2636
2668
|
} catch (error) {
|
|
2637
2669
|
if (options.onError) return options.onError(error, request, nativeContext);
|
|
2638
2670
|
return mapError2(error);
|
|
@@ -2643,11 +2675,11 @@ function createManagedAiDocsFetchHandlers(options) {
|
|
|
2643
2675
|
async function readJson2(request, maxBodyBytes = 86e5) {
|
|
2644
2676
|
const declaredSize = Number(request.headers.get("content-length"));
|
|
2645
2677
|
if (Number.isFinite(declaredSize) && declaredSize > maxBodyBytes) {
|
|
2646
|
-
throw new
|
|
2678
|
+
throw new AiAppAssistantManagementError(413, "invalid_request", "Request body is too large");
|
|
2647
2679
|
}
|
|
2648
2680
|
const text = await request.text();
|
|
2649
2681
|
if (new TextEncoder().encode(text).byteLength > maxBodyBytes) {
|
|
2650
|
-
throw new
|
|
2682
|
+
throw new AiAppAssistantManagementError(413, "invalid_request", "Request body is too large");
|
|
2651
2683
|
}
|
|
2652
2684
|
return JSON.parse(text);
|
|
2653
2685
|
}
|
|
@@ -2668,9 +2700,9 @@ function streamResponse(generation, first, requestId) {
|
|
|
2668
2700
|
const failure = normalizeAiSdkGenerationError(error, 1);
|
|
2669
2701
|
controller.enqueue(encoder.encode(`${JSON.stringify({
|
|
2670
2702
|
type: "error",
|
|
2671
|
-
message: error instanceof
|
|
2672
|
-
retryable: error instanceof
|
|
2673
|
-
...error instanceof
|
|
2703
|
+
message: error instanceof AiAppAssistantManagementError ? error.message : "The assistant response could not be generated.",
|
|
2704
|
+
retryable: error instanceof AiAppAssistantManagementError ? false : failure.retryable,
|
|
2705
|
+
...error instanceof AiAppAssistantManagementError ? {} : {
|
|
2674
2706
|
code: failure.code,
|
|
2675
2707
|
requestId
|
|
2676
2708
|
}
|
|
@@ -2690,7 +2722,7 @@ function streamResponse(generation, first, requestId) {
|
|
|
2690
2722
|
});
|
|
2691
2723
|
}
|
|
2692
2724
|
function mapError2(error) {
|
|
2693
|
-
if (error instanceof
|
|
2725
|
+
if (error instanceof AiAppAssistantManagementError) {
|
|
2694
2726
|
return json({ error: error.code, message: error.message, ...error.details }, error.status);
|
|
2695
2727
|
}
|
|
2696
2728
|
if (error instanceof import_zod4.ZodError || error instanceof SyntaxError) {
|
|
@@ -2710,16 +2742,16 @@ function json(value, status = 200) {
|
|
|
2710
2742
|
}
|
|
2711
2743
|
|
|
2712
2744
|
// src/managed-server.ts
|
|
2713
|
-
function
|
|
2745
|
+
function createManagedAiAppAssistantServer(options) {
|
|
2714
2746
|
const telemetry = resolveTelemetry(options.configuration, options.telemetry);
|
|
2715
2747
|
const configuration = resolveConfiguration(options.configuration);
|
|
2716
|
-
const runtime =
|
|
2748
|
+
const runtime = createManagedAiAppAssistantRuntime({
|
|
2717
2749
|
configuration,
|
|
2718
2750
|
...options.documents ? { documents: options.documents } : {},
|
|
2719
2751
|
...options.runtime,
|
|
2720
2752
|
...telemetry ? { telemetryStore: telemetry } : {}
|
|
2721
2753
|
});
|
|
2722
|
-
const fetch =
|
|
2754
|
+
const fetch = createManagedAiAppAssistantFetchHandlers({
|
|
2723
2755
|
runtime,
|
|
2724
2756
|
...options.http
|
|
2725
2757
|
});
|
|
@@ -2737,19 +2769,19 @@ function resolveTelemetry(configuration, telemetry) {
|
|
|
2737
2769
|
if (telemetry === false) return void 0;
|
|
2738
2770
|
if (telemetry?.store) return telemetry.store;
|
|
2739
2771
|
const recentFailureLimit = telemetry?.recentFailureLimit;
|
|
2740
|
-
if (!(configuration instanceof
|
|
2741
|
-
return
|
|
2742
|
-
prefix: `${configuration.storage.prefix ?? "ai-
|
|
2772
|
+
if (!(configuration instanceof AiAppAssistantConfigurationManager) && !("repository" in configuration) && configuration.storage?.type === "redis") {
|
|
2773
|
+
return createRedisAiAppAssistantTelemetryStore(configuration.storage.client, {
|
|
2774
|
+
prefix: `${configuration.storage.prefix ?? "ai-app-assistant:"}telemetry:`,
|
|
2743
2775
|
...recentFailureLimit !== void 0 ? { recentFailureLimit } : {}
|
|
2744
2776
|
});
|
|
2745
2777
|
}
|
|
2746
|
-
return
|
|
2778
|
+
return createMemoryAiAppAssistantTelemetryStore(
|
|
2747
2779
|
recentFailureLimit !== void 0 ? { recentFailureLimit } : void 0
|
|
2748
2780
|
);
|
|
2749
2781
|
}
|
|
2750
2782
|
function resolveConfiguration(configuration) {
|
|
2751
|
-
if (configuration instanceof
|
|
2752
|
-
if ("repository" in configuration) return new
|
|
2783
|
+
if (configuration instanceof AiAppAssistantConfigurationManager) return configuration;
|
|
2784
|
+
if ("repository" in configuration) return new AiAppAssistantConfigurationManager(configuration);
|
|
2753
2785
|
const {
|
|
2754
2786
|
storage = { type: "memory" },
|
|
2755
2787
|
encryptionKey,
|
|
@@ -2760,20 +2792,20 @@ function resolveConfiguration(configuration) {
|
|
|
2760
2792
|
apiKeyStorageAvailable,
|
|
2761
2793
|
...manager
|
|
2762
2794
|
} = configuration;
|
|
2763
|
-
const prefix = storage.type === "redis" ? storage.prefix ?? "ai-
|
|
2764
|
-
const store = storage.type === "redis" ?
|
|
2795
|
+
const prefix = storage.type === "redis" ? storage.prefix ?? "ai-app-assistant:" : "ai-app-assistant:";
|
|
2796
|
+
const store = storage.type === "redis" ? createRedisAiAppAssistantStore(storage.client, { prefix: `${prefix}persistent:` }) : createMemoryAiAppAssistantStore();
|
|
2765
2797
|
const protector = secretProtector ?? (encryptionKey ? createAes256GcmSecretProtector(encryptionKey) : createDisabledSecretProtector());
|
|
2766
|
-
return new
|
|
2798
|
+
return new AiAppAssistantConfigurationManager({
|
|
2767
2799
|
...manager,
|
|
2768
|
-
repository:
|
|
2800
|
+
repository: createAiAppAssistantConfigurationRepository({
|
|
2769
2801
|
store,
|
|
2770
2802
|
secretProtector: protector,
|
|
2771
2803
|
...repositoryKey ? { key: repositoryKey } : {}
|
|
2772
2804
|
}),
|
|
2773
|
-
quotaStore: quotaStore ?? (storage.type === "redis" ?
|
|
2805
|
+
quotaStore: quotaStore ?? (storage.type === "redis" ? createRedisAiAppAssistantQuotaStore(storage.client, { prefix: `${prefix}quota:` }) : createMemoryAiAppAssistantQuotaStore()),
|
|
2774
2806
|
apiKeyStorageAvailable: apiKeyStorageAvailable ?? Boolean(secretProtector || encryptionKey),
|
|
2775
2807
|
...synchronizer ? { synchronizer } : storage.type === "redis" ? {
|
|
2776
|
-
synchronizer:
|
|
2808
|
+
synchronizer: createPollingAiAppAssistantConfigurationSynchronizer(store, {
|
|
2777
2809
|
key: "configuration-revision",
|
|
2778
2810
|
intervalMs: storage.synchronizationIntervalMs ?? 2e3
|
|
2779
2811
|
})
|
|
@@ -2782,17 +2814,17 @@ function resolveConfiguration(configuration) {
|
|
|
2782
2814
|
}
|
|
2783
2815
|
|
|
2784
2816
|
// src/deployment-defaults.ts
|
|
2785
|
-
function
|
|
2817
|
+
function createAiAppAssistantDeploymentDefaults(options) {
|
|
2786
2818
|
const apiKeys = Object.fromEntries(
|
|
2787
2819
|
Object.entries(options.apiKeys ?? {}).map(([provider2, value]) => [provider2, value?.trim() || void 0])
|
|
2788
2820
|
);
|
|
2789
2821
|
const resolveApiKey2 = (provider2) => apiKeys[provider2];
|
|
2790
2822
|
if (!options.enabled || !options.model?.trim()) return { resolveApiKey: resolveApiKey2 };
|
|
2791
2823
|
const match = options.model.trim().match(/^([^:/]+)[:/](.+)$/);
|
|
2792
|
-
if (!match) throw new TypeError(`Invalid AI
|
|
2824
|
+
if (!match) throw new TypeError(`Invalid AI App Assistant model identifier: ${options.model}`);
|
|
2793
2825
|
const provider = match[1] === "gemini" ? "google" : match[1];
|
|
2794
2826
|
if (!listAiProviders().some((candidate) => candidate.id === provider)) {
|
|
2795
|
-
throw new TypeError(`Unsupported AI
|
|
2827
|
+
throw new TypeError(`Unsupported AI App Assistant provider: ${match[1]}`);
|
|
2796
2828
|
}
|
|
2797
2829
|
const apiKey = resolveApiKey2(provider);
|
|
2798
2830
|
const baseURL = options.baseURLs?.[provider]?.trim() || void 0;
|
|
@@ -3010,54 +3042,54 @@ function clampInteger3(value, minimum, maximum) {
|
|
|
3010
3042
|
var import_ai_app_assistant_contracts6 = require("@123toto/ai-app-assistant-contracts");
|
|
3011
3043
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3012
3044
|
0 && (module.exports = {
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3045
|
+
AiAppAssistantConfigurationConflictError,
|
|
3046
|
+
AiAppAssistantConfigurationManager,
|
|
3047
|
+
AiAppAssistantManagementError,
|
|
3048
|
+
AiAppAssistantRequestError,
|
|
3017
3049
|
AiModelDiscoveryError,
|
|
3018
3050
|
AiSdkConfigurationError,
|
|
3019
3051
|
AiSdkGenerationError,
|
|
3020
3052
|
PROTOCOL_VERSION,
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3053
|
+
aiAppAssistantAccessRuleSchema,
|
|
3054
|
+
aiAppAssistantConfigurationInputSchema,
|
|
3055
|
+
aiAppAssistantConfigurationOptionsSchema,
|
|
3056
|
+
aiAppAssistantConfigurationSaveResultSchema,
|
|
3057
|
+
aiAppAssistantConnectionResultSchema,
|
|
3058
|
+
aiAppAssistantConnectionTestInputSchema,
|
|
3059
|
+
aiAppAssistantCredentialsSchema,
|
|
3060
|
+
aiAppAssistantManagedConfigurationViewSchema,
|
|
3061
|
+
aiAppAssistantModelInfoSchema,
|
|
3062
|
+
aiAppAssistantProviderInfoSchema,
|
|
3063
|
+
aiAppAssistantProviderSchema,
|
|
3064
|
+
aiAppAssistantRequestSchema,
|
|
3065
|
+
aiAppAssistantResponseSchema,
|
|
3066
|
+
aiAppAssistantTransportEventSchema,
|
|
3035
3067
|
createAes256GcmSecretProtector,
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3068
|
+
createAiAppAssistant,
|
|
3069
|
+
createAiAppAssistantConfigurationRepository,
|
|
3070
|
+
createAiAppAssistantDeploymentDefaults,
|
|
3071
|
+
createAiAppAssistantFailureEvent,
|
|
3072
|
+
createAiAppAssistantFetchHandlers,
|
|
3073
|
+
createAiAppAssistantNodeHttpListener,
|
|
3074
|
+
createAiAppAssistantServer,
|
|
3042
3075
|
createAiSdkGenerator,
|
|
3043
3076
|
createDisabledSecretProtector,
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
createMemoryAiDocsTelemetryStore,
|
|
3077
|
+
createManagedAiAppAssistantFetchHandlers,
|
|
3078
|
+
createManagedAiAppAssistantRuntime,
|
|
3079
|
+
createManagedAiAppAssistantServer,
|
|
3080
|
+
createMemoryAiAppAssistantQuotaStore,
|
|
3081
|
+
createMemoryAiAppAssistantStore,
|
|
3082
|
+
createMemoryAiAppAssistantTelemetryStore,
|
|
3051
3083
|
createOpenAiCompatibleGenerator,
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3084
|
+
createPollingAiAppAssistantConfigurationSynchronizer,
|
|
3085
|
+
createRedisAiAppAssistantQuotaStore,
|
|
3086
|
+
createRedisAiAppAssistantStore,
|
|
3087
|
+
createRedisAiAppAssistantTelemetryStore,
|
|
3056
3088
|
filterOpenApiContext,
|
|
3057
3089
|
listAiModels,
|
|
3058
3090
|
listAiProviders,
|
|
3059
3091
|
normalizeAiSdkGenerationError,
|
|
3060
3092
|
testAiSdkConnection,
|
|
3061
|
-
|
|
3093
|
+
validateAndSaveAiAppAssistantConfiguration
|
|
3062
3094
|
});
|
|
3063
3095
|
//# sourceMappingURL=index.cjs.map
|