katt 0.0.2 → 0.0.3

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +168 -168
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Katt is a lightweight testing framework for running AI Evals, inspired by [Jest](https://github.com/jestjs/jest).
4
4
 
5
- <img src="docs/logo.png" alt="Katt logo" width="250" />
5
+ <img src="https://raw.githubusercontent.com/raphaelpor/katt/main/docs/logo.png" alt="Katt logo" width="250" />
6
6
 
7
7
  ## Overview
8
8
 
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { AsyncLocalStorage as E } from "node:async_hooks";
3
3
  import { CopilotClient as et } from "@github/copilot-sdk";
4
- import { readFile as M, readdir as nt } from "node:fs/promises";
5
- import { resolve as x, dirname as T, isAbsolute as ot, basename as it, join as st } from "node:path";
6
- import { readFileSync as Y, writeFileSync as Z, mkdirSync as rt } from "node:fs";
4
+ import { readFile as O, readdir as nt } from "node:fs/promises";
5
+ import { resolve as F, dirname as N, isAbsolute as ot, basename as st, join as it } from "node:path";
6
+ import { readFileSync as H, writeFileSync as R, mkdirSync as rt } from "node:fs";
7
7
  import { fileURLToPath as ct, pathToFileURL as at } from "node:url";
8
8
  const D = new E(), lt = {
9
9
  describeStack: [],
@@ -11,13 +11,13 @@ const D = new E(), lt = {
11
11
  tokenUsageStack: [],
12
12
  modelStack: []
13
13
  };
14
- let U = 0, W = 0;
15
- const w = [], A = [];
16
- let J = 0;
14
+ let M = 0, G = 0;
15
+ const A = [], $ = [];
16
+ let T = 0;
17
17
  function u() {
18
18
  return D.getStore() ?? lt;
19
19
  }
20
- function H(t) {
20
+ function X(t) {
21
21
  return {
22
22
  describeStack: [...t.describeStack],
23
23
  itStack: [...t.itStack],
@@ -26,25 +26,25 @@ function H(t) {
26
26
  };
27
27
  }
28
28
  function ut() {
29
- return U += 1, `d${U}`;
29
+ return M += 1, `d${M}`;
30
30
  }
31
31
  function dt() {
32
- return W += 1, `i${W}`;
32
+ return G += 1, `i${G}`;
33
33
  }
34
- function X(t, e) {
35
- const n = e ?? H(u());
34
+ function V(t, e) {
35
+ const n = e ?? X(u());
36
36
  return D.run(n, t);
37
37
  }
38
- function z() {
39
- return H(u());
38
+ function P() {
39
+ return X(u());
40
40
  }
41
41
  function gt(t) {
42
42
  u().describeStack.push({ id: ut(), description: t });
43
43
  }
44
- function b() {
44
+ function y() {
45
45
  u().describeStack.pop();
46
46
  }
47
- function P() {
47
+ function Y() {
48
48
  return u().describeStack.map((t) => t.description).join(" > ");
49
49
  }
50
50
  function ft(t) {
@@ -53,7 +53,7 @@ function ft(t) {
53
53
  function v() {
54
54
  u().itStack.pop(), u().tokenUsageStack.pop(), u().modelStack.pop();
55
55
  }
56
- function V() {
56
+ function z() {
57
57
  return u().itStack.map((t) => t.description).join(" > ");
58
58
  }
59
59
  function pt(t) {
@@ -72,112 +72,112 @@ function It(t) {
72
72
  const e = u(), n = e.modelStack.length - 1;
73
73
  n < 0 || (e.modelStack[n] = t);
74
74
  }
75
- function Ct() {
75
+ function mt() {
76
76
  const t = u(), e = t.modelStack.length - 1;
77
77
  if (!(e < 0))
78
78
  return t.modelStack[e];
79
79
  }
80
- function $(t) {
81
- w.push(t);
80
+ function b(t) {
81
+ A.push(t);
82
82
  }
83
- function mt() {
84
- J += 1;
83
+ function Ct() {
84
+ T += 1;
85
85
  }
86
86
  function St() {
87
- return J;
87
+ return T;
88
88
  }
89
- function wt() {
90
- J = 0;
89
+ function At() {
90
+ T = 0;
91
91
  }
92
- function At(t) {
93
- A.push(t);
92
+ function $t(t) {
93
+ $.push(t);
94
94
  }
95
- function $t() {
96
- return [...A];
95
+ function bt() {
96
+ return [...$];
97
97
  }
98
- function B() {
99
- return A.length;
98
+ function U() {
99
+ return $.length;
100
100
  }
101
101
  function kt() {
102
- A.length = 0;
102
+ $.length = 0;
103
103
  }
104
- async function yt() {
104
+ async function wt() {
105
105
  const t = [];
106
- for (; w.length > 0; ) {
107
- const e = w.splice(0, w.length), n = await Promise.allSettled(e);
106
+ for (; A.length > 0; ) {
107
+ const e = A.splice(0, A.length), n = await Promise.allSettled(e);
108
108
  t.push(...n);
109
109
  }
110
110
  return t;
111
111
  }
112
- function bt(t, e) {
113
- X(() => {
112
+ function yt(t, e) {
113
+ V(() => {
114
114
  gt(t);
115
115
  try {
116
116
  const n = e();
117
117
  if (n && typeof n.then == "function") {
118
- $(
118
+ b(
119
119
  n.finally(() => {
120
- b();
120
+ y();
121
121
  })
122
122
  );
123
123
  return;
124
124
  }
125
125
  } catch (n) {
126
- throw b(), n;
126
+ throw y(), n;
127
127
  }
128
- b();
129
- }, z());
128
+ y();
129
+ }, P());
130
130
  }
131
- const vt = "\x1B[1;36m", Lt = "\x1B[33m", jt = "\x1B[38;5;208m", Ft = "\x1B[1;38;5;208m", k = "\x1B[0m";
131
+ const vt = "\x1B[1;36m", Lt = "\x1B[33m", jt = "\x1B[38;5;208m", xt = "\x1B[1;38;5;208m", k = "\x1B[0m";
132
132
  function f(t) {
133
133
  return `${vt}${t}${k}`;
134
134
  }
135
- function m(t) {
135
+ function C(t) {
136
136
  return `${Lt}${t}${k}`;
137
137
  }
138
- function G(t) {
138
+ function W(t) {
139
139
  return `${jt}${t}${k}`;
140
140
  }
141
- function xt(t) {
142
- return `${Ft}${t}${k}`;
141
+ function Ft(t) {
142
+ return `${xt}${t}${k}`;
143
143
  }
144
- let F = "";
145
- function Tt() {
146
- F = "";
144
+ let x = "";
145
+ function Nt() {
146
+ x = "";
147
147
  }
148
- function Jt({
148
+ function Tt({
149
149
  suitePath: t,
150
150
  casePath: e,
151
151
  didPass: n,
152
152
  durationMs: o,
153
- model: s,
154
- tokenUsage: i
153
+ model: i,
154
+ tokenUsage: s
155
155
  }) {
156
156
  const r = t.length > 0 ? t : "(root)", a = e.length > 0 ? e : "(root)";
157
- F !== r && (console.log(`Suite "${f(r)}"`), F = r);
157
+ x !== r && (console.log(`Suite "${f(r)}"`), x = r);
158
158
  const l = n ? "✅ Passed in" : "❌ Failed in", d = [
159
159
  `Test "${f(a)}"`,
160
160
  `- ${l} ${f(`${o}ms`)}`
161
161
  ];
162
- s && d.push(`- Model ${f(s)}`), (i ?? 0) > 0 && d.push(`- Tokens used ${f(String(i))}`), d.push("---"), console.log(d.join(`
162
+ i && d.push(`- Model ${f(i)}`), (s ?? 0) > 0 && d.push(`- Tokens used ${f(String(s))}`), d.push("---"), console.log(d.join(`
163
163
  `));
164
164
  }
165
165
  function I(t, e, n = "(root)") {
166
- const o = V();
167
- Jt({
168
- suitePath: P(),
166
+ const o = z();
167
+ Tt({
168
+ suitePath: Y(),
169
169
  casePath: o.length > 0 ? o : n,
170
170
  didPass: t,
171
171
  durationMs: e,
172
- model: Ct(),
172
+ model: mt(),
173
173
  tokenUsage: ht()
174
174
  });
175
175
  }
176
- const N = new E();
177
- function Nt(t, e) {
176
+ const B = new E();
177
+ function Bt(t, e) {
178
178
  return typeof t == "object" && t !== null && "code" in t && t.code === e;
179
179
  }
180
- function Rt(t) {
180
+ function Jt(t) {
181
181
  try {
182
182
  const e = JSON.parse(t);
183
183
  return typeof e == "object" && e !== null ? e : void 0;
@@ -186,7 +186,7 @@ function Rt(t) {
186
186
  return;
187
187
  }
188
188
  }
189
- function Zt(t) {
189
+ function Rt(t) {
190
190
  const e = t?.copilot;
191
191
  if (typeof e != "object" || e === null || Array.isArray(e))
192
192
  return;
@@ -195,19 +195,19 @@ function Zt(t) {
195
195
  }, o = n.model;
196
196
  return (typeof o != "string" || o.length === 0) && delete n.model, Object.keys(n).length > 0 ? n : void 0;
197
197
  }
198
- async function Ut() {
199
- const t = x(process.cwd(), "katt.json");
198
+ async function Mt() {
199
+ const t = F(process.cwd(), "katt.json");
200
200
  try {
201
- const e = await M(t, "utf8");
202
- return Zt(Rt(e));
201
+ const e = await O(t, "utf8");
202
+ return Rt(Jt(e));
203
203
  } catch (e) {
204
- if (Nt(e, "ENOENT"))
204
+ if (Bt(e, "ENOENT"))
205
205
  return;
206
206
  console.warn(`Failed to read katt.json: ${String(e)}`);
207
207
  return;
208
208
  }
209
209
  }
210
- function K(t) {
210
+ function Q(t) {
211
211
  return typeof t == "string" && t.length > 0 ? t : void 0;
212
212
  }
213
213
  function L(t) {
@@ -215,7 +215,7 @@ function L(t) {
215
215
  return;
216
216
  const e = { ...t };
217
217
  if (e.model !== void 0) {
218
- const n = K(e.model);
218
+ const n = Q(e.model);
219
219
  n ? e.model = n : delete e.model;
220
220
  }
221
221
  return Object.keys(e).length > 0 ? e : void 0;
@@ -223,23 +223,23 @@ function L(t) {
223
223
  function S(t) {
224
224
  return !Number.isFinite(t) || (t ?? 0) <= 0 ? 0 : Math.floor(t ?? 0);
225
225
  }
226
- function Wt(t) {
226
+ function Gt(t) {
227
227
  return S(t.inputTokens) + S(t.outputTokens) + S(t.cacheReadTokens) + S(t.cacheWriteTokens);
228
228
  }
229
- async function y(t, e = {}) {
230
- const n = L(await Ut()), o = L(e), s = L({
229
+ async function w(t, e = {}) {
230
+ const n = L(await Mt()), o = L(e), i = L({
231
231
  ...n ?? {},
232
232
  ...o ?? {}
233
- }), i = K(s?.model), r = new et({ useLoggedInUser: !0 });
233
+ }), s = Q(i?.model), r = new et({ useLoggedInUser: !0 });
234
234
  let a, l, d = 0;
235
235
  try {
236
- await r.start(), a = await r.createSession(s), l = a.on("assistant.usage", (c) => {
237
- d += Wt(c.data);
236
+ await r.start(), a = await r.createSession(i), l = a.on("assistant.usage", (c) => {
237
+ d += Gt(c.data);
238
238
  });
239
239
  const g = await a.sendAndWait({ prompt: t });
240
240
  if (!g?.data?.content)
241
241
  throw new Error("Copilot did not return a response.");
242
- return i && It(i), g.data.content;
242
+ return s && It(s), g.data.content;
243
243
  } finally {
244
244
  const g = [];
245
245
  if (l?.(), d > 0 && pt(d), a)
@@ -259,37 +259,37 @@ async function y(t, e = {}) {
259
259
  );
260
260
  }
261
261
  }
262
- async function Bt(t, e = {}) {
263
- const n = N.getStore(), o = n?.evalFile ? T(n.evalFile) : process.cwd(), s = ot(t) ? t : x(o, t), i = await M(s, "utf8");
264
- return y(i, e);
262
+ async function Ut(t, e = {}) {
263
+ const n = B.getStore(), o = n?.evalFile ? N(n.evalFile) : process.cwd(), i = ot(t) ? t : F(o, t), s = await O(i, "utf8");
264
+ return w(s, e);
265
265
  }
266
266
  function p(t) {
267
- At({
268
- describePath: P(),
269
- itPath: V(),
267
+ $t({
268
+ describePath: Y(),
269
+ itPath: z(),
270
270
  message: t
271
271
  });
272
272
  }
273
- async function Gt(t, e) {
274
- const n = Date.now(), o = `expected '${t}' to satisfy '${e}'`, s = y(`Evaluate if the expectation is fulfiled in by the input.
273
+ async function Wt(t, e) {
274
+ const n = Date.now(), o = `expected '${t}' to satisfy '${e}'`, i = w(`Evaluate if the expectation is fulfiled in by the input.
275
275
  Expectation: "${e}".
276
276
  Input:
277
277
  ---
278
278
  ${t}
279
279
  ---
280
280
  Important: Answer with "Yes" or "No" only, without any additional text.
281
- `).then((i) => {
282
- i.includes("Yes") ? I(!0, Date.now() - n, "promptCheck") : i.includes("No") ? p(o) : p(`failed to evaluate expectation '${e}'`);
281
+ `).then((s) => {
282
+ s.includes("Yes") ? I(!0, Date.now() - n, "promptCheck") : s.includes("No") ? p(o) : p(`failed to evaluate expectation '${e}'`);
283
283
  });
284
- return $(s), s;
284
+ return b(i), i;
285
285
  }
286
- const Ot = 3;
286
+ const Zt = 3;
287
287
  function Et(t) {
288
288
  const e = t.match(/\b([1-5])\b/);
289
289
  return !e || !e[1] ? null : Number(e[1]);
290
290
  }
291
- async function Mt(t, e, n) {
292
- const o = Date.now(), s = n?.threshold ?? Ot, i = y(
291
+ async function Ot(t, e, n) {
292
+ const o = Date.now(), i = n?.threshold ?? Zt, s = w(
293
293
  `Classify the input by how "${e}" it is on a scale of 1 to 5.
294
294
  1 means "not ${e}" and 5 means "very ${e}".
295
295
  Return only a single number: 1, 2, 3, 4, or 5.
@@ -307,8 +307,8 @@ ${t}
307
307
  );
308
308
  return;
309
309
  }
310
- const l = `expected response to be classified as '${e}' with score >= ${s}, got ${a}`;
311
- if (a < s) {
310
+ const l = `expected response to be classified as '${e}' with score >= ${i}, got ${a}`;
311
+ if (a < i) {
312
312
  p(l);
313
313
  return;
314
314
  }
@@ -318,75 +318,75 @@ ${t}
318
318
  "toBeClassifiedAs"
319
319
  );
320
320
  });
321
- return $(i), i;
321
+ return b(s), s;
322
322
  }
323
- function Yt(t, e) {
323
+ function Ht(t, e) {
324
324
  const n = `expected '${t}' to include '${e}'`;
325
325
  t.includes(e) || p(n);
326
326
  }
327
- let _ = !1;
327
+ let K = !1;
328
328
  function Dt(t) {
329
- _ = t;
329
+ K = t;
330
330
  }
331
- function Ht() {
332
- return _;
331
+ function Xt() {
332
+ return K;
333
333
  }
334
- function Xt(t) {
335
- const n = it(t).replace(/\.eval\.[^./\\]+$/, "");
336
- return st(
337
- T(t),
334
+ function Vt(t) {
335
+ const n = st(t).replace(/\.eval\.[^./\\]+$/, "");
336
+ return it(
337
+ N(t),
338
338
  "__snapshots__",
339
339
  `${n}.snap.md`
340
340
  );
341
341
  }
342
- function O(t) {
342
+ function Z(t) {
343
343
  return t.split(/\r?\n/);
344
344
  }
345
- function zt(t, e) {
345
+ function Pt(t, e) {
346
346
  if (t === e)
347
347
  return " (no diff)";
348
- const n = O(t), o = O(e), s = Math.max(n.length, o.length), i = [];
349
- for (let r = 0; r < s; r += 1) {
348
+ const n = Z(t), o = Z(e), i = Math.max(n.length, o.length), s = [];
349
+ for (let r = 0; r < i; r += 1) {
350
350
  const a = n[r], l = o[r];
351
351
  if (a !== l) {
352
352
  if (a === void 0 && l !== void 0) {
353
- i.push(`+ ${l}`);
353
+ s.push(`+ ${l}`);
354
354
  continue;
355
355
  }
356
356
  if (a !== void 0 && l === void 0) {
357
- i.push(`- ${a}`);
357
+ s.push(`- ${a}`);
358
358
  continue;
359
359
  }
360
- i.push(`- ${a ?? ""}`), i.push(`+ ${l ?? ""}`);
360
+ s.push(`- ${a ?? ""}`), s.push(`+ ${l ?? ""}`);
361
361
  }
362
362
  }
363
- return i.join(`
363
+ return s.join(`
364
364
  `);
365
365
  }
366
- function Pt(t) {
367
- const e = N.getStore()?.evalFile;
366
+ function Yt(t) {
367
+ const e = B.getStore()?.evalFile;
368
368
  if (!e) {
369
369
  p(
370
370
  "toMatchSnapshot can only be used while running an eval file."
371
371
  );
372
372
  return;
373
373
  }
374
- const n = Xt(e);
374
+ const n = Vt(e);
375
375
  try {
376
- const o = Y(n, "utf8");
376
+ const o = H(n, "utf8");
377
377
  if (o === t)
378
378
  return;
379
- if (Ht()) {
380
- Z(n, t, "utf8");
379
+ if (Xt()) {
380
+ R(n, t, "utf8");
381
381
  return;
382
382
  }
383
- const s = zt(o, t);
383
+ const i = Pt(o, t);
384
384
  p(
385
385
  [
386
386
  `Snapshot mismatch at ${n}`,
387
387
  "",
388
388
  "Diff:",
389
- s,
389
+ i,
390
390
  "",
391
391
  "Run katt with --update-snapshots (or -u) to accept this change."
392
392
  ].join(`
@@ -400,42 +400,42 @@ function Pt(t) {
400
400
  return;
401
401
  }
402
402
  try {
403
- rt(T(n), { recursive: !0 }), Z(n, t, "utf8");
404
- } catch (i) {
403
+ rt(N(n), { recursive: !0 }), R(n, t, "utf8");
404
+ } catch (s) {
405
405
  p(
406
- `Failed to write snapshot at ${n}: ${String(i)}`
406
+ `Failed to write snapshot at ${n}: ${String(s)}`
407
407
  );
408
408
  }
409
409
  }
410
410
  }
411
- function Vt(t) {
411
+ function zt(t) {
412
412
  return {
413
413
  toContain: (e) => {
414
- Yt(t, e);
414
+ Ht(t, e);
415
415
  },
416
416
  toMatchSnapshot: () => {
417
- Pt(t);
417
+ Yt(t);
418
418
  },
419
419
  promptCheck: async (e) => {
420
- await Gt(t, e);
420
+ await Wt(t, e);
421
421
  },
422
422
  toBeClassifiedAs: async (e, n) => {
423
- await Mt(t, e, n);
423
+ await Ot(t, e, n);
424
424
  }
425
425
  };
426
426
  }
427
- function Kt(t, e) {
428
- X(() => {
429
- mt(), ft(t);
430
- const n = B(), o = Date.now(), s = () => B() === n, i = () => Date.now() - o;
427
+ function Qt(t, e) {
428
+ V(() => {
429
+ Ct(), ft(t);
430
+ const n = U(), o = Date.now(), i = () => U() === n, s = () => Date.now() - o;
431
431
  try {
432
432
  const r = e();
433
433
  if (r && typeof r.then == "function") {
434
- $(
434
+ b(
435
435
  r.then(() => {
436
- I(!0, i());
436
+ I(!0, s());
437
437
  }).catch((a) => {
438
- throw I(!1, i()), a;
438
+ throw I(!1, s()), a;
439
439
  }).finally(() => {
440
440
  v();
441
441
  })
@@ -443,39 +443,39 @@ function Kt(t, e) {
443
443
  return;
444
444
  }
445
445
  } catch (r) {
446
- throw I(!1, i()), v(), r;
446
+ throw I(!1, s()), v(), r;
447
447
  }
448
- I(s(), i()), v();
449
- }, z());
448
+ I(i(), s()), v();
449
+ }, P());
450
450
  }
451
- const _t = /\.eval\.(js|ts)$/, Qt = /* @__PURE__ */ new Set([".git", "node_modules"]);
452
- async function Q(t) {
451
+ const Kt = /\.eval\.(js|ts)$/, _t = /* @__PURE__ */ new Set([".git", "node_modules"]);
452
+ async function _(t) {
453
453
  const e = await nt(t, { withFileTypes: !0 }), n = [];
454
454
  return await Promise.all(
455
455
  e.map(async (o) => {
456
- const s = x(t, o.name);
456
+ const i = F(t, o.name);
457
457
  if (o.isDirectory()) {
458
- if (Qt.has(o.name))
458
+ if (_t.has(o.name))
459
459
  return;
460
- n.push(...await Q(s));
460
+ n.push(...await _(i));
461
461
  return;
462
462
  }
463
- o.isFile() && _t.test(o.name) && n.push(s);
463
+ o.isFile() && Kt.test(o.name) && n.push(i);
464
464
  })
465
465
  ), n;
466
466
  }
467
- const j = new URL("data:application/json;base64,ewogICJuYW1lIjogImthdHQiLAogICJ2ZXJzaW9uIjogIjAuMS4wIiwKICAiZGVzY3JpcHRpb24iOiAiQ0xJIHRvb2wgdGhhdCB0ZXN0cyB0aGUgb3V0cHV0IG9mIGFnZW50aWMgQUkgdG9vbHMiLAogICJrZXl3b3JkcyI6IFsKICAgICJjbGkiLAogICAgImFpIiwKICAgICJhZ2VudGljLWFpIiwKICAgICJ0ZXN0aW5nIiwKICAgICJldmFsdWF0aW9uIgogIF0sCiAgImF1dGhvciI6ICJSYXBoYWVsIFBvcnRvIChodHRwczovL2dpdGh1Yi5jb20vcmFwaGFlbHBvcikiLAogICJsaWNlbnNlIjogIk1JVCIsCiAgInByaXZhdGUiOiB0cnVlLAogICJ0eXBlIjogIm1vZHVsZSIsCiAgIm1haW4iOiAiZGlzdC9pbmRleC5qcyIsCiAgImJpbiI6IHsKICAgICJrYXR0IjogImRpc3QvaW5kZXguanMiCiAgfSwKICAic2NyaXB0cyI6IHsKICAgICJidWlsZCI6ICJ2aXRlIGJ1aWxkIiwKICAgICJkZXYiOiAidHN4IHNyYy9pbmRleC50cyIsCiAgICAibGludCI6ICJiaW9tZSBsaW50IC4vc3JjIiwKICAgICJmb3JtYXQiOiAiYmlvbWUgZm9ybWF0IC0td3JpdGUgLi9zcmMiLAogICAgInRlc3QiOiAidml0ZXN0IiwKICAgICJ0eXBlY2hlY2siOiAidHNjIC1wIHRzY29uZmlnLmpzb24gLS1ub0VtaXQiLAogICAgInRlc3Q6YnVpbGQiOiAibm9kZSAuL2Rpc3QvaW5kZXguanMiCiAgfSwKICAidHlwZXMiOiAiZGlzdC9pbmRleC5kLnRzIiwKICAiZGV2RGVwZW5kZW5jaWVzIjogewogICAgIkBiaW9tZWpzL2Jpb21lIjogIjEuOS40IiwKICAgICJAdHlwZXMvbm9kZSI6ICIyNS4yLjAiLAogICAgInRzeCI6ICI0LjIxLjAiLAogICAgInR5cGVzY3JpcHQiOiAiNS44LjIiLAogICAgInZpdGUiOiAiNy4zLjEiLAogICAgInZpdGUtcGx1Z2luLWR0cyI6ICI0LjUuNCIsCiAgICAidml0ZXN0IjogIjMuMi40IiwKICAgICJ2c2NvZGUtanNvbnJwYyI6ICJeOC4yLjEiCiAgfSwKICAiZGVwZW5kZW5jaWVzIjogewogICAgIkBnaXRodWIvY29waWxvdC1zZGsiOiAiXjAuMS4yMSIKICB9LAogICJidWdzIjogewogICAgInVybCI6ICJodHRwczovL2dpdGh1Yi5jb20vcmFwaGFlbHBvci9rYXR0L2lzc3VlcyIKICB9LAogICJob21lcGFnZSI6ICJodHRwczovL2dpdGh1Yi5jb20vcmFwaGFlbHBvci9rYXR0Igp9Cg==", import.meta.url);
468
- let C;
467
+ const j = new URL("data:application/json;base64,ewogICJuYW1lIjogImthdHQiLAogICJ2ZXJzaW9uIjogIjAuMC4yIiwKICAiZGVzY3JpcHRpb24iOiAiQ0xJIHRvb2wgdGhhdCB0ZXN0cyB0aGUgb3V0cHV0IG9mIGFnZW50aWMgQUkgdG9vbHMiLAogICJrZXl3b3JkcyI6IFsKICAgICJjbGkiLAogICAgImFpIiwKICAgICJhZ2VudGljLWFpIiwKICAgICJ0ZXN0aW5nIiwKICAgICJldmFsdWF0aW9uIgogIF0sCiAgImF1dGhvciI6ICJSYXBoYWVsIFBvcnRvIChodHRwczovL2dpdGh1Yi5jb20vcmFwaGFlbHBvcikiLAogICJsaWNlbnNlIjogIk1JVCIsCiAgInR5cGUiOiAibW9kdWxlIiwKICAibWFpbiI6ICJkaXN0L2luZGV4LmpzIiwKICAiYmluIjogewogICAgImthdHQiOiAiZGlzdC9pbmRleC5qcyIKICB9LAogICJzY3JpcHRzIjogewogICAgImJ1aWxkIjogInZpdGUgYnVpbGQiLAogICAgImRldiI6ICJ0c3ggc3JjL2luZGV4LnRzIiwKICAgICJsaW50IjogImJpb21lIGxpbnQgLi9zcmMiLAogICAgImZvcm1hdCI6ICJiaW9tZSBmb3JtYXQgLS13cml0ZSAuL3NyYyIsCiAgICAidGVzdCI6ICJ2aXRlc3QiLAogICAgInR5cGVjaGVjayI6ICJ0c2MgLXAgdHNjb25maWcuanNvbiAtLW5vRW1pdCIsCiAgICAidGVzdDpidWlsZCI6ICJub2RlIC4vZGlzdC9pbmRleC5qcyIKICB9LAogICJ0eXBlcyI6ICJkaXN0L2luZGV4LmQudHMiLAogICJkZXZEZXBlbmRlbmNpZXMiOiB7CiAgICAiQGJpb21lanMvYmlvbWUiOiAiMS45LjQiLAogICAgIkB0eXBlcy9ub2RlIjogIjI1LjIuMCIsCiAgICAidHN4IjogIjQuMjEuMCIsCiAgICAidHlwZXNjcmlwdCI6ICI1LjguMiIsCiAgICAidml0ZSI6ICI3LjMuMSIsCiAgICAidml0ZS1wbHVnaW4tZHRzIjogIjQuNS40IiwKICAgICJ2aXRlc3QiOiAiMy4yLjQiLAogICAgInZzY29kZS1qc29ucnBjIjogIl44LjIuMSIKICB9LAogICJkZXBlbmRlbmNpZXMiOiB7CiAgICAiQGdpdGh1Yi9jb3BpbG90LXNkayI6ICJeMC4xLjIxIgogIH0sCiAgImJ1Z3MiOiB7CiAgICAidXJsIjogImh0dHBzOi8vZ2l0aHViLmNvbS9yYXBoYWVscG9yL2thdHQvaXNzdWVzIgogIH0sCiAgImhvbWVwYWdlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9yYXBoYWVscG9yL2thdHQiCn0K", import.meta.url);
468
+ let m;
469
469
  function qt() {
470
- if (C !== void 0)
471
- return C;
470
+ if (m !== void 0)
471
+ return m;
472
472
  try {
473
- const t = j.protocol === "data:" ? te(j) : Y(ct(j), "utf8"), e = JSON.parse(t);
474
- C = typeof e.version == "string" ? e.version : "unknown";
473
+ const t = j.protocol === "data:" ? te(j) : H(ct(j), "utf8"), e = JSON.parse(t);
474
+ m = typeof e.version == "string" ? e.version : "unknown";
475
475
  } catch {
476
- C = "unknown";
476
+ m = "unknown";
477
477
  }
478
- return C;
478
+ return m;
479
479
  }
480
480
  function te(t) {
481
481
  const e = t.pathname.indexOf(",");
@@ -485,18 +485,18 @@ function te(t) {
485
485
  return n.includes(";base64") ? Buffer.from(o, "base64").toString("utf8") : decodeURIComponent(o);
486
486
  }
487
487
  function ee() {
488
- const t = " ██╗ ██╗ █████╗ ████████╗████████╗", e = " ██║ ██╔╝██╔══██╗╚══██╔══╝╚══██╔══╝", n = " █████╔╝ ███████║ ██║ ██║", o = " ██╔═██╗ ██╔══██║ ██║ ██║", s = " ██║ ██╗██║ ██║ ██║ ██║", i = " ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝", r = `v${qt()}`, a = Math.max(
488
+ const t = " ██╗ ██╗ █████╗ ████████╗████████╗", e = " ██║ ██╔╝██╔══██╗╚══██╔══╝╚══██╔══╝", n = " █████╔╝ ███████║ ██║ ██║", o = " ██╔═██╗ ██╔══██║ ██║ ██║", i = " ██║ ██╗██║ ██║ ██║ ██║", s = " ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝", r = `v${qt()}`, a = Math.max(
489
489
  0,
490
490
  Math.floor((t.length - r.length) / 2)
491
491
  ), l = `${" ".repeat(a)}${r}`;
492
492
  console.log(`
493
- ${m(t)}
494
- ${m(e)}
495
- ${m(n)}
496
- ${G(o)}
497
- ${G(s)}
498
- ${xt(i)}
499
- ${m(l)}
493
+ ${C(t)}
494
+ ${C(e)}
495
+ ${C(n)}
496
+ ${W(o)}
497
+ ${W(i)}
498
+ ${Ft(s)}
499
+ ${C(l)}
500
500
  `);
501
501
  }
502
502
  function ne(t) {
@@ -507,26 +507,26 @@ async function oe() {
507
507
  const t = process.argv.slice(2), e = t.includes("--update-snapshots") || t.includes("-u");
508
508
  Dt(e), ee();
509
509
  const n = /* @__PURE__ */ new Date();
510
- Tt(), kt(), wt();
511
- const o = await Q(process.cwd());
510
+ Nt(), kt(), At();
511
+ const o = await _(process.cwd());
512
512
  if (o.length === 0)
513
513
  return console.log("No .eval.js or .eval.ts files found."), 1;
514
- const i = (await Promise.allSettled(
514
+ const s = (await Promise.allSettled(
515
515
  o.map(
516
- (c) => N.run(
516
+ (c) => B.run(
517
517
  { evalFile: c },
518
518
  () => import(at(c).href)
519
519
  )
520
520
  )
521
521
  )).map((c, h) => ({ result: c, file: o[h] })).filter(({ result: c }) => c.status === "rejected");
522
- if (i.length > 0) {
523
- for (const c of i) {
522
+ if (s.length > 0) {
523
+ for (const c of s) {
524
524
  const h = c.result.status === "rejected" ? c.result.reason : void 0;
525
525
  console.error(`Error executing ${c.file}: ${String(h)}`);
526
526
  }
527
527
  return 1;
528
528
  }
529
- const a = (await yt()).filter(
529
+ const a = (await wt()).filter(
530
530
  (c) => c.status === "rejected"
531
531
  );
532
532
  if (a.length > 0) {
@@ -534,11 +534,11 @@ async function oe() {
534
534
  c.status === "rejected" && console.error(`Error executing async test: ${String(c.reason)}`);
535
535
  return 1;
536
536
  }
537
- const l = $t();
537
+ const l = bt();
538
538
  if (l.length > 0) {
539
539
  console.error("❌ Failed tests:");
540
540
  for (const [c, h] of l.entries()) {
541
- const R = [h.describePath, h.itPath].filter((tt) => tt.length > 0).join(" > "), q = R.length > 0 ? `${R}: ` : "";
541
+ const J = [h.describePath, h.itPath].filter((tt) => tt.length > 0).join(" > "), q = J.length > 0 ? `${J}: ` : "";
542
542
  console.error(`${c + 1}. ${q}${h.message}`);
543
543
  }
544
544
  return 1;
@@ -555,7 +555,7 @@ async function oe() {
555
555
  `)
556
556
  ), 0;
557
557
  }
558
- Object.assign(globalThis, { describe: bt, it: Kt, expect: Vt, prompt: y, promptFile: Bt });
558
+ Object.assign(globalThis, { describe: yt, it: Qt, expect: zt, prompt: w, promptFile: Ut });
559
559
  oe().then((t) => {
560
560
  process.exit(t);
561
561
  }).catch((t) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "katt",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "CLI tool that tests the output of agentic AI tools",
5
5
  "keywords": [
6
6
  "cli",