katt 0.0.6 → 0.0.8

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/index.js CHANGED
@@ -1,195 +1,231 @@
1
- import { r as $, c as x, p as E, a as d, l, b as p, g as w, d as N, e as P, f as h, s as A, h as S, i as j, j as _, k as O, m as L, n as I, o as U, q as R } from "./runCli-B3oIBxOl.js";
2
- import { t as xt } from "./runCli-B3oIBxOl.js";
3
- import { CopilotClient as z } from "@github/copilot-sdk";
4
- import { readFile as F } from "node:fs/promises";
5
- import { resolve as k, dirname as g, isAbsolute as B, basename as W, join as K } from "node:path";
6
- import { readFileSync as H, writeFileSync as C, mkdirSync as Y } from "node:fs";
7
- function wt(t, e) {
8
- $(() => {
9
- N(), E(t);
10
- const n = w(), o = Date.now(), r = () => w() === n, s = () => Date.now() - o;
1
+ import { r as N, c as I, a as j, p as z, b as C, l as h, d as T, g as D, e as B, f as $, h as H, s as A, i as W, j as L, k as G, m as X, n as Y, o as q, q as K, t as J } from "./runCli-425rgVp8.js";
2
+ import { u as jt } from "./runCli-425rgVp8.js";
3
+ import { CopilotClient as Q } from "@github/copilot-sdk";
4
+ import { mkdtemp as V, rm as Z, readFile as R } from "node:fs/promises";
5
+ import { join as S, dirname as v, isAbsolute as tt, resolve as et, basename as nt } from "node:path";
6
+ import { spawn as ot } from "node:child_process";
7
+ import { tmpdir as rt } from "node:os";
8
+ import { readFileSync as st, writeFileSync as M, mkdirSync as it } from "node:fs";
9
+ function Pt(t, e) {
10
+ N(() => {
11
+ j(), z(t);
12
+ const n = D(), o = Date.now(), i = () => D() === n, s = () => Date.now() - o;
11
13
  try {
12
- const i = e();
13
- if (i && typeof i.then == "function") {
14
- d(
15
- i.then(() => {
16
- l(!0, s());
14
+ const r = e();
15
+ if (r && typeof r.then == "function") {
16
+ C(
17
+ r.then(() => {
18
+ h(!0, s());
17
19
  }).catch((a) => {
18
- throw l(!1, s()), a;
20
+ throw h(!1, s()), a;
19
21
  }).finally(() => {
20
- p();
22
+ T();
21
23
  })
22
24
  );
23
25
  return;
24
26
  }
25
- } catch (i) {
26
- throw l(!1, s()), p(), i;
27
+ } catch (r) {
28
+ throw h(!1, s()), T(), r;
27
29
  }
28
- l(r(), s()), p();
29
- }, x());
30
+ h(i(), s()), T();
31
+ }, I());
30
32
  }
31
- function Ct(t, e) {
32
- $(() => {
33
- P(t);
33
+ function Nt(t, e) {
34
+ N(() => {
35
+ B(t);
34
36
  try {
35
37
  const n = e();
36
38
  if (n && typeof n.then == "function") {
37
- d(
39
+ C(
38
40
  n.finally(() => {
39
- h();
41
+ $();
40
42
  })
41
43
  );
42
44
  return;
43
45
  }
44
46
  } catch (n) {
45
- throw h(), n;
47
+ throw $(), n;
46
48
  }
47
- h();
48
- }, x());
49
+ $();
50
+ }, I());
49
51
  }
50
- function q(t, e) {
52
+ const at = "katt-codex-", ct = "last-message.txt";
53
+ function ut(t, e) {
51
54
  return typeof t == "object" && t !== null && "code" in t && t.code === e;
52
55
  }
53
- function J(t) {
54
- try {
55
- const e = JSON.parse(t);
56
- return typeof e == "object" && e !== null ? e : void 0;
57
- } catch (e) {
58
- console.warn(`Failed to parse katt.json: ${String(e)}`);
59
- return;
60
- }
56
+ function m(t) {
57
+ return typeof t == "string" && t.length > 0;
61
58
  }
62
- async function G() {
63
- const t = k(process.cwd(), "katt.json");
64
- try {
65
- const e = await F(t, "utf8");
66
- return J(e);
67
- } catch (e) {
68
- if (q(e, "ENOENT"))
69
- return;
70
- console.warn(`Failed to read katt.json: ${String(e)}`);
71
- return;
72
- }
59
+ function dt(t) {
60
+ return m(t) ? [t] : Array.isArray(t) ? t.filter(m) : [];
73
61
  }
74
- function Q(t) {
75
- const e = t?.copilot;
76
- if (typeof e != "object" || e === null || Array.isArray(e))
77
- return;
78
- const n = {
79
- ...e
80
- }, o = n.model;
81
- return (typeof o != "string" || o.length === 0) && delete n.model, Object.keys(n).length > 0 ? n : void 0;
62
+ function lt(t, e) {
63
+ const n = e ?? {}, o = [
64
+ "exec",
65
+ "--color",
66
+ "never",
67
+ "--output-last-message",
68
+ t
69
+ ];
70
+ m(n.model) && o.push("--model", n.model), m(n.profile) && o.push("--profile", n.profile), m(n.sandbox) && o.push("--sandbox", n.sandbox), n.fullAuto === !0 && o.push("--full-auto"), n.skipGitRepoCheck === !0 && o.push("--skip-git-repo-check"), n.dangerouslyBypassApprovalsAndSandbox === !0 && o.push("--dangerously-bypass-approvals-and-sandbox");
71
+ for (const i of dt(n.config))
72
+ o.push("--config", i);
73
+ return o.push("-"), o;
82
74
  }
83
- function V(t) {
84
- if (!(typeof t != "number" || !Number.isFinite(t)) && !(t <= 0))
85
- return Math.floor(t);
75
+ function ft(t, e, n, o) {
76
+ return new Promise((i, s) => {
77
+ const r = ot("codex", e, {
78
+ cwd: o,
79
+ stdio: ["pipe", "pipe", "pipe"]
80
+ });
81
+ let a = "", c = "", p = !1;
82
+ r.stdout.setEncoding("utf8"), r.stderr.setEncoding("utf8"), r.stdout.on("data", (u) => {
83
+ a += u;
84
+ }), r.stderr.on("data", (u) => {
85
+ c += u;
86
+ }), r.stdin.on("error", () => {
87
+ });
88
+ const g = setTimeout(() => {
89
+ p = !0, r.kill("SIGTERM");
90
+ }, n);
91
+ r.once("error", (u) => {
92
+ clearTimeout(g), s(
93
+ new Error(
94
+ `Failed to start Codex CLI. Ensure codex is installed and available on PATH. ${String(
95
+ u
96
+ )}`
97
+ )
98
+ );
99
+ }), r.once("close", (u, x) => {
100
+ clearTimeout(g), i({
101
+ exitCode: u,
102
+ signal: x,
103
+ stdout: a.trim(),
104
+ stderr: c.trim(),
105
+ timedOut: p
106
+ });
107
+ }), r.stdin.end(t);
108
+ });
109
+ }
110
+ async function pt(t, e) {
111
+ try {
112
+ return await R(t, "utf8");
113
+ } catch (n) {
114
+ if (!ut(n, "ENOENT"))
115
+ throw n;
116
+ return e;
117
+ }
86
118
  }
87
- function X(t) {
88
- const e = t?.prompt;
89
- if (!(typeof e != "object" || e === null || Array.isArray(e)))
90
- return V(e.timeoutMs);
119
+ function ht(t) {
120
+ if (t.timedOut)
121
+ return "Codex timed out before returning a response.";
122
+ if (t.exitCode === null)
123
+ return `Codex exited due to signal ${t.signal ?? "unknown"}.`;
124
+ const e = t.stderr.length > 0 ? ` ${t.stderr}` : "";
125
+ return `Codex exited with code ${t.exitCode}.${e}`;
91
126
  }
92
- async function Z() {
93
- const t = await G();
94
- return {
95
- copilot: Q(t),
96
- promptTimeoutMs: X(t)
97
- };
127
+ async function mt(t, e, n) {
128
+ const o = n ?? {}, i = m(o.workingDirectory) ? o.workingDirectory : process.cwd(), s = await V(S(rt(), at)), r = S(s, ct);
129
+ try {
130
+ const a = lt(r, n), c = await ft(
131
+ t,
132
+ a,
133
+ e,
134
+ i
135
+ );
136
+ if (c.timedOut)
137
+ throw new Error(`Codex timed out after ${e}ms.`);
138
+ if (c.exitCode !== 0)
139
+ throw new Error(ht(c));
140
+ const p = await pt(r, c.stdout);
141
+ if (p.length === 0)
142
+ throw new Error("Codex did not return a response.");
143
+ return p;
144
+ } finally {
145
+ await Z(s, { recursive: !0, force: !0 });
146
+ }
98
147
  }
99
- const tt = 6e5;
100
- function M(t) {
148
+ const gt = 6e5;
149
+ function U(t) {
101
150
  return typeof t == "string" && t.length > 0 ? t : void 0;
102
151
  }
103
- function m(t) {
152
+ function E(t) {
104
153
  if (!t)
105
154
  return;
106
155
  const e = { ...t };
107
156
  if (e.model !== void 0) {
108
- const n = M(e.model);
157
+ const n = U(
158
+ typeof e.model == "string" ? e.model : void 0
159
+ );
109
160
  n ? e.model = n : delete e.model;
110
161
  }
111
162
  return Object.keys(e).length > 0 ? e : void 0;
112
163
  }
113
- function b(t) {
164
+ function O(t) {
114
165
  if (!(typeof t != "number" || !Number.isFinite(t)) && !(t <= 0))
115
166
  return Math.floor(t);
116
167
  }
117
- function f(t) {
168
+ function y(t) {
118
169
  return !Number.isFinite(t) || (t ?? 0) <= 0 ? 0 : Math.floor(t ?? 0);
119
170
  }
120
- function et(t) {
121
- return f(t.inputTokens) + f(t.outputTokens) + f(t.cacheReadTokens) + f(t.cacheWriteTokens);
171
+ function xt(t) {
172
+ return y(t.inputTokens) + y(t.outputTokens) + y(t.cacheReadTokens) + y(t.cacheWriteTokens);
122
173
  }
123
- function nt(t, e) {
124
- const { timeoutMs: n, ...o } = t, r = m(e.copilot), s = m(
174
+ async function F(t, e = {}) {
175
+ const { timeoutMs: n, ...o } = e, i = await H(), s = E(i.agentOptions), r = E(
125
176
  o
126
- ), i = m({
127
- ...r ?? {},
128
- ...s ?? {}
129
- }), a = b(e.promptTimeoutMs), D = b(n) ?? a ?? tt;
130
- return {
131
- sessionOptions: i,
132
- model: M(i?.model),
133
- timeoutMs: D
134
- };
135
- }
136
- async function ot(t, e) {
137
- const n = [];
138
- if (e.unsubscribeUsage?.(), e.usedTokens > 0 && j(e.usedTokens), e.session)
139
- try {
140
- await e.session.destroy();
141
- } catch (o) {
142
- n.push(o);
143
- }
144
- try {
145
- const o = await t.stop();
146
- n.push(...o);
147
- } catch (o) {
148
- n.push(o);
149
- }
150
- n.length > 0 && console.error(
151
- `Copilot cleanup encountered ${n.length} error(s).`
177
+ ), a = E({
178
+ ...s ?? {},
179
+ ...r ?? {}
180
+ }), c = O(i.promptTimeoutMs), g = O(n) ?? c ?? gt, u = U(
181
+ typeof a?.model == "string" ? a.model : void 0
152
182
  );
153
- }
154
- async function y(t, e = {}) {
155
- const n = await Z(), o = nt(e, n), r = new z({ useLoggedInUser: !0 }), s = {
156
- session: void 0,
157
- unsubscribeUsage: void 0,
158
- usedTokens: 0
159
- };
183
+ if (i.agent === "codex") {
184
+ const d = await mt(t, g, a);
185
+ return u && A(u), d;
186
+ }
187
+ const x = new Q({ useLoggedInUser: !0 });
188
+ let w, k, b = 0;
160
189
  try {
161
- await r.start(), s.session = await r.createSession(
162
- o.sessionOptions
163
- ), s.unsubscribeUsage = s.session.on(
164
- "assistant.usage",
165
- (a) => {
166
- s.usedTokens += et(a.data);
167
- }
168
- );
169
- const i = await s.session.sendAndWait(
170
- { prompt: t },
171
- o.timeoutMs
172
- );
173
- if (!i?.data?.content)
190
+ await x.start(), w = await x.createSession(a), k = w.on("assistant.usage", (f) => {
191
+ b += xt(f.data);
192
+ });
193
+ const d = await w.sendAndWait({ prompt: t }, g);
194
+ if (!d?.data?.content)
174
195
  throw new Error("Copilot did not return a response.");
175
- return o.model && A(o.model), i.data.content;
196
+ return u && A(u), d.data.content;
176
197
  } finally {
177
- await ot(r, s);
198
+ const d = [];
199
+ if (k?.(), b > 0 && W(b), w)
200
+ try {
201
+ await w.destroy();
202
+ } catch (f) {
203
+ d.push(f);
204
+ }
205
+ try {
206
+ const f = await x.stop();
207
+ d.push(...f);
208
+ } catch (f) {
209
+ d.push(f);
210
+ }
211
+ d.length > 0 && console.error(
212
+ `Copilot cleanup encountered ${d.length} error(s).`
213
+ );
178
214
  }
179
215
  }
180
- async function bt(t, e = {}) {
181
- const n = S.getStore(), o = n?.evalFile ? g(n.evalFile) : process.cwd(), r = B(t) ? t : k(o, t), s = await F(r, "utf8");
182
- return y(s, e);
216
+ async function It(t, e = {}) {
217
+ const n = L.getStore(), o = n?.evalFile ? v(n.evalFile) : process.cwd(), i = tt(t) ? t : et(o, t), s = await R(i, "utf8");
218
+ return F(s, e);
183
219
  }
184
- function c(t) {
185
- _({
186
- describePath: L(),
187
- itPath: O(),
220
+ function l(t) {
221
+ G({
222
+ describePath: Y(),
223
+ itPath: X(),
188
224
  message: t
189
225
  });
190
226
  }
191
- async function st(t, e) {
192
- const n = Date.now(), o = `expected '${t}' to satisfy '${e}'`, r = y(`Evaluate if the expectation is fulfiled in by the input.
227
+ async function wt(t, e) {
228
+ const n = Date.now(), o = `expected '${t}' to satisfy '${e}'`, i = F(`Evaluate if the expectation is fulfiled in by the input.
193
229
  Expectation: "${e}".
194
230
  Input:
195
231
  ---
@@ -197,17 +233,17 @@ async function st(t, e) {
197
233
  ---
198
234
  Important: Answer with "Yes" or "No" only, without any additional text.
199
235
  `).then((s) => {
200
- s.includes("Yes") ? l(!0, Date.now() - n, "promptCheck") : s.includes("No") ? c(o) : c(`failed to evaluate expectation '${e}'`);
236
+ s.includes("Yes") ? h(!0, Date.now() - n, "promptCheck") : s.includes("No") ? l(o) : l(`failed to evaluate expectation '${e}'`);
201
237
  });
202
- return d(r), r;
238
+ return C(i), i;
203
239
  }
204
- const rt = 3;
205
- function it(t) {
240
+ const yt = 3;
241
+ function Ct(t) {
206
242
  const e = t.match(/\b([1-5])\b/);
207
243
  return !e || !e[1] ? null : Number(e[1]);
208
244
  }
209
- async function at(t, e, n) {
210
- const o = Date.now(), r = n?.threshold ?? rt, s = y(
245
+ async function bt(t, e, n) {
246
+ const o = Date.now(), i = n?.threshold ?? yt, s = F(
211
247
  `Classify the input by how "${e}" it is on a scale of 1 to 5.
212
248
  1 means "not ${e}" and 5 means "very ${e}".
213
249
  Return only a single number: 1, 2, 3, 4, or 5.
@@ -217,141 +253,141 @@ Input:
217
253
  ${t}
218
254
  ---`,
219
255
  n?.model ? { model: n.model } : void 0
220
- ).then((i) => {
221
- const a = it(i);
256
+ ).then((r) => {
257
+ const a = Ct(r);
222
258
  if (a === null) {
223
- c(
224
- `failed to classify as '${e}'. Evaluator returned '${i}'`
259
+ l(
260
+ `failed to classify as '${e}'. Evaluator returned '${r}'`
225
261
  );
226
262
  return;
227
263
  }
228
- const u = `expected response to be classified as '${e}' with score >= ${r}, got ${a}`;
229
- if (a < r) {
230
- c(u);
264
+ const c = `expected response to be classified as '${e}' with score >= ${i}, got ${a}`;
265
+ if (a < i) {
266
+ l(c);
231
267
  return;
232
268
  }
233
- l(
269
+ h(
234
270
  !0,
235
271
  Date.now() - o,
236
272
  "toBeClassifiedAs"
237
273
  );
238
274
  });
239
- return d(s), s;
275
+ return C(s), s;
240
276
  }
241
- function ct(t, e) {
277
+ function Tt(t, e) {
242
278
  const n = `expected '${t}' to include '${e}'`;
243
- t.includes(e) || c(n);
279
+ t.includes(e) || l(n);
244
280
  }
245
- function v(t) {
281
+ function _(t) {
246
282
  const e = t.trim().replace(/[<>:"/\\|?*\x00-\x1f]/g, "_").replace(/\s+/g, "_");
247
283
  return e.length > 0 ? e : "unnamed";
248
284
  }
249
- function ut() {
250
- const t = U().map(
251
- (o) => v(o.description)
252
- ), e = R().map(
253
- (o) => v(o.description)
285
+ function $t() {
286
+ const t = K().map(
287
+ (o) => _(o.description)
288
+ ), e = J().map(
289
+ (o) => _(o.description)
254
290
  ), n = [...t, ...e];
255
291
  return n.length === 0 ? "root" : n.join("__");
256
292
  }
257
- function lt(t) {
258
- const n = W(t).replace(/\.eval\.[^./\\]+$/, ""), o = ut();
259
- return K(
260
- g(t),
293
+ function Et(t) {
294
+ const n = nt(t).replace(/\.eval\.[^./\\]+$/, ""), o = $t();
295
+ return S(
296
+ v(t),
261
297
  "__snapshots__",
262
298
  `${n}__${o}.snap.md`
263
299
  );
264
300
  }
265
- function T(t) {
301
+ function P(t) {
266
302
  return t.split(/\r?\n/);
267
303
  }
268
- function ft(t, e) {
304
+ function St(t, e) {
269
305
  if (t === e)
270
306
  return " (no diff)";
271
- const n = T(t), o = T(e), r = Math.max(n.length, o.length), s = [];
272
- for (let i = 0; i < r; i += 1) {
273
- const a = n[i], u = o[i];
274
- if (a !== u) {
275
- if (a === void 0 && u !== void 0) {
276
- s.push(`+ ${u}`);
307
+ const n = P(t), o = P(e), i = Math.max(n.length, o.length), s = [];
308
+ for (let r = 0; r < i; r += 1) {
309
+ const a = n[r], c = o[r];
310
+ if (a !== c) {
311
+ if (a === void 0 && c !== void 0) {
312
+ s.push(`+ ${c}`);
277
313
  continue;
278
314
  }
279
- if (a !== void 0 && u === void 0) {
315
+ if (a !== void 0 && c === void 0) {
280
316
  s.push(`- ${a}`);
281
317
  continue;
282
318
  }
283
- s.push(`- ${a ?? ""}`), s.push(`+ ${u ?? ""}`);
319
+ s.push(`- ${a ?? ""}`), s.push(`+ ${c ?? ""}`);
284
320
  }
285
321
  }
286
322
  return s.join(`
287
323
  `);
288
324
  }
289
- function dt(t) {
290
- const e = S.getStore()?.evalFile;
325
+ function vt(t) {
326
+ const e = L.getStore()?.evalFile;
291
327
  if (!e) {
292
- c(
328
+ l(
293
329
  "toMatchSnapshot can only be used while running an eval file."
294
330
  );
295
331
  return;
296
332
  }
297
- const n = lt(e);
333
+ const n = Et(e);
298
334
  try {
299
- const o = H(n, "utf8");
335
+ const o = st(n, "utf8");
300
336
  if (o === t)
301
337
  return;
302
- if (I()) {
303
- C(n, t, "utf8");
338
+ if (q()) {
339
+ M(n, t, "utf8");
304
340
  return;
305
341
  }
306
- const r = ft(o, t);
307
- c(
342
+ const i = St(o, t);
343
+ l(
308
344
  [
309
345
  `Snapshot mismatch at ${n}`,
310
346
  "",
311
347
  "Diff:",
312
- r,
348
+ i,
313
349
  "",
314
- "Run katt with --update-snapshots (or -u) to accept this change."
350
+ "Run 'npx katt --update-snapshots' (or -u) to accept this change."
315
351
  ].join(`
316
352
  `)
317
353
  );
318
354
  } catch (o) {
319
355
  if (o.code !== "ENOENT") {
320
- c(
356
+ l(
321
357
  `Failed to read snapshot at ${n}: ${String(o)}`
322
358
  );
323
359
  return;
324
360
  }
325
361
  try {
326
- Y(g(n), { recursive: !0 }), C(n, t, "utf8");
362
+ it(v(n), { recursive: !0 }), M(n, t, "utf8");
327
363
  } catch (s) {
328
- c(
364
+ l(
329
365
  `Failed to write snapshot at ${n}: ${String(s)}`
330
366
  );
331
367
  }
332
368
  }
333
369
  }
334
- function vt(t) {
370
+ function Lt(t) {
335
371
  return {
336
372
  toContain: (e) => {
337
- ct(t, e);
373
+ Tt(t, e);
338
374
  },
339
375
  toMatchSnapshot: () => {
340
- dt(t);
376
+ vt(t);
341
377
  },
342
378
  promptCheck: async (e) => {
343
- await st(t, e);
379
+ await wt(t, e);
344
380
  },
345
381
  toBeClassifiedAs: async (e, n) => {
346
- await at(t, e, n);
382
+ await bt(t, e, n);
347
383
  }
348
384
  };
349
385
  }
350
386
  export {
351
- Ct as describe,
352
- vt as expect,
353
- wt as it,
354
- y as prompt,
355
- bt as promptFile,
356
- xt as runCli
387
+ Nt as describe,
388
+ Lt as expect,
389
+ Pt as it,
390
+ F as prompt,
391
+ It as promptFile,
392
+ jt as runCli
357
393
  };
package/dist/katt.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as r } from "./runCli-B3oIBxOl.js";
2
+ import { u as r } from "./runCli-425rgVp8.js";
3
3
  r().then((e) => {
4
4
  process.exit(e);
5
5
  }).catch((e) => {