manifest 5.37.0 → 5.38.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/backend/app.module.js +2 -0
- package/dist/backend/common/constants/cache.constants.js +2 -1
- package/dist/backend/model-discovery/provider-model-fetcher.service.js +30 -5
- package/dist/backend/public-stats/public-stats.controller.js +105 -0
- package/dist/backend/public-stats/public-stats.module.js +26 -0
- package/dist/backend/public-stats/public-stats.service.js +119 -0
- package/dist/backend/routing/proxy/chatgpt-adapter.js +81 -0
- package/dist/backend/routing/proxy/provider-client-converters.js +2 -1
- package/dist/backend/routing/proxy/provider-client.js +3 -0
- package/dist/backend/routing/proxy/proxy-response-handler.js +2 -2
- package/dist/backend/scoring/index.js +3 -11
- package/dist/openclaw.plugin.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -61,7 +61,7 @@ Dashboard opens at **http://127.0.0.1:2099**. The plugin starts an embedded serv
|
|
|
61
61
|
Run the full Manifest stack (app + PostgreSQL) with a single command:
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
|
-
curl -O https://raw.githubusercontent.com/mnfst/manifest/main/docker-compose.yml
|
|
64
|
+
curl -O https://raw.githubusercontent.com/mnfst/manifest/main/docker/docker-compose.yml
|
|
65
65
|
docker compose up -d
|
|
66
66
|
```
|
|
67
67
|
|
|
@@ -32,6 +32,7 @@ const routing_module_1 = require("./routing/routing.module");
|
|
|
32
32
|
const common_module_1 = require("./common/common.module");
|
|
33
33
|
const sse_module_1 = require("./sse/sse.module");
|
|
34
34
|
const github_module_1 = require("./github/github.module");
|
|
35
|
+
const public_stats_module_1 = require("./public-stats/public-stats.module");
|
|
35
36
|
const isLocalMode = process.env['MANIFEST_MODE'] === 'local';
|
|
36
37
|
const sessionGuardClass = isLocalMode ? local_auth_guard_1.LocalAuthGuard : session_guard_1.SessionGuard;
|
|
37
38
|
const frontendPath = (0, frontend_path_1.resolveFrontendDir)();
|
|
@@ -81,6 +82,7 @@ exports.AppModule = AppModule = __decorate([
|
|
|
81
82
|
routing_module_1.RoutingModule,
|
|
82
83
|
sse_module_1.SseModule,
|
|
83
84
|
github_module_1.GithubModule,
|
|
85
|
+
public_stats_module_1.PublicStatsModule,
|
|
84
86
|
],
|
|
85
87
|
providers: [
|
|
86
88
|
{ provide: core_1.APP_GUARD, useClass: sessionGuardClass },
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MODEL_PRICES_CACHE_TTL_MS = exports.AGENT_LIST_CACHE_TTL_MS = exports.DASHBOARD_CACHE_TTL_MS = void 0;
|
|
3
|
+
exports.PUBLIC_STATS_CACHE_TTL_MS = exports.MODEL_PRICES_CACHE_TTL_MS = exports.AGENT_LIST_CACHE_TTL_MS = exports.DASHBOARD_CACHE_TTL_MS = void 0;
|
|
4
4
|
exports.DASHBOARD_CACHE_TTL_MS = 30_000;
|
|
5
5
|
exports.AGENT_LIST_CACHE_TTL_MS = 60_000;
|
|
6
6
|
exports.MODEL_PRICES_CACHE_TTL_MS = 300_000;
|
|
7
|
+
exports.PUBLIC_STATS_CACHE_TTL_MS = 86_400_000;
|
|
7
8
|
//# sourceMappingURL=cache.constants.js.map
|
|
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
};
|
|
8
8
|
var ProviderModelFetcherService_1;
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.ProviderModelFetcherService = exports.PROVIDER_CONFIGS = exports.PROVIDER_NON_CHAT = exports.UNIVERSAL_NON_CHAT_RE = void 0;
|
|
10
|
+
exports.ProviderModelFetcherService = exports.PROVIDER_CONFIGS = exports.PROVIDER_BLOCKLIST = exports.PROVIDER_NON_CHAT = exports.UNIVERSAL_NON_CHAT_RE = void 0;
|
|
11
11
|
exports.filterNonChatModels = filterNonChatModels;
|
|
12
12
|
const common_1 = require("@nestjs/common");
|
|
13
13
|
const ollama_1 = require("../common/constants/ollama");
|
|
@@ -65,23 +65,48 @@ exports.UNIVERSAL_NON_CHAT_RE = /(?:embed|tts|whisper|dall-e|imagen|cogview|wanx
|
|
|
65
65
|
exports.PROVIDER_NON_CHAT = {
|
|
66
66
|
openai: /(?:moderation|davinci|babbage|^text-|realtime|-transcribe|^sora|^gpt-3\.5-turbo-instruct|audio|^chatgpt-image)/i,
|
|
67
67
|
'openai-subscription': /(?:moderation|davinci|babbage|^text-|realtime|-transcribe|^sora|audio|^chatgpt-image)/i,
|
|
68
|
-
gemini: /(?:^aqs-|nano-banana|^deep-research|computer-use|^lyria)/i,
|
|
69
|
-
mistral: /(?:^mistral-ocr|moderation|voxtral-.*-(?:transcribe|realtime))/i,
|
|
70
|
-
xai: /(?:imagine)/i,
|
|
68
|
+
gemini: /(?:^aqs-|nano-banana|^deep-research|computer-use|^lyria|^gemini-2\.0-flash-lite$|flash-lite-preview)/i,
|
|
69
|
+
mistral: /(?:^mistral-ocr|moderation|voxtral-.*-(?:transcribe|realtime)|^labs-)/i,
|
|
70
|
+
xai: /(?:imagine|multi-agent)/i,
|
|
71
|
+
};
|
|
72
|
+
exports.PROVIDER_BLOCKLIST = {
|
|
73
|
+
mistral: new Set([
|
|
74
|
+
'voxtral-mini-2602',
|
|
75
|
+
]),
|
|
76
|
+
zai: new Set([
|
|
77
|
+
'glm-5.1',
|
|
78
|
+
]),
|
|
71
79
|
};
|
|
72
80
|
function filterNonChatModels(models, configKey) {
|
|
73
81
|
const providerFilter = exports.PROVIDER_NON_CHAT[configKey];
|
|
82
|
+
const blocklist = exports.PROVIDER_BLOCKLIST[configKey];
|
|
74
83
|
return models.filter((m) => {
|
|
75
84
|
if (exports.UNIVERSAL_NON_CHAT_RE.test(m.id))
|
|
76
85
|
return false;
|
|
77
86
|
if (providerFilter && providerFilter.test(m.id))
|
|
78
87
|
return false;
|
|
88
|
+
if (blocklist && blocklist.has(m.id))
|
|
89
|
+
return false;
|
|
79
90
|
return true;
|
|
80
91
|
});
|
|
81
92
|
}
|
|
82
93
|
function bearerHeaders(key) {
|
|
83
94
|
return { Authorization: `Bearer ${key}` };
|
|
84
95
|
}
|
|
96
|
+
const parseMistral = createModelParser({
|
|
97
|
+
arrayKey: 'data',
|
|
98
|
+
filter: (entry) => {
|
|
99
|
+
if (typeof entry.id !== 'string' || entry.id.length === 0)
|
|
100
|
+
return false;
|
|
101
|
+
if (entry.deprecation != null)
|
|
102
|
+
return false;
|
|
103
|
+
if (entry.capabilities && entry.capabilities.completion_chat === false)
|
|
104
|
+
return false;
|
|
105
|
+
return true;
|
|
106
|
+
},
|
|
107
|
+
getId: (entry) => entry.id,
|
|
108
|
+
getDisplayName: (_entry, id) => id,
|
|
109
|
+
});
|
|
85
110
|
const parseAnthropic = createModelParser({
|
|
86
111
|
arrayKey: 'data',
|
|
87
112
|
filter: (entry) => typeof entry.id === 'string' && entry.type === 'model',
|
|
@@ -208,7 +233,7 @@ exports.PROVIDER_CONFIGS = {
|
|
|
208
233
|
mistral: {
|
|
209
234
|
endpoint: 'https://api.mistral.ai/v1/models',
|
|
210
235
|
buildHeaders: bearerHeaders,
|
|
211
|
-
parse:
|
|
236
|
+
parse: parseMistral,
|
|
212
237
|
},
|
|
213
238
|
moonshot: {
|
|
214
239
|
endpoint: 'https://api.moonshot.ai/v1/models',
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var PublicStatsController_1;
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.PublicStatsController = void 0;
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
const public_decorator_1 = require("../common/decorators/public.decorator");
|
|
16
|
+
const cache_constants_1 = require("../common/constants/cache.constants");
|
|
17
|
+
const public_stats_service_1 = require("./public-stats.service");
|
|
18
|
+
let cachedUsage = null;
|
|
19
|
+
let usageTimestamp = 0;
|
|
20
|
+
let usageInflight = null;
|
|
21
|
+
let cachedFree = null;
|
|
22
|
+
let freeTimestamp = 0;
|
|
23
|
+
let freeInflight = null;
|
|
24
|
+
let PublicStatsController = PublicStatsController_1 = class PublicStatsController {
|
|
25
|
+
service;
|
|
26
|
+
logger = new common_1.Logger(PublicStatsController_1.name);
|
|
27
|
+
constructor(service) {
|
|
28
|
+
this.service = service;
|
|
29
|
+
}
|
|
30
|
+
async getUsage() {
|
|
31
|
+
if (cachedUsage && Date.now() - usageTimestamp < cache_constants_1.PUBLIC_STATS_CACHE_TTL_MS) {
|
|
32
|
+
return cachedUsage;
|
|
33
|
+
}
|
|
34
|
+
if (!usageInflight) {
|
|
35
|
+
usageInflight = this.refreshUsage().finally(() => {
|
|
36
|
+
usageInflight = null;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return usageInflight;
|
|
40
|
+
}
|
|
41
|
+
async getFreeModels() {
|
|
42
|
+
if (cachedFree && Date.now() - freeTimestamp < cache_constants_1.PUBLIC_STATS_CACHE_TTL_MS) {
|
|
43
|
+
return cachedFree;
|
|
44
|
+
}
|
|
45
|
+
if (!freeInflight) {
|
|
46
|
+
freeInflight = this.refreshFreeModels().finally(() => {
|
|
47
|
+
freeInflight = null;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return freeInflight;
|
|
51
|
+
}
|
|
52
|
+
async refreshUsage() {
|
|
53
|
+
try {
|
|
54
|
+
const stats = await this.service.getUsageStats();
|
|
55
|
+
cachedUsage = {
|
|
56
|
+
total_messages: stats.total_messages,
|
|
57
|
+
top_models: stats.top_models,
|
|
58
|
+
cached_at: new Date().toISOString(),
|
|
59
|
+
};
|
|
60
|
+
usageTimestamp = Date.now();
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
64
|
+
this.logger.error(`Failed to fetch usage stats: ${msg}`);
|
|
65
|
+
}
|
|
66
|
+
return (cachedUsage ?? { total_messages: 0, top_models: [], cached_at: new Date().toISOString() });
|
|
67
|
+
}
|
|
68
|
+
async refreshFreeModels() {
|
|
69
|
+
try {
|
|
70
|
+
const stats = await this.service.getUsageStats();
|
|
71
|
+
const models = this.service.getFreeModels(stats.token_map);
|
|
72
|
+
cachedFree = {
|
|
73
|
+
models,
|
|
74
|
+
total_models: models.length,
|
|
75
|
+
cached_at: new Date().toISOString(),
|
|
76
|
+
};
|
|
77
|
+
freeTimestamp = Date.now();
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
81
|
+
this.logger.error(`Failed to fetch free models: ${msg}`);
|
|
82
|
+
}
|
|
83
|
+
return cachedFree ?? { models: [], total_models: 0, cached_at: new Date().toISOString() };
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
exports.PublicStatsController = PublicStatsController;
|
|
87
|
+
__decorate([
|
|
88
|
+
(0, public_decorator_1.Public)(),
|
|
89
|
+
(0, common_1.Get)('usage'),
|
|
90
|
+
__metadata("design:type", Function),
|
|
91
|
+
__metadata("design:paramtypes", []),
|
|
92
|
+
__metadata("design:returntype", Promise)
|
|
93
|
+
], PublicStatsController.prototype, "getUsage", null);
|
|
94
|
+
__decorate([
|
|
95
|
+
(0, public_decorator_1.Public)(),
|
|
96
|
+
(0, common_1.Get)('free-models'),
|
|
97
|
+
__metadata("design:type", Function),
|
|
98
|
+
__metadata("design:paramtypes", []),
|
|
99
|
+
__metadata("design:returntype", Promise)
|
|
100
|
+
], PublicStatsController.prototype, "getFreeModels", null);
|
|
101
|
+
exports.PublicStatsController = PublicStatsController = PublicStatsController_1 = __decorate([
|
|
102
|
+
(0, common_1.Controller)('api/v1/public'),
|
|
103
|
+
__metadata("design:paramtypes", [public_stats_service_1.PublicStatsService])
|
|
104
|
+
], PublicStatsController);
|
|
105
|
+
//# sourceMappingURL=public-stats.controller.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.PublicStatsModule = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const typeorm_1 = require("@nestjs/typeorm");
|
|
12
|
+
const agent_message_entity_1 = require("../entities/agent-message.entity");
|
|
13
|
+
const model_prices_module_1 = require("../model-prices/model-prices.module");
|
|
14
|
+
const public_stats_controller_1 = require("./public-stats.controller");
|
|
15
|
+
const public_stats_service_1 = require("./public-stats.service");
|
|
16
|
+
let PublicStatsModule = class PublicStatsModule {
|
|
17
|
+
};
|
|
18
|
+
exports.PublicStatsModule = PublicStatsModule;
|
|
19
|
+
exports.PublicStatsModule = PublicStatsModule = __decorate([
|
|
20
|
+
(0, common_1.Module)({
|
|
21
|
+
imports: [typeorm_1.TypeOrmModule.forFeature([agent_message_entity_1.AgentMessage]), model_prices_module_1.ModelPricesModule],
|
|
22
|
+
controllers: [public_stats_controller_1.PublicStatsController],
|
|
23
|
+
providers: [public_stats_service_1.PublicStatsService],
|
|
24
|
+
})
|
|
25
|
+
], PublicStatsModule);
|
|
26
|
+
//# sourceMappingURL=public-stats.module.js.map
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.PublicStatsService = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const typeorm_1 = require("@nestjs/typeorm");
|
|
18
|
+
const typeorm_2 = require("typeorm");
|
|
19
|
+
const agent_message_entity_1 = require("../entities/agent-message.entity");
|
|
20
|
+
const model_pricing_cache_service_1 = require("../model-prices/model-pricing-cache.service");
|
|
21
|
+
const sql_dialect_1 = require("../common/utils/sql-dialect");
|
|
22
|
+
const MAX_RESULTS = 10;
|
|
23
|
+
const EXCLUDED_PROVIDERS = new Set(['Unknown']);
|
|
24
|
+
function isCustomModel(model) {
|
|
25
|
+
return model.startsWith('custom:');
|
|
26
|
+
}
|
|
27
|
+
let PublicStatsService = class PublicStatsService {
|
|
28
|
+
messageRepo;
|
|
29
|
+
pricingCache;
|
|
30
|
+
constructor(messageRepo, pricingCache) {
|
|
31
|
+
this.messageRepo = messageRepo;
|
|
32
|
+
this.pricingCache = pricingCache;
|
|
33
|
+
}
|
|
34
|
+
async getUsageStats() {
|
|
35
|
+
const cutoff = (0, sql_dialect_1.computeCutoff)('7 days');
|
|
36
|
+
const [countRow, topRows, tokenRows] = await Promise.all([
|
|
37
|
+
this.messageRepo.createQueryBuilder('at').select('COUNT(*)', 'total').getRawOne(),
|
|
38
|
+
this.messageRepo
|
|
39
|
+
.createQueryBuilder('at')
|
|
40
|
+
.select('at.model', 'model')
|
|
41
|
+
.addSelect('COUNT(*)', 'usage_count')
|
|
42
|
+
.where('at.model IS NOT NULL')
|
|
43
|
+
.groupBy('at.model')
|
|
44
|
+
.orderBy('usage_count', 'DESC')
|
|
45
|
+
.getRawMany(),
|
|
46
|
+
this.messageRepo
|
|
47
|
+
.createQueryBuilder('at')
|
|
48
|
+
.select('at.model', 'model')
|
|
49
|
+
.addSelect('SUM(at.input_tokens + at.output_tokens)', 'tokens')
|
|
50
|
+
.where('at.model IS NOT NULL')
|
|
51
|
+
.andWhere('at.timestamp >= :cutoff', { cutoff })
|
|
52
|
+
.groupBy('at.model')
|
|
53
|
+
.getRawMany(),
|
|
54
|
+
]);
|
|
55
|
+
const tokenMap = new Map();
|
|
56
|
+
for (const r of tokenRows) {
|
|
57
|
+
tokenMap.set(r.model, Number(r.tokens ?? 0));
|
|
58
|
+
}
|
|
59
|
+
const eligible = [];
|
|
60
|
+
for (const r of topRows) {
|
|
61
|
+
const modelName = r.model;
|
|
62
|
+
if (isCustomModel(modelName))
|
|
63
|
+
continue;
|
|
64
|
+
const pricing = this.pricingCache.getByModel(modelName);
|
|
65
|
+
const provider = pricing?.provider || 'Unknown';
|
|
66
|
+
if (EXCLUDED_PROVIDERS.has(provider))
|
|
67
|
+
continue;
|
|
68
|
+
eligible.push({
|
|
69
|
+
model: modelName,
|
|
70
|
+
provider,
|
|
71
|
+
tokens_7d: tokenMap.get(modelName) ?? 0,
|
|
72
|
+
input_price_per_million: pricing?.input_price_per_token != null
|
|
73
|
+
? Number(pricing.input_price_per_token) * 1_000_000
|
|
74
|
+
: null,
|
|
75
|
+
output_price_per_million: pricing?.output_price_per_token != null
|
|
76
|
+
? Number(pricing.output_price_per_token) * 1_000_000
|
|
77
|
+
: null,
|
|
78
|
+
usage_rank: 0,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
eligible.sort((a, b) => b.tokens_7d - a.tokens_7d);
|
|
82
|
+
const topModels = eligible.slice(0, MAX_RESULTS);
|
|
83
|
+
topModels.forEach((m, i) => (m.usage_rank = i + 1));
|
|
84
|
+
return {
|
|
85
|
+
total_messages: Number(countRow?.total ?? 0),
|
|
86
|
+
top_models: topModels,
|
|
87
|
+
token_map: tokenMap,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
getFreeModels(tokenMap) {
|
|
91
|
+
return this.pricingCache
|
|
92
|
+
.getAll()
|
|
93
|
+
.filter((e) => {
|
|
94
|
+
if ((e.input_price_per_token ?? 0) !== 0 || (e.output_price_per_token ?? 0) !== 0)
|
|
95
|
+
return false;
|
|
96
|
+
if (isCustomModel(e.model_name))
|
|
97
|
+
return false;
|
|
98
|
+
const provider = e.provider || 'Unknown';
|
|
99
|
+
if (EXCLUDED_PROVIDERS.has(provider))
|
|
100
|
+
return false;
|
|
101
|
+
return (tokenMap.get(e.model_name) ?? 0) > 0;
|
|
102
|
+
})
|
|
103
|
+
.map((e) => ({
|
|
104
|
+
model_name: e.model_name,
|
|
105
|
+
provider: e.provider || 'Unknown',
|
|
106
|
+
tokens_7d: tokenMap.get(e.model_name) ?? 0,
|
|
107
|
+
}))
|
|
108
|
+
.sort((a, b) => b.tokens_7d - a.tokens_7d)
|
|
109
|
+
.slice(0, MAX_RESULTS);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
exports.PublicStatsService = PublicStatsService;
|
|
113
|
+
exports.PublicStatsService = PublicStatsService = __decorate([
|
|
114
|
+
(0, common_1.Injectable)(),
|
|
115
|
+
__param(0, (0, typeorm_1.InjectRepository)(agent_message_entity_1.AgentMessage)),
|
|
116
|
+
__metadata("design:paramtypes", [typeorm_2.Repository,
|
|
117
|
+
model_pricing_cache_service_1.ModelPricingCacheService])
|
|
118
|
+
], PublicStatsService);
|
|
119
|
+
//# sourceMappingURL=public-stats.service.js.map
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.toResponsesRequest = toResponsesRequest;
|
|
4
4
|
exports.fromResponsesResponse = fromResponsesResponse;
|
|
5
5
|
exports.transformResponsesStreamChunk = transformResponsesStreamChunk;
|
|
6
|
+
exports.collectChatGptSseResponse = collectChatGptSseResponse;
|
|
6
7
|
const crypto_1 = require("crypto");
|
|
7
8
|
const chatgpt_helpers_1 = require("./chatgpt-helpers");
|
|
8
9
|
function toResponsesRequest(body, model) {
|
|
@@ -188,4 +189,84 @@ function handleCompletedEvent(dataStr, model) {
|
|
|
188
189
|
const finish = (0, chatgpt_helpers_1.formatSSE)({ delta: {}, finish_reason: hasFunctionCalls ? 'tool_calls' : 'stop' }, model, usage);
|
|
189
190
|
return `${finish}\ndata: [DONE]\n\n`;
|
|
190
191
|
}
|
|
192
|
+
function collectChatGptSseResponse(sseText, model) {
|
|
193
|
+
let text = '';
|
|
194
|
+
const toolCallMap = new Map();
|
|
195
|
+
let usage;
|
|
196
|
+
let hasFunctionCalls = false;
|
|
197
|
+
const events = sseText.split('\n\n');
|
|
198
|
+
for (const event of events) {
|
|
199
|
+
const lines = event.split('\n');
|
|
200
|
+
let eventType = '';
|
|
201
|
+
let dataStr = '';
|
|
202
|
+
for (const line of lines) {
|
|
203
|
+
if (line.startsWith('event: '))
|
|
204
|
+
eventType = line.slice(7).trim();
|
|
205
|
+
else if (line.startsWith('data: '))
|
|
206
|
+
dataStr = line.slice(6);
|
|
207
|
+
}
|
|
208
|
+
if (!eventType || !dataStr)
|
|
209
|
+
continue;
|
|
210
|
+
const data = (0, chatgpt_helpers_1.safeParse)(dataStr);
|
|
211
|
+
if (!data)
|
|
212
|
+
continue;
|
|
213
|
+
if (eventType === 'response.output_text.delta') {
|
|
214
|
+
text += typeof data.delta === 'string' ? data.delta : '';
|
|
215
|
+
}
|
|
216
|
+
else if (eventType === 'response.output_item.added') {
|
|
217
|
+
const item = (0, chatgpt_helpers_1.isObjectRecord)(data.item) ? data.item : undefined;
|
|
218
|
+
if (item?.type === 'function_call') {
|
|
219
|
+
const idx = typeof data.output_index === 'number' ? data.output_index : toolCallMap.size;
|
|
220
|
+
toolCallMap.set(idx, {
|
|
221
|
+
id: item.call_id ?? '',
|
|
222
|
+
type: 'function',
|
|
223
|
+
function: { name: item.name ?? '', arguments: '' },
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
else if (eventType === 'response.function_call_arguments.delta') {
|
|
228
|
+
const idx = typeof data.output_index === 'number' ? data.output_index : 0;
|
|
229
|
+
const tc = toolCallMap.get(idx);
|
|
230
|
+
if (tc) {
|
|
231
|
+
tc.function.arguments += typeof data.delta === 'string' ? data.delta : '';
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
else if (eventType === 'response.completed') {
|
|
235
|
+
const response = (0, chatgpt_helpers_1.isObjectRecord)(data.response) ? data.response : undefined;
|
|
236
|
+
const respUsage = response?.usage;
|
|
237
|
+
if (respUsage) {
|
|
238
|
+
const inputDetails = respUsage.input_tokens_details;
|
|
239
|
+
usage = {
|
|
240
|
+
prompt_tokens: respUsage.input_tokens ?? 0,
|
|
241
|
+
completion_tokens: respUsage.output_tokens ?? 0,
|
|
242
|
+
total_tokens: respUsage.total_tokens ?? 0,
|
|
243
|
+
cache_read_tokens: inputDetails?.cached_tokens ?? 0,
|
|
244
|
+
cache_creation_tokens: 0,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
const output = Array.isArray(response?.output)
|
|
248
|
+
? response.output
|
|
249
|
+
: [];
|
|
250
|
+
hasFunctionCalls = output.some((item) => item.type === 'function_call');
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
const toolCalls = [...toolCallMap.values()];
|
|
254
|
+
const message = { role: 'assistant', content: text || null };
|
|
255
|
+
if (toolCalls.length > 0)
|
|
256
|
+
message.tool_calls = toolCalls;
|
|
257
|
+
return {
|
|
258
|
+
id: `chatcmpl-${(0, crypto_1.randomUUID)().replace(/-/g, '').slice(0, 29)}`,
|
|
259
|
+
object: 'chat.completion',
|
|
260
|
+
created: Math.floor(Date.now() / 1000),
|
|
261
|
+
model,
|
|
262
|
+
choices: [
|
|
263
|
+
{
|
|
264
|
+
index: 0,
|
|
265
|
+
message,
|
|
266
|
+
finish_reason: hasFunctionCalls || toolCalls.length > 0 ? 'tool_calls' : 'stop',
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
usage: usage ?? { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },
|
|
270
|
+
};
|
|
271
|
+
}
|
|
191
272
|
//# sourceMappingURL=chatgpt-adapter.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.toResponsesRequest = exports.toAnthropicRequest = exports.toGoogleRequest = void 0;
|
|
3
|
+
exports.collectChatGptSseResponse = exports.toResponsesRequest = exports.toAnthropicRequest = exports.toGoogleRequest = void 0;
|
|
4
4
|
exports.convertChatGptResponse = convertChatGptResponse;
|
|
5
5
|
exports.convertChatGptStreamChunk = convertChatGptStreamChunk;
|
|
6
6
|
exports.convertGoogleResponse = convertGoogleResponse;
|
|
@@ -15,6 +15,7 @@ const anthropic_adapter_1 = require("./anthropic-adapter");
|
|
|
15
15
|
Object.defineProperty(exports, "toAnthropicRequest", { enumerable: true, get: function () { return anthropic_adapter_1.toAnthropicRequest; } });
|
|
16
16
|
const chatgpt_adapter_1 = require("./chatgpt-adapter");
|
|
17
17
|
Object.defineProperty(exports, "toResponsesRequest", { enumerable: true, get: function () { return chatgpt_adapter_1.toResponsesRequest; } });
|
|
18
|
+
Object.defineProperty(exports, "collectChatGptSseResponse", { enumerable: true, get: function () { return chatgpt_adapter_1.collectChatGptSseResponse; } });
|
|
18
19
|
function convertChatGptResponse(body, model) {
|
|
19
20
|
return (0, chatgpt_adapter_1.fromResponsesResponse)(body, model);
|
|
20
21
|
}
|
|
@@ -117,6 +117,9 @@ let ProviderClient = ProviderClient_1 = class ProviderClient {
|
|
|
117
117
|
createAnthropicStreamTransformer(model) {
|
|
118
118
|
return (0, provider_client_converters_1.createAnthropicTransformer)(model);
|
|
119
119
|
}
|
|
120
|
+
collectChatGptSseResponse(sseText, model) {
|
|
121
|
+
return (0, provider_client_converters_1.collectChatGptSseResponse)(sseText, model);
|
|
122
|
+
}
|
|
120
123
|
};
|
|
121
124
|
exports.ProviderClient = ProviderClient;
|
|
122
125
|
exports.ProviderClient = ProviderClient = ProviderClient_1 = __decorate([
|
|
@@ -151,8 +151,8 @@ async function handleNonStreamResponse(res, forward, meta, metaHeaders, provider
|
|
|
151
151
|
responseBody = providerClient.convertAnthropicResponse(anthropicData, meta.model);
|
|
152
152
|
}
|
|
153
153
|
else if (forward.isChatGpt) {
|
|
154
|
-
const
|
|
155
|
-
responseBody = providerClient.
|
|
154
|
+
const sseText = await forward.response.text();
|
|
155
|
+
responseBody = providerClient.collectChatGptSseResponse(sseText, meta.model);
|
|
156
156
|
}
|
|
157
157
|
else {
|
|
158
158
|
responseBody = await forward.response.json();
|
|
@@ -119,18 +119,10 @@ function scoreRequest(input, configOverride, momentum) {
|
|
|
119
119
|
const hasTools = tools && tools.length > 0;
|
|
120
120
|
const hasMomentum = momentum?.recentTiers && momentum.recentTiers.length > 0;
|
|
121
121
|
if (lastUserText.length > 0 && lastUserText.length < 50 && !hasTools) {
|
|
122
|
-
if (!hasMomentum) {
|
|
123
|
-
return {
|
|
124
|
-
tier: 'simple',
|
|
125
|
-
score: -0.3,
|
|
126
|
-
confidence: 0.9,
|
|
127
|
-
reason: 'short_message',
|
|
128
|
-
dimensions: emptyDimensions(config),
|
|
129
|
-
momentum: null,
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
122
|
const lastMatches = trie.scan(lastUserText);
|
|
133
|
-
|
|
123
|
+
const hasSimpleIndicator = lastMatches.some((m) => m.dimension === 'simpleIndicators');
|
|
124
|
+
const hasComplexSignal = lastMatches.some((m) => m.dimension !== 'simpleIndicators' && m.dimension !== 'relay');
|
|
125
|
+
if (!hasComplexSignal && (!hasMomentum || hasSimpleIndicator)) {
|
|
134
126
|
return {
|
|
135
127
|
tier: 'simple',
|
|
136
128
|
score: -0.3,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "manifest",
|
|
3
3
|
"name": "Manifest Self-Hosted LLM Router",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.38.2",
|
|
5
5
|
"description": "Run the Manifest LLM router locally with SQLite. Zero-config dashboard included.",
|
|
6
6
|
"author": "MNFST Inc.",
|
|
7
7
|
"homepage": "https://manifest.build",
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "manifest",
|
|
3
3
|
"name": "Manifest Self-Hosted LLM Router",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.38.2",
|
|
5
5
|
"description": "Run the Manifest LLM router locally with SQLite. Zero-config dashboard included.",
|
|
6
6
|
"author": "MNFST Inc.",
|
|
7
7
|
"homepage": "https://manifest.build",
|