@rigour-labs/core 4.3.3 → 4.3.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.
@@ -2,13 +2,13 @@
2
2
  const DEFAULT_MODELS = {
3
3
  claude: 'claude-opus-4-6',
4
4
  anthropic: 'claude-sonnet-4-6',
5
- openai: 'gpt-4o-mini',
6
- gemini: 'gemini-3-flash',
7
- groq: 'llama-3.1-70b-versatile',
5
+ openai: 'gpt-5-mini',
6
+ gemini: 'gemini-2.5-flash',
7
+ groq: 'llama-3.3-70b-versatile',
8
8
  mistral: 'mistral-large-latest',
9
- together: 'meta-llama/Llama-3.1-70B-Instruct-Turbo',
10
- fireworks: 'accounts/fireworks/models/llama-v3p1-70b-instruct',
11
- deepseek: 'deepseek-coder',
9
+ together: 'meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8',
10
+ fireworks: 'accounts/fireworks/models/llama-v3p3-70b-instruct',
11
+ deepseek: 'deepseek-v4',
12
12
  perplexity: 'llama-3.1-sonar-large-128k-online',
13
13
  ollama: 'qwen2.5-coder:7b',
14
14
  lmstudio: 'qwen2.5-coder-7b-instruct',
@@ -13,9 +13,17 @@ export declare function getModelPath(tier: ModelTier): string;
13
13
  * Get model info for a tier.
14
14
  */
15
15
  export declare function getModelInfo(tier: ModelTier): ModelInfo;
16
+ /**
17
+ * Check HuggingFace for a newer model version (like antivirus signature updates).
18
+ * Reads latest_version.json from the RLAIF dataset repo. Non-blocking — if the
19
+ * check fails (offline, HF down), we silently use the cached/bundled version.
20
+ *
21
+ * Results are cached locally for 24 hours to avoid hammering HF on every run.
22
+ */
23
+ export declare function checkForUpdates(onProgress?: (message: string, percent?: number) => void): Promise<string>;
16
24
  /**
17
25
  * Download a model from HuggingFace CDN.
18
- * Tries fine-tuned model first, falls back to stock Qwen if unavailable.
26
+ * Checks for updates first, then tries fine-tuned model, falls back to stock Qwen.
19
27
  */
20
28
  export declare function downloadModel(tier: ModelTier, onProgress?: (message: string, percent?: number) => void): Promise<string>;
21
29
  /**
@@ -6,8 +6,11 @@ import path from 'path';
6
6
  import fs from 'fs-extra';
7
7
  import { createHash } from 'crypto';
8
8
  import { RIGOUR_DIR } from '../storage/db.js';
9
- import { MODELS, FALLBACK_MODELS } from './types.js';
9
+ import { MODELS, FALLBACK_MODELS, VERSION_CHECK_URL, BUNDLED_MODEL_VERSION, updateModelVersion } from './types.js';
10
10
  const MODELS_DIR = path.join(RIGOUR_DIR, 'models');
11
+ const VERSION_CACHE_PATH = path.join(MODELS_DIR, '.latest_version.json');
12
+ const VERSION_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // Check once per day
13
+ const VERSION_CHECK_TIMEOUT_MS = 5000; // 5s timeout — don't block startup
11
14
  const SHA256_RE = /^[a-f0-9]{64}$/i;
12
15
  function getModelMetadataPath(filename) {
13
16
  return path.join(MODELS_DIR, filename + '.meta.json');
@@ -173,12 +176,66 @@ async function downloadFromUrl(tier, model, onProgress) {
173
176
  throw error;
174
177
  }
175
178
  }
179
+ /**
180
+ * Check HuggingFace for a newer model version (like antivirus signature updates).
181
+ * Reads latest_version.json from the RLAIF dataset repo. Non-blocking — if the
182
+ * check fails (offline, HF down), we silently use the cached/bundled version.
183
+ *
184
+ * Results are cached locally for 24 hours to avoid hammering HF on every run.
185
+ */
186
+ export async function checkForUpdates(onProgress) {
187
+ fs.ensureDirSync(MODELS_DIR);
188
+ // Check local version cache first — avoid network on every run
189
+ try {
190
+ if (await fs.pathExists(VERSION_CACHE_PATH)) {
191
+ const cached = await fs.readJson(VERSION_CACHE_PATH);
192
+ const age = Date.now() - new Date(cached.checkedAt).getTime();
193
+ if (age < VERSION_CHECK_INTERVAL_MS && cached.version) {
194
+ const v = String(cached.version);
195
+ updateModelVersion(v);
196
+ return v;
197
+ }
198
+ }
199
+ }
200
+ catch {
201
+ // Corrupted cache — proceed to network check
202
+ }
203
+ // Fetch latest version from HuggingFace (with timeout)
204
+ try {
205
+ const controller = new AbortController();
206
+ const timeout = setTimeout(() => controller.abort(), VERSION_CHECK_TIMEOUT_MS);
207
+ const response = await fetch(VERSION_CHECK_URL, { signal: controller.signal });
208
+ clearTimeout(timeout);
209
+ if (response.ok) {
210
+ const data = await response.json();
211
+ const latestVersion = String(data.version || BUNDLED_MODEL_VERSION);
212
+ // Cache the result locally
213
+ await fs.writeJson(VERSION_CACHE_PATH, {
214
+ version: latestVersion,
215
+ checkedAt: new Date().toISOString(),
216
+ source: 'huggingface',
217
+ }, { spaces: 2 }).catch(() => { });
218
+ // Update in-memory model definitions
219
+ updateModelVersion(latestVersion);
220
+ if (latestVersion !== BUNDLED_MODEL_VERSION) {
221
+ onProgress?.(`Model update available: v${latestVersion}`, 0);
222
+ }
223
+ return latestVersion;
224
+ }
225
+ }
226
+ catch {
227
+ // Offline / HF down / timeout — use bundled version silently
228
+ }
229
+ return BUNDLED_MODEL_VERSION;
230
+ }
176
231
  /**
177
232
  * Download a model from HuggingFace CDN.
178
- * Tries fine-tuned model first, falls back to stock Qwen if unavailable.
233
+ * Checks for updates first, then tries fine-tuned model, falls back to stock Qwen.
179
234
  */
180
235
  export async function downloadModel(tier, onProgress) {
181
236
  fs.ensureDirSync(MODELS_DIR);
237
+ // Check for newer model version (non-blocking, cached 24h)
238
+ await checkForUpdates(onProgress);
182
239
  if (await isModelCached(tier)) {
183
240
  onProgress?.(`Model ${MODELS[tier].name} already cached`, 100);
184
241
  return getModelPath(tier);
@@ -62,7 +62,7 @@ export interface DeepAnalysisResult {
62
62
  * Available model tiers.
63
63
  *
64
64
  * - deep: Qwen2.5-Coder-1.5B fine-tuned — full power, company-hosted
65
- * - lite: Qwen3.5-0.8B fine-tuned — lightweight, ships as default CLI sidecar
65
+ * - lite: Qwen2.5-Coder-0.5B fine-tuned — lightweight, ships as default CLI sidecar
66
66
  * - legacy: Qwen2.5-Coder-0.5B fine-tuned — previous default, reproducibility
67
67
  */
68
68
  export type ModelTier = 'deep' | 'lite' | 'legacy';
@@ -78,13 +78,24 @@ export interface ModelInfo {
78
78
  sizeHuman: string;
79
79
  }
80
80
  /**
81
- * Model version — bump when new fine-tuned GGUF is published.
82
- * The RLAIF pipeline uploads new models to HuggingFace, and
83
- * model-manager checks this version to auto-update.
81
+ * Minimum bundled model version — used as fallback when the auto-update
82
+ * check fails (offline, HF down, first run). The RLAIF training pipeline
83
+ * publishes new versions to HuggingFace and updates latest_version.json.
84
+ * At startup, model-manager checks HF for the latest version and downloads
85
+ * it automatically (like antivirus signature updates).
84
86
  */
85
- export declare const MODEL_VERSION = "1";
86
- /** All supported model definitions */
87
+ export declare const BUNDLED_MODEL_VERSION = "1";
88
+ /** HuggingFace dataset repo where latest_version.json lives */
89
+ export declare const VERSION_CHECK_URL = "https://huggingface.co/datasets/rigour-labs/rigour-rlaif-data/resolve/main/latest_version.json";
90
+ /** Build model info for a given tier and version */
91
+ export declare function buildModelInfo(tier: ModelTier, version: string): ModelInfo;
92
+ /** Current model definitions — initialized with bundled version, updated at runtime */
87
93
  export declare const MODELS: Record<ModelTier, ModelInfo>;
94
+ /**
95
+ * Update MODELS in-place to point to a newer version.
96
+ * Called by model-manager after checking latest_version.json.
97
+ */
98
+ export declare function updateModelVersion(version: string): void;
88
99
  /**
89
100
  * Fallback stock models — used when fine-tuned model is not yet
90
101
  * available on HuggingFace (initial setup / first-time users).
@@ -1,36 +1,46 @@
1
1
  /**
2
- * Model version — bump when new fine-tuned GGUF is published.
3
- * The RLAIF pipeline uploads new models to HuggingFace, and
4
- * model-manager checks this version to auto-update.
2
+ * Minimum bundled model version — used as fallback when the auto-update
3
+ * check fails (offline, HF down, first run). The RLAIF training pipeline
4
+ * publishes new versions to HuggingFace and updates latest_version.json.
5
+ * At startup, model-manager checks HF for the latest version and downloads
6
+ * it automatically (like antivirus signature updates).
5
7
  */
6
- export const MODEL_VERSION = '1';
7
- /** All supported model definitions */
8
+ export const BUNDLED_MODEL_VERSION = '1';
9
+ /** HuggingFace dataset repo where latest_version.json lives */
10
+ export const VERSION_CHECK_URL = 'https://huggingface.co/datasets/rigour-labs/rigour-rlaif-data/resolve/main/latest_version.json';
11
+ /** Build model info for a given tier and version */
12
+ export function buildModelInfo(tier, version) {
13
+ const meta = {
14
+ deep: { base: 'Qwen2.5-Coder-1.5B', size: 900_000_000, sizeH: '900MB' },
15
+ lite: { base: 'Qwen2.5-Coder-0.5B', size: 500_000_000, sizeH: '500MB' },
16
+ legacy: { base: 'Qwen2.5-Coder-0.5B', size: 350_000_000, sizeH: '350MB' },
17
+ };
18
+ const m = meta[tier];
19
+ return {
20
+ tier,
21
+ name: `Rigour-${tier[0].toUpperCase() + tier.slice(1)}-v${version} (${m.base} fine-tuned)`,
22
+ filename: `rigour-${tier}-v${version}-q4_k_m.gguf`,
23
+ url: `https://huggingface.co/rigour-labs/rigour-${tier}-v${version}-gguf/resolve/main/rigour-${tier}-v${version}-q4_k_m.gguf`,
24
+ sizeBytes: m.size,
25
+ sizeHuman: m.sizeH,
26
+ };
27
+ }
28
+ /** Current model definitions — initialized with bundled version, updated at runtime */
8
29
  export const MODELS = {
9
- deep: {
10
- tier: 'deep',
11
- name: 'Rigour-Deep-v1 (Qwen2.5-Coder-1.5B fine-tuned)',
12
- filename: `rigour-deep-v${MODEL_VERSION}-q4_k_m.gguf`,
13
- url: `https://huggingface.co/rigour-labs/rigour-deep-v1-gguf/resolve/main/rigour-deep-v${MODEL_VERSION}-q4_k_m.gguf`,
14
- sizeBytes: 900_000_000,
15
- sizeHuman: '900MB',
16
- },
17
- lite: {
18
- tier: 'lite',
19
- name: 'Rigour-Lite-v1 (Qwen3.5-0.8B fine-tuned)',
20
- filename: `rigour-lite-v${MODEL_VERSION}-q4_k_m.gguf`,
21
- url: `https://huggingface.co/rigour-labs/rigour-lite-v1-gguf/resolve/main/rigour-lite-v${MODEL_VERSION}-q4_k_m.gguf`,
22
- sizeBytes: 500_000_000,
23
- sizeHuman: '500MB',
24
- },
25
- legacy: {
26
- tier: 'legacy',
27
- name: 'Rigour-Legacy-v1 (Qwen2.5-Coder-0.5B fine-tuned)',
28
- filename: `rigour-legacy-v${MODEL_VERSION}-q4_k_m.gguf`,
29
- url: `https://huggingface.co/rigour-labs/rigour-legacy-v1-gguf/resolve/main/rigour-legacy-v${MODEL_VERSION}-q4_k_m.gguf`,
30
- sizeBytes: 350_000_000,
31
- sizeHuman: '350MB',
32
- },
30
+ deep: buildModelInfo('deep', BUNDLED_MODEL_VERSION),
31
+ lite: buildModelInfo('lite', BUNDLED_MODEL_VERSION),
32
+ legacy: buildModelInfo('legacy', BUNDLED_MODEL_VERSION),
33
33
  };
34
+ /**
35
+ * Update MODELS in-place to point to a newer version.
36
+ * Called by model-manager after checking latest_version.json.
37
+ */
38
+ export function updateModelVersion(version) {
39
+ for (const tier of ['deep', 'lite', 'legacy']) {
40
+ const updated = buildModelInfo(tier, version);
41
+ MODELS[tier] = updated;
42
+ }
43
+ }
34
44
  /**
35
45
  * Fallback stock models — used when fine-tuned model is not yet
36
46
  * available on HuggingFace (initial setup / first-time users).
@@ -46,9 +56,9 @@ export const FALLBACK_MODELS = {
46
56
  },
47
57
  lite: {
48
58
  tier: 'lite',
49
- name: 'Qwen3.5-0.8B (stock)',
50
- filename: 'qwen3.5-0.8b-q4_k_m.gguf',
51
- url: 'https://huggingface.co/Qwen/Qwen3.5-0.8B-GGUF/resolve/main/qwen3.5-0.8b-q4_k_m.gguf',
59
+ name: 'Qwen2.5-Coder-0.5B-Instruct (stock)',
60
+ filename: 'qwen2.5-coder-0.5b-instruct-q4_k_m.gguf',
61
+ url: 'https://huggingface.co/Qwen/Qwen2.5-Coder-0.5B-Instruct-GGUF/resolve/main/qwen2.5-coder-0.5b-instruct-q4_k_m.gguf',
52
62
  sizeBytes: 500_000_000,
53
63
  sizeHuman: '500MB',
54
64
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rigour-labs/core",
3
- "version": "4.3.3",
3
+ "version": "4.3.4",
4
4
  "description": "Deterministic quality gate engine for AI-generated code. AST analysis, drift detection, and Fix Packet generation across TypeScript, JavaScript, Python, Go, Ruby, and C#.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://rigour.run",
@@ -59,11 +59,11 @@
59
59
  "@xenova/transformers": "^2.17.2",
60
60
  "better-sqlite3": "^11.0.0",
61
61
  "openai": "^4.104.0",
62
- "@rigour-labs/brain-darwin-arm64": "4.3.3",
63
- "@rigour-labs/brain-linux-arm64": "4.3.3",
64
- "@rigour-labs/brain-darwin-x64": "4.3.3",
65
- "@rigour-labs/brain-win-x64": "4.3.3",
66
- "@rigour-labs/brain-linux-x64": "4.3.3"
62
+ "@rigour-labs/brain-darwin-arm64": "4.3.4",
63
+ "@rigour-labs/brain-darwin-x64": "4.3.4",
64
+ "@rigour-labs/brain-linux-x64": "4.3.4",
65
+ "@rigour-labs/brain-linux-arm64": "4.3.4",
66
+ "@rigour-labs/brain-win-x64": "4.3.4"
67
67
  },
68
68
  "devDependencies": {
69
69
  "@types/better-sqlite3": "^7.6.12",