manifest 5.28.1 → 5.28.4

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.
Files changed (57) hide show
  1. package/README.md +1 -9
  2. package/dist/backend/analytics/controllers/agent-analytics.controller.js +0 -2
  3. package/dist/backend/analytics/controllers/agents.controller.js +0 -2
  4. package/dist/backend/app.module.js +1 -0
  5. package/dist/backend/auth/auth.instance.js +0 -10
  6. package/dist/backend/common/filters/spa-fallback.filter.js +7 -4
  7. package/dist/backend/common/utils/anthropic-model-id.js +36 -0
  8. package/dist/backend/database/local-bootstrap.service.js +0 -2
  9. package/dist/backend/database/migrations/1773600000000-AddOverrideProvider.js +18 -0
  10. package/dist/backend/entities/tier-assignment.entity.js +5 -0
  11. package/dist/backend/health/health.controller.js +0 -2
  12. package/dist/backend/main.js +1 -1
  13. package/dist/backend/model-prices/model-name-normalizer.js +11 -0
  14. package/dist/backend/model-prices/model-prices.module.js +11 -2
  15. package/dist/backend/model-prices/model-prices.service.js +1 -0
  16. package/dist/backend/model-prices/model-pricing-cache.service.js +26 -6
  17. package/dist/backend/otlp/otlp.controller.js +0 -7
  18. package/dist/backend/routing/dto/routing.dto.js +7 -0
  19. package/dist/backend/routing/model-discovery/model-discovery.service.js +12 -3
  20. package/dist/backend/routing/model-discovery/model-fallback.js +12 -3
  21. package/dist/backend/routing/model-discovery/provider-model-registry.service.js +84 -0
  22. package/dist/backend/routing/proxy/provider-client.js +68 -0
  23. package/dist/backend/routing/proxy/proxy.controller.js +1 -7
  24. package/dist/backend/routing/proxy/proxy.service.js +119 -15
  25. package/dist/backend/routing/resolve.controller.js +0 -4
  26. package/dist/backend/routing/resolve.service.js +6 -3
  27. package/dist/backend/routing/routing-invalidation.service.js +1 -0
  28. package/dist/backend/routing/routing.controller.js +1 -8
  29. package/dist/backend/routing/routing.service.js +14 -3
  30. package/dist/backend/routing/tier-auto-assign.service.js +1 -0
  31. package/dist/index.js +15 -15
  32. package/dist/index.js.map +4 -4
  33. package/dist/local-mode.js +2 -2
  34. package/dist/openclaw.plugin.json +3 -3
  35. package/dist/server.js +0 -3
  36. package/openclaw.plugin.json +3 -3
  37. package/package.json +1 -1
  38. package/public/assets/{Account-lMoZskop.js → Account-BCGnPZpy.js} +1 -1
  39. package/public/assets/{Limits-B-6iTyQT.js → Limits-oxYjJ-dc.js} +1 -1
  40. package/public/assets/{Login-DCJ6baks.js → Login-CO8qeCzE.js} +1 -1
  41. package/public/assets/{MessageLog-WSu2aiYt.js → MessageLog-Dgo_LIpr.js} +1 -1
  42. package/public/assets/{ModelPrices-COnpiTsJ.js → ModelPrices-C65v0VGg.js} +1 -1
  43. package/public/assets/{Overview-BFROKNs8.js → Overview-BxMRtfGQ.js} +1 -1
  44. package/public/assets/{Register-BRjUN5YN.js → Register-B23msCLK.js} +1 -1
  45. package/public/assets/{ResetPassword-ChtceLPF.js → ResetPassword-DxYU1h7s.js} +1 -1
  46. package/public/assets/Routing-DsotPZ7f.js +3 -0
  47. package/public/assets/{Settings-DRSVp3Qa.js → Settings-R67t6_xt.js} +1 -1
  48. package/public/assets/{SocialButtons-CHClLuQb.js → SocialButtons-2KTxe6fx.js} +1 -1
  49. package/public/assets/index-C5s5w1mG.js +2 -0
  50. package/public/assets/{model-display-CLqbKFOT.js → model-display-uKwr3P-q.js} +1 -1
  51. package/public/assets/{overview-NV8VepBt.js → overview-Bfro9DjY.js} +1 -1
  52. package/public/index.html +1 -1
  53. package/skills/manifest/SKILL.md +87 -81
  54. package/dist/backend/common/utils/posthog-sender.js +0 -19
  55. package/dist/backend/common/utils/product-telemetry.js +0 -55
  56. package/public/assets/Routing-CtIaVTz0.js +0 -3
  57. package/public/assets/index-CP_42-of.js +0 -2
package/README.md CHANGED
@@ -108,15 +108,7 @@ tailscale serve --bg 2099
108
108
 
109
109
  **In cloud mode, the blind proxy physically cannot read your prompts.** This is fundamentally different from services saying "trust us."
110
110
 
