@harperfast/harper 5.2.0-beta.4 → 5.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/bin/backup.ts +169 -0
- package/bin/cliOperations.ts +92 -73
- package/bin/copyDb.ts +21 -4
- package/bin/harper.ts +43 -55
- package/bin/help.ts +216 -0
- package/components/Application.ts +236 -46
- package/components/ApplicationScope.ts +26 -0
- package/components/EntryHandler.ts +410 -105
- package/components/RuntimeModuleTracker.ts +189 -0
- package/components/Scope.ts +120 -30
- package/components/componentLoader.ts +177 -25
- package/components/deployLifecycle.ts +119 -33
- package/components/mcp/toolRegistry.ts +10 -0
- package/components/mcp/tools/application.ts +12 -5
- package/components/mcp/tools/operations.ts +9 -0
- package/components/mcp/tools/schemas/operationDescriptions.ts +3 -0
- package/components/mcp/tools/schemas/operations.ts +9 -0
- package/components/operations.js +5 -6
- package/components/operationsValidation.js +32 -2
- package/components/scopeMount.ts +150 -0
- package/config/configUtils.ts +12 -9
- package/config-root.schema.json +14 -0
- package/dataLayer/backupManifest.ts +102 -0
- package/dataLayer/blobBackup.ts +286 -0
- package/dataLayer/harperBridge/ResourceBridge.ts +69 -5
- package/dataLayer/hdbInfoController.ts +8 -0
- package/dataLayer/restoreMarker.ts +276 -0
- package/dataLayer/rocksdbBackup.ts +1100 -0
- package/dataLayer/schemaDescribe.ts +2 -1
- package/dist/bin/backup.d.ts +9 -0
- package/dist/bin/backup.js +192 -0
- package/dist/bin/backup.js.map +1 -0
- package/dist/bin/cliOperations.d.ts +13 -0
- package/dist/bin/cliOperations.js +89 -70
- package/dist/bin/cliOperations.js.map +1 -1
- package/dist/bin/copyDb.js +13 -2
- package/dist/bin/copyDb.js.map +1 -1
- package/dist/bin/harper.d.ts +13 -0
- package/dist/bin/harper.js +45 -56
- package/dist/bin/harper.js.map +1 -1
- package/dist/bin/help.d.ts +8 -0
- package/dist/bin/help.js +192 -0
- package/dist/bin/help.js.map +1 -0
- package/dist/components/Application.d.ts +16 -1
- package/dist/components/Application.js +210 -38
- package/dist/components/Application.js.map +1 -1
- package/dist/components/ApplicationScope.d.ts +7 -0
- package/dist/components/ApplicationScope.js +22 -0
- package/dist/components/ApplicationScope.js.map +1 -1
- package/dist/components/EntryHandler.d.ts +4 -4
- package/dist/components/EntryHandler.js +386 -95
- package/dist/components/EntryHandler.js.map +1 -1
- package/dist/components/RuntimeModuleTracker.d.ts +11 -0
- package/dist/components/RuntimeModuleTracker.js +189 -0
- package/dist/components/RuntimeModuleTracker.js.map +1 -0
- package/dist/components/Scope.d.ts +38 -1
- package/dist/components/Scope.js +117 -28
- package/dist/components/Scope.js.map +1 -1
- package/dist/components/componentLoader.d.ts +2 -6
- package/dist/components/componentLoader.js +160 -18
- package/dist/components/componentLoader.js.map +1 -1
- package/dist/components/deployLifecycle.d.ts +6 -2
- package/dist/components/deployLifecycle.js +109 -31
- package/dist/components/deployLifecycle.js.map +1 -1
- package/dist/components/mcp/toolRegistry.d.ts +7 -0
- package/dist/components/mcp/toolRegistry.js +10 -0
- package/dist/components/mcp/toolRegistry.js.map +1 -1
- package/dist/components/mcp/tools/application.js +11 -5
- package/dist/components/mcp/tools/application.js.map +1 -1
- package/dist/components/mcp/tools/operations.js +9 -0
- package/dist/components/mcp/tools/operations.js.map +1 -1
- package/dist/components/mcp/tools/schemas/operationDescriptions.js +2 -0
- package/dist/components/mcp/tools/schemas/operationDescriptions.js.map +1 -1
- package/dist/components/mcp/tools/schemas/operations.js +9 -0
- package/dist/components/mcp/tools/schemas/operations.js.map +1 -1
- package/dist/components/operations.js +6 -6
- package/dist/components/operations.js.map +1 -1
- package/dist/components/operationsValidation.js +34 -2
- package/dist/components/operationsValidation.js.map +1 -1
- package/dist/components/scopeMount.d.ts +86 -0
- package/dist/components/scopeMount.js +131 -0
- package/dist/components/scopeMount.js.map +1 -0
- package/dist/config/configUtils.js +13 -9
- package/dist/config/configUtils.js.map +1 -1
- package/dist/dataLayer/backupManifest.d.ts +26 -0
- package/dist/dataLayer/backupManifest.js +97 -0
- package/dist/dataLayer/backupManifest.js.map +1 -0
- package/dist/dataLayer/blobBackup.d.ts +87 -0
- package/dist/dataLayer/blobBackup.js +282 -0
- package/dist/dataLayer/blobBackup.js.map +1 -0
- package/dist/dataLayer/harperBridge/ResourceBridge.d.ts +3 -0
- package/dist/dataLayer/harperBridge/ResourceBridge.js +45 -5
- package/dist/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
- package/dist/dataLayer/hdbInfoController.js +4 -0
- package/dist/dataLayer/hdbInfoController.js.map +1 -1
- package/dist/dataLayer/restoreMarker.d.ts +122 -0
- package/dist/dataLayer/restoreMarker.js +261 -0
- package/dist/dataLayer/restoreMarker.js.map +1 -0
- package/dist/dataLayer/rocksdbBackup.d.ts +127 -0
- package/dist/dataLayer/rocksdbBackup.js +1039 -0
- package/dist/dataLayer/rocksdbBackup.js.map +1 -0
- package/dist/dataLayer/schemaDescribe.js +2 -1
- package/dist/dataLayer/schemaDescribe.js.map +1 -1
- package/dist/resources/DatabaseTransaction.d.ts +55 -0
- package/dist/resources/DatabaseTransaction.js +282 -109
- package/dist/resources/DatabaseTransaction.js.map +1 -1
- package/dist/resources/ResourceInterface.d.ts +8 -5
- package/dist/resources/ResourceInterface.js.map +1 -1
- package/dist/resources/Resources.js +22 -4
- package/dist/resources/Resources.js.map +1 -1
- package/dist/resources/Table.d.ts +6 -5
- package/dist/resources/Table.js +114 -37
- package/dist/resources/Table.js.map +1 -1
- package/dist/resources/analytics/write.js +6 -6
- package/dist/resources/analytics/write.js.map +1 -1
- package/dist/resources/blob.d.ts +8 -1
- package/dist/resources/blob.js +31 -14
- package/dist/resources/blob.js.map +1 -1
- package/dist/resources/databases.d.ts +59 -1
- package/dist/resources/databases.js +386 -41
- package/dist/resources/databases.js.map +1 -1
- package/dist/resources/jsResource.d.ts +4 -26
- package/dist/resources/jsResource.js +5 -59
- package/dist/resources/jsResource.js.map +1 -1
- package/dist/resources/models/Models.d.ts +11 -1
- package/dist/resources/models/Models.js +10 -1
- package/dist/resources/models/Models.js.map +1 -1
- package/dist/resources/models/backendRegistry.d.ts +9 -0
- package/dist/resources/models/backendRegistry.js +10 -0
- package/dist/resources/models/backendRegistry.js.map +1 -1
- package/dist/resources/models/openaiStream.d.ts +16 -1
- package/dist/resources/models/openaiStream.js +113 -21
- package/dist/resources/models/openaiStream.js.map +1 -1
- package/dist/resources/models/v1/chatCompletions.d.ts +54 -0
- package/dist/resources/models/v1/chatCompletions.js +115 -0
- package/dist/resources/models/v1/chatCompletions.js.map +1 -0
- package/dist/resources/models/v1/embeddings.d.ts +11 -0
- package/dist/resources/models/v1/embeddings.js +71 -0
- package/dist/resources/models/v1/embeddings.js.map +1 -0
- package/dist/resources/models/v1/errors.d.ts +54 -0
- package/dist/resources/models/v1/errors.js +130 -0
- package/dist/resources/models/v1/errors.js.map +1 -0
- package/dist/resources/models/v1/index.d.ts +36 -0
- package/dist/resources/models/v1/index.js +75 -0
- package/dist/resources/models/v1/index.js.map +1 -0
- package/dist/resources/models/v1/models.d.ts +26 -0
- package/dist/resources/models/v1/models.js +44 -0
- package/dist/resources/models/v1/models.js.map +1 -0
- package/dist/resources/models/v1/translation.d.ts +133 -0
- package/dist/resources/models/v1/translation.js +298 -0
- package/dist/resources/models/v1/translation.js.map +1 -0
- package/dist/resources/roles.d.ts +1 -1
- package/dist/resources/roles.js +54 -7
- package/dist/resources/roles.js.map +1 -1
- package/dist/resources/transaction.js +0 -3
- package/dist/resources/transaction.js.map +1 -1
- package/dist/security/jsLoader.js +84 -33
- package/dist/security/jsLoader.js.map +1 -1
- package/dist/security/role.js +4 -0
- package/dist/security/role.js.map +1 -1
- package/dist/security/superUserGuard.d.ts +7 -0
- package/dist/security/superUserGuard.js +23 -0
- package/dist/security/superUserGuard.js.map +1 -0
- package/dist/security/tokenAuthentication.d.ts +0 -1
- package/dist/security/tokenAuthentication.js +6 -2
- package/dist/security/tokenAuthentication.js.map +1 -1
- package/dist/security/user.d.ts +6 -1
- package/dist/security/user.js +23 -1
- package/dist/security/user.js.map +1 -1
- package/dist/server/REST.js +25 -9
- package/dist/server/REST.js.map +1 -1
- package/dist/server/fastifyRoutes.js +15 -1
- package/dist/server/fastifyRoutes.js.map +1 -1
- package/dist/server/http.d.ts +23 -2
- package/dist/server/http.js +99 -12
- package/dist/server/http.js.map +1 -1
- package/dist/server/itc/serverHandlers.js +7 -1
- package/dist/server/itc/serverHandlers.js.map +1 -1
- package/dist/server/jobs/jobProcess.js +20 -1
- package/dist/server/jobs/jobProcess.js.map +1 -1
- package/dist/server/jobs/jobRunner.js +10 -0
- package/dist/server/jobs/jobRunner.js.map +1 -1
- package/dist/server/jobs/jobs.js +11 -0
- package/dist/server/jobs/jobs.js.map +1 -1
- package/dist/server/middlewareChain.d.ts +10 -1
- package/dist/server/middlewareChain.js +81 -21
- package/dist/server/middlewareChain.js.map +1 -1
- package/dist/server/operationsServer.d.ts +0 -2
- package/dist/server/operationsServer.js.map +1 -1
- package/dist/server/serverHelpers/multipartParser.js +9 -0
- package/dist/server/serverHelpers/multipartParser.js.map +1 -1
- package/dist/server/serverHelpers/operationAuthorizationState.d.ts +2 -0
- package/dist/server/serverHelpers/operationAuthorizationState.js +13 -0
- package/dist/server/serverHelpers/operationAuthorizationState.js.map +1 -0
- package/dist/server/serverHelpers/registeredOperations.d.ts +3 -2
- package/dist/server/serverHelpers/registeredOperations.js +14 -13
- package/dist/server/serverHelpers/registeredOperations.js.map +1 -1
- package/dist/server/serverHelpers/serverHandlers.js +27 -7
- package/dist/server/serverHelpers/serverHandlers.js.map +1 -1
- package/dist/server/serverHelpers/serverUtilities.d.ts +1 -1
- package/dist/server/serverHelpers/serverUtilities.js +21 -7
- package/dist/server/serverHelpers/serverUtilities.js.map +1 -1
- package/dist/server/static.js +68 -21
- package/dist/server/static.js.map +1 -1
- package/dist/server/storageReclamation.d.ts +17 -0
- package/dist/server/storageReclamation.js +90 -6
- package/dist/server/storageReclamation.js.map +1 -1
- package/dist/server/threads/socketRouter.js +20 -0
- package/dist/server/threads/socketRouter.js.map +1 -1
- package/dist/server/threads/threadServer.js +12 -0
- package/dist/server/threads/threadServer.js.map +1 -1
- package/dist/sqlEngine/diff/differential.js +7 -3
- package/dist/sqlEngine/diff/differential.js.map +1 -1
- package/dist/sqlTranslator/index.js +6 -1
- package/dist/sqlTranslator/index.js.map +1 -1
- package/dist/upgrade/upgradePrompt.d.ts +2 -2
- package/dist/upgrade/upgradePrompt.js +22 -3
- package/dist/upgrade/upgradePrompt.js.map +1 -1
- package/dist/utility/OperationFunctionCaller.js +25 -6
- package/dist/utility/OperationFunctionCaller.js.map +1 -1
- package/dist/utility/errors/commonErrors.d.ts +1 -0
- package/dist/utility/errors/commonErrors.js +1 -0
- package/dist/utility/errors/commonErrors.js.map +1 -1
- package/dist/utility/hdbTerms.d.ts +13 -1
- package/dist/utility/hdbTerms.js +13 -1
- package/dist/utility/hdbTerms.js.map +1 -1
- package/dist/utility/install/installer.js +32 -0
- package/dist/utility/install/installer.js.map +1 -1
- package/dist/utility/logging/harper_logger.d.ts +47 -0
- package/dist/utility/logging/harper_logger.js +803 -38
- package/dist/utility/logging/harper_logger.js.map +1 -1
- package/dist/utility/operation_authorization.js +13 -3
- package/dist/utility/operation_authorization.js.map +1 -1
- package/npm-shrinkwrap.json +198 -193
- package/package.json +12 -7
- package/resources/DESIGN.md +2 -0
- package/resources/DatabaseTransaction.ts +310 -104
- package/resources/ResourceInterface.ts +8 -5
- package/resources/Resources.ts +22 -4
- package/resources/Table.ts +341 -263
- package/resources/analytics/write.ts +22 -20
- package/resources/blob.ts +31 -14
- package/resources/databases.ts +387 -46
- package/resources/jsResource.ts +5 -62
- package/resources/models/Models.ts +14 -1
- package/resources/models/backendRegistry.ts +10 -0
- package/resources/models/openaiStream.ts +131 -19
- package/resources/models/v1/chatCompletions.ts +128 -0
- package/resources/models/v1/embeddings.ts +70 -0
- package/resources/models/v1/errors.ts +141 -0
- package/resources/models/v1/index.ts +72 -0
- package/resources/models/v1/models.ts +53 -0
- package/resources/models/v1/translation.ts +362 -0
- package/resources/roles.ts +67 -7
- package/resources/transaction.ts +0 -3
- package/security/jsLoader.ts +84 -30
- package/security/role.ts +7 -0
- package/security/superUserGuard.ts +20 -0
- package/security/tokenAuthentication.ts +6 -3
- package/security/user.ts +26 -1
- package/server/DESIGN.md +61 -34
- package/server/REST.ts +25 -9
- package/server/fastifyRoutes.ts +20 -1
- package/server/http.ts +100 -13
- package/server/itc/serverHandlers.js +7 -1
- package/server/jobs/jobProcess.ts +18 -1
- package/server/jobs/jobRunner.ts +10 -0
- package/server/jobs/jobs.ts +11 -0
- package/server/middlewareChain.ts +79 -20
- package/server/operationsServer.ts +0 -2
- package/server/serverHelpers/multipartParser.ts +9 -0
- package/server/serverHelpers/operationAuthorizationState.ts +11 -0
- package/server/serverHelpers/registeredOperations.ts +19 -15
- package/server/serverHelpers/serverHandlers.js +28 -7
- package/server/serverHelpers/serverUtilities.ts +29 -7
- package/server/static.ts +87 -23
- package/server/storageReclamation.ts +104 -8
- package/server/threads/socketRouter.ts +20 -0
- package/server/threads/threadServer.js +11 -0
- package/sqlTranslator/index.ts +6 -1
- package/static/defaultConfig.yaml +3 -0
- package/studio/web/assets/{Chat-DK3GlWEb.js → Chat-aApwhRmz.js} +2 -2
- package/studio/web/assets/{Chat-DK3GlWEb.js.map → Chat-aApwhRmz.js.map} +1 -1
- package/studio/web/assets/{FloatingChat-fBcC1Ew_.js → FloatingChat-sC0H91n9.js} +4 -4
- package/studio/web/assets/{FloatingChat-fBcC1Ew_.js.map → FloatingChat-sC0H91n9.js.map} +1 -1
- package/studio/web/assets/{apiToken-DJo1nakA.js → apiToken-DZ8JhHOI.js} +2 -2
- package/studio/web/assets/{apiToken-DJo1nakA.js.map → apiToken-DZ8JhHOI.js.map} +1 -1
- package/studio/web/assets/{applications-BDfH8urd.js → applications-9SEVLIO5.js} +2 -2
- package/studio/web/assets/{applications-BDfH8urd.js.map → applications-9SEVLIO5.js.map} +1 -1
- package/studio/web/assets/{index-BHo3c2Gk.js → index-Dy3uDGXb.js} +6 -6
- package/studio/web/assets/index-Dy3uDGXb.js.map +1 -0
- package/studio/web/assets/{index.lazy-BTo0y6UM.js → index.lazy-CN1zq4I4.js} +4 -4
- package/studio/web/assets/{index.lazy-BTo0y6UM.js.map → index.lazy-CN1zq4I4.js.map} +1 -1
- package/studio/web/assets/{notifications-CMxvWNnz.js → notifications-BFAF07xr.js} +2 -2
- package/studio/web/assets/{notifications-CMxvWNnz.js.map → notifications-BFAF07xr.js.map} +1 -1
- package/studio/web/assets/{notifications-D3GoB26g.js → notifications-CKlYVvVN.js} +2 -2
- package/studio/web/assets/{notifications-D3GoB26g.js.map → notifications-CKlYVvVN.js.map} +1 -1
- package/studio/web/assets/{profile-Doj5FVDE.js → profile-A1zhEdFG.js} +2 -2
- package/studio/web/assets/{profile-Doj5FVDE.js.map → profile-A1zhEdFG.js.map} +1 -1
- package/studio/web/assets/{setComponentFile-yinsqJy0.js → setComponentFile-SEtBt_GV.js} +2 -2
- package/studio/web/assets/{setComponentFile-yinsqJy0.js.map → setComponentFile-SEtBt_GV.js.map} +1 -1
- package/studio/web/assets/{setup-DJwR0BHd.js → setup-BisINqdH.js} +2 -2
- package/studio/web/assets/{setup-DJwR0BHd.js.map → setup-BisINqdH.js.map} +1 -1
- package/studio/web/assets/{status-Br_AbsJs.js → status-BuQoCc7l.js} +2 -2
- package/studio/web/assets/{status-Br_AbsJs.js.map → status-BuQoCc7l.js.map} +1 -1
- package/studio/web/assets/{swagger-ui-react-02XH5sVf.js → swagger-ui-react-CAi_s1PC.js} +2 -2
- package/studio/web/assets/{swagger-ui-react-02XH5sVf.js.map → swagger-ui-react-CAi_s1PC.js.map} +1 -1
- package/studio/web/assets/{tsMode-D1DMKY7h.js → tsMode-DT74tlkM.js} +2 -2
- package/studio/web/assets/{tsMode-D1DMKY7h.js.map → tsMode-DT74tlkM.js.map} +1 -1
- package/studio/web/assets/{useEntityRestURL-DtRblRgw.js → useEntityRestURL-CGRGc1n7.js} +2 -2
- package/studio/web/assets/{useEntityRestURL-DtRblRgw.js.map → useEntityRestURL-CGRGc1n7.js.map} +1 -1
- package/studio/web/index.html +1 -1
- package/upgrade/upgradePrompt.ts +22 -3
- package/utility/OperationFunctionCaller.ts +24 -3
- package/utility/errors/commonErrors.ts +2 -0
- package/utility/hdbTerms.ts +13 -1
- package/utility/install/installer.ts +37 -0
- package/utility/logging/harper_logger.ts +786 -41
- package/utility/operation_authorization.ts +31 -3
- package/studio/web/assets/index-BHo3c2Gk.js.map +0 -1
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OpenAI error envelope helpers for the `/v1/*` gateway (#631).
|
|
4
|
+
*
|
|
5
|
+
* Harper's REST layer serialises uncaught errors as RFC 9457 Problem Details.
|
|
6
|
+
* Resources that need the OpenAI `{ error: { message, type, code, param } }`
|
|
7
|
+
* shape must catch errors themselves and call `toOpenAIError()` / `badRequest()`.
|
|
8
|
+
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.toOpenAIError = toOpenAIError;
|
|
14
|
+
exports.badRequest = badRequest;
|
|
15
|
+
exports.authorizeV1Request = authorizeV1Request;
|
|
16
|
+
const backendRegistry_ts_1 = require("../backendRegistry.js");
|
|
17
|
+
const Models_ts_1 = require("../Models.js");
|
|
18
|
+
const harper_logger_ts_1 = __importDefault(require("../../../utility/logging/harper_logger.js"));
|
|
19
|
+
/**
|
|
20
|
+
* Map any thrown value to an OpenAI error envelope. Uses `statusCode` when
|
|
21
|
+
* present (Harper's `ClientError` / `ServerError` convention). Falls back to
|
|
22
|
+
* `500 server_error`. `ModelBackendNotFoundError` maps to `404 model_not_found`.
|
|
23
|
+
*/
|
|
24
|
+
function toOpenAIError(err) {
|
|
25
|
+
let status = 500;
|
|
26
|
+
let type = 'server_error';
|
|
27
|
+
let code = null;
|
|
28
|
+
if (err instanceof backendRegistry_ts_1.ModelBackendNotFoundError) {
|
|
29
|
+
status = 404;
|
|
30
|
+
type = 'invalid_request_error';
|
|
31
|
+
code = 'model_not_found';
|
|
32
|
+
}
|
|
33
|
+
else if (err instanceof Models_ts_1.ModelCapabilityError) {
|
|
34
|
+
// Caller-driven mismatch (e.g. `tools` or streaming against a backend that
|
|
35
|
+
// doesn't support it): the request is what's wrong, not the server. It extends
|
|
36
|
+
// ServerError (statusCode 500), so this must precede the statusCode branch —
|
|
37
|
+
// falling through would report a generic sanitized 500 for a client-actionable
|
|
38
|
+
// condition. The message is safe to pass through: it names only the backend and
|
|
39
|
+
// the capability the caller asked for.
|
|
40
|
+
status = 400;
|
|
41
|
+
type = 'invalid_request_error';
|
|
42
|
+
code = 'capability_unsupported';
|
|
43
|
+
}
|
|
44
|
+
else if (err instanceof Error && typeof err.statusCode === 'number') {
|
|
45
|
+
status = err.statusCode;
|
|
46
|
+
if (status === 401) {
|
|
47
|
+
type = 'authentication_error';
|
|
48
|
+
}
|
|
49
|
+
else if (status === 403) {
|
|
50
|
+
// OpenAI semantics: 401 = bad/missing credentials, 403 = valid credentials
|
|
51
|
+
// lacking permission (matches authorizeV1Request's own 403 envelope).
|
|
52
|
+
type = 'permission_error';
|
|
53
|
+
}
|
|
54
|
+
else if (status < 500) {
|
|
55
|
+
type = 'invalid_request_error';
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
type = 'server_error';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// 5xx messages stay generic: internal error strings (backend stack details, file
|
|
62
|
+
// paths) don't belong in a wire response. The real error goes to the log. 4xx
|
|
63
|
+
// messages are client-actionable and pass through.
|
|
64
|
+
let message;
|
|
65
|
+
if (status >= 500) {
|
|
66
|
+
harper_logger_ts_1.default.error('v1 gateway error', err);
|
|
67
|
+
message = 'Internal server error';
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
message = err instanceof Error ? err.message : 'Bad request';
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
status,
|
|
74
|
+
headers: { 'Content-Type': 'application/json' },
|
|
75
|
+
data: { error: { message, type, code, param: null } },
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/** Convenience for early request-body validation failures. */
|
|
79
|
+
function badRequest(message) {
|
|
80
|
+
return {
|
|
81
|
+
status: 400,
|
|
82
|
+
headers: { 'Content-Type': 'application/json' },
|
|
83
|
+
data: { error: { message, type: 'invalid_request_error', code: null, param: null } },
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Gate for the `/v1/*` handlers, since overriding the static `get`/`post` methods
|
|
88
|
+
* bypasses Resource's `transactional()` wrapper and its default `allowRead`/`allowCreate`
|
|
89
|
+
* checks (Resource.ts:685-733, 426-435) never run for these endpoints.
|
|
90
|
+
*
|
|
91
|
+
* Mirrors Resource's default gate (super_user-only) rather than introducing a new
|
|
92
|
+
* permission — see PR discussion for whether a dedicated `/v1/*` permission should
|
|
93
|
+
* replace this later.
|
|
94
|
+
*
|
|
95
|
+
* Returns an OpenAI-shape error response when access should be denied, or `null`
|
|
96
|
+
* when the request may proceed.
|
|
97
|
+
*/
|
|
98
|
+
function authorizeV1Request(request) {
|
|
99
|
+
const user = request?.user;
|
|
100
|
+
if (!user) {
|
|
101
|
+
return {
|
|
102
|
+
status: 401,
|
|
103
|
+
headers: { 'Content-Type': 'application/json' },
|
|
104
|
+
data: {
|
|
105
|
+
error: {
|
|
106
|
+
message: 'You must provide valid credentials to access this endpoint.',
|
|
107
|
+
type: 'authentication_error',
|
|
108
|
+
code: null,
|
|
109
|
+
param: null,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
if (!user.role?.permission?.super_user) {
|
|
115
|
+
return {
|
|
116
|
+
status: 403,
|
|
117
|
+
headers: { 'Content-Type': 'application/json' },
|
|
118
|
+
data: {
|
|
119
|
+
error: {
|
|
120
|
+
message: 'You do not have permission to access this endpoint.',
|
|
121
|
+
type: 'permission_error',
|
|
122
|
+
code: null,
|
|
123
|
+
param: null,
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../../resources/models/v1/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/v1/*` OpenAI-compatible gateway (#631).
|
|
3
|
+
*
|
|
4
|
+
* Registers three REST resources on the REST port:
|
|
5
|
+
* POST /v1/embeddings → V1Embeddings
|
|
6
|
+
* POST /v1/chat/completions → V1ChatCompletions
|
|
7
|
+
* GET /v1/models → V1Models
|
|
8
|
+
*
|
|
9
|
+
* Off by default, and `defaultConfig.yaml` deliberately ships no `modelsGateway`
|
|
10
|
+
* block: with the key absent the root loader skips the component before resolving
|
|
11
|
+
* it, so none of this module graph is imported on an instance that does not use
|
|
12
|
+
* the gateway. Opt in by adding the block to `harperdb-config.yaml` with
|
|
13
|
+
* `enabled: true`, or via `set_configuration` (`modelsGateway_enabled`).
|
|
14
|
+
* `enabled: false` is honored too, for an instance that wants the block present
|
|
15
|
+
* but inert — that costs the import, which is why it is not the shipped default.
|
|
16
|
+
*
|
|
17
|
+
* Example (opt in). `rest` is required: these are REST-served resources and the
|
|
18
|
+
* gateway deliberately does not force REST to start (see `handleApplication`).
|
|
19
|
+
* Without it the resources register but every `/v1/*` path 404s.
|
|
20
|
+
*
|
|
21
|
+
* ```yaml
|
|
22
|
+
* rest: true
|
|
23
|
+
* modelsGateway:
|
|
24
|
+
* enabled: true
|
|
25
|
+
* models:
|
|
26
|
+
* generative:
|
|
27
|
+
* default:
|
|
28
|
+
* backend: ollama
|
|
29
|
+
* model: llama3.2
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* All three endpoints require `super_user` permission. Anonymous or
|
|
33
|
+
* insufficient-privilege requests receive a well-formed OpenAI error envelope.
|
|
34
|
+
*/
|
|
35
|
+
import type { Scope } from '../../../components/Scope.ts';
|
|
36
|
+
export declare function handleApplication(scope: Scope): void;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `/v1/*` OpenAI-compatible gateway (#631).
|
|
4
|
+
*
|
|
5
|
+
* Registers three REST resources on the REST port:
|
|
6
|
+
* POST /v1/embeddings → V1Embeddings
|
|
7
|
+
* POST /v1/chat/completions → V1ChatCompletions
|
|
8
|
+
* GET /v1/models → V1Models
|
|
9
|
+
*
|
|
10
|
+
* Off by default, and `defaultConfig.yaml` deliberately ships no `modelsGateway`
|
|
11
|
+
* block: with the key absent the root loader skips the component before resolving
|
|
12
|
+
* it, so none of this module graph is imported on an instance that does not use
|
|
13
|
+
* the gateway. Opt in by adding the block to `harperdb-config.yaml` with
|
|
14
|
+
* `enabled: true`, or via `set_configuration` (`modelsGateway_enabled`).
|
|
15
|
+
* `enabled: false` is honored too, for an instance that wants the block present
|
|
16
|
+
* but inert — that costs the import, which is why it is not the shipped default.
|
|
17
|
+
*
|
|
18
|
+
* Example (opt in). `rest` is required: these are REST-served resources and the
|
|
19
|
+
* gateway deliberately does not force REST to start (see `handleApplication`).
|
|
20
|
+
* Without it the resources register but every `/v1/*` path 404s.
|
|
21
|
+
*
|
|
22
|
+
* ```yaml
|
|
23
|
+
* rest: true
|
|
24
|
+
* modelsGateway:
|
|
25
|
+
* enabled: true
|
|
26
|
+
* models:
|
|
27
|
+
* generative:
|
|
28
|
+
* default:
|
|
29
|
+
* backend: ollama
|
|
30
|
+
* model: llama3.2
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* All three endpoints require `super_user` permission. Anonymous or
|
|
34
|
+
* insufficient-privilege requests receive a well-formed OpenAI error envelope.
|
|
35
|
+
*/
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.handleApplication = handleApplication;
|
|
41
|
+
const harper_logger_ts_1 = __importDefault(require("../../../utility/logging/harper_logger.js"));
|
|
42
|
+
const configUtils_ts_1 = require("../../../config/configUtils.js");
|
|
43
|
+
const embeddings_ts_1 = require("./embeddings.js");
|
|
44
|
+
const chatCompletions_ts_1 = require("./chatCompletions.js");
|
|
45
|
+
const models_ts_1 = require("./models.js");
|
|
46
|
+
function handleApplication(scope) {
|
|
47
|
+
if (!scope.options.get(['enabled']))
|
|
48
|
+
return;
|
|
49
|
+
// These resources are served by REST's middleware chain, so the instance must also
|
|
50
|
+
// have a `rest`/`REST` config section — the gateway deliberately does NOT force REST
|
|
51
|
+
// to start. Doing so requires reaching into REST's module state before application
|
|
52
|
+
// configs have loaded, which silently discards an app's own `rest` options (webSocket,
|
|
53
|
+
// urlPath/host, middleware ordering). Core has no supported way yet for a component to
|
|
54
|
+
// declare "I serve REST resources"; that gap is tracked separately.
|
|
55
|
+
//
|
|
56
|
+
// Warn rather than fail: an app loaded later may still declare `rest`, so absence here
|
|
57
|
+
// is not conclusive. But defaultConfig ships no `rest` section, so enabling the gateway
|
|
58
|
+
// alone yields three registered resources and a 404 on every /v1 path — worth a line in
|
|
59
|
+
// the log instead of silence.
|
|
60
|
+
const rootConfig = (0, configUtils_ts_1.getConfigObj)();
|
|
61
|
+
if (rootConfig && !rootConfig.rest && !rootConfig.REST) {
|
|
62
|
+
harper_logger_ts_1.default.warn('modelsGateway is enabled but no `rest` section is configured; /v1/* endpoints are only served when REST is active');
|
|
63
|
+
}
|
|
64
|
+
// Explicit protocol visibility: these are REST-only wire-protocol endpoints. Without a
|
|
65
|
+
// policy, the shared registry matches them for every protocol lookup — WS dispatch could
|
|
66
|
+
// reach V1ChatCompletions.connect() and then fail iterating its non-iterable badRequest
|
|
67
|
+
// envelope, and they would surface through MQTT/GraphQL/MCP enumeration too. `sse` stays
|
|
68
|
+
// enabled for chat only: an explicit `Accept: text/event-stream` POST is dispatched via
|
|
69
|
+
// the sse lookup (REST.ts) and is a supported streaming client shape (see connect()).
|
|
70
|
+
const restOnly = { rest: true, sse: false, ws: false, mqtt: false, graphql: false, mcp: false };
|
|
71
|
+
scope.resources.set('v1/models', models_ts_1.V1Models, restOnly);
|
|
72
|
+
scope.resources.set('v1/embeddings', embeddings_ts_1.V1Embeddings, restOnly);
|
|
73
|
+
scope.resources.set('v1/chat/completions', chatCompletions_ts_1.V1ChatCompletions, { ...restOnly, sse: true });
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../resources/models/v1/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;;;;;AASH,8CA6BC;AAnCD,iGAAqE;AACrE,mEAA8D;AAC9D,mDAA+C;AAC/C,6DAAyD;AACzD,2CAAuC;AAEvC,SAAgB,iBAAiB,CAAC,KAAY;IAC7C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QAAE,OAAO;IAC5C,mFAAmF;IACnF,qFAAqF;IACrF,mFAAmF;IACnF,uFAAuF;IACvF,uFAAuF;IACvF,oEAAoE;IACpE,EAAE;IACF,uFAAuF;IACvF,wFAAwF;IACxF,wFAAwF;IACxF,8BAA8B;IAC9B,MAAM,UAAU,GAAG,IAAA,6BAAY,GAAyC,CAAC;IACzE,IAAI,UAAU,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QACxD,0BAAY,CAAC,IAAI,CAChB,mHAAmH,CACnH,CAAC;IACH,CAAC;IACD,uFAAuF;IACvF,yFAAyF;IACzF,wFAAwF;IACxF,yFAAyF;IACzF,wFAAwF;IACxF,sFAAsF;IACtF,MAAM,QAAQ,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IAChG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,oBAAQ,EAAE,QAAQ,CAAC,CAAC;IACrD,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,eAAe,EAAE,4BAAY,EAAE,QAAQ,CAAC,CAAC;IAC7D,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,qBAAqB,EAAE,sCAAiB,EAAE,EAAE,GAAG,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3F,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `GET /v1/models` — OpenAI-compatible model list endpoint (#631).
|
|
3
|
+
*
|
|
4
|
+
* Enumerates all registered embedding and generative backends from the
|
|
5
|
+
* process-wide `backendRegistry`. The response mirrors the OpenAI shape:
|
|
6
|
+
* `{ object: 'list', data: [{ id, object: 'model', created, owned_by }] }`.
|
|
7
|
+
*
|
|
8
|
+
* `logicalName` (not `backend.name`) is the `id` — it's what callers pass as
|
|
9
|
+
* `model` in subsequent requests.
|
|
10
|
+
*/
|
|
11
|
+
import { Resource } from '../../Resource.ts';
|
|
12
|
+
import { type OpenAIErrorResponse } from './errors.ts';
|
|
13
|
+
export interface OAIModelEntry {
|
|
14
|
+
id: string;
|
|
15
|
+
object: 'model';
|
|
16
|
+
created: number;
|
|
17
|
+
owned_by: string;
|
|
18
|
+
}
|
|
19
|
+
export interface OAIModelList {
|
|
20
|
+
object: 'list';
|
|
21
|
+
data: OAIModelEntry[];
|
|
22
|
+
}
|
|
23
|
+
export declare class V1Models extends Resource {
|
|
24
|
+
static reservedPath: boolean;
|
|
25
|
+
static get(_target: unknown, request: unknown): OAIModelList | OpenAIErrorResponse;
|
|
26
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `GET /v1/models` — OpenAI-compatible model list endpoint (#631).
|
|
4
|
+
*
|
|
5
|
+
* Enumerates all registered embedding and generative backends from the
|
|
6
|
+
* process-wide `backendRegistry`. The response mirrors the OpenAI shape:
|
|
7
|
+
* `{ object: 'list', data: [{ id, object: 'model', created, owned_by }] }`.
|
|
8
|
+
*
|
|
9
|
+
* `logicalName` (not `backend.name`) is the `id` — it's what callers pass as
|
|
10
|
+
* `model` in subsequent requests.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.V1Models = void 0;
|
|
14
|
+
const Resource_ts_1 = require("../../Resource.js");
|
|
15
|
+
const backendRegistry_ts_1 = require("../backendRegistry.js");
|
|
16
|
+
const errors_ts_1 = require("./errors.js");
|
|
17
|
+
// @ts-ignore — Resource base class is not typed for static dispatch; pattern mirrors login.ts
|
|
18
|
+
class V1Models extends Resource_ts_1.Resource {
|
|
19
|
+
// Reserve this fixed route: a later app registration at the same path becomes a
|
|
20
|
+
// loud conflict (ErrorResource) instead of silently replacing the gateway and its
|
|
21
|
+
// super_user gate. See Resources.set.
|
|
22
|
+
static reservedPath = true;
|
|
23
|
+
static get(_target, request) {
|
|
24
|
+
const authError = (0, errors_ts_1.authorizeV1Request)(request);
|
|
25
|
+
if (authError)
|
|
26
|
+
return authError;
|
|
27
|
+
const created = Math.floor(Date.now() / 1000);
|
|
28
|
+
// OpenAI model ids are unique; a logical name registered for both generative and
|
|
29
|
+
// embedding (e.g. `default` in each section) is one model id to callers.
|
|
30
|
+
const ids = new Set();
|
|
31
|
+
const data = [];
|
|
32
|
+
for (const kind of ['generative', 'embedding']) {
|
|
33
|
+
for (const { logicalName } of (0, backendRegistry_ts_1.listBackends)(kind)) {
|
|
34
|
+
if (ids.has(logicalName))
|
|
35
|
+
continue;
|
|
36
|
+
ids.add(logicalName);
|
|
37
|
+
data.push({ id: logicalName, object: 'model', created, owned_by: 'harper' });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return { object: 'list', data };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.V1Models = V1Models;
|
|
44
|
+
//# sourceMappingURL=models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.js","sourceRoot":"","sources":["../../../../resources/models/v1/models.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAEH,mDAA6C;AAC7C,8DAAqD;AACrD,2CAA2E;AAc3E,8FAA8F;AAC9F,MAAa,QAAS,SAAQ,sBAAQ;IACrC,gFAAgF;IAChF,kFAAkF;IAClF,sCAAsC;IACtC,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC;IAE3B,MAAM,CAAC,GAAG,CAAC,OAAgB,EAAE,OAAgB;QAC5C,MAAM,SAAS,GAAG,IAAA,8BAAkB,EAAC,OAAc,CAAC,CAAC;QACrD,IAAI,SAAS;YAAE,OAAO,SAAS,CAAC;QAEhC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC9C,iFAAiF;QACjF,yEAAyE;QACzE,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;QAC9B,MAAM,IAAI,GAAoB,EAAE,CAAC;QACjC,KAAK,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,WAAW,CAAU,EAAE,CAAC;YACzD,KAAK,MAAM,EAAE,WAAW,EAAE,IAAI,IAAA,iCAAY,EAAC,IAAI,CAAC,EAAE,CAAC;gBAClD,IAAI,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC;oBAAE,SAAS;gBACnC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBACrB,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC9E,CAAC;QACF,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACjC,CAAC;;AAvBF,4BAwBC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI ↔ Harper internal shape mappers for the `/v1/*` gateway (#631).
|
|
3
|
+
*
|
|
4
|
+
* All functions are pure (no I/O, no side-effects) so they can be unit-tested
|
|
5
|
+
* in isolation without a running Harper instance.
|
|
6
|
+
*/
|
|
7
|
+
import type { EmbedOpts, GenerateInput, GenerateOpts, GenerateResult, Message, ToolDef, TokenUsage } from '../types.ts';
|
|
8
|
+
export interface OAIMessageIn {
|
|
9
|
+
role: string;
|
|
10
|
+
/** May be null for assistant messages that only contain tool_calls. */
|
|
11
|
+
content: string | null;
|
|
12
|
+
tool_calls?: Array<{
|
|
13
|
+
id: string;
|
|
14
|
+
type: string;
|
|
15
|
+
function: {
|
|
16
|
+
name: string;
|
|
17
|
+
arguments: string;
|
|
18
|
+
};
|
|
19
|
+
}>;
|
|
20
|
+
/** Present on role === 'tool' messages. */
|
|
21
|
+
tool_call_id?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface OAIToolIn {
|
|
24
|
+
type: 'function';
|
|
25
|
+
function: {
|
|
26
|
+
name: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
parameters?: object;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export interface OAIChatRequest {
|
|
32
|
+
model?: string;
|
|
33
|
+
messages: OAIMessageIn[];
|
|
34
|
+
tools?: OAIToolIn[];
|
|
35
|
+
/** Subset recognised: 'none' | 'auto' | 'required' | {type:'function', function:{name}}. */
|
|
36
|
+
tool_choice?: unknown;
|
|
37
|
+
temperature?: number;
|
|
38
|
+
/** OpenAI v1 field; superseded by max_completion_tokens in v1+. */
|
|
39
|
+
max_tokens?: number;
|
|
40
|
+
/** Preferred alias; takes precedence over max_tokens when both present. */
|
|
41
|
+
max_completion_tokens?: number;
|
|
42
|
+
response_format?: {
|
|
43
|
+
type: string;
|
|
44
|
+
json_schema?: unknown;
|
|
45
|
+
};
|
|
46
|
+
stream?: boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Map an OpenAI `messages` array to Harper `Message[]`.
|
|
50
|
+
* Normalises `tool_calls[].function.arguments` from JSON strings to parsed
|
|
51
|
+
* objects (Harper's internal contract); maps `tool_call_id` to `toolCallId`.
|
|
52
|
+
*/
|
|
53
|
+
export declare function translateMessages(oaiMessages: OAIMessageIn[]): Message[];
|
|
54
|
+
/** Map OpenAI `tools[]` to Harper `ToolDef[]`. */
|
|
55
|
+
export declare function translateTools(oaiTools: OAIToolIn[]): ToolDef[];
|
|
56
|
+
/**
|
|
57
|
+
* Build Harper `GenerateInput` from translated messages and tool definitions.
|
|
58
|
+
* Uses the object form `{ messages, tools }` when tools are present, so that
|
|
59
|
+
* tool definitions travel alongside messages per Harper's type contract.
|
|
60
|
+
*/
|
|
61
|
+
export declare function toGenerateInput(messages: Message[], tools: ToolDef[] | undefined): GenerateInput;
|
|
62
|
+
/**
|
|
63
|
+
* Validate the OpenAI wire shapes this gateway maps, returning a client-facing
|
|
64
|
+
* message for a 400 or `null` when the request is well-formed.
|
|
65
|
+
*
|
|
66
|
+
* Kept separate from the mappers so malformed nested input (`messages: [null]`,
|
|
67
|
+
* `tool_calls: [{}]`, `tools: [{}]`) becomes an OpenAI-shaped 400 instead of a
|
|
68
|
+
* TypeError escaping the handler as an RFC 9457 500.
|
|
69
|
+
*/
|
|
70
|
+
export declare function validateChatRequest(body: OAIChatRequest): string | null;
|
|
71
|
+
/**
|
|
72
|
+
* Map an OpenAI chat-completion request body to `GenerateOpts`.
|
|
73
|
+
*
|
|
74
|
+
* `tool_choice` is honored by the caller, not here: `'none'` omits tools from the
|
|
75
|
+
* generate input entirely, and unrepresentable choices are rejected up front by
|
|
76
|
+
* `validateChatRequest`. Full in-process tool-call orchestration is #612 (out of
|
|
77
|
+
* scope for #631), so tool calls are always returned to the caller to invoke.
|
|
78
|
+
*
|
|
79
|
+
* Assumes `validateChatRequest` has already passed.
|
|
80
|
+
*/
|
|
81
|
+
export declare function toGenerateOpts(body: OAIChatRequest): GenerateOpts;
|
|
82
|
+
/** Map an OpenAI embeddings request body to `EmbedOpts`. */
|
|
83
|
+
export declare function toEmbedOpts(body: {
|
|
84
|
+
model?: string;
|
|
85
|
+
}): EmbedOpts;
|
|
86
|
+
interface OAIToolCallOut {
|
|
87
|
+
id: string;
|
|
88
|
+
type: 'function';
|
|
89
|
+
function: {
|
|
90
|
+
name: string;
|
|
91
|
+
arguments: string;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
interface OAIAssistantMessage {
|
|
95
|
+
role: 'assistant';
|
|
96
|
+
/** null when the message contains only tool_calls. */
|
|
97
|
+
content: string | null;
|
|
98
|
+
tool_calls?: OAIToolCallOut[];
|
|
99
|
+
}
|
|
100
|
+
export interface OAIChatCompletion {
|
|
101
|
+
id: string;
|
|
102
|
+
object: 'chat.completion';
|
|
103
|
+
created: number;
|
|
104
|
+
model: string;
|
|
105
|
+
choices: Array<{
|
|
106
|
+
index: number;
|
|
107
|
+
message: OAIAssistantMessage;
|
|
108
|
+
finish_reason: string;
|
|
109
|
+
}>;
|
|
110
|
+
usage: {
|
|
111
|
+
prompt_tokens: number;
|
|
112
|
+
completion_tokens: number;
|
|
113
|
+
total_tokens: number;
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/** Map a Harper `GenerateResult` to an OpenAI `chat.completion` response object. */
|
|
117
|
+
export declare function toChatCompletion(result: GenerateResult, model: string, id?: string): OAIChatCompletion;
|
|
118
|
+
export interface OAIEmbedResponse {
|
|
119
|
+
object: 'list';
|
|
120
|
+
data: Array<{
|
|
121
|
+
embedding: number[];
|
|
122
|
+
index: number;
|
|
123
|
+
object: 'embedding';
|
|
124
|
+
}>;
|
|
125
|
+
model: string;
|
|
126
|
+
usage: {
|
|
127
|
+
prompt_tokens: number;
|
|
128
|
+
total_tokens: number;
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/** Map `Float32Array[]` from `models.embed()` to an OpenAI embeddings response. */
|
|
132
|
+
export declare function toEmbedResponse(vecs: Float32Array[], model: string, usage?: TokenUsage): OAIEmbedResponse;
|
|
133
|
+
export {};
|