jev-recipes 0.9.1 → 0.9.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/README.md CHANGED
@@ -204,6 +204,8 @@ npx jev-recipes run route input.json
204
204
 
205
205
  Read `result.status` and `result.route` in the JSON output. Substitute another recipe's name in both commands to use a different decision. Run `npx jev-recipes --help` for all commands.
206
206
 
207
+ `run` accepts UTF-8 JSON files and stdin, with or without a byte-order mark (BOM), and UTF-16 files or stdin with a BOM. Non-English text and route names are preserved; no file conversion is needed for these encodings.
208
+
207
209
  The CLI reads environment variables; it does not automatically load `.env`. Errors go to stderr with exit code `1`. A review outcome is a completed evaluation, so inspect the result before acting.
208
210
 
209
211
  <a id="understand-the-result"></a>
package/dist/cli/index.js CHANGED
@@ -106,23 +106,46 @@ async function runLiveRecipe(name, source) {
106
106
  name +
107
107
  ' without a key.');
108
108
  }
109
- const inputJson = source === '-' ? await readStandardInput() : await readFile(source, 'utf8');
109
+ const input = await readJsonInput(source);
110
110
  const run = await loadRecipe(name);
111
- const result = await run(JSON.parse(inputJson));
111
+ const result = await run(input);
112
112
  printJson({ mode: 'live', result });
113
113
  }
114
+ async function readJsonInput(source) {
115
+ const inputBytes = source === '-' ? await readStandardInput() : await readFile(source);
116
+ const inputText = decodeInputText(inputBytes);
117
+ return JSON.parse(inputText);
118
+ }
119
+ async function readStandardInput() {
120
+ const chunks = [];
121
+ for await (const chunk of stdin)
122
+ chunks.push(chunk);
123
+ return Buffer.concat(chunks);
124
+ }
125
+ function decodeInputText(bytes) {
126
+ const encoding = detectInputEncoding(bytes);
127
+ try {
128
+ return new TextDecoder(encoding, { fatal: true }).decode(bytes);
129
+ }
130
+ catch {
131
+ throw new Error('Input must be UTF-8 or UTF-16 with a byte-order mark.');
132
+ }
133
+ }
134
+ function detectInputEncoding(bytes) {
135
+ const byteOrderMark = bytes.subarray(0, 2);
136
+ const utf16LittleEndianMark = Buffer.from([0xff, 0xfe]);
137
+ const utf16BigEndianMark = Buffer.from([0xfe, 0xff]);
138
+ if (byteOrderMark.equals(utf16LittleEndianMark))
139
+ return 'utf-16le';
140
+ if (byteOrderMark.equals(utf16BigEndianMark))
141
+ return 'utf-16be';
142
+ return 'utf-8';
143
+ }
114
144
  async function readDemoFixture(name) {
115
145
  const fixturePath = new URL(`../recipes/${name}/demo.json`, import.meta.url);
116
146
  const fixtureJson = await readFile(fixturePath, 'utf8');
117
147
  return demoFixtureSchema.parse(JSON.parse(fixtureJson));
118
148
  }
119
- async function readStandardInput() {
120
- stdin.setEncoding('utf8');
121
- let input = '';
122
- for await (const chunk of stdin)
123
- input += chunk;
124
- return input;
125
- }
126
149
  function printJson(value) {
127
150
  stdout.write(`${JSON.stringify(value, null, 2)}\n`);
128
151
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jev-recipes",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "description": "248 small Jev decisions for JavaScript and TypeScript: route, rerank, gate, grade, compare, and label text for agents, RAG, support, code review, and music. Each returns a typed result with explicit uncertainty. Plug into Vercel AI SDK or LangChain agents, import one recipe, or run the CLI with JSON from any language.",
5
5
  "type": "module",
6
6
  "license": "MIT",