@trazum/cli 1.50.1 → 1.50.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/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +26 -1
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/es.d.ts.map +1 -1
- package/dist/i18n/es.js +27 -1
- package/dist/i18n/es.js.map +1 -1
- package/dist/i18n/types.d.ts +18 -0
- package/dist/i18n/types.d.ts.map +1 -1
- package/dist/index.js +126 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/i18n/en.ts +31 -1
- package/src/i18n/es.ts +32 -1
- package/src/i18n/types.ts +19 -0
- package/src/index.ts +134 -2
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
2
3
|
import { open, readdir, readFile, stat, writeFile } from 'node:fs/promises';
|
|
3
|
-
import { join, resolve as resolvePath } from 'node:path';
|
|
4
|
+
import { dirname, join, resolve as resolvePath } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
4
6
|
import { gunzipSync } from 'node:zlib';
|
|
5
7
|
import { applyRewrites, BASELINE_FILENAME, BASELINE_VERSION, breaches, cacheableMinimum, analyzeCachePrefix, billLevers, bucketedCacheEconomics, bucketedProfile, buildHistory, buildPlan, connectorFor, CONNECTORS, normalizeAnthropicUsage, normalizeOpenAIUsage, bucketsFromRecords, evaluateWatch, firedKey, pruneRecords, recordsFromBuckets, storeInventory, storedReportFrom, verifyPlan, cacheEconomics, cacheHitRate, contextPressure, comparePrompts, compareToBaseline, computeSavings, countTokensAnthropic, DEFAULT_USAGE, budgetPositions, conform, detectFromSource, matchLocale, parsePlanDocument, waiverDay, waiverHistory, proposeInit, MIN_RATE_DAYS, parseConfig, coverageDrift, driversBetween, explainGateFailure, assignSources, fleetRollup, labelCoverage, measuredUsage, gateMargin, GATE_MARGIN_TIGHT, estimateTokens, evaluate, extractPrompts, findExamples, formatBaseline, formatSignedUsd, formatUsd, getMessages, getModel, hasMarker, LOCALES, MAX_BASELINE_BYTES, moneyIsComparable, mostSpecificMatch, nearestName, optimize, parseBaseline, PHRASE_LANGUAGES, plannedCalls, profilePrompt, profileToCsv, profileUsage, promptId, providerFromEnv, pruneExamples, refineWithLlm, rejectionText, reorderForCache, repriceProfile, reviewAgeDays, reviewExamples, RULES, sharedPrefixes, sharesOf, SOURCE_EXTENSIONS, suggestRewrites, toOtlpMetrics, toPromptfoo, TTL_1H_MS, UNLABELLED, withExactTokenCounts, } from '@trazum/core';
|
|
6
8
|
import { cacheDir, cacheStats, cachingProvider, clearCache } from './suggest-cache.js';
|
|
@@ -287,7 +289,7 @@ function disabledRules(args, config) {
|
|
|
287
289
|
* a threshold is set — `--max-growh 5` would have been ignored and the build
|
|
288
290
|
* gone green. Silence is the wrong answer for a typo.
|
|
289
291
|
*/
|
|
290
|
-
const GLOBAL_FLAGS = ['help', 'h', 'locale', 'json', 'config', 'pricing', 'pricing-live'];
|
|
292
|
+
const GLOBAL_FLAGS = ['help', 'h', 'version', 'v', 'locale', 'json', 'config', 'pricing', 'pricing-live'];
|
|
291
293
|
const COMMAND_FLAGS = {
|
|
292
294
|
optimize: [
|
|
293
295
|
'level', 'model', 'calls', 'output-tokens', 'cache-hit-rate', 'batch',
|
|
@@ -313,6 +315,7 @@ const COMMAND_FLAGS = {
|
|
|
313
315
|
rank: ['level', 'model', 'calls', 'output-tokens', 'batch', 'disable', 'prompt', 'markdown-out'],
|
|
314
316
|
init: ['dry-run', 'yes', 'json', 'pricing', 'pricing-live'],
|
|
315
317
|
conform: ['contract', 'json'],
|
|
318
|
+
feedback: [],
|
|
316
319
|
where: [],
|
|
317
320
|
rules: [],
|
|
318
321
|
blame: ['limit', 'model', 'calls', 'output-tokens', 'batch', 'prompt', 'markdown-out'],
|
|
@@ -1039,6 +1042,43 @@ const INIT_LOG_CANDIDATES = [
|
|
|
1039
1042
|
* answers for a file somebody named while this answers for a repository
|
|
1040
1043
|
* nobody has vouched for.
|
|
1041
1044
|
*/
|
|
1045
|
+
/**
|
|
1046
|
+
* Where feedback goes. Compiled in, never configurable.
|
|
1047
|
+
*
|
|
1048
|
+
* A flag or a config key naming this host would let a fork — or anything that
|
|
1049
|
+
* had rewritten a config on disk — point somebody's bug report, and the
|
|
1050
|
+
* prefilled body with it, at a machine they did not choose. It is one string
|
|
1051
|
+
* and it stays one string.
|
|
1052
|
+
*/
|
|
1053
|
+
/**
|
|
1054
|
+
* Which Trazum this is.
|
|
1055
|
+
*
|
|
1056
|
+
* Read from the manifest beside the built entry point rather than baked in by
|
|
1057
|
+
* a generator, so it cannot drift from what npm installed — the one number a
|
|
1058
|
+
* bug report is useless without is the one that must not be a copy.
|
|
1059
|
+
*
|
|
1060
|
+
* `readFileSync` at module load, deliberately: every other read in this file
|
|
1061
|
+
* is async and inside a command, but a version has to be available to
|
|
1062
|
+
* `--version` before any command is chosen, and one small synchronous read at
|
|
1063
|
+
* startup is cheaper than making the whole entry point await.
|
|
1064
|
+
*
|
|
1065
|
+
* A failure falls back to `unknown` rather than throwing. A tool that will not
|
|
1066
|
+
* start because it cannot find its own manifest is worse than one that admits
|
|
1067
|
+
* it does not know — and `unknown` in a bug report is itself a useful fact
|
|
1068
|
+
* about how somebody installed it.
|
|
1069
|
+
*/
|
|
1070
|
+
const VERSION = (() => {
|
|
1071
|
+
try {
|
|
1072
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
1073
|
+
const manifest = JSON.parse(readFileSync(join(here, '..', 'package.json'), 'utf8'));
|
|
1074
|
+
const found = manifest.version;
|
|
1075
|
+
return typeof found === 'string' ? found : 'unknown';
|
|
1076
|
+
}
|
|
1077
|
+
catch {
|
|
1078
|
+
return 'unknown';
|
|
1079
|
+
}
|
|
1080
|
+
})();
|
|
1081
|
+
const FEEDBACK_REPO = 'https://github.com/Davmunrey/Trazum';
|
|
1042
1082
|
/** Problems listed before the rest are counted. A wall of them helps nobody. */
|
|
1043
1083
|
const MAX_CONFORM_PROBLEMS = 20;
|
|
1044
1084
|
/** The contracts `--contract` accepts, so a typo is refused with the list. */
|
|
@@ -1467,6 +1507,74 @@ async function commandConform(args, t) {
|
|
|
1467
1507
|
}
|
|
1468
1508
|
console.log();
|
|
1469
1509
|
}
|
|
1510
|
+
/**
|
|
1511
|
+
* `trazum feedback` — where to say it, and what to say.
|
|
1512
|
+
*
|
|
1513
|
+
* **This command sends nothing.** Trazum has no telemetry: the CLI makes no
|
|
1514
|
+
* network call it was not explicitly asked to make, and there is no ping, no
|
|
1515
|
+
* install hook and no anonymous counter anywhere in it. That is not an
|
|
1516
|
+
* omission somebody has been meaning to fix — a tool whose entire argument is
|
|
1517
|
+
* that it reads your bill without uploading it cannot also be quietly
|
|
1518
|
+
* reporting on you, and the security suite fails the build if this command
|
|
1519
|
+
* ever reaches the network.
|
|
1520
|
+
*
|
|
1521
|
+
* So the loop is closed the only honest way: the person decides to send
|
|
1522
|
+
* something, and this makes that as cheap as possible. It prints the four
|
|
1523
|
+
* places worth writing to, and a **prefilled link** carrying the facts a
|
|
1524
|
+
* maintainer always has to ask for — version, runtime, platform — printed in
|
|
1525
|
+
* full first, so nothing travels that the sender has not read.
|
|
1526
|
+
*
|
|
1527
|
+
* Nothing about *their work* is in it. Not the config, not a prompt, not a
|
|
1528
|
+
* label, not a figure. Those are the things a bug report needs and the things
|
|
1529
|
+
* only the reporter can decide to share, and a command that helpfully attached
|
|
1530
|
+
* them would be the leak this product exists not to be.
|
|
1531
|
+
*/
|
|
1532
|
+
function commandFeedback(t) {
|
|
1533
|
+
const version = VERSION;
|
|
1534
|
+
/**
|
|
1535
|
+
* Facts about the machine, and nothing about the person.
|
|
1536
|
+
*
|
|
1537
|
+
* `process.platform` and the Node version are what every "cannot reproduce"
|
|
1538
|
+
* thread eventually asks for. The locale is here because Trazum ships two
|
|
1539
|
+
* languages and a report reading wrong in one of them is a real bug class.
|
|
1540
|
+
*/
|
|
1541
|
+
const environment = [
|
|
1542
|
+
`Trazum ${version}`,
|
|
1543
|
+
`Node ${process.version}`,
|
|
1544
|
+
`${process.platform} ${process.arch}`,
|
|
1545
|
+
`locale ${t.locale}`,
|
|
1546
|
+
];
|
|
1547
|
+
const body = [
|
|
1548
|
+
'<!-- What happened, and what you expected instead. -->',
|
|
1549
|
+
'',
|
|
1550
|
+
'',
|
|
1551
|
+
'---',
|
|
1552
|
+
...environment.map((line) => `- ${line}`),
|
|
1553
|
+
].join('\n');
|
|
1554
|
+
const url = `${FEEDBACK_REPO}/issues/new?body=${encodeURIComponent(body)}`;
|
|
1555
|
+
console.log();
|
|
1556
|
+
console.log(c.bold(t.feedback.heading()));
|
|
1557
|
+
console.log(` ${c.dim(wrap(t.feedback.sendsNothing(), 74, ' '))}`);
|
|
1558
|
+
console.log();
|
|
1559
|
+
console.log(c.bold(t.feedback.whereHeading()));
|
|
1560
|
+
console.log(` ${t.feedback.wrongOptimisation()}`);
|
|
1561
|
+
console.log(` ${c.dim(`${FEEDBACK_REPO}/issues/new?template=wrong_optimisation.yml`)}`);
|
|
1562
|
+
console.log(` ${t.feedback.bug()}`);
|
|
1563
|
+
console.log(` ${c.dim(`${FEEDBACK_REPO}/issues/new?template=bug_report.yml`)}`);
|
|
1564
|
+
console.log(` ${t.feedback.question()}`);
|
|
1565
|
+
console.log(` ${c.dim(`${FEEDBACK_REPO}/discussions`)}`);
|
|
1566
|
+
console.log(` ${t.feedback.security()}`);
|
|
1567
|
+
console.log(` ${c.dim(`${FEEDBACK_REPO}/security/advisories/new`)}`);
|
|
1568
|
+
console.log();
|
|
1569
|
+
console.log(c.bold(t.feedback.environmentHeading()));
|
|
1570
|
+
for (const line of environment)
|
|
1571
|
+
console.log(` ${line}`);
|
|
1572
|
+
console.log(` ${c.dim(wrap(t.feedback.environmentOnly(), 74, ' '))}`);
|
|
1573
|
+
console.log();
|
|
1574
|
+
console.log(c.bold(t.feedback.linkHeading()));
|
|
1575
|
+
console.log(` ${url}`);
|
|
1576
|
+
console.log();
|
|
1577
|
+
}
|
|
1470
1578
|
function commandModels(t, pricing) {
|
|
1471
1579
|
const n = (value) => value.toLocaleString(t.numberLocale);
|
|
1472
1580
|
const col = t.models.columns;
|
|
@@ -6265,6 +6373,19 @@ async function main() {
|
|
|
6265
6373
|
console.log(t.cache.cleared(removed, before.bytes, dir));
|
|
6266
6374
|
return;
|
|
6267
6375
|
}
|
|
6376
|
+
/**
|
|
6377
|
+
* Before the help branch, and before the config loads.
|
|
6378
|
+
*
|
|
6379
|
+
* `trazum --version` on its own is how somebody answers "which one is
|
|
6380
|
+
* installed", and it has to work when the config is broken — that is
|
|
6381
|
+
* precisely the moment they are being asked. Placed above `!args.command`
|
|
6382
|
+
* for the same reason `--clear-suggestion-cache` is: with nothing else on
|
|
6383
|
+
* the line, the help branch would have swallowed it.
|
|
6384
|
+
*/
|
|
6385
|
+
if (boolFlag(args, 'version') || boolFlag(args, 'v')) {
|
|
6386
|
+
console.log(VERSION);
|
|
6387
|
+
return;
|
|
6388
|
+
}
|
|
6268
6389
|
if (boolFlag(args, 'help') || boolFlag(args, 'h') || !args.command) {
|
|
6269
6390
|
console.log(t.help({
|
|
6270
6391
|
model: DEFAULT_USAGE.model,
|
|
@@ -6365,6 +6486,9 @@ async function main() {
|
|
|
6365
6486
|
case 'models':
|
|
6366
6487
|
commandModels(t, pricing);
|
|
6367
6488
|
break;
|
|
6489
|
+
case 'feedback':
|
|
6490
|
+
commandFeedback(t);
|
|
6491
|
+
break;
|
|
6368
6492
|
case 'conform':
|
|
6369
6493
|
await commandConform(args, t);
|
|
6370
6494
|
break;
|