@siftline/cli 0.1.0 → 0.1.1

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
@@ -33,4 +33,4 @@ ESM only. Node 22.14 or newer.
33
33
 
34
34
  ## Licence
35
35
 
36
- MIT see [LICENSE](./LICENSE).
36
+ MIT. See [LICENSE](./LICENSE).
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { i as API_KEY_ENV, t as run } from "./src-lWwTID7-.mjs";
2
+ import { i as API_KEY_ENV, t as run } from "./src-Ci51FAD3.mjs";
3
3
  import { TypeSafeClient } from "@typesafe-ai/sdk";
4
4
  //#region src/cli.ts
5
5
  const controller = new AbortController();
package/dist/index.d.mts CHANGED
@@ -2,7 +2,7 @@ import { SystemOneClient } from "@siftline/core";
2
2
  //#region src/deps.d.ts
3
3
  /** `process.stdout` and `process.stderr` satisfy this, and so does a string buffer. */
4
4
  interface OutputStream {
5
- write: (chunk: string) => unknown;
5
+ write: (chunk: string) => void;
6
6
  readonly isTTY?: boolean;
7
7
  }
8
8
  /** `process.stdin`, or any async iterable of chunks. */
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { i as API_KEY_ENV, n as USAGE, r as VERSION, t as run } from "./src-lWwTID7-.mjs";
1
+ import { i as API_KEY_ENV, n as USAGE, r as VERSION, t as run } from "./src-Ci51FAD3.mjs";
2
2
  export { API_KEY_ENV, USAGE, VERSION, run };
@@ -1,5 +1,6 @@
1
1
  import { DEFAULT_MAX_IN_FLIGHT, JudgeError, SiftlineError, VERSION, createJudge, parseFixtures, parseRecipe, recordSchema, routeDecision, ruleSchema, serializeDecision, testRecipe, validateFixtures, validateRules } from "@siftline/core";
2
2
  import { readFile } from "node:fs/promises";
3
+ import { z } from "zod";
3
4
  import { parseArgs } from "node:util";
4
5
  //#region src/deps.ts
5
6
  /** A bad invocation. Exit 2, with the usage block. */
