smallm 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -6
- package/dist/cache-file.d.ts +38 -4
- package/dist/cache-file.d.ts.map +1 -1
- package/dist/cache-file.js +314 -25
- package/dist/cache-file.js.map +1 -1
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +37 -8
- package/dist/cli.js.map +1 -1
- package/dist/http.d.ts +19 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +57 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -5
- package/dist/index.js.map +1 -1
- package/dist/params.d.ts +6 -1
- package/dist/params.d.ts.map +1 -1
- package/dist/params.js +15 -2
- package/dist/params.js.map +1 -1
- package/dist/query.d.ts +9 -1
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +73 -7
- package/dist/query.js.map +1 -1
- package/dist/registry/huggingface.d.ts +2 -0
- package/dist/registry/huggingface.d.ts.map +1 -1
- package/dist/registry/huggingface.js +81 -11
- package/dist/registry/huggingface.js.map +1 -1
- package/dist/registry/ollama.d.ts +2 -0
- package/dist/registry/ollama.d.ts.map +1 -1
- package/dist/registry/ollama.js +42 -12
- package/dist/registry/ollama.js.map +1 -1
- package/dist/scorer.d.ts.map +1 -1
- package/dist/scorer.js +2 -1
- package/dist/scorer.js.map +1 -1
- package/dist/types.d.ts +10 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/validate.d.ts +22 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +114 -0
- package/dist/validate.js.map +1 -0
- package/package.json +15 -3
|
@@ -1,21 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.huggingfaceProvider = exports.HuggingFaceApiError = void 0;
|
|
3
|
+
exports.huggingfaceProvider = exports.HuggingFaceApiError = exports.FETCH_TIMEOUT_MS = void 0;
|
|
4
4
|
exports.mapTaskToPipelineTag = mapTaskToPipelineTag;
|
|
5
5
|
exports.fetchCandidateModels = fetchCandidateModels;
|
|
6
6
|
const errors_1 = require("../errors");
|
|
7
7
|
Object.defineProperty(exports, "HuggingFaceApiError", { enumerable: true, get: function () { return errors_1.HFApiError; } });
|
|
8
|
+
const validate_1 = require("../validate");
|
|
9
|
+
const http_1 = require("../http");
|
|
8
10
|
const HF_API_BASE = "https://huggingface.co/api/models";
|
|
9
11
|
/** Number of candidates to pull per query, per docx 6.3: fixed fetch limit, no pagination in MVP. */
|
|
10
12
|
const FETCH_LIMIT = 50;
|
|
13
|
+
/** Per-attempt request timeout — without one, a stalled connection hangs the caller forever. */
|
|
14
|
+
exports.FETCH_TIMEOUT_MS = 10000;
|
|
15
|
+
/** Hard cap on the decompressed body — 50 list items is a few tens of KB. */
|
|
16
|
+
const MAX_RESPONSE_BYTES = 5 * 1024 * 1024;
|
|
17
|
+
/** Redirects are followed only to HTTPS huggingface.co / hf.co hosts, at most this many times. */
|
|
18
|
+
const MAX_REDIRECTS = 3;
|
|
19
|
+
const ALLOWED_REDIRECT_HOST = /(^|\.)(huggingface\.co|hf\.co)$/i;
|
|
11
20
|
/** (v0.2) Retry policy: cap at 3 attempts, exponential backoff, only for transient failures. */
|
|
12
21
|
const MAX_RETRIES = 3;
|
|
13
22
|
const BACKOFF_SCHEDULE_MS = [500, 1000, 2000];
|
|
14
23
|
function sleep(ms) {
|
|
15
24
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
16
25
|
}
|
|
17
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* True for 429 (rate limit), any 5xx, and network failures/timeouts (no
|
|
28
|
+
* HTTP status at all) — the only cases worth retrying.
|
|
29
|
+
*/
|
|
18
30
|
function isTransient(status) {
|
|
31
|
+
if (status === undefined)
|
|
32
|
+
return true;
|
|
19
33
|
return status === 429 || (status >= 500 && status < 600);
|
|
20
34
|
}
|
|
21
35
|
/**
|
|
@@ -32,24 +46,81 @@ const TASK_TO_PIPELINE_TAG = {
|
|
|
32
46
|
translate: "translation",
|
|
33
47
|
};
|
|
34
48
|
function mapTaskToPipelineTag(task) {
|
|
35
|
-
|
|
49
|
+
// Own-property check: a plain lookup returns inherited members for tasks
|
|
50
|
+
// like "toString", "constructor" or "__proto__".
|
|
51
|
+
return Object.prototype.hasOwnProperty.call(TASK_TO_PIPELINE_TAG, task) ? TASK_TO_PIPELINE_TAG[task] : task;
|
|
36
52
|
}
|
|
37
53
|
/** A single fetch attempt — no retry logic here, that lives in fetchCandidateModels. */
|
|
54
|
+
function networkFailureReason(err) {
|
|
55
|
+
const name = err?.name;
|
|
56
|
+
return name === "TimeoutError" || name === "AbortError" ? `timed out after ${exports.FETCH_TIMEOUT_MS}ms` : "network error";
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* fetch with redirects followed manually, and only to HTTPS HuggingFace
|
|
60
|
+
* hosts. Default fetch follows any redirect, so a compromised or spoofed
|
|
61
|
+
* upstream could bounce the request to an internal or plain-http URL.
|
|
62
|
+
*/
|
|
63
|
+
async function fetchFollowingSafeRedirects(url, signal) {
|
|
64
|
+
let current = url;
|
|
65
|
+
for (let hop = 0; hop <= MAX_REDIRECTS; hop++) {
|
|
66
|
+
const response = await fetch(current, { signal, redirect: "manual" });
|
|
67
|
+
const location = response.status >= 300 && response.status < 400 ? response.headers?.get?.("location") : null;
|
|
68
|
+
if (!location)
|
|
69
|
+
return response;
|
|
70
|
+
const next = new URL(location, current);
|
|
71
|
+
if (next.protocol !== "https:" || !ALLOWED_REDIRECT_HOST.test(next.hostname)) {
|
|
72
|
+
throw new errors_1.HFApiError(`HuggingFace API redirected to a disallowed location (${next.protocol}//${next.hostname})`, response.status);
|
|
73
|
+
}
|
|
74
|
+
current = next.toString();
|
|
75
|
+
}
|
|
76
|
+
throw new errors_1.HFApiError("HuggingFace API redirected too many times", 310);
|
|
77
|
+
}
|
|
38
78
|
async function fetchOnce(url) {
|
|
39
|
-
|
|
79
|
+
// One timeout covers the redirects, headers and body read together.
|
|
80
|
+
const signal = AbortSignal.timeout(exports.FETCH_TIMEOUT_MS);
|
|
81
|
+
let response;
|
|
82
|
+
try {
|
|
83
|
+
response = await fetchFollowingSafeRedirects(url, signal);
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
if (err instanceof errors_1.HFApiError)
|
|
87
|
+
throw err;
|
|
88
|
+
// Network failure or timeout: wrap in a typed error (no status => retryable).
|
|
89
|
+
throw new errors_1.HFApiError(`HuggingFace API request failed: ${networkFailureReason(err)}`);
|
|
90
|
+
}
|
|
40
91
|
if (!response.ok) {
|
|
41
92
|
if (response.status === 429) {
|
|
42
93
|
throw new errors_1.RateLimitError(`HuggingFace API rate-limited the request (429)`);
|
|
43
94
|
}
|
|
44
95
|
throw new errors_1.HFApiError(`HuggingFace API request failed with status ${response.status}`, response.status);
|
|
45
96
|
}
|
|
46
|
-
|
|
47
|
-
|
|
97
|
+
let data;
|
|
98
|
+
try {
|
|
99
|
+
data = await (0, http_1.readJsonWithLimit)(response, MAX_RESPONSE_BYTES);
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
if (err instanceof http_1.ResponseTooLargeError) {
|
|
103
|
+
throw new errors_1.HFApiError(`HuggingFace API response too large (over ${MAX_RESPONSE_BYTES} bytes)`, response.status);
|
|
104
|
+
}
|
|
105
|
+
if (err instanceof SyntaxError) {
|
|
106
|
+
throw new errors_1.HFApiError("HuggingFace API returned invalid JSON", response.status);
|
|
107
|
+
}
|
|
108
|
+
// Connection dropped or timed out mid-body: retryable, like a failed request.
|
|
109
|
+
throw new errors_1.HFApiError(`HuggingFace API request failed: ${networkFailureReason(err)}`);
|
|
110
|
+
}
|
|
111
|
+
if (!Array.isArray(data)) {
|
|
112
|
+
throw new errors_1.HFApiError("HuggingFace API returned an unexpected response shape", response.status);
|
|
113
|
+
}
|
|
114
|
+
// Runtime shape check: drop items without a safe string id; coerce the rest.
|
|
115
|
+
return data
|
|
116
|
+
.filter((item) => item !== null && typeof item === "object" && (0, validate_1.isSafeModelId)(item.id))
|
|
117
|
+
.slice(0, FETCH_LIMIT)
|
|
118
|
+
.map((item) => ({
|
|
48
119
|
id: item.id,
|
|
49
120
|
provider: "huggingface",
|
|
50
|
-
pipeline_tag: item.pipeline_tag,
|
|
51
|
-
tags: item.tags
|
|
52
|
-
downloads: item.downloads
|
|
121
|
+
pipeline_tag: (0, validate_1.isSafeString)(item.pipeline_tag, 128) ? item.pipeline_tag : undefined,
|
|
122
|
+
tags: (0, validate_1.sanitizeTags)(item.tags),
|
|
123
|
+
downloads: typeof item.downloads === "number" && Number.isFinite(item.downloads) && item.downloads >= 0 ? item.downloads : 0,
|
|
53
124
|
}));
|
|
54
125
|
}
|
|
55
126
|
/**
|
|
@@ -72,8 +143,7 @@ async function fetchCandidateModels(task) {
|
|
|
72
143
|
catch (err) {
|
|
73
144
|
if (!(err instanceof errors_1.HFApiError))
|
|
74
145
|
throw err; // unexpected error shape — don't swallow it
|
|
75
|
-
const
|
|
76
|
-
const canRetry = isTransient(status) && attempt < MAX_RETRIES;
|
|
146
|
+
const canRetry = isTransient(err.status) && attempt < MAX_RETRIES;
|
|
77
147
|
lastError = err;
|
|
78
148
|
if (!canRetry)
|
|
79
149
|
throw err;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"huggingface.js","sourceRoot":"","sources":["../../src/registry/huggingface.ts"],"names":[],"mappings":";;;;;AACA,sCAAuD;oGAA9C,mBAAU;
|
|
1
|
+
{"version":3,"file":"huggingface.js","sourceRoot":"","sources":["../../src/registry/huggingface.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import { Provider } from "./provider";
|
|
2
|
+
/** Local service, so a short timeout: a process holding the port without answering must not hang the call. */
|
|
3
|
+
export declare const OLLAMA_TIMEOUT_MS = 3000;
|
|
2
4
|
export declare const ollamaProvider: Provider;
|
|
3
5
|
//# sourceMappingURL=ollama.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../src/registry/ollama.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../src/registry/ollama.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAYtC,8GAA8G;AAC9G,eAAO,MAAM,iBAAiB,OAAQ,CAAC;AAuHvC,eAAO,MAAM,cAAc,EAAE,QAG5B,CAAC"}
|
package/dist/registry/ollama.js
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ollamaProvider = void 0;
|
|
4
|
-
|
|
5
|
-
const
|
|
3
|
+
exports.ollamaProvider = exports.OLLAMA_TIMEOUT_MS = void 0;
|
|
4
|
+
const validate_1 = require("../validate");
|
|
5
|
+
const http_1 = require("../http");
|
|
6
|
+
/**
|
|
7
|
+
* Default local Ollama REST API address — Ollama's standard port, on the
|
|
8
|
+
* explicit IPv4 loopback address Ollama binds by default. Not "localhost":
|
|
9
|
+
* that resolves to ::1 first on many systems, so any other local user who
|
|
10
|
+
* binds [::1]:11434 would answer instead of the real Ollama.
|
|
11
|
+
*/
|
|
12
|
+
const OLLAMA_API_BASE = "http://127.0.0.1:11434";
|
|
13
|
+
/** Local service, so a short timeout: a process holding the port without answering must not hang the call. */
|
|
14
|
+
exports.OLLAMA_TIMEOUT_MS = 3000;
|
|
15
|
+
/** Cap on how many local models are considered — guards against an absurd response. */
|
|
16
|
+
const MAX_OLLAMA_MODELS = 500;
|
|
17
|
+
/** Hard cap on the decompressed /api/tags body (~1 KB per model). */
|
|
18
|
+
const MAX_OLLAMA_RESPONSE_BYTES = 2 * 1024 * 1024;
|
|
6
19
|
/**
|
|
7
20
|
* Extracts a billions-of-params number from Ollama's `parameter_size`
|
|
8
21
|
* string (e.g. "7B" -> 7, "1.1B" -> 1.1). Returns null if unparseable —
|
|
@@ -11,7 +24,8 @@ const OLLAMA_API_BASE = "http://localhost:11434";
|
|
|
11
24
|
function parseParamsB(parameterSize) {
|
|
12
25
|
if (!parameterSize)
|
|
13
26
|
return null;
|
|
14
|
-
|
|
27
|
+
// (?<!\d): only start at the beginning of a digit run, keeping this linear-time.
|
|
28
|
+
const match = parameterSize.match(/(?<!\d)(\d+(?:\.\d+)?)\s*[bB]/);
|
|
15
29
|
if (!match)
|
|
16
30
|
return null;
|
|
17
31
|
const num = parseFloat(match[1]);
|
|
@@ -35,7 +49,8 @@ function parseParamsB(parameterSize) {
|
|
|
35
49
|
async function listOllamaModels() {
|
|
36
50
|
let response;
|
|
37
51
|
try {
|
|
38
|
-
|
|
52
|
+
// A local service never needs to redirect; refuse instead of following.
|
|
53
|
+
response = await fetch(`${OLLAMA_API_BASE}/api/tags`, { signal: AbortSignal.timeout(exports.OLLAMA_TIMEOUT_MS), redirect: "error" });
|
|
39
54
|
}
|
|
40
55
|
catch {
|
|
41
56
|
console.warn(`[smallm] Could not reach local Ollama at ${OLLAMA_API_BASE} — is Ollama running? Returning no Ollama candidates.`);
|
|
@@ -47,13 +62,28 @@ async function listOllamaModels() {
|
|
|
47
62
|
}
|
|
48
63
|
let data;
|
|
49
64
|
try {
|
|
50
|
-
data = (await
|
|
65
|
+
data = (await (0, http_1.readJsonWithLimit)(response, MAX_OLLAMA_RESPONSE_BYTES));
|
|
51
66
|
}
|
|
52
|
-
catch {
|
|
53
|
-
|
|
67
|
+
catch (err) {
|
|
68
|
+
const reason = err instanceof http_1.ResponseTooLargeError ? "response too large" : "could not parse response";
|
|
69
|
+
console.warn(`[smallm] Local Ollama ${reason} — returning no Ollama candidates.`);
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
const models = data && typeof data === "object" ? data.models ?? [] : null;
|
|
73
|
+
if (!Array.isArray(models)) {
|
|
74
|
+
console.warn("[smallm] Unexpected Ollama response shape — returning no Ollama candidates.");
|
|
54
75
|
return [];
|
|
55
76
|
}
|
|
56
|
-
|
|
77
|
+
// Runtime shape check: drop entries without a safe string name; coerce the rest.
|
|
78
|
+
const valid = models
|
|
79
|
+
.filter((item) => item !== null && typeof item === "object" && (0, validate_1.isSafeModelId)(item.name))
|
|
80
|
+
.slice(0, MAX_OLLAMA_MODELS)
|
|
81
|
+
.map((item) => {
|
|
82
|
+
const details = item.details && typeof item.details === "object" ? item.details : {};
|
|
83
|
+
const parameterSize = (0, validate_1.isSafeString)(details.parameter_size, 32) ? details.parameter_size : undefined;
|
|
84
|
+
return { name: item.name, families: (0, validate_1.sanitizeTags)(details.families), parameterSize };
|
|
85
|
+
});
|
|
86
|
+
return valid.map((item) => ({
|
|
57
87
|
id: item.name,
|
|
58
88
|
provider: "ollama",
|
|
59
89
|
// Ollama doesn't classify models by HF-style pipeline_tag — leaving
|
|
@@ -61,11 +91,11 @@ async function listOllamaModels() {
|
|
|
61
91
|
// can't determine" and lets it through, same as any other missing
|
|
62
92
|
// metadata (not a provider-specific special case).
|
|
63
93
|
pipeline_tag: undefined,
|
|
64
|
-
tags: item.
|
|
94
|
+
tags: item.families,
|
|
65
95
|
// Ollama's local API doesn't expose a download-count concept.
|
|
66
96
|
downloads: 0,
|
|
67
|
-
paramsB: parseParamsB(item.
|
|
68
|
-
paramsSource: item.
|
|
97
|
+
paramsB: parseParamsB(item.parameterSize),
|
|
98
|
+
paramsSource: item.parameterSize ? "tag" : "unknown",
|
|
69
99
|
// Ollama doesn't report context window via this endpoint either — same
|
|
70
100
|
// known limitation already flagged for HuggingFace models elsewhere.
|
|
71
101
|
contextWindow: null,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../src/registry/ollama.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../src/registry/ollama.ts"],"names":[],"mappings":"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"}
|
package/dist/scorer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scorer.d.ts","sourceRoot":"","sources":["../src/scorer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAM3D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;CACf;
|
|
1
|
+
{"version":3,"file":"scorer.d.ts","sourceRoot":"","sources":["../src/scorer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAM3D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;CACf;AAuCD,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,GAAG,cAAc,CASzG;AAID,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,cAAc,GAAG,MAAM,CAwBnE;AAID,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAK9D;AAmBD,+GAA+G;AAC/G,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKjF;AAED,MAAM,WAAW,aAAa;IAC5B,2FAA2F;IAC3F,aAAa,EAAE,cAAc,CAAC;IAC9B,gEAAgE;IAChE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,UAAU,EACjB,mBAAmB,EAAE,MAAM,GAC1B,aAAa,CAmBf;AAED,sGAAsG;AACtG,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAoBxE"}
|
package/dist/scorer.js
CHANGED
|
@@ -42,7 +42,8 @@ function scoreDomain(model, domain) {
|
|
|
42
42
|
if (domain === undefined)
|
|
43
43
|
return NEUTRAL_SCORE; // component not requested
|
|
44
44
|
const tags = model.tags ?? [];
|
|
45
|
-
const
|
|
45
|
+
const wanted = domain.toLowerCase(); // once, not once per tag
|
|
46
|
+
const found = tags.some((tag) => tag.toLowerCase() === wanted);
|
|
46
47
|
return found ? 100 : 0;
|
|
47
48
|
}
|
|
48
49
|
function scoreModel(model, query, expectedPipelineTag) {
|
package/dist/scorer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scorer.js","sourceRoot":"","sources":["../src/scorer.ts"],"names":[],"mappings":";;;;;;;;AACA,6CAAuD;AAEvD,MAAM,aAAa,GAAG,EAAE,CAAC;AACzB,MAAM,aAAa,GAAG,CAAC,CAAC;AAWxB,4CAA4C;AAE5C,oFAAoF;AACpF,SAAS,SAAS,CAAC,KAAc,EAAE,mBAA2B;IAC5D,IAAI,CAAC,KAAK,CAAC,YAAY;QAAE,OAAO,aAAa,CAAC,CAAC,mBAAmB;IAClE,OAAO,KAAK,CAAC,YAAY,KAAK,mBAAmB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,KAAc,EAAE,aAAqB;IACzD,IAAI,KAAK,CAAC,aAAa,IAAI,IAAI;QAAE,OAAO,aAAa,CAAC;IACtD,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,GAAG,aAAa,CAAC,CAAC,kCAAkC;IACrF,MAAM,KAAK,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IAC/C,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,oFAAoF;AACpF,SAAS,SAAS,CAAC,KAAc,EAAE,UAA8B;IAC/D,IAAI,KAAK,CAAC,OAAO,IAAI,IAAI;QAAE,OAAO,aAAa,CAAC,CAAC,mBAAmB;IACpE,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,aAAa,CAAC,CAAC,6BAA6B;IACjF,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,gCAAgC;AAChC,SAAS,WAAW,CAAC,KAAc,EAAE,MAA0B;IAC7D,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,aAAa,CAAC,CAAC,0BAA0B;IAC1E,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"scorer.js","sourceRoot":"","sources":["../src/scorer.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -139,9 +139,17 @@ export interface BenchmarkEntry {
|
|
|
139
139
|
}
|
|
140
140
|
/** Options for the v0.2 file-based cache. */
|
|
141
141
|
export interface CacheOptions {
|
|
142
|
-
/**
|
|
142
|
+
/**
|
|
143
|
+
* Default: a per-user cache dir ($XDG_CACHE_HOME/smallm, ~/.cache/smallm,
|
|
144
|
+
* ~/Library/Caches/smallm, or %LOCALAPPDATA%\smallm\cache). Must be owned
|
|
145
|
+
* by the current user and not world-writable. Never pass untrusted input here.
|
|
146
|
+
* Windows UNC/network and device paths (\\server\share, \\?\, \\.\) are
|
|
147
|
+
* rejected. On Windows, ACLs of a custom directory are NOT checked (Node has
|
|
148
|
+
* no ACL API) — don't point this at a folder other users can write to.
|
|
149
|
+
* If the *default* directory is unusable, an in-memory cache is used instead.
|
|
150
|
+
*/
|
|
143
151
|
dir?: string;
|
|
144
|
-
/** Default: same TTL as MVP's in-memory cache (5 minutes). */
|
|
152
|
+
/** Default: same TTL as MVP's in-memory cache (5 minutes). Values above 7 days are clamped to 7 days. */
|
|
145
153
|
ttlMs?: number;
|
|
146
154
|
}
|
|
147
155
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,gDAAgD;AAChD,MAAM,WAAW,UAAU;IACzB,uFAAuF;IACvF,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAEpF,oFAAoF;IACpF,aAAa,EAAE,MAAM,CAAC;IAEtB;+EAC2E;IAC3E,QAAQ,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,UAAU,GAAG,YAAY,CAAC;IAEzD,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAE5B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAE1B;;;OAGG;IACH,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;CAC5B;AAED,2CAA2C;AAC3C,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE1D,iDAAiD;AACjD,MAAM,MAAM,YAAY,GAAG,aAAa,GAAG,QAAQ,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,oDAAoD;AACpD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,QAAQ,EAAE,YAAY,CAAC;IACvB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,sDAAsD;IACtD,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iFAAiF;IACjF,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY;IACZ,KAAK,EAAE,MAAM,CAAC;IAEd;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB,sGAAsG;IACtG,EAAE,EAAE,MAAM,CAAC;IACX;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,qHAAqH;IACrH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,0HAA0H;IAC1H,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,qFAAqF;IACrF,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC;AAE/B;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;AAI/D;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,KAAK,GAAG,SAAS,GAAG,UAAU,CAAC;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,6CAA6C;AAC7C,MAAM,WAAW,YAAY;IAC3B
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CacheOptions, RawModel } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Characters that can hide or disguise text in a terminal: C0/C1 controls
|
|
4
|
+
* (escape sequences), zero-width characters, bidi overrides/isolates
|
|
5
|
+
* ("Trojan Source"-style reordering), line/paragraph separators and BOM.
|
|
6
|
+
*/
|
|
7
|
+
export declare const UNSAFE_DISPLAY_CHARS: RegExp;
|
|
8
|
+
/** A non-empty, bounded string with no control characters (rules out terminal escape sequences). */
|
|
9
|
+
export declare function isSafeString(value: unknown, maxLength: number): value is string;
|
|
10
|
+
/** Keeps only safe string tags, bounded in count and length. */
|
|
11
|
+
export declare function sanitizeTags(value: unknown): string[];
|
|
12
|
+
export declare function isSafeModelId(value: unknown): value is string;
|
|
13
|
+
/** True only if every element is a well-formed RawModel. A cache entry failing this is treated as a miss. */
|
|
14
|
+
export declare function isRawModelArray(value: unknown): value is RawModel[];
|
|
15
|
+
/** TTLs above this are clamped (not rejected), so an entry can never be pinned "forever". */
|
|
16
|
+
export declare const MAX_CACHE_TTL_MS: number;
|
|
17
|
+
/**
|
|
18
|
+
* Single source of truth for cacheOptions validation (used by validateQuery
|
|
19
|
+
* and by the FileTTLCache constructor). `label` prefixes error messages.
|
|
20
|
+
*/
|
|
21
|
+
export declare function validateCacheOptions(options: unknown, label?: string): asserts options is CacheOptions;
|
|
22
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA8B,QAAQ,EAAE,MAAM,SAAS,CAAC;AAqB7E;;;;GAIG;AAEH,eAAO,MAAM,oBAAoB,QAA8E,CAAC;AAOhH,oGAAoG;AACpG,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,KAAK,IAAI,MAAM,CAE/E;AAMD,gEAAgE;AAChE,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAGrD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAE7D;AAmBD,6GAA6G;AAC7G,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,EAAE,CAEnE;AAID,6FAA6F;AAC7F,eAAO,MAAM,gBAAgB,QAA0B,CAAC;AAWxD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,SAAiB,GAAG,OAAO,CAAC,OAAO,IAAI,YAAY,CAgB9G"}
|
package/dist/validate.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MAX_CACHE_TTL_MS = exports.UNSAFE_DISPLAY_CHARS = void 0;
|
|
4
|
+
exports.isSafeString = isSafeString;
|
|
5
|
+
exports.sanitizeTags = sanitizeTags;
|
|
6
|
+
exports.isSafeModelId = isSafeModelId;
|
|
7
|
+
exports.isRawModelArray = isRawModelArray;
|
|
8
|
+
exports.validateCacheOptions = validateCacheOptions;
|
|
9
|
+
const errors_1 = require("./errors");
|
|
10
|
+
/**
|
|
11
|
+
* Runtime shape checks for data that crosses a trust boundary: HTTP
|
|
12
|
+
* responses (HuggingFace, Ollama) and on-disk cache files. TypeScript casts
|
|
13
|
+
* don't check anything at runtime, so without these a malformed or hostile
|
|
14
|
+
* payload would crash deep inside filters/scorer with a raw TypeError, or
|
|
15
|
+
* inject unexpected values into results.
|
|
16
|
+
*/
|
|
17
|
+
/** Upper bound on a model id's length — HF ids are far shorter; anything longer is junk. */
|
|
18
|
+
const MAX_ID_LENGTH = 256;
|
|
19
|
+
const MAX_TAGS = 100;
|
|
20
|
+
const MAX_TAG_LENGTH = 128;
|
|
21
|
+
/** A cached candidate list is ~50 (HF) or ≤500 (Ollama) entries; anything far beyond that wasn't written by us. */
|
|
22
|
+
const MAX_CACHED_MODELS = 2000;
|
|
23
|
+
const PROVIDERS = new Set(["huggingface", "ollama"]);
|
|
24
|
+
const PARAMS_SOURCES = new Set(["id", "tag", "config", "unknown"]);
|
|
25
|
+
/**
|
|
26
|
+
* Characters that can hide or disguise text in a terminal: C0/C1 controls
|
|
27
|
+
* (escape sequences), zero-width characters, bidi overrides/isolates
|
|
28
|
+
* ("Trojan Source"-style reordering), line/paragraph separators and BOM.
|
|
29
|
+
*/
|
|
30
|
+
// eslint-disable-next-line no-control-regex
|
|
31
|
+
exports.UNSAFE_DISPLAY_CHARS = /[\u0000-\u001f\u007f-\u009f\u200b-\u200f\u2028-\u202e\u2060-\u2069\ufeff]/;
|
|
32
|
+
const CONTROL_CHARS = exports.UNSAFE_DISPLAY_CHARS;
|
|
33
|
+
function isObject(value) {
|
|
34
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
35
|
+
}
|
|
36
|
+
/** A non-empty, bounded string with no control characters (rules out terminal escape sequences). */
|
|
37
|
+
function isSafeString(value, maxLength) {
|
|
38
|
+
return typeof value === "string" && value.length > 0 && value.length <= maxLength && !CONTROL_CHARS.test(value);
|
|
39
|
+
}
|
|
40
|
+
function isFiniteNonNegative(value) {
|
|
41
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
42
|
+
}
|
|
43
|
+
/** Keeps only safe string tags, bounded in count and length. */
|
|
44
|
+
function sanitizeTags(value) {
|
|
45
|
+
if (!Array.isArray(value))
|
|
46
|
+
return [];
|
|
47
|
+
return value.filter((t) => isSafeString(t, MAX_TAG_LENGTH)).slice(0, MAX_TAGS);
|
|
48
|
+
}
|
|
49
|
+
function isSafeModelId(value) {
|
|
50
|
+
return isSafeString(value, MAX_ID_LENGTH);
|
|
51
|
+
}
|
|
52
|
+
/** Strict check that a single value is a well-formed RawModel (used for cache entries). */
|
|
53
|
+
function isRawModel(value) {
|
|
54
|
+
if (!isObject(value))
|
|
55
|
+
return false;
|
|
56
|
+
if (!isSafeModelId(value.id))
|
|
57
|
+
return false;
|
|
58
|
+
if (value.provider !== undefined && (typeof value.provider !== "string" || !PROVIDERS.has(value.provider)))
|
|
59
|
+
return false;
|
|
60
|
+
if (value.pipeline_tag !== undefined && !isSafeString(value.pipeline_tag, MAX_TAG_LENGTH))
|
|
61
|
+
return false;
|
|
62
|
+
if (value.tags !== undefined) {
|
|
63
|
+
if (!Array.isArray(value.tags) || value.tags.length > MAX_TAGS)
|
|
64
|
+
return false;
|
|
65
|
+
if (!value.tags.every((t) => isSafeString(t, MAX_TAG_LENGTH)))
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
if (value.downloads !== undefined && !isFiniteNonNegative(value.downloads))
|
|
69
|
+
return false;
|
|
70
|
+
if (value.paramsB !== undefined && value.paramsB !== null && !isFiniteNonNegative(value.paramsB))
|
|
71
|
+
return false;
|
|
72
|
+
if (value.paramsSource !== undefined && (typeof value.paramsSource !== "string" || !PARAMS_SOURCES.has(value.paramsSource)))
|
|
73
|
+
return false;
|
|
74
|
+
if (value.contextWindow !== undefined && value.contextWindow !== null && !isFiniteNonNegative(value.contextWindow))
|
|
75
|
+
return false;
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
/** True only if every element is a well-formed RawModel. A cache entry failing this is treated as a miss. */
|
|
79
|
+
function isRawModelArray(value) {
|
|
80
|
+
return Array.isArray(value) && value.length <= MAX_CACHED_MODELS && value.every(isRawModel);
|
|
81
|
+
}
|
|
82
|
+
// ---- cacheOptions ----
|
|
83
|
+
/** TTLs above this are clamped (not rejected), so an entry can never be pinned "forever". */
|
|
84
|
+
exports.MAX_CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
85
|
+
/**
|
|
86
|
+
* True for Windows UNC and device paths (\\server\share, //server/share,
|
|
87
|
+
* \\?\..., \\.\...). Creating a directory there makes Windows open an SMB
|
|
88
|
+
* connection, which can leak the account's NTLM hash to whoever runs the server.
|
|
89
|
+
*/
|
|
90
|
+
function isWindowsNetworkOrDevicePath(dir) {
|
|
91
|
+
return /^[\\/]{2}/.test(dir);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Single source of truth for cacheOptions validation (used by validateQuery
|
|
95
|
+
* and by the FileTTLCache constructor). `label` prefixes error messages.
|
|
96
|
+
*/
|
|
97
|
+
function validateCacheOptions(options, label = "cacheOptions") {
|
|
98
|
+
if (typeof options !== "object" || options === null || Array.isArray(options)) {
|
|
99
|
+
throw new errors_1.ValidationError(`${label} must be an object when provided`);
|
|
100
|
+
}
|
|
101
|
+
const { dir, ttlMs } = options;
|
|
102
|
+
if (dir !== undefined) {
|
|
103
|
+
if (typeof dir !== "string" || dir.trim() === "" || dir.includes("\0")) {
|
|
104
|
+
throw new errors_1.ValidationError(`${label}.dir must be a non-empty path string when provided`);
|
|
105
|
+
}
|
|
106
|
+
if (process.platform === "win32" && isWindowsNetworkOrDevicePath(dir)) {
|
|
107
|
+
throw new errors_1.ValidationError(`${label}.dir must be a local path (UNC/network and device paths are not allowed)`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (ttlMs !== undefined && (typeof ttlMs !== "number" || !Number.isFinite(ttlMs) || ttlMs < 0)) {
|
|
111
|
+
throw new errors_1.ValidationError(`${label}.ttlMs must be a finite, non-negative number when provided`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "smallm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Find the right small language model (SLM) for a task, based on given context. Live rule-based matching against the HuggingFace API.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./package.json": "./package.json"
|
|
13
|
+
},
|
|
7
14
|
"bin": {
|
|
8
15
|
"smallm": "dist/cli.js"
|
|
9
16
|
},
|
|
@@ -13,11 +20,16 @@
|
|
|
13
20
|
"directories": {
|
|
14
21
|
"test": "test"
|
|
15
22
|
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18"
|
|
25
|
+
},
|
|
16
26
|
"scripts": {
|
|
27
|
+
"prebuild": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
17
28
|
"build": "tsc",
|
|
18
29
|
"postbuild": "node -e \"try { require('fs').chmodSync('dist/cli.js', 0o755); } catch (e) {}\"",
|
|
19
30
|
"test": "vitest run",
|
|
20
|
-
"test:watch": "vitest"
|
|
31
|
+
"test:watch": "vitest",
|
|
32
|
+
"prepublishOnly": "npm test && npm run build"
|
|
21
33
|
},
|
|
22
34
|
"keywords": [
|
|
23
35
|
"llm",
|
|
@@ -42,4 +54,4 @@
|
|
|
42
54
|
"bugs": {
|
|
43
55
|
"url": "https://github.com/dhruvil05/smallm/issues"
|
|
44
56
|
}
|
|
45
|
-
}
|
|
57
|
+
}
|