@dexto/core 1.5.6 → 1.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/DextoAgent.cjs +189 -30
- package/dist/agent/DextoAgent.d.ts +44 -9
- package/dist/agent/DextoAgent.d.ts.map +1 -1
- package/dist/agent/DextoAgent.js +190 -31
- package/dist/agent/schemas.cjs +5 -0
- package/dist/agent/schemas.d.ts +456 -66
- package/dist/agent/schemas.d.ts.map +1 -1
- package/dist/agent/schemas.js +5 -0
- package/dist/context/manager.cjs +1 -1
- package/dist/context/manager.js +1 -1
- package/dist/context/utils.cjs +90 -17
- package/dist/context/utils.d.ts.map +1 -1
- package/dist/context/utils.js +90 -17
- package/dist/errors/types.cjs +2 -1
- package/dist/errors/types.d.ts +2 -1
- package/dist/errors/types.d.ts.map +1 -1
- package/dist/errors/types.js +2 -1
- package/dist/events/index.cjs +4 -1
- package/dist/events/index.d.ts +37 -2
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +4 -1
- package/dist/image/types.d.ts +15 -0
- package/dist/image/types.d.ts.map +1 -1
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/llm/curation-config.cjs +82 -0
- package/dist/llm/curation-config.d.ts +13 -0
- package/dist/llm/curation-config.d.ts.map +1 -0
- package/dist/llm/curation-config.js +59 -0
- package/dist/llm/curation.cjs +57 -0
- package/dist/llm/curation.d.ts +16 -0
- package/dist/llm/curation.d.ts.map +1 -0
- package/dist/llm/curation.js +34 -0
- package/dist/llm/error-codes.cjs +1 -0
- package/dist/llm/error-codes.d.ts +1 -0
- package/dist/llm/error-codes.d.ts.map +1 -1
- package/dist/llm/error-codes.js +1 -0
- package/dist/llm/errors.cjs +16 -1
- package/dist/llm/errors.d.ts +15 -8
- package/dist/llm/errors.d.ts.map +1 -1
- package/dist/llm/errors.js +16 -1
- package/dist/llm/executor/provider-options.cjs +1 -1
- package/dist/llm/executor/provider-options.js +1 -1
- package/dist/llm/executor/turn-executor.cjs +35 -2
- package/dist/llm/executor/turn-executor.d.ts.map +1 -1
- package/dist/llm/executor/turn-executor.js +35 -2
- package/dist/llm/index.cjs +14 -3
- package/dist/llm/index.d.ts +3 -1
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js +13 -2
- package/dist/llm/registry/auto-update.cjs +263 -0
- package/dist/llm/registry/auto-update.d.ts +27 -0
- package/dist/llm/registry/auto-update.d.ts.map +1 -0
- package/dist/llm/registry/auto-update.js +227 -0
- package/dist/llm/registry/index.cjs +806 -0
- package/dist/llm/{registry.d.ts → registry/index.d.ts} +67 -13
- package/dist/llm/registry/index.d.ts.map +1 -0
- package/dist/llm/registry/index.js +756 -0
- package/dist/llm/registry/models.generated.cjs +4861 -0
- package/dist/llm/registry/models.generated.d.ts +431 -0
- package/dist/llm/registry/models.generated.d.ts.map +1 -0
- package/dist/llm/registry/models.generated.js +4838 -0
- package/dist/llm/registry/models.manual.cjs +44 -0
- package/dist/llm/registry/models.manual.d.ts +22 -0
- package/dist/llm/registry/models.manual.d.ts.map +1 -0
- package/dist/llm/registry/models.manual.js +21 -0
- package/dist/llm/registry/sync.cjs +354 -0
- package/dist/llm/registry/sync.d.ts +41 -0
- package/dist/llm/registry/sync.d.ts.map +1 -0
- package/dist/llm/registry/sync.js +328 -0
- package/dist/llm/resolver.cjs +29 -7
- package/dist/llm/resolver.d.ts +1 -1
- package/dist/llm/resolver.d.ts.map +1 -1
- package/dist/llm/resolver.js +31 -8
- package/dist/llm/schemas.cjs +13 -1
- package/dist/llm/schemas.d.ts +59 -59
- package/dist/llm/schemas.d.ts.map +1 -1
- package/dist/llm/schemas.js +14 -1
- package/dist/llm/services/factory.cjs +43 -27
- package/dist/llm/services/factory.d.ts +20 -1
- package/dist/llm/services/factory.d.ts.map +1 -1
- package/dist/llm/services/factory.js +44 -28
- package/dist/llm/services/test-utils.integration.cjs +5 -1
- package/dist/llm/services/test-utils.integration.d.ts.map +1 -1
- package/dist/llm/services/test-utils.integration.js +5 -1
- package/dist/llm/services/vercel.cjs +4 -1
- package/dist/llm/services/vercel.d.ts +1 -0
- package/dist/llm/services/vercel.d.ts.map +1 -1
- package/dist/llm/services/vercel.js +4 -1
- package/dist/llm/types.cjs +5 -2
- package/dist/llm/types.d.ts +1 -1
- package/dist/llm/types.d.ts.map +1 -1
- package/dist/llm/types.js +5 -2
- package/dist/llm/validation.cjs +1 -1
- package/dist/llm/validation.js +1 -1
- package/dist/logger/v2/dexto-logger.cjs +4 -0
- package/dist/logger/v2/dexto-logger.d.ts +3 -0
- package/dist/logger/v2/dexto-logger.d.ts.map +1 -1
- package/dist/logger/v2/dexto-logger.js +4 -0
- package/dist/logger/v2/types.d.ts +2 -0
- package/dist/logger/v2/types.d.ts.map +1 -1
- package/dist/mcp/error-codes.cjs +1 -0
- package/dist/mcp/error-codes.d.ts +1 -0
- package/dist/mcp/error-codes.d.ts.map +1 -1
- package/dist/mcp/error-codes.js +1 -0
- package/dist/mcp/errors.cjs +13 -0
- package/dist/mcp/errors.d.ts +7 -0
- package/dist/mcp/errors.d.ts.map +1 -1
- package/dist/mcp/errors.js +13 -0
- package/dist/mcp/manager.cjs +46 -4
- package/dist/mcp/manager.d.ts +10 -2
- package/dist/mcp/manager.d.ts.map +1 -1
- package/dist/mcp/manager.js +46 -4
- package/dist/mcp/mcp-client.cjs +89 -5
- package/dist/mcp/mcp-client.d.ts +5 -1
- package/dist/mcp/mcp-client.d.ts.map +1 -1
- package/dist/mcp/mcp-client.js +89 -5
- package/dist/mcp/schemas.cjs +6 -1
- package/dist/mcp/schemas.d.ts +1 -1
- package/dist/mcp/schemas.d.ts.map +1 -1
- package/dist/mcp/schemas.js +6 -1
- package/dist/mcp/types.d.ts +5 -0
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/prompts/index.d.ts +1 -1
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/prompt-manager.cjs +90 -4
- package/dist/prompts/prompt-manager.d.ts +16 -6
- package/dist/prompts/prompt-manager.d.ts.map +1 -1
- package/dist/prompts/prompt-manager.js +90 -4
- package/dist/prompts/providers/config-prompt-provider.cjs +104 -10
- package/dist/prompts/providers/config-prompt-provider.d.ts.map +1 -1
- package/dist/prompts/providers/config-prompt-provider.js +105 -11
- package/dist/prompts/providers/custom-prompt-provider.cjs +1 -0
- package/dist/prompts/providers/custom-prompt-provider.d.ts.map +1 -1
- package/dist/prompts/providers/custom-prompt-provider.js +1 -0
- package/dist/prompts/providers/mcp-prompt-provider.cjs +1 -0
- package/dist/prompts/providers/mcp-prompt-provider.d.ts.map +1 -1
- package/dist/prompts/providers/mcp-prompt-provider.js +1 -0
- package/dist/prompts/schemas.cjs +28 -2
- package/dist/prompts/schemas.d.ts +130 -0
- package/dist/prompts/schemas.d.ts.map +1 -1
- package/dist/prompts/schemas.js +28 -2
- package/dist/prompts/types.d.ts +55 -3
- package/dist/prompts/types.d.ts.map +1 -1
- package/dist/resources/handlers/filesystem-handler.cjs +25 -0
- package/dist/resources/handlers/filesystem-handler.d.ts +1 -0
- package/dist/resources/handlers/filesystem-handler.d.ts.map +1 -1
- package/dist/resources/handlers/filesystem-handler.js +25 -0
- package/dist/session/chat-session.cjs +1 -1
- package/dist/session/chat-session.d.ts +1 -1
- package/dist/session/chat-session.d.ts.map +1 -1
- package/dist/session/chat-session.js +1 -1
- package/dist/session/index.d.ts +1 -1
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/message-queue.cjs +29 -5
- package/dist/session/message-queue.d.ts +3 -1
- package/dist/session/message-queue.d.ts.map +1 -1
- package/dist/session/message-queue.js +29 -5
- package/dist/session/session-manager.cjs +84 -3
- package/dist/session/session-manager.d.ts +12 -0
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +74 -3
- package/dist/session/types.d.ts +1 -0
- package/dist/session/types.d.ts.map +1 -1
- package/dist/systemPrompt/contributors.cjs +42 -0
- package/dist/systemPrompt/contributors.d.ts +13 -0
- package/dist/systemPrompt/contributors.d.ts.map +1 -1
- package/dist/systemPrompt/contributors.js +41 -0
- package/dist/tools/errors.cjs +7 -3
- package/dist/tools/errors.d.ts +5 -1
- package/dist/tools/errors.d.ts.map +1 -1
- package/dist/tools/errors.js +7 -3
- package/dist/tools/internal-tools/constants.cjs +2 -1
- package/dist/tools/internal-tools/constants.d.ts +1 -1
- package/dist/tools/internal-tools/constants.d.ts.map +1 -1
- package/dist/tools/internal-tools/constants.js +2 -1
- package/dist/tools/internal-tools/implementations/invoke-skill-tool.cjs +140 -0
- package/dist/tools/internal-tools/implementations/invoke-skill-tool.d.ts +24 -0
- package/dist/tools/internal-tools/implementations/invoke-skill-tool.d.ts.map +1 -0
- package/dist/tools/internal-tools/implementations/invoke-skill-tool.js +117 -0
- package/dist/tools/internal-tools/provider.cjs +15 -0
- package/dist/tools/internal-tools/provider.d.ts +15 -1
- package/dist/tools/internal-tools/provider.d.ts.map +1 -1
- package/dist/tools/internal-tools/provider.js +15 -0
- package/dist/tools/internal-tools/registry.cjs +6 -0
- package/dist/tools/internal-tools/registry.d.ts +35 -1
- package/dist/tools/internal-tools/registry.d.ts.map +1 -1
- package/dist/tools/internal-tools/registry.js +6 -0
- package/dist/tools/schemas.d.ts +1 -1
- package/dist/tools/schemas.d.ts.map +1 -1
- package/dist/tools/tool-call-metadata.cjs +75 -0
- package/dist/tools/tool-call-metadata.d.ts +16 -0
- package/dist/tools/tool-call-metadata.d.ts.map +1 -0
- package/dist/tools/tool-call-metadata.js +51 -0
- package/dist/tools/tool-manager.cjs +481 -103
- package/dist/tools/tool-manager.d.ts +131 -9
- package/dist/tools/tool-manager.d.ts.map +1 -1
- package/dist/tools/tool-manager.js +482 -104
- package/dist/utils/api-key-resolver.cjs +5 -2
- package/dist/utils/api-key-resolver.d.ts.map +1 -1
- package/dist/utils/api-key-resolver.js +5 -2
- package/dist/utils/env.cjs +49 -0
- package/dist/utils/env.d.ts +4 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +24 -0
- package/dist/utils/index.cjs +3 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/service-initializer.cjs +25 -7
- package/dist/utils/service-initializer.d.ts +24 -1
- package/dist/utils/service-initializer.d.ts.map +1 -1
- package/dist/utils/service-initializer.js +25 -7
- package/package.json +6 -2
- package/dist/llm/registry.cjs +0 -1631
- package/dist/llm/registry.d.ts.map +0 -1
- package/dist/llm/registry.js +0 -1586
|
@@ -125,7 +125,10 @@ class TurnExecutor {
|
|
|
125
125
|
contributorContext,
|
|
126
126
|
this.llmContext
|
|
127
127
|
);
|
|
128
|
-
const toolDefinitions = supportsTools ?
|
|
128
|
+
const toolDefinitions = supportsTools ? this.toolManager.filterToolsForSession(
|
|
129
|
+
await this.toolManager.getAllTools(),
|
|
130
|
+
this.sessionId
|
|
131
|
+
) : {};
|
|
129
132
|
let estimatedTokens = await this.contextManager.getEstimatedNextInputTokens(
|
|
130
133
|
prepared.systemPrompt,
|
|
131
134
|
prepared.preparedHistory,
|
|
@@ -390,7 +393,10 @@ class TurnExecutor {
|
|
|
390
393
|
* - StreamProcessor handles persistence via tool-result events
|
|
391
394
|
*/
|
|
392
395
|
async createTools() {
|
|
393
|
-
const tools =
|
|
396
|
+
const tools = this.toolManager.filterToolsForSession(
|
|
397
|
+
await this.toolManager.getAllTools(),
|
|
398
|
+
this.sessionId
|
|
399
|
+
);
|
|
394
400
|
return Object.fromEntries(
|
|
395
401
|
Object.entries(tools).map(([name, tool]) => [
|
|
396
402
|
name,
|
|
@@ -786,6 +792,33 @@ class TurnExecutor {
|
|
|
786
792
|
const headers = err.responseHeaders || {};
|
|
787
793
|
const retryAfter = headers["retry-after"] ? Number(headers["retry-after"]) : void 0;
|
|
788
794
|
const body = typeof err.responseBody === "string" ? err.responseBody : JSON.stringify(err.responseBody ?? "");
|
|
795
|
+
if (status === 402) {
|
|
796
|
+
let balance;
|
|
797
|
+
try {
|
|
798
|
+
const parsed = JSON.parse(body);
|
|
799
|
+
const msg = parsed?.error?.message || "";
|
|
800
|
+
const match = msg.match(/Balance:\s*\$?([\d.]+)/i);
|
|
801
|
+
if (match) {
|
|
802
|
+
balance = parseFloat(match[1]);
|
|
803
|
+
}
|
|
804
|
+
} catch {
|
|
805
|
+
}
|
|
806
|
+
return new DextoRuntimeError(
|
|
807
|
+
LLMErrorCode.INSUFFICIENT_CREDITS,
|
|
808
|
+
ErrorScope.LLM,
|
|
809
|
+
ErrorType.PAYMENT_REQUIRED,
|
|
810
|
+
`Insufficient Dexto credits${balance !== void 0 ? `. Balance: $${balance.toFixed(2)}` : ""}`,
|
|
811
|
+
{
|
|
812
|
+
sessionId: this.sessionId,
|
|
813
|
+
provider: this.llmContext.provider,
|
|
814
|
+
model: this.llmContext.model,
|
|
815
|
+
status,
|
|
816
|
+
balance,
|
|
817
|
+
body
|
|
818
|
+
},
|
|
819
|
+
"Run `dexto billing` to check your balance"
|
|
820
|
+
);
|
|
821
|
+
}
|
|
789
822
|
if (status === 429) {
|
|
790
823
|
return new DextoRuntimeError(
|
|
791
824
|
LLMErrorCode.RATE_LIMIT_EXCEEDED,
|
package/dist/llm/index.cjs
CHANGED
|
@@ -19,30 +19,41 @@ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "defau
|
|
|
19
19
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
20
|
var llm_exports = {};
|
|
21
21
|
__export(llm_exports, {
|
|
22
|
+
getLlmRegistryAutoUpdateStatus: () => import_auto_update.getLlmRegistryAutoUpdateStatus,
|
|
22
23
|
getOpenRouterModelContextLength: () => import_openrouter_model_registry.getOpenRouterModelContextLength,
|
|
23
24
|
getOpenRouterModelInfo: () => import_openrouter_model_registry.getOpenRouterModelInfo,
|
|
25
|
+
loadLlmRegistryCache: () => import_auto_update.loadLlmRegistryCache,
|
|
24
26
|
lookupOpenRouterModel: () => import_openrouter_model_registry.lookupOpenRouterModel,
|
|
25
|
-
|
|
27
|
+
refreshLlmRegistryCache: () => import_auto_update.refreshLlmRegistryCache,
|
|
28
|
+
refreshOpenRouterModelCache: () => import_openrouter_model_registry.refreshOpenRouterModelCache,
|
|
29
|
+
startLlmRegistryAutoUpdate: () => import_auto_update.startLlmRegistryAutoUpdate
|
|
26
30
|
});
|
|
27
31
|
module.exports = __toCommonJS(llm_exports);
|
|
28
32
|
__reExport(llm_exports, require("./errors.js"), module.exports);
|
|
29
33
|
__reExport(llm_exports, require("./error-codes.js"), module.exports);
|
|
30
|
-
__reExport(llm_exports, require("./registry.js"), module.exports);
|
|
34
|
+
__reExport(llm_exports, require("./registry/index.js"), module.exports);
|
|
35
|
+
__reExport(llm_exports, require("./curation.js"), module.exports);
|
|
31
36
|
__reExport(llm_exports, require("./validation.js"), module.exports);
|
|
32
37
|
__reExport(llm_exports, require("./types.js"), module.exports);
|
|
33
38
|
__reExport(llm_exports, require("./services/index.js"), module.exports);
|
|
34
39
|
__reExport(llm_exports, require("./schemas.js"), module.exports);
|
|
35
40
|
var import_openrouter_model_registry = require("./providers/openrouter-model-registry.js");
|
|
41
|
+
var import_auto_update = require("./registry/auto-update.js");
|
|
36
42
|
__reExport(llm_exports, require("./providers/local/index.js"), module.exports);
|
|
37
43
|
// Annotate the CommonJS export names for ESM import in node:
|
|
38
44
|
0 && (module.exports = {
|
|
45
|
+
getLlmRegistryAutoUpdateStatus,
|
|
39
46
|
getOpenRouterModelContextLength,
|
|
40
47
|
getOpenRouterModelInfo,
|
|
48
|
+
loadLlmRegistryCache,
|
|
41
49
|
lookupOpenRouterModel,
|
|
50
|
+
refreshLlmRegistryCache,
|
|
42
51
|
refreshOpenRouterModelCache,
|
|
52
|
+
startLlmRegistryAutoUpdate,
|
|
43
53
|
...require("./errors.js"),
|
|
44
54
|
...require("./error-codes.js"),
|
|
45
|
-
...require("./registry.js"),
|
|
55
|
+
...require("./registry/index.js"),
|
|
56
|
+
...require("./curation.js"),
|
|
46
57
|
...require("./validation.js"),
|
|
47
58
|
...require("./types.js"),
|
|
48
59
|
...require("./services/index.js"),
|
package/dist/llm/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
export * from './errors.js';
|
|
2
2
|
export * from './error-codes.js';
|
|
3
|
-
export * from './registry.js';
|
|
3
|
+
export * from './registry/index.js';
|
|
4
|
+
export * from './curation.js';
|
|
4
5
|
export * from './validation.js';
|
|
5
6
|
export * from './types.js';
|
|
6
7
|
export * from './services/index.js';
|
|
7
8
|
export * from './schemas.js';
|
|
8
9
|
export { lookupOpenRouterModel, refreshOpenRouterModelCache, getOpenRouterModelContextLength, getOpenRouterModelInfo, type LookupStatus, type OpenRouterModelInfo, } from './providers/openrouter-model-registry.js';
|
|
10
|
+
export { startLlmRegistryAutoUpdate, refreshLlmRegistryCache, loadLlmRegistryCache, getLlmRegistryAutoUpdateStatus, type LlmRegistryAutoUpdateStatus, } from './registry/auto-update.js';
|
|
9
11
|
export * from './providers/local/index.js';
|
|
10
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/llm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,OAAO,EACH,qBAAqB,EACrB,2BAA2B,EAC3B,+BAA+B,EAC/B,sBAAsB,EACtB,KAAK,YAAY,EACjB,KAAK,mBAAmB,GAC3B,MAAM,0CAA0C,CAAC;AAGlD,cAAc,4BAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,OAAO,EACH,qBAAqB,EACrB,2BAA2B,EAC3B,+BAA+B,EAC/B,sBAAsB,EACtB,KAAK,YAAY,EACjB,KAAK,mBAAmB,GAC3B,MAAM,0CAA0C,CAAC;AAGlD,OAAO,EACH,0BAA0B,EAC1B,uBAAuB,EACvB,oBAAoB,EACpB,8BAA8B,EAC9B,KAAK,2BAA2B,GACnC,MAAM,2BAA2B,CAAC;AAGnC,cAAc,4BAA4B,CAAC"}
|
package/dist/llm/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import "../chunk-PTJYTZNU.js";
|
|
2
2
|
export * from "./errors.js";
|
|
3
3
|
export * from "./error-codes.js";
|
|
4
|
-
export * from "./registry.js";
|
|
4
|
+
export * from "./registry/index.js";
|
|
5
|
+
export * from "./curation.js";
|
|
5
6
|
export * from "./validation.js";
|
|
6
7
|
export * from "./types.js";
|
|
7
8
|
export * from "./services/index.js";
|
|
@@ -12,10 +13,20 @@ import {
|
|
|
12
13
|
getOpenRouterModelContextLength,
|
|
13
14
|
getOpenRouterModelInfo
|
|
14
15
|
} from "./providers/openrouter-model-registry.js";
|
|
16
|
+
import {
|
|
17
|
+
startLlmRegistryAutoUpdate,
|
|
18
|
+
refreshLlmRegistryCache,
|
|
19
|
+
loadLlmRegistryCache,
|
|
20
|
+
getLlmRegistryAutoUpdateStatus
|
|
21
|
+
} from "./registry/auto-update.js";
|
|
15
22
|
export * from "./providers/local/index.js";
|
|
16
23
|
export {
|
|
24
|
+
getLlmRegistryAutoUpdateStatus,
|
|
17
25
|
getOpenRouterModelContextLength,
|
|
18
26
|
getOpenRouterModelInfo,
|
|
27
|
+
loadLlmRegistryCache,
|
|
19
28
|
lookupOpenRouterModel,
|
|
20
|
-
|
|
29
|
+
refreshLlmRegistryCache,
|
|
30
|
+
refreshOpenRouterModelCache,
|
|
31
|
+
startLlmRegistryAutoUpdate
|
|
21
32
|
};
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var auto_update_exports = {};
|
|
30
|
+
__export(auto_update_exports, {
|
|
31
|
+
getLlmRegistryAutoUpdateStatus: () => getLlmRegistryAutoUpdateStatus,
|
|
32
|
+
loadLlmRegistryCache: () => loadLlmRegistryCache,
|
|
33
|
+
refreshLlmRegistryCache: () => refreshLlmRegistryCache,
|
|
34
|
+
startLlmRegistryAutoUpdate: () => startLlmRegistryAutoUpdate
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(auto_update_exports);
|
|
37
|
+
var import_node_fs = require("node:fs");
|
|
38
|
+
var import_node_fs2 = require("node:fs");
|
|
39
|
+
var import_node_path = __toESM(require("node:path"), 1);
|
|
40
|
+
var import_path = require("../../utils/path.js");
|
|
41
|
+
var import_logger = require("../../logger/logger.js");
|
|
42
|
+
var import_types = require("../types.js");
|
|
43
|
+
var import_index = require("./index.js");
|
|
44
|
+
var import_sync = require("./sync.js");
|
|
45
|
+
const CACHE_SUBDIR = "cache";
|
|
46
|
+
const CACHE_FILENAME = "llm-registry-models.json";
|
|
47
|
+
const CACHE_SCHEMA_VERSION = 1;
|
|
48
|
+
const DEFAULT_TTL_MS = 1e3 * 60 * 60;
|
|
49
|
+
const MIN_REFRESH_INTERVAL_MS = 1e3 * 60 * 5;
|
|
50
|
+
const UPDATABLE_PROVIDERS = [
|
|
51
|
+
"openai",
|
|
52
|
+
"anthropic",
|
|
53
|
+
"google",
|
|
54
|
+
"groq",
|
|
55
|
+
"xai",
|
|
56
|
+
"cohere",
|
|
57
|
+
"minimax",
|
|
58
|
+
"glm",
|
|
59
|
+
"vertex",
|
|
60
|
+
"bedrock"
|
|
61
|
+
];
|
|
62
|
+
function truthyEnv(name) {
|
|
63
|
+
const v = process.env[name];
|
|
64
|
+
if (!v) return false;
|
|
65
|
+
return v === "1" || v === "true" || v === "yes" || v === "on";
|
|
66
|
+
}
|
|
67
|
+
function getTtlMs() {
|
|
68
|
+
const raw = process.env.DEXTO_LLM_REGISTRY_TTL_MS;
|
|
69
|
+
if (!raw) return DEFAULT_TTL_MS;
|
|
70
|
+
const n = Number(raw);
|
|
71
|
+
return Number.isFinite(n) && n > 0 ? n : DEFAULT_TTL_MS;
|
|
72
|
+
}
|
|
73
|
+
function getCachePath() {
|
|
74
|
+
return (0, import_path.getDextoGlobalPath)(CACHE_SUBDIR, CACHE_FILENAME);
|
|
75
|
+
}
|
|
76
|
+
function isModelInfo(value) {
|
|
77
|
+
if (typeof value !== "object" || value === null) return false;
|
|
78
|
+
const name = value.name;
|
|
79
|
+
return typeof name === "string" && name.trim() !== "";
|
|
80
|
+
}
|
|
81
|
+
function applyModelsByProvider(modelsByProvider) {
|
|
82
|
+
for (const provider of UPDATABLE_PROVIDERS) {
|
|
83
|
+
const incoming = modelsByProvider[provider] ?? [];
|
|
84
|
+
const existing = import_index.LLM_REGISTRY[provider].models ?? [];
|
|
85
|
+
const incomingByName = /* @__PURE__ */ new Map();
|
|
86
|
+
for (const m of incoming) {
|
|
87
|
+
incomingByName.set(m.name.toLowerCase(), m);
|
|
88
|
+
}
|
|
89
|
+
const existingDefault = existing.find((m) => m.default)?.name.toLowerCase();
|
|
90
|
+
const incomingDefault = incoming.find((m) => m.default)?.name.toLowerCase();
|
|
91
|
+
const merged = [];
|
|
92
|
+
const seen = /* @__PURE__ */ new Set();
|
|
93
|
+
for (const m of existing) {
|
|
94
|
+
const key = m.name.toLowerCase();
|
|
95
|
+
const updated = incomingByName.get(key);
|
|
96
|
+
if (!updated) {
|
|
97
|
+
merged.push(m);
|
|
98
|
+
} else {
|
|
99
|
+
const name = updated.name ?? m.name;
|
|
100
|
+
const maxInputTokens = typeof updated.maxInputTokens === "number" && updated.maxInputTokens > 0 ? updated.maxInputTokens : m.maxInputTokens;
|
|
101
|
+
const supportedFileTypes = Array.isArray(updated.supportedFileTypes) ? updated.supportedFileTypes : m.supportedFileTypes;
|
|
102
|
+
const displayName = updated.displayName ?? m.displayName;
|
|
103
|
+
const pricing = updated.pricing ?? m.pricing;
|
|
104
|
+
merged.push({
|
|
105
|
+
name,
|
|
106
|
+
maxInputTokens,
|
|
107
|
+
supportedFileTypes,
|
|
108
|
+
...displayName ? { displayName } : {},
|
|
109
|
+
...pricing ? { pricing } : {}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
seen.add(key);
|
|
113
|
+
}
|
|
114
|
+
const newModels = incoming.filter((m) => !seen.has(m.name.toLowerCase()));
|
|
115
|
+
newModels.sort((a, b) => a.name.localeCompare(b.name));
|
|
116
|
+
merged.push(...newModels);
|
|
117
|
+
const chosenDefault = incomingDefault ?? existingDefault ?? merged[0]?.name.toLowerCase();
|
|
118
|
+
const finalMerged = merged.map((m) => {
|
|
119
|
+
const copy = { ...m };
|
|
120
|
+
delete copy.default;
|
|
121
|
+
return copy;
|
|
122
|
+
});
|
|
123
|
+
if (chosenDefault) {
|
|
124
|
+
const idx = finalMerged.findIndex((m) => m.name.toLowerCase() === chosenDefault);
|
|
125
|
+
if (idx >= 0) {
|
|
126
|
+
finalMerged[idx] = { ...finalMerged[idx], default: true };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
import_index.LLM_REGISTRY[provider].models = finalMerged;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function normalizeModelsByProvider(raw) {
|
|
133
|
+
const out = {};
|
|
134
|
+
for (const p of import_types.LLM_PROVIDERS) {
|
|
135
|
+
const value = raw[p];
|
|
136
|
+
out[p] = Array.isArray(value) ? value.filter(isModelInfo) : [];
|
|
137
|
+
}
|
|
138
|
+
return out;
|
|
139
|
+
}
|
|
140
|
+
function tryLoadCacheFromDisk(log) {
|
|
141
|
+
const cachePath = getCachePath();
|
|
142
|
+
if (!(0, import_node_fs2.existsSync)(cachePath)) return null;
|
|
143
|
+
try {
|
|
144
|
+
const text = (0, import_node_fs2.readFileSync)(cachePath, "utf-8");
|
|
145
|
+
const parsed = JSON.parse(text);
|
|
146
|
+
if (parsed.schemaVersion !== CACHE_SCHEMA_VERSION) return null;
|
|
147
|
+
if (!parsed.fetchedAt || typeof parsed.fetchedAt !== "string") return null;
|
|
148
|
+
if (!parsed.modelsByProvider || typeof parsed.modelsByProvider !== "object") return null;
|
|
149
|
+
const fetchedAt = Date.parse(parsed.fetchedAt);
|
|
150
|
+
if (!Number.isFinite(fetchedAt)) return null;
|
|
151
|
+
const modelsByProvider = normalizeModelsByProvider(
|
|
152
|
+
parsed.modelsByProvider
|
|
153
|
+
);
|
|
154
|
+
return { fetchedAt, modelsByProvider };
|
|
155
|
+
} catch (e) {
|
|
156
|
+
log?.warn?.(
|
|
157
|
+
`Failed to load LLM registry cache (${cachePath}): ${e instanceof Error ? e.message : String(e)}`
|
|
158
|
+
);
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
let refreshPromise = null;
|
|
163
|
+
let lastRefreshAttemptAt = null;
|
|
164
|
+
let lastFetchedAt = null;
|
|
165
|
+
let lastSource = "snapshot";
|
|
166
|
+
let autoRefreshStarted = false;
|
|
167
|
+
function isFresh(now, fetchedAt, ttlMs) {
|
|
168
|
+
return now - fetchedAt < ttlMs;
|
|
169
|
+
}
|
|
170
|
+
function getLlmRegistryAutoUpdateStatus() {
|
|
171
|
+
const cachePath = getCachePath();
|
|
172
|
+
const fetchedAt = lastFetchedAt ? new Date(lastFetchedAt) : null;
|
|
173
|
+
const now = Date.now();
|
|
174
|
+
return {
|
|
175
|
+
cachePath,
|
|
176
|
+
lastFetchedAt: fetchedAt,
|
|
177
|
+
isFresh: lastFetchedAt ? isFresh(now, lastFetchedAt, getTtlMs()) : false,
|
|
178
|
+
source: lastSource
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function loadLlmRegistryCache(options) {
|
|
182
|
+
const cache = tryLoadCacheFromDisk(options?.logger);
|
|
183
|
+
if (!cache) return false;
|
|
184
|
+
applyModelsByProvider(cache.modelsByProvider);
|
|
185
|
+
lastFetchedAt = cache.fetchedAt;
|
|
186
|
+
lastSource = "cache";
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
async function writeCacheFile(cachePath, modelsByProvider) {
|
|
190
|
+
await import_node_fs.promises.mkdir(import_node_path.default.dirname(cachePath), { recursive: true });
|
|
191
|
+
const payload = {
|
|
192
|
+
schemaVersion: CACHE_SCHEMA_VERSION,
|
|
193
|
+
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
194
|
+
modelsByProvider
|
|
195
|
+
};
|
|
196
|
+
const tmpPath = `${cachePath}.tmp`;
|
|
197
|
+
await import_node_fs.promises.writeFile(tmpPath, JSON.stringify(payload), "utf-8");
|
|
198
|
+
await import_node_fs.promises.rename(tmpPath, cachePath);
|
|
199
|
+
}
|
|
200
|
+
async function refreshLlmRegistryCache(options) {
|
|
201
|
+
if (truthyEnv("DEXTO_LLM_REGISTRY_DISABLE_FETCH") || !options?.allowInTests && (process.env.NODE_ENV === "test" || truthyEnv("VITEST"))) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (refreshPromise && !options?.force) {
|
|
205
|
+
await refreshPromise;
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const now = Date.now();
|
|
209
|
+
if (!options?.force && lastRefreshAttemptAt && now - lastRefreshAttemptAt < MIN_REFRESH_INTERVAL_MS) {
|
|
210
|
+
if (refreshPromise) await refreshPromise;
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
lastRefreshAttemptAt = now;
|
|
214
|
+
const log = options?.logger ?? import_logger.logger;
|
|
215
|
+
refreshPromise = (async () => {
|
|
216
|
+
const modelsByProvider = await (0, import_sync.buildModelsByProviderFromRemote)({
|
|
217
|
+
userAgent: "dexto-llm-registry",
|
|
218
|
+
timeoutMs: 3e4
|
|
219
|
+
});
|
|
220
|
+
const cachePath = getCachePath();
|
|
221
|
+
await writeCacheFile(cachePath, modelsByProvider);
|
|
222
|
+
applyModelsByProvider(modelsByProvider);
|
|
223
|
+
lastFetchedAt = Date.now();
|
|
224
|
+
lastSource = "remote";
|
|
225
|
+
log?.debug?.(`Refreshed LLM registry cache (${cachePath})`);
|
|
226
|
+
})().catch((e) => {
|
|
227
|
+
log?.warn?.(
|
|
228
|
+
`Failed to refresh LLM registry cache: ${e instanceof Error ? e.message : String(e)}`
|
|
229
|
+
);
|
|
230
|
+
}).finally(() => {
|
|
231
|
+
refreshPromise = null;
|
|
232
|
+
});
|
|
233
|
+
await refreshPromise;
|
|
234
|
+
}
|
|
235
|
+
function startLlmRegistryAutoUpdate(options) {
|
|
236
|
+
if (autoRefreshStarted) return;
|
|
237
|
+
autoRefreshStarted = true;
|
|
238
|
+
const log = options?.logger ?? import_logger.logger;
|
|
239
|
+
const loaded = loadLlmRegistryCache({ logger: log });
|
|
240
|
+
if (loaded) {
|
|
241
|
+
log?.debug?.(`Loaded LLM registry cache from disk (${getCachePath()})`);
|
|
242
|
+
}
|
|
243
|
+
if (options?.refreshOnStart !== false) {
|
|
244
|
+
void refreshLlmRegistryCache({ logger: log });
|
|
245
|
+
}
|
|
246
|
+
const timer = setInterval(
|
|
247
|
+
() => {
|
|
248
|
+
const ttlMs = getTtlMs();
|
|
249
|
+
const now = Date.now();
|
|
250
|
+
if (lastFetchedAt && isFresh(now, lastFetchedAt, ttlMs)) return;
|
|
251
|
+
void refreshLlmRegistryCache({ logger: log });
|
|
252
|
+
},
|
|
253
|
+
Math.min(getTtlMs(), DEFAULT_TTL_MS)
|
|
254
|
+
);
|
|
255
|
+
timer.unref?.();
|
|
256
|
+
}
|
|
257
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
258
|
+
0 && (module.exports = {
|
|
259
|
+
getLlmRegistryAutoUpdateStatus,
|
|
260
|
+
loadLlmRegistryCache,
|
|
261
|
+
refreshLlmRegistryCache,
|
|
262
|
+
startLlmRegistryAutoUpdate
|
|
263
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { IDextoLogger } from '../../logger/v2/types.js';
|
|
2
|
+
type LogLike = Pick<IDextoLogger, 'debug' | 'info' | 'warn' | 'error'>;
|
|
3
|
+
export type LlmRegistryAutoUpdateStatus = {
|
|
4
|
+
cachePath: string;
|
|
5
|
+
lastFetchedAt: Date | null;
|
|
6
|
+
isFresh: boolean;
|
|
7
|
+
source: 'snapshot' | 'cache' | 'remote';
|
|
8
|
+
};
|
|
9
|
+
export declare function getLlmRegistryAutoUpdateStatus(): LlmRegistryAutoUpdateStatus;
|
|
10
|
+
export declare function loadLlmRegistryCache(options?: {
|
|
11
|
+
logger?: LogLike;
|
|
12
|
+
}): boolean;
|
|
13
|
+
export declare function refreshLlmRegistryCache(options?: {
|
|
14
|
+
logger?: LogLike;
|
|
15
|
+
force?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Test-only escape hatch to validate refresh behavior with mocks while keeping
|
|
18
|
+
* network fetch disabled by default in CI/unit tests.
|
|
19
|
+
*/
|
|
20
|
+
allowInTests?: boolean;
|
|
21
|
+
}): Promise<void>;
|
|
22
|
+
export declare function startLlmRegistryAutoUpdate(options?: {
|
|
23
|
+
logger?: LogLike;
|
|
24
|
+
refreshOnStart?: boolean;
|
|
25
|
+
}): void;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=auto-update.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-update.d.ts","sourceRoot":"","sources":["../../../src/llm/registry/auto-update.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAO7D,KAAK,OAAO,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAuKvE,MAAM,MAAM,2BAA2B,GAAG;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,IAAI,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;CAC3C,CAAC;AAMF,wBAAgB,8BAA8B,IAAI,2BAA2B,CAU5E;AAED,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAO5E;AAiBD,wBAAsB,uBAAuB,CAAC,OAAO,CAAC,EAAE;IACpD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDhB;AAED,wBAAgB,0BAA0B,CAAC,OAAO,CAAC,EAAE;IACjD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG,IAAI,CA6BP"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import "../../chunk-PTJYTZNU.js";
|
|
2
|
+
import { promises as fs } from "node:fs";
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { getDextoGlobalPath } from "../../utils/path.js";
|
|
6
|
+
import { logger as defaultLogger } from "../../logger/logger.js";
|
|
7
|
+
import { LLM_PROVIDERS } from "../types.js";
|
|
8
|
+
import { LLM_REGISTRY } from "./index.js";
|
|
9
|
+
import { buildModelsByProviderFromRemote } from "./sync.js";
|
|
10
|
+
const CACHE_SUBDIR = "cache";
|
|
11
|
+
const CACHE_FILENAME = "llm-registry-models.json";
|
|
12
|
+
const CACHE_SCHEMA_VERSION = 1;
|
|
13
|
+
const DEFAULT_TTL_MS = 1e3 * 60 * 60;
|
|
14
|
+
const MIN_REFRESH_INTERVAL_MS = 1e3 * 60 * 5;
|
|
15
|
+
const UPDATABLE_PROVIDERS = [
|
|
16
|
+
"openai",
|
|
17
|
+
"anthropic",
|
|
18
|
+
"google",
|
|
19
|
+
"groq",
|
|
20
|
+
"xai",
|
|
21
|
+
"cohere",
|
|
22
|
+
"minimax",
|
|
23
|
+
"glm",
|
|
24
|
+
"vertex",
|
|
25
|
+
"bedrock"
|
|
26
|
+
];
|
|
27
|
+
function truthyEnv(name) {
|
|
28
|
+
const v = process.env[name];
|
|
29
|
+
if (!v) return false;
|
|
30
|
+
return v === "1" || v === "true" || v === "yes" || v === "on";
|
|
31
|
+
}
|
|
32
|
+
function getTtlMs() {
|
|
33
|
+
const raw = process.env.DEXTO_LLM_REGISTRY_TTL_MS;
|
|
34
|
+
if (!raw) return DEFAULT_TTL_MS;
|
|
35
|
+
const n = Number(raw);
|
|
36
|
+
return Number.isFinite(n) && n > 0 ? n : DEFAULT_TTL_MS;
|
|
37
|
+
}
|
|
38
|
+
function getCachePath() {
|
|
39
|
+
return getDextoGlobalPath(CACHE_SUBDIR, CACHE_FILENAME);
|
|
40
|
+
}
|
|
41
|
+
function isModelInfo(value) {
|
|
42
|
+
if (typeof value !== "object" || value === null) return false;
|
|
43
|
+
const name = value.name;
|
|
44
|
+
return typeof name === "string" && name.trim() !== "";
|
|
45
|
+
}
|
|
46
|
+
function applyModelsByProvider(modelsByProvider) {
|
|
47
|
+
for (const provider of UPDATABLE_PROVIDERS) {
|
|
48
|
+
const incoming = modelsByProvider[provider] ?? [];
|
|
49
|
+
const existing = LLM_REGISTRY[provider].models ?? [];
|
|
50
|
+
const incomingByName = /* @__PURE__ */ new Map();
|
|
51
|
+
for (const m of incoming) {
|
|
52
|
+
incomingByName.set(m.name.toLowerCase(), m);
|
|
53
|
+
}
|
|
54
|
+
const existingDefault = existing.find((m) => m.default)?.name.toLowerCase();
|
|
55
|
+
const incomingDefault = incoming.find((m) => m.default)?.name.toLowerCase();
|
|
56
|
+
const merged = [];
|
|
57
|
+
const seen = /* @__PURE__ */ new Set();
|
|
58
|
+
for (const m of existing) {
|
|
59
|
+
const key = m.name.toLowerCase();
|
|
60
|
+
const updated = incomingByName.get(key);
|
|
61
|
+
if (!updated) {
|
|
62
|
+
merged.push(m);
|
|
63
|
+
} else {
|
|
64
|
+
const name = updated.name ?? m.name;
|
|
65
|
+
const maxInputTokens = typeof updated.maxInputTokens === "number" && updated.maxInputTokens > 0 ? updated.maxInputTokens : m.maxInputTokens;
|
|
66
|
+
const supportedFileTypes = Array.isArray(updated.supportedFileTypes) ? updated.supportedFileTypes : m.supportedFileTypes;
|
|
67
|
+
const displayName = updated.displayName ?? m.displayName;
|
|
68
|
+
const pricing = updated.pricing ?? m.pricing;
|
|
69
|
+
merged.push({
|
|
70
|
+
name,
|
|
71
|
+
maxInputTokens,
|
|
72
|
+
supportedFileTypes,
|
|
73
|
+
...displayName ? { displayName } : {},
|
|
74
|
+
...pricing ? { pricing } : {}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
seen.add(key);
|
|
78
|
+
}
|
|
79
|
+
const newModels = incoming.filter((m) => !seen.has(m.name.toLowerCase()));
|
|
80
|
+
newModels.sort((a, b) => a.name.localeCompare(b.name));
|
|
81
|
+
merged.push(...newModels);
|
|
82
|
+
const chosenDefault = incomingDefault ?? existingDefault ?? merged[0]?.name.toLowerCase();
|
|
83
|
+
const finalMerged = merged.map((m) => {
|
|
84
|
+
const copy = { ...m };
|
|
85
|
+
delete copy.default;
|
|
86
|
+
return copy;
|
|
87
|
+
});
|
|
88
|
+
if (chosenDefault) {
|
|
89
|
+
const idx = finalMerged.findIndex((m) => m.name.toLowerCase() === chosenDefault);
|
|
90
|
+
if (idx >= 0) {
|
|
91
|
+
finalMerged[idx] = { ...finalMerged[idx], default: true };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
LLM_REGISTRY[provider].models = finalMerged;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function normalizeModelsByProvider(raw) {
|
|
98
|
+
const out = {};
|
|
99
|
+
for (const p of LLM_PROVIDERS) {
|
|
100
|
+
const value = raw[p];
|
|
101
|
+
out[p] = Array.isArray(value) ? value.filter(isModelInfo) : [];
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
function tryLoadCacheFromDisk(log) {
|
|
106
|
+
const cachePath = getCachePath();
|
|
107
|
+
if (!existsSync(cachePath)) return null;
|
|
108
|
+
try {
|
|
109
|
+
const text = readFileSync(cachePath, "utf-8");
|
|
110
|
+
const parsed = JSON.parse(text);
|
|
111
|
+
if (parsed.schemaVersion !== CACHE_SCHEMA_VERSION) return null;
|
|
112
|
+
if (!parsed.fetchedAt || typeof parsed.fetchedAt !== "string") return null;
|
|
113
|
+
if (!parsed.modelsByProvider || typeof parsed.modelsByProvider !== "object") return null;
|
|
114
|
+
const fetchedAt = Date.parse(parsed.fetchedAt);
|
|
115
|
+
if (!Number.isFinite(fetchedAt)) return null;
|
|
116
|
+
const modelsByProvider = normalizeModelsByProvider(
|
|
117
|
+
parsed.modelsByProvider
|
|
118
|
+
);
|
|
119
|
+
return { fetchedAt, modelsByProvider };
|
|
120
|
+
} catch (e) {
|
|
121
|
+
log?.warn?.(
|
|
122
|
+
`Failed to load LLM registry cache (${cachePath}): ${e instanceof Error ? e.message : String(e)}`
|
|
123
|
+
);
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
let refreshPromise = null;
|
|
128
|
+
let lastRefreshAttemptAt = null;
|
|
129
|
+
let lastFetchedAt = null;
|
|
130
|
+
let lastSource = "snapshot";
|
|
131
|
+
let autoRefreshStarted = false;
|
|
132
|
+
function isFresh(now, fetchedAt, ttlMs) {
|
|
133
|
+
return now - fetchedAt < ttlMs;
|
|
134
|
+
}
|
|
135
|
+
function getLlmRegistryAutoUpdateStatus() {
|
|
136
|
+
const cachePath = getCachePath();
|
|
137
|
+
const fetchedAt = lastFetchedAt ? new Date(lastFetchedAt) : null;
|
|
138
|
+
const now = Date.now();
|
|
139
|
+
return {
|
|
140
|
+
cachePath,
|
|
141
|
+
lastFetchedAt: fetchedAt,
|
|
142
|
+
isFresh: lastFetchedAt ? isFresh(now, lastFetchedAt, getTtlMs()) : false,
|
|
143
|
+
source: lastSource
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function loadLlmRegistryCache(options) {
|
|
147
|
+
const cache = tryLoadCacheFromDisk(options?.logger);
|
|
148
|
+
if (!cache) return false;
|
|
149
|
+
applyModelsByProvider(cache.modelsByProvider);
|
|
150
|
+
lastFetchedAt = cache.fetchedAt;
|
|
151
|
+
lastSource = "cache";
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
async function writeCacheFile(cachePath, modelsByProvider) {
|
|
155
|
+
await fs.mkdir(path.dirname(cachePath), { recursive: true });
|
|
156
|
+
const payload = {
|
|
157
|
+
schemaVersion: CACHE_SCHEMA_VERSION,
|
|
158
|
+
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
159
|
+
modelsByProvider
|
|
160
|
+
};
|
|
161
|
+
const tmpPath = `${cachePath}.tmp`;
|
|
162
|
+
await fs.writeFile(tmpPath, JSON.stringify(payload), "utf-8");
|
|
163
|
+
await fs.rename(tmpPath, cachePath);
|
|
164
|
+
}
|
|
165
|
+
async function refreshLlmRegistryCache(options) {
|
|
166
|
+
if (truthyEnv("DEXTO_LLM_REGISTRY_DISABLE_FETCH") || !options?.allowInTests && (process.env.NODE_ENV === "test" || truthyEnv("VITEST"))) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (refreshPromise && !options?.force) {
|
|
170
|
+
await refreshPromise;
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const now = Date.now();
|
|
174
|
+
if (!options?.force && lastRefreshAttemptAt && now - lastRefreshAttemptAt < MIN_REFRESH_INTERVAL_MS) {
|
|
175
|
+
if (refreshPromise) await refreshPromise;
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
lastRefreshAttemptAt = now;
|
|
179
|
+
const log = options?.logger ?? defaultLogger;
|
|
180
|
+
refreshPromise = (async () => {
|
|
181
|
+
const modelsByProvider = await buildModelsByProviderFromRemote({
|
|
182
|
+
userAgent: "dexto-llm-registry",
|
|
183
|
+
timeoutMs: 3e4
|
|
184
|
+
});
|
|
185
|
+
const cachePath = getCachePath();
|
|
186
|
+
await writeCacheFile(cachePath, modelsByProvider);
|
|
187
|
+
applyModelsByProvider(modelsByProvider);
|
|
188
|
+
lastFetchedAt = Date.now();
|
|
189
|
+
lastSource = "remote";
|
|
190
|
+
log?.debug?.(`Refreshed LLM registry cache (${cachePath})`);
|
|
191
|
+
})().catch((e) => {
|
|
192
|
+
log?.warn?.(
|
|
193
|
+
`Failed to refresh LLM registry cache: ${e instanceof Error ? e.message : String(e)}`
|
|
194
|
+
);
|
|
195
|
+
}).finally(() => {
|
|
196
|
+
refreshPromise = null;
|
|
197
|
+
});
|
|
198
|
+
await refreshPromise;
|
|
199
|
+
}
|
|
200
|
+
function startLlmRegistryAutoUpdate(options) {
|
|
201
|
+
if (autoRefreshStarted) return;
|
|
202
|
+
autoRefreshStarted = true;
|
|
203
|
+
const log = options?.logger ?? defaultLogger;
|
|
204
|
+
const loaded = loadLlmRegistryCache({ logger: log });
|
|
205
|
+
if (loaded) {
|
|
206
|
+
log?.debug?.(`Loaded LLM registry cache from disk (${getCachePath()})`);
|
|
207
|
+
}
|
|
208
|
+
if (options?.refreshOnStart !== false) {
|
|
209
|
+
void refreshLlmRegistryCache({ logger: log });
|
|
210
|
+
}
|
|
211
|
+
const timer = setInterval(
|
|
212
|
+
() => {
|
|
213
|
+
const ttlMs = getTtlMs();
|
|
214
|
+
const now = Date.now();
|
|
215
|
+
if (lastFetchedAt && isFresh(now, lastFetchedAt, ttlMs)) return;
|
|
216
|
+
void refreshLlmRegistryCache({ logger: log });
|
|
217
|
+
},
|
|
218
|
+
Math.min(getTtlMs(), DEFAULT_TTL_MS)
|
|
219
|
+
);
|
|
220
|
+
timer.unref?.();
|
|
221
|
+
}
|
|
222
|
+
export {
|
|
223
|
+
getLlmRegistryAutoUpdateStatus,
|
|
224
|
+
loadLlmRegistryCache,
|
|
225
|
+
refreshLlmRegistryCache,
|
|
226
|
+
startLlmRegistryAutoUpdate
|
|
227
|
+
};
|