champollion 0.3.4 → 0.4.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 +41 -26
- package/bin/cli.js +53 -5
- package/index.js +63 -2
- package/lib/api-key.js +17 -4
- package/lib/autofix.js +83 -36
- package/lib/bridge/method_bridge.py +15 -3
- package/lib/cards/reader.js +34 -0
- package/lib/cards/remote.js +15 -0
- package/lib/cards/search-names.js +178 -0
- package/lib/command-help.js +286 -85
- package/lib/commands/audit.js +10 -3
- package/lib/commands/card.js +583 -226
- package/lib/commands/doctor.js +54 -18
- package/lib/commands/help.js +37 -32
- package/lib/commands/init.js +1689 -87
- package/lib/commands/integrity.js +127 -40
- package/lib/commands/leaderboard.js +187 -67
- package/lib/commands/models.js +9 -2
- package/lib/commands/provenance.js +7 -2
- package/lib/commands/recommend.js +43 -14
- package/lib/commands/register-corpus.js +632 -125
- package/lib/commands/seal-corpus.js +1 -1
- package/lib/commands/status.js +564 -27
- package/lib/commands/submit.js +17 -12
- package/lib/commands/sync.js +31 -7
- package/lib/commands/tm.js +15 -9
- package/lib/commands/verify.js +27 -3
- package/lib/commands/wrap.js +63 -5
- package/lib/commands/xliff.js +135 -64
- package/lib/commercial-eligibility.js +1 -1
- package/lib/config.js +196 -14
- package/lib/content-estimate.js +96 -0
- package/lib/content-refusals.js +270 -0
- package/lib/content-review.js +372 -0
- package/lib/content-sync.js +1127 -344
- package/lib/content.js +94 -7
- package/lib/corpus-registration.mjs +194 -35
- package/lib/cost-label.js +29 -0
- package/lib/cost-report.js +726 -78
- package/lib/diff.js +38 -4
- package/lib/docusaurus-sync.js +965 -253
- package/lib/edit-distance.js +31 -0
- package/lib/fallback.js +964 -0
- package/lib/file-scope.js +106 -0
- package/lib/flatten.js +80 -3
- package/lib/flutter-locales.js +124 -0
- package/lib/format.js +266 -12
- package/lib/hash.js +146 -21
- package/lib/icu-structure.js +929 -0
- package/lib/integrity.js +223 -75
- package/lib/language-pair.js +157 -0
- package/lib/lint.js +78 -16
- package/lib/local-only-marks.js +106 -0
- package/lib/locale-layout.js +1103 -0
- package/lib/locale-state.js +571 -0
- package/lib/methods/anthropic.js +5 -0
- package/lib/methods/apertium.js +6 -3
- package/lib/methods/api.js +138 -25
- package/lib/methods/base.js +17 -0
- package/lib/methods/coaching-data.js +153 -0
- package/lib/methods/content-separator.js +43 -0
- package/lib/methods/deepl.js +1 -1
- package/lib/methods/direct-llm.js +252 -103
- package/lib/methods/external.js +146 -63
- package/lib/methods/gemini.js +1 -0
- package/lib/methods/google-translate.js +1 -0
- package/lib/methods/http-utils.js +41 -0
- package/lib/methods/libretranslate.js +7 -2
- package/lib/methods/llm-coached.js +68 -128
- package/lib/methods/llm.js +80 -31
- package/lib/methods/local.js +93 -10
- package/lib/methods/microsoft-translator.js +1 -2
- package/lib/methods/openai.js +4 -2
- package/lib/methods/openrouter-client.js +20 -19
- package/lib/methods/openrouter-pricing.js +150 -13
- package/lib/methods/prompt-methods.js +20 -0
- package/lib/methods/provider-pricing.js +42 -1
- package/lib/methods/request-capture.js +104 -0
- package/lib/methods/tilde.js +1 -1
- package/lib/methods/translated.js +1 -2
- package/lib/missing-key.js +93 -0
- package/lib/models.js +11 -0
- package/lib/name-rules.js +32 -0
- package/lib/named-keys.js +172 -0
- package/lib/no-translate.js +4 -3
- package/lib/output.js +160 -19
- package/lib/pairs.js +586 -30
- package/lib/placeholders.js +394 -0
- package/lib/plugins.js +8 -0
- package/lib/plural-gap-redo.js +109 -0
- package/lib/plurals.js +323 -0
- package/lib/po.js +1187 -0
- package/lib/public-catalogue.js +74 -0
- package/lib/recommend.js +527 -32
- package/lib/redo.js +95 -0
- package/lib/refusal-category.js +44 -0
- package/lib/registers.js +255 -11
- package/lib/repair-script.js +20 -13
- package/lib/scripts.js +6 -1
- package/lib/seal.mjs +4 -3
- package/lib/sealed-qualifier.mjs +1 -1
- package/lib/segment.js +2 -1
- package/lib/seo.js +19 -9
- package/lib/serve.js +43 -6
- package/lib/shared-output-seed.js +164 -0
- package/lib/source-contexts.js +39 -0
- package/lib/submit.mjs +57 -5
- package/lib/sync.js +2923 -474
- package/lib/terminology.js +13 -4
- package/lib/tm-evict.js +179 -0
- package/lib/tm-seed.js +5 -2
- package/lib/tm.js +818 -36
- package/lib/translate-pair.js +639 -34
- package/lib/translate.js +78 -5
- package/lib/types.js +22 -3
- package/lib/validate.js +880 -17
- package/lib/verify.js +1296 -104
- package/lib/watch.js +32 -13
- package/lib/xliff.js +44 -3
- package/package.json +1 -1
- package/shared/CORPORA-CARDS.md +2 -0
- package/shared/cards-fallback.json +1 -1
- package/shared/curated-orthography-conventions.json +26 -8
- package/shared/gettext-plural-forms.json +45 -0
- package/shared/method-registry.json +2 -0
- package/shared/metric-registry.json +96 -18
- package/shared/schemas/champollion-plugin.schema.json +4 -0
- package/shared/schemas/corpora-card.schema.json +8 -2
- package/shared/schemas/method-index-record.schema.json +67 -0
- package/shared/schemas/method-registry.schema.json +4 -0
- package/shared/schemas/metric-registry.schema.json +55 -1
- package/shared/docent/corpus.json +0 -11739
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The public corpus catalogue, read without a key: the `datasets` table the
|
|
3
|
+
* harness and the leaderboard resolve corpora against (anon SELECT, public
|
|
4
|
+
* segments only — mt-eval-arena/supabase/migrations/016_datasets_rls.sql),
|
|
5
|
+
* through the same read-only REST path the CLI already uses for language
|
|
6
|
+
* cards (lib/cards/remote.js fetchJson, lib/cards/env.js endpoint + key).
|
|
7
|
+
*
|
|
8
|
+
* Used by `network register-corpus` on an npm install, which ships no
|
|
9
|
+
* corpora cards: a private / local-only / sealed registration of a file that
|
|
10
|
+
* is a byte-identical copy of a public benchmark must not be graded
|
|
11
|
+
* "Contamination: NONE" just because the comparison was never made (Round 9,
|
|
12
|
+
* researcher persona).
|
|
13
|
+
*
|
|
14
|
+
* PRIVACY: the file's sha256 never leaves the machine. The catalogue's
|
|
15
|
+
* (id, sha256) pairs are downloaded and compared HERE; only a matching
|
|
16
|
+
* PUBLIC id is then looked up for its name and licence.
|
|
17
|
+
*
|
|
18
|
+
* Fail-soft: offline (CHAMPOLLION_OFFLINE=1), unreachable, or an answer that
|
|
19
|
+
* is not the expected shape → `{ ok: false, why }`, never a guess. The caller
|
|
20
|
+
* then records the comparison as not made.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { fetchJson } from './cards/remote.js';
|
|
24
|
+
import { SUPABASE_URL, OFFLINE } from './cards/env.js';
|
|
25
|
+
|
|
26
|
+
/** PostgREST caps a response at 1000 rows on Supabase. */
|
|
27
|
+
const PAGE = 1000;
|
|
28
|
+
/** A bound on the whole read: a catalogue far larger than this is not this table. */
|
|
29
|
+
const MAX_PAGES = 50;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Look for public corpora whose built file has one of these sha256s.
|
|
33
|
+
*
|
|
34
|
+
* @param {string[]} sha256s - lower-case hex digests of the local files
|
|
35
|
+
* @param {{ timeoutMs?: number }} [options]
|
|
36
|
+
* @returns {Promise<{ ok: true, compared: number, hits: Map<string, { id: string, name: string, license: string|null }> }
|
|
37
|
+
* | { ok: false, why: string }>}
|
|
38
|
+
* compared: how many public corpora were compared against; hits: sha256 → corpus
|
|
39
|
+
*/
|
|
40
|
+
export async function findPublicCorporaBySha(sha256s, { timeoutMs = 8000 } = {}) {
|
|
41
|
+
if (OFFLINE) return { ok: false, why: 'offline (CHAMPOLLION_OFFLINE=1)' };
|
|
42
|
+
const wanted = new Set(sha256s.map(s => String(s).toLowerCase()));
|
|
43
|
+
const found = new Map(); // sha → id
|
|
44
|
+
let compared = 0;
|
|
45
|
+
try {
|
|
46
|
+
for (let page = 0; page < MAX_PAGES; page++) {
|
|
47
|
+
const params = new URLSearchParams({
|
|
48
|
+
select: 'id,sha256', sha256: 'not.is.null', order: 'id.asc', limit: String(PAGE), offset: String(page * PAGE),
|
|
49
|
+
});
|
|
50
|
+
// eslint-disable-next-line no-await-in-loop — pages in order; one at a time is polite to the endpoint
|
|
51
|
+
const rows = await fetchJson(`${SUPABASE_URL}/rest/v1/datasets?${params}`, { timeoutMs, retries: 1 });
|
|
52
|
+
if (!Array.isArray(rows)) return { ok: false, why: 'the public catalogue answered in an unexpected shape' };
|
|
53
|
+
for (const r of rows) {
|
|
54
|
+
if (!r || typeof r.sha256 !== 'string') continue;
|
|
55
|
+
compared++;
|
|
56
|
+
const sha = r.sha256.toLowerCase();
|
|
57
|
+
if (wanted.has(sha) && !found.has(sha)) found.set(sha, String(r.id));
|
|
58
|
+
}
|
|
59
|
+
if (rows.length < PAGE) break;
|
|
60
|
+
}
|
|
61
|
+
const hits = new Map();
|
|
62
|
+
for (const [sha, id] of found) {
|
|
63
|
+
const params = new URLSearchParams({ select: 'id,name,license', id: `eq.${id}`, limit: '1' });
|
|
64
|
+
// eslint-disable-next-line no-await-in-loop — at most one lookup per local file
|
|
65
|
+
const [row] = await fetchJson(`${SUPABASE_URL}/rest/v1/datasets?${params}`, { timeoutMs, retries: 1 });
|
|
66
|
+
hits.set(sha, { id, name: row?.name || id, license: row?.license || null });
|
|
67
|
+
}
|
|
68
|
+
if (compared === 0) return { ok: false, why: 'the public catalogue listed no corpus checksums' };
|
|
69
|
+
return { ok: true, compared, hits };
|
|
70
|
+
} catch (err) {
|
|
71
|
+
const reason = err?.status ? `HTTP ${err.status}` : (err?.name === 'TimeoutError' ? 'no answer in time' : (err?.cause?.code || err?.message || 'unreachable'));
|
|
72
|
+
return { ok: false, why: `the public catalogue could not be read (${reason})` };
|
|
73
|
+
}
|
|
74
|
+
}
|