@@ -65,21 +66,28 @@ async function readRecords(path, stdin) {
65
66
  async function readStdin(stream) {
66
67
  const decoder = new TextDecoder();
67
68
  let text = "";
68
- for await (const chunk of stream) text += typeof chunk === "string" ? chunk : decoder.decode(chunk, { stream: true });
69
+ for await (const chunk of stream) text += chunk instanceof Uint8Array ? decoder.decode(chunk, { stream: true }) : chunk;
69
70
  return text + decoder.decode();
70
71
  }
71
- /** Zod's issues by duck typing: the CLI states no opinion on the validator core uses. */
72
- function issuesOf(value) {
73
- if (typeof value !== "object" || value === null || !("issues" in value)) return void 0;
74
- const raw = value.issues;
75
- if (!Array.isArray(raw)) return void 0;
76
- const issues = [];
77
- for (const candidate of raw) if (isIssue(candidate)) issues.push(candidate);
72
+ const issueSchema = z.object({
73
+ path: z.array(z.union([
74
+ z.string(),
75
+ z.number(),
76
+ z.symbol()
77
+ ])),
78
+ message: z.string()
79
+ });
80
+ const issuesHolder = z.object({ issues: z.array(z.unknown()) });
81
+ /** Zod's issues by shape, not by class, so a second copy of Zod still reads. */
82
+ function issuesOf(cause) {
83
+ const holder = issuesHolder.safeParse(cause);
84
+ if (!holder.success) return void 0;
85
+ const issues = holder.data.issues.flatMap((candidate) => {
86
+ const issue = issueSchema.safeParse(candidate);
87
+ return issue.success ? [issue.data] : [];
88
+ });
78
89
  return issues.length === 0 ? void 0 : issues;
79
90
  }
80
- function isIssue(value) {
81
- return typeof value === "object" && value !== null && "message" in value && typeof value.message === "string" && "path" in value && Array.isArray(value.path);
82
- }
83
91
  function reason(cause) {
84
92
  const issues = issuesOf(cause);
85
93
  if (issues) return firstIssue(issues);
@@ -119,10 +127,10 @@ function parseTestArgs(args) {
119
127
  return {
120
128
  positionals,
121
129
  options: {
122
- maxInFlight: gateWidth(textValue(values["max-in-flight"])),
123
- minAccuracy: ratio$1(textValue(values["min-accuracy"])),
124
- json: values["json"] === true,
125
- quiet: values["quiet"] === true
130
+ maxInFlight: gateWidth(values["max-in-flight"]),
131
+ minAccuracy: ratio$1(values["min-accuracy"]),
132
+ json: values.json === true,
133
+ quiet: values.quiet === true
126
134
  }
127
135
  };
128
136
  }
@@ -131,24 +139,20 @@ function parseLabelArgs(args) {
131
139
  return {
132
140
  positionals,
133
141
  options: {
134
- maxInFlight: gateWidth(textValue(values["max-in-flight"])),
135
- quiet: values["quiet"] === true,
136
- rules: textValue(values["rules"]) ?? null
142
+ maxInFlight: gateWidth(values["max-in-flight"]),
143
+ quiet: values.quiet === true,
144
+ rules: values.rules ?? null
137
145
  }
138
146
  };
139
147
  }
140
148
  function parseWith(args, flags) {
141
149
  try {
142
- const parsed = parseArgs({
150
+ return parseArgs({
143
151
  args: [...args],
144
152
  options: flags,
145
153
  allowPositionals: true,
146
154
  strict: true
147
155
  });
148
- return {
149
- values: parsed.values,
150
- positionals: parsed.positionals
151
- };
152
156
  } catch (cause) {
153
157
  throw new UsageError(firstSentence(cause), { cause });
154
158
  }
@@ -158,9 +162,6 @@ function requireApiKey(env) {
158
162
  const key = env[API_KEY_ENV];
159
163
  if (key === void 0 || key.trim() === "") throw new UsageError(`${API_KEY_ENV} is not set`);
160
164
  }
161
- function textValue(value) {
162
- return typeof value === "string" ? value : void 0;
163
- }
164
165
  function gateWidth(raw) {
165
166
  if (raw === void 0) return DEFAULT_MAX_IN_FLIGHT;
166
167
  const value = parseNumber(raw);
@@ -385,7 +386,7 @@ async function runTest(args, deps) {
385
386
  //#endregion
386
387
  //#region src/usage.ts
387
388
  /** The published version of `@siftline/cli`, baked in at build time. */
388
- const VERSION$1 = "0.1.0";
389
+ const VERSION$1 = "0.1.1";
389
390
  const USAGE = [
390
391
  `siftline ${VERSION$1} (engine ${VERSION})`,
391
392
  "",
@@ -426,29 +427,29 @@ async function run(argv, deps) {
426
427
  if (command !== "test" && command !== "label") throw new UsageError(`unknown command: ${command}`);
427
428
  requireApiKey(deps.env);
428
429
  return command === "label" ? await runLabel(rest, deps) : await runTest(rest, deps);
429
- } catch (error) {
430
- return exitFor(error, deps);
430
+ } catch (cause) {
431
+ return exitFor(cause, deps);
431
432
  }
432
433
  }
433
434
  /** Every failure's exit code and its one stderr line. */
434
- function exitFor(error, deps) {
435
+ function exitFor(cause, deps) {
435
436
  if (deps.signal?.aborted) {
436
437
  writeLine(deps.stderr, "siftline: interrupted");
437
438
  return 130;
438
439
  }
439
- if (error instanceof UsageError) {
440
- writeLine(deps.stderr, `siftline: ${error.message}\n\n${USAGE}`);
440
+ if (cause instanceof UsageError) {
441
+ writeLine(deps.stderr, `siftline: ${cause.message}\n\n${USAGE}`);
441
442
  return 2;
442
443
  }
443
- if (error instanceof InputError) {
444
- writeLine(deps.stderr, `siftline: ${error.message}`);
444
+ if (cause instanceof InputError) {
445
+ writeLine(deps.stderr, `siftline: ${cause.message}`);
445
446
  return 2;
446
447
  }
447
- if (error instanceof SiftlineError) {
448
- writeLine(deps.stderr, `siftline: ${error.message}`);
449
- return error.code === "fixture_invalid" ? 2 : 1;
448
+ if (cause instanceof SiftlineError) {
449
+ writeLine(deps.stderr, `siftline: ${cause.message}`);
450
+ return cause.code === "fixture_invalid" ? 2 : 1;
450
451
  }
451
- writeLine(deps.stderr, `siftline: ${error instanceof Error ? error.message : String(error)}`);
452
+ writeLine(deps.stderr, `siftline: ${cause instanceof Error ? cause.message : String(cause)}`);
452
453
  return 1;
453
454
  }
454
455
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@siftline/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "The Siftline command line: measure a recipe against its fixtures, then label for real.",
5
5
  "keywords": [
6
6
  "classification",
@@ -45,8 +45,9 @@
45
45
  "typecheck": "tsc --noEmit"
46
46
  },
47
47
  "dependencies": {
48
- "@siftline/core": "^0.1.0",
49
- "@typesafe-ai/sdk": "0.6.0"
48
+ "@siftline/core": "^0.1.1",
49
+ "@typesafe-ai/sdk": "0.6.0",
50
+ "zod": "4.6.5"
50
51
  },
51
52
  "devDependencies": {
52
53
  "@arethetypeswrong/core": "0.18.5",