libmodulor 0.3.0 → 0.5.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/CHANGELOG.md +29 -1
- package/README.md +7 -182
- package/dist/esm/app/workers/AppSrcFilePathBuilder.d.ts +16 -0
- package/dist/esm/app/workers/AppSrcFilePathBuilder.js +6 -4
- package/dist/esm/apps/Helper/index.js +1 -0
- package/dist/esm/apps/Helper/src/ucds/GenerateAppsTestsUCD.js +3 -2
- package/dist/esm/bundlers/vite/StripUCDLifecycleServerPlugin.js +3 -0
- package/dist/esm/convention.d.ts +1 -0
- package/dist/esm/convention.js +17 -4
- package/dist/esm/dt/Validation.d.ts +8 -0
- package/dist/esm/dt/Validation.js +8 -0
- package/dist/esm/dt/base/TBase.d.ts +2 -1
- package/dist/esm/dt/base/TBoolean.js +2 -0
- package/dist/esm/dt/base/TInt.js +3 -0
- package/dist/esm/dt/base/TNumber.js +2 -0
- package/dist/esm/dt/base/TObject.d.ts +15 -0
- package/dist/esm/dt/base/TObject.js +14 -0
- package/dist/esm/dt/base/TString.js +1 -1
- package/dist/esm/dt/final/TAmount.js +1 -0
- package/dist/esm/dt/final/TCountryISO3166Alpha2.js +1 -0
- package/dist/esm/dt/final/TCurrencyISO4217.js +1 -0
- package/dist/esm/dt/final/TDateTimeFormat.js +1 -0
- package/dist/esm/dt/final/TEmail.js +2 -0
- package/dist/esm/dt/final/TEmoji.js +4 -0
- package/dist/esm/dt/final/TFile.js +3 -0
- package/dist/esm/dt/final/THostAddress.js +2 -0
- package/dist/esm/dt/final/TIPv6.js +1 -0
- package/dist/esm/dt/final/TJWT.js +8 -0
- package/dist/esm/dt/final/TPercentage.js +5 -0
- package/dist/esm/dt/final/TSQLQuery.js +1 -0
- package/dist/esm/dt/final/TSSHPrivateKey.js +3 -1
- package/dist/esm/dt/final/TSemVerVersion.js +1 -0
- package/dist/esm/dt/final/TShellCommand.js +1 -0
- package/dist/esm/dt/final/TURL.js +2 -0
- package/dist/esm/dt/final/TUUID.js +1 -0
- package/dist/esm/dt/final/TYesNo.js +1 -1
- package/dist/esm/i18n/WordingManager.d.ts +16 -0
- package/dist/esm/i18n/types.d.ts +5 -0
- package/dist/esm/icon/Icon.d.ts +7 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.react-native-pure.d.ts +10 -0
- package/dist/esm/index.react-native-pure.js +10 -0
- package/dist/esm/product/manifest.d.ts +15 -0
- package/dist/esm/products/Helper/index.js +3 -0
- package/dist/esm/products/Helper/manifest.d.ts +6 -1
- package/dist/esm/std/BufferManager.d.ts +18 -0
- package/dist/esm/std/ClockManager.d.ts +5 -0
- package/dist/esm/std/EnvironmentManager.d.ts +10 -0
- package/dist/esm/std/HTTPAPICaller.d.ts +6 -0
- package/dist/esm/std/I18nManager.d.ts +26 -0
- package/dist/esm/std/JWTManager.d.ts +26 -0
- package/dist/esm/std/JobManager.d.ts +6 -0
- package/dist/esm/std/LLMManager.d.ts +25 -0
- package/dist/esm/std/LLMManager.js +1 -0
- package/dist/esm/std/PromptManager.d.ts +8 -0
- package/dist/esm/std/SettingsManager.d.ts +19 -0
- package/dist/esm/std/SettingsManager.js +9 -0
- package/dist/esm/std/impl/ConsoleLogger.js +7 -1
- package/dist/esm/std/impl/FakeEmailManager.js +1 -0
- package/dist/esm/std/impl/FakeJobManager.js +1 -0
- package/dist/esm/std/impl/FetchHTTPAPICallExecutor.d.ts +9 -0
- package/dist/esm/std/impl/FetchHTTPAPICallExecutor.js +11 -0
- package/dist/esm/std/impl/MistralAILLMManager.d.ts +17 -0
- package/dist/esm/std/impl/MistralAILLMManager.js +56 -0
- package/dist/esm/std/impl/NodeCryptoManager.js +6 -1
- package/dist/esm/std/impl/NodeDeterministicCryptoManager.d.ts +14 -0
- package/dist/esm/std/impl/NodeDeterministicCryptoManager.js +17 -3
- package/dist/esm/std/impl/NodeFSManager.js +10 -0
- package/dist/esm/std/impl/NodeHTTPAPICallExecutorAgentBuilder.js +2 -0
- package/dist/esm/std/impl/NodePromptManager.js +3 -0
- package/dist/esm/std/impl/OllamaLLMManager.d.ts +20 -0
- package/dist/esm/std/impl/OllamaLLMManager.js +56 -0
- package/dist/esm/std/impl/OpenAILLMManager.d.ts +17 -0
- package/dist/esm/std/impl/OpenAILLMManager.js +51 -0
- package/dist/esm/std/impl/SimpleHTTPAPICaller.js +14 -0
- package/dist/esm/std/impl/SimpleMapI18nManager.js +4 -2
- package/dist/esm/std/impl/StdDateClockManager.js +3 -0
- package/dist/esm/std/impl/UCDataStoreExternalResourceManager.js +3 -0
- package/dist/esm/std/impl/WebCryptoManager.js +9 -0
- package/dist/esm/std/index.d.ts +1 -0
- package/dist/esm/std/index.js +1 -0
- package/dist/esm/target/lib/cli/renderer.js +3 -0
- package/dist/esm/target/lib/client/consts.d.ts +3 -0
- package/dist/esm/target/lib/client/consts.js +3 -0
- package/dist/esm/target/lib/mcp-server/MCPServerBooter.js +1 -0
- package/dist/esm/target/lib/react/UCContainer.js +1 -0
- package/dist/esm/target/lib/react/UCPanel.js +4 -0
- package/dist/esm/target/lib/react/entrypoint.d.ts +2 -0
- package/dist/esm/target/lib/react/useUC.d.ts +8 -0
- package/dist/esm/target/lib/react/useUC.js +22 -0
- package/dist/esm/target/lib/react/useUCOR.d.ts +15 -0
- package/dist/esm/target/lib/react/useUCOR.js +45 -0
- package/dist/esm/target/lib/rn/input.d.ts +15 -0
- package/dist/esm/target/lib/rn/input.js +28 -0
- package/dist/esm/target/lib/server/AuthenticationChecker.js +2 -1
- package/dist/esm/target/lib/server/BasicAuthenticationChecker.js +1 -0
- package/dist/esm/target/lib/server/CSPDirectivesBuilder.js +13 -0
- package/dist/esm/target/lib/server/CustomerFacingErrorBuilder.js +3 -0
- package/dist/esm/target/lib/server/PrivateApiKeyAuthenticationChecker.js +1 -0
- package/dist/esm/target/lib/server/PublicApiKeyChecker.js +1 -1
- package/dist/esm/target/lib/server/RequestChecker.js +5 -4
- package/dist/esm/target/lib/server/RequestHandler.d.ts +5 -0
- package/dist/esm/target/lib/server/RequestLogger.js +5 -0
- package/dist/esm/target/lib/server/ServerManager.d.ts +19 -0
- package/dist/esm/target/lib/server/consts.d.ts +3 -0
- package/dist/esm/target/lib/server/consts.js +3 -0
- package/dist/esm/target/lib/web/input.d.ts +21 -0
- package/dist/esm/target/lib/web/input.js +4 -0
- package/dist/esm/target/node-core-cli/NodeCoreCLIManager.js +2 -2
- package/dist/esm/target/node-express-server/NodeExpressServerManager.js +5 -0
- package/dist/esm/target/node-express-server/lib/AuthCookieCreator.js +1 -1
- package/dist/esm/target/node-express-server/middlewares/AuthenticationCheckerMiddlewareBuilder.js +1 -0
- package/dist/esm/target/node-express-server/middlewares/PublicApiKeyCheckerMiddlewareBuilder.js +1 -0
- package/dist/esm/target/node-express-server/middlewares/RequestCheckerMiddlewareBuilder.js +1 -0
- package/dist/esm/target/node-express-server/middlewares/RequestHandlerMiddlewareBuilder.js +8 -0
- package/dist/esm/target/node-express-server/middlewares/RequestLoggerMiddlewareBuilder.js +1 -0
- package/dist/esm/target/node-mcp-server/NodeLocalStdioMCPServerManager.d.ts +10 -0
- package/dist/esm/target/node-mcp-server/NodeLocalStdioMCPServerManager.js +14 -0
- package/dist/esm/target/react-native-pure/UCAutoExecLoader.d.ts +2 -0
- package/dist/esm/target/react-native-pure/UCAutoExecLoader.js +5 -0
- package/dist/esm/target/react-native-pure/UCEntrypointTouchable.d.ts +4 -0
- package/dist/esm/target/react-native-pure/UCEntrypointTouchable.js +6 -0
- package/dist/esm/target/react-native-pure/UCExecTouchable.d.ts +4 -0
- package/dist/esm/target/react-native-pure/UCExecTouchable.js +9 -0
- package/dist/esm/target/react-native-pure/UCForm.d.ts +4 -0
- package/dist/esm/target/react-native-pure/UCForm.js +13 -0
- package/dist/esm/target/react-native-pure/UCFormField.d.ts +11 -0
- package/dist/esm/target/react-native-pure/UCFormField.js +32 -0
- package/dist/esm/target/react-native-pure/UCFormFieldControl.d.ts +11 -0
- package/dist/esm/target/react-native-pure/UCFormFieldControl.js +37 -0
- package/dist/esm/target/react-native-pure/UCFormFieldDesc.d.ts +7 -0
- package/dist/esm/target/react-native-pure/UCFormFieldDesc.js +11 -0
- package/dist/esm/target/react-native-pure/UCFormFieldErr.d.ts +7 -0
- package/dist/esm/target/react-native-pure/UCFormFieldErr.js +5 -0
- package/dist/esm/target/react-native-pure/UCFormFieldLabel.d.ts +7 -0
- package/dist/esm/target/react-native-pure/UCFormFieldLabel.js +8 -0
- package/dist/esm/target/react-native-pure/UCFormSubmitControl.d.ts +9 -0
- package/dist/esm/target/react-native-pure/UCFormSubmitControl.js +8 -0
- package/dist/esm/target/react-web-pure/UCEntrypointTouchable.d.ts +1 -1
- package/dist/esm/target/react-web-pure/UCExecTouchable.d.ts +1 -1
- package/dist/esm/target/react-web-pure/UCExecTouchable.js +1 -1
- package/dist/esm/target/react-web-pure/UCFormFieldControl.d.ts +1 -1
- package/dist/esm/target/react-web-pure/UCFormFieldControl.js +3 -3
- package/dist/esm/testing/AppTester.d.ts +4 -0
- package/dist/esm/testing/AppTester.js +16 -0
- package/dist/esm/testing/AppTesterConfigurator.d.ts +68 -0
- package/dist/esm/testing/UCDataStoreTester.d.ts +9 -0
- package/dist/esm/testing/UCDataStoreTester.js +13 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter.js +22 -2
- package/dist/esm/testing/impl/SimpleAppTesterConfigurator.js +1 -0
- package/dist/esm/testing/impl/SimpleHTMLAppTestReportEmitter.js +9 -3
- package/dist/esm/testing/impl/TypeScriptLibUCDefASTParser.js +12 -4
- package/dist/esm/testing/impl/VitestAppTestSuiteEmitter.js +6 -0
- package/dist/esm/testing/opts.d.ts +38 -0
- package/dist/esm/testing/opts.js +1 -1
- package/dist/esm/testing/uc-input.js +2 -0
- package/dist/esm/testing/workers/AppTesterCtxInitializer.js +7 -0
- package/dist/esm/testing/workers/UCExecutor.js +1 -0
- package/dist/esm/testing/workers/checkers/AppIndexChecker.js +1 -0
- package/dist/esm/testing/workers/checkers/UCDefSourcesChecker.js +4 -0
- package/dist/esm/uc/UC.js +19 -1
- package/dist/esm/uc/UCInputField.d.ts +28 -0
- package/dist/esm/uc/UCInputField.js +42 -0
- package/dist/esm/uc/data.d.ts +3 -0
- package/dist/esm/uc/def.d.ts +7 -0
- package/dist/esm/uc/exec.d.ts +39 -0
- package/dist/esm/uc/exec.js +29 -0
- package/dist/esm/uc/ext.d.ts +30 -1
- package/dist/esm/uc/helpers/UCOutputBuilder.js +5 -0
- package/dist/esm/uc/helpers/UCOutputReader.js +3 -1
- package/dist/esm/uc/impl/HTTPUCTransporter.js +4 -0
- package/dist/esm/uc/impl/InMemoryUCDataStore.js +7 -0
- package/dist/esm/uc/impl/KnexUCDataStore.d.ts +4 -0
- package/dist/esm/uc/impl/KnexUCDataStore.js +14 -0
- package/dist/esm/uc/impl/SimpleUCManager.js +6 -0
- package/dist/esm/uc/input-field.d.ts +60 -0
- package/dist/esm/uc/input-field.js +33 -0
- package/dist/esm/uc/input.d.ts +24 -0
- package/dist/esm/uc/lifecycle/client/IdleClientMain.js +1 -0
- package/dist/esm/uc/lifecycle/server/IdleServerMain.js +2 -0
- package/dist/esm/uc/manager.d.ts +11 -0
- package/dist/esm/uc/metadata.d.ts +10 -0
- package/dist/esm/uc/opi-layout.d.ts +3 -0
- package/dist/esm/uc/opi.d.ts +8 -0
- package/dist/esm/uc/output-field.d.ts +9 -0
- package/dist/esm/uc/output-part.d.ts +22 -0
- package/dist/esm/uc/output.d.ts +3 -0
- package/dist/esm/uc/policies/RoleRegularUCPolicy.js +1 -0
- package/dist/esm/uc/policies/funcs.js +1 -0
- package/dist/esm/uc/policy.d.ts +22 -0
- package/dist/esm/uc/sec.d.ts +9 -0
- package/dist/esm/uc/server.d.ts +10 -0
- package/dist/esm/uc/settings.d.ts +25 -0
- package/dist/esm/uc/side-effect.d.ts +16 -0
- package/dist/esm/uc/side-effect.js +16 -0
- package/dist/esm/uc/utils/rInput.d.ts +12 -0
- package/dist/esm/uc/utils/rInput.js +2 -0
- package/dist/esm/uc/utils/rVal.d.ts +25 -0
- package/dist/esm/uc/utils/rVal.js +27 -0
- package/dist/esm/uc/utils/recIs.d.ts +9 -0
- package/dist/esm/uc/utils/recIs.js +12 -1
- package/dist/esm/uc/utils/stripUCDLifecycleServer.d.ts +13 -0
- package/dist/esm/uc/utils/stripUCDLifecycleServer.js +17 -0
- package/dist/esm/uc/utils/ucifcoIsForArray.d.ts +6 -0
- package/dist/esm/uc/utils/ucifcoIsForArray.js +6 -0
- package/dist/esm/uc/workers/SimpleAggregateFinder.d.ts +12 -0
- package/dist/esm/uc/workers/SimpleAggregateFinder.js +12 -0
- package/dist/esm/uc/workers/UCBuilder.d.ts +7 -0
- package/dist/esm/uc/workers/UCBuilder.js +7 -0
- package/dist/esm/uc/workers/UCExecChecker.js +2 -0
- package/dist/esm/uc/workers/UCInputFilesProcessor.js +10 -4
- package/dist/esm/uc/workers/UCOutputFilesProcessor.js +6 -2
- package/dist/esm/utils/async/sleep.d.ts +10 -0
- package/dist/esm/utils/async/sleep.js +10 -0
- package/dist/esm/utils/http/appendData.js +5 -1
- package/dist/esm/utils/ioc/ContainerPrinter.js +2 -0
- package/dist/esm/utils/ioc/bindCommon.js +4 -0
- package/dist/esm/utils/ioc/bindNodeCLI.js +2 -0
- package/dist/esm/utils/ioc/bindNodeCore.js +1 -0
- package/dist/esm/utils/ioc/bindProduct.js +2 -0
- package/dist/esm/utils/ioc/bindRN.js +1 -0
- package/dist/esm/utils/ioc/bindServer.js +1 -0
- package/dist/esm/utils/ioc/bindWeb.js +2 -0
- package/dist/esm/utils/ioc/container.js +6 -0
- package/dist/esm/utils/numbers/units.js +3 -0
- package/dist/esm/utils/types/funcs.d.ts +35 -0
- package/dist/esm/utils/types/funcs.js +35 -0
- package/dist/esm/utils/types/utility-types.d.ts +17 -0
- package/dist/esm/utils/types/utility-types.js +1 -0
- package/package.json +16 -9
- package/docs/assets/trading-buy-asset-sequence-diagram.png +0 -0
- package/docs/assets/trading-target-mcp-server.png +0 -0
- package/docs/assets/trading-target-web-human.png +0 -0
- package/docs/assets/trading-target-web.png +0 -0
- package/docs/getting-started/001_Create_the_project.md +0 -168
- package/docs/getting-started/002_Create_the_App.md +0 -49
- package/docs/getting-started/003_Create_the_UseCase.md +0 -205
- package/docs/getting-started/004_Test_the_App.md +0 -114
- package/docs/getting-started/005_Create_the_Product.md +0 -46
- package/docs/getting-started/006_Create_the_server_Target.md +0 -130
- package/docs/getting-started/007_Create_the_web_Target.md +0 -262
- package/docs/getting-started/008_Switch_to_a_persistent_data_storage.md +0 -55
- package/docs/getting-started/009_Define_wording_for_humans.md +0 -42
- package/docs/getting-started/010_Create_the_cli_Target.md +0 -102
- package/docs/getting-started/011_Create_the_mcp_server_Target.md +0 -157
- package/docs/getting-started/012_Summary.md +0 -29
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
var MistralAILLMManager_1;
|
|
14
|
+
import { inject, injectable } from 'inversify';
|
|
15
|
+
let MistralAILLMManager = class MistralAILLMManager {
|
|
16
|
+
static { MistralAILLMManager_1 = this; }
|
|
17
|
+
httpAPICaller;
|
|
18
|
+
settingsManager;
|
|
19
|
+
static BASE_URL = 'https://api.mistral.ai/v1';
|
|
20
|
+
constructor(httpAPICaller, settingsManager) {
|
|
21
|
+
this.httpAPICaller = httpAPICaller;
|
|
22
|
+
this.settingsManager = settingsManager;
|
|
23
|
+
}
|
|
24
|
+
s() {
|
|
25
|
+
return {
|
|
26
|
+
mai_api_key: this.settingsManager.get()('mai_api_key'),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
async send(req) {
|
|
30
|
+
return await this.httpAPICaller.exec({
|
|
31
|
+
authorizationHeader: {
|
|
32
|
+
value: this.s().mai_api_key,
|
|
33
|
+
prefix: 'Bearer',
|
|
34
|
+
},
|
|
35
|
+
errBuilder: async (error) => {
|
|
36
|
+
if ('message' in error) {
|
|
37
|
+
return error.message;
|
|
38
|
+
}
|
|
39
|
+
return error.detail.map((d) => d.msg).join('\n');
|
|
40
|
+
},
|
|
41
|
+
method: 'POST',
|
|
42
|
+
req: {
|
|
43
|
+
envelope: 'json',
|
|
44
|
+
builder: async () => req,
|
|
45
|
+
},
|
|
46
|
+
urlBuilder: async () => `${MistralAILLMManager_1.BASE_URL}/chat/completions`,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
MistralAILLMManager = MistralAILLMManager_1 = __decorate([
|
|
51
|
+
injectable(),
|
|
52
|
+
__param(0, inject('HTTPAPICaller')),
|
|
53
|
+
__param(1, inject('SettingsManager')),
|
|
54
|
+
__metadata("design:paramtypes", [Object, Object])
|
|
55
|
+
], MistralAILLMManager);
|
|
56
|
+
export { MistralAILLMManager };
|
|
@@ -7,10 +7,13 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import crypto from 'node:crypto';
|
|
8
8
|
import { promisify } from 'node:util';
|
|
9
9
|
import { injectable } from 'inversify';
|
|
10
|
+
// https://nodejs.org/api/crypto.html#cryptopbkdf2password-salt-iterations-keylen-digest-callback
|
|
10
11
|
const pbkdf2 = promisify(crypto.pbkdf2);
|
|
12
|
+
// https://nodejs.org/api/crypto.html#cryptoscryptpassword-salt-keylen-options-callback
|
|
11
13
|
const scrypt = promisify(crypto.scrypt);
|
|
12
14
|
let NodeCryptoManager = class NodeCryptoManager {
|
|
13
15
|
async clear() {
|
|
16
|
+
// Nothing to do
|
|
14
17
|
}
|
|
15
18
|
hash(algorithm, base, binaryToTextEncoding) {
|
|
16
19
|
return crypto
|
|
@@ -35,9 +38,11 @@ let NodeCryptoManager = class NodeCryptoManager {
|
|
|
35
38
|
return Uint8Array.from(result);
|
|
36
39
|
}
|
|
37
40
|
async randomString(length) {
|
|
41
|
+
// Not perfect in terms of randomness (because of Math.random() but pretty fine for now)
|
|
38
42
|
let res = '';
|
|
39
43
|
while (res.length < length) {
|
|
40
44
|
const next = Math.random().toString(36).slice(2, 3);
|
|
45
|
+
// For now, we want only chars at the beginning, so it can be used as an identifier (i.e. in a database)
|
|
41
46
|
if (res.length === 0 &&
|
|
42
47
|
Number.isInteger(Number.parseInt(next, 10))) {
|
|
43
48
|
continue;
|
|
@@ -50,7 +55,7 @@ let NodeCryptoManager = class NodeCryptoManager {
|
|
|
50
55
|
return crypto.randomUUID();
|
|
51
56
|
}
|
|
52
57
|
async scrypt(password, salt, keyLength) {
|
|
53
|
-
const buffer = (await scrypt(password, salt, keyLength));
|
|
58
|
+
const buffer = (await scrypt(password, salt, keyLength)); // Forced to cast because it seems to be not typed correctly
|
|
54
59
|
return buffer.toString('hex');
|
|
55
60
|
}
|
|
56
61
|
};
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import type { UIntQuantity, UUID } from '../../dt/index.js';
|
|
2
2
|
import type { CryptoManagerRandomString } from '../CryptoManager.js';
|
|
3
3
|
import { NodeCryptoManager } from './NodeCryptoManager.js';
|
|
4
|
+
/**
|
|
5
|
+
* A deterministic {@link CryptoManager} based on {@link NodeCryptoManager}
|
|
6
|
+
*
|
|
7
|
+
* The main purpose is to have an implementation that generates always the
|
|
8
|
+
* same data deterministically to make snapshot assertions in tests easier.
|
|
9
|
+
*
|
|
10
|
+
* WARNING : it keeps internal "seeds" to generate always the same data.
|
|
11
|
+
*
|
|
12
|
+
* In our case, it's an auto-incremented integer.
|
|
13
|
+
*
|
|
14
|
+
* So if the same implementation is used in multiple places
|
|
15
|
+
* (e.g. in concurrent tests within the same test suite),
|
|
16
|
+
* be ready for "race conditions" and inconsistencies.
|
|
17
|
+
*/
|
|
4
18
|
export declare class NodeDeterministicCryptoManager extends NodeCryptoManager {
|
|
5
19
|
private randomStringIdx;
|
|
6
20
|
private uuidIdx;
|
|
@@ -7,6 +7,20 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { createHash } from 'node:crypto';
|
|
8
8
|
import { injectable } from 'inversify';
|
|
9
9
|
import { NodeCryptoManager } from './NodeCryptoManager.js';
|
|
10
|
+
/**
|
|
11
|
+
* A deterministic {@link CryptoManager} based on {@link NodeCryptoManager}
|
|
12
|
+
*
|
|
13
|
+
* The main purpose is to have an implementation that generates always the
|
|
14
|
+
* same data deterministically to make snapshot assertions in tests easier.
|
|
15
|
+
*
|
|
16
|
+
* WARNING : it keeps internal "seeds" to generate always the same data.
|
|
17
|
+
*
|
|
18
|
+
* In our case, it's an auto-incremented integer.
|
|
19
|
+
*
|
|
20
|
+
* So if the same implementation is used in multiple places
|
|
21
|
+
* (e.g. in concurrent tests within the same test suite),
|
|
22
|
+
* be ready for "race conditions" and inconsistencies.
|
|
23
|
+
*/
|
|
10
24
|
let NodeDeterministicCryptoManager = class NodeDeterministicCryptoManager extends NodeCryptoManager {
|
|
11
25
|
randomStringIdx = 0;
|
|
12
26
|
uuidIdx = 0;
|
|
@@ -33,14 +47,14 @@ let NodeDeterministicCryptoManager = class NodeDeterministicCryptoManager extend
|
|
|
33
47
|
const hashBytes = hash.digest().subarray(0, 16);
|
|
34
48
|
const bytes = Array.from(hashBytes);
|
|
35
49
|
if (bytes[6] !== undefined) {
|
|
36
|
-
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
50
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40; // Set the version to 4 (UUID v4)
|
|
37
51
|
}
|
|
38
52
|
if (bytes[8] !== undefined) {
|
|
39
|
-
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
53
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80; // Set the variant to the correct RFC 4122 variant
|
|
40
54
|
}
|
|
41
55
|
const raw = bytes
|
|
42
56
|
.map((byte) => {
|
|
43
|
-
return (byte + 0x1_00).toString(16).substring(1);
|
|
57
|
+
return (byte + 0x1_00).toString(16).substring(1); // Convert byte to hex
|
|
44
58
|
})
|
|
45
59
|
.join('');
|
|
46
60
|
const uuid = [
|
|
@@ -13,6 +13,9 @@ let NodeFSManager = class NodeFSManager {
|
|
|
13
13
|
return true;
|
|
14
14
|
}
|
|
15
15
|
async cat(path, opts) {
|
|
16
|
+
// Be careful : omitting to pass an encoding makes it return a Buffer and not a string
|
|
17
|
+
// This can be problematic in some callers, manipulating the file as a string (e.g. startsWith, includes, etc.)
|
|
18
|
+
// So make sure to fallback on a default encoding
|
|
16
19
|
return readFile(path, opts?.encoding ?? 'utf8');
|
|
17
20
|
}
|
|
18
21
|
async chmod(path, mode) {
|
|
@@ -25,6 +28,8 @@ let NodeFSManager = class NodeFSManager {
|
|
|
25
28
|
await appendFile(src, content);
|
|
26
29
|
}
|
|
27
30
|
async exists(path) {
|
|
31
|
+
// Before, we could use fs.exists(path) but it's been deprecated : @deprecated since v1.0.0 Use `fs.stat()` or `fs.access()` instead
|
|
32
|
+
// Both functions are very unpractical to use because we need to wrap everything in a try/catch. It's too verbose !
|
|
28
33
|
try {
|
|
29
34
|
await stat(path);
|
|
30
35
|
return true;
|
|
@@ -45,6 +50,11 @@ let NodeFSManager = class NodeFSManager {
|
|
|
45
50
|
const parsedPath = parse(path);
|
|
46
51
|
const stats = await stat(path);
|
|
47
52
|
const { birthtime, size } = stats;
|
|
53
|
+
// For now there is nothing in the standard library to detect it.
|
|
54
|
+
// There are 3rd party packages like mime, mime-type, etc. but we prefer
|
|
55
|
+
// limiting the external dependencies.
|
|
56
|
+
// One can also call `file -b --mime-type /some/path` via exec/spawn if their
|
|
57
|
+
// system has this utility.
|
|
48
58
|
const mimeType = null;
|
|
49
59
|
const type = this.determineType(stats);
|
|
50
60
|
return {
|
|
@@ -21,6 +21,8 @@ let NodeHTTPAPICallExecutorAgentBuilder = class NodeHTTPAPICallExecutorAgentBuil
|
|
|
21
21
|
exec({ url, }) {
|
|
22
22
|
if (url.protocol.startsWith('https')) {
|
|
23
23
|
return new https.Agent({
|
|
24
|
+
// We allow self-signed certificates in non-prod environments
|
|
25
|
+
// This is useful when testing the CLI calling a the server from a docker container for example
|
|
24
26
|
rejectUnauthorized: this.environmentManager.isProd(),
|
|
25
27
|
});
|
|
26
28
|
}
|
|
@@ -9,10 +9,13 @@ import { createInterface } from 'node:readline/promises';
|
|
|
9
9
|
import { injectable } from 'inversify';
|
|
10
10
|
let NodePromptManager = class NodePromptManager {
|
|
11
11
|
async prompt(invite, opts) {
|
|
12
|
+
// TODO : Add keypress handling to hide when sensitive data is typed
|
|
12
13
|
const readLine = createInterface({
|
|
13
14
|
input: stdin,
|
|
14
15
|
output: stdout,
|
|
15
16
|
});
|
|
17
|
+
// To avoid "Warning: Detected unsettled top-level await at file:///[...]/dist/esm/xxx.js"
|
|
18
|
+
// when pressing Ctrl+C while being prompted
|
|
16
19
|
readLine.on('SIGINT', () => {
|
|
17
20
|
readLine.close();
|
|
18
21
|
process.exit(0);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { URL } from '../../dt/index.js';
|
|
2
|
+
import type { HTTPAPICaller } from '../HTTPAPICaller.js';
|
|
3
|
+
import type { LLMManager, LLMManagerSendReq, LLMManagerSendRes } from '../LLMManager.js';
|
|
4
|
+
import type { Configurable, Settings, SettingsManager } from '../SettingsManager.js';
|
|
5
|
+
/**
|
|
6
|
+
* Unlike the "commercial" APIs, Ollama does not secure the API with an API key
|
|
7
|
+
* @see https://github.com/ollama/ollama/issues/849
|
|
8
|
+
*/
|
|
9
|
+
export interface OllamaLLMManagerSettings extends Settings {
|
|
10
|
+
oll_base_url: URL;
|
|
11
|
+
}
|
|
12
|
+
type S = OllamaLLMManagerSettings;
|
|
13
|
+
export declare class OllamaLLMManager implements Configurable<S>, LLMManager {
|
|
14
|
+
private httpAPICaller;
|
|
15
|
+
private settingsManager;
|
|
16
|
+
constructor(httpAPICaller: HTTPAPICaller, settingsManager: SettingsManager<S>);
|
|
17
|
+
s(): OllamaLLMManagerSettings;
|
|
18
|
+
send(req: LLMManagerSendReq): Promise<LLMManagerSendRes>;
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { inject, injectable } from 'inversify';
|
|
14
|
+
import { IllegalArgumentError } from '../../error/index.js';
|
|
15
|
+
let OllamaLLMManager = class OllamaLLMManager {
|
|
16
|
+
httpAPICaller;
|
|
17
|
+
settingsManager;
|
|
18
|
+
constructor(httpAPICaller, settingsManager) {
|
|
19
|
+
this.httpAPICaller = httpAPICaller;
|
|
20
|
+
this.settingsManager = settingsManager;
|
|
21
|
+
}
|
|
22
|
+
s() {
|
|
23
|
+
return {
|
|
24
|
+
oll_base_url: this.settingsManager.get()('oll_base_url'),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
async send(req) {
|
|
28
|
+
const firstMessage = req.messages[0];
|
|
29
|
+
if (!firstMessage) {
|
|
30
|
+
throw new IllegalArgumentError('Please provide at least one message');
|
|
31
|
+
}
|
|
32
|
+
return await this.httpAPICaller.exec({
|
|
33
|
+
errBuilder: async (error) => error.error,
|
|
34
|
+
method: 'POST',
|
|
35
|
+
outputBuilder: async (res) => ({
|
|
36
|
+
choices: [{ message: { content: res.response } }],
|
|
37
|
+
}),
|
|
38
|
+
req: {
|
|
39
|
+
envelope: 'json',
|
|
40
|
+
builder: async () => ({
|
|
41
|
+
model: req.model,
|
|
42
|
+
prompt: firstMessage.content,
|
|
43
|
+
stream: false,
|
|
44
|
+
}),
|
|
45
|
+
},
|
|
46
|
+
urlBuilder: async () => `${this.s().oll_base_url}/api/generate`,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
OllamaLLMManager = __decorate([
|
|
51
|
+
injectable(),
|
|
52
|
+
__param(0, inject('HTTPAPICaller')),
|
|
53
|
+
__param(1, inject('SettingsManager')),
|
|
54
|
+
__metadata("design:paramtypes", [Object, Object])
|
|
55
|
+
], OllamaLLMManager);
|
|
56
|
+
export { OllamaLLMManager };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ApiKey } from '../../dt/index.js';
|
|
2
|
+
import type { HTTPAPICaller } from '../HTTPAPICaller.js';
|
|
3
|
+
import type { LLMManager, LLMManagerSendReq, LLMManagerSendRes } from '../LLMManager.js';
|
|
4
|
+
import type { Configurable, Settings, SettingsManager } from '../SettingsManager.js';
|
|
5
|
+
export interface OpenAILLMManagerSettings extends Settings {
|
|
6
|
+
oai_api_key: ApiKey;
|
|
7
|
+
}
|
|
8
|
+
type S = OpenAILLMManagerSettings;
|
|
9
|
+
export declare class OpenAILLMManager implements Configurable<S>, LLMManager {
|
|
10
|
+
private httpAPICaller;
|
|
11
|
+
private settingsManager;
|
|
12
|
+
private static BASE_URL;
|
|
13
|
+
constructor(httpAPICaller: HTTPAPICaller, settingsManager: SettingsManager<S>);
|
|
14
|
+
s(): OpenAILLMManagerSettings;
|
|
15
|
+
send(req: LLMManagerSendReq): Promise<LLMManagerSendRes>;
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
var OpenAILLMManager_1;
|
|
14
|
+
import { inject, injectable } from 'inversify';
|
|
15
|
+
let OpenAILLMManager = class OpenAILLMManager {
|
|
16
|
+
static { OpenAILLMManager_1 = this; }
|
|
17
|
+
httpAPICaller;
|
|
18
|
+
settingsManager;
|
|
19
|
+
static BASE_URL = 'https://api.openai.com/v1';
|
|
20
|
+
constructor(httpAPICaller, settingsManager) {
|
|
21
|
+
this.httpAPICaller = httpAPICaller;
|
|
22
|
+
this.settingsManager = settingsManager;
|
|
23
|
+
}
|
|
24
|
+
s() {
|
|
25
|
+
return {
|
|
26
|
+
oai_api_key: this.settingsManager.get()('oai_api_key'),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
async send(req) {
|
|
30
|
+
return await this.httpAPICaller.exec({
|
|
31
|
+
authorizationHeader: {
|
|
32
|
+
value: this.s().oai_api_key,
|
|
33
|
+
prefix: 'Bearer',
|
|
34
|
+
},
|
|
35
|
+
errBuilder: async (error) => error.error.message,
|
|
36
|
+
method: 'POST',
|
|
37
|
+
req: {
|
|
38
|
+
envelope: 'json',
|
|
39
|
+
builder: async () => req,
|
|
40
|
+
},
|
|
41
|
+
urlBuilder: async () => `${OpenAILLMManager_1.BASE_URL}/chat/completions`,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
OpenAILLMManager = OpenAILLMManager_1 = __decorate([
|
|
46
|
+
injectable(),
|
|
47
|
+
__param(0, inject('HTTPAPICaller')),
|
|
48
|
+
__param(1, inject('SettingsManager')),
|
|
49
|
+
__metadata("design:paramtypes", [Object, Object])
|
|
50
|
+
], OpenAILLMManager);
|
|
51
|
+
export { OpenAILLMManager };
|
|
@@ -64,6 +64,7 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
|
|
|
64
64
|
if (status === 202 || status === 204) {
|
|
65
65
|
return {};
|
|
66
66
|
}
|
|
67
|
+
// Using .startsWith instead of === because the value can look like this 'application/json; charset=utf-8'
|
|
67
68
|
const responseContentType = headers.get('Content-Type');
|
|
68
69
|
const isJSON = responseContentType?.startsWith('application/json');
|
|
69
70
|
const isFormURLEncoded = responseContentType?.startsWith('application/x-www-form-urlencoded');
|
|
@@ -87,6 +88,10 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
|
|
|
87
88
|
async computeHeaders({ additionalHeadersBuilder, authorizationHeader, basicAuth, contentType = 'application/json', req, }) {
|
|
88
89
|
const headers = {};
|
|
89
90
|
if (req?.envelope !== 'form-data') {
|
|
91
|
+
// The boundary needs to be set when sending data this way, so the server can understand how to read it (Source : https://stackoverflow.com/a/20321259/1259118)
|
|
92
|
+
// In RN, the content-type we set is automatically overriden by the internal fetch client (i.e. 'content-type': 'multipart/form-data; boundary=7ZsqoHiTstShSc4-Yi4U7ier3GPc_4QL5iN2eT9rnSNd0g1UoFPgt3I6.fsWlV8YpJhFkG')
|
|
93
|
+
// In CLI, if it is set, it's not overriden. So it creates problems. With 'form-data', we send 'content-type': 'multipart/form-data'` but the server expects something like 'content-type': 'multipart/form-data;boundary=--------------------------743913816161509008636675'
|
|
94
|
+
// So we don't set it at all and we're good to go.
|
|
90
95
|
headers['Content-Type'] = contentType;
|
|
91
96
|
}
|
|
92
97
|
if (authorizationHeader) {
|
|
@@ -110,6 +115,8 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
|
|
|
110
115
|
return headers;
|
|
111
116
|
}
|
|
112
117
|
async processResBad({ errBuilder, opts, }, isJSON, isXML, response) {
|
|
118
|
+
// NOTE : This method must handle all possible cases and never throw
|
|
119
|
+
// Indeed, it's supposed to handle the errors so it shouldn't throw one
|
|
113
120
|
let error;
|
|
114
121
|
try {
|
|
115
122
|
if (isJSON) {
|
|
@@ -134,6 +141,7 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
|
|
|
134
141
|
return null;
|
|
135
142
|
}
|
|
136
143
|
if (typeof error === 'string') {
|
|
144
|
+
// For example, it can be from `asText`, containing funny formatting (developers and errors you know...)
|
|
137
145
|
return error.trim();
|
|
138
146
|
}
|
|
139
147
|
if (!error) {
|
|
@@ -144,10 +152,14 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
|
|
|
144
152
|
if (typeof message === 'string') {
|
|
145
153
|
return message;
|
|
146
154
|
}
|
|
155
|
+
// Case where `errBuilder` is of type (error: string) => string
|
|
156
|
+
// If an object is passed to it, it would return an object instead, interpreted incorrectly as [object Object] by error handlers
|
|
147
157
|
return JSON.stringify(message);
|
|
148
158
|
}
|
|
149
159
|
catch (err) {
|
|
150
160
|
this.logger.error(err);
|
|
161
|
+
// Case where `errBuilder` is of type (error: Object) => string
|
|
162
|
+
// If an object of another shape is passed to it, it would trigger some TypeError or cannot call .message of undefined
|
|
151
163
|
return JSON.stringify(error);
|
|
152
164
|
}
|
|
153
165
|
}
|
|
@@ -163,7 +175,9 @@ let SimpleHTTPAPICaller = class SimpleHTTPAPICaller {
|
|
|
163
175
|
});
|
|
164
176
|
if (isFormURLEncoded) {
|
|
165
177
|
payload = {};
|
|
178
|
+
// TODO : Find a better way to do this (without adding any external dependency because the code must be portable)
|
|
166
179
|
new URL(`http://localhost?${asText}`).searchParams.forEach((v, k) => {
|
|
180
|
+
// @ts-ignore
|
|
167
181
|
payload[k] = v;
|
|
168
182
|
});
|
|
169
183
|
}
|
|
@@ -17,7 +17,7 @@ let SimpleMapI18nManager = class SimpleMapI18nManager {
|
|
|
17
17
|
static { SimpleMapI18nManager_1 = this; }
|
|
18
18
|
i18n;
|
|
19
19
|
logger;
|
|
20
|
-
static PLACEHOLDERS_REGEX = /{{([A-Z-a-z0-9]+)}}/g;
|
|
20
|
+
static PLACEHOLDERS_REGEX = /{{([A-Z-a-z0-9]+)}}/g; // Note the 'g' so it can be used with `matchAll`
|
|
21
21
|
entries;
|
|
22
22
|
constructor(i18n, logger) {
|
|
23
23
|
this.i18n = i18n;
|
|
@@ -48,12 +48,14 @@ let SimpleMapI18nManager = class SimpleMapI18nManager {
|
|
|
48
48
|
if (opts?.fallback) {
|
|
49
49
|
return opts.fallback;
|
|
50
50
|
}
|
|
51
|
-
return key;
|
|
51
|
+
return key; // Mimic the behavior of some common libraries like i18next
|
|
52
52
|
}
|
|
53
53
|
tOrNull(key, _opts) {
|
|
54
54
|
return this.entries.get(key) || null;
|
|
55
55
|
}
|
|
56
56
|
replacePlaceholders(v, opts) {
|
|
57
|
+
// DO NOT USE THIS IN PRODUCTION
|
|
58
|
+
// The purpose of it is to have a simple and dependency-less implementation, to play with
|
|
57
59
|
let res = v;
|
|
58
60
|
const placeholders = res.matchAll(SimpleMapI18nManager_1.PLACEHOLDERS_REGEX);
|
|
59
61
|
for (const [placeholder, key] of placeholders) {
|
|
@@ -10,6 +10,9 @@ let StdDateClockManager = class StdDateClockManager {
|
|
|
10
10
|
return new Date();
|
|
11
11
|
}
|
|
12
12
|
nowToKey() {
|
|
13
|
+
// The rationale behind this being hardcoded is to avoid adding a library (luxon, date-fns) just for that.
|
|
14
|
+
// For instance, luxon adds a huge amount of code to a basic web target when bundled, for nothing.
|
|
15
|
+
// See https://github.com/moment/luxon/issues/854#issuecomment-1729384672
|
|
13
16
|
return this.now()
|
|
14
17
|
.toISOString()
|
|
15
18
|
.replaceAll(/-|T|:/g, '')
|
|
@@ -11,6 +11,9 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
11
11
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
12
|
};
|
|
13
13
|
import { inject, injectable } from 'inversify';
|
|
14
|
+
// TODO : Wait for the DB to be ready or add a retry mechanism
|
|
15
|
+
// Because when we start from a fresh install, this is executed before the docker container is ready
|
|
16
|
+
// A temporary workaround is to stop and restart everything. At the 2nd startup, the db is ready, and it works
|
|
14
17
|
let UCDataStoreExternalResourceManager = class UCDataStoreExternalResourceManager {
|
|
15
18
|
ucDataStore;
|
|
16
19
|
constructor(ucDataStore) {
|
|
@@ -10,6 +10,7 @@ const DIGEST_MAPPING = new Map([
|
|
|
10
10
|
]);
|
|
11
11
|
let WebCryptoManager = class WebCryptoManager {
|
|
12
12
|
async clear() {
|
|
13
|
+
// Nothing to do
|
|
13
14
|
}
|
|
14
15
|
hash(_algorithm, _base) {
|
|
15
16
|
throw new Error('Method not implemented.');
|
|
@@ -25,9 +26,13 @@ let WebCryptoManager = class WebCryptoManager {
|
|
|
25
26
|
if (!hash) {
|
|
26
27
|
throw new Error(`Digest ${digest} is not valid for WebCryptoManager`);
|
|
27
28
|
}
|
|
29
|
+
// "Secure context: This feature is available only in secure contexts (HTTPS), in some or all supporting browsers."
|
|
30
|
+
// Warning: This API provides a number of low-level cryptographic primitives. It's very easy to misuse them, and the pitfalls involved can be very subtle.
|
|
31
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto
|
|
28
32
|
const textEncoder = new TextEncoder();
|
|
29
33
|
const passwordKey = await crypto.subtle.importKey('raw', textEncoder.encode(password), 'PBKDF2', false, ['deriveBits']);
|
|
30
34
|
const result = await crypto.subtle.deriveBits({
|
|
35
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Pbkdf2Params
|
|
31
36
|
hash,
|
|
32
37
|
iterations: iterationsCount,
|
|
33
38
|
name: 'PBKDF2',
|
|
@@ -36,9 +41,11 @@ let WebCryptoManager = class WebCryptoManager {
|
|
|
36
41
|
return new Uint8Array(result);
|
|
37
42
|
}
|
|
38
43
|
async randomString(length) {
|
|
44
|
+
// Not perfect in terms of randomness (because of Math.random() but pretty fine for now)
|
|
39
45
|
let res = '';
|
|
40
46
|
while (res.length < length) {
|
|
41
47
|
const next = Math.random().toString(36).slice(2, 3);
|
|
48
|
+
// For now, we want only chars at the beginning, so it can be used as an identifier (i.e. in a database)
|
|
42
49
|
if (res.length === 0 &&
|
|
43
50
|
Number.isInteger(Number.parseInt(next, 10))) {
|
|
44
51
|
continue;
|
|
@@ -48,6 +55,8 @@ let WebCryptoManager = class WebCryptoManager {
|
|
|
48
55
|
return res;
|
|
49
56
|
}
|
|
50
57
|
randomUUID() {
|
|
58
|
+
// "Secure context: This feature is available only in secure contexts (HTTPS), in some or all supporting browsers."
|
|
59
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID
|
|
51
60
|
return crypto.randomUUID();
|
|
52
61
|
}
|
|
53
62
|
async scrypt() {
|
package/dist/esm/std/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export * from './HTTPAPICallExecutor.js';
|
|
|
13
13
|
export * from './I18nManager.js';
|
|
14
14
|
export * from './JobManager.js';
|
|
15
15
|
export * from './JWTManager.js';
|
|
16
|
+
export * from './LLMManager.js';
|
|
16
17
|
export * from './Logger.js';
|
|
17
18
|
export * from './PromptManager.js';
|
|
18
19
|
export * from './SettingsManager.js';
|
package/dist/esm/std/index.js
CHANGED
|
@@ -13,6 +13,7 @@ export * from './HTTPAPICallExecutor.js';
|
|
|
13
13
|
export * from './I18nManager.js';
|
|
14
14
|
export * from './JobManager.js';
|
|
15
15
|
export * from './JWTManager.js';
|
|
16
|
+
export * from './LLMManager.js';
|
|
16
17
|
export * from './Logger.js';
|
|
17
18
|
export * from './PromptManager.js';
|
|
18
19
|
export * from './SettingsManager.js';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CustomError } from '../../../error/index.js';
|
|
2
2
|
export function print(line) {
|
|
3
|
+
// biome-ignore lint/suspicious/noConsole: we want it
|
|
3
4
|
console.info(line);
|
|
4
5
|
}
|
|
5
6
|
export function printError(err) {
|
|
@@ -7,11 +8,13 @@ export function printError(err) {
|
|
|
7
8
|
if (err instanceof Error) {
|
|
8
9
|
message = err.message;
|
|
9
10
|
if (!(err instanceof CustomError)) {
|
|
11
|
+
// biome-ignore lint/suspicious/noConsole: we want it
|
|
10
12
|
console.error(err);
|
|
11
13
|
}
|
|
12
14
|
}
|
|
13
15
|
else if (typeof err === 'string') {
|
|
14
16
|
message = err;
|
|
15
17
|
}
|
|
18
|
+
// biome-ignore lint/suspicious/noConsole: we want it
|
|
16
19
|
console.error(message);
|
|
17
20
|
}
|
|
@@ -32,6 +32,7 @@ let MCPServerBooter = class MCPServerBooter {
|
|
|
32
32
|
srcImporter,
|
|
33
33
|
});
|
|
34
34
|
for await (const uc of ucs) {
|
|
35
|
+
// Declared only for compatibility with ServerManager's contract but not used
|
|
35
36
|
const contract = ucHTTPContract(uc);
|
|
36
37
|
await this.ucManager.initServer(uc);
|
|
37
38
|
await this.serverManager.mount(uc.appManifest, uc.def, contract);
|
|
@@ -33,6 +33,9 @@ export function UCPanel({ autoExec = false, clearAfterExec = true, onDone, onErr
|
|
|
33
33
|
};
|
|
34
34
|
const onSubmit = async () => {
|
|
35
35
|
setExecState('submitting');
|
|
36
|
+
// Is some targets, the confirmClient blocks the main thread (e.g. window.confirm()).
|
|
37
|
+
// This leads to the state set above not being updated.
|
|
38
|
+
// This is a "hacky" workaroud to let React re-render the control with 'submitting' state before
|
|
36
39
|
await sleep(100);
|
|
37
40
|
await onStartSubmitting?.();
|
|
38
41
|
const confirmed = await ucManager.confirmClient(uc);
|
|
@@ -62,6 +65,7 @@ export function UCPanel({ autoExec = false, clearAfterExec = true, onDone, onErr
|
|
|
62
65
|
};
|
|
63
66
|
const disabled = ucIsDisabled(execState);
|
|
64
67
|
const loading = ucIsLoading(execState);
|
|
68
|
+
// TODO : Keep these as a state to avoid recomputation
|
|
65
69
|
const ctx = {
|
|
66
70
|
clearAfterExec,
|
|
67
71
|
disabled,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { URLPath } from '../../../dt/index.js';
|
|
2
2
|
import type { UC, UCInput, UCOPIBase } from '../../../uc/index.js';
|
|
3
|
+
export type UCEntrypointOnPress = () => Promise<void>;
|
|
3
4
|
export interface UCEntrypointCtx<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> {
|
|
5
|
+
onPress?: UCEntrypointOnPress;
|
|
4
6
|
path?: URLPath | undefined;
|
|
5
7
|
uc: UC<I, OPI0, OPI1>;
|
|
6
8
|
}
|
|
@@ -2,6 +2,14 @@ import { type ArgsRecord, UC, type UCDef, type UCInput, type UCOPIBase } from '.
|
|
|
2
2
|
type CloneFunc<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> = (i: Partial<I>) => UC<I, OPI0, OPI1>;
|
|
3
3
|
type DivertFunc<II extends UCInput | undefined = undefined, OOPI0 extends UCOPIBase | undefined = undefined, OOPI1 extends UCOPIBase | undefined = undefined> = (siblingUCD: UCDef) => UC<II, OOPI0, OOPI1>;
|
|
4
4
|
type RefillFunc<I extends UCInput | undefined = undefined> = (i: Partial<I>) => void;
|
|
5
|
+
/**
|
|
6
|
+
* This hook provides utilities to init a use case and perform actions on it in a React way
|
|
7
|
+
* @param appManifest
|
|
8
|
+
* @param def
|
|
9
|
+
* @param auth
|
|
10
|
+
* @param opts
|
|
11
|
+
* @returns
|
|
12
|
+
*/
|
|
5
13
|
export declare function useUC<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(appManifest: ArgsRecord<I, OPI0, OPI1>['appManifest'], def: ArgsRecord<I, OPI0, OPI1>['def'], auth: ArgsRecord<I, OPI0, OPI1>['auth'], opts?: {
|
|
6
14
|
fillWith: Partial<I>;
|
|
7
15
|
}): [
|