111
- The only thing Manifest collects is anonymous product analytics (hashed machine ID, OS platform, package version, event names) to help improve the project. No personally identifiable information or agent data is included.
112
-
113
- **Opting out:**
114
-
115
- ```bash
116
- MANIFEST_TELEMETRY_OPTOUT=1
117
- ```
118
-
119
- Or add `"telemetryOptOut": true` to `~/.openclaw/manifest/config.json`.
111
+ In local mode, all Manifest data stays on your machine. No analytics or telemetry data is sent externally.
120
112
 
121
113
 
122
114
  ## Manifest vs OpenRouter
@@ -21,7 +21,6 @@ const agent_analytics_service_1 = require("../services/agent-analytics.service")
21
21
  const range_query_dto_1 = require("../../common/dto/range-query.dto");
22
22
  const agent_cache_interceptor_1 = require("../../common/interceptors/agent-cache.interceptor");
23
23
  const cache_constants_1 = require("../../common/constants/cache.constants");
24
- const product_telemetry_1 = require("../../common/utils/product-telemetry");
25
24
  let AgentAnalyticsController = class AgentAnalyticsController {
26
25
  analytics;
27
26
  constructor(analytics) {
@@ -34,7 +33,6 @@ let AgentAnalyticsController = class AgentAnalyticsController {
34
33
  return {
35
34
  ...usage,
36
35
  agentName: ctx.agentName,
37
- telemetryId: (0, product_telemetry_1.hashForTelemetry)(ctx.userId),
38
36
  };
39
37
  }
40
38
  async getCosts(query, req) {
@@ -26,7 +26,6 @@ const rename_agent_dto_1 = require("../../common/dto/rename-agent.dto");
26
26
  const user_cache_interceptor_1 = require("../../common/interceptors/user-cache.interceptor");
27
27
  const cache_constants_1 = require("../../common/constants/cache.constants");
28
28
  const local_mode_constants_1 = require("../../common/constants/local-mode.constants");
29
- const product_telemetry_1 = require("../../common/utils/product-telemetry");
30
29
  const slugify_1 = require("../../common/utils/slugify");
31
30
  const tenant_cache_service_1 = require("../../common/services/tenant-cache.service");
32
31
  let AgentsController = class AgentsController {
@@ -68,7 +67,6 @@ let AgentsController = class AgentsController {
68
67
  }
69
68
  throw error;
70
69
  }
71
- (0, product_telemetry_1.trackCloudEvent)('agent_created', user.id, { agent_name: slug });
72
70
  return {
73
71
  agent: { id: result.agentId, name: slug, display_name: displayName },
74
72
  apiKey: result.apiKey,
@@ -42,6 +42,7 @@ const serveStaticImports = frontendPath
42
42
  ? [
43
43
  serve_static_1.ServeStaticModule.forRoot({
44
44
  rootPath: frontendPath,
45
+ renderPath: '/__serve_static_never_match',
45
46
  exclude: ['/api/{*path}', '/otlp/{*path}', '/v1/{*path}'],
46
47
  serveStaticOptions: {
47
48
  maxAge: ONE_YEAR_S * 1000,
@@ -6,7 +6,6 @@ const render_1 = require("@react-email/render");
6
6
  const verify_email_1 = require("../notifications/emails/verify-email");
7
7
  const reset_password_1 = require("../notifications/emails/reset-password");
8
8
  const send_email_1 = require("../notifications/services/email-providers/send-email");
9
- const product_telemetry_1 = require("../common/utils/product-telemetry");
10
9
  const local_mode_constants_1 = require("../common/constants/local-mode.constants");
11
10
  const isLocalMode = process.env['MANIFEST_MODE'] === 'local';
12
11
  const port = process.env['PORT'] ?? '3001';
@@ -116,15 +115,6 @@ const authInstance = isLocalMode
116
115
  },
117
116
  },
118
117
  trustedOrigins: buildTrustedOrigins(),
119
- databaseHooks: {
120
- user: {
121
- create: {
122
- after: async (user) => {
123
- (0, product_telemetry_1.trackCloudEvent)('user_registered', user.id);
124
- },
125
- },
126
- },
127
- },
128
118
  });
129
119
  exports.auth = authInstance;
130
120
  //# sourceMappingURL=auth.instance.js.map
@@ -12,27 +12,30 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.SpaFallbackFilter = void 0;
13
13
  const common_1 = require("@nestjs/common");
14
14
  const path_1 = require("path");
15
+ const fs_1 = require("fs");
15
16
  const frontend_path_1 = require("../utils/frontend-path");
16
17
  const API_PREFIXES = ['/api/', '/otlp/', '/v1/'];
17
18
  let SpaFallbackFilter = class SpaFallbackFilter {
18
- indexPath;
19
+ indexContent;
19
20
  constructor() {
20
21
  const frontendDir = (0, frontend_path_1.resolveFrontendDir)();
21
- this.indexPath = frontendDir ? (0, path_1.join)(frontendDir, 'index.html') : null;
22
+ this.indexContent = frontendDir ? (0, fs_1.readFileSync)((0, path_1.join)(frontendDir, 'index.html'), 'utf-8') : null;
22
23
  }
23
24
  catch(exception, host) {
24
25
  const ctx = host.switchToHttp();
25
26
  const req = ctx.getRequest();
26
27
  const res = ctx.getResponse();
27
28
  if (req.method !== 'GET' ||
28
- !this.indexPath ||
29
+ !this.indexContent ||
29
30
  API_PREFIXES.some((p) => req.originalUrl.startsWith(p))) {
30
31
  const response = exception.getResponse();
31
32
  const status = exception.getStatus();
32
33
  res.status(status).json(response);
33
34
  return;
34
35
  }
35
- res.sendFile(this.indexPath);
36
+ res.setHeader('Content-Type', 'text/html');
37
+ res.setHeader('Cache-Control', 'no-cache');
38
+ res.status(200).send(this.indexContent);
36
39
  }
37
40
  };
38
41
  exports.SpaFallbackFilter = SpaFallbackFilter;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeAnthropicShortModelId = normalizeAnthropicShortModelId;
4
+ exports.buildAnthropicShortModelIdVariants = buildAnthropicShortModelIdVariants;
5
+ const ANTHROPIC_PREFIX = 'anthropic/';
6
+ const SHORT_ANTHROPIC_MODEL_RE = /^claude-(opus|sonnet|haiku)-/i;
7
+ const DOTTED_MINOR_RE = /-(\d+)\.(\d{1,2})(?=$|-\d{8}$)/g;
8
+ const DASHED_MINOR_RE = /-(\d+)-(\d{1,2})(?=$|-\d{8}$)/g;
9
+ function splitAnthropicPrefix(model) {
10
+ if (model.startsWith(ANTHROPIC_PREFIX)) {
11
+ return {
12
+ prefix: ANTHROPIC_PREFIX,
13
+ bare: model.slice(ANTHROPIC_PREFIX.length),
14
+ };
15
+ }
16
+ return { prefix: '', bare: model };
17
+ }
18
+ function supportsShortAnthropicMinorVersion(model) {
19
+ return SHORT_ANTHROPIC_MODEL_RE.test(model);
20
+ }
21
+ function normalizeAnthropicShortModelId(model) {
22
+ const { prefix, bare } = splitAnthropicPrefix(model);
23
+ if (!supportsShortAnthropicMinorVersion(bare))
24
+ return model;
25
+ return `${prefix}${bare.replace(DOTTED_MINOR_RE, '-$1-$2')}`;
26
+ }
27
+ function buildAnthropicShortModelIdVariants(model) {
28
+ const normalized = normalizeAnthropicShortModelId(model);
29
+ const { prefix, bare } = splitAnthropicPrefix(normalized);
30
+ if (!supportsShortAnthropicMinorVersion(bare))
31
+ return [model];
32
+ const variants = new Set([model, normalized]);
33
+ variants.add(`${prefix}${bare.replace(DASHED_MINOR_RE, '-$1.$2')}`);
34
+ return [...variants];
35
+ }
36
+ //# sourceMappingURL=anthropic-model-id.js.map
@@ -62,7 +62,6 @@ const user_provider_entity_1 = require("../entities/user-provider.entity");
62
62
  const tier_assignment_entity_1 = require("../entities/tier-assignment.entity");
63
63
  const hash_util_1 = require("../common/utils/hash.util");
64
64
  const local_mode_constants_1 = require("../common/constants/local-mode.constants");
65
- const product_telemetry_1 = require("../common/utils/product-telemetry");
66
65
  const seed_messages_1 = require("./seed-messages");
67
66
  let LocalBootstrapService = LocalBootstrapService_1 = class LocalBootstrapService {
68
67
  tenantRepo;
@@ -124,7 +123,6 @@ let LocalBootstrapService = LocalBootstrapService_1 = class LocalBootstrapServic
124
123
  is_active: true,
125
124
  tenant_id: local_mode_constants_1.LOCAL_TENANT_ID,
126
125
  });
127
- (0, product_telemetry_1.trackEvent)('agent_created', { agent_name: local_mode_constants_1.LOCAL_AGENT_NAME });
128
126
  this.logger.log(`Created tenant/agent for local mode`);
129
127
  }
130
128
  const apiKey = this.readApiKeyFromConfig();
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AddOverrideProvider1773600000000 = void 0;
4
+ const typeorm_1 = require("typeorm");
5
+ class AddOverrideProvider1773600000000 {
6
+ async up(queryRunner) {
7
+ await queryRunner.addColumn('tier_assignments', new typeorm_1.TableColumn({
8
+ name: 'override_provider',
9
+ type: 'varchar',
10
+ isNullable: true,
11
+ }));
12
+ }
13
+ async down(queryRunner) {
14
+ await queryRunner.dropColumn('tier_assignments', 'override_provider');
15
+ }
16
+ }
17
+ exports.AddOverrideProvider1773600000000 = AddOverrideProvider1773600000000;
18
+ //# sourceMappingURL=1773600000000-AddOverrideProvider.js.map
@@ -18,6 +18,7 @@ let TierAssignment = class TierAssignment {
18
18
  agent_id;
19
19
  tier;
20
20
  override_model;
21
+ override_provider;
21
22
  override_auth_type;
22
23
  auto_assigned_model;
23
24
  fallback_models;
@@ -44,6 +45,10 @@ __decorate([
44
45
  (0, typeorm_1.Column)('varchar', { nullable: true }),
45
46
  __metadata("design:type", Object)
46
47
  ], TierAssignment.prototype, "override_model", void 0);
48
+ __decorate([
49
+ (0, typeorm_1.Column)('varchar', { nullable: true }),
50
+ __metadata("design:type", Object)
51
+ ], TierAssignment.prototype, "override_provider", void 0);
47
52
  __decorate([
48
53
  (0, typeorm_1.Column)('varchar', { nullable: true }),
49
54
  __metadata("design:type", Object)
@@ -22,14 +22,12 @@ let HealthController = class HealthController {
22
22
  getHealth() {
23
23
  const isLocal = process.env['MANIFEST_MODE'] === 'local';
24
24
  const isDev = process.env['NODE_ENV'] !== 'production';
25
- const optOut = process.env['MANIFEST_TELEMETRY_OPTOUT'];
26
25
  return {
27
26
  status: 'healthy',
28
27
  uptime_seconds: Math.floor((Date.now() - this.startTime) / 1000),
29
28
  ...(isLocal ? { version: this.versionCheck.getCurrentVersion() } : {}),
30
29
  mode: isLocal ? 'local' : 'cloud',
31
30
  devMode: isDev,
32
- telemetryOptOut: optOut === '1' || optOut === 'true',
33
31
  ...this.versionCheck.getUpdateInfo(),
34
32
  };
35
33
  }
@@ -62,7 +62,7 @@ async function bootstrap() {
62
62
  scriptSrc: ["'self'"],
63
63
  styleSrc: ["'self'", "'unsafe-inline'"],
64
64
  imgSrc: ["'self'", 'data:'],
65
- connectSrc: ["'self'", 'https://eu.i.posthog.com'],
65
+ connectSrc: ["'self'"],
66
66
  fontSrc: ["'self'"],
67
67
  objectSrc: ["'none'"],
68
68
  frameAncestors: ["'none'"],
@@ -5,6 +5,7 @@ exports.stripDateSuffix = stripDateSuffix;
5
5
  exports.buildAliasMap = buildAliasMap;
6
6
  exports.normalizeDots = normalizeDots;
7
7
  exports.resolveModelName = resolveModelName;
8
+ const anthropic_model_id_1 = require("../common/utils/anthropic-model-id");
8
9
  const KNOWN_ALIASES = [
9
10
  ['claude-opus-4', 'claude-opus-4-6'],
10
11
  ['claude-sonnet-4.5', 'claude-sonnet-4-5-20250929'],
@@ -61,10 +62,20 @@ function buildAliasMap(canonicalNames) {
61
62
  const map = new Map();
62
63
  for (const name of canonicalNames) {
63
64
  map.set(name, name);
65
+ for (const variant of (0, anthropic_model_id_1.buildAnthropicShortModelIdVariants)(name)) {
66
+ if (!map.has(variant)) {
67
+ map.set(variant, name);
68
+ }
69
+ }
64
70
  const bare = stripProviderPrefix(name);
65
71
  if (bare !== name && !map.has(bare)) {
66
72
  map.set(bare, name);
67
73
  }
74
+ for (const variant of (0, anthropic_model_id_1.buildAnthropicShortModelIdVariants)(bare)) {
75
+ if (!map.has(variant)) {
76
+ map.set(variant, name);
77
+ }
78
+ }
68
79
  }
69
80
  for (const [alias, canonical] of KNOWN_ALIASES) {
70
81
  if (map.has(alias))
@@ -8,18 +8,27 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.ModelPricesModule = void 0;
10
10
  const common_1 = require("@nestjs/common");
11
+ const typeorm_1 = require("@nestjs/typeorm");
11
12
  const model_prices_controller_1 = require("./model-prices.controller");
12
13
  const model_prices_service_1 = require("./model-prices.service");
13
14
  const model_pricing_cache_service_1 = require("./model-pricing-cache.service");
14
15
  const pricing_sync_service_1 = require("../database/pricing-sync.service");
16
+ const provider_model_registry_service_1 = require("../routing/model-discovery/provider-model-registry.service");
17
+ const user_provider_entity_1 = require("../entities/user-provider.entity");
15
18
  let ModelPricesModule = class ModelPricesModule {
16
19
  };
17
20
  exports.ModelPricesModule = ModelPricesModule;
18
21
  exports.ModelPricesModule = ModelPricesModule = __decorate([
19
22
  (0, common_1.Module)({
23
+ imports: [typeorm_1.TypeOrmModule.forFeature([user_provider_entity_1.UserProvider])],
20
24
  controllers: [model_prices_controller_1.ModelPricesController],
21
- providers: [model_prices_service_1.ModelPricesService, model_pricing_cache_service_1.ModelPricingCacheService, pricing_sync_service_1.PricingSyncService],
22
- exports: [model_pricing_cache_service_1.ModelPricingCacheService, pricing_sync_service_1.PricingSyncService],
25
+ providers: [
26
+ model_prices_service_1.ModelPricesService,
27
+ model_pricing_cache_service_1.ModelPricingCacheService,
28
+ pricing_sync_service_1.PricingSyncService,
29
+ provider_model_registry_service_1.ProviderModelRegistryService,
30
+ ],
31
+ exports: [model_pricing_cache_service_1.ModelPricingCacheService, pricing_sync_service_1.PricingSyncService, provider_model_registry_service_1.ProviderModelRegistryService],
23
32
  })
24
33
  ], ModelPricesModule);
25
34
  //# sourceMappingURL=model-prices.module.js.map
@@ -30,6 +30,7 @@ let ModelPricesService = class ModelPricesService {
30
30
  input_price_per_million: r.input_price_per_token != null ? Number(r.input_price_per_token) * 1_000_000 : null,
31
31
  output_price_per_million: r.output_price_per_token != null ? Number(r.output_price_per_token) * 1_000_000 : null,
32
32
  display_name: r.display_name || null,
33
+ validated: r.validated,
33
34
  })),
34
35
  lastSyncedAt,
35
36
  };
@@ -8,6 +8,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
8
8
  var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
10
  };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
11
14
  var ModelPricingCacheService_1;
12
15
  Object.defineProperty(exports, "__esModule", { value: true });
13
16
  exports.ModelPricingCacheService = void 0;
@@ -15,13 +18,16 @@ const common_1 = require("@nestjs/common");
15
18
  const model_name_normalizer_1 = require("./model-name-normalizer");
16
19
  const pricing_sync_service_1 = require("../database/pricing-sync.service");
17
20
  const providers_1 = require("../common/constants/providers");
21
+ const provider_model_registry_service_1 = require("../routing/model-discovery/provider-model-registry.service");
18
22
  let ModelPricingCacheService = ModelPricingCacheService_1 = class ModelPricingCacheService {
19
23
  pricingSync;
24
+ modelRegistry;
20
25
  logger = new common_1.Logger(ModelPricingCacheService_1.name);
21
26
  cache = new Map();
22
27
  aliasMap = new Map();
23
- constructor(pricingSync) {
28
+ constructor(pricingSync, modelRegistry) {
24
29
  this.pricingSync = pricingSync;
30
+ this.modelRegistry = modelRegistry;
25
31
  }
26
32
  async onApplicationBootstrap() {
27
33
  await this.reload();
@@ -30,14 +36,16 @@ let ModelPricingCacheService = ModelPricingCacheService_1 = class ModelPricingCa
30
36
  this.cache.clear();
31
37
  const orCache = this.pricingSync.getAll();
32
38
  for (const [fullId, entry] of orCache) {
33
- const { provider, canonical } = this.resolveProviderAndName(fullId);
39
+ const { provider, canonical, providerId } = this.resolveProviderAndName(fullId);
34
40
  const displayName = entry.displayName ?? null;
41
+ const validated = this.resolveValidated(providerId, canonical);
35
42
  this.cache.set(fullId, {
36
43
  model_name: fullId,
37
44
  provider,
38
45
  input_price_per_token: entry.input,
39
46
  output_price_per_token: entry.output,
40
47
  display_name: displayName,
48
+ validated,
41
49
  });
42
50
  if (canonical !== fullId && !this.cache.has(canonical)) {
43
51
  this.cache.set(canonical, {
@@ -46,6 +54,7 @@ let ModelPricingCacheService = ModelPricingCacheService_1 = class ModelPricingCa
46
54
  input_price_per_token: entry.input,
47
55
  output_price_per_token: entry.output,
48
56
  display_name: displayName,
57
+ validated,
49
58
  });
50
59
  }
51
60
  }
@@ -74,11 +83,11 @@ let ModelPricingCacheService = ModelPricingCacheService_1 = class ModelPricingCa
74
83
  }
75
84
  resolveProviderAndName(openRouterId) {
76
85
  if (openRouterId.startsWith('openrouter/')) {
77
- return { provider: 'OpenRouter', canonical: openRouterId };
86
+ return { provider: 'OpenRouter', canonical: openRouterId, providerId: null };
78
87
  }
79
88
  const slashIdx = openRouterId.indexOf('/');
80
89
  if (slashIdx <= 0) {
81
- return { provider: 'OpenRouter', canonical: openRouterId };
90
+ return { provider: 'OpenRouter', canonical: openRouterId, providerId: null };
82
91
  }
83
92
  const prefix = openRouterId.substring(0, slashIdx);
84
93
  const displayName = providers_1.OPENROUTER_PREFIX_TO_PROVIDER.get(prefix);
@@ -86,14 +95,25 @@ let ModelPricingCacheService = ModelPricingCacheService_1 = class ModelPricingCa
86
95
  return {
87
96
  provider: displayName,
88
97
  canonical: openRouterId.substring(slashIdx + 1),
98
+ providerId: prefix,
89
99
  };
90
100
  }
91
- return { provider: 'OpenRouter', canonical: openRouterId };
101
+ return { provider: 'OpenRouter', canonical: openRouterId, providerId: null };
102
+ }
103
+ resolveValidated(providerId, canonical) {
104
+ if (!this.modelRegistry || !providerId)
105
+ return undefined;
106
+ const entry = providers_1.PROVIDER_BY_ID_OR_ALIAS.get(providerId);
107
+ const canonicalProviderId = entry?.id ?? providerId;
108
+ const result = this.modelRegistry.isModelConfirmed(canonicalProviderId, canonical);
109
+ return result ?? undefined;
92
110
  }
93
111
  };
94
112
  exports.ModelPricingCacheService = ModelPricingCacheService;
95
113
  exports.ModelPricingCacheService = ModelPricingCacheService = ModelPricingCacheService_1 = __decorate([
96
114
  (0, common_1.Injectable)(),
97
- __metadata("design:paramtypes", [pricing_sync_service_1.PricingSyncService])
115
+ __param(1, (0, common_1.Optional)()),
116
+ __param(1, (0, common_1.Inject)(provider_model_registry_service_1.ProviderModelRegistryService)),
117
+ __metadata("design:paramtypes", [pricing_sync_service_1.PricingSyncService, Object])
98
118
  ], ModelPricingCacheService);
99
119
  //# sourceMappingURL=model-pricing-cache.service.js.map
@@ -26,7 +26,6 @@ const metric_ingest_service_1 = require("./services/metric-ingest.service");
26
26
  const log_ingest_service_1 = require("./services/log-ingest.service");
27
27
  const ingest_event_bus_service_1 = require("../common/services/ingest-event-bus.service");
28
28
  const manifest_runtime_service_1 = require("../common/services/manifest-runtime.service");
29
- const product_telemetry_1 = require("../common/utils/product-telemetry");
30
29
  let OtlpController = OtlpController_1 = class OtlpController {
31
30
  decoder;
32
31
  traceIngest;
@@ -84,9 +83,6 @@ let OtlpController = OtlpController_1 = class OtlpController {
84
83
  const markerPath = (0, path_1.join)(markerDir, '.first_telemetry_sent');
85
84
  if ((0, fs_1.existsSync)(markerPath))
86
85
  return;
87
- (0, product_telemetry_1.trackEvent)('first_telemetry_received', {
88
- agent_id_hash: ctx.agentId.slice(0, 8),
89
- });
90
86
  (0, fs_1.mkdirSync)(markerDir, { recursive: true });
91
87
  (0, fs_1.writeFileSync)(markerPath, new Date().toISOString(), { mode: 0o600 });
92
88
  }
@@ -94,9 +90,6 @@ let OtlpController = OtlpController_1 = class OtlpController {
94
90
  if (this.seenAgents.has(ctx.agentId))
95
91
  return;
96
92
  this.seenAgents.add(ctx.agentId);
97
- (0, product_telemetry_1.trackCloudEvent)('first_telemetry_received', ctx.userId, {
98
- agent_id_hash: ctx.agentId.slice(0, 8),
99
- });
100
93
  }
101
94
  }
102
95
  };
@@ -88,6 +88,7 @@ __decorate([
88
88
  ], RemoveProviderQueryDto.prototype, "authType", void 0);
89
89
  class SetOverrideDto {
90
90
  model;
91
+ provider;
91
92
  authType;
92
93
  }
93
94
  exports.SetOverrideDto = SetOverrideDto;
@@ -96,6 +97,12 @@ __decorate([
96
97
  (0, class_validator_1.IsNotEmpty)(),
97
98
  __metadata("design:type", String)
98
99
  ], SetOverrideDto.prototype, "model", void 0);
100
+ __decorate([
101
+ (0, class_validator_1.IsOptional)(),
102
+ (0, class_validator_1.IsString)(),
103
+ (0, class_validator_1.IsNotEmpty)(),
104
+ __metadata("design:type", String)
105
+ ], SetOverrideDto.prototype, "provider", void 0);
99
106
  __decorate([
100
107
  (0, class_validator_1.IsOptional)(),
101
108
  (0, class_validator_1.IsIn)(VALID_AUTH_TYPES),
@@ -20,6 +20,7 @@ const typeorm_2 = require("typeorm");
20
20
  const user_provider_entity_1 = require("../../entities/user-provider.entity");
21
21
  const custom_provider_entity_1 = require("../../entities/custom-provider.entity");
22
22
  const provider_model_fetcher_service_1 = require("./provider-model-fetcher.service");
23
+ const provider_model_registry_service_1 = require("./provider-model-registry.service");
23
24
  const crypto_util_1 = require("../../common/utils/crypto.util");
24
25
  const quality_score_util_1 = require("../../database/quality-score.util");
25
26
  const pricing_sync_service_1 = require("../../database/pricing-sync.service");
@@ -32,12 +33,14 @@ let ModelDiscoveryService = ModelDiscoveryService_1 = class ModelDiscoveryServic
32
33
  customProviderRepo;
33
34
  fetcher;
34
35
  pricingSync;
36
+ modelRegistry;
35
37
  logger = new common_1.Logger(ModelDiscoveryService_1.name);
36
- constructor(providerRepo, customProviderRepo, fetcher, pricingSync) {
38
+ constructor(providerRepo, customProviderRepo, fetcher, pricingSync, modelRegistry) {
37
39
  this.providerRepo = providerRepo;
38
40
  this.customProviderRepo = customProviderRepo;
39
41
  this.fetcher = fetcher;
40
42
  this.pricingSync = pricingSync;
43
+ this.modelRegistry = modelRegistry;
41
44
  }
42
45
  async discoverModels(provider) {
43
46
  let apiKey = '';
@@ -72,8 +75,12 @@ let ModelDiscoveryService = ModelDiscoveryService_1 = class ModelDiscoveryServic
72
75
  }
73
76
  else {
74
77
  raw = await this.fetcher.fetch(provider.provider, apiKey, provider.auth_type, endpointOverride);
78
+ if (raw.length > 0 && this.modelRegistry) {
79
+ this.modelRegistry.registerModels(provider.provider, raw.map((m) => m.id));
80
+ }
75
81
  if (raw.length === 0) {
76
- raw = (0, model_fallback_1.buildFallbackModels)(this.pricingSync, provider.provider);
82
+ const confirmed = this.modelRegistry?.getConfirmedModels(provider.provider) ?? null;
83
+ raw = (0, model_fallback_1.buildFallbackModels)(this.pricingSync, provider.provider, confirmed);
77
84
  if (raw.length > 0) {
78
85
  this.logger.log(`Native API returned 0 models for ${provider.provider} — using ${raw.length} models from pricing data`);
79
86
  }
@@ -215,8 +222,10 @@ exports.ModelDiscoveryService = ModelDiscoveryService = ModelDiscoveryService_1
215
222
  __param(1, (0, typeorm_1.InjectRepository)(custom_provider_entity_1.CustomProvider)),
216
223
  __param(3, (0, common_1.Optional)()),
217
224
  __param(3, (0, common_1.Inject)(pricing_sync_service_1.PricingSyncService)),
225
+ __param(4, (0, common_1.Optional)()),
226
+ __param(4, (0, common_1.Inject)(provider_model_registry_service_1.ProviderModelRegistryService)),
218
227
  __metadata("design:paramtypes", [typeorm_2.Repository,
219
228
  typeorm_2.Repository,
220
- provider_model_fetcher_service_1.ProviderModelFetcherService, Object])
229
+ provider_model_fetcher_service_1.ProviderModelFetcherService, Object, Object])
221
230
  ], ModelDiscoveryService);
222
231
  //# sourceMappingURL=model-discovery.service.js.map
@@ -7,6 +7,12 @@ exports.buildSubscriptionFallbackModels = buildSubscriptionFallbackModels;
7
7
  exports.supplementWithKnownModels = supplementWithKnownModels;
8
8
  const providers_1 = require("../../common/constants/providers");
9
9
  const subscription_capabilities_1 = require("../../../../subscription-capabilities");
10
+ const anthropic_model_id_1 = require("../../common/utils/anthropic-model-id");
11
+ function normalizeProviderModelId(providerId, modelId) {
12
+ return providerId.toLowerCase() === 'anthropic'
13
+ ? (0, anthropic_model_id_1.normalizeAnthropicShortModelId)(modelId)
14
+ : modelId;
15
+ }
10
16
  function findOpenRouterPrefix(providerId) {
11
17
  const lower = providerId.toLowerCase();
12
18
  if (providers_1.OPENROUTER_PREFIX_TO_PROVIDER.has(lower))
@@ -54,20 +60,23 @@ function lookupWithVariants(pricingSync, prefix, modelId) {
54
60
  }
55
61
  return null;
56
62
  }
57
- function buildFallbackModels(pricingSync, providerId) {
63
+ function buildFallbackModels(pricingSync, providerId, confirmedModels) {
58
64
  if (!pricingSync)
59
65
  return [];
60
66
  const models = [];
61
67
  const seen = new Set();
68
+ const hasConfirmed = confirmedModels != null && confirmedModels.size > 0;
62
69
  const orPrefix = findOpenRouterPrefix(providerId);
63
70
  if (!orPrefix)
64
71
  return [];
65
72
  for (const [fullId, entry] of pricingSync.getAll()) {
66
73
  if (!fullId.startsWith(`${orPrefix}/`))
67
74
  continue;
68
- const modelId = fullId.substring(orPrefix.length + 1);
75
+ const modelId = normalizeProviderModelId(providerId, fullId.substring(orPrefix.length + 1));
69
76
  if (seen.has(modelId))
70
77
  continue;
78
+ if (hasConfirmed && !confirmedModels.has(modelId.toLowerCase()))
79
+ continue;
71
80
  seen.add(modelId);
72
81
  models.push({
73
82
  id: modelId,
@@ -96,7 +105,7 @@ function buildSubscriptionFallbackModels(pricingSync, providerId) {
96
105
  for (const [fullId, entry] of pricingSync.getAll()) {
97
106
  if (!fullId.startsWith(`${orPrefix}/`))
98
107
  continue;
99
- const modelId = fullId.substring(orPrefix.length + 1);
108
+ const modelId = normalizeProviderModelId(providerId, fullId.substring(orPrefix.length + 1));
100
109
  if (!normalizedKnownPrefixes.some((p) => modelId.toLowerCase().startsWith(p))) {
101
110
  continue;
102
111
  }
@@ -0,0 +1,84 @@
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
+ var ProviderModelRegistryService_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.ProviderModelRegistryService = void 0;
17
+ const common_1 = require("@nestjs/common");
18
+ const typeorm_1 = require("@nestjs/typeorm");
19
+ const typeorm_2 = require("typeorm");
20
+ const user_provider_entity_1 = require("../../entities/user-provider.entity");
21
+ let ProviderModelRegistryService = ProviderModelRegistryService_1 = class ProviderModelRegistryService {
22
+ providerRepo;
23
+ logger = new common_1.Logger(ProviderModelRegistryService_1.name);
24
+ registry = new Map();
25
+ constructor(providerRepo) {
26
+ this.providerRepo = providerRepo;
27
+ }
28
+ async onApplicationBootstrap() {
29
+ await this.loadFromCache();
30
+ }
31
+ registerModels(providerId, modelIds) {
32
+ const key = providerId.toLowerCase();
33
+ const existing = this.registry.get(key);
34
+ if (existing) {
35
+ for (const id of modelIds)
36
+ existing.add(id.toLowerCase());
37
+ }
38
+ else {
39
+ this.registry.set(key, new Set(modelIds.map((id) => id.toLowerCase())));
40
+ }
41
+ }
42
+ getConfirmedModels(providerId) {
43
+ return this.registry.get(providerId.toLowerCase()) ?? null;
44
+ }
45
+ isModelConfirmed(providerId, modelId) {
46
+ const confirmed = this.registry.get(providerId.toLowerCase());
47
+ if (!confirmed)
48
+ return null;
49
+ return confirmed.has(modelId.toLowerCase());
50
+ }
51
+ async loadFromCache() {
52
+ try {
53
+ const providers = await this.providerRepo
54
+ .createQueryBuilder('p')
55
+ .select(['p.provider', 'p.cached_models'])
56
+ .where('p.cached_models IS NOT NULL')
57
+ .getMany();
58
+ let totalModels = 0;
59
+ for (const p of providers) {
60
+ if (!Array.isArray(p.cached_models))
61
+ continue;
62
+ const ids = p.cached_models.map((m) => m.id).filter(Boolean);
63
+ if (ids.length > 0) {
64
+ this.registerModels(p.provider, ids);
65
+ totalModels += ids.length;
66
+ }
67
+ }
68
+ const providerCount = this.registry.size;
69
+ if (providerCount > 0) {
70
+ this.logger.log(`Provider model registry loaded: ${providerCount} providers, ${totalModels} model entries`);
71
+ }
72
+ }
73
+ catch (err) {
74
+ this.logger.warn(`Failed to load provider model registry from cache: ${err}`);
75
+ }
76
+ }
77
+ };
78
+ exports.ProviderModelRegistryService = ProviderModelRegistryService;
79
+ exports.ProviderModelRegistryService = ProviderModelRegistryService = ProviderModelRegistryService_1 = __decorate([
80
+ (0, common_1.Injectable)(),
81
+ __param(0, (0, typeorm_1.InjectRepository)(user_provider_entity_1.UserProvider)),
82
+ __metadata("design:paramtypes", [typeorm_2.Repository])
83
+ ], ProviderModelRegistryService);
84
+ //# sourceMappingURL=provider-model-registry.service.js.map