reflex-skills 0.5.0 → 0.5.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/LICENSE +21 -0
- package/README.md +19 -4
- package/dist/reflex.js +1404 -576
- package/package.json +2 -1
package/dist/reflex.js
CHANGED
|
@@ -590,8 +590,8 @@ var require_help = __commonJS({
|
|
|
590
590
|
helper.visibleCommands(cmd),
|
|
591
591
|
(sub) => sub.helpGroup() || "Commands:"
|
|
592
592
|
);
|
|
593
|
-
commandGroups.forEach((
|
|
594
|
-
const commandList =
|
|
593
|
+
commandGroups.forEach((commands2, group) => {
|
|
594
|
+
const commandList = commands2.map((sub) => {
|
|
595
595
|
return callFormatItem(
|
|
596
596
|
helper.styleSubcommandTerm(helper.subcommandTerm(sub)),
|
|
597
597
|
helper.styleSubcommandDescription(helper.subcommandDescription(sub))
|
|
@@ -742,8 +742,8 @@ ${itemIndentStr}`);
|
|
|
742
742
|
const rawLines = str3.split(/\r\n|\n/);
|
|
743
743
|
const chunkPattern = /[\s]*[^\s]+/g;
|
|
744
744
|
const wrappedLines = [];
|
|
745
|
-
rawLines.forEach((
|
|
746
|
-
const chunks =
|
|
745
|
+
rawLines.forEach((line2) => {
|
|
746
|
+
const chunks = line2.match(chunkPattern);
|
|
747
747
|
if (chunks === null) {
|
|
748
748
|
wrappedLines.push("");
|
|
749
749
|
return;
|
|
@@ -3461,12 +3461,12 @@ var require_src = __commonJS({
|
|
|
3461
3461
|
else if (y3 > 0) ret += `${CSI}${y3}B`;
|
|
3462
3462
|
return ret;
|
|
3463
3463
|
},
|
|
3464
|
-
up: (
|
|
3465
|
-
down: (
|
|
3466
|
-
forward: (
|
|
3467
|
-
backward: (
|
|
3468
|
-
nextLine: (
|
|
3469
|
-
prevLine: (
|
|
3464
|
+
up: (count3 = 1) => `${CSI}${count3}A`,
|
|
3465
|
+
down: (count3 = 1) => `${CSI}${count3}B`,
|
|
3466
|
+
forward: (count3 = 1) => `${CSI}${count3}C`,
|
|
3467
|
+
backward: (count3 = 1) => `${CSI}${count3}D`,
|
|
3468
|
+
nextLine: (count3 = 1) => `${CSI}E`.repeat(count3),
|
|
3469
|
+
prevLine: (count3 = 1) => `${CSI}F`.repeat(count3),
|
|
3470
3470
|
left: `${CSI}G`,
|
|
3471
3471
|
hide: `${CSI}?25l`,
|
|
3472
3472
|
show: `${CSI}?25h`,
|
|
@@ -3474,21 +3474,21 @@ var require_src = __commonJS({
|
|
|
3474
3474
|
restore: `${ESC}8`
|
|
3475
3475
|
};
|
|
3476
3476
|
var scroll = {
|
|
3477
|
-
up: (
|
|
3478
|
-
down: (
|
|
3477
|
+
up: (count3 = 1) => `${CSI}S`.repeat(count3),
|
|
3478
|
+
down: (count3 = 1) => `${CSI}T`.repeat(count3)
|
|
3479
3479
|
};
|
|
3480
3480
|
var erase = {
|
|
3481
3481
|
screen: `${CSI}2J`,
|
|
3482
|
-
up: (
|
|
3483
|
-
down: (
|
|
3482
|
+
up: (count3 = 1) => `${CSI}1J`.repeat(count3),
|
|
3483
|
+
down: (count3 = 1) => `${CSI}J`.repeat(count3),
|
|
3484
3484
|
line: `${CSI}2K`,
|
|
3485
3485
|
lineEnd: `${CSI}K`,
|
|
3486
3486
|
lineStart: `${CSI}1K`,
|
|
3487
|
-
lines(
|
|
3487
|
+
lines(count3) {
|
|
3488
3488
|
let clear = "";
|
|
3489
|
-
for (let i = 0; i <
|
|
3490
|
-
clear += this.line + (i <
|
|
3491
|
-
if (
|
|
3489
|
+
for (let i = 0; i < count3; i++)
|
|
3490
|
+
clear += this.line + (i < count3 - 1 ? cursor.up() : "");
|
|
3491
|
+
if (count3)
|
|
3492
3492
|
clear += cursor.left;
|
|
3493
3493
|
return clear;
|
|
3494
3494
|
}
|
|
@@ -3571,12 +3571,103 @@ var require_picocolors = __commonJS({
|
|
|
3571
3571
|
});
|
|
3572
3572
|
|
|
3573
3573
|
// src/guard.ts
|
|
3574
|
+
import dgram from "node:dgram";
|
|
3575
|
+
import dns from "node:dns";
|
|
3576
|
+
import { syncBuiltinESMExports } from "node:module";
|
|
3574
3577
|
import net from "node:net";
|
|
3578
|
+
import threads from "node:worker_threads";
|
|
3579
|
+
var MESSAGE = "Reflex does not make network connections";
|
|
3580
|
+
var MODEL_HOSTS = ["huggingface.co", "hf.co"];
|
|
3581
|
+
var DNS_QUERIES = /^(lookup|lookupService|resolve\w*|reverse)$/;
|
|
3582
|
+
var WORKER_GUARD = `{
|
|
3583
|
+
const blocked = () => { throw new Error(${JSON.stringify(`${MESSAGE}.`)}); };
|
|
3584
|
+
const get = process.getBuiltinModule;
|
|
3585
|
+
get("node:net").Socket.prototype.connect = blocked;
|
|
3586
|
+
const udp = get("node:dgram").Socket.prototype;
|
|
3587
|
+
udp.send = udp.connect = blocked;
|
|
3588
|
+
const dns = get("node:dns");
|
|
3589
|
+
for (const target of [dns, dns.promises, dns.Resolver.prototype, dns.promises.Resolver.prototype])
|
|
3590
|
+
for (const key of Object.getOwnPropertyNames(target))
|
|
3591
|
+
if (${DNS_QUERIES}.test(key) && typeof target[key] === "function") target[key] = blocked;
|
|
3592
|
+
}`;
|
|
3593
|
+
var allowed = [];
|
|
3594
|
+
function hostAllowed(host) {
|
|
3595
|
+
if (typeof host !== "string") return false;
|
|
3596
|
+
const h2 = host.toLowerCase().replace(/\.$/, "");
|
|
3597
|
+
return allowed.some((a) => h2 === a || h2.endsWith(`.${a}`));
|
|
3598
|
+
}
|
|
3599
|
+
function connectHost(args) {
|
|
3600
|
+
const first = Array.isArray(args[0]) ? args[0][0] : args[0];
|
|
3601
|
+
if (typeof first === "object" && first !== null) {
|
|
3602
|
+
const o2 = first;
|
|
3603
|
+
return o2.path === void 0 ? o2.host ?? "localhost" : void 0;
|
|
3604
|
+
}
|
|
3605
|
+
if (typeof first === "number" || /^\d+$/.test(String(first))) return typeof args[1] === "string" ? args[1] : "localhost";
|
|
3606
|
+
return void 0;
|
|
3607
|
+
}
|
|
3608
|
+
var refuse = (host) => {
|
|
3609
|
+
throw new Error(typeof host === "string" ? `${MESSAGE} (blocked ${host}).` : `${MESSAGE}.`);
|
|
3610
|
+
};
|
|
3575
3611
|
function installNetworkGuard() {
|
|
3576
|
-
const
|
|
3577
|
-
|
|
3612
|
+
const undo = [];
|
|
3613
|
+
const patch = (target, key3, make) => {
|
|
3614
|
+
const t = target;
|
|
3615
|
+
const original = t[key3];
|
|
3616
|
+
t[key3] = make(original);
|
|
3617
|
+
undo.push(() => t[key3] = original);
|
|
3618
|
+
};
|
|
3619
|
+
patch(
|
|
3620
|
+
net.Socket.prototype,
|
|
3621
|
+
"connect",
|
|
3622
|
+
(original) => function connect(...args) {
|
|
3623
|
+
const host = connectHost(args);
|
|
3624
|
+
return hostAllowed(host) ? original.apply(this, args) : refuse(host);
|
|
3625
|
+
}
|
|
3626
|
+
);
|
|
3627
|
+
for (const key3 of ["send", "connect"]) patch(dgram.Socket.prototype, key3, () => () => refuse(void 0));
|
|
3628
|
+
for (const target of [dns, dns.promises, dns.Resolver.prototype, dns.promises.Resolver.prototype]) {
|
|
3629
|
+
for (const key3 of Object.getOwnPropertyNames(target)) {
|
|
3630
|
+
if (!DNS_QUERIES.test(key3) || typeof target[key3] !== "function") continue;
|
|
3631
|
+
patch(
|
|
3632
|
+
target,
|
|
3633
|
+
key3,
|
|
3634
|
+
(original) => key3 === "lookup" ? function lookup(...args) {
|
|
3635
|
+
return hostAllowed(args[0]) ? original.apply(this, args) : refuse(args[0]);
|
|
3636
|
+
} : () => refuse(void 0)
|
|
3637
|
+
);
|
|
3638
|
+
}
|
|
3639
|
+
}
|
|
3640
|
+
const Base = threads.Worker;
|
|
3641
|
+
class GuardedWorker extends Base {
|
|
3642
|
+
constructor(filename, options = {}) {
|
|
3643
|
+
const inline = options.eval === true && typeof filename === "string";
|
|
3644
|
+
const guard = ["--import", `data:text/javascript,${encodeURIComponent(WORKER_GUARD)}`];
|
|
3645
|
+
super(inline ? `${WORKER_GUARD}
|
|
3646
|
+
${filename}` : filename, inline ? options : { ...options, execArgv: [...options.execArgv ?? process.execArgv, ...guard] });
|
|
3647
|
+
}
|
|
3648
|
+
}
|
|
3649
|
+
patch(threads, "Worker", () => GuardedWorker);
|
|
3650
|
+
syncBuiltinESMExports();
|
|
3651
|
+
return () => {
|
|
3652
|
+
for (const fn of undo.reverse()) fn();
|
|
3653
|
+
syncBuiltinESMExports();
|
|
3578
3654
|
};
|
|
3579
|
-
|
|
3655
|
+
}
|
|
3656
|
+
function allowHosts(hosts) {
|
|
3657
|
+
const before = allowed;
|
|
3658
|
+
allowed = [...before, ...hosts, ...proxyHosts()];
|
|
3659
|
+
return () => {
|
|
3660
|
+
allowed = before;
|
|
3661
|
+
};
|
|
3662
|
+
}
|
|
3663
|
+
function proxyHosts() {
|
|
3664
|
+
if (!process.env.NODE_USE_ENV_PROXY) return [];
|
|
3665
|
+
const url2 = process.env.HTTPS_PROXY ?? process.env.https_proxy;
|
|
3666
|
+
try {
|
|
3667
|
+
return url2 ? [new URL(url2).hostname.toLowerCase()] : [];
|
|
3668
|
+
} catch {
|
|
3669
|
+
return [];
|
|
3670
|
+
}
|
|
3580
3671
|
}
|
|
3581
3672
|
function quietSqliteWarning() {
|
|
3582
3673
|
const listeners = process.listeners("warning");
|
|
@@ -4286,8 +4377,8 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
|
|
|
4286
4377
|
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
4287
4378
|
var c = import_picocolors3.default;
|
|
4288
4379
|
var interactive = () => Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
4289
|
-
function out(
|
|
4290
|
-
process.stdout.write(
|
|
4380
|
+
function out(line2 = "") {
|
|
4381
|
+
process.stdout.write(line2 + "\n");
|
|
4291
4382
|
}
|
|
4292
4383
|
function title(text) {
|
|
4293
4384
|
out();
|
|
@@ -4359,7 +4450,7 @@ async function ask(message, initial, validate3) {
|
|
|
4359
4450
|
}
|
|
4360
4451
|
function fileBlock(path, content) {
|
|
4361
4452
|
out(c.dim(`\u250C\u2500 ${path}`));
|
|
4362
|
-
for (const
|
|
4453
|
+
for (const line2 of content.trimEnd().split("\n")) out(`${c.dim("\u2502")} ${line2}`);
|
|
4363
4454
|
out(c.dim("\u2514\u2500"));
|
|
4364
4455
|
}
|
|
4365
4456
|
function spinner() {
|
|
@@ -5151,9 +5242,9 @@ function assertNever(_x) {
|
|
|
5151
5242
|
}
|
|
5152
5243
|
function assert(_3) {
|
|
5153
5244
|
}
|
|
5154
|
-
function getEnumValues(
|
|
5155
|
-
const numericValues = Object.values(
|
|
5156
|
-
const values = Object.entries(
|
|
5245
|
+
function getEnumValues(entries2) {
|
|
5246
|
+
const numericValues = Object.values(entries2).filter((v2) => typeof v2 === "number");
|
|
5247
|
+
const values = Object.entries(entries2).filter(([k3, _3]) => numericValues.indexOf(+k3) === -1).map(([_3, v2]) => v2);
|
|
5157
5248
|
return values;
|
|
5158
5249
|
}
|
|
5159
5250
|
function joinValues(array2, separator = "|") {
|
|
@@ -5690,14 +5781,14 @@ function codePointLength(str3) {
|
|
|
5690
5781
|
const units = str3.length;
|
|
5691
5782
|
if (!highSurrogate.test(str3))
|
|
5692
5783
|
return units;
|
|
5693
|
-
let
|
|
5784
|
+
let count3 = units;
|
|
5694
5785
|
for (let i = 0; i < units - 1; i++) {
|
|
5695
5786
|
if ((str3.charCodeAt(i) & 64512) === 55296 && (str3.charCodeAt(i + 1) & 64512) === 56320) {
|
|
5696
|
-
|
|
5787
|
+
count3--;
|
|
5697
5788
|
i++;
|
|
5698
5789
|
}
|
|
5699
5790
|
}
|
|
5700
|
-
return
|
|
5791
|
+
return count3;
|
|
5701
5792
|
}
|
|
5702
5793
|
function getLengthableOrigin(input2) {
|
|
5703
5794
|
if (Array.isArray(input2))
|
|
@@ -6976,16 +7067,16 @@ var $ZodCheckProperties = /* @__PURE__ */ $constructor("$ZodCheckProperties", (i
|
|
|
6976
7067
|
hide(inst, Symbol.iterator, function* () {
|
|
6977
7068
|
yield inst;
|
|
6978
7069
|
});
|
|
6979
|
-
let
|
|
7070
|
+
let entries2;
|
|
6980
7071
|
inst._zod.check = (payload) => {
|
|
6981
7072
|
if (payload.value == null) {
|
|
6982
7073
|
payload.issues.push({ expected: "object", code: "invalid_type", input: payload.value, inst });
|
|
6983
7074
|
return void 0;
|
|
6984
7075
|
}
|
|
6985
|
-
|
|
7076
|
+
entries2 ?? (entries2 = Reflect.ownKeys(def.shape).map((key3) => [key3, def.shape[key3]]));
|
|
6986
7077
|
const input2 = payload.value;
|
|
6987
7078
|
let proms;
|
|
6988
|
-
for (const [key3, schema] of
|
|
7079
|
+
for (const [key3, schema] of entries2) {
|
|
6989
7080
|
const result = schema._zod.run({ value: input2[key3], issues: [] }, {});
|
|
6990
7081
|
if (result instanceof Promise) {
|
|
6991
7082
|
proms ?? (proms = []);
|
|
@@ -7048,8 +7139,8 @@ var Doc = class {
|
|
|
7048
7139
|
const lines = content.split("\n").filter((x2) => x2);
|
|
7049
7140
|
const minIndent = Math.min(...lines.map((x2) => x2.length - x2.trimStart().length));
|
|
7050
7141
|
const dedented = lines.map((x2) => x2.slice(minIndent)).map((x2) => " ".repeat(this.indent * 2) + x2);
|
|
7051
|
-
for (const
|
|
7052
|
-
this.content.push(
|
|
7142
|
+
for (const line2 of dedented) {
|
|
7143
|
+
this.content.push(line2);
|
|
7053
7144
|
}
|
|
7054
7145
|
}
|
|
7055
7146
|
compile() {
|
|
@@ -10052,8 +10143,8 @@ function az_default() {
|
|
|
10052
10143
|
}
|
|
10053
10144
|
|
|
10054
10145
|
// ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/be.js
|
|
10055
|
-
function getBelarusianPlural(
|
|
10056
|
-
const absCount = Math.abs(
|
|
10146
|
+
function getBelarusianPlural(count3, one, few, many) {
|
|
10147
|
+
const absCount = Math.abs(count3);
|
|
10057
10148
|
const lastDigit = absCount % 10;
|
|
10058
10149
|
const lastTwoDigits = absCount % 100;
|
|
10059
10150
|
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
|
@@ -12700,8 +12791,8 @@ function hu_default() {
|
|
|
12700
12791
|
}
|
|
12701
12792
|
|
|
12702
12793
|
// ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/hy.js
|
|
12703
|
-
function getArmenianPlural(
|
|
12704
|
-
return Math.abs(
|
|
12794
|
+
function getArmenianPlural(count3, one, many) {
|
|
12795
|
+
return Math.abs(count3) === 1 ? one : many;
|
|
12705
12796
|
}
|
|
12706
12797
|
function withDefiniteArticle(word) {
|
|
12707
12798
|
if (!word)
|
|
@@ -15439,8 +15530,8 @@ function ro_default() {
|
|
|
15439
15530
|
}
|
|
15440
15531
|
|
|
15441
15532
|
// ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/ru.js
|
|
15442
|
-
function getRussianPlural(
|
|
15443
|
-
const absCount = Math.abs(
|
|
15533
|
+
function getRussianPlural(count3, one, few, many) {
|
|
15534
|
+
const absCount = Math.abs(count3);
|
|
15444
15535
|
const lastDigit = absCount % 10;
|
|
15445
15536
|
const lastTwoDigits = absCount % 100;
|
|
15446
15537
|
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
|
@@ -17337,10 +17428,10 @@ var $ZodRegistry = class {
|
|
|
17337
17428
|
this._idmap = /* @__PURE__ */ new Map();
|
|
17338
17429
|
}
|
|
17339
17430
|
add(schema, ..._meta) {
|
|
17340
|
-
const
|
|
17341
|
-
this._map.set(schema,
|
|
17342
|
-
if (
|
|
17343
|
-
this._idmap.set(
|
|
17431
|
+
const meta4 = _meta[0];
|
|
17432
|
+
this._map.set(schema, meta4);
|
|
17433
|
+
if (meta4 && typeof meta4 === "object" && "id" in meta4) {
|
|
17434
|
+
this._idmap.set(meta4.id, schema);
|
|
17344
17435
|
}
|
|
17345
17436
|
return this;
|
|
17346
17437
|
}
|
|
@@ -17350,9 +17441,9 @@ var $ZodRegistry = class {
|
|
|
17350
17441
|
return this;
|
|
17351
17442
|
}
|
|
17352
17443
|
remove(schema) {
|
|
17353
|
-
const
|
|
17354
|
-
if (
|
|
17355
|
-
this._idmap.delete(
|
|
17444
|
+
const meta4 = this._map.get(schema);
|
|
17445
|
+
if (meta4 && typeof meta4 === "object" && "id" in meta4) {
|
|
17446
|
+
this._idmap.delete(meta4.id);
|
|
17356
17447
|
}
|
|
17357
17448
|
this._map.delete(schema);
|
|
17358
17449
|
return this;
|
|
@@ -19767,18 +19858,18 @@ function _set(Class2, valueType, params) {
|
|
|
19767
19858
|
}
|
|
19768
19859
|
// @__NO_SIDE_EFFECTS__
|
|
19769
19860
|
function _enum(Class2, values, params) {
|
|
19770
|
-
const
|
|
19861
|
+
const entries2 = Array.isArray(values) ? Object.fromEntries(values.map((v2) => [v2, v2])) : values;
|
|
19771
19862
|
return new Class2({
|
|
19772
19863
|
type: "enum",
|
|
19773
|
-
entries,
|
|
19864
|
+
entries: entries2,
|
|
19774
19865
|
...normalizeParams(params)
|
|
19775
19866
|
});
|
|
19776
19867
|
}
|
|
19777
19868
|
// @__NO_SIDE_EFFECTS__
|
|
19778
|
-
function _nativeEnum(Class2,
|
|
19869
|
+
function _nativeEnum(Class2, entries2, params) {
|
|
19779
19870
|
return new Class2({
|
|
19780
19871
|
type: "enum",
|
|
19781
|
-
entries,
|
|
19872
|
+
entries: entries2,
|
|
19782
19873
|
...normalizeParams(params)
|
|
19783
19874
|
});
|
|
19784
19875
|
}
|
|
@@ -20074,13 +20165,13 @@ function initializeContext(params) {
|
|
|
20074
20165
|
external: params?.external ?? void 0
|
|
20075
20166
|
};
|
|
20076
20167
|
}
|
|
20077
|
-
function handleUnrepresentable(schema, ctx,
|
|
20168
|
+
function handleUnrepresentable(schema, ctx, json3, params, message) {
|
|
20078
20169
|
const result = typeof ctx.unrepresentable === "function" ? ctx.unrepresentable({ zodSchema: schema, path: params.path, message }) : ctx.unrepresentable;
|
|
20079
20170
|
if (result === "any")
|
|
20080
20171
|
return false;
|
|
20081
20172
|
if (result === void 0 || result === "throw")
|
|
20082
20173
|
throw new Error(message);
|
|
20083
|
-
Object.assign(
|
|
20174
|
+
Object.assign(json3, result);
|
|
20084
20175
|
return true;
|
|
20085
20176
|
}
|
|
20086
20177
|
function processSchema(schema, ctx, _params = { path: [], schemaPath: [] }) {
|
|
@@ -20126,9 +20217,9 @@ function processSchema(schema, ctx, _params = { path: [], schemaPath: [] }) {
|
|
|
20126
20217
|
ctx.seen.get(parent).isParent = true;
|
|
20127
20218
|
}
|
|
20128
20219
|
}
|
|
20129
|
-
const
|
|
20130
|
-
if (
|
|
20131
|
-
assignProps(result.schema,
|
|
20220
|
+
const meta4 = ctx.metadataRegistry.get(schema);
|
|
20221
|
+
if (meta4)
|
|
20222
|
+
assignProps(result.schema, meta4);
|
|
20132
20223
|
if (ctx.io === "input" && isTransforming(schema)) {
|
|
20133
20224
|
delete result.schema.examples;
|
|
20134
20225
|
delete result.schema.default;
|
|
@@ -20316,12 +20407,12 @@ function foldObjects(members2) {
|
|
|
20316
20407
|
}
|
|
20317
20408
|
return folded;
|
|
20318
20409
|
}
|
|
20319
|
-
function foldIntersection(
|
|
20320
|
-
const allOf =
|
|
20410
|
+
function foldIntersection(json3) {
|
|
20411
|
+
const allOf = json3.allOf;
|
|
20321
20412
|
if (!Array.isArray(allOf) || allOf.length < 2)
|
|
20322
20413
|
return;
|
|
20323
20414
|
for (const key3 of FOLDABLE_KEYS)
|
|
20324
|
-
if (key3 in
|
|
20415
|
+
if (key3 in json3)
|
|
20325
20416
|
return;
|
|
20326
20417
|
const unions = allOf.filter((m2) => UNION_KEYS.some((k3) => Array.isArray(m2[k3])));
|
|
20327
20418
|
let folded = null;
|
|
@@ -20340,8 +20431,8 @@ function foldIntersection(json2) {
|
|
|
20340
20431
|
}
|
|
20341
20432
|
if (!folded)
|
|
20342
20433
|
return;
|
|
20343
|
-
delete
|
|
20344
|
-
assignProps(
|
|
20434
|
+
delete json3.allOf;
|
|
20435
|
+
assignProps(json3, folded);
|
|
20345
20436
|
}
|
|
20346
20437
|
function finalize(ctx, schema) {
|
|
20347
20438
|
const root = ctx.seen.get(schema);
|
|
@@ -20423,20 +20514,20 @@ function finalize(ctx, schema) {
|
|
|
20423
20514
|
if (ctx.intersections.length) {
|
|
20424
20515
|
const carriers = /* @__PURE__ */ new Map();
|
|
20425
20516
|
for (const seen of ctx.seen.values()) {
|
|
20426
|
-
for (const
|
|
20427
|
-
const allOf =
|
|
20517
|
+
for (const json3 of [seen.schema, seen.def]) {
|
|
20518
|
+
const allOf = json3?.allOf;
|
|
20428
20519
|
if (!Array.isArray(allOf))
|
|
20429
20520
|
continue;
|
|
20430
20521
|
const existing = carriers.get(allOf);
|
|
20431
20522
|
if (existing)
|
|
20432
|
-
existing.push(
|
|
20523
|
+
existing.push(json3);
|
|
20433
20524
|
else
|
|
20434
|
-
carriers.set(allOf, [
|
|
20525
|
+
carriers.set(allOf, [json3]);
|
|
20435
20526
|
}
|
|
20436
20527
|
}
|
|
20437
20528
|
for (const allOf of ctx.intersections) {
|
|
20438
|
-
for (const
|
|
20439
|
-
foldIntersection(
|
|
20529
|
+
for (const json3 of carriers.get(allOf) ?? [])
|
|
20530
|
+
foldIntersection(json3);
|
|
20440
20531
|
}
|
|
20441
20532
|
}
|
|
20442
20533
|
}
|
|
@@ -20671,29 +20762,29 @@ var exactPatterns = /* @__PURE__ */ new Map([
|
|
|
20671
20762
|
]);
|
|
20672
20763
|
var exactPattern = (p3) => exactPatterns.get(p3) ?? p3;
|
|
20673
20764
|
var stringProcessor = (schema, ctx, _json, _params) => {
|
|
20674
|
-
const
|
|
20675
|
-
|
|
20765
|
+
const json3 = _json;
|
|
20766
|
+
json3.type = "string";
|
|
20676
20767
|
const { minimum, maximum, format, patterns, contentEncoding, laxFormat } = aggregateChecks(schema);
|
|
20677
20768
|
if (typeof minimum === "number")
|
|
20678
|
-
|
|
20769
|
+
json3.minLength = minimum;
|
|
20679
20770
|
if (typeof maximum === "number")
|
|
20680
|
-
|
|
20771
|
+
json3.maxLength = maximum;
|
|
20681
20772
|
if (format) {
|
|
20682
|
-
|
|
20683
|
-
if (
|
|
20684
|
-
delete
|
|
20773
|
+
json3.format = formatMap[format] ?? format;
|
|
20774
|
+
if (json3.format === "")
|
|
20775
|
+
delete json3.format;
|
|
20685
20776
|
if (format === "time" || laxFormat) {
|
|
20686
|
-
delete
|
|
20777
|
+
delete json3.format;
|
|
20687
20778
|
}
|
|
20688
20779
|
}
|
|
20689
20780
|
if (contentEncoding)
|
|
20690
|
-
|
|
20781
|
+
json3.contentEncoding = contentEncoding;
|
|
20691
20782
|
if (patterns && patterns.size > 0) {
|
|
20692
20783
|
const patternList = [...patterns].map(exactPattern);
|
|
20693
20784
|
if (patternList.length === 1)
|
|
20694
|
-
|
|
20785
|
+
json3.pattern = patternList[0].source;
|
|
20695
20786
|
else if (patternList.length > 1) {
|
|
20696
|
-
|
|
20787
|
+
json3.allOf = [
|
|
20697
20788
|
...patternList.map((regex) => ({
|
|
20698
20789
|
...ctx.target === "draft-07" || ctx.target === "draft-04" || ctx.target === "openapi-3.0" ? { type: "string" } : {},
|
|
20699
20790
|
pattern: regex.source
|
|
@@ -20703,31 +20794,31 @@ var stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
20703
20794
|
}
|
|
20704
20795
|
};
|
|
20705
20796
|
var numberProcessor = (schema, ctx, _json, params) => {
|
|
20706
|
-
const
|
|
20797
|
+
const json3 = _json;
|
|
20707
20798
|
const { minimum, maximum, multipleOf, exclusiveMaximum, exclusiveMinimum, isInt: isInt2 } = aggregateChecks(schema);
|
|
20708
|
-
|
|
20799
|
+
json3.type = isInt2 ? "integer" : "number";
|
|
20709
20800
|
const exMin = typeof exclusiveMinimum === "number" && exclusiveMinimum >= (minimum ?? Number.NEGATIVE_INFINITY);
|
|
20710
20801
|
const exMax = typeof exclusiveMaximum === "number" && exclusiveMaximum <= (maximum ?? Number.POSITIVE_INFINITY);
|
|
20711
20802
|
const legacy = ctx.target === "draft-04" || ctx.target === "openapi-3.0";
|
|
20712
20803
|
if (exMin) {
|
|
20713
20804
|
if (legacy) {
|
|
20714
|
-
|
|
20715
|
-
|
|
20805
|
+
json3.minimum = exclusiveMinimum;
|
|
20806
|
+
json3.exclusiveMinimum = true;
|
|
20716
20807
|
} else {
|
|
20717
|
-
|
|
20808
|
+
json3.exclusiveMinimum = exclusiveMinimum;
|
|
20718
20809
|
}
|
|
20719
20810
|
} else if (typeof minimum === "number") {
|
|
20720
|
-
|
|
20811
|
+
json3.minimum = minimum;
|
|
20721
20812
|
}
|
|
20722
20813
|
if (exMax) {
|
|
20723
20814
|
if (legacy) {
|
|
20724
|
-
|
|
20725
|
-
|
|
20815
|
+
json3.maximum = exclusiveMaximum;
|
|
20816
|
+
json3.exclusiveMaximum = true;
|
|
20726
20817
|
} else {
|
|
20727
|
-
|
|
20818
|
+
json3.exclusiveMaximum = exclusiveMaximum;
|
|
20728
20819
|
}
|
|
20729
20820
|
} else if (typeof maximum === "number") {
|
|
20730
|
-
|
|
20821
|
+
json3.maximum = maximum;
|
|
20731
20822
|
}
|
|
20732
20823
|
if (multipleOf) {
|
|
20733
20824
|
const divisors = /* @__PURE__ */ new Set();
|
|
@@ -20735,75 +20826,75 @@ var numberProcessor = (schema, ctx, _json, params) => {
|
|
|
20735
20826
|
if (Number.isFinite(divisor) && divisor !== 0)
|
|
20736
20827
|
divisors.add(Math.abs(divisor));
|
|
20737
20828
|
else
|
|
20738
|
-
handleUnrepresentable(schema, ctx,
|
|
20829
|
+
handleUnrepresentable(schema, ctx, json3, params, `A multipleOf divisor of ${divisor} cannot be represented in JSON Schema`);
|
|
20739
20830
|
}
|
|
20740
20831
|
const [first, ...rest] = divisors;
|
|
20741
20832
|
if (first !== void 0)
|
|
20742
|
-
|
|
20833
|
+
json3.multipleOf = first;
|
|
20743
20834
|
if (rest.length)
|
|
20744
|
-
|
|
20835
|
+
json3.allOf = [...json3.allOf ?? [], ...rest.map((m2) => ({ multipleOf: m2 }))];
|
|
20745
20836
|
}
|
|
20746
20837
|
};
|
|
20747
|
-
var booleanProcessor = (_schema, _ctx,
|
|
20748
|
-
|
|
20838
|
+
var booleanProcessor = (_schema, _ctx, json3, _params) => {
|
|
20839
|
+
json3.type = "boolean";
|
|
20749
20840
|
};
|
|
20750
|
-
var bigintProcessor = (schema, ctx,
|
|
20751
|
-
handleUnrepresentable(schema, ctx,
|
|
20841
|
+
var bigintProcessor = (schema, ctx, json3, params) => {
|
|
20842
|
+
handleUnrepresentable(schema, ctx, json3, params, "BigInt cannot be represented in JSON Schema");
|
|
20752
20843
|
};
|
|
20753
|
-
var symbolProcessor = (schema, ctx,
|
|
20754
|
-
handleUnrepresentable(schema, ctx,
|
|
20844
|
+
var symbolProcessor = (schema, ctx, json3, params) => {
|
|
20845
|
+
handleUnrepresentable(schema, ctx, json3, params, "Symbols cannot be represented in JSON Schema");
|
|
20755
20846
|
};
|
|
20756
|
-
var nullProcessor = (_schema, ctx,
|
|
20847
|
+
var nullProcessor = (_schema, ctx, json3, _params) => {
|
|
20757
20848
|
if (ctx.target === "openapi-3.0") {
|
|
20758
|
-
|
|
20759
|
-
|
|
20760
|
-
|
|
20849
|
+
json3.type = "string";
|
|
20850
|
+
json3.nullable = true;
|
|
20851
|
+
json3.enum = [null];
|
|
20761
20852
|
} else {
|
|
20762
|
-
|
|
20853
|
+
json3.type = "null";
|
|
20763
20854
|
}
|
|
20764
20855
|
};
|
|
20765
|
-
var undefinedProcessor = (schema, ctx,
|
|
20766
|
-
handleUnrepresentable(schema, ctx,
|
|
20856
|
+
var undefinedProcessor = (schema, ctx, json3, params) => {
|
|
20857
|
+
handleUnrepresentable(schema, ctx, json3, params, "Undefined cannot be represented in JSON Schema");
|
|
20767
20858
|
};
|
|
20768
|
-
var voidProcessor = (schema, ctx,
|
|
20769
|
-
handleUnrepresentable(schema, ctx,
|
|
20859
|
+
var voidProcessor = (schema, ctx, json3, params) => {
|
|
20860
|
+
handleUnrepresentable(schema, ctx, json3, params, "Void cannot be represented in JSON Schema");
|
|
20770
20861
|
};
|
|
20771
|
-
var neverProcessor = (_schema, _ctx,
|
|
20772
|
-
|
|
20862
|
+
var neverProcessor = (_schema, _ctx, json3, _params) => {
|
|
20863
|
+
json3.not = {};
|
|
20773
20864
|
};
|
|
20774
20865
|
var anyProcessor = (_schema, _ctx, _json, _params) => {
|
|
20775
20866
|
};
|
|
20776
20867
|
var unknownProcessor = (_schema, _ctx, _json, _params) => {
|
|
20777
20868
|
};
|
|
20778
|
-
var dateProcessor = (schema, ctx,
|
|
20779
|
-
handleUnrepresentable(schema, ctx,
|
|
20869
|
+
var dateProcessor = (schema, ctx, json3, params) => {
|
|
20870
|
+
handleUnrepresentable(schema, ctx, json3, params, "Date cannot be represented in JSON Schema");
|
|
20780
20871
|
};
|
|
20781
|
-
var enumProcessor = (schema, _ctx,
|
|
20872
|
+
var enumProcessor = (schema, _ctx, json3, _params) => {
|
|
20782
20873
|
const def = schema._zod.def;
|
|
20783
20874
|
const values = getEnumValues(def.entries);
|
|
20784
20875
|
if (values.length === 0) {
|
|
20785
|
-
|
|
20876
|
+
json3.not = {};
|
|
20786
20877
|
return;
|
|
20787
20878
|
}
|
|
20788
20879
|
if (values.every((v2) => typeof v2 === "number"))
|
|
20789
|
-
|
|
20880
|
+
json3.type = "number";
|
|
20790
20881
|
if (values.every((v2) => typeof v2 === "string"))
|
|
20791
|
-
|
|
20792
|
-
|
|
20882
|
+
json3.type = "string";
|
|
20883
|
+
json3.enum = values;
|
|
20793
20884
|
};
|
|
20794
|
-
var literalProcessor = (schema, ctx,
|
|
20885
|
+
var literalProcessor = (schema, ctx, json3, params) => {
|
|
20795
20886
|
const def = schema._zod.def;
|
|
20796
20887
|
if (def.values.length === 0) {
|
|
20797
|
-
|
|
20888
|
+
json3.not = {};
|
|
20798
20889
|
return;
|
|
20799
20890
|
}
|
|
20800
20891
|
const vals = [];
|
|
20801
20892
|
for (const val of def.values) {
|
|
20802
20893
|
if (val === void 0) {
|
|
20803
|
-
if (handleUnrepresentable(schema, ctx,
|
|
20894
|
+
if (handleUnrepresentable(schema, ctx, json3, params, "Literal `undefined` cannot be represented in JSON Schema"))
|
|
20804
20895
|
return;
|
|
20805
20896
|
} else if (typeof val === "bigint") {
|
|
20806
|
-
if (handleUnrepresentable(schema, ctx,
|
|
20897
|
+
if (handleUnrepresentable(schema, ctx, json3, params, "BigInt literals cannot be represented in JSON Schema"))
|
|
20807
20898
|
return;
|
|
20808
20899
|
vals.push(Number(val));
|
|
20809
20900
|
} else {
|
|
@@ -20813,37 +20904,37 @@ var literalProcessor = (schema, ctx, json2, params) => {
|
|
|
20813
20904
|
if (vals.length === 0) {
|
|
20814
20905
|
} else if (vals.length === 1) {
|
|
20815
20906
|
const val = vals[0];
|
|
20816
|
-
|
|
20907
|
+
json3.type = val === null ? "null" : typeof val;
|
|
20817
20908
|
if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") {
|
|
20818
|
-
|
|
20909
|
+
json3.enum = [val];
|
|
20819
20910
|
} else {
|
|
20820
|
-
|
|
20911
|
+
json3.const = val;
|
|
20821
20912
|
}
|
|
20822
20913
|
} else {
|
|
20823
20914
|
if (vals.every((v2) => typeof v2 === "number"))
|
|
20824
|
-
|
|
20915
|
+
json3.type = "number";
|
|
20825
20916
|
if (vals.every((v2) => typeof v2 === "string"))
|
|
20826
|
-
|
|
20917
|
+
json3.type = "string";
|
|
20827
20918
|
if (vals.every((v2) => typeof v2 === "boolean"))
|
|
20828
|
-
|
|
20919
|
+
json3.type = "boolean";
|
|
20829
20920
|
if (vals.every((v2) => v2 === null))
|
|
20830
|
-
|
|
20831
|
-
|
|
20921
|
+
json3.type = "null";
|
|
20922
|
+
json3.enum = vals;
|
|
20832
20923
|
}
|
|
20833
20924
|
};
|
|
20834
|
-
var nanProcessor = (schema, ctx,
|
|
20835
|
-
handleUnrepresentable(schema, ctx,
|
|
20925
|
+
var nanProcessor = (schema, ctx, json3, params) => {
|
|
20926
|
+
handleUnrepresentable(schema, ctx, json3, params, "NaN cannot be represented in JSON Schema");
|
|
20836
20927
|
};
|
|
20837
|
-
var templateLiteralProcessor = (schema, _ctx,
|
|
20838
|
-
const _json =
|
|
20928
|
+
var templateLiteralProcessor = (schema, _ctx, json3, _params) => {
|
|
20929
|
+
const _json = json3;
|
|
20839
20930
|
const pattern = schema._zod.pattern;
|
|
20840
20931
|
if (!pattern)
|
|
20841
20932
|
throw new Error("Pattern not found in template literal");
|
|
20842
20933
|
_json.type = "string";
|
|
20843
20934
|
_json.pattern = pattern.source;
|
|
20844
20935
|
};
|
|
20845
|
-
var fileProcessor = (schema, _ctx,
|
|
20846
|
-
const _json =
|
|
20936
|
+
var fileProcessor = (schema, _ctx, json3, _params) => {
|
|
20937
|
+
const _json = json3;
|
|
20847
20938
|
_json.type = "string";
|
|
20848
20939
|
_json.format = "binary";
|
|
20849
20940
|
_json.contentEncoding = "binary";
|
|
@@ -20861,34 +20952,34 @@ var fileProcessor = (schema, _ctx, json2, _params) => {
|
|
|
20861
20952
|
else
|
|
20862
20953
|
_json.anyOf = mime.map((m2) => ({ contentMediaType: m2 }));
|
|
20863
20954
|
};
|
|
20864
|
-
var successProcessor = (_schema, _ctx,
|
|
20865
|
-
|
|
20955
|
+
var successProcessor = (_schema, _ctx, json3, _params) => {
|
|
20956
|
+
json3.type = "boolean";
|
|
20866
20957
|
};
|
|
20867
|
-
var customProcessor = (schema, ctx,
|
|
20868
|
-
handleUnrepresentable(schema, ctx,
|
|
20958
|
+
var customProcessor = (schema, ctx, json3, params) => {
|
|
20959
|
+
handleUnrepresentable(schema, ctx, json3, params, "Custom types cannot be represented in JSON Schema");
|
|
20869
20960
|
};
|
|
20870
|
-
var functionProcessor = (schema, ctx,
|
|
20871
|
-
handleUnrepresentable(schema, ctx,
|
|
20961
|
+
var functionProcessor = (schema, ctx, json3, params) => {
|
|
20962
|
+
handleUnrepresentable(schema, ctx, json3, params, "Function types cannot be represented in JSON Schema");
|
|
20872
20963
|
};
|
|
20873
|
-
var transformProcessor = (schema, ctx,
|
|
20874
|
-
handleUnrepresentable(schema, ctx,
|
|
20964
|
+
var transformProcessor = (schema, ctx, json3, params) => {
|
|
20965
|
+
handleUnrepresentable(schema, ctx, json3, params, "Transforms cannot be represented in JSON Schema");
|
|
20875
20966
|
};
|
|
20876
|
-
var mapProcessor = (schema, ctx,
|
|
20877
|
-
handleUnrepresentable(schema, ctx,
|
|
20967
|
+
var mapProcessor = (schema, ctx, json3, params) => {
|
|
20968
|
+
handleUnrepresentable(schema, ctx, json3, params, "Map cannot be represented in JSON Schema");
|
|
20878
20969
|
};
|
|
20879
|
-
var setProcessor = (schema, ctx,
|
|
20880
|
-
handleUnrepresentable(schema, ctx,
|
|
20970
|
+
var setProcessor = (schema, ctx, json3, params) => {
|
|
20971
|
+
handleUnrepresentable(schema, ctx, json3, params, "Set cannot be represented in JSON Schema");
|
|
20881
20972
|
};
|
|
20882
20973
|
var arrayProcessor = (schema, ctx, _json, params) => {
|
|
20883
|
-
const
|
|
20974
|
+
const json3 = _json;
|
|
20884
20975
|
const def = schema._zod.def;
|
|
20885
20976
|
const { minimum, maximum } = aggregateChecks(schema);
|
|
20886
20977
|
if (typeof minimum === "number")
|
|
20887
|
-
|
|
20978
|
+
json3.minItems = minimum;
|
|
20888
20979
|
if (typeof maximum === "number")
|
|
20889
|
-
|
|
20890
|
-
|
|
20891
|
-
|
|
20980
|
+
json3.maxItems = maximum;
|
|
20981
|
+
json3.type = "array";
|
|
20982
|
+
json3.items = processSchema(def.element, ctx, {
|
|
20892
20983
|
...params,
|
|
20893
20984
|
path: [...params.path, "items"]
|
|
20894
20985
|
});
|
|
@@ -20904,17 +20995,17 @@ function inputOptin(schema) {
|
|
|
20904
20995
|
return schema._zod.optin;
|
|
20905
20996
|
}
|
|
20906
20997
|
var objectProcessor = (schema, ctx, _json, params) => {
|
|
20907
|
-
const
|
|
20998
|
+
const json3 = _json;
|
|
20908
20999
|
const def = schema._zod.def;
|
|
20909
21000
|
const shape = def.shape;
|
|
20910
21001
|
const symbolKeys = Object.getOwnPropertySymbols(shape);
|
|
20911
|
-
if (symbolKeys.length && handleUnrepresentable(schema, ctx,
|
|
21002
|
+
if (symbolKeys.length && handleUnrepresentable(schema, ctx, json3, params, "Symbol keys cannot be represented in JSON Schema")) {
|
|
20912
21003
|
return;
|
|
20913
21004
|
}
|
|
20914
|
-
|
|
20915
|
-
|
|
21005
|
+
json3.type = "object";
|
|
21006
|
+
json3.properties = {};
|
|
20916
21007
|
for (const key3 in shape) {
|
|
20917
|
-
assignProp(
|
|
21008
|
+
assignProp(json3.properties, key3, processSchema(shape[key3], ctx, {
|
|
20918
21009
|
...params,
|
|
20919
21010
|
path: [...params.path, "properties", key3]
|
|
20920
21011
|
}));
|
|
@@ -20927,21 +21018,21 @@ var objectProcessor = (schema, ctx, _json, params) => {
|
|
|
20927
21018
|
}
|
|
20928
21019
|
}
|
|
20929
21020
|
if (requiredKeys.length > 0) {
|
|
20930
|
-
|
|
21021
|
+
json3.required = requiredKeys;
|
|
20931
21022
|
}
|
|
20932
21023
|
if (def.catchall?._zod.def.type === "never") {
|
|
20933
|
-
|
|
21024
|
+
json3.additionalProperties = false;
|
|
20934
21025
|
} else if (!def.catchall) {
|
|
20935
21026
|
if (ctx.io === "output")
|
|
20936
|
-
|
|
21027
|
+
json3.additionalProperties = false;
|
|
20937
21028
|
} else if (def.catchall) {
|
|
20938
|
-
|
|
21029
|
+
json3.additionalProperties = processSchema(def.catchall, ctx, {
|
|
20939
21030
|
...params,
|
|
20940
21031
|
path: [...params.path, "additionalProperties"]
|
|
20941
21032
|
});
|
|
20942
21033
|
}
|
|
20943
21034
|
};
|
|
20944
|
-
var unionProcessor = (schema, ctx,
|
|
21035
|
+
var unionProcessor = (schema, ctx, json3, params) => {
|
|
20945
21036
|
const def = schema._zod.def;
|
|
20946
21037
|
const isExclusive = def.inclusive === false;
|
|
20947
21038
|
const options = def.options.map((x2, i) => processSchema(x2, ctx, {
|
|
@@ -20949,12 +21040,12 @@ var unionProcessor = (schema, ctx, json2, params) => {
|
|
|
20949
21040
|
path: [...params.path, isExclusive ? "oneOf" : "anyOf", i]
|
|
20950
21041
|
}));
|
|
20951
21042
|
if (isExclusive) {
|
|
20952
|
-
|
|
21043
|
+
json3.oneOf = options;
|
|
20953
21044
|
} else {
|
|
20954
|
-
|
|
21045
|
+
json3.anyOf = options;
|
|
20955
21046
|
}
|
|
20956
21047
|
};
|
|
20957
|
-
var intersectionProcessor = (schema, ctx,
|
|
21048
|
+
var intersectionProcessor = (schema, ctx, json3, params) => {
|
|
20958
21049
|
const def = schema._zod.def;
|
|
20959
21050
|
const a = processSchema(def.left, ctx, {
|
|
20960
21051
|
...params,
|
|
@@ -20969,13 +21060,13 @@ var intersectionProcessor = (schema, ctx, json2, params) => {
|
|
|
20969
21060
|
...isSimpleIntersection(a) ? a.allOf : [a],
|
|
20970
21061
|
...isSimpleIntersection(b3) ? b3.allOf : [b3]
|
|
20971
21062
|
];
|
|
20972
|
-
|
|
21063
|
+
json3.allOf = allOf;
|
|
20973
21064
|
ctx.intersections.push(allOf);
|
|
20974
21065
|
};
|
|
20975
21066
|
var tupleProcessor = (schema, ctx, _json, params) => {
|
|
20976
|
-
const
|
|
21067
|
+
const json3 = _json;
|
|
20977
21068
|
const def = schema._zod.def;
|
|
20978
|
-
|
|
21069
|
+
json3.type = "array";
|
|
20979
21070
|
const prefixPath = ctx.target === "draft-2020-12" ? "prefixItems" : "items";
|
|
20980
21071
|
const restPath = ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems";
|
|
20981
21072
|
const prefixItems = def.items.map((x2, i) => processSchema(x2, ctx, {
|
|
@@ -20997,70 +21088,70 @@ var tupleProcessor = (schema, ctx, _json, params) => {
|
|
|
20997
21088
|
const maxItems = def.items.length;
|
|
20998
21089
|
const isClosed = !def.rest;
|
|
20999
21090
|
if (ctx.target === "draft-2020-12") {
|
|
21000
|
-
|
|
21091
|
+
json3.prefixItems = prefixItems;
|
|
21001
21092
|
if (isClosed) {
|
|
21002
|
-
|
|
21093
|
+
json3.items = false;
|
|
21003
21094
|
} else if (rest) {
|
|
21004
|
-
|
|
21095
|
+
json3.items = rest;
|
|
21005
21096
|
}
|
|
21006
21097
|
if (minItems > 0)
|
|
21007
|
-
|
|
21098
|
+
json3.minItems = minItems;
|
|
21008
21099
|
if (isClosed)
|
|
21009
|
-
|
|
21100
|
+
json3.maxItems = maxItems;
|
|
21010
21101
|
} else if (ctx.target === "openapi-3.0") {
|
|
21011
|
-
|
|
21102
|
+
json3.items = {
|
|
21012
21103
|
anyOf: prefixItems
|
|
21013
21104
|
};
|
|
21014
21105
|
if (rest) {
|
|
21015
|
-
|
|
21106
|
+
json3.items.anyOf.push(rest);
|
|
21016
21107
|
}
|
|
21017
21108
|
if (minItems > 0)
|
|
21018
|
-
|
|
21109
|
+
json3.minItems = minItems;
|
|
21019
21110
|
if (isClosed)
|
|
21020
|
-
|
|
21111
|
+
json3.maxItems = maxItems;
|
|
21021
21112
|
} else {
|
|
21022
|
-
|
|
21113
|
+
json3.items = prefixItems;
|
|
21023
21114
|
if (isClosed) {
|
|
21024
|
-
|
|
21115
|
+
json3.additionalItems = false;
|
|
21025
21116
|
} else if (rest) {
|
|
21026
|
-
|
|
21117
|
+
json3.additionalItems = rest;
|
|
21027
21118
|
}
|
|
21028
21119
|
if (minItems > 0)
|
|
21029
|
-
|
|
21120
|
+
json3.minItems = minItems;
|
|
21030
21121
|
if (isClosed)
|
|
21031
|
-
|
|
21122
|
+
json3.maxItems = maxItems;
|
|
21032
21123
|
}
|
|
21033
21124
|
const { minimum, maximum } = aggregateChecks(schema);
|
|
21034
21125
|
if (typeof minimum === "number")
|
|
21035
|
-
|
|
21126
|
+
json3.minItems = minimum;
|
|
21036
21127
|
if (typeof maximum === "number")
|
|
21037
|
-
|
|
21128
|
+
json3.maxItems = maximum;
|
|
21038
21129
|
};
|
|
21039
|
-
function stringifyKeyNames(bySchema,
|
|
21040
|
-
if (
|
|
21041
|
-
if (visited.has(
|
|
21042
|
-
return
|
|
21043
|
-
visited.add(
|
|
21044
|
-
const def = bySchema.get(
|
|
21130
|
+
function stringifyKeyNames(bySchema, json3, visited) {
|
|
21131
|
+
if (json3.$ref) {
|
|
21132
|
+
if (visited.has(json3))
|
|
21133
|
+
return json3;
|
|
21134
|
+
visited.add(json3);
|
|
21135
|
+
const def = bySchema.get(json3)?.def;
|
|
21045
21136
|
if (!def)
|
|
21046
|
-
return
|
|
21137
|
+
return json3;
|
|
21047
21138
|
const inlined = stringifyKeyNames(bySchema, def, visited);
|
|
21048
|
-
return inlined === def ?
|
|
21139
|
+
return inlined === def ? json3 : inlined;
|
|
21049
21140
|
}
|
|
21050
21141
|
for (const keyword of ["anyOf", "oneOf"]) {
|
|
21051
|
-
const branches =
|
|
21142
|
+
const branches = json3[keyword];
|
|
21052
21143
|
if (!Array.isArray(branches))
|
|
21053
21144
|
continue;
|
|
21054
21145
|
const mapped = branches.map((branch) => stringifyKeyNames(bySchema, branch, visited));
|
|
21055
21146
|
if (mapped.some((branch, i) => branch !== branches[i]))
|
|
21056
|
-
|
|
21147
|
+
json3 = { ...json3, [keyword]: mapped };
|
|
21057
21148
|
}
|
|
21058
|
-
const types = Array.isArray(
|
|
21149
|
+
const types = Array.isArray(json3.type) ? json3.type : [json3.type];
|
|
21059
21150
|
const numericType = !types.includes("string") && types.some((t) => t === "number" || t === "integer");
|
|
21060
|
-
const values =
|
|
21151
|
+
const values = json3.enum ?? (json3.const !== void 0 ? [json3.const] : void 0);
|
|
21061
21152
|
if (!numericType && !values?.some((v2) => typeof v2 === "number"))
|
|
21062
|
-
return
|
|
21063
|
-
const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id, ...rest } =
|
|
21153
|
+
return json3;
|
|
21154
|
+
const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id, ...rest } = json3;
|
|
21064
21155
|
if (rest.enum)
|
|
21065
21156
|
rest.enum = rest.enum.map((v2) => typeof v2 === "number" ? String(v2) : v2);
|
|
21066
21157
|
else if (typeof rest.const === "number")
|
|
@@ -21100,9 +21191,9 @@ function rewriteKeyNames(ctx) {
|
|
|
21100
21191
|
}
|
|
21101
21192
|
}
|
|
21102
21193
|
var recordProcessor = (schema, ctx, _json, params) => {
|
|
21103
|
-
const
|
|
21194
|
+
const json3 = _json;
|
|
21104
21195
|
const def = schema._zod.def;
|
|
21105
|
-
|
|
21196
|
+
json3.type = "object";
|
|
21106
21197
|
const keyType = def.keyType;
|
|
21107
21198
|
const patterns = aggregateChecks(keyType).patterns;
|
|
21108
21199
|
if (def.mode === "loose" && patterns && patterns.size > 0) {
|
|
@@ -21110,13 +21201,13 @@ var recordProcessor = (schema, ctx, _json, params) => {
|
|
|
21110
21201
|
...params,
|
|
21111
21202
|
path: [...params.path, "patternProperties", "*"]
|
|
21112
21203
|
});
|
|
21113
|
-
|
|
21204
|
+
json3.patternProperties = {};
|
|
21114
21205
|
for (const pattern of patterns) {
|
|
21115
|
-
assignProp(
|
|
21206
|
+
assignProp(json3.patternProperties, exactPattern(pattern).source, valueSchema);
|
|
21116
21207
|
}
|
|
21117
21208
|
} else {
|
|
21118
21209
|
if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
|
|
21119
|
-
|
|
21210
|
+
json3.propertyNames = processSchema(def.keyType, ctx, {
|
|
21120
21211
|
...params,
|
|
21121
21212
|
path: [...params.path, "propertyNames"]
|
|
21122
21213
|
});
|
|
@@ -21128,7 +21219,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
|
|
|
21128
21219
|
}
|
|
21129
21220
|
pending.push(schema);
|
|
21130
21221
|
}
|
|
21131
|
-
|
|
21222
|
+
json3.additionalProperties = processSchema(def.valueType, ctx, {
|
|
21132
21223
|
...params,
|
|
21133
21224
|
path: [...params.path, "additionalProperties"]
|
|
21134
21225
|
});
|
|
@@ -21138,19 +21229,19 @@ var recordProcessor = (schema, ctx, _json, params) => {
|
|
|
21138
21229
|
if (keyValues && !def.partial && !omittableOnInput) {
|
|
21139
21230
|
const validKeyValues = [...keyValues].filter((v2) => typeof v2 === "string" || typeof v2 === "number");
|
|
21140
21231
|
if (validKeyValues.length > 0) {
|
|
21141
|
-
|
|
21232
|
+
json3.required = validKeyValues.map(String);
|
|
21142
21233
|
}
|
|
21143
21234
|
}
|
|
21144
21235
|
};
|
|
21145
|
-
var nullableProcessor = (schema, ctx,
|
|
21236
|
+
var nullableProcessor = (schema, ctx, json3, params) => {
|
|
21146
21237
|
const def = schema._zod.def;
|
|
21147
21238
|
const inner = processSchema(def.innerType, ctx, params);
|
|
21148
21239
|
const seen = ctx.seen.get(schema);
|
|
21149
21240
|
if (ctx.target === "openapi-3.0") {
|
|
21150
21241
|
seen.ref = def.innerType;
|
|
21151
|
-
|
|
21242
|
+
json3.nullable = true;
|
|
21152
21243
|
} else {
|
|
21153
|
-
|
|
21244
|
+
json3.anyOf = [inner, { type: "null" }];
|
|
21154
21245
|
}
|
|
21155
21246
|
};
|
|
21156
21247
|
var nonoptionalProcessor = (schema, ctx, _json, params) => {
|
|
@@ -21160,7 +21251,7 @@ var nonoptionalProcessor = (schema, ctx, _json, params) => {
|
|
|
21160
21251
|
seen.ref = def.innerType;
|
|
21161
21252
|
};
|
|
21162
21253
|
var UNREPRESENTABLE_DEFAULT = /* @__PURE__ */ Symbol();
|
|
21163
|
-
function serializeDefaultValue(value, schema, ctx,
|
|
21254
|
+
function serializeDefaultValue(value, schema, ctx, json3, params) {
|
|
21164
21255
|
let unrepresentable = false;
|
|
21165
21256
|
const serialized = JSON.stringify(value, (_3, val) => {
|
|
21166
21257
|
if (typeof val !== "bigint")
|
|
@@ -21170,30 +21261,30 @@ function serializeDefaultValue(value, schema, ctx, json2, params) {
|
|
|
21170
21261
|
});
|
|
21171
21262
|
if (!unrepresentable)
|
|
21172
21263
|
return JSON.parse(serialized);
|
|
21173
|
-
handleUnrepresentable(schema, ctx,
|
|
21264
|
+
handleUnrepresentable(schema, ctx, json3, params, "BigInt defaults cannot be represented in JSON Schema");
|
|
21174
21265
|
return UNREPRESENTABLE_DEFAULT;
|
|
21175
21266
|
}
|
|
21176
|
-
var defaultProcessor = (schema, ctx,
|
|
21267
|
+
var defaultProcessor = (schema, ctx, json3, params) => {
|
|
21177
21268
|
const def = schema._zod.def;
|
|
21178
21269
|
processSchema(def.innerType, ctx, params);
|
|
21179
21270
|
const seen = ctx.seen.get(schema);
|
|
21180
21271
|
seen.ref = def.innerType;
|
|
21181
|
-
const value = serializeDefaultValue(def.defaultValue, schema, ctx,
|
|
21272
|
+
const value = serializeDefaultValue(def.defaultValue, schema, ctx, json3, params);
|
|
21182
21273
|
if (value !== UNREPRESENTABLE_DEFAULT)
|
|
21183
|
-
|
|
21274
|
+
json3.default = value;
|
|
21184
21275
|
};
|
|
21185
|
-
var prefaultProcessor = (schema, ctx,
|
|
21276
|
+
var prefaultProcessor = (schema, ctx, json3, params) => {
|
|
21186
21277
|
const def = schema._zod.def;
|
|
21187
21278
|
processSchema(def.innerType, ctx, params);
|
|
21188
21279
|
const seen = ctx.seen.get(schema);
|
|
21189
21280
|
seen.ref = def.innerType;
|
|
21190
21281
|
if (ctx.io !== "input")
|
|
21191
21282
|
return;
|
|
21192
|
-
const value = serializeDefaultValue(def.defaultValue, schema, ctx,
|
|
21283
|
+
const value = serializeDefaultValue(def.defaultValue, schema, ctx, json3, params);
|
|
21193
21284
|
if (value !== UNREPRESENTABLE_DEFAULT)
|
|
21194
|
-
|
|
21285
|
+
json3._prefault = value;
|
|
21195
21286
|
};
|
|
21196
|
-
var catchProcessor = (schema, ctx,
|
|
21287
|
+
var catchProcessor = (schema, ctx, json3, params) => {
|
|
21197
21288
|
const def = schema._zod.def;
|
|
21198
21289
|
processSchema(def.innerType, ctx, params);
|
|
21199
21290
|
const seen = ctx.seen.get(schema);
|
|
@@ -21202,10 +21293,10 @@ var catchProcessor = (schema, ctx, json2, params) => {
|
|
|
21202
21293
|
try {
|
|
21203
21294
|
catchValue = def.catchValue(void 0);
|
|
21204
21295
|
} catch {
|
|
21205
|
-
handleUnrepresentable(schema, ctx,
|
|
21296
|
+
handleUnrepresentable(schema, ctx, json3, params, "Dynamic catch values are not supported in JSON Schema");
|
|
21206
21297
|
return;
|
|
21207
21298
|
}
|
|
21208
|
-
|
|
21299
|
+
json3.default = catchValue;
|
|
21209
21300
|
};
|
|
21210
21301
|
var pipeProcessor = (schema, ctx, _json, params) => {
|
|
21211
21302
|
const def = schema._zod.def;
|
|
@@ -21215,12 +21306,12 @@ var pipeProcessor = (schema, ctx, _json, params) => {
|
|
|
21215
21306
|
const seen = ctx.seen.get(schema);
|
|
21216
21307
|
seen.ref = innerType;
|
|
21217
21308
|
};
|
|
21218
|
-
var readonlyProcessor = (schema, ctx,
|
|
21309
|
+
var readonlyProcessor = (schema, ctx, json3, params) => {
|
|
21219
21310
|
const def = schema._zod.def;
|
|
21220
21311
|
processSchema(def.innerType, ctx, params);
|
|
21221
21312
|
const seen = ctx.seen.get(schema);
|
|
21222
21313
|
seen.ref = def.innerType;
|
|
21223
|
-
|
|
21314
|
+
json3.readOnly = true;
|
|
21224
21315
|
};
|
|
21225
21316
|
var promiseProcessor = (schema, ctx, _json, params) => {
|
|
21226
21317
|
const def = schema._zod.def;
|
|
@@ -21707,8 +21798,8 @@ var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
|
|
|
21707
21798
|
brand() {
|
|
21708
21799
|
return this;
|
|
21709
21800
|
},
|
|
21710
|
-
register(reg,
|
|
21711
|
-
reg.add(this,
|
|
21801
|
+
register(reg, meta4) {
|
|
21802
|
+
reg.add(this, meta4);
|
|
21712
21803
|
return this;
|
|
21713
21804
|
},
|
|
21714
21805
|
refine(check2, params) {
|
|
@@ -21862,7 +21953,7 @@ var _ZodString = /* @__PURE__ */ $constructor(
|
|
|
21862
21953
|
(inst, def) => {
|
|
21863
21954
|
$ZodString.init(inst, def);
|
|
21864
21955
|
ZodType.init(inst, def);
|
|
21865
|
-
inst._zod.processJSONSchema = (ctx,
|
|
21956
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => stringProcessor(inst, ctx, json3, params);
|
|
21866
21957
|
},
|
|
21867
21958
|
/* @__PURE__ */ util_exports.derived({
|
|
21868
21959
|
format: (inst) => aggregateChecks(inst).format ?? null,
|
|
@@ -22221,7 +22312,7 @@ var ZodNumber = /* @__PURE__ */ $constructor(
|
|
|
22221
22312
|
(inst, def) => {
|
|
22222
22313
|
$ZodNumber.init(inst, def);
|
|
22223
22314
|
ZodType.init(inst, def);
|
|
22224
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22315
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => numberProcessor(inst, ctx, json3, params);
|
|
22225
22316
|
inst.isFinite = true;
|
|
22226
22317
|
},
|
|
22227
22318
|
/* @__PURE__ */ util_exports.derived({
|
|
@@ -22311,7 +22402,7 @@ function uint32(params) {
|
|
|
22311
22402
|
var ZodBoolean = /* @__PURE__ */ $constructor("ZodBoolean", (inst, def) => {
|
|
22312
22403
|
$ZodBoolean.init(inst, def);
|
|
22313
22404
|
ZodType.init(inst, def);
|
|
22314
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22405
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => booleanProcessor(inst, ctx, json3, params);
|
|
22315
22406
|
});
|
|
22316
22407
|
function boolean2(params) {
|
|
22317
22408
|
return _boolean(ZodBoolean, params);
|
|
@@ -22321,7 +22412,7 @@ var ZodBigInt = /* @__PURE__ */ $constructor(
|
|
|
22321
22412
|
(inst, def) => {
|
|
22322
22413
|
$ZodBigInt.init(inst, def);
|
|
22323
22414
|
ZodType.init(inst, def);
|
|
22324
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22415
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => bigintProcessor(inst, ctx, json3, params);
|
|
22325
22416
|
},
|
|
22326
22417
|
/* @__PURE__ */ util_exports.derived({
|
|
22327
22418
|
minValue: (inst) => aggregateChecks(inst).minimum ?? null,
|
|
@@ -22379,7 +22470,7 @@ function uint64(params) {
|
|
|
22379
22470
|
var ZodSymbol = /* @__PURE__ */ $constructor("ZodSymbol", (inst, def) => {
|
|
22380
22471
|
$ZodSymbol.init(inst, def);
|
|
22381
22472
|
ZodType.init(inst, def);
|
|
22382
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22473
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => symbolProcessor(inst, ctx, json3, params);
|
|
22383
22474
|
});
|
|
22384
22475
|
function symbol(params) {
|
|
22385
22476
|
return _symbol(ZodSymbol, params);
|
|
@@ -22387,7 +22478,7 @@ function symbol(params) {
|
|
|
22387
22478
|
var ZodUndefined = /* @__PURE__ */ $constructor("ZodUndefined", (inst, def) => {
|
|
22388
22479
|
$ZodUndefined.init(inst, def);
|
|
22389
22480
|
ZodType.init(inst, def);
|
|
22390
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22481
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => undefinedProcessor(inst, ctx, json3, params);
|
|
22391
22482
|
});
|
|
22392
22483
|
function _undefined3(params) {
|
|
22393
22484
|
return _undefined2(ZodUndefined, params);
|
|
@@ -22395,7 +22486,7 @@ function _undefined3(params) {
|
|
|
22395
22486
|
var ZodNull = /* @__PURE__ */ $constructor("ZodNull", (inst, def) => {
|
|
22396
22487
|
$ZodNull.init(inst, def);
|
|
22397
22488
|
ZodType.init(inst, def);
|
|
22398
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22489
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => nullProcessor(inst, ctx, json3, params);
|
|
22399
22490
|
});
|
|
22400
22491
|
function _null3(params) {
|
|
22401
22492
|
return _null2(ZodNull, params);
|
|
@@ -22403,7 +22494,7 @@ function _null3(params) {
|
|
|
22403
22494
|
var ZodAny = /* @__PURE__ */ $constructor("ZodAny", (inst, def) => {
|
|
22404
22495
|
$ZodAny.init(inst, def);
|
|
22405
22496
|
ZodType.init(inst, def);
|
|
22406
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22497
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => anyProcessor(inst, ctx, json3, params);
|
|
22407
22498
|
});
|
|
22408
22499
|
function any() {
|
|
22409
22500
|
return _any(ZodAny);
|
|
@@ -22411,7 +22502,7 @@ function any() {
|
|
|
22411
22502
|
var ZodUnknown = /* @__PURE__ */ $constructor("ZodUnknown", (inst, def) => {
|
|
22412
22503
|
$ZodUnknown.init(inst, def);
|
|
22413
22504
|
ZodType.init(inst, def);
|
|
22414
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22505
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => unknownProcessor(inst, ctx, json3, params);
|
|
22415
22506
|
});
|
|
22416
22507
|
function unknown() {
|
|
22417
22508
|
return _unknown(ZodUnknown);
|
|
@@ -22419,7 +22510,7 @@ function unknown() {
|
|
|
22419
22510
|
var ZodNever = /* @__PURE__ */ $constructor("ZodNever", (inst, def) => {
|
|
22420
22511
|
$ZodNever.init(inst, def);
|
|
22421
22512
|
ZodType.init(inst, def);
|
|
22422
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22513
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => neverProcessor(inst, ctx, json3, params);
|
|
22423
22514
|
});
|
|
22424
22515
|
function never(params) {
|
|
22425
22516
|
return _never(ZodNever, params);
|
|
@@ -22427,7 +22518,7 @@ function never(params) {
|
|
|
22427
22518
|
var ZodVoid = /* @__PURE__ */ $constructor("ZodVoid", (inst, def) => {
|
|
22428
22519
|
$ZodVoid.init(inst, def);
|
|
22429
22520
|
ZodType.init(inst, def);
|
|
22430
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22521
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => voidProcessor(inst, ctx, json3, params);
|
|
22431
22522
|
});
|
|
22432
22523
|
function _void2(params) {
|
|
22433
22524
|
return _void(ZodVoid, params);
|
|
@@ -22437,7 +22528,7 @@ var ZodDate = /* @__PURE__ */ $constructor(
|
|
|
22437
22528
|
(inst, def) => {
|
|
22438
22529
|
$ZodDate.init(inst, def);
|
|
22439
22530
|
ZodType.init(inst, def);
|
|
22440
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22531
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => dateProcessor(inst, ctx, json3, params);
|
|
22441
22532
|
inst.min = (value, params) => inst.check(_gte(value, params));
|
|
22442
22533
|
inst.max = (value, params) => inst.check(_lte(value, params));
|
|
22443
22534
|
},
|
|
@@ -22459,7 +22550,7 @@ var ZodArray = /* @__PURE__ */ $constructor("ZodArray", (inst, def) => {
|
|
|
22459
22550
|
_ensureDefaultMemoizer();
|
|
22460
22551
|
$ZodArray.init(inst, def);
|
|
22461
22552
|
ZodType.init(inst, def);
|
|
22462
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22553
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => arrayProcessor(inst, ctx, json3, params);
|
|
22463
22554
|
inst.element = def.element;
|
|
22464
22555
|
}, {
|
|
22465
22556
|
min(n, params) {
|
|
@@ -22489,7 +22580,7 @@ var ZodObject = /* @__PURE__ */ $constructor("ZodObject", (inst, def) => {
|
|
|
22489
22580
|
_ensureDefaultMemoizer();
|
|
22490
22581
|
$ZodObjectJIT.init(inst, def);
|
|
22491
22582
|
ZodType.init(inst, def);
|
|
22492
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22583
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => objectProcessor(inst, ctx, json3, params);
|
|
22493
22584
|
util_exports.installLazyProp(inst, "shape", (self) => self._zod.def.shape, false);
|
|
22494
22585
|
}, {
|
|
22495
22586
|
keyof() {
|
|
@@ -22562,7 +22653,7 @@ function looseObject(shape, params) {
|
|
|
22562
22653
|
var ZodUnion = /* @__PURE__ */ $constructor("ZodUnion", (inst, def) => {
|
|
22563
22654
|
$ZodUnion.init(inst, def);
|
|
22564
22655
|
ZodType.init(inst, def);
|
|
22565
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22656
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => unionProcessor(inst, ctx, json3, params);
|
|
22566
22657
|
inst.options = def.options;
|
|
22567
22658
|
});
|
|
22568
22659
|
function union(options, params) {
|
|
@@ -22575,7 +22666,7 @@ function union(options, params) {
|
|
|
22575
22666
|
var ZodXor = /* @__PURE__ */ $constructor("ZodXor", (inst, def) => {
|
|
22576
22667
|
ZodUnion.init(inst, def);
|
|
22577
22668
|
$ZodXor.init(inst, def);
|
|
22578
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22669
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => unionProcessor(inst, ctx, json3, params);
|
|
22579
22670
|
inst.options = def.options;
|
|
22580
22671
|
});
|
|
22581
22672
|
function xor(options, params) {
|
|
@@ -22601,7 +22692,7 @@ function discriminatedUnion(discriminator, options, params) {
|
|
|
22601
22692
|
var ZodIntersection = /* @__PURE__ */ $constructor("ZodIntersection", (inst, def) => {
|
|
22602
22693
|
$ZodIntersection.init(inst, def);
|
|
22603
22694
|
ZodType.init(inst, def);
|
|
22604
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22695
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => intersectionProcessor(inst, ctx, json3, params);
|
|
22605
22696
|
});
|
|
22606
22697
|
function intersection(left, right) {
|
|
22607
22698
|
return new ZodIntersection({
|
|
@@ -22614,7 +22705,7 @@ var ZodTuple = /* @__PURE__ */ $constructor("ZodTuple", (inst, def) => {
|
|
|
22614
22705
|
_ensureDefaultMemoizer();
|
|
22615
22706
|
$ZodTuple.init(inst, def);
|
|
22616
22707
|
ZodType.init(inst, def);
|
|
22617
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22708
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => tupleProcessor(inst, ctx, json3, params);
|
|
22618
22709
|
}, {
|
|
22619
22710
|
rest(rest) {
|
|
22620
22711
|
return this.clone({
|
|
@@ -22647,7 +22738,7 @@ var ZodRecord = /* @__PURE__ */ $constructor("ZodRecord", (inst, def) => {
|
|
|
22647
22738
|
_ensureDefaultMemoizer();
|
|
22648
22739
|
$ZodRecord.init(inst, def);
|
|
22649
22740
|
ZodType.init(inst, def);
|
|
22650
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22741
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => recordProcessor(inst, ctx, json3, params);
|
|
22651
22742
|
inst.keyType = def.keyType;
|
|
22652
22743
|
inst.valueType = def.valueType;
|
|
22653
22744
|
});
|
|
@@ -22689,7 +22780,7 @@ var ZodMap = /* @__PURE__ */ $constructor("ZodMap", (inst, def) => {
|
|
|
22689
22780
|
_ensureDefaultMemoizer();
|
|
22690
22781
|
$ZodMap.init(inst, def);
|
|
22691
22782
|
ZodType.init(inst, def);
|
|
22692
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22783
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => mapProcessor(inst, ctx, json3, params);
|
|
22693
22784
|
inst.keyType = def.keyType;
|
|
22694
22785
|
inst.valueType = def.valueType;
|
|
22695
22786
|
inst.min = (...args) => inst.check(_minSize(...args));
|
|
@@ -22709,7 +22800,7 @@ var ZodSet = /* @__PURE__ */ $constructor("ZodSet", (inst, def) => {
|
|
|
22709
22800
|
_ensureDefaultMemoizer();
|
|
22710
22801
|
$ZodSet.init(inst, def);
|
|
22711
22802
|
ZodType.init(inst, def);
|
|
22712
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22803
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => setProcessor(inst, ctx, json3, params);
|
|
22713
22804
|
inst.min = (...args) => inst.check(_minSize(...args));
|
|
22714
22805
|
inst.nonempty = (params) => inst.check(_minSize(1, params));
|
|
22715
22806
|
inst.max = (...args) => inst.check(_maxSize(...args));
|
|
@@ -22725,7 +22816,7 @@ function set(valueType, params) {
|
|
|
22725
22816
|
var ZodEnum = /* @__PURE__ */ $constructor("ZodEnum", (inst, def) => {
|
|
22726
22817
|
$ZodEnum.init(inst, def);
|
|
22727
22818
|
ZodType.init(inst, def);
|
|
22728
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22819
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => enumProcessor(inst, ctx, json3, params);
|
|
22729
22820
|
inst.enum = def.entries;
|
|
22730
22821
|
inst.options = [...inst._zod.values];
|
|
22731
22822
|
const keys = new Set(Object.keys(def.entries));
|
|
@@ -22761,24 +22852,24 @@ var ZodEnum = /* @__PURE__ */ $constructor("ZodEnum", (inst, def) => {
|
|
|
22761
22852
|
};
|
|
22762
22853
|
});
|
|
22763
22854
|
function _enum2(values, params) {
|
|
22764
|
-
const
|
|
22855
|
+
const entries2 = Array.isArray(values) ? Object.fromEntries(values.map((v2) => [v2, v2])) : values;
|
|
22765
22856
|
return new ZodEnum({
|
|
22766
22857
|
type: "enum",
|
|
22767
|
-
entries,
|
|
22858
|
+
entries: entries2,
|
|
22768
22859
|
...util_exports.normalizeParams(params)
|
|
22769
22860
|
});
|
|
22770
22861
|
}
|
|
22771
|
-
function nativeEnum(
|
|
22862
|
+
function nativeEnum(entries2, params) {
|
|
22772
22863
|
return new ZodEnum({
|
|
22773
22864
|
type: "enum",
|
|
22774
|
-
entries,
|
|
22865
|
+
entries: entries2,
|
|
22775
22866
|
...util_exports.normalizeParams(params)
|
|
22776
22867
|
});
|
|
22777
22868
|
}
|
|
22778
22869
|
var ZodLiteral = /* @__PURE__ */ $constructor("ZodLiteral", (inst, def) => {
|
|
22779
22870
|
$ZodLiteral.init(inst, def);
|
|
22780
22871
|
ZodType.init(inst, def);
|
|
22781
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22872
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => literalProcessor(inst, ctx, json3, params);
|
|
22782
22873
|
inst.values = new Set(def.values);
|
|
22783
22874
|
Object.defineProperty(inst, "value", {
|
|
22784
22875
|
get() {
|
|
@@ -22799,7 +22890,7 @@ function literal(value, params) {
|
|
|
22799
22890
|
var ZodFile = /* @__PURE__ */ $constructor("ZodFile", (inst, def) => {
|
|
22800
22891
|
$ZodFile.init(inst, def);
|
|
22801
22892
|
ZodType.init(inst, def);
|
|
22802
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22893
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => fileProcessor(inst, ctx, json3, params);
|
|
22803
22894
|
inst.min = (size2, params) => inst.check(_minSize(size2, params));
|
|
22804
22895
|
inst.max = (size2, params) => inst.check(_maxSize(size2, params));
|
|
22805
22896
|
inst.mime = (types, params) => inst.check(_mime(Array.isArray(types) ? types : [types], params));
|
|
@@ -22811,7 +22902,7 @@ var ZodTransform = /* @__PURE__ */ $constructor("ZodTransform", (inst, def) => {
|
|
|
22811
22902
|
_ensureDefaultMemoizer();
|
|
22812
22903
|
$ZodTransform.init(inst, def);
|
|
22813
22904
|
ZodType.init(inst, def);
|
|
22814
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22905
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => transformProcessor(inst, ctx, json3, params);
|
|
22815
22906
|
inst._zod.parse = (payload, _ctx) => {
|
|
22816
22907
|
if (_ctx.direction === "backward") {
|
|
22817
22908
|
throw new $ZodEncodeError(inst.constructor.name);
|
|
@@ -22850,7 +22941,7 @@ function transform(fn) {
|
|
|
22850
22941
|
var ZodOptional = /* @__PURE__ */ $constructor("ZodOptional", (inst, def) => {
|
|
22851
22942
|
$ZodOptional.init(inst, def);
|
|
22852
22943
|
ZodType.init(inst, def);
|
|
22853
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22944
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => optionalProcessor(inst, ctx, json3, params);
|
|
22854
22945
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
22855
22946
|
});
|
|
22856
22947
|
function optional(innerType) {
|
|
@@ -22862,7 +22953,7 @@ function optional(innerType) {
|
|
|
22862
22953
|
var ZodExactOptional = /* @__PURE__ */ $constructor("ZodExactOptional", (inst, def) => {
|
|
22863
22954
|
$ZodExactOptional.init(inst, def);
|
|
22864
22955
|
ZodType.init(inst, def);
|
|
22865
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22956
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => optionalProcessor(inst, ctx, json3, params);
|
|
22866
22957
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
22867
22958
|
});
|
|
22868
22959
|
function exactOptional(innerType) {
|
|
@@ -22874,7 +22965,7 @@ function exactOptional(innerType) {
|
|
|
22874
22965
|
var ZodNullable = /* @__PURE__ */ $constructor("ZodNullable", (inst, def) => {
|
|
22875
22966
|
$ZodNullable.init(inst, def);
|
|
22876
22967
|
ZodType.init(inst, def);
|
|
22877
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22968
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => nullableProcessor(inst, ctx, json3, params);
|
|
22878
22969
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
22879
22970
|
});
|
|
22880
22971
|
function nullable(innerType) {
|
|
@@ -22889,7 +22980,7 @@ function nullish2(innerType) {
|
|
|
22889
22980
|
var ZodDefault = /* @__PURE__ */ $constructor("ZodDefault", (inst, def) => {
|
|
22890
22981
|
$ZodDefault.init(inst, def);
|
|
22891
22982
|
ZodType.init(inst, def);
|
|
22892
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22983
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => defaultProcessor(inst, ctx, json3, params);
|
|
22893
22984
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
22894
22985
|
inst.removeDefault = inst.unwrap;
|
|
22895
22986
|
});
|
|
@@ -22905,7 +22996,7 @@ function _default2(innerType, defaultValue) {
|
|
|
22905
22996
|
var ZodPrefault = /* @__PURE__ */ $constructor("ZodPrefault", (inst, def) => {
|
|
22906
22997
|
$ZodPrefault.init(inst, def);
|
|
22907
22998
|
ZodType.init(inst, def);
|
|
22908
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22999
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => prefaultProcessor(inst, ctx, json3, params);
|
|
22909
23000
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
22910
23001
|
});
|
|
22911
23002
|
function prefault(innerType, defaultValue) {
|
|
@@ -22920,7 +23011,7 @@ function prefault(innerType, defaultValue) {
|
|
|
22920
23011
|
var ZodNonOptional = /* @__PURE__ */ $constructor("ZodNonOptional", (inst, def) => {
|
|
22921
23012
|
$ZodNonOptional.init(inst, def);
|
|
22922
23013
|
ZodType.init(inst, def);
|
|
22923
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23014
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => nonoptionalProcessor(inst, ctx, json3, params);
|
|
22924
23015
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
22925
23016
|
});
|
|
22926
23017
|
function nonoptional(innerType, params) {
|
|
@@ -22933,7 +23024,7 @@ function nonoptional(innerType, params) {
|
|
|
22933
23024
|
var ZodSuccess = /* @__PURE__ */ $constructor("ZodSuccess", (inst, def) => {
|
|
22934
23025
|
$ZodSuccess.init(inst, def);
|
|
22935
23026
|
ZodType.init(inst, def);
|
|
22936
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23027
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => successProcessor(inst, ctx, json3, params);
|
|
22937
23028
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
22938
23029
|
});
|
|
22939
23030
|
function success(innerType) {
|
|
@@ -22945,7 +23036,7 @@ function success(innerType) {
|
|
|
22945
23036
|
var ZodCatch = /* @__PURE__ */ $constructor("ZodCatch", (inst, def) => {
|
|
22946
23037
|
$ZodCatch.init(inst, def);
|
|
22947
23038
|
ZodType.init(inst, def);
|
|
22948
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23039
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => catchProcessor(inst, ctx, json3, params);
|
|
22949
23040
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
22950
23041
|
inst.removeCatch = inst.unwrap;
|
|
22951
23042
|
});
|
|
@@ -22959,7 +23050,7 @@ function _catch2(innerType, catchValue) {
|
|
|
22959
23050
|
var ZodNaN = /* @__PURE__ */ $constructor("ZodNaN", (inst, def) => {
|
|
22960
23051
|
$ZodNaN.init(inst, def);
|
|
22961
23052
|
ZodType.init(inst, def);
|
|
22962
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23053
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => nanProcessor(inst, ctx, json3, params);
|
|
22963
23054
|
});
|
|
22964
23055
|
function nan(params) {
|
|
22965
23056
|
return _nan(ZodNaN, params);
|
|
@@ -22967,7 +23058,7 @@ function nan(params) {
|
|
|
22967
23058
|
var ZodPipe = /* @__PURE__ */ $constructor("ZodPipe", (inst, def) => {
|
|
22968
23059
|
$ZodPipe.init(inst, def);
|
|
22969
23060
|
ZodType.init(inst, def);
|
|
22970
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23061
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => pipeProcessor(inst, ctx, json3, params);
|
|
22971
23062
|
inst.in = def.in;
|
|
22972
23063
|
inst.out = def.out;
|
|
22973
23064
|
});
|
|
@@ -23009,7 +23100,7 @@ var ZodPreprocess = /* @__PURE__ */ $constructor("ZodPreprocess", (inst, def) =>
|
|
|
23009
23100
|
var ZodReadonly = /* @__PURE__ */ $constructor("ZodReadonly", (inst, def) => {
|
|
23010
23101
|
$ZodReadonly.init(inst, def);
|
|
23011
23102
|
ZodType.init(inst, def);
|
|
23012
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23103
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => readonlyProcessor(inst, ctx, json3, params);
|
|
23013
23104
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
23014
23105
|
});
|
|
23015
23106
|
function readonly(innerType) {
|
|
@@ -23021,7 +23112,7 @@ function readonly(innerType) {
|
|
|
23021
23112
|
var ZodTemplateLiteral = /* @__PURE__ */ $constructor("ZodTemplateLiteral", (inst, def) => {
|
|
23022
23113
|
$ZodTemplateLiteral.init(inst, def);
|
|
23023
23114
|
ZodType.init(inst, def);
|
|
23024
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23115
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => templateLiteralProcessor(inst, ctx, json3, params);
|
|
23025
23116
|
});
|
|
23026
23117
|
function templateLiteral(parts, params) {
|
|
23027
23118
|
return new ZodTemplateLiteral({
|
|
@@ -23033,7 +23124,7 @@ function templateLiteral(parts, params) {
|
|
|
23033
23124
|
var ZodLazy = /* @__PURE__ */ $constructor("ZodLazy", (inst, def) => {
|
|
23034
23125
|
$ZodLazy.init(inst, def);
|
|
23035
23126
|
ZodType.init(inst, def);
|
|
23036
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23127
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => lazyProcessor(inst, ctx, json3, params);
|
|
23037
23128
|
inst.unwrap = () => inst._zod.def.getter();
|
|
23038
23129
|
});
|
|
23039
23130
|
function lazy(getter) {
|
|
@@ -23045,7 +23136,7 @@ function lazy(getter) {
|
|
|
23045
23136
|
var ZodPromise = /* @__PURE__ */ $constructor("ZodPromise", (inst, def) => {
|
|
23046
23137
|
$ZodPromise.init(inst, def);
|
|
23047
23138
|
ZodType.init(inst, def);
|
|
23048
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23139
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => promiseProcessor(inst, ctx, json3, params);
|
|
23049
23140
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
23050
23141
|
});
|
|
23051
23142
|
function promise(innerType) {
|
|
@@ -23057,7 +23148,7 @@ function promise(innerType) {
|
|
|
23057
23148
|
var ZodFunction = /* @__PURE__ */ $constructor("ZodFunction", (inst, def) => {
|
|
23058
23149
|
$ZodFunction.init(inst, def);
|
|
23059
23150
|
ZodType.init(inst, def);
|
|
23060
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23151
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => functionProcessor(inst, ctx, json3, params);
|
|
23061
23152
|
});
|
|
23062
23153
|
function _function(params) {
|
|
23063
23154
|
return new ZodFunction({
|
|
@@ -23069,7 +23160,7 @@ function _function(params) {
|
|
|
23069
23160
|
var ZodCustom = /* @__PURE__ */ $constructor("ZodCustom", (inst, def) => {
|
|
23070
23161
|
$ZodCustom.init(inst, def);
|
|
23071
23162
|
ZodType.init(inst, def);
|
|
23072
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23163
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => customProcessor(inst, ctx, json3, params);
|
|
23073
23164
|
});
|
|
23074
23165
|
function check(fn) {
|
|
23075
23166
|
const ch = new $ZodCheck({
|
|
@@ -24158,7 +24249,7 @@ var RULES = [
|
|
|
24158
24249
|
// DATABASE_URL=..., OPENAI_API_KEY="...", export AWS_SECRET_ACCESS_KEY=...
|
|
24159
24250
|
name: "sensitive-assignment",
|
|
24160
24251
|
pattern: new RegExp(`\\b(${SENSITIVE_KEY})(\\s*[=:]\\s*)("[^"\\n]*"|'[^'\\n]*'|[^\\s"',;]+)`, "g"),
|
|
24161
|
-
replace: (_m, key3,
|
|
24252
|
+
replace: (_m, key3, sep4) => `${key3}${sep4.includes(":") ? ": " : "="}[REDACTED]`
|
|
24162
24253
|
},
|
|
24163
24254
|
{
|
|
24164
24255
|
// aws configure set aws_secret_access_key VALUE
|
|
@@ -24170,7 +24261,7 @@ var RULES = [
|
|
|
24170
24261
|
// password=..., "token": "...", api_key: ...
|
|
24171
24262
|
name: "credential-field",
|
|
24172
24263
|
pattern: /(["']?)\b(password|passwd|pwd|pass|secret|token|api[_-]?key|apikey|access[_-]?token|refresh[_-]?token|id[_-]?token|client[_-]?secret|auth[_-]?token|private[_-]?key)\b\1(\s*[=:]\s*)("[^"\n]*"|'[^'\n]*'|[^\s&,;"'}]+)/gi,
|
|
24173
|
-
replace: (_m, q2, key3,
|
|
24264
|
+
replace: (_m, q2, key3, sep4) => `${q2}${key3}${q2}${sep4}[REDACTED]`
|
|
24174
24265
|
},
|
|
24175
24266
|
{
|
|
24176
24267
|
name: "authorization-header",
|
|
@@ -24221,25 +24312,39 @@ var RULES = [
|
|
|
24221
24312
|
replace: "[REDACTED_TOKEN]"
|
|
24222
24313
|
}
|
|
24223
24314
|
];
|
|
24224
|
-
|
|
24225
|
-
|
|
24315
|
+
var COMMON_NAMES = /* @__PURE__ */ new Set([
|
|
24316
|
+
// System, CI and container accounts
|
|
24317
|
+
...["root", "admin", "administrator", "user", "guest", "test", "tester", "dev", "developer", "build", "builder"],
|
|
24318
|
+
...["runner", "deploy", "app", "node", "git", "www", "web", "server", "ubuntu", "debian", "centos", "fedora"],
|
|
24319
|
+
...["alpine", "vagrant", "docker", "jenkins", "codespace", "vscode", "coder", "gitpod", "default", "owner"],
|
|
24320
|
+
...["local", "home", "work", "ops", "operator", "service", "bot", "agent", "demo", "sandbox", "main", "master"],
|
|
24321
|
+
// Given names that are also everyday words
|
|
24322
|
+
...["will", "mark", "max", "bill", "rob", "pat", "sue", "may", "june", "april", "august", "art", "grant"],
|
|
24323
|
+
...["hunter", "chase", "rose", "frank", "gene", "ray", "jack", "joy", "hope", "grace", "dawn", "summer", "guy"]
|
|
24324
|
+
]);
|
|
24325
|
+
function currentUserName() {
|
|
24226
24326
|
try {
|
|
24227
|
-
|
|
24327
|
+
return process.env.REFLEX_REDACT_USER ?? userInfo().username;
|
|
24228
24328
|
} catch {
|
|
24229
|
-
|
|
24329
|
+
return void 0;
|
|
24230
24330
|
}
|
|
24231
|
-
if (!name || name.length < 3) return void 0;
|
|
24232
|
-
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
24233
|
-
return new RegExp(`\\b${escaped}\\b`, "gi");
|
|
24234
24331
|
}
|
|
24235
|
-
var
|
|
24236
|
-
function
|
|
24237
|
-
|
|
24238
|
-
|
|
24239
|
-
|
|
24240
|
-
|
|
24241
|
-
name
|
|
24332
|
+
var escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
24333
|
+
function userRules() {
|
|
24334
|
+
const rules2 = [];
|
|
24335
|
+
const name = currentUserName();
|
|
24336
|
+
const homeFolder = homedir().replace(/[\\/]+$/, "");
|
|
24337
|
+
if (homeFolder.length >= 2) {
|
|
24338
|
+
rules2.push({ name: "home", pattern: new RegExp(`(?<![\\w.-])${escapeRegExp(homeFolder)}(?![\\w.-])`, "g"), replace: "~" });
|
|
24339
|
+
}
|
|
24340
|
+
if (name && name.length >= 3 && !COMMON_NAMES.has(name.toLowerCase())) {
|
|
24341
|
+
rules2.push({ name: "username", pattern: new RegExp(`\\b${escapeRegExp(name)}\\b`, "gi"), replace: "<user>" });
|
|
24242
24342
|
}
|
|
24343
|
+
return rules2;
|
|
24344
|
+
}
|
|
24345
|
+
var USER_RULES = userRules();
|
|
24346
|
+
function redactionFingerprint() {
|
|
24347
|
+
const name = currentUserName() ?? "";
|
|
24243
24348
|
return createHash2("sha256").update(`${name}
|
|
24244
24349
|
${homedir()}`).digest("hex").slice(0, 16);
|
|
24245
24350
|
}
|
|
@@ -24254,37 +24359,34 @@ function redactDeep(value) {
|
|
|
24254
24359
|
function redactWithReport(input2) {
|
|
24255
24360
|
let text = input2;
|
|
24256
24361
|
let redactions = 0;
|
|
24257
|
-
const
|
|
24258
|
-
for (const rule of RULES) {
|
|
24362
|
+
const rules2 = /* @__PURE__ */ new Set();
|
|
24363
|
+
for (const rule of [...RULES, ...USER_RULES]) {
|
|
24259
24364
|
text = text.replace(rule.pattern, (...args) => {
|
|
24260
24365
|
redactions++;
|
|
24261
|
-
|
|
24366
|
+
rules2.add(rule.name);
|
|
24262
24367
|
if (typeof rule.replace === "string") return rule.replace;
|
|
24263
24368
|
const offsetIndex = args.findIndex((a) => typeof a === "number");
|
|
24264
24369
|
const groups = args.slice(0, offsetIndex).map((a) => typeof a === "string" ? a : "");
|
|
24265
24370
|
return rule.replace(...groups);
|
|
24266
24371
|
});
|
|
24267
24372
|
}
|
|
24268
|
-
|
|
24269
|
-
text = text.replace(userPattern, () => {
|
|
24270
|
-
redactions++;
|
|
24271
|
-
rules.add("username");
|
|
24272
|
-
return "<user>";
|
|
24273
|
-
});
|
|
24274
|
-
}
|
|
24275
|
-
return { text, redactions, rules: [...rules] };
|
|
24373
|
+
return { text, redactions, rules: [...rules2] };
|
|
24276
24374
|
}
|
|
24277
24375
|
function redact(input2) {
|
|
24278
24376
|
return redactWithReport(input2).text;
|
|
24279
24377
|
}
|
|
24280
|
-
var PATH_RULES = /* @__PURE__ */ new Set(["macos-home", "linux-home", "windows-home", "encoded-home", "email"]);
|
|
24378
|
+
var PATH_RULES = /* @__PURE__ */ new Set(["macos-home", "linux-home", "windows-home", "encoded-home", "email", "home", "username"]);
|
|
24281
24379
|
function redactPath(input2) {
|
|
24282
24380
|
let text = input2;
|
|
24283
|
-
for (const rule of RULES) {
|
|
24381
|
+
for (const rule of [...RULES, ...USER_RULES]) {
|
|
24284
24382
|
if (!PATH_RULES.has(rule.name) || typeof rule.replace !== "string") continue;
|
|
24285
24383
|
text = text.replace(rule.pattern, rule.replace);
|
|
24286
24384
|
}
|
|
24287
|
-
return
|
|
24385
|
+
return text;
|
|
24386
|
+
}
|
|
24387
|
+
var REDACT_MARGIN = 1024;
|
|
24388
|
+
function redactTruncated(input2, max) {
|
|
24389
|
+
return redact(input2.slice(0, max + REDACT_MARGIN)).slice(0, max);
|
|
24288
24390
|
}
|
|
24289
24391
|
function excerpt(input2, maxLength = 160) {
|
|
24290
24392
|
const flat = redact(input2).replace(/\s+/g, " ").trim();
|
|
@@ -24385,6 +24487,47 @@ async function replaceOwnedFile(path, content, mode = 420) {
|
|
|
24385
24487
|
}
|
|
24386
24488
|
}
|
|
24387
24489
|
|
|
24490
|
+
// ../../packages/safety/src/spawn.ts
|
|
24491
|
+
import { statSync } from "node:fs";
|
|
24492
|
+
import { posix, win32 } from "node:path";
|
|
24493
|
+
var isFile = (path) => {
|
|
24494
|
+
try {
|
|
24495
|
+
return statSync(path).isFile();
|
|
24496
|
+
} catch {
|
|
24497
|
+
return false;
|
|
24498
|
+
}
|
|
24499
|
+
};
|
|
24500
|
+
function findOnPath(name, host = {}) {
|
|
24501
|
+
const env = host.env ?? process.env;
|
|
24502
|
+
const exists2 = host.isFile ?? isFile;
|
|
24503
|
+
if ((host.platform ?? process.platform) !== "win32") {
|
|
24504
|
+
for (const dir of (env.PATH ?? "").split(posix.delimiter)) if (dir && exists2(posix.join(dir, name))) return posix.join(dir, name);
|
|
24505
|
+
return void 0;
|
|
24506
|
+
}
|
|
24507
|
+
const exts = (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").toLowerCase().split(";").filter(Boolean);
|
|
24508
|
+
const names = exts.some((e2) => name.toLowerCase().endsWith(e2)) ? [name] : exts.map((e2) => name + e2);
|
|
24509
|
+
for (const dir of (env.Path ?? env.PATH ?? "").split(win32.delimiter)) {
|
|
24510
|
+
if (!dir) continue;
|
|
24511
|
+
for (const n of names) if (exists2(win32.join(dir, n))) return win32.join(dir, n);
|
|
24512
|
+
}
|
|
24513
|
+
return void 0;
|
|
24514
|
+
}
|
|
24515
|
+
var UNSAFE_FOR_CMD = /["%\r\n\0]/;
|
|
24516
|
+
function agentLaunch(command, args, host = {}) {
|
|
24517
|
+
if ((host.platform ?? process.platform) !== "win32") return { command, args };
|
|
24518
|
+
const path = findOnPath(command, host);
|
|
24519
|
+
if (!path) return { command, args };
|
|
24520
|
+
if (!/\.(cmd|bat)$/i.test(path)) return { command: path, args };
|
|
24521
|
+
if ([path, ...args].some((a) => UNSAFE_FOR_CMD.test(a))) {
|
|
24522
|
+
throw new Error(
|
|
24523
|
+
`${win32.basename(path)} is a Windows batch launcher, which can't be given quotes, % or line breaks safely. Leave them out, or install ${command} as an .exe.`
|
|
24524
|
+
);
|
|
24525
|
+
}
|
|
24526
|
+
const line2 = [path, ...args].map((a) => `"${a.replace(/(\\+)$/, "$1$1")}"`).join(" ");
|
|
24527
|
+
const env = host.env ?? process.env;
|
|
24528
|
+
return { command: env.ComSpec ?? "cmd.exe", args: ["/d", "/s", "/v:off", "/c", `"${line2}"`], windowsVerbatimArguments: true };
|
|
24529
|
+
}
|
|
24530
|
+
|
|
24388
24531
|
// ../../packages/adapters/src/jsonl.ts
|
|
24389
24532
|
import { createReadStream } from "node:fs";
|
|
24390
24533
|
import { createInterface as createInterface2 } from "node:readline";
|
|
@@ -24392,19 +24535,19 @@ var MAX_LINE_BYTES = 4 * 1024 * 1024;
|
|
|
24392
24535
|
async function* readJsonl(path) {
|
|
24393
24536
|
const stream = createReadStream(path, { encoding: "utf8" });
|
|
24394
24537
|
const rl = createInterface2({ input: stream, crlfDelay: Infinity });
|
|
24395
|
-
let
|
|
24538
|
+
let line2 = 0;
|
|
24396
24539
|
try {
|
|
24397
24540
|
for await (const raw of rl) {
|
|
24398
|
-
|
|
24541
|
+
line2++;
|
|
24399
24542
|
if (!raw.trim()) continue;
|
|
24400
24543
|
if (raw.length > MAX_LINE_BYTES) {
|
|
24401
|
-
yield { line, error: "too-large" };
|
|
24544
|
+
yield { line: line2, error: "too-large" };
|
|
24402
24545
|
continue;
|
|
24403
24546
|
}
|
|
24404
24547
|
try {
|
|
24405
|
-
yield { line, value: JSON.parse(raw) };
|
|
24548
|
+
yield { line: line2, value: JSON.parse(raw) };
|
|
24406
24549
|
} catch {
|
|
24407
|
-
yield { line, error: "invalid-json" };
|
|
24550
|
+
yield { line: line2, error: "invalid-json" };
|
|
24408
24551
|
}
|
|
24409
24552
|
}
|
|
24410
24553
|
} finally {
|
|
@@ -24422,10 +24565,10 @@ var MAX_REQUEST_CHARS = 2e3;
|
|
|
24422
24565
|
var MAX_COMMAND_CHARS = 600;
|
|
24423
24566
|
var MAX_ASSISTANT_CHARS = 400;
|
|
24424
24567
|
var clean = {
|
|
24425
|
-
request: (text) =>
|
|
24426
|
-
command: (text) =>
|
|
24427
|
-
assistant: (text) =>
|
|
24428
|
-
path: (text) =>
|
|
24568
|
+
request: (text) => redactTruncated(text, MAX_REQUEST_CHARS).trim(),
|
|
24569
|
+
command: (text) => redactTruncated(text, MAX_COMMAND_CHARS).trim(),
|
|
24570
|
+
assistant: (text) => redactTruncated(text, MAX_ASSISTANT_CHARS).trim(),
|
|
24571
|
+
path: (text) => redactTruncated(text, 400)
|
|
24429
24572
|
};
|
|
24430
24573
|
function isHarnessText(text) {
|
|
24431
24574
|
const t = text.trimStart();
|
|
@@ -24444,13 +24587,13 @@ function patchedFiles(patch) {
|
|
|
24444
24587
|
async function listFiles(dir, ext, depth) {
|
|
24445
24588
|
const out2 = [];
|
|
24446
24589
|
async function walk(current, level) {
|
|
24447
|
-
let
|
|
24590
|
+
let entries2;
|
|
24448
24591
|
try {
|
|
24449
|
-
|
|
24592
|
+
entries2 = await readdir(current, { withFileTypes: true });
|
|
24450
24593
|
} catch {
|
|
24451
24594
|
return;
|
|
24452
24595
|
}
|
|
24453
|
-
for (const entry of
|
|
24596
|
+
for (const entry of entries2) {
|
|
24454
24597
|
if (entry.isSymbolicLink()) continue;
|
|
24455
24598
|
const full = join2(current, entry.name);
|
|
24456
24599
|
if (level < depth) {
|
|
@@ -24647,13 +24790,13 @@ var ClaudeCodeAdapter = class {
|
|
|
24647
24790
|
let skippedRecords = 0;
|
|
24648
24791
|
const fallbackId = basename2(file2.path, ".jsonl");
|
|
24649
24792
|
try {
|
|
24650
|
-
for await (const
|
|
24793
|
+
for await (const line2 of readJsonl(file2.path)) {
|
|
24651
24794
|
totalRecords++;
|
|
24652
|
-
if (
|
|
24795
|
+
if (line2.error) {
|
|
24653
24796
|
skippedRecords++;
|
|
24654
24797
|
continue;
|
|
24655
24798
|
}
|
|
24656
|
-
const parsed = ClaudeRecord.safeParse(
|
|
24799
|
+
const parsed = ClaudeRecord.safeParse(line2.value);
|
|
24657
24800
|
if (!parsed.success) {
|
|
24658
24801
|
skippedRecords++;
|
|
24659
24802
|
continue;
|
|
@@ -24835,27 +24978,27 @@ var CodexAdapter = class {
|
|
|
24835
24978
|
const eventUserMessages = [];
|
|
24836
24979
|
let model2;
|
|
24837
24980
|
try {
|
|
24838
|
-
for await (const
|
|
24981
|
+
for await (const line2 of readJsonl(file2.path)) {
|
|
24839
24982
|
totalRecords++;
|
|
24840
|
-
if (
|
|
24983
|
+
if (line2.error) {
|
|
24841
24984
|
skippedRecords++;
|
|
24842
24985
|
continue;
|
|
24843
24986
|
}
|
|
24844
|
-
const wrapped = RolloutLine.safeParse(
|
|
24987
|
+
const wrapped = RolloutLine.safeParse(line2.value);
|
|
24845
24988
|
if (!wrapped.success) {
|
|
24846
24989
|
skippedRecords++;
|
|
24847
24990
|
continue;
|
|
24848
24991
|
}
|
|
24849
24992
|
const at = wrapped.data.timestamp;
|
|
24850
24993
|
const kind = wrapped.data.type;
|
|
24851
|
-
const body = wrapped.data.payload ??
|
|
24994
|
+
const body = wrapped.data.payload ?? line2.value;
|
|
24852
24995
|
b3.touch(at);
|
|
24853
24996
|
if (kind === "session_meta") {
|
|
24854
|
-
const
|
|
24855
|
-
if (
|
|
24856
|
-
if (
|
|
24857
|
-
if (
|
|
24858
|
-
b3.touch(
|
|
24997
|
+
const meta4 = Item.safeParse({ type: "session_meta", ...body });
|
|
24998
|
+
if (meta4.success) {
|
|
24999
|
+
if (meta4.data.id) b3.nativeId = meta4.data.id.slice(0, 80);
|
|
25000
|
+
if (meta4.data.cwd) b3.cwd = meta4.data.cwd;
|
|
25001
|
+
b3.touch(meta4.data.timestamp);
|
|
24859
25002
|
}
|
|
24860
25003
|
continue;
|
|
24861
25004
|
}
|
|
@@ -24951,7 +25094,7 @@ var CodexAdapter = class {
|
|
|
24951
25094
|
};
|
|
24952
25095
|
|
|
24953
25096
|
// ../../packages/adapters/src/cursor.ts
|
|
24954
|
-
import { existsSync, statSync } from "node:fs";
|
|
25097
|
+
import { existsSync, statSync as statSync2 } from "node:fs";
|
|
24955
25098
|
import { lstat as lstat3, readdir as readdir2 } from "node:fs/promises";
|
|
24956
25099
|
import { homedir as homedir6 } from "node:os";
|
|
24957
25100
|
import { basename as basename4, dirname as dirname2, join as join6 } from "node:path";
|
|
@@ -25014,6 +25157,95 @@ var CursorModelIndex = class {
|
|
|
25014
25157
|
}
|
|
25015
25158
|
};
|
|
25016
25159
|
|
|
25160
|
+
// ../../packages/adapters/src/cursor-usage.ts
|
|
25161
|
+
import { closeSync, fstatSync, openSync, readSync } from "node:fs";
|
|
25162
|
+
var MAX_LOG_BYTES = 64 * 1024 * 1024;
|
|
25163
|
+
var ID2 = /^[A-Za-z0-9-]{1,80}$/;
|
|
25164
|
+
var MODEL = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,79}$/;
|
|
25165
|
+
var CLAUDE = /^(?:claude-)?(?:(\d+(?:[.-]\d+)?)-(opus|sonnet|haiku|fable|mythos)|(opus|sonnet|haiku|fable|mythos)-(\d+(?:[.-]\d+)?))(?:-.*)?$/;
|
|
25166
|
+
function cursorModelName(id) {
|
|
25167
|
+
const m2 = id.toLowerCase().match(CLAUDE);
|
|
25168
|
+
if (!m2) return id;
|
|
25169
|
+
const name = `claude-${m2[2] ?? m2[3]}-${(m2[1] ?? m2[4]).replace(".", "-")}`;
|
|
25170
|
+
return priceOf(name) ? name : id;
|
|
25171
|
+
}
|
|
25172
|
+
function tail(path, max) {
|
|
25173
|
+
let fd;
|
|
25174
|
+
try {
|
|
25175
|
+
fd = openSync(path, "r");
|
|
25176
|
+
const size2 = fstatSync(fd).size;
|
|
25177
|
+
const start = Math.max(0, size2 - max);
|
|
25178
|
+
const buf = Buffer.alloc(size2 - start);
|
|
25179
|
+
readSync(fd, buf, 0, buf.length, start);
|
|
25180
|
+
const text = buf.toString("utf8");
|
|
25181
|
+
return start ? text.slice(text.indexOf("\n") + 1) : text;
|
|
25182
|
+
} catch {
|
|
25183
|
+
return "";
|
|
25184
|
+
} finally {
|
|
25185
|
+
if (fd !== void 0) closeSync(fd);
|
|
25186
|
+
}
|
|
25187
|
+
}
|
|
25188
|
+
var count = (v2) => typeof v2 === "number" && Number.isFinite(v2) && v2 > 0 ? Math.round(v2) : 0;
|
|
25189
|
+
var CursorUsageLog = class {
|
|
25190
|
+
constructor(path) {
|
|
25191
|
+
this.path = path;
|
|
25192
|
+
}
|
|
25193
|
+
path;
|
|
25194
|
+
turns;
|
|
25195
|
+
load() {
|
|
25196
|
+
if (this.turns) return this.turns;
|
|
25197
|
+
const turns = /* @__PURE__ */ new Map();
|
|
25198
|
+
this.turns = turns;
|
|
25199
|
+
for (const line2 of tail(this.path, MAX_LOG_BYTES).split("\n")) {
|
|
25200
|
+
let r2;
|
|
25201
|
+
try {
|
|
25202
|
+
r2 = JSON.parse(line2);
|
|
25203
|
+
} catch {
|
|
25204
|
+
continue;
|
|
25205
|
+
}
|
|
25206
|
+
const conv = typeof r2.conversation_id === "string" && ID2.test(r2.conversation_id) ? r2.conversation_id : void 0;
|
|
25207
|
+
const gen = typeof r2.generation_id === "string" && ID2.test(r2.generation_id) ? r2.generation_id : void 0;
|
|
25208
|
+
if (!conv || !gen) continue;
|
|
25209
|
+
const cacheRead = count(r2.cache_read_tokens);
|
|
25210
|
+
const cacheWrite = count(r2.cache_write_tokens);
|
|
25211
|
+
const usage2 = { input: Math.max(0, count(r2.input_tokens) - cacheRead - cacheWrite), output: count(r2.output_tokens), cacheRead, cacheWrite };
|
|
25212
|
+
const turn = {
|
|
25213
|
+
event: r2.event === "stop" ? "stop" : "afterAgentResponse",
|
|
25214
|
+
at: typeof r2.at === "string" ? Date.parse(r2.at) || 0 : 0,
|
|
25215
|
+
model: typeof r2.model === "string" && MODEL.test(r2.model) ? cursorModelName(r2.model) : void 0,
|
|
25216
|
+
usage: usage2
|
|
25217
|
+
};
|
|
25218
|
+
const byGen = turns.get(conv) ?? /* @__PURE__ */ new Map();
|
|
25219
|
+
turns.set(conv, byGen);
|
|
25220
|
+
const prev = byGen.get(gen);
|
|
25221
|
+
if (!prev || turn.event === "stop" || prev.event !== "stop") byGen.set(gen, turn);
|
|
25222
|
+
}
|
|
25223
|
+
return turns;
|
|
25224
|
+
}
|
|
25225
|
+
/** Usage for these conversations, in total and per model. */
|
|
25226
|
+
usageFor(ids) {
|
|
25227
|
+
let usage2;
|
|
25228
|
+
const byModel2 = {};
|
|
25229
|
+
for (const id of ids)
|
|
25230
|
+
for (const t of this.load().get(id)?.values() ?? []) {
|
|
25231
|
+
usage2 = addUsage(usage2, t.usage);
|
|
25232
|
+
if (t.model) byModel2[t.model] = addUsage(byModel2[t.model], t.usage);
|
|
25233
|
+
}
|
|
25234
|
+
return usage2 ? { usage: usage2, byModel: byModel2 } : void 0;
|
|
25235
|
+
}
|
|
25236
|
+
/** How many turns were recorded for these conversations, and when the latest was: part of a chat's identity for the scan cache. */
|
|
25237
|
+
signature(ids) {
|
|
25238
|
+
let turns = 0;
|
|
25239
|
+
let latest = 0;
|
|
25240
|
+
for (const id of ids)
|
|
25241
|
+
for (const t of this.load().get(id)?.values() ?? []) {
|
|
25242
|
+
turns++;
|
|
25243
|
+
latest = Math.max(latest, t.at);
|
|
25244
|
+
}
|
|
25245
|
+
return { turns, latest };
|
|
25246
|
+
}
|
|
25247
|
+
};
|
|
25248
|
+
|
|
25017
25249
|
// ../../packages/adapters/src/cursor.ts
|
|
25018
25250
|
var CONTROL = /[\x00-\x1f\x7f-\x9f]/g;
|
|
25019
25251
|
var Block = external_exports.object({
|
|
@@ -25042,7 +25274,7 @@ var MAX_AGENT_TRANSCRIPTS = 300;
|
|
|
25042
25274
|
async function agentTranscripts(chatFile) {
|
|
25043
25275
|
return listFiles(join6(dirname2(chatFile), "subagents"), ".jsonl", 0);
|
|
25044
25276
|
}
|
|
25045
|
-
async function
|
|
25277
|
+
async function isFile2(path) {
|
|
25046
25278
|
try {
|
|
25047
25279
|
return (await lstat3(path)).isFile();
|
|
25048
25280
|
} catch {
|
|
@@ -25070,7 +25302,7 @@ function decodeWorkspace(encoded, root = "/") {
|
|
|
25070
25302
|
budget--;
|
|
25071
25303
|
const candidate = join6(dir, tokens2.slice(i, j2).join("-"));
|
|
25072
25304
|
try {
|
|
25073
|
-
if (existsSync(candidate) &&
|
|
25305
|
+
if (existsSync(candidate) && statSync2(candidate).isDirectory()) {
|
|
25074
25306
|
const found = walk(candidate, j2);
|
|
25075
25307
|
if (found) return found;
|
|
25076
25308
|
}
|
|
@@ -25089,10 +25321,21 @@ var CursorAdapter = class {
|
|
|
25089
25321
|
/** Cursor's app database, for model names. Undefined for a custom transcript folder, which reads only that folder. */
|
|
25090
25322
|
stateDb;
|
|
25091
25323
|
models;
|
|
25092
|
-
|
|
25324
|
+
/** Token counts recorded by Reflex's Cursor hook, when it was turned on. */
|
|
25325
|
+
usage;
|
|
25326
|
+
constructor(root, stateDb, opts = {}) {
|
|
25093
25327
|
this.root = root ?? process.env.REFLEX_CURSOR_DIR ?? join6(homedir6(), ".cursor", "projects");
|
|
25094
25328
|
const custom2 = root ?? process.env.REFLEX_CURSOR_DIR;
|
|
25095
25329
|
this.stateDb = stateDb ?? process.env.REFLEX_CURSOR_STATE_DB ?? (custom2 ? void 0 : defaultCursorStateDb());
|
|
25330
|
+
if (opts.usageLog) this.usage = new CursorUsageLog(opts.usageLog);
|
|
25331
|
+
}
|
|
25332
|
+
/**
|
|
25333
|
+
* The conversation ids whose recorded turns belong to this chat: the chat's own. Agents it
|
|
25334
|
+
* launched may report their own turns too, and whether the chat's totals already include them
|
|
25335
|
+
* is not known yet, so they are left out rather than possibly counted twice.
|
|
25336
|
+
*/
|
|
25337
|
+
conversationIds(chatFile) {
|
|
25338
|
+
return [basename4(chatFile, ".jsonl")];
|
|
25096
25339
|
}
|
|
25097
25340
|
/** Whether the user allowed reading model names from Cursor's app database in this scan. */
|
|
25098
25341
|
get readsModels() {
|
|
@@ -25122,11 +25365,11 @@ var CursorAdapter = class {
|
|
|
25122
25365
|
}
|
|
25123
25366
|
async requestPermission(ask2, days) {
|
|
25124
25367
|
if (!await ask2(`Read Cursor agent sessions from the last ${days} day${days === 1 ? "" : "s"} at ${displayPath(this.root)}?`)) return false;
|
|
25125
|
-
if (this.stateDb && await
|
|
25126
|
-
const
|
|
25368
|
+
if (this.stateDb && await isFile2(this.stateDb)) {
|
|
25369
|
+
const allowed2 = await ask2(
|
|
25127
25370
|
`Also read which model each Cursor chat used, from Cursor's app database at ${displayPath(this.stateDb)}? Read-only; only model names are extracted, never messages.`
|
|
25128
25371
|
);
|
|
25129
|
-
if (
|
|
25372
|
+
if (allowed2) this.models = new CursorModelIndex(this.stateDb);
|
|
25130
25373
|
}
|
|
25131
25374
|
return true;
|
|
25132
25375
|
}
|
|
@@ -25150,6 +25393,11 @@ var CursorAdapter = class {
|
|
|
25150
25393
|
f.identity.ctimeMs = Math.max(f.identity.ctimeMs, agent.identity.ctimeMs);
|
|
25151
25394
|
}
|
|
25152
25395
|
}
|
|
25396
|
+
if (this.usage) {
|
|
25397
|
+
const sig = this.usage.signature(this.conversationIds(f.path));
|
|
25398
|
+
f.sizeBytes += sig.turns;
|
|
25399
|
+
if (f.identity && sig.latest) f.identity.ctimeMs = Math.max(f.identity.ctimeMs, sig.latest);
|
|
25400
|
+
}
|
|
25153
25401
|
if (f.modifiedAt >= cutoff) out2.push(f);
|
|
25154
25402
|
}
|
|
25155
25403
|
return out2;
|
|
@@ -25194,6 +25442,11 @@ var CursorAdapter = class {
|
|
|
25194
25442
|
}
|
|
25195
25443
|
if (delegated.length) b3.events.splice(firstSpawn ?? b3.events.length, 0, ...delegated.slice(0, Math.max(0, MAX_EVENTS_PER_SESSION - b3.events.length)));
|
|
25196
25444
|
b3.touch(file2.modifiedAt.toISOString());
|
|
25445
|
+
const recorded2 = this.usage?.usageFor(this.conversationIds(file2.path));
|
|
25446
|
+
if (recorded2) {
|
|
25447
|
+
b3.usage = recorded2.usage;
|
|
25448
|
+
if (Object.keys(recorded2.byModel).length) b3.usageByModel = recorded2.byModel;
|
|
25449
|
+
}
|
|
25197
25450
|
const session = b3.build();
|
|
25198
25451
|
if (spawned.length || transcripts) session.agents = { spawned, transcripts };
|
|
25199
25452
|
if (this.models) session.models = this.models.modelsFor(b3.nativeId);
|
|
@@ -25205,13 +25458,13 @@ var CursorAdapter = class {
|
|
|
25205
25458
|
}
|
|
25206
25459
|
/** Streams a transcript's user and assistant content blocks; malformed lines and blocks are counted and skipped. */
|
|
25207
25460
|
async readBlocks(path, b3, counts, onBlock) {
|
|
25208
|
-
for await (const
|
|
25461
|
+
for await (const line2 of readJsonl(path)) {
|
|
25209
25462
|
counts.total++;
|
|
25210
|
-
if (
|
|
25463
|
+
if (line2.error) {
|
|
25211
25464
|
counts.skipped++;
|
|
25212
25465
|
continue;
|
|
25213
25466
|
}
|
|
25214
|
-
const parsed = CursorRecord.safeParse(
|
|
25467
|
+
const parsed = CursorRecord.safeParse(line2.value);
|
|
25215
25468
|
if (!parsed.success) {
|
|
25216
25469
|
counts.skipped++;
|
|
25217
25470
|
continue;
|
|
@@ -25801,7 +26054,7 @@ function bigrams(stems) {
|
|
|
25801
26054
|
}
|
|
25802
26055
|
var BIGRAM_BLEND = 0.3;
|
|
25803
26056
|
function termSimilarities(termLists, weights) {
|
|
25804
|
-
const stems = termLists.map((
|
|
26057
|
+
const stems = termLists.map((terms2) => terms2.map(stem));
|
|
25805
26058
|
const words2 = buildTfIdf(stems, weights && new Map([...weights].map(([t, w2]) => [stem(t), w2]))).vectors;
|
|
25806
26059
|
const pairs = buildTfIdf(stems.map(bigrams)).vectors;
|
|
25807
26060
|
return (i, j2) => {
|
|
@@ -25829,9 +26082,9 @@ var CONCEPT_WORDS = {
|
|
|
25829
26082
|
var CONCEPT_OF = /* @__PURE__ */ new Map();
|
|
25830
26083
|
var DEVELOPER_WORDS = /* @__PURE__ */ new Set([...Object.values(CONCEPT_WORDS).flat(), ...Object.values(CANONICAL)]);
|
|
25831
26084
|
for (const [concept, words2] of Object.entries(CONCEPT_WORDS)) for (const w2 of words2) CONCEPT_OF.set(w2, concept);
|
|
25832
|
-
function concepts(
|
|
26085
|
+
function concepts(terms2) {
|
|
25833
26086
|
const v2 = /* @__PURE__ */ new Map();
|
|
25834
|
-
for (const t of
|
|
26087
|
+
for (const t of terms2) {
|
|
25835
26088
|
const c2 = t.startsWith("@") ? "dependency" : CONCEPT_OF.get(t) ?? CONCEPT_OF.get(stem(t));
|
|
25836
26089
|
if (c2) v2.set(c2, (v2.get(c2) ?? 0) + 1);
|
|
25837
26090
|
}
|
|
@@ -25846,14 +26099,14 @@ function buildTfIdf(docs, weights) {
|
|
|
25846
26099
|
for (const doc of docs) for (const term of new Set(doc)) df.set(term, (df.get(term) ?? 0) + 1);
|
|
25847
26100
|
const n = docs.length;
|
|
25848
26101
|
const idf = /* @__PURE__ */ new Map();
|
|
25849
|
-
for (const [term,
|
|
26102
|
+
for (const [term, count3] of df) idf.set(term, Math.log((n + 1) / (count3 + 1)) + 1);
|
|
25850
26103
|
const vectors = docs.map((doc) => {
|
|
25851
26104
|
const tf = /* @__PURE__ */ new Map();
|
|
25852
26105
|
for (const term of doc) tf.set(term, (tf.get(term) ?? 0) + 1);
|
|
25853
26106
|
const v2 = /* @__PURE__ */ new Map();
|
|
25854
26107
|
let norm = 0;
|
|
25855
|
-
for (const [term,
|
|
25856
|
-
const w2 = (1 + Math.log(
|
|
26108
|
+
for (const [term, count3] of tf) {
|
|
26109
|
+
const w2 = (1 + Math.log(count3)) * (idf.get(term) ?? 1) * (weights?.get(term) ?? 1);
|
|
25857
26110
|
v2.set(term, w2);
|
|
25858
26111
|
norm += w2 * w2;
|
|
25859
26112
|
}
|
|
@@ -25879,24 +26132,33 @@ var WEIGHTS = {
|
|
|
25879
26132
|
repository: 0.05
|
|
25880
26133
|
};
|
|
25881
26134
|
function jaccard(a, b3) {
|
|
25882
|
-
|
|
25883
|
-
|
|
26135
|
+
return setJaccard(new Set(a), new Set(b3));
|
|
26136
|
+
}
|
|
26137
|
+
function setJaccard(A3, B2) {
|
|
25884
26138
|
if (!A3.size && !B2.size) return 0;
|
|
25885
26139
|
let inter = 0;
|
|
25886
26140
|
for (const x2 of A3) if (B2.has(x2)) inter++;
|
|
25887
26141
|
return inter / (A3.size + B2.size - inter);
|
|
25888
26142
|
}
|
|
26143
|
+
var lcsRows = new Int32Array(0);
|
|
25889
26144
|
function lcsLength(a, b3) {
|
|
25890
26145
|
if (!a.length || !b3.length) return 0;
|
|
25891
|
-
|
|
26146
|
+
const width = b3.length + 1;
|
|
26147
|
+
if (lcsRows.length < 2 * width) lcsRows = new Int32Array(2 * width);
|
|
26148
|
+
const rows2 = lcsRows;
|
|
26149
|
+
let prev = 0;
|
|
26150
|
+
let cur = width;
|
|
26151
|
+
rows2.fill(0, prev, prev + width);
|
|
25892
26152
|
for (let i = 1; i <= a.length; i++) {
|
|
25893
|
-
|
|
26153
|
+
rows2[cur] = 0;
|
|
25894
26154
|
for (let j2 = 1; j2 <= b3.length; j2++) {
|
|
25895
|
-
cur
|
|
26155
|
+
rows2[cur + j2] = a[i - 1] === b3[j2 - 1] ? rows2[prev + j2 - 1] + 1 : Math.max(rows2[prev + j2], rows2[cur + j2 - 1]);
|
|
25896
26156
|
}
|
|
26157
|
+
const done = prev;
|
|
25897
26158
|
prev = cur;
|
|
26159
|
+
cur = done;
|
|
25898
26160
|
}
|
|
25899
|
-
return prev
|
|
26161
|
+
return rows2[prev + b3.length];
|
|
25900
26162
|
}
|
|
25901
26163
|
var COARSE = {
|
|
25902
26164
|
"inspect-git": "git",
|
|
@@ -25920,16 +26182,21 @@ var COARSE = {
|
|
|
25920
26182
|
function collapse(seq) {
|
|
25921
26183
|
return seq.filter((s, i) => i === 0 || seq[i - 1] !== s);
|
|
25922
26184
|
}
|
|
26185
|
+
var steps = (seq) => ({ seq, set: new Set(seq) });
|
|
26186
|
+
function actionShape(sequence) {
|
|
26187
|
+
const fine = sequence.filter((s) => s !== "summarize");
|
|
26188
|
+
return { fine: steps(fine), coarse: steps(collapse(fine.map((v2) => COARSE[v2] ?? v2))) };
|
|
26189
|
+
}
|
|
25923
26190
|
function sequenceAgreement(x2, y3) {
|
|
25924
|
-
if (!x2.length || !y3.length) return 0;
|
|
25925
|
-
const lcs = 2 * lcsLength(x2, y3) / (x2.length + y3.length);
|
|
25926
|
-
return 0.5 * lcs + 0.5 *
|
|
26191
|
+
if (!x2.seq.length || !y3.seq.length) return 0;
|
|
26192
|
+
const lcs = 2 * lcsLength(x2.seq, y3.seq) / (x2.seq.length + y3.seq.length);
|
|
26193
|
+
return 0.5 * lcs + 0.5 * setJaccard(x2.set, y3.set);
|
|
26194
|
+
}
|
|
26195
|
+
function shapeSimilarity(a, b3) {
|
|
26196
|
+
return 0.5 * sequenceAgreement(a.fine, b3.fine) + 0.5 * sequenceAgreement(a.coarse, b3.coarse);
|
|
25927
26197
|
}
|
|
25928
26198
|
function actionSimilarity(a, b3) {
|
|
25929
|
-
|
|
25930
|
-
const y3 = b3.filter((s) => s !== "summarize");
|
|
25931
|
-
const coarse = (s) => collapse(s.map((v2) => COARSE[v2] ?? v2));
|
|
25932
|
-
return 0.5 * sequenceAgreement(x2, y3) + 0.5 * sequenceAgreement(coarse(x2), coarse(y3));
|
|
26199
|
+
return shapeSimilarity(actionShape(a), actionShape(b3));
|
|
25933
26200
|
}
|
|
25934
26201
|
function opKeys(t) {
|
|
25935
26202
|
const keys = new Set(t.commands.map(opKey));
|
|
@@ -25941,12 +26208,15 @@ function opKeys(t) {
|
|
|
25941
26208
|
keys.delete("");
|
|
25942
26209
|
return keys;
|
|
25943
26210
|
}
|
|
25944
|
-
function
|
|
26211
|
+
function traceFeatures(t) {
|
|
26212
|
+
return { actions: actionShape(t.actionSequence), keys: opKeys(t), files: new Set(t.fileCategories) };
|
|
26213
|
+
}
|
|
26214
|
+
function similarity(a, b3, intentScore, fa = traceFeatures(a), fb = traceFeatures(b3)) {
|
|
25945
26215
|
const parts = {
|
|
25946
26216
|
intent: intentScore,
|
|
25947
|
-
actions:
|
|
25948
|
-
commands:
|
|
25949
|
-
files:
|
|
26217
|
+
actions: shapeSimilarity(fa.actions, fb.actions),
|
|
26218
|
+
commands: setJaccard(fa.keys, fb.keys),
|
|
26219
|
+
files: setJaccard(fa.files, fb.files),
|
|
25950
26220
|
repository: a.projectHash && a.projectHash === b3.projectHash ? 1 : 0
|
|
25951
26221
|
};
|
|
25952
26222
|
const total = WEIGHTS.intent * parts.intent + WEIGHTS.actions * parts.actions + WEIGHTS.commands * parts.commands + WEIGHTS.files * parts.files + WEIGHTS.repository * parts.repository;
|
|
@@ -26040,8 +26310,11 @@ function render(polarity, ws) {
|
|
|
26040
26310
|
return polarity === "avoid" ? `Don't ${phrase}.` : `${phrase[0].toUpperCase()}${phrase.slice(1)}.`;
|
|
26041
26311
|
}
|
|
26042
26312
|
function recurringCorrections(perInstance) {
|
|
26313
|
+
return recurringCorrectionsBySession(perInstance).map(({ instances: _3, ...c2 }) => c2);
|
|
26314
|
+
}
|
|
26315
|
+
function recurringCorrectionsBySession(perInstance) {
|
|
26043
26316
|
const items = perInstance.flatMap((cs, inst) => cs.map((c2) => ({ ...c2, inst, keys: matchKeys(c2.words) })));
|
|
26044
|
-
const
|
|
26317
|
+
const rules2 = /* @__PURE__ */ new Map();
|
|
26045
26318
|
for (let i = 0; i < items.length; i++) {
|
|
26046
26319
|
for (let j2 = i + 1; j2 < items.length; j2++) {
|
|
26047
26320
|
const a = items[i];
|
|
@@ -26051,16 +26324,16 @@ function recurringCorrections(perInstance) {
|
|
|
26051
26324
|
const shared = a.words.filter((_3, k3) => other.has(a.keys[k3]));
|
|
26052
26325
|
if (!wellFormed(a.polarity, shared)) continue;
|
|
26053
26326
|
const id = `${a.polarity}:${shared.join(" ")}`;
|
|
26054
|
-
const rule =
|
|
26327
|
+
const rule = rules2.get(id) ?? { polarity: a.polarity, words: shared, sessions: /* @__PURE__ */ new Set() };
|
|
26055
26328
|
rule.sessions.add(a.inst).add(b3.inst);
|
|
26056
|
-
|
|
26329
|
+
rules2.set(id, rule);
|
|
26057
26330
|
}
|
|
26058
26331
|
}
|
|
26059
|
-
const all = [...
|
|
26332
|
+
const all = [...rules2.values()];
|
|
26060
26333
|
const covered = (r2) => all.some(
|
|
26061
26334
|
(s) => s !== r2 && s.polarity === r2.polarity && s.words.length < r2.words.length && s.words.every((w2) => r2.words.includes(w2)) && [...r2.sessions].every((x2) => s.sessions.has(x2))
|
|
26062
26335
|
);
|
|
26063
|
-
return all.filter((r2) => !covered(r2)).map((r2) => ({ polarity: r2.polarity, text: render(r2.polarity, r2.words), sessions: r2.sessions.size })).sort((a, b3) => b3.sessions - a.sessions || a.text.localeCompare(b3.text));
|
|
26336
|
+
return all.filter((r2) => !covered(r2)).map((r2) => ({ polarity: r2.polarity, text: render(r2.polarity, r2.words), sessions: r2.sessions.size, instances: [...r2.sessions].sort((a, b3) => a - b3) })).sort((a, b3) => b3.sessions - a.sessions || a.text.localeCompare(b3.text));
|
|
26064
26337
|
}
|
|
26065
26338
|
|
|
26066
26339
|
// ../../packages/analysis/src/context.ts
|
|
@@ -26068,12 +26341,12 @@ function withFloor(vectors, floor) {
|
|
|
26068
26341
|
return Object.assign(vectors, { floor });
|
|
26069
26342
|
}
|
|
26070
26343
|
var CONTEXT_CHARS = 2e3;
|
|
26071
|
-
function isNoiseLine(
|
|
26072
|
-
return /^\s*at\s/.test(
|
|
26073
|
-
|
|
26344
|
+
function isNoiseLine(line2) {
|
|
26345
|
+
return /^\s*at\s/.test(line2) || /\d{4}-\d\d-\d\dT\d\d:\d\d/.test(line2) || /^\s*[✓✗✔✘×√]\s/.test(line2) || /^\s*\[[\w-]+\]/.test(line2) || // Mostly digits and symbols. Letters of any script count, so non-English text is never noise.
|
|
26346
|
+
line2.length > 30 && (line2.match(new RegExp("\\p{L}{2,}", "gu")) ?? []).join("").length / line2.length < 0.4;
|
|
26074
26347
|
}
|
|
26075
26348
|
function requestWords(text) {
|
|
26076
|
-
const kept = text.replace(/```[\s\S]*?(```|$)/g, " ").split("\n").filter((
|
|
26349
|
+
const kept = text.replace(/```[\s\S]*?(```|$)/g, " ").split("\n").filter((line2) => !isNoiseLine(line2)).join("\n").replace(/\bat [\w.<>$]+ \([^)]*:\d+:\d+\)/g, " ").trim();
|
|
26077
26350
|
return kept || text;
|
|
26078
26351
|
}
|
|
26079
26352
|
function contextDocument(t, request) {
|
|
@@ -26122,8 +26395,8 @@ function usedSkill(trace, name) {
|
|
|
26122
26395
|
return (trace.skillsUsed ?? []).some((s) => s === name || s.endsWith(`:${name}`));
|
|
26123
26396
|
}
|
|
26124
26397
|
function buildTrace(session) {
|
|
26125
|
-
const
|
|
26126
|
-
const
|
|
26398
|
+
const steps2 = [];
|
|
26399
|
+
const commands2 = [];
|
|
26127
26400
|
const tools = /* @__PURE__ */ new Set();
|
|
26128
26401
|
const fileCategories = /* @__PURE__ */ new Set();
|
|
26129
26402
|
const eventHashes = [];
|
|
@@ -26140,8 +26413,8 @@ function buildTrace(session) {
|
|
|
26140
26413
|
tools.add("shell");
|
|
26141
26414
|
for (const s of skillsIn(ev.command)) skills.add(s);
|
|
26142
26415
|
for (const fp of classifyCommand(ev.command)) {
|
|
26143
|
-
|
|
26144
|
-
|
|
26416
|
+
commands2.push(ev.isError ? { ...fp, failed: true } : fp);
|
|
26417
|
+
steps2.push({ action: fp.action, isError: ev.isError, command: fp });
|
|
26145
26418
|
show2(fp.normalized);
|
|
26146
26419
|
}
|
|
26147
26420
|
eventHashes.push(shortHash(`shell|${ev.at ?? ""}|${ev.command}`));
|
|
@@ -26152,7 +26425,7 @@ function buildTrace(session) {
|
|
|
26152
26425
|
if (ev.op === "read") for (const s of skillsIn(ev.path)) skills.add(s);
|
|
26153
26426
|
const category = fileCategory(ev.path);
|
|
26154
26427
|
fileCategories.add(category);
|
|
26155
|
-
|
|
26428
|
+
steps2.push({ action: fileAction(ev.op, category), isError: ev.isError });
|
|
26156
26429
|
show2(`${ev.op === "read" ? "read" : "edit"} ${FILE_LABEL[category]}`);
|
|
26157
26430
|
eventHashes.push(shortHash(`file|${ev.at ?? ""}|${ev.op}|${ev.path}`));
|
|
26158
26431
|
break;
|
|
@@ -26162,7 +26435,7 @@ function buildTrace(session) {
|
|
|
26162
26435
|
if (ev.skill) skills.add(ev.skill);
|
|
26163
26436
|
const action = TOOL_ACTIONS[ev.tool];
|
|
26164
26437
|
if (action) {
|
|
26165
|
-
|
|
26438
|
+
steps2.push({ action, isError: ev.isError });
|
|
26166
26439
|
show2(action === "search-code" ? "search code" : "look up docs");
|
|
26167
26440
|
}
|
|
26168
26441
|
break;
|
|
@@ -26174,14 +26447,14 @@ function buildTrace(session) {
|
|
|
26174
26447
|
break;
|
|
26175
26448
|
}
|
|
26176
26449
|
}
|
|
26177
|
-
for (const fp of
|
|
26450
|
+
for (const fp of commands2) {
|
|
26178
26451
|
if (fp.action === "inspect-ci") fileCategories.add("ci-config");
|
|
26179
26452
|
if (fp.action === "inspect-dependencies" && /<file>/.test(fp.normalized)) fileCategories.add("dependency-manifest");
|
|
26180
26453
|
}
|
|
26181
26454
|
const lastAssistant = [...session.events].reverse().find((e2) => e2.kind !== "error");
|
|
26182
26455
|
const summarized = lastAssistant?.kind === "assistant";
|
|
26183
26456
|
const actionSequence = [];
|
|
26184
|
-
for (const s of
|
|
26457
|
+
for (const s of steps2) {
|
|
26185
26458
|
if (actionSequence[actionSequence.length - 1] !== s.action) actionSequence.push(s.action);
|
|
26186
26459
|
}
|
|
26187
26460
|
if (summarized) actionSequence.push("summarize");
|
|
@@ -26200,11 +26473,11 @@ function buildTrace(session) {
|
|
|
26200
26473
|
projectHash: session.project?.pathHash,
|
|
26201
26474
|
intents,
|
|
26202
26475
|
tools: [...tools].sort(),
|
|
26203
|
-
commands,
|
|
26476
|
+
commands: commands2,
|
|
26204
26477
|
fileCategories: [...fileCategories].sort(),
|
|
26205
26478
|
actionSequence: actionSequence.slice(0, MAX_SEQUENCE),
|
|
26206
26479
|
displaySteps,
|
|
26207
|
-
outcome: outcomeOf(
|
|
26480
|
+
outcome: outcomeOf(steps2, summarized),
|
|
26208
26481
|
excerpt: excerpt(session.requests[0]?.text ?? "", 180),
|
|
26209
26482
|
fingerprint,
|
|
26210
26483
|
eventHashes,
|
|
@@ -26237,14 +26510,14 @@ function summarizeAgents(session) {
|
|
|
26237
26510
|
toolCalls: session.events.filter((e2) => (e2.kind === "shell" || e2.kind === "file" || e2.kind === "tool") && e2.byAgent).length
|
|
26238
26511
|
};
|
|
26239
26512
|
}
|
|
26240
|
-
function outcomeOf(
|
|
26513
|
+
function outcomeOf(steps2, summarized) {
|
|
26241
26514
|
let lastModify = -1;
|
|
26242
|
-
|
|
26515
|
+
steps2.forEach((s, i) => {
|
|
26243
26516
|
if (MODIFY_ACTIONS.has(s.action)) lastModify = i;
|
|
26244
26517
|
});
|
|
26245
|
-
const verified =
|
|
26246
|
-
const failedAt =
|
|
26247
|
-
const recoveredFromFailure = failedAt >= 0 &&
|
|
26518
|
+
const verified = steps2.some((s, i) => i > lastModify && VERIFY_ACTIONS.has(s.action) && !s.isError);
|
|
26519
|
+
const failedAt = steps2.findIndex((s) => s.isError);
|
|
26520
|
+
const recoveredFromFailure = failedAt >= 0 && steps2.slice(failedAt + 1).some((s) => VERIFY_ACTIONS.has(s.action) && !s.isError);
|
|
26248
26521
|
return { verified, recoveredFromFailure, modified: lastModify >= 0, summarized };
|
|
26249
26522
|
}
|
|
26250
26523
|
function isGenericTrace(trace) {
|
|
@@ -26362,6 +26635,30 @@ function fillerWeights(traces) {
|
|
|
26362
26635
|
var CLUSTER_THRESHOLD = 0.45;
|
|
26363
26636
|
var MIN_INTENT_COHESION = 0.2;
|
|
26364
26637
|
var MIN_INTENT_LINK = 0.35;
|
|
26638
|
+
var PairMatrix = class _PairMatrix {
|
|
26639
|
+
constructor(size2) {
|
|
26640
|
+
this.size = size2;
|
|
26641
|
+
this.values = new Float64Array(size2 * (size2 - 1) / 2);
|
|
26642
|
+
}
|
|
26643
|
+
size;
|
|
26644
|
+
values;
|
|
26645
|
+
index(i, j2) {
|
|
26646
|
+
const a = i < j2 ? i : j2;
|
|
26647
|
+
const b3 = i < j2 ? j2 : i;
|
|
26648
|
+
return a * (2 * this.size - a - 1) / 2 + b3 - a - 1;
|
|
26649
|
+
}
|
|
26650
|
+
get(i, j2) {
|
|
26651
|
+
return i === j2 ? 1 : this.values[this.index(i, j2)];
|
|
26652
|
+
}
|
|
26653
|
+
set(i, j2, value) {
|
|
26654
|
+
this.values[this.index(i, j2)] = value;
|
|
26655
|
+
}
|
|
26656
|
+
copy() {
|
|
26657
|
+
const m2 = new _PairMatrix(this.size);
|
|
26658
|
+
m2.values.set(this.values);
|
|
26659
|
+
return m2;
|
|
26660
|
+
}
|
|
26661
|
+
};
|
|
26365
26662
|
var EMBEDDING_FLOOR = 0.05;
|
|
26366
26663
|
function rescaleEmbedding(cos, floor = EMBEDDING_FLOOR) {
|
|
26367
26664
|
return Math.min(1, Math.max(0, (cos - floor) / (1 - floor)));
|
|
@@ -26382,21 +26679,15 @@ function intentSimilarities(traces, vectors) {
|
|
|
26382
26679
|
}
|
|
26383
26680
|
function similarityMatrices(traces, vectors) {
|
|
26384
26681
|
const intentOf = intentSimilarities(traces, vectors);
|
|
26385
|
-
const
|
|
26682
|
+
const features = traces.map(traceFeatures);
|
|
26386
26683
|
const n = traces.length;
|
|
26387
|
-
const
|
|
26388
|
-
const m2 = { total: make(), intent: make(), actions: make() };
|
|
26684
|
+
const m2 = { total: new PairMatrix(n), intent: new PairMatrix(n), actions: new PairMatrix(n) };
|
|
26389
26685
|
for (let i = 0; i < n; i++) {
|
|
26390
26686
|
for (let j2 = i + 1; j2 < n; j2++) {
|
|
26391
|
-
const s = similarity(traces[i], traces[j2], intentOf(i, j2),
|
|
26392
|
-
|
|
26393
|
-
|
|
26394
|
-
|
|
26395
|
-
["actions", s.actions]
|
|
26396
|
-
]) {
|
|
26397
|
-
m2[name][i][j2] = v2;
|
|
26398
|
-
m2[name][j2][i] = v2;
|
|
26399
|
-
}
|
|
26687
|
+
const s = similarity(traces[i], traces[j2], intentOf(i, j2), features[i], features[j2]);
|
|
26688
|
+
m2.total.set(i, j2, s.total);
|
|
26689
|
+
m2.intent.set(i, j2, s.intent);
|
|
26690
|
+
m2.actions.set(i, j2, s.actions);
|
|
26400
26691
|
}
|
|
26401
26692
|
}
|
|
26402
26693
|
return m2;
|
|
@@ -26406,7 +26697,7 @@ function meanPairwise(matrix, members2) {
|
|
|
26406
26697
|
let pairs = 0;
|
|
26407
26698
|
for (let x2 = 0; x2 < members2.length; x2++)
|
|
26408
26699
|
for (let y3 = x2 + 1; y3 < members2.length; y3++) {
|
|
26409
|
-
total += matrix
|
|
26700
|
+
total += matrix.get(members2[x2], members2[y3]);
|
|
26410
26701
|
pairs++;
|
|
26411
26702
|
}
|
|
26412
26703
|
return pairs ? total / pairs : 1;
|
|
@@ -26415,37 +26706,56 @@ function clusterTraces(traces, threshold = CLUSTER_THRESHOLD, vectors, minIntent
|
|
|
26415
26706
|
const sim = similarityMatrices(traces, vectors);
|
|
26416
26707
|
const n = traces.length;
|
|
26417
26708
|
const members2 = traces.map((_3, i) => [i]);
|
|
26418
|
-
const link = sim.total.
|
|
26419
|
-
const intentLink = sim.intent.
|
|
26709
|
+
const link = sim.total.copy();
|
|
26710
|
+
const intentLink = sim.intent.copy();
|
|
26711
|
+
const bestJ = new Int32Array(n).fill(-1);
|
|
26712
|
+
const bestLink = new Float64Array(n).fill(-1);
|
|
26713
|
+
const findBest = (i) => {
|
|
26714
|
+
bestJ[i] = -1;
|
|
26715
|
+
bestLink[i] = -1;
|
|
26716
|
+
for (let j2 = i + 1; j2 < n; j2++) {
|
|
26717
|
+
if (!members2[j2] || intentLink.get(i, j2) < minIntent) continue;
|
|
26718
|
+
const v2 = link.get(i, j2);
|
|
26719
|
+
if (v2 > bestLink[i]) {
|
|
26720
|
+
bestLink[i] = v2;
|
|
26721
|
+
bestJ[i] = j2;
|
|
26722
|
+
}
|
|
26723
|
+
}
|
|
26724
|
+
};
|
|
26725
|
+
for (let i = 0; i < n; i++) findBest(i);
|
|
26420
26726
|
for (; ; ) {
|
|
26421
26727
|
let best = -1;
|
|
26422
26728
|
let bi = -1;
|
|
26423
|
-
let bj = -1;
|
|
26424
26729
|
for (let i = 0; i < n; i++) {
|
|
26425
|
-
if (
|
|
26426
|
-
|
|
26427
|
-
|
|
26428
|
-
if (link[i][j2] > best) {
|
|
26429
|
-
best = link[i][j2];
|
|
26430
|
-
bi = i;
|
|
26431
|
-
bj = j2;
|
|
26432
|
-
}
|
|
26730
|
+
if (members2[i] && bestJ[i] >= 0 && bestLink[i] > best) {
|
|
26731
|
+
best = bestLink[i];
|
|
26732
|
+
bi = i;
|
|
26433
26733
|
}
|
|
26434
26734
|
}
|
|
26435
26735
|
if (bi < 0 || best < threshold) break;
|
|
26736
|
+
const bj = bestJ[bi];
|
|
26436
26737
|
const a = members2[bi];
|
|
26437
26738
|
const b3 = members2[bj];
|
|
26438
26739
|
for (let k3 = 0; k3 < n; k3++) {
|
|
26439
26740
|
if (!members2[k3] || k3 === bi || k3 === bj) continue;
|
|
26440
|
-
|
|
26441
|
-
|
|
26442
|
-
link[k3][bi] = v2;
|
|
26443
|
-
const w2 = (a.length * intentLink[bi][k3] + b3.length * intentLink[bj][k3]) / (a.length + b3.length);
|
|
26444
|
-
intentLink[bi][k3] = w2;
|
|
26445
|
-
intentLink[k3][bi] = w2;
|
|
26741
|
+
link.set(bi, k3, (a.length * link.get(bi, k3) + b3.length * link.get(bj, k3)) / (a.length + b3.length));
|
|
26742
|
+
intentLink.set(bi, k3, (a.length * intentLink.get(bi, k3) + b3.length * intentLink.get(bj, k3)) / (a.length + b3.length));
|
|
26446
26743
|
}
|
|
26447
26744
|
members2[bi] = [...a, ...b3].sort((x2, y3) => x2 - y3);
|
|
26448
26745
|
members2[bj] = null;
|
|
26746
|
+
bestJ[bj] = -1;
|
|
26747
|
+
findBest(bi);
|
|
26748
|
+
for (let k3 = 0; k3 < bj; k3++) {
|
|
26749
|
+
if (!members2[k3] || k3 === bi) continue;
|
|
26750
|
+
if (bestJ[k3] === bi || bestJ[k3] === bj) findBest(k3);
|
|
26751
|
+
else if (k3 < bi && intentLink.get(k3, bi) >= minIntent) {
|
|
26752
|
+
const v2 = link.get(k3, bi);
|
|
26753
|
+
if (v2 > bestLink[k3] || v2 === bestLink[k3] && bi < bestJ[k3]) {
|
|
26754
|
+
bestLink[k3] = v2;
|
|
26755
|
+
bestJ[k3] = bi;
|
|
26756
|
+
}
|
|
26757
|
+
}
|
|
26758
|
+
}
|
|
26449
26759
|
}
|
|
26450
26760
|
return members2.filter((m2) => m2 !== null).map((m2) => ({
|
|
26451
26761
|
members: m2,
|
|
@@ -26698,15 +27008,15 @@ function stepOrder(inst) {
|
|
|
26698
27008
|
return at;
|
|
26699
27009
|
}
|
|
26700
27010
|
var LAST_OCCURRENCE = /* @__PURE__ */ new Set(["run-tests", "run-build", "run-lint", "inspect-diff"]);
|
|
26701
|
-
function completionCriteria(
|
|
27011
|
+
function completionCriteria(steps2) {
|
|
26702
27012
|
const out2 = [];
|
|
26703
|
-
if (
|
|
26704
|
-
if (
|
|
26705
|
-
if (
|
|
26706
|
-
if (
|
|
26707
|
-
if (
|
|
26708
|
-
if (
|
|
26709
|
-
if (
|
|
27013
|
+
if (steps2.has("inspect-ci")) out2.push("The CI-equivalent command succeeds locally where it can be reproduced.");
|
|
27014
|
+
if (steps2.has("run-tests")) out2.push("Relevant tests pass.");
|
|
27015
|
+
if (steps2.has("run-build")) out2.push("Build or typecheck succeeds.");
|
|
27016
|
+
if (steps2.has("run-lint")) out2.push("Linter passes.");
|
|
27017
|
+
if (steps2.has("inspect-diff") || steps2.has("inspect-git")) out2.push("Repository state and the final diff have been reviewed; the diff contains only intended changes.");
|
|
27018
|
+
if (steps2.has("submit-review")) out2.push("The review is posted with concrete findings, or explicitly states that none were found.");
|
|
27019
|
+
if (steps2.has("summarize")) out2.push("A summary states the root cause (or findings), what changed, and how it was verified.");
|
|
26710
27020
|
return out2;
|
|
26711
27021
|
}
|
|
26712
27022
|
function frequentTerms(instances, limit = 6) {
|
|
@@ -26770,15 +27080,15 @@ function analyze(traces, opts = {}) {
|
|
|
26770
27080
|
if (cluster.members.length < MIN_INSTANCES) continue;
|
|
26771
27081
|
if (cluster.intentCohesion < MIN_INTENT_COHESION || cluster.actionCohesion < MIN_ACTION_COHESION) continue;
|
|
26772
27082
|
const group = cluster.members.map((i) => candidates[i]);
|
|
26773
|
-
const
|
|
26774
|
-
const stepKinds = new Set(
|
|
27083
|
+
const steps2 = consensusSteps(group);
|
|
27084
|
+
const stepKinds = new Set(steps2.map((s) => s.kind));
|
|
26775
27085
|
if (stepKinds.size - (stepKinds.has("summarize") ? 1 : 0) < 3) continue;
|
|
26776
|
-
const
|
|
27086
|
+
const terms2 = distinctiveTerms(group, context);
|
|
26777
27087
|
const frequent = frequentTerms(group);
|
|
26778
27088
|
const fileCats = new Set(group.flatMap((g2) => g2.primary.fileCategories));
|
|
26779
27089
|
const family = FAMILIES.filter((f) => f.requires(stepKinds, fileCats)).map((f) => ({ f, score: f.terms.filter((t) => frequent.includes(t)).length })).filter((x2) => x2.score > 0).sort((a, b3) => b3.score - a.score)[0]?.f;
|
|
26780
|
-
const fallbackTerms =
|
|
26781
|
-
const baseSlug = family?.slug ?? toSlug(fallbackTerms.join(" ") ||
|
|
27090
|
+
const fallbackTerms = terms2.slice(0, 3);
|
|
27091
|
+
const baseSlug = family?.slug ?? toSlug(fallbackTerms.join(" ") || steps2.map((s) => s.kind).slice(0, 2).join(" "));
|
|
26782
27092
|
const inside = /* @__PURE__ */ new Map();
|
|
26783
27093
|
for (const g2 of group) for (const s of skillsOf(g2)) inside.set(s, (inside.get(s) ?? 0) + 1);
|
|
26784
27094
|
const rest = Math.max(1, instances.length - group.length);
|
|
@@ -26808,13 +27118,13 @@ function analyze(traces, opts = {}) {
|
|
|
26808
27118
|
const repoNames = [...new Set(group.map((g2) => g2.primary.projectName).filter((x2) => !!x2))].sort();
|
|
26809
27119
|
const sources = {};
|
|
26810
27120
|
for (const id of SOURCE_IDS) {
|
|
26811
|
-
const
|
|
26812
|
-
if (
|
|
27121
|
+
const count3 = group.filter((g2) => g2.primary.source === id).length;
|
|
27122
|
+
if (count3) sources[id] = count3;
|
|
26813
27123
|
}
|
|
26814
27124
|
const dates = group.map((g2) => g2.primary.startedAt).filter((d3) => !!d3).sort();
|
|
26815
27125
|
const verifiedRate = group.filter((g2) => g2.primary.outcome.verified).length / group.length;
|
|
26816
27126
|
const durations = group.map((g2) => g2.primary.startedAt && g2.primary.endedAt ? (Date.parse(g2.primary.endedAt) - Date.parse(g2.primary.startedAt)) / 6e4 : NaN).filter((m2) => Number.isFinite(m2) && m2 > 0);
|
|
26817
|
-
const consensus =
|
|
27127
|
+
const consensus = steps2.reduce((acc, s) => acc + s.support, 0) / steps2.length;
|
|
26818
27128
|
const confidence = 0.3 * Math.min(1, cluster.cohesion / 0.75) + 0.2 * Math.min(1, group.length / 6) + 0.15 * Math.min(1, repos.length / 3) + 0.2 * consensus + 0.15 * verifiedRate;
|
|
26819
27129
|
const notes = [];
|
|
26820
27130
|
if (repos.length === 1) notes.push("All evidence comes from a single repository; the skill may be repository-specific.");
|
|
@@ -26825,8 +27135,8 @@ function analyze(traces, opts = {}) {
|
|
|
26825
27135
|
suggestions.push({
|
|
26826
27136
|
slug,
|
|
26827
27137
|
title: family?.title ?? `Repeated workflow: ${fallbackTerms.join(", ") || slug}`,
|
|
26828
|
-
description: family?.description ?? `Repeated workflow involving ${
|
|
26829
|
-
whenToUse: family?.whenToUse ?? `Use for requests similar to: ${
|
|
27138
|
+
description: family?.description ?? `Repeated workflow involving ${steps2.map((s) => s.label).slice(0, 3).join(", ")}.`,
|
|
27139
|
+
whenToUse: family?.whenToUse ?? `Use for requests similar to: ${terms2.slice(0, 5).join(", ")}.`,
|
|
26830
27140
|
confidence: Math.round(confidence * 100) / 100,
|
|
26831
27141
|
cohesion: Math.round(cluster.cohesion * 100) / 100,
|
|
26832
27142
|
instances: group.length,
|
|
@@ -26835,9 +27145,9 @@ function analyze(traces, opts = {}) {
|
|
|
26835
27145
|
sources,
|
|
26836
27146
|
firstSeen: dates[0],
|
|
26837
27147
|
lastSeen: dates[dates.length - 1],
|
|
26838
|
-
steps,
|
|
27148
|
+
steps: steps2,
|
|
26839
27149
|
completion: completionCriteria(stepKinds),
|
|
26840
|
-
topTerms:
|
|
27150
|
+
topTerms: terms2,
|
|
26841
27151
|
evidence: group.map((g2) => evidenceFor(g2, slug)).sort((a, b3) => (a.date ?? "").localeCompare(b3.date ?? "")),
|
|
26842
27152
|
notes,
|
|
26843
27153
|
verifiedRate: Math.round(verifiedRate * 100) / 100,
|
|
@@ -26974,8 +27284,8 @@ var requestDocument = (request) => contextDocument({ excerpt: "", fileCategories
|
|
|
26974
27284
|
var DEFAULT_ROUTER_SETTINGS = { autopilot: false, explore: 0, protect: [] };
|
|
26975
27285
|
function chooseRoute(guess, table2, opts) {
|
|
26976
27286
|
const fallback = opts.sources[0] ?? "claude-code";
|
|
26977
|
-
const
|
|
26978
|
-
const arms = (guess.kind ? table2.find((k3) => k3.kind.key === guess.kind.key)?.arms ?? [] : []).filter(
|
|
27287
|
+
const allowed2 = (a) => opts.sources.includes(a.source);
|
|
27288
|
+
const arms = (guess.kind ? table2.find((k3) => k3.kind.key === guess.kind.key)?.arms ?? [] : []).filter(allowed2);
|
|
26979
27289
|
const p3 = pickArm(arms);
|
|
26980
27290
|
const base = { guess, randomized: false, pick: p3.arm, arms };
|
|
26981
27291
|
const explore = Math.min(MAX_EXPLORE, Math.max(0, opts.settings.explore));
|
|
@@ -27156,13 +27466,13 @@ function reviewSkill(skill, content, traces) {
|
|
|
27156
27466
|
protected: fixed
|
|
27157
27467
|
};
|
|
27158
27468
|
if (n < MIN_REVIEW_SESSIONS) return { ...base, commands: [], missing: [], rarelyTaken: [], constraints: [] };
|
|
27159
|
-
const
|
|
27160
|
-
const
|
|
27161
|
-
const missing =
|
|
27469
|
+
const steps2 = consensusSteps(instances).filter((s) => !GENERIC.has(s.kind) && MENTIONS[s.kind]);
|
|
27470
|
+
const commands2 = steps2.filter((s) => mentions(text, s.kind)).map((s) => ({ ...s, examples: s.examples.filter((e2) => !text.includes(e2.toLowerCase()) && !(s.kind.startsWith("inspect-") && WRITES.test(e2))) })).filter((s) => s.examples.length);
|
|
27471
|
+
const missing = steps2.filter((s) => !mentions(text, s.kind) && !(fixed.length && s.kind === "summarize"));
|
|
27162
27472
|
const share = (kind) => runs.filter((t) => kind === "apply-fix" ? t.actionSequence.some((a) => a.startsWith("modify-")) : t.actionSequence.includes(kind)).length / n;
|
|
27163
27473
|
const rarelyTaken = Object.keys(MENTIONS).filter((k3) => !GENERIC.has(k3) && !k3.startsWith("modify-") && k3 !== "summarize" && mentions(text, k3) && share(k3) < STALE_BELOW).map((k3) => ({ kind: k3, label: STEP_TEXT[k3].label, share: share(k3) })).sort((a, b3) => a.share - b3.share).slice(0, MAX_RARELY);
|
|
27164
27474
|
const constraints = recurringCorrections(runs.map((t) => t.corrections ?? [])).filter(isSafeConstraint).filter((c2) => c2.text.toLowerCase().replace(/[^a-z\s-]/g, "").split(/\s+/).some((w2) => w2.length > 2 && !VAGUE.has(w2) && !/^(don't|dont|never|always|avoid|use|prefer|run|keep)$/.test(w2))).filter((c2) => !(fixed.length && OUTPUT_WORDS.test(c2.text))).filter((c2) => !c2.text.toLowerCase().split(/\s+/).every((w2) => w2.length < 3 || text.includes(w2))).slice(0, MAX_CONSTRAINTS2);
|
|
27165
|
-
return { ...base, commands, model: modelAdvice(runs), missing, rarelyTaken, constraints };
|
|
27475
|
+
return { ...base, commands: commands2, model: modelAdvice(runs), missing, rarelyTaken, constraints };
|
|
27166
27476
|
}
|
|
27167
27477
|
function outputShape(text) {
|
|
27168
27478
|
const trimmed = text.trim();
|
|
@@ -27178,21 +27488,21 @@ function outputShape(text) {
|
|
|
27178
27488
|
let fence = false;
|
|
27179
27489
|
let prev = "";
|
|
27180
27490
|
for (const raw of trimmed.split("\n")) {
|
|
27181
|
-
const
|
|
27182
|
-
if (/^\s*```/.test(
|
|
27183
|
-
shape.push(fence ? "code:end" : `code:${
|
|
27491
|
+
const line2 = raw.trimEnd();
|
|
27492
|
+
if (/^\s*```/.test(line2)) {
|
|
27493
|
+
shape.push(fence ? "code:end" : `code:${line2.trim().slice(3).trim() || "text"}`);
|
|
27184
27494
|
fence = !fence;
|
|
27185
27495
|
prev = "";
|
|
27186
27496
|
continue;
|
|
27187
27497
|
}
|
|
27188
27498
|
if (fence) continue;
|
|
27189
27499
|
let kind = "";
|
|
27190
|
-
const h2 = /^(#{1,6})\s+(.+)$/.exec(
|
|
27500
|
+
const h2 = /^(#{1,6})\s+(.+)$/.exec(line2);
|
|
27191
27501
|
if (h2) kind = `h${h2[1].length}:${h2[2].split(":")[0].replace(/[\d.,/-]+/g, "#").trim().toLowerCase()}`;
|
|
27192
|
-
else if (/^\s*\|.*\|\s*$/.test(
|
|
27193
|
-
else if (/^\s*[-*+]\s+/.test(
|
|
27194
|
-
else if (/^\s*\d+[.)]\s+/.test(
|
|
27195
|
-
else if (/^\s*\*\*[^*]+\*\*:?/.test(
|
|
27502
|
+
else if (/^\s*\|.*\|\s*$/.test(line2)) kind = /^\s*\|[\s:|-]+\|\s*$/.test(line2) ? "" : prev.startsWith("table") ? "table:row" : `table:${line2.split("|").filter((c2) => c2.trim()).length}`;
|
|
27503
|
+
else if (/^\s*[-*+]\s+/.test(line2)) kind = "list";
|
|
27504
|
+
else if (/^\s*\d+[.)]\s+/.test(line2)) kind = "numbered";
|
|
27505
|
+
else if (/^\s*\*\*[^*]+\*\*:?/.test(line2)) kind = `label:${/\*\*([^*]+)\*\*/.exec(line2)[1].toLowerCase()}`;
|
|
27196
27506
|
if (!kind || kind === prev && (kind === "list" || kind === "numbered" || kind === "table:row")) {
|
|
27197
27507
|
if (kind) prev = kind;
|
|
27198
27508
|
continue;
|
|
@@ -27203,6 +27513,136 @@ function outputShape(text) {
|
|
|
27203
27513
|
return shape;
|
|
27204
27514
|
}
|
|
27205
27515
|
|
|
27516
|
+
// ../../packages/analysis/src/handbook.ts
|
|
27517
|
+
var MAX_SOURCES = 5;
|
|
27518
|
+
var MIN_COMMAND_SESSIONS = 2;
|
|
27519
|
+
var WHEN_SHARE = 2 / 3;
|
|
27520
|
+
var WHEN_LIFT = 2;
|
|
27521
|
+
var SITUATIONS = [
|
|
27522
|
+
{ category: "dependency-manifest", when: "when changing dependencies", words: ["dependency", "package", "install", "lockfile", "upgrade"] },
|
|
27523
|
+
{ category: "migration", when: "when changing the database schema", words: ["migration", "schema", "database", "db", "sql"] },
|
|
27524
|
+
{ category: "ci-config", when: "when working on CI", words: ["ci", "pipeline", "workflow", "github", "action"] },
|
|
27525
|
+
{ category: "test", when: "when writing or changing tests", words: ["test", "spec"] },
|
|
27526
|
+
{ category: "config", when: "when changing configuration", words: ["config", "configuration", "setting"] },
|
|
27527
|
+
{ category: "docs", when: "when editing docs", words: ["doc", "readme", "documentation"] }
|
|
27528
|
+
];
|
|
27529
|
+
var VERIFY = [
|
|
27530
|
+
{ action: "run-tests", label: "Run tests with", words: ["test", "spec", "unit", "e2e"] },
|
|
27531
|
+
{ action: "run-build", label: "Build or typecheck with", words: ["build", "compile", "typecheck", "type", "tsc"] },
|
|
27532
|
+
{ action: "run-lint", label: "Lint with", words: ["lint", "format", "style", "prettier", "eslint"] }
|
|
27533
|
+
];
|
|
27534
|
+
var projectOf = (i) => i.primary.projectHash;
|
|
27535
|
+
var time4 = (t) => t.startedAt ? Date.parse(t.startedAt) || 0 : 0;
|
|
27536
|
+
function sourcesOf(group) {
|
|
27537
|
+
const newest = [...group].sort((a, b3) => time4(b3.primary) - time4(a.primary));
|
|
27538
|
+
return {
|
|
27539
|
+
last: newest[0]?.primary.startedAt,
|
|
27540
|
+
sources: newest.slice(0, MAX_SOURCES).map((i) => ({ date: i.primary.startedAt, tool: i.primary.source, request: i.primary.excerpt }))
|
|
27541
|
+
};
|
|
27542
|
+
}
|
|
27543
|
+
function scopeOf(group) {
|
|
27544
|
+
const hashes = new Set(group.map(projectOf));
|
|
27545
|
+
if (hashes.size !== 1) return void 0;
|
|
27546
|
+
const hash2 = [...hashes][0];
|
|
27547
|
+
return hash2 ? { name: group[0].primary.projectName, hash: hash2 } : void 0;
|
|
27548
|
+
}
|
|
27549
|
+
function situation(group, others) {
|
|
27550
|
+
const count3 = (xs, cat) => xs.filter((i) => i.primary.fileCategories.includes(cat)).length;
|
|
27551
|
+
let best;
|
|
27552
|
+
for (const s of SITUATIONS) {
|
|
27553
|
+
const inside = count3(group, s.category) / group.length;
|
|
27554
|
+
if (inside < WHEN_SHARE) continue;
|
|
27555
|
+
const lift = inside / ((count3(others, s.category) + 0.5) / (others.length + 1));
|
|
27556
|
+
if (lift >= WHEN_LIFT && (!best || lift > best.lift)) best = { when: s.when, lift };
|
|
27557
|
+
}
|
|
27558
|
+
return best?.when;
|
|
27559
|
+
}
|
|
27560
|
+
function rules(instances, forgotten) {
|
|
27561
|
+
const out2 = [];
|
|
27562
|
+
for (const r2 of recurringCorrectionsBySession(instances.map((i) => i.primary.corrections ?? []))) {
|
|
27563
|
+
if (forgotten.has(r2.text) || !isSafeConstraint(r2)) continue;
|
|
27564
|
+
const group = r2.instances.map((k3) => instances[k3]);
|
|
27565
|
+
const project = scopeOf(group);
|
|
27566
|
+
const members2 = new Set(group);
|
|
27567
|
+
const others = instances.filter((i) => !members2.has(i) && (!project || projectOf(i) === project.hash));
|
|
27568
|
+
const when = situation(group, others);
|
|
27569
|
+
out2.push({ id: practiceId("rule", project?.hash, r2.text), kind: "rule", project, text: r2.text, when, sessions: r2.sessions, ...sourcesOf(group) });
|
|
27570
|
+
}
|
|
27571
|
+
return out2;
|
|
27572
|
+
}
|
|
27573
|
+
function commands(instances) {
|
|
27574
|
+
const byProject2 = /* @__PURE__ */ new Map();
|
|
27575
|
+
for (const i of instances) {
|
|
27576
|
+
const h2 = projectOf(i);
|
|
27577
|
+
if (h2) byProject2.set(h2, [...byProject2.get(h2) ?? [], i]);
|
|
27578
|
+
}
|
|
27579
|
+
const out2 = [];
|
|
27580
|
+
for (const [hash2, group] of byProject2) {
|
|
27581
|
+
for (const v2 of VERIFY) {
|
|
27582
|
+
const worked = /* @__PURE__ */ new Map();
|
|
27583
|
+
const failed = /* @__PURE__ */ new Map();
|
|
27584
|
+
for (const i of group) {
|
|
27585
|
+
const runs = i.primary.commands.filter((c2) => c2.action === v2.action);
|
|
27586
|
+
for (const cmd2 of new Set(runs.map((c2) => c2.normalized).filter(isSafeExample))) {
|
|
27587
|
+
const same = runs.filter((c2) => c2.normalized === cmd2);
|
|
27588
|
+
if (same.some((c2) => !c2.failed)) worked.set(cmd2, [...worked.get(cmd2) ?? [], i]);
|
|
27589
|
+
else failed.set(cmd2, (failed.get(cmd2) ?? 0) + 1);
|
|
27590
|
+
}
|
|
27591
|
+
}
|
|
27592
|
+
const top = [...worked].sort((a, b3) => b3[1].length - a[1].length || a[0].localeCompare(b3[0]))[0];
|
|
27593
|
+
if (!top || top[1].length < MIN_COMMAND_SESSIONS) continue;
|
|
27594
|
+
const [cmd, sessions2] = top;
|
|
27595
|
+
const notThis = [...failed].filter(([other, n]) => other !== cmd && n >= MIN_COMMAND_SESSIONS && !worked.has(other)).sort((a, b3) => b3[1] - a[1])[0];
|
|
27596
|
+
const text = `${v2.label} \`${cmd}\`.${notThis ? ` Not \`${notThis[0]}\`: it failed in ${notThis[1]} sessions.` : ""}`;
|
|
27597
|
+
out2.push({
|
|
27598
|
+
id: practiceId("command", hash2, `${v2.action}:${cmd}`),
|
|
27599
|
+
kind: "command",
|
|
27600
|
+
project: { name: sessions2[0].primary.projectName, hash: hash2 },
|
|
27601
|
+
text,
|
|
27602
|
+
sessions: sessions2.length,
|
|
27603
|
+
...sourcesOf(sessions2)
|
|
27604
|
+
});
|
|
27605
|
+
}
|
|
27606
|
+
}
|
|
27607
|
+
return out2;
|
|
27608
|
+
}
|
|
27609
|
+
function practiceId(kind, project, key3) {
|
|
27610
|
+
return shortHash(`${kind}|${project ?? "*"}|${key3}`, 8);
|
|
27611
|
+
}
|
|
27612
|
+
function buildHandbook(traces, opts = {}) {
|
|
27613
|
+
const { instances } = deduplicate(traces);
|
|
27614
|
+
return [...commands(instances), ...rules(instances, opts.forgotten ?? /* @__PURE__ */ new Set())].sort(
|
|
27615
|
+
(a, b3) => b3.sessions - a.sessions || a.kind.localeCompare(b3.kind) || a.text.localeCompare(b3.text)
|
|
27616
|
+
);
|
|
27617
|
+
}
|
|
27618
|
+
function practicesFor(practices, projectHash) {
|
|
27619
|
+
return practices.filter((p3) => !p3.project || p3.project.hash === projectHash).sort((a, b3) => Number(!a.project) - Number(!b3.project));
|
|
27620
|
+
}
|
|
27621
|
+
var QUESTION_FILLER = new Set(
|
|
27622
|
+
"a an the to it is are be do does did how what when where which who why we i you our my your here there this that in on of for with and or should can could would will".split(" ")
|
|
27623
|
+
);
|
|
27624
|
+
function terms(text) {
|
|
27625
|
+
return new Set(
|
|
27626
|
+
text.toLowerCase().split(/[^a-z0-9.-]+/).map((w2) => w2.replace(/^[.-]+|[.-]+$/g, "")).filter((w2) => w2.length > 1 && !QUESTION_FILLER.has(w2)).map(stem)
|
|
27627
|
+
);
|
|
27628
|
+
}
|
|
27629
|
+
function practiceTerms(p3) {
|
|
27630
|
+
const extra = [];
|
|
27631
|
+
for (const s of SITUATIONS) if (p3.when === s.when) extra.push(...s.words);
|
|
27632
|
+
for (const v2 of VERIFY) if (p3.text.startsWith(v2.label)) extra.push(...v2.words, "command", "run");
|
|
27633
|
+
return terms(`${p3.text} ${p3.when ?? ""} ${extra.join(" ")}`);
|
|
27634
|
+
}
|
|
27635
|
+
function askHandbook(practices, question, projectHash, limit = 3) {
|
|
27636
|
+
const q2 = terms(question);
|
|
27637
|
+
if (!q2.size) return [];
|
|
27638
|
+
return practices.map((p3) => {
|
|
27639
|
+
const t = practiceTerms(p3);
|
|
27640
|
+
const hits = [...q2].filter((w2) => t.has(w2)).length;
|
|
27641
|
+
const local = p3.project ? p3.project.hash === projectHash ? 1.5 : 0.5 : 1;
|
|
27642
|
+
return { practice: p3, score: hits / q2.size * local };
|
|
27643
|
+
}).filter((a) => a.score > 0).sort((a, b3) => b3.score - a.score || b3.practice.sessions - a.practice.sessions).slice(0, limit);
|
|
27644
|
+
}
|
|
27645
|
+
|
|
27206
27646
|
// src/commands/scan.ts
|
|
27207
27647
|
import { totalmem as totalmem2 } from "node:os";
|
|
27208
27648
|
|
|
@@ -27304,8 +27744,8 @@ function parseFrontmatter(content) {
|
|
|
27304
27744
|
const end = content.indexOf("\n---", 3);
|
|
27305
27745
|
if (end < 0) return void 0;
|
|
27306
27746
|
const out2 = {};
|
|
27307
|
-
for (const
|
|
27308
|
-
const m2 = /^([a-z][a-z0-9-]*):\s*(.*)$/i.exec(
|
|
27747
|
+
for (const line2 of content.slice(4, end).split("\n")) {
|
|
27748
|
+
const m2 = /^([a-z][a-z0-9-]*):\s*(.*)$/i.exec(line2);
|
|
27309
27749
|
if (!m2) continue;
|
|
27310
27750
|
let v2 = m2[2].trim();
|
|
27311
27751
|
if (v2.startsWith('"')) {
|
|
@@ -27331,15 +27771,15 @@ function checkSkill(content, expectedName) {
|
|
|
27331
27771
|
const description = fm?.description ?? "";
|
|
27332
27772
|
if (!description) errors.push("frontmatter `description` is missing");
|
|
27333
27773
|
if (description.length > 1024) errors.push("description is longer than 1024 characters");
|
|
27334
|
-
for (const
|
|
27335
|
-
${
|
|
27336
|
-
`)) errors.push(`missing section "${
|
|
27337
|
-
const
|
|
27338
|
-
if (
|
|
27774
|
+
for (const section2 of REQUIRED_SECTIONS) if (!content.includes(`
|
|
27775
|
+
${section2}
|
|
27776
|
+
`)) errors.push(`missing section "${section2}"`);
|
|
27777
|
+
const steps2 = (content.split("## Workflow")[1]?.split("\n## ")[0] ?? "").split("\n").filter((l2) => /^\d+\. /.test(l2)).length;
|
|
27778
|
+
if (steps2 < 3) errors.push(`workflow has ${steps2} steps; at least 3 expected`);
|
|
27339
27779
|
if (findLeaks(content).length) errors.push("contains sensitive-looking content (secret, email, or home path)");
|
|
27340
27780
|
if (/(^|[\s`'"(])(\/Users\/|\/home\/|[A-Z]:\\Users\\)/m.test(content)) errors.push("contains a local absolute path");
|
|
27341
27781
|
if (!/generator: reflex/.test(content)) warnings.push("no Reflex provenance metadata (hand-written or edited skill)");
|
|
27342
|
-
return { ok: errors.length === 0, errors, warnings, name, steps, lines };
|
|
27782
|
+
return { ok: errors.length === 0, errors, warnings, name, steps: steps2, lines };
|
|
27343
27783
|
}
|
|
27344
27784
|
|
|
27345
27785
|
// ../../packages/skills/src/diff.ts
|
|
@@ -27579,8 +28019,9 @@ function runClaudeInSandbox(sandbox, skillName2, timeoutMs = 6 * 60 * 1e3) {
|
|
|
27579
28019
|
"--allowedTools",
|
|
27580
28020
|
...ALLOWED_TOOLS
|
|
27581
28021
|
];
|
|
28022
|
+
const launch = agentLaunch("claude", args);
|
|
27582
28023
|
return new Promise((resolve5) => {
|
|
27583
|
-
const child = spawn(
|
|
28024
|
+
const child = spawn(launch.command, launch.args, { cwd: sandbox.dir, stdio: ["ignore", "pipe", "ignore"], windowsVerbatimArguments: launch.windowsVerbatimArguments });
|
|
27584
28025
|
let buffer = "";
|
|
27585
28026
|
let timedOut = false;
|
|
27586
28027
|
const run2 = { exitCode: null, skillUsed: false, commands: [], editedFiles: [], testsPass: false, timedOut: false };
|
|
@@ -27593,19 +28034,19 @@ function runClaudeInSandbox(sandbox, skillName2, timeoutMs = 6 * 60 * 1e3) {
|
|
|
27593
28034
|
const base = bases.find((b3) => p3.startsWith(b3));
|
|
27594
28035
|
return base ? p3.slice(base.length) : displayPath(p3);
|
|
27595
28036
|
};
|
|
27596
|
-
const handle = (
|
|
28037
|
+
const handle = (line2) => {
|
|
27597
28038
|
let msg;
|
|
27598
28039
|
try {
|
|
27599
|
-
msg = JSON.parse(
|
|
28040
|
+
msg = JSON.parse(line2);
|
|
27600
28041
|
} catch {
|
|
27601
28042
|
return;
|
|
27602
28043
|
}
|
|
27603
|
-
if (msg.type === "result" && typeof msg.result === "string") run2.finalMessage =
|
|
28044
|
+
if (msg.type === "result" && typeof msg.result === "string") run2.finalMessage = redactTruncated(msg.result, 2e3);
|
|
27604
28045
|
if (msg.type !== "assistant" || !Array.isArray(msg.message?.content)) return;
|
|
27605
28046
|
for (const block of msg.message.content) {
|
|
27606
28047
|
if (block.type !== "tool_use") continue;
|
|
27607
28048
|
if (block.name === "Skill" && String(block.input?.skill ?? "").replace(/^.*:/, "") === skillName2) run2.skillUsed = true;
|
|
27608
|
-
if (block.name === "Bash" && typeof block.input?.command === "string") run2.commands.push(
|
|
28049
|
+
if (block.name === "Bash" && typeof block.input?.command === "string") run2.commands.push(redactTruncated(block.input.command, 200));
|
|
27609
28050
|
if ((block.name === "Edit" || block.name === "Write") && typeof block.input?.file_path === "string")
|
|
27610
28051
|
run2.editedFiles.push(sandboxRelative(block.input.file_path));
|
|
27611
28052
|
}
|
|
@@ -27687,15 +28128,16 @@ function cleanMemoryText(text) {
|
|
|
27687
28128
|
if (!t || redactions > 0 || findLeaks(t).length) return void 0;
|
|
27688
28129
|
return t;
|
|
27689
28130
|
}
|
|
27690
|
-
function renderMemoryBlock(
|
|
28131
|
+
function renderMemoryBlock(rules2) {
|
|
27691
28132
|
const lines = [
|
|
27692
28133
|
MEMORY_START,
|
|
27693
28134
|
"## Remembered by Reflex",
|
|
27694
28135
|
"",
|
|
27695
28136
|
"Corrections the developer gave coding agents in more than one past session. Follow them unless the current task says otherwise.",
|
|
27696
28137
|
"Managed by `reflex memory`: edits inside this block are replaced on the next scan.",
|
|
28138
|
+
'To see how work is done in the current repository (commands that work, rules the developer gave), run `reflex handbook --json`, or `reflex handbook ask "<question>" --json`. Both are read-only.',
|
|
27697
28139
|
"",
|
|
27698
|
-
...
|
|
28140
|
+
...rules2.map((r2) => `- ${r2.text}${r2.sessions ? ` (${r2.sessions} sessions)` : ""}`),
|
|
27699
28141
|
MEMORY_END
|
|
27700
28142
|
];
|
|
27701
28143
|
return lines.join("\n");
|
|
@@ -27774,19 +28216,19 @@ function learnedSection(review, opts = {}) {
|
|
|
27774
28216
|
for (const c2 of constraints) lines.push(`- ${c2.text} (${c2.sessions} sessions)`);
|
|
27775
28217
|
}
|
|
27776
28218
|
lines.push(LEARNED_END);
|
|
27777
|
-
const
|
|
27778
|
-
if (findLeaks(
|
|
27779
|
-
return
|
|
28219
|
+
const section2 = redact(lines.join("\n"));
|
|
28220
|
+
if (findLeaks(section2).length) throw new Error("The proposed section still contains sensitive-looking content; refusing to propose it.");
|
|
28221
|
+
return section2;
|
|
27780
28222
|
}
|
|
27781
|
-
function applyLearned(content,
|
|
28223
|
+
function applyLearned(content, section2) {
|
|
27782
28224
|
const starts = content.split(LEARNED_START).length - 1;
|
|
27783
28225
|
const ends = content.split(LEARNED_END).length - 1;
|
|
27784
28226
|
if (starts > 1 || ends > 1 || starts !== ends || starts && content.indexOf(LEARNED_END) < content.indexOf(LEARNED_START))
|
|
27785
28227
|
throw new Error(`The skill's "Learned from your sessions" markers are incomplete or repeated. Fix or remove ${LEARNED_START} and ${LEARNED_END}, then run reflex improve again.`);
|
|
27786
28228
|
const start = content.indexOf(LEARNED_START);
|
|
27787
28229
|
const end = start >= 0 ? content.indexOf(LEARNED_END, start) : -1;
|
|
27788
|
-
if (start >= 0 && end >= 0) return content.slice(0, start) +
|
|
27789
|
-
return content.replace(/\n*$/, "\n\n") +
|
|
28230
|
+
if (start >= 0 && end >= 0) return content.slice(0, start) + section2 + content.slice(end + LEARNED_END.length);
|
|
28231
|
+
return content.replace(/\n*$/, "\n\n") + section2 + "\n";
|
|
27790
28232
|
}
|
|
27791
28233
|
function withoutLearned(content) {
|
|
27792
28234
|
const start = content.indexOf(LEARNED_START);
|
|
@@ -27809,6 +28251,7 @@ async function applyToOwnSkill(path, readHash, next, backupDir, name, now = /* @
|
|
|
27809
28251
|
if (sha256(current) !== readHash) throw new Error("The skill changed since Reflex read it; run `reflex improve` again.");
|
|
27810
28252
|
const stat4 = await lstat6(path);
|
|
27811
28253
|
if (!stat4.isFile()) throw new Error("Not a regular file.");
|
|
28254
|
+
if ((stat4.mode & 146) === 0) throw new Error("You can't write to this skill file, so Reflex won't change it.");
|
|
27812
28255
|
await access(path, constants3.W_OK).catch(() => {
|
|
27813
28256
|
throw new Error("You can't write to this skill file, so Reflex won't change it.");
|
|
27814
28257
|
});
|
|
@@ -27876,19 +28319,20 @@ function runClaudeBench(dir, task, model2, tools, timeoutMs) {
|
|
|
27876
28319
|
"--allowedTools",
|
|
27877
28320
|
...tools
|
|
27878
28321
|
];
|
|
28322
|
+
const launch = agentLaunch("claude", args);
|
|
27879
28323
|
const started = Date.now();
|
|
27880
28324
|
return new Promise((resolve5) => {
|
|
27881
|
-
const child = spawn2(
|
|
28325
|
+
const child = spawn2(launch.command, launch.args, { cwd: dir, stdio: ["ignore", "pipe", "ignore"], windowsVerbatimArguments: launch.windowsVerbatimArguments });
|
|
27882
28326
|
const run2 = { exitCode: null, timedOut: false, durationMs: 0 };
|
|
27883
28327
|
let buffer = "";
|
|
27884
28328
|
const timer = setTimeout(() => {
|
|
27885
28329
|
run2.timedOut = true;
|
|
27886
28330
|
child.kill("SIGTERM");
|
|
27887
28331
|
}, timeoutMs);
|
|
27888
|
-
const handle = (
|
|
28332
|
+
const handle = (line2) => {
|
|
27889
28333
|
let msg;
|
|
27890
28334
|
try {
|
|
27891
|
-
msg = JSON.parse(
|
|
28335
|
+
msg = JSON.parse(line2);
|
|
27892
28336
|
} catch {
|
|
27893
28337
|
return;
|
|
27894
28338
|
}
|
|
@@ -27940,7 +28384,10 @@ var paths = {
|
|
|
27940
28384
|
home: reflexHome,
|
|
27941
28385
|
db: () => join13(reflexHome(), "reflex.db"),
|
|
27942
28386
|
skills: () => join13(reflexHome(), "skills"),
|
|
27943
|
-
models: () => join13(reflexHome(), "models")
|
|
28387
|
+
models: () => join13(reflexHome(), "models"),
|
|
28388
|
+
/** Token counts Reflex's Cursor hook records (`reflex cursor-usage on`). */
|
|
28389
|
+
cursorUsage: () => join13(reflexHome(), "cursor-usage.jsonl"),
|
|
28390
|
+
hooks: () => join13(reflexHome(), "hooks")
|
|
27944
28391
|
};
|
|
27945
28392
|
|
|
27946
28393
|
// ../../packages/storage/src/db.ts
|
|
@@ -28067,6 +28514,7 @@ function parseJson(raw, shape, what) {
|
|
|
28067
28514
|
if (!result.success) throw new Error(`Reflex database has a malformed ${what}. Run \`reflex scan\` again.`);
|
|
28068
28515
|
return result.data;
|
|
28069
28516
|
}
|
|
28517
|
+
var BUSY_TIMEOUT_MS = 1e4;
|
|
28070
28518
|
var Store = class {
|
|
28071
28519
|
db;
|
|
28072
28520
|
constructor(file2 = paths.db()) {
|
|
@@ -28075,6 +28523,8 @@ var Store = class {
|
|
|
28075
28523
|
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
28076
28524
|
this.db = new DatabaseSync2(file2);
|
|
28077
28525
|
chmodSync(file2, 384);
|
|
28526
|
+
this.db.exec(`PRAGMA busy_timeout = ${BUSY_TIMEOUT_MS}`);
|
|
28527
|
+
this.db.exec("PRAGMA journal_mode = WAL");
|
|
28078
28528
|
const version2 = Number(this.db.prepare("PRAGMA user_version").get().user_version);
|
|
28079
28529
|
if (version2 < 4) this.db.exec("DROP TABLE IF EXISTS sessions");
|
|
28080
28530
|
this.db.exec(SCHEMA);
|
|
@@ -28089,7 +28539,7 @@ var Store = class {
|
|
|
28089
28539
|
}
|
|
28090
28540
|
/** Record a scan and make the given cached traces its working set (what suggest, stats and the TUI see). */
|
|
28091
28541
|
saveScan(scan2, traceRows) {
|
|
28092
|
-
this.db.exec("BEGIN");
|
|
28542
|
+
this.db.exec("BEGIN IMMEDIATE");
|
|
28093
28543
|
try {
|
|
28094
28544
|
const res = this.db.prepare(
|
|
28095
28545
|
"INSERT INTO scans (started_at, days, mode, sources_json, files, sessions, partial, unreadable, skipped_records) VALUES (?,?,?,?,?,?,?,?,?)"
|
|
@@ -28129,7 +28579,7 @@ var Store = class {
|
|
|
28129
28579
|
}
|
|
28130
28580
|
/** Replace what is cached for one file (its identity and its traces) atomically. */
|
|
28131
28581
|
saveFile(file2, traces) {
|
|
28132
|
-
this.db.exec("BEGIN");
|
|
28582
|
+
this.db.exec("BEGIN IMMEDIATE");
|
|
28133
28583
|
try {
|
|
28134
28584
|
this.db.prepare("DELETE FROM traces WHERE path = ?").run(file2.path);
|
|
28135
28585
|
this.db.prepare(
|
|
@@ -28160,7 +28610,7 @@ var Store = class {
|
|
|
28160
28610
|
}
|
|
28161
28611
|
/** Rewrite a kept trace in place (re-redaction after the rules or the user's identity changed). */
|
|
28162
28612
|
updateKeptTraces(path, traces, keys) {
|
|
28163
|
-
this.db.exec("BEGIN");
|
|
28613
|
+
this.db.exec("BEGIN IMMEDIATE");
|
|
28164
28614
|
try {
|
|
28165
28615
|
const update = this.db.prepare("UPDATE traces SET trace_json = ? WHERE row_id = ?");
|
|
28166
28616
|
for (const t of traces) update.run(JSON.stringify(t.trace), t.row);
|
|
@@ -28205,7 +28655,7 @@ var Store = class {
|
|
|
28205
28655
|
/** Store the current suggestions, keeping any earlier approve/reject decision for the same slug. */
|
|
28206
28656
|
saveSuggestions(scanId, suggestions) {
|
|
28207
28657
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
28208
|
-
this.db.exec("BEGIN");
|
|
28658
|
+
this.db.exec("BEGIN IMMEDIATE");
|
|
28209
28659
|
try {
|
|
28210
28660
|
this.db.prepare("UPDATE suggestions SET rank = NULL").run();
|
|
28211
28661
|
const upsert = this.db.prepare(
|
|
@@ -28299,11 +28749,11 @@ var Store = class {
|
|
|
28299
28749
|
}
|
|
28300
28750
|
return out2;
|
|
28301
28751
|
}
|
|
28302
|
-
saveEmbeddings(model2,
|
|
28752
|
+
saveEmbeddings(model2, entries2) {
|
|
28303
28753
|
const put = this.db.prepare("INSERT OR REPLACE INTO embeddings (key, model, vector) VALUES (?,?,COALESCE(?, zeroblob(0)))");
|
|
28304
|
-
this.db.exec("BEGIN");
|
|
28754
|
+
this.db.exec("BEGIN IMMEDIATE");
|
|
28305
28755
|
try {
|
|
28306
|
-
for (const [key3, v2] of
|
|
28756
|
+
for (const [key3, v2] of entries2) put.run(key3, model2, new Uint8Array(v2.buffer, v2.byteOffset, v2.byteLength));
|
|
28307
28757
|
this.db.exec("COMMIT");
|
|
28308
28758
|
} catch (err) {
|
|
28309
28759
|
this.db.exec("ROLLBACK");
|
|
@@ -28315,11 +28765,11 @@ var Store = class {
|
|
|
28315
28765
|
this.db.prepare("DELETE FROM embeddings WHERE key NOT IN (SELECT value FROM json_each(?))").run(JSON.stringify(keep));
|
|
28316
28766
|
}
|
|
28317
28767
|
/** Replace the mined memory with the latest result. User decisions (forgotten, added) are kept. */
|
|
28318
|
-
syncMinedMemory(
|
|
28768
|
+
syncMinedMemory(rules2) {
|
|
28319
28769
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
28320
|
-
this.db.exec("BEGIN");
|
|
28770
|
+
this.db.exec("BEGIN IMMEDIATE");
|
|
28321
28771
|
try {
|
|
28322
|
-
const keep = new Set(
|
|
28772
|
+
const keep = new Set(rules2.map((r2) => r2.text));
|
|
28323
28773
|
for (const row of this.db.prepare("SELECT text FROM memory_entries WHERE origin = 'mined' AND status = 'active'").all()) {
|
|
28324
28774
|
if (!keep.has(row.text)) this.db.prepare("DELETE FROM memory_entries WHERE text = ?").run(row.text);
|
|
28325
28775
|
}
|
|
@@ -28327,7 +28777,7 @@ var Store = class {
|
|
|
28327
28777
|
`INSERT INTO memory_entries (text, origin, status, sessions, updated_at) VALUES (?, 'mined', 'active', ?, ?)
|
|
28328
28778
|
ON CONFLICT(text) DO UPDATE SET sessions = excluded.sessions, updated_at = excluded.updated_at`
|
|
28329
28779
|
);
|
|
28330
|
-
for (const r2 of
|
|
28780
|
+
for (const r2 of rules2) upsert.run(r2.text, r2.sessions, now);
|
|
28331
28781
|
this.db.exec("COMMIT");
|
|
28332
28782
|
} catch (err) {
|
|
28333
28783
|
this.db.exec("ROLLBACK");
|
|
@@ -28684,8 +29134,8 @@ var COMFORTABLE = { memoryGB: 8, cores: 4 };
|
|
|
28684
29134
|
function machineIsSmall(totalBytes = totalmem(), cores = availableParallelism()) {
|
|
28685
29135
|
return totalBytes / 1e9 < COMFORTABLE.memoryGB - 0.5 || cores < COMFORTABLE.cores;
|
|
28686
29136
|
}
|
|
28687
|
-
function embeddingSeconds(model2, sessions2,
|
|
28688
|
-
const speedup = 1 + (
|
|
29137
|
+
function embeddingSeconds(model2, sessions2, threads2 = embeddingThreads()) {
|
|
29138
|
+
const speedup = 1 + (threads2 - 1) * 0.83;
|
|
28689
29139
|
return sessions2 * model2.secondsPerSession / speedup;
|
|
28690
29140
|
}
|
|
28691
29141
|
|
|
@@ -28705,8 +29155,8 @@ async function tokenizerFor(dir, model2) {
|
|
|
28705
29155
|
return (text) => tokenizer2.encode(text, model2.maxTokens);
|
|
28706
29156
|
}
|
|
28707
29157
|
const { Tokenizer } = await import("./tokenizers-CLBWC4RJ.js");
|
|
28708
|
-
const [
|
|
28709
|
-
const tokenizer = new Tokenizer(JSON.parse(
|
|
29158
|
+
const [json3, config2] = await Promise.all([readVerified(dir, "tokenizer.json", model2), readVerified(dir, "tokenizer_config.json", model2)]);
|
|
29159
|
+
const tokenizer = new Tokenizer(JSON.parse(json3.toString("utf8")), JSON.parse(config2.toString("utf8")));
|
|
28710
29160
|
return (text) => {
|
|
28711
29161
|
const ids = tokenizer.encode(text).ids;
|
|
28712
29162
|
return ids.length > model2.maxTokens ? [...ids.slice(0, model2.maxTokens - 1), ids[ids.length - 1]] : ids;
|
|
@@ -30430,13 +30880,13 @@ import { join as join17 } from "node:path";
|
|
|
30430
30880
|
async function skillFiles() {
|
|
30431
30881
|
const out2 = [];
|
|
30432
30882
|
for (const t of await detectTargets()) {
|
|
30433
|
-
let
|
|
30883
|
+
let entries2;
|
|
30434
30884
|
try {
|
|
30435
|
-
|
|
30885
|
+
entries2 = await readdir3(t.skillsDir, { withFileTypes: true });
|
|
30436
30886
|
} catch {
|
|
30437
30887
|
continue;
|
|
30438
30888
|
}
|
|
30439
|
-
for (const e2 of
|
|
30889
|
+
for (const e2 of entries2) {
|
|
30440
30890
|
if (!(e2.isDirectory() || e2.isSymbolicLink()) || !OWN_SKILL_NAME.test(e2.name)) continue;
|
|
30441
30891
|
const entry = join17(t.skillsDir, e2.name);
|
|
30442
30892
|
try {
|
|
@@ -30502,7 +30952,7 @@ function chooseAdapters(opts) {
|
|
|
30502
30952
|
if (opts.cursorDir) adapters.push(new CursorAdapter(opts.cursorDir));
|
|
30503
30953
|
return { adapters: only(adapters), mode: "custom" };
|
|
30504
30954
|
}
|
|
30505
|
-
return { adapters: only([new ClaudeCodeAdapter(), new CodexAdapter(), new CursorAdapter()]), mode: "local" };
|
|
30955
|
+
return { adapters: only([new ClaudeCodeAdapter(), new CodexAdapter(), new CursorAdapter(void 0, void 0, { usageLog: paths.cursorUsage() })]), mode: "local" };
|
|
30506
30956
|
}
|
|
30507
30957
|
async function scan(opts) {
|
|
30508
30958
|
const { adapters, mode } = chooseAdapters(opts);
|
|
@@ -30939,7 +31389,8 @@ async function validate2(name, opts) {
|
|
|
30939
31389
|
out(c.dim(` Or let Reflex run it: reflex validate ${name} --run`));
|
|
30940
31390
|
return;
|
|
30941
31391
|
}
|
|
30942
|
-
|
|
31392
|
+
const claude = agentLaunch("claude", ["--version"]);
|
|
31393
|
+
if (spawnSync3(claude.command, claude.args, { stdio: "ignore", windowsVerbatimArguments: claude.windowsVerbatimArguments }).status !== 0) {
|
|
30943
31394
|
fail("The `claude` CLI was not found on PATH.");
|
|
30944
31395
|
return;
|
|
30945
31396
|
}
|
|
@@ -30960,7 +31411,7 @@ async function validate2(name, opts) {
|
|
|
30960
31411
|
if (run2.finalMessage) {
|
|
30961
31412
|
out();
|
|
30962
31413
|
out(c.dim(" Final message:"));
|
|
30963
|
-
for (const
|
|
31414
|
+
for (const line2 of run2.finalMessage.split("\n").slice(0, 14)) out(c.dim(` ${line2}`));
|
|
30964
31415
|
}
|
|
30965
31416
|
out();
|
|
30966
31417
|
if (run2.skillUsed && run2.testsPass) ok(`${name} worked on a new task.`);
|
|
@@ -30971,9 +31422,9 @@ async function validate2(name, opts) {
|
|
|
30971
31422
|
var sourceSummary = (s) => Object.entries(s.sources).map(([k3, n]) => `${SOURCE_LABELS[k3] ?? k3} ${n}`).join(", ");
|
|
30972
31423
|
function costLine(s) {
|
|
30973
31424
|
const cost = s.cost;
|
|
30974
|
-
const
|
|
30975
|
-
if (cost.runsWithTokens) return
|
|
30976
|
-
return s.sources.cursor ? `${
|
|
31425
|
+
const line2 = describeCost(cost);
|
|
31426
|
+
if (cost.runsWithTokens) return line2;
|
|
31427
|
+
return s.sources.cursor ? `${line2} ${c.dim("(Cursor doesn't record tokens)")}` : line2;
|
|
30977
31428
|
}
|
|
30978
31429
|
function renderSuggestion(entry) {
|
|
30979
31430
|
const s = entry.data;
|
|
@@ -31187,14 +31638,168 @@ async function reject(ref) {
|
|
|
31187
31638
|
// src/commands/misc.ts
|
|
31188
31639
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
31189
31640
|
import { readdir as readdir4, rm as rm3, stat as stat3 } from "node:fs/promises";
|
|
31641
|
+
import { homedir as homedir11 } from "node:os";
|
|
31642
|
+
import { join as join20 } from "node:path";
|
|
31643
|
+
|
|
31644
|
+
// src/cursor-hook.ts
|
|
31645
|
+
import { realpathSync as realpathSync2 } from "node:fs";
|
|
31646
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
31190
31647
|
import { homedir as homedir10 } from "node:os";
|
|
31191
|
-
import { join as join19 } from "node:path";
|
|
31192
|
-
var
|
|
31648
|
+
import { delimiter, join as join19, sep as sep3 } from "node:path";
|
|
31649
|
+
var HOOK_EVENTS = ["stop", "afterAgentResponse"];
|
|
31650
|
+
var SCRIPT_NAME = "cursor-usage.mjs";
|
|
31651
|
+
function assertHookSupported(platform2 = process.platform) {
|
|
31652
|
+
if (platform2 === "win32") throw new Error("reflex cursor-usage isn't available on Windows yet: Reflex can't yet write a hook command Cursor runs there.");
|
|
31653
|
+
}
|
|
31654
|
+
var cursorHooksFile = () => process.env.REFLEX_CURSOR_HOOKS_FILE ?? join19(homedir10(), ".cursor", "hooks.json");
|
|
31655
|
+
var hookScript = () => join19(paths.hooks(), SCRIPT_NAME);
|
|
31656
|
+
function hookSource(logPath) {
|
|
31657
|
+
return `// Written by Reflex (reflex cursor-usage on). Records token counts per Cursor agent turn; never text.
|
|
31658
|
+
import { appendFileSync } from "node:fs";
|
|
31659
|
+
const LOG = ${JSON.stringify(logPath)};
|
|
31660
|
+
const ID = /^[A-Za-z0-9-]{1,80}$/;
|
|
31661
|
+
const MODEL = /^[A-Za-z0-9][A-Za-z0-9._:\\/-]{0,79}$/;
|
|
31662
|
+
const id = (v) => (typeof v === "string" && ID.test(v) ? v : undefined);
|
|
31663
|
+
const model = (v) => (typeof v === "string" && MODEL.test(v) ? v : undefined);
|
|
31664
|
+
const n = (v) => (typeof v === "number" && Number.isFinite(v) && v >= 0 ? Math.round(v) : undefined);
|
|
31665
|
+
let raw = "";
|
|
31666
|
+
process.stdin.setEncoding("utf8");
|
|
31667
|
+
process.stdin.on("data", (c) => { if (raw.length < 8000000) raw += c; });
|
|
31668
|
+
process.stdin.on("end", () => {
|
|
31669
|
+
try {
|
|
31670
|
+
const p = JSON.parse(raw);
|
|
31671
|
+
const event = p.hook_event_name;
|
|
31672
|
+
const rec = {
|
|
31673
|
+
v: 1,
|
|
31674
|
+
at: new Date().toISOString(),
|
|
31675
|
+
event,
|
|
31676
|
+
conversation_id: id(p.conversation_id),
|
|
31677
|
+
generation_id: id(p.generation_id),
|
|
31678
|
+
model: model(p.model_id) ?? model(p.model),
|
|
31679
|
+
input_tokens: n(p.input_tokens),
|
|
31680
|
+
output_tokens: n(p.output_tokens),
|
|
31681
|
+
cache_read_tokens: n(p.cache_read_tokens),
|
|
31682
|
+
cache_write_tokens: n(p.cache_write_tokens),
|
|
31683
|
+
};
|
|
31684
|
+
const counted = rec.input_tokens !== undefined || rec.output_tokens !== undefined;
|
|
31685
|
+
if ((event === "stop" || event === "afterAgentResponse") && rec.conversation_id && rec.generation_id && counted) {
|
|
31686
|
+
appendFileSync(LOG, JSON.stringify(rec) + "\\n", { mode: 0o600 });
|
|
31687
|
+
}
|
|
31688
|
+
} catch {}
|
|
31689
|
+
process.stdout.write("{}");
|
|
31690
|
+
});
|
|
31691
|
+
`;
|
|
31692
|
+
}
|
|
31693
|
+
function stableNode(execPath = process.execPath, pathEnv = process.env.PATH ?? "") {
|
|
31694
|
+
let real;
|
|
31695
|
+
try {
|
|
31696
|
+
real = realpathSync2(execPath);
|
|
31697
|
+
} catch {
|
|
31698
|
+
return execPath;
|
|
31699
|
+
}
|
|
31700
|
+
for (const dir of pathEnv.split(delimiter)) {
|
|
31701
|
+
if (!dir) continue;
|
|
31702
|
+
const candidate = join19(dir, "node");
|
|
31703
|
+
try {
|
|
31704
|
+
if (candidate !== execPath && realpathSync2(candidate) === real) return candidate;
|
|
31705
|
+
} catch {
|
|
31706
|
+
continue;
|
|
31707
|
+
}
|
|
31708
|
+
}
|
|
31709
|
+
return execPath;
|
|
31710
|
+
}
|
|
31711
|
+
function hookCommand(node2 = stableNode(), script = hookScript()) {
|
|
31712
|
+
for (const p3 of [node2, script]) if (p3.includes("'")) throw new Error(`Reflex can't quote the path ${p3} for a hook command.`);
|
|
31713
|
+
return `'${node2}' '${script}'`;
|
|
31714
|
+
}
|
|
31715
|
+
var ours = (e2) => typeof e2?.command === "string" && e2.command.endsWith(`${sep3}hooks${sep3}${SCRIPT_NAME}'`);
|
|
31716
|
+
function entries(hooks, event, file2) {
|
|
31717
|
+
const v2 = hooks[event];
|
|
31718
|
+
if (v2 === void 0) return [];
|
|
31719
|
+
if (!Array.isArray(v2)) throw new Error(`${file2} has "${event}" that isn't a list; Reflex won't overwrite it. Fix it, then run this again.`);
|
|
31720
|
+
return [...v2];
|
|
31721
|
+
}
|
|
31722
|
+
async function readHooks(file2) {
|
|
31723
|
+
if (await isSymlink(file2)) throw new Error(`${file2} is a symlink; Reflex won't write through it. Add the hook entry yourself (see reflex cursor-usage status).`);
|
|
31724
|
+
if (!await pathExists(file2)) return { data: { version: 1, hooks: {} } };
|
|
31725
|
+
const raw = await readFile7(file2, "utf8");
|
|
31726
|
+
let data;
|
|
31727
|
+
try {
|
|
31728
|
+
data = JSON.parse(raw);
|
|
31729
|
+
} catch {
|
|
31730
|
+
throw new Error(`${file2} is not valid JSON; Reflex won't overwrite it. Fix it, then run this again.`);
|
|
31731
|
+
}
|
|
31732
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) throw new Error(`${file2} is not a hooks object; Reflex won't overwrite it.`);
|
|
31733
|
+
return { data, raw };
|
|
31734
|
+
}
|
|
31735
|
+
async function hookStatus(file2 = cursorHooksFile()) {
|
|
31736
|
+
try {
|
|
31737
|
+
const { data } = await readHooks(file2);
|
|
31738
|
+
const hooks = data.hooks ?? {};
|
|
31739
|
+
return { events: HOOK_EVENTS.filter((e2) => Array.isArray(hooks[e2]) && hooks[e2].some(ours)) };
|
|
31740
|
+
} catch (e2) {
|
|
31741
|
+
return { events: [], error: e2 instanceof Error ? e2.message : String(e2) };
|
|
31742
|
+
}
|
|
31743
|
+
}
|
|
31744
|
+
async function writeHooks(file2, data, raw) {
|
|
31745
|
+
let backup;
|
|
31746
|
+
if (raw !== void 0) {
|
|
31747
|
+
const dir = join19(paths.home(), "backups");
|
|
31748
|
+
await ensureDir(paths.home(), 448);
|
|
31749
|
+
await ensureDir(dir, 448);
|
|
31750
|
+
backup = join19(dir, `cursor-hooks-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.json`);
|
|
31751
|
+
await writeNewFile(backup, raw, 384);
|
|
31752
|
+
}
|
|
31753
|
+
await ensureDir(join19(file2, ".."), 493);
|
|
31754
|
+
await replaceOwnedFile(file2, JSON.stringify(data, null, 2) + "\n", 420);
|
|
31755
|
+
return backup;
|
|
31756
|
+
}
|
|
31757
|
+
async function installHook(file2 = cursorHooksFile()) {
|
|
31758
|
+
assertHookSupported();
|
|
31759
|
+
await ensureDir(paths.home(), 448);
|
|
31760
|
+
await ensureDir(paths.hooks(), 448);
|
|
31761
|
+
await replaceOwnedFile(hookScript(), hookSource(paths.cursorUsage()), 448);
|
|
31762
|
+
const { data, raw } = await readHooks(file2);
|
|
31763
|
+
const hooks = { ...data.hooks ?? {} };
|
|
31764
|
+
const command = hookCommand();
|
|
31765
|
+
const added = [];
|
|
31766
|
+
for (const event of HOOK_EVENTS) {
|
|
31767
|
+
const list = entries(hooks, event, file2);
|
|
31768
|
+
if (list.some(ours)) {
|
|
31769
|
+
hooks[event] = list.map((e2) => ours(e2) ? { ...e2, command } : e2);
|
|
31770
|
+
continue;
|
|
31771
|
+
}
|
|
31772
|
+
hooks[event] = [...list, { command, timeout: 5 }];
|
|
31773
|
+
added.push(event);
|
|
31774
|
+
}
|
|
31775
|
+
const backup = await writeHooks(file2, { ...data, version: data.version ?? 1, hooks }, raw);
|
|
31776
|
+
return { added, backup };
|
|
31777
|
+
}
|
|
31778
|
+
async function removeHook(file2 = cursorHooksFile()) {
|
|
31779
|
+
if (!await pathExists(file2)) return { removed: [] };
|
|
31780
|
+
const { data, raw } = await readHooks(file2);
|
|
31781
|
+
const hooks = { ...data.hooks ?? {} };
|
|
31782
|
+
const removed = [];
|
|
31783
|
+
for (const event of HOOK_EVENTS) {
|
|
31784
|
+
const list = entries(hooks, event, file2);
|
|
31785
|
+
const kept = list.filter((e2) => !ours(e2));
|
|
31786
|
+
if (kept.length === list.length) continue;
|
|
31787
|
+
removed.push(event);
|
|
31788
|
+
if (kept.length) hooks[event] = kept;
|
|
31789
|
+
else delete hooks[event];
|
|
31790
|
+
}
|
|
31791
|
+
if (!removed.length) return { removed };
|
|
31792
|
+
const backup = await writeHooks(file2, { ...data, hooks }, raw);
|
|
31793
|
+
return { removed, backup };
|
|
31794
|
+
}
|
|
31795
|
+
|
|
31796
|
+
// src/commands/misc.ts
|
|
31797
|
+
var conductorRoot = () => process.env.REFLEX_CONDUCTOR_DIR ?? join20(homedir11(), "conductor", "workspaces");
|
|
31193
31798
|
async function conductorWorkspaces() {
|
|
31194
31799
|
const dir = conductorRoot();
|
|
31195
31800
|
try {
|
|
31196
|
-
const
|
|
31197
|
-
return { dir, repos:
|
|
31801
|
+
const entries2 = await readdir4(dir, { withFileTypes: true });
|
|
31802
|
+
return { dir, repos: entries2.filter((e2) => e2.isDirectory() && !e2.name.startsWith(".")).length };
|
|
31198
31803
|
} catch {
|
|
31199
31804
|
return void 0;
|
|
31200
31805
|
}
|
|
@@ -31228,10 +31833,15 @@ async function doctor() {
|
|
|
31228
31833
|
out();
|
|
31229
31834
|
out("Agent CLIs (for fresh-task validation)");
|
|
31230
31835
|
for (const bin of ["claude", "codex"]) {
|
|
31231
|
-
const
|
|
31836
|
+
const launch = agentLaunch(bin, ["--version"]);
|
|
31837
|
+
const found = spawnSync4(launch.command, launch.args, { stdio: "ignore", windowsVerbatimArguments: launch.windowsVerbatimArguments }).status === 0;
|
|
31232
31838
|
out(` ${found ? c.green("\u2714") : c.dim("\xB7")} ${bin}`);
|
|
31233
31839
|
}
|
|
31234
31840
|
out();
|
|
31841
|
+
const hook = await hookStatus();
|
|
31842
|
+
out("Cursor token usage");
|
|
31843
|
+
out(` ${hook.events.length ? c.green("\u2714") : c.dim("\xB7")} ${"Cursor hook".padEnd(12)} ${hook.events.length ? `recording (${hook.events.join(", ")})` : c.dim("off \xB7 reflex cursor-usage on")}`);
|
|
31844
|
+
out();
|
|
31235
31845
|
}
|
|
31236
31846
|
async function sessions() {
|
|
31237
31847
|
const store = new Store();
|
|
@@ -31323,12 +31933,18 @@ async function reset(opts) {
|
|
|
31323
31933
|
out("Nothing to reset.");
|
|
31324
31934
|
return;
|
|
31325
31935
|
}
|
|
31326
|
-
out(`This deletes Reflex's own data in ${displayPath(home)}: the local database (including sessions kept from deleted transcripts), generated skills and
|
|
31936
|
+
out(`This deletes Reflex's own data in ${displayPath(home)}: the local database (including sessions kept from deleted transcripts), generated skills, validation sandboxes and recorded Cursor token counts.`);
|
|
31327
31937
|
out(c.dim("Skills you installed into Claude Code, Codex or Cursor are not touched; Reflex's agent-memory block is removed. The embedding model is kept (`reflex model remove`)."));
|
|
31328
31938
|
if (!await confirm("Delete Reflex data?", opts)) return;
|
|
31329
31939
|
for (const w2 of await removeMemory()) if (w2.changed) ok(`Removed Reflex's memory block from ${displayPath(w2.path)}`);
|
|
31330
|
-
|
|
31331
|
-
|
|
31940
|
+
try {
|
|
31941
|
+
const { removed } = await removeHook();
|
|
31942
|
+
if (removed.length) ok(`Removed Reflex's hook from ${displayPath(cursorHooksFile())}`);
|
|
31943
|
+
} catch (e2) {
|
|
31944
|
+
warn(`Could not remove Reflex's Cursor hook: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
31945
|
+
}
|
|
31946
|
+
for (const child of ["reflex.db", "reflex.db-journal", "reflex.db-wal", "reflex.db-shm", "skills", "validation", "cursor-usage.jsonl", "hooks"]) {
|
|
31947
|
+
await rm3(join20(home, child), { recursive: true, force: true });
|
|
31332
31948
|
}
|
|
31333
31949
|
ok("Reset.");
|
|
31334
31950
|
}
|
|
@@ -31341,9 +31957,9 @@ function reportWrites(writes) {
|
|
|
31341
31957
|
else out(c.dim(` ${w2.target.label}: ${displayPath(w2.path)} already up to date`));
|
|
31342
31958
|
}
|
|
31343
31959
|
}
|
|
31344
|
-
function find(
|
|
31960
|
+
function find(entries2, ref) {
|
|
31345
31961
|
const n = Number(ref.replace(/^#/, ""));
|
|
31346
|
-
const e2 = Number.isInteger(n) && n > 0 ?
|
|
31962
|
+
const e2 = Number.isInteger(n) && n > 0 ? entries2[n - 1] : entries2.find((x2) => x2.text === ref);
|
|
31347
31963
|
if (!e2) throw new Error(`No memory entry "${ref.slice(0, 40)}". Run \`reflex memory\` to list them.`);
|
|
31348
31964
|
return e2;
|
|
31349
31965
|
}
|
|
@@ -31352,7 +31968,7 @@ async function memoryStatus() {
|
|
|
31352
31968
|
try {
|
|
31353
31969
|
await syncMemory(store, { mine: Boolean(store.latestScan()) });
|
|
31354
31970
|
const { enabled } = store.memoryState();
|
|
31355
|
-
const
|
|
31971
|
+
const entries2 = store.memoryEntries();
|
|
31356
31972
|
const targets = (await memoryTargets()).filter((t) => t.detected);
|
|
31357
31973
|
title(`Agent memory \xB7 ${enabled ? c.green("on") : c.dim("off")}`);
|
|
31358
31974
|
out(
|
|
@@ -31360,15 +31976,15 @@ async function memoryStatus() {
|
|
|
31360
31976
|
);
|
|
31361
31977
|
rows(targets.map((t) => [t.label, displayPath(t.file)]));
|
|
31362
31978
|
out();
|
|
31363
|
-
if (!
|
|
31979
|
+
if (!entries2.length) {
|
|
31364
31980
|
out(`Nothing to remember yet. Memory comes from corrections you gave in at least 2 independent sessions${store.latestScan() ? "" : "; run `reflex scan` first"}.`);
|
|
31365
31981
|
out(c.dim('Add your own: reflex memory add "use pnpm, not npm"'));
|
|
31366
31982
|
return;
|
|
31367
31983
|
}
|
|
31368
|
-
|
|
31369
|
-
const
|
|
31370
|
-
const
|
|
31371
|
-
out(e2.status === "forgotten" ? c.dim(`${
|
|
31984
|
+
entries2.forEach((e2, i) => {
|
|
31985
|
+
const meta4 = e2.origin === "added" ? "added by you" : plural(e2.sessions, "session");
|
|
31986
|
+
const line2 = ` ${String(i + 1).padStart(2)}. ${e2.text} ${c.dim(`(${meta4})`)}`;
|
|
31987
|
+
out(e2.status === "forgotten" ? c.dim(`${line2} forgotten`) : line2);
|
|
31372
31988
|
});
|
|
31373
31989
|
out();
|
|
31374
31990
|
out(c.dim('reflex memory forget <n> \xB7 remember <n> \xB7 add "<text>" \xB7 on \xB7 off'));
|
|
@@ -31461,12 +32077,12 @@ async function storedSessions() {
|
|
|
31461
32077
|
}
|
|
31462
32078
|
}
|
|
31463
32079
|
async function machineCheck(model2) {
|
|
31464
|
-
const
|
|
32080
|
+
const threads2 = embeddingThreads();
|
|
31465
32081
|
const memGB = totalmem3() / 1e9;
|
|
31466
32082
|
const sessions2 = await storedSessions();
|
|
31467
|
-
const estimate = sessions2 ? `about ${duration3(embeddingSeconds(model2, sessions2,
|
|
32083
|
+
const estimate = sessions2 ? `about ${duration3(embeddingSeconds(model2, sessions2, threads2))} for your ${sessions2} stored sessions` : `about ${duration3(embeddingSeconds(model2, 100, threads2))} per 100 sessions`;
|
|
31468
32084
|
rows([
|
|
31469
|
-
["This machine", `${memGB.toFixed(0)} GB memory, ${availableParallelism2()} cores (${
|
|
32085
|
+
["This machine", `${memGB.toFixed(0)} GB memory, ${availableParallelism2()} cores (${threads2} used for embedding)`],
|
|
31470
32086
|
["First scan", `${estimate}; later scans only embed new sessions (older CPUs can take up to 3x longer)`]
|
|
31471
32087
|
]);
|
|
31472
32088
|
out();
|
|
@@ -31527,6 +32143,7 @@ async function modelFetch(opts) {
|
|
|
31527
32143
|
const total = modelBytes(model2);
|
|
31528
32144
|
let done = 0;
|
|
31529
32145
|
let last = 0;
|
|
32146
|
+
const closeNetwork = allowHosts(MODEL_HOSTS);
|
|
31530
32147
|
try {
|
|
31531
32148
|
await fetchModel(
|
|
31532
32149
|
paths.models(),
|
|
@@ -31545,6 +32162,8 @@ async function modelFetch(opts) {
|
|
|
31545
32162
|
} catch (err) {
|
|
31546
32163
|
spin.stop("Download failed");
|
|
31547
32164
|
throw err;
|
|
32165
|
+
} finally {
|
|
32166
|
+
closeNetwork();
|
|
31548
32167
|
}
|
|
31549
32168
|
await setActiveModel(paths.models(), model2);
|
|
31550
32169
|
spin.stop("Downloaded and verified");
|
|
@@ -31575,11 +32194,87 @@ async function modelRemove(opts) {
|
|
|
31575
32194
|
ok(next ? `Removed ${target.name}. Scans now use ${next.name}.` : `Removed ${target.name}. Scans will compare requests by words only.`);
|
|
31576
32195
|
}
|
|
31577
32196
|
|
|
32197
|
+
// src/commands/cursor-usage.ts
|
|
32198
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
32199
|
+
async function recorded() {
|
|
32200
|
+
const conversations = /* @__PURE__ */ new Set();
|
|
32201
|
+
let turns = 0;
|
|
32202
|
+
let latest;
|
|
32203
|
+
try {
|
|
32204
|
+
for (const line2 of (await readFile8(paths.cursorUsage(), "utf8")).split("\n")) {
|
|
32205
|
+
try {
|
|
32206
|
+
const r2 = JSON.parse(line2);
|
|
32207
|
+
if (r2.event !== "stop" || !r2.conversation_id) continue;
|
|
32208
|
+
turns++;
|
|
32209
|
+
conversations.add(r2.conversation_id);
|
|
32210
|
+
if (r2.at && (!latest || r2.at > latest)) latest = r2.at;
|
|
32211
|
+
} catch {
|
|
32212
|
+
continue;
|
|
32213
|
+
}
|
|
32214
|
+
}
|
|
32215
|
+
} catch {
|
|
32216
|
+
}
|
|
32217
|
+
return { turns, conversations, latest };
|
|
32218
|
+
}
|
|
32219
|
+
async function cursorUsageStatus() {
|
|
32220
|
+
const file2 = cursorHooksFile();
|
|
32221
|
+
const status = await hookStatus(file2);
|
|
32222
|
+
const rec = await recorded();
|
|
32223
|
+
title("Cursor token usage");
|
|
32224
|
+
const on = status.events.length === HOOK_EVENTS.length;
|
|
32225
|
+
rows([
|
|
32226
|
+
["Hook", on ? `${c.green("on")} ${c.dim(`\xB7 ${displayPath(file2)} (${status.events.join(", ")})`)}` : status.events.length ? c.yellow(`partly on (${status.events.join(", ")})`) : `off ${c.dim("\xB7 reflex cursor-usage on")}`],
|
|
32227
|
+
["Recorded", rec.turns ? `${plural(rec.turns, "turn")} in ${plural(rec.conversations.size, "chat")}${rec.latest ? c.dim(` \xB7 latest ${rec.latest.slice(0, 16).replace("T", " ")} UTC`) : ""}` : c.dim("nothing yet")],
|
|
32228
|
+
["Log", displayPath(paths.cursorUsage())]
|
|
32229
|
+
]);
|
|
32230
|
+
if (status.error) warn(status.error);
|
|
32231
|
+
if (on && !await pathExists(hookScript())) warn("The hook script is missing; run reflex cursor-usage on again.");
|
|
32232
|
+
const store = new Store();
|
|
32233
|
+
try {
|
|
32234
|
+
if (store.latestScan() && rec.conversations.size) {
|
|
32235
|
+
const priced = store.traces().filter((t) => t.source === "cursor" && t.usage).length;
|
|
32236
|
+
out();
|
|
32237
|
+
out(` ${plural(priced, "Cursor chat")} in the last scan ${priced === 1 ? "has" : "have"} token counts. ${c.dim("reflex scan picks up new turns.")}`);
|
|
32238
|
+
}
|
|
32239
|
+
} finally {
|
|
32240
|
+
store.close();
|
|
32241
|
+
}
|
|
32242
|
+
out();
|
|
32243
|
+
out(c.dim("Cursor saves no token usage in its transcripts; its hooks receive it at the end of each agent turn. Only chats from when"));
|
|
32244
|
+
out(c.dim("the hook is on get counts. Cursor's command-line agent in -p mode sends no end-of-turn hook, so those runs have none."));
|
|
32245
|
+
}
|
|
32246
|
+
async function cursorUsageOn(opts) {
|
|
32247
|
+
assertHookSupported();
|
|
32248
|
+
const file2 = cursorHooksFile();
|
|
32249
|
+
title("Record Cursor token usage");
|
|
32250
|
+
out(" Cursor sends each agent turn's token counts to its hooks. Reflex adds one hook that writes only the chat and turn");
|
|
32251
|
+
out(" ids, the model and the four token counts to a local file. Never your prompt or the answer; no network.");
|
|
32252
|
+
out();
|
|
32253
|
+
rows([
|
|
32254
|
+
["Hooks file", `${displayPath(file2)} ${c.dim(`(adds ${HOOK_EVENTS.join(" and ")}; your other hooks stay as they are; a backup goes to ~/.reflex/backups)`)}`],
|
|
32255
|
+
["Runs", c.dim(hookCommand().replace(/'/g, ""))],
|
|
32256
|
+
["Writes to", displayPath(paths.cursorUsage())]
|
|
32257
|
+
]);
|
|
32258
|
+
out();
|
|
32259
|
+
if (!await confirm(`Add the hook to ${displayPath(file2)}?`, opts)) return;
|
|
32260
|
+
const { added, backup } = await installHook(file2);
|
|
32261
|
+
ok(added.length ? `Hook on (${added.join(", ")}). Cursor reloads hooks.json by itself; new turns are recorded from now on.` : "Hook was already on; its command is refreshed.");
|
|
32262
|
+
if (backup) out(c.dim(` Previous hooks file: ${displayPath(backup)}`));
|
|
32263
|
+
out(c.dim(" reflex scan attaches the counts to your Cursor chats. reflex cursor-usage off removes the hook."));
|
|
32264
|
+
}
|
|
32265
|
+
async function cursorUsageOff() {
|
|
32266
|
+
const { removed, backup } = await removeHook();
|
|
32267
|
+
if (!removed.length) ok("The hook was not on.");
|
|
32268
|
+
else ok(`Hook off (removed ${removed.join(", ")} from ${displayPath(cursorHooksFile())}).`);
|
|
32269
|
+
if (backup) out(c.dim(` Previous hooks file: ${displayPath(backup)}`));
|
|
32270
|
+
out(c.dim(` Recorded counts stay in ${displayPath(paths.cursorUsage())}; reflex reset deletes them.`));
|
|
32271
|
+
}
|
|
32272
|
+
|
|
31578
32273
|
// src/commands/improve.ts
|
|
31579
32274
|
import { randomUUID } from "node:crypto";
|
|
31580
32275
|
import { existsSync as existsSync5 } from "node:fs";
|
|
31581
|
-
import { delimiter, join as
|
|
31582
|
-
var onPath = (cmd) => (process.env.PATH ?? "").split(
|
|
32276
|
+
import { delimiter as delimiter2, join as join21, resolve as resolve4 } from "node:path";
|
|
32277
|
+
var onPath = (cmd) => (process.env.PATH ?? "").split(delimiter2).some((d3) => d3 && existsSync5(join21(d3, cmd)));
|
|
31583
32278
|
var unique = (xs) => [...new Map(xs.map((x2) => [x2.sessionId, x2])).values()];
|
|
31584
32279
|
async function listSkills2(store) {
|
|
31585
32280
|
const traces = unique(store.traces());
|
|
@@ -31595,8 +32290,8 @@ async function listSkills2(store) {
|
|
|
31595
32290
|
for (const n of names.sort((a, b3) => loaded(b3) - loaded(a) || a.localeCompare(b3))) {
|
|
31596
32291
|
const mine = found.filter((f) => f.name === n);
|
|
31597
32292
|
const where = [...mine.map((f) => f.target), ...mine.some((f) => f.link) ? ["linked"] : []];
|
|
31598
|
-
const
|
|
31599
|
-
out(` ${n.padEnd(28)} ${c.dim(where.join(", ").padEnd(28))} ${
|
|
32293
|
+
const count3 = loaded(n);
|
|
32294
|
+
out(` ${n.padEnd(28)} ${c.dim(where.join(", ").padEnd(28))} ${count3 ? `loaded in ${plural(count3, "session")}` : c.dim("not loaded in the last scan")}${own2.has(n) ? c.dim(" \xB7 generated by Reflex") : ""}`);
|
|
31600
32295
|
}
|
|
31601
32296
|
out();
|
|
31602
32297
|
out(c.dim(` reflex improve <name> compares a skill with the sessions that loaded it (needs ${MIN_REVIEW_SESSIONS}+).`));
|
|
@@ -31646,7 +32341,7 @@ async function verifyOutput(name, current, next, opts) {
|
|
|
31646
32341
|
if (!Number.isInteger(runs) || runs < 1 || runs > 5) throw new Error("--runs must be 1 to 5.");
|
|
31647
32342
|
if (!Number.isFinite(minutes) || minutes < 1 || minutes > 120) throw new Error("--timeout is minutes per run, 1 to 120.");
|
|
31648
32343
|
out(c.dim(` The check runs "${task}" ${plural(runs, "time")} with each version: ${plural(runs * 2, "non-persistent Claude Code session")} on your account, project settings only,`));
|
|
31649
|
-
const benchRoot =
|
|
32344
|
+
const benchRoot = join21(paths.home(), "bench");
|
|
31650
32345
|
out(c.dim(` in fresh copies of ${displayPath(root)} at ${headCommit(root) ?? "HEAD"} under ${displayPath(benchRoot)} (deleted afterwards). Answers are compared in memory, never saved.`));
|
|
31651
32346
|
if (!await confirm(`Run the before/after check?`, opts)) return void 0;
|
|
31652
32347
|
await ensureDir(paths.home(), 448);
|
|
@@ -31658,7 +32353,7 @@ async function verifyOutput(name, current, next, opts) {
|
|
|
31658
32353
|
for (let i = 0; i < runs; i++) {
|
|
31659
32354
|
const shapes = { before: [], after: [] };
|
|
31660
32355
|
for (const side of ["before", "after"]) {
|
|
31661
|
-
const dir =
|
|
32356
|
+
const dir = join21(benchRoot, `improve-${name}-${side}-${randomUUID().slice(0, 8)}`);
|
|
31662
32357
|
cloneRepo(root, dir);
|
|
31663
32358
|
const spin = spinner();
|
|
31664
32359
|
try {
|
|
@@ -31724,19 +32419,19 @@ async function improve(name, opts) {
|
|
|
31724
32419
|
const behavior = opts.behavior === true;
|
|
31725
32420
|
out();
|
|
31726
32421
|
renderReview(review, behavior);
|
|
31727
|
-
const
|
|
31728
|
-
if (!
|
|
32422
|
+
const section2 = learnedSection(review, { behavior });
|
|
32423
|
+
if (!section2) {
|
|
31729
32424
|
ok(
|
|
31730
32425
|
behavior || !review.missing.length && !review.constraints.length ? `Nothing to add: ${name} already covers what these sessions did.` : `Nothing to add that keeps ${name} doing exactly what it does. --behavior proposes the steps and corrections above.`
|
|
31731
32426
|
);
|
|
31732
32427
|
return;
|
|
31733
32428
|
}
|
|
31734
|
-
const next = applyLearned(content,
|
|
31735
|
-
const proposalDir = assertInside(paths.home(),
|
|
32429
|
+
const next = applyLearned(content, section2);
|
|
32430
|
+
const proposalDir = assertInside(paths.home(), join21(paths.home(), "proposals", name));
|
|
31736
32431
|
await ensureDir(paths.home(), 448);
|
|
31737
|
-
await ensureDir(
|
|
32432
|
+
await ensureDir(join21(paths.home(), "proposals"), 448);
|
|
31738
32433
|
await ensureDir(proposalDir, 448);
|
|
31739
|
-
const proposal =
|
|
32434
|
+
const proposal = join21(proposalDir, "SKILL.md");
|
|
31740
32435
|
await replaceOwnedFile(proposal, next, 384);
|
|
31741
32436
|
out(c.bold("Proposed change"));
|
|
31742
32437
|
fileBlock(displayPath(target.path), lineDiff(content, next));
|
|
@@ -31782,7 +32477,7 @@ async function improve(name, opts) {
|
|
|
31782
32477
|
if (store.installations(name).some((i) => resolve4(i.path) === resolve4(target.path)))
|
|
31783
32478
|
warn("Reflex installed this copy; after the change it counts as edited, so `reflex install`/remove will leave it alone.");
|
|
31784
32479
|
if (!await confirm(`Apply it to ${displayPath(target.path)}? The current file is backed up first.`, opts)) return;
|
|
31785
|
-
const backup = await applyToOwnSkill(target.path, sha256(content), next,
|
|
32480
|
+
const backup = await applyToOwnSkill(target.path, sha256(content), next, join21(paths.home(), "backups"), name);
|
|
31786
32481
|
store.updateSkillChange(changeId, { applied: true, backup: displayPath(backup) });
|
|
31787
32482
|
ok(`Updated ${displayPath(target.path)}. Backup: ${displayPath(backup)}`);
|
|
31788
32483
|
} finally {
|
|
@@ -31790,15 +32485,136 @@ async function improve(name, opts) {
|
|
|
31790
32485
|
}
|
|
31791
32486
|
}
|
|
31792
32487
|
|
|
32488
|
+
// src/commands/handbook.ts
|
|
32489
|
+
import { dirname as dirname8 } from "node:path";
|
|
32490
|
+
var TOOL = { "claude-code": "Claude Code", codex: "Codex", cursor: "Cursor" };
|
|
32491
|
+
function load() {
|
|
32492
|
+
const store = new Store();
|
|
32493
|
+
try {
|
|
32494
|
+
if (!store.latestScan()) throw new Error("No scan yet. Run `reflex scan --days 30` first.");
|
|
32495
|
+
const forgotten = new Set(store.memoryEntries().filter((e2) => e2.status === "forgotten").map((e2) => e2.text));
|
|
32496
|
+
return buildHandbook(store.traces(), { forgotten });
|
|
32497
|
+
} finally {
|
|
32498
|
+
store.close();
|
|
32499
|
+
}
|
|
32500
|
+
}
|
|
32501
|
+
function scope(practices, opts) {
|
|
32502
|
+
const known = new Map(practices.filter((p3) => p3.project).map((p3) => [p3.project.hash, p3.project]));
|
|
32503
|
+
if (opts.project) {
|
|
32504
|
+
const hit = [...known.values()].find((p3) => p3.name === opts.project || p3.hash === opts.project);
|
|
32505
|
+
if (!hit) throw new Error(`No practices for a repository named "${opts.project}". \`reflex handbook --all\` lists them.`);
|
|
32506
|
+
return hit;
|
|
32507
|
+
}
|
|
32508
|
+
for (let dir = process.cwd(); ; dir = dirname8(dir)) {
|
|
32509
|
+
const hit = known.get(shortHash(dir));
|
|
32510
|
+
if (hit) return hit;
|
|
32511
|
+
if (dirname8(dir) === dir) return {};
|
|
32512
|
+
}
|
|
32513
|
+
}
|
|
32514
|
+
function meta3(p3) {
|
|
32515
|
+
return `${plural(p3.sessions, "session")}${p3.last ? ` \xB7 last ${shortDate(p3.last)}` : ""} \xB7 ${p3.id}`;
|
|
32516
|
+
}
|
|
32517
|
+
function line(p3) {
|
|
32518
|
+
return ` ${p3.text}${p3.when ? c.cyan(` (${p3.when})`) : ""} ${c.dim(meta3(p3))}`;
|
|
32519
|
+
}
|
|
32520
|
+
function section(name, items) {
|
|
32521
|
+
if (!items.length) return;
|
|
32522
|
+
out(c.bold(` ${name}`));
|
|
32523
|
+
for (const p3 of items) out(line(p3));
|
|
32524
|
+
out();
|
|
32525
|
+
}
|
|
32526
|
+
var json2 = (value) => out(JSON.stringify(value, null, 2));
|
|
32527
|
+
async function handbook(opts) {
|
|
32528
|
+
const all = load();
|
|
32529
|
+
if (opts.all) {
|
|
32530
|
+
if (opts.json) return json2({ project: null, practices: all });
|
|
32531
|
+
title(`Handbook \xB7 every repository \xB7 ${plural(all.length, "practice")}`);
|
|
32532
|
+
const groups = /* @__PURE__ */ new Map();
|
|
32533
|
+
for (const p3 of all) groups.set(p3.project?.name ?? "Across repositories", [...groups.get(p3.project?.name ?? "Across repositories") ?? [], p3]);
|
|
32534
|
+
for (const [name, items] of groups) section(name, items);
|
|
32535
|
+
return;
|
|
32536
|
+
}
|
|
32537
|
+
const where = scope(all, opts);
|
|
32538
|
+
const practices = practicesFor(all, where.hash);
|
|
32539
|
+
if (opts.json) return json2({ project: where.hash ? where : null, practices });
|
|
32540
|
+
title(`Handbook \xB7 ${where.name ?? "no repository matched this folder"}`);
|
|
32541
|
+
if (!practices.length) {
|
|
32542
|
+
out("Nothing learned yet. Practices come from commands that worked and corrections you repeated, in at least 2 independent sessions.");
|
|
32543
|
+
return;
|
|
32544
|
+
}
|
|
32545
|
+
const own2 = practices.filter((p3) => p3.project);
|
|
32546
|
+
section("Commands that work here", own2.filter((p3) => p3.kind === "command"));
|
|
32547
|
+
section("Rules you gave agents here", own2.filter((p3) => p3.kind === "rule"));
|
|
32548
|
+
section("Rules across your repositories", practices.filter((p3) => !p3.project));
|
|
32549
|
+
out(c.dim(`reflex handbook show <id> \xB7 ask "<question>" \xB7 export \xB7 --json${where.hash ? "" : " \xB7 --project <name> \xB7 --all"}`));
|
|
32550
|
+
}
|
|
32551
|
+
async function handbookShow(id, opts) {
|
|
32552
|
+
const p3 = load().find((x2) => x2.id === id);
|
|
32553
|
+
if (!p3) throw new Error(`No practice ${id}. \`reflex handbook\` lists them with their ids.`);
|
|
32554
|
+
if (opts.json) return json2(p3);
|
|
32555
|
+
title(p3.text);
|
|
32556
|
+
if (p3.when) out(` Applies ${p3.when}.`);
|
|
32557
|
+
out(` ${p3.project?.name ? `In ${p3.project.name}` : "Across your repositories"} \xB7 ${plural(p3.sessions, "independent session")}`);
|
|
32558
|
+
out();
|
|
32559
|
+
out(c.bold(` Sessions behind it${p3.sessions > p3.sources.length ? ` (newest ${p3.sources.length})` : ""}`));
|
|
32560
|
+
for (const s of p3.sources) out(` ${shortDate(s.date)} ${(TOOL[s.tool] ?? s.tool).padEnd(11)} ${c.dim(s.request || "(no request text)")}`);
|
|
32561
|
+
}
|
|
32562
|
+
async function handbookAsk(words2, opts) {
|
|
32563
|
+
const question = words2.join(" ").trim();
|
|
32564
|
+
if (!question) throw new Error('Ask a question: reflex handbook ask "how do we run tests here?"');
|
|
32565
|
+
const all = load();
|
|
32566
|
+
const where = scope(all, opts);
|
|
32567
|
+
const answers = askHandbook(practicesFor(all, where.hash), question, where.hash);
|
|
32568
|
+
if (opts.json) return json2({ question, project: where.hash ? where : null, answers: answers.map((a) => ({ score: Number(a.score.toFixed(3)), ...a.practice })) });
|
|
32569
|
+
out();
|
|
32570
|
+
if (!answers.length) {
|
|
32571
|
+
out(`Nothing in the handbook${where.name ? ` for ${where.name}` : ""} answers that. Reflex only knows what past sessions showed.`);
|
|
32572
|
+
return;
|
|
32573
|
+
}
|
|
32574
|
+
for (const { practice: p3 } of answers) {
|
|
32575
|
+
out(`${c.green("\u203A")} ${p3.text}${p3.when ? c.cyan(` (${p3.when})`) : ""}`);
|
|
32576
|
+
out(c.dim(` ${p3.project?.name ? `in ${p3.project.name}` : "across your repositories"} \xB7 ${meta3(p3)} \xB7 reflex handbook show ${p3.id}`));
|
|
32577
|
+
}
|
|
32578
|
+
}
|
|
32579
|
+
async function handbookExport(opts) {
|
|
32580
|
+
const all = load();
|
|
32581
|
+
const where = opts.all ? {} : scope(all, opts);
|
|
32582
|
+
const practices = opts.all ? all : practicesFor(all, where.hash);
|
|
32583
|
+
const name = opts.all ? "all repositories" : where.name ?? "this folder";
|
|
32584
|
+
const entry = (p3) => `- ${p3.text}${p3.when ? ` *(${p3.when})*` : ""} \xB7 ${plural(p3.sessions, "session")}${p3.last ? `, last ${shortDate(p3.last)}` : ""}`;
|
|
32585
|
+
const lines = [
|
|
32586
|
+
`# Handbook: ${name}`,
|
|
32587
|
+
"",
|
|
32588
|
+
`Learned by Reflex from past coding-agent sessions, ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}. Each item held in at least 2 independent sessions; the count says how many.`,
|
|
32589
|
+
""
|
|
32590
|
+
];
|
|
32591
|
+
const groups = [
|
|
32592
|
+
["Commands that work", practices.filter((p3) => p3.kind === "command")],
|
|
32593
|
+
["Rules", practices.filter((p3) => p3.kind === "rule" && p3.project)],
|
|
32594
|
+
["Rules across repositories", practices.filter((p3) => p3.kind === "rule" && !p3.project)]
|
|
32595
|
+
];
|
|
32596
|
+
for (const [heading, items] of groups) {
|
|
32597
|
+
if (!items.length) continue;
|
|
32598
|
+
lines.push(`## ${heading}`, "");
|
|
32599
|
+
if (opts.all && heading !== "Rules across repositories") {
|
|
32600
|
+
const byRepo = /* @__PURE__ */ new Map();
|
|
32601
|
+
for (const p3 of items) byRepo.set(p3.project?.name ?? "unnamed", [...byRepo.get(p3.project?.name ?? "unnamed") ?? [], p3]);
|
|
32602
|
+
for (const [repo, ps] of byRepo) lines.push(`### ${repo}`, "", ...ps.map(entry), "");
|
|
32603
|
+
} else lines.push(...items.map(entry), "");
|
|
32604
|
+
}
|
|
32605
|
+
if (!practices.length) lines.push("Nothing learned yet.", "");
|
|
32606
|
+
out(lines.join("\n").trimEnd());
|
|
32607
|
+
}
|
|
32608
|
+
|
|
31793
32609
|
// src/commands/route.ts
|
|
31794
32610
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
31795
32611
|
import { randomInt, randomUUID as randomUUID2 } from "node:crypto";
|
|
31796
32612
|
import { existsSync as existsSync6 } from "node:fs";
|
|
31797
|
-
import { basename as basename7, delimiter as
|
|
32613
|
+
import { basename as basename7, delimiter as delimiter3, join as join22 } from "node:path";
|
|
31798
32614
|
var CLI = { "claude-code": "claude", codex: "codex" };
|
|
31799
32615
|
var MODEL_NAME2 = /^[A-Za-z0-9][A-Za-z0-9._:[\]-]{0,63}$/;
|
|
31800
32616
|
var CODEX_MODEL = /^(gpt|o\d|codex)/i;
|
|
31801
|
-
var onPath2 = (cmd) => (process.env.PATH ?? "").split(
|
|
32617
|
+
var onPath2 = (cmd) => (process.env.PATH ?? "").split(delimiter3).some((d3) => d3 && existsSync6(join22(d3, cmd)));
|
|
31802
32618
|
var unique2 = (traces) => [...new Map(traces.map((t) => [t.sessionId, t])).values()];
|
|
31803
32619
|
var usd = (n) => n === void 0 ? "\u2014" : n < 0.01 ? "<$0.01" : `$${n.toFixed(2)}`;
|
|
31804
32620
|
var fixes = (f) => `${f.toFixed(2)} fixes/request`;
|
|
@@ -31903,7 +32719,8 @@ async function runRouted(words2, opts) {
|
|
|
31903
32719
|
if (!run2) return;
|
|
31904
32720
|
const model2 = run2.model ? ["--model", run2.model] : [];
|
|
31905
32721
|
const args = run2.source === "claude-code" ? [...model2, "--session-id", run2.nativeId, request] : [...model2, request];
|
|
31906
|
-
const
|
|
32722
|
+
const launch = agentLaunch(CLI[run2.source], args);
|
|
32723
|
+
const res = spawnSync5(launch.command, launch.args, { stdio: "inherit", windowsVerbatimArguments: launch.windowsVerbatimArguments });
|
|
31907
32724
|
if (res.error) throw new Error(`Could not start ${CLI[run2.source]}: ${res.error.message}`);
|
|
31908
32725
|
process.exitCode = res.status ?? 0;
|
|
31909
32726
|
if (opts.ask !== false && interactive()) await askOutcome(runId);
|
|
@@ -32017,7 +32834,7 @@ async function bench(words2, opts) {
|
|
|
32017
32834
|
const traces = unique2(store.traces());
|
|
32018
32835
|
const kind = classifyRequest(task, traces).kind;
|
|
32019
32836
|
const { tools, agentCanRunCheck } = benchTools(opts.check);
|
|
32020
|
-
const benchRoot =
|
|
32837
|
+
const benchRoot = join22(paths.home(), "bench");
|
|
32021
32838
|
const total = runs * models.length;
|
|
32022
32839
|
const table2 = routingTable(traces);
|
|
32023
32840
|
const typical = models.map((m2) => ({ m: m2, cost: typicalCost(table2, "claude-code", m2) }));
|
|
@@ -32051,7 +32868,7 @@ async function bench(words2, opts) {
|
|
|
32051
32868
|
await ensureDir(benchRoot, 448);
|
|
32052
32869
|
const batch = randomUUID2().slice(0, 8);
|
|
32053
32870
|
const timeoutMs = minutes * 6e4;
|
|
32054
|
-
const baseline =
|
|
32871
|
+
const baseline = join22(benchRoot, `${batch}-before`);
|
|
32055
32872
|
cloneRepo(root, baseline);
|
|
32056
32873
|
try {
|
|
32057
32874
|
if (opts.setup && !runUserCommand(baseline, opts.setup, timeoutMs)) throw new Error(`The setup command failed in a fresh copy: \`${opts.setup}\`. Fix it, then run bench again.`);
|
|
@@ -32064,7 +32881,7 @@ async function bench(words2, opts) {
|
|
|
32064
32881
|
for (let i = 0; i < runs; i++) {
|
|
32065
32882
|
const order = models.map((_3, j2) => models[(i + j2) % models.length]);
|
|
32066
32883
|
for (const model2 of order) {
|
|
32067
|
-
const dir =
|
|
32884
|
+
const dir = join22(benchRoot, `${batch}-${model2.replace(/[^A-Za-z0-9.-]/g, "_")}-${i + 1}`);
|
|
32068
32885
|
cloneRepo(root, dir);
|
|
32069
32886
|
const spin = spinner();
|
|
32070
32887
|
try {
|
|
@@ -32207,8 +33024,8 @@ function hcat(blocks, gap) {
|
|
|
32207
33024
|
for (let i = 0; i < h2; i++) {
|
|
32208
33025
|
let l2 = [];
|
|
32209
33026
|
blocks.forEach((b3, j2) => {
|
|
32210
|
-
const
|
|
32211
|
-
l2 = l2.concat(
|
|
33027
|
+
const line2 = b3.lines[i];
|
|
33028
|
+
l2 = l2.concat(line2 ? fit(line2, b3.w) : [S2(" ".repeat(b3.w))]);
|
|
32212
33029
|
if (j2 < blocks.length - 1) l2.push(S2(" ".repeat(gap)));
|
|
32213
33030
|
});
|
|
32214
33031
|
out2.push(l2);
|
|
@@ -32381,18 +33198,18 @@ function hbars(title2, items, w2, o2 = {}) {
|
|
|
32381
33198
|
function mdLines(src, w2) {
|
|
32382
33199
|
const out2 = [];
|
|
32383
33200
|
let fm = 0;
|
|
32384
|
-
src.forEach((
|
|
33201
|
+
src.forEach((line2) => {
|
|
32385
33202
|
let c2 = "fg";
|
|
32386
33203
|
let b3 = null;
|
|
32387
|
-
if (
|
|
33204
|
+
if (line2 === "---") {
|
|
32388
33205
|
fm++;
|
|
32389
33206
|
c2 = "dim";
|
|
32390
33207
|
} else if (fm === 1) c2 = "dim";
|
|
32391
|
-
else if (
|
|
33208
|
+
else if (line2.startsWith("#")) {
|
|
32392
33209
|
c2 = "hi";
|
|
32393
33210
|
b3 = BOLD;
|
|
32394
33211
|
}
|
|
32395
|
-
wrap(
|
|
33212
|
+
wrap(line2, w2).forEach((t) => out2.push([S2(t, c2, b3)]));
|
|
32396
33213
|
});
|
|
32397
33214
|
return out2;
|
|
32398
33215
|
}
|
|
@@ -32702,8 +33519,8 @@ function renderMorning(w2, h2, data, _ui) {
|
|
|
32702
33519
|
...data.skills.items.map((x2) => ({ k: "skill", x: x2 })),
|
|
32703
33520
|
...(data.workflows?.items ?? []).map((x2) => ({ k: "wf", x: x2 }))
|
|
32704
33521
|
];
|
|
32705
|
-
const
|
|
32706
|
-
const cap = Math.max(2, Math.min(8, h2 - L3.length -
|
|
33522
|
+
const tail2 = 4;
|
|
33523
|
+
const cap = Math.max(2, Math.min(8, h2 - L3.length - tail2 - 3));
|
|
32707
33524
|
const cw3 = Math.floor((w2 - 6) / 3);
|
|
32708
33525
|
const col = (k3) => {
|
|
32709
33526
|
const xs = all.filter((e2) => e2.x.state === k3);
|
|
@@ -34145,7 +34962,12 @@ function runTui(opts) {
|
|
|
34145
34962
|
const resume = async (c2) => {
|
|
34146
34963
|
let error62;
|
|
34147
34964
|
await term.suspend(() => {
|
|
34148
|
-
|
|
34965
|
+
try {
|
|
34966
|
+
const launch = agentLaunch(c2.cmd, c2.args);
|
|
34967
|
+
error62 = spawnSync6(launch.command, launch.args, { stdio: "inherit", cwd: c2.cwd, windowsVerbatimArguments: launch.windowsVerbatimArguments }).error;
|
|
34968
|
+
} catch (e2) {
|
|
34969
|
+
error62 = e2 instanceof Error ? e2 : new Error(String(e2));
|
|
34970
|
+
}
|
|
34149
34971
|
});
|
|
34150
34972
|
term.invalidate();
|
|
34151
34973
|
await reload();
|
|
@@ -34235,12 +35057,12 @@ var weekdayLabel = (d3) => `${WEEKDAYS[d3.getDay()]} ${dayLabel(d3).toLowerCase(
|
|
|
34235
35057
|
var rangeLabel = (from, to) => `${dayLabel(from).toLowerCase()} \u2013 ${dayLabel(to).toLowerCase()}`;
|
|
34236
35058
|
var clockLabel = (d3) => `${pad2(d3.getHours())}:${pad2(d3.getMinutes())}`;
|
|
34237
35059
|
var dayStart = (d3, n = 0) => new Date(d3.getFullYear(), d3.getMonth(), d3.getDate() + n);
|
|
34238
|
-
var
|
|
35060
|
+
var count2 = (n) => n.toLocaleString("en-US");
|
|
34239
35061
|
|
|
34240
35062
|
// ../../packages/tui/src/live/skills.ts
|
|
34241
35063
|
import { constants as constants4 } from "node:fs";
|
|
34242
35064
|
import { lstat as lstat9, open as open6 } from "node:fs/promises";
|
|
34243
|
-
import { join as
|
|
35065
|
+
import { join as join23 } from "node:path";
|
|
34244
35066
|
var MAX_SKILL_BYTES = 64 * 1024;
|
|
34245
35067
|
var TOOL_OF = { "claude-code": "claude", codex: "codex", cursor: "cursor" };
|
|
34246
35068
|
var toolName = (target) => toCells(TOOL_OF[target] ?? target);
|
|
@@ -34264,11 +35086,11 @@ async function readCapped(file2) {
|
|
|
34264
35086
|
}
|
|
34265
35087
|
async function readReflexCopy(name) {
|
|
34266
35088
|
if (!isValidSlug(name)) return void 0;
|
|
34267
|
-
const dir =
|
|
35089
|
+
const dir = join23(paths.skills(), name);
|
|
34268
35090
|
if (await isSymlink(paths.skills()) || await isSymlink(dir)) return void 0;
|
|
34269
|
-
return readCapped(
|
|
35091
|
+
return readCapped(join23(dir, "SKILL.md"));
|
|
34270
35092
|
}
|
|
34271
|
-
async function
|
|
35093
|
+
async function isFile3(path) {
|
|
34272
35094
|
try {
|
|
34273
35095
|
return (await lstat9(path)).isFile();
|
|
34274
35096
|
} catch {
|
|
@@ -34292,7 +35114,7 @@ async function skillItems(store, scan2, targets, now) {
|
|
|
34292
35114
|
const names = new Set(generated.map((k3) => k3.name));
|
|
34293
35115
|
const installs = store.installations();
|
|
34294
35116
|
const installed = async (name) => {
|
|
34295
|
-
for (const r2 of installs) if (r2.skill === name && await
|
|
35117
|
+
for (const r2 of installs) if (r2.skill === name && await isFile3(r2.path)) return true;
|
|
34296
35118
|
return false;
|
|
34297
35119
|
};
|
|
34298
35120
|
const path = (name) => claude ? toCells(`${displayPath(claude.skillsDir)}/${name}/SKILL.md`) : "";
|
|
@@ -34315,7 +35137,7 @@ async function skillItems(store, scan2, targets, now) {
|
|
|
34315
35137
|
state: found.has(k3.suggestionSlug) ? "" : "retired",
|
|
34316
35138
|
steps: s?.steps.length ?? 0,
|
|
34317
35139
|
path: path(name),
|
|
34318
|
-
markdown: text === void 0 ? [toCells(`could not read ${displayPath(
|
|
35140
|
+
markdown: text === void 0 ? [toCells(`could not read ${displayPath(join23(paths.skills(), k3.name, "SKILL.md"))}`)] : toLines(text)
|
|
34319
35141
|
});
|
|
34320
35142
|
}
|
|
34321
35143
|
return { items, targets: targets.filter((t) => t.detected).map((t) => toCells(`${displayPath(t.skillsDir)}/<name>/SKILL.md`)) };
|
|
@@ -34516,29 +35338,29 @@ function buildRouter(priced, rebuiltAt, windowDays2, autopilot = false) {
|
|
|
34516
35338
|
}
|
|
34517
35339
|
|
|
34518
35340
|
// ../../packages/tui/src/live/search.ts
|
|
34519
|
-
import { closeSync, constants as constants5, existsSync as existsSync7, lstatSync as lstatSync2, openSync, readSync, readdirSync, statSync as
|
|
34520
|
-
import { basename as basename8,
|
|
35341
|
+
import { closeSync as closeSync2, constants as constants5, existsSync as existsSync7, lstatSync as lstatSync2, openSync as openSync2, readSync as readSync2, readdirSync, statSync as statSync3 } from "node:fs";
|
|
35342
|
+
import { basename as basename8, join as join24 } from "node:path";
|
|
34521
35343
|
var SESSION_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,79}$/;
|
|
34522
35344
|
var MAX_CWD_SCAN_BYTES = 256 * 1024;
|
|
34523
35345
|
function buildSearch(priced) {
|
|
34524
35346
|
const sessions2 = /* @__PURE__ */ new Map();
|
|
34525
35347
|
const bySession = /* @__PURE__ */ new Map();
|
|
34526
|
-
const
|
|
35348
|
+
const meta4 = /* @__PURE__ */ new Map();
|
|
34527
35349
|
const all = [];
|
|
34528
35350
|
for (const { t, at, tool, cost } of priced) {
|
|
34529
35351
|
const nativeId = t.sessionId.slice(t.source.length + 1);
|
|
34530
35352
|
const key3 = sessions2.has(nativeId.slice(0, 8)) ? nativeId : nativeId.slice(0, 8);
|
|
34531
35353
|
sessions2.set(key3, { source: t.source, nativeId });
|
|
34532
|
-
|
|
35354
|
+
meta4.set(key3, { usd: cost?.usd, turnCount: t.requests });
|
|
34533
35355
|
const base = { date: at ? dayLabel(new Date(at)) : "\u2014", tool, project: toCells(t.projectName ?? "\u2014"), session: toCells(key3), at };
|
|
34534
35356
|
const texts = [["you", t.excerpt], ...t.displaySteps.map((s) => ["ai", s])];
|
|
34535
|
-
const
|
|
35357
|
+
const entries2 = [];
|
|
34536
35358
|
texts.forEach(([role, raw], i) => {
|
|
34537
35359
|
const text = toCells(raw).trim();
|
|
34538
|
-
if (text)
|
|
35360
|
+
if (text) entries2.push({ ...base, turn: i + 1, role, text, lower: text.toLowerCase() });
|
|
34539
35361
|
});
|
|
34540
|
-
bySession.set(key3,
|
|
34541
|
-
all.push(...
|
|
35362
|
+
bySession.set(key3, entries2);
|
|
35363
|
+
all.push(...entries2);
|
|
34542
35364
|
}
|
|
34543
35365
|
all.sort((a, b3) => b3.at - a.at || b3.turn - a.turn);
|
|
34544
35366
|
const index = {
|
|
@@ -34548,7 +35370,7 @@ function buildSearch(priced) {
|
|
|
34548
35370
|
return all.filter((e2) => (tool === "all" || e2.tool === tool) && (!needle || e2.lower.includes(needle)));
|
|
34549
35371
|
},
|
|
34550
35372
|
session(id) {
|
|
34551
|
-
return { turns: bySession.get(id) ?? [], ...
|
|
35373
|
+
return { turns: bySession.get(id) ?? [], ...meta4.get(id) };
|
|
34552
35374
|
}
|
|
34553
35375
|
};
|
|
34554
35376
|
return { index, sessions: sessions2 };
|
|
@@ -34562,24 +35384,24 @@ function claudeCwd(nativeId) {
|
|
|
34562
35384
|
return void 0;
|
|
34563
35385
|
}
|
|
34564
35386
|
for (const dir of dirs) {
|
|
34565
|
-
const file2 =
|
|
35387
|
+
const file2 = join24(root, dir, `${nativeId}.jsonl`);
|
|
34566
35388
|
try {
|
|
34567
35389
|
if (!lstatSync2(file2).isFile()) continue;
|
|
34568
35390
|
} catch {
|
|
34569
35391
|
continue;
|
|
34570
35392
|
}
|
|
34571
|
-
const fd =
|
|
35393
|
+
const fd = openSync2(file2, constants5.O_RDONLY | constants5.O_NOFOLLOW);
|
|
34572
35394
|
const buf = Buffer.alloc(MAX_CWD_SCAN_BYTES);
|
|
34573
35395
|
let n;
|
|
34574
35396
|
try {
|
|
34575
|
-
n =
|
|
35397
|
+
n = readSync2(fd, buf, 0, buf.length, 0);
|
|
34576
35398
|
} finally {
|
|
34577
|
-
|
|
35399
|
+
closeSync2(fd);
|
|
34578
35400
|
}
|
|
34579
|
-
for (const
|
|
35401
|
+
for (const line2 of buf.subarray(0, n).toString("utf8").split("\n")) {
|
|
34580
35402
|
try {
|
|
34581
|
-
const cwd = JSON.parse(
|
|
34582
|
-
if (typeof cwd === "string" &&
|
|
35403
|
+
const cwd = JSON.parse(line2).cwd;
|
|
35404
|
+
if (typeof cwd === "string" && statSync3(cwd).isDirectory()) return cwd;
|
|
34583
35405
|
} catch {
|
|
34584
35406
|
continue;
|
|
34585
35407
|
}
|
|
@@ -34596,10 +35418,9 @@ function cursorWorkspace(nativeId) {
|
|
|
34596
35418
|
} catch {
|
|
34597
35419
|
return void 0;
|
|
34598
35420
|
}
|
|
34599
|
-
const dir = dirs.find((d3) => existsSync7(
|
|
35421
|
+
const dir = dirs.find((d3) => existsSync7(join24(root, d3, "agent-transcripts", nativeId)));
|
|
34600
35422
|
return dir ? decodeWorkspace(dir) : void 0;
|
|
34601
35423
|
}
|
|
34602
|
-
var onPath3 = (cmd) => (process.env.PATH ?? "").split(delimiter3).some((d3) => d3 && existsSync7(join23(d3, cmd)));
|
|
34603
35424
|
function resumeCommand(ref) {
|
|
34604
35425
|
if (!ref || !SESSION_ID.test(ref.nativeId)) return { ok: false, message: "this session cannot be resumed", tone: "dim" };
|
|
34605
35426
|
const id = ref.nativeId;
|
|
@@ -34612,14 +35433,14 @@ function resumeCommand(ref) {
|
|
|
34612
35433
|
const dir = cursorWorkspace(id);
|
|
34613
35434
|
if (!dir) return { ok: false, message: "this Cursor chat has no workspace folder on this machine", tone: "dim" };
|
|
34614
35435
|
const done = `opened ${toCells(basename8(dir))} in Cursor \xB7 the chat is in its agent history`;
|
|
34615
|
-
if (
|
|
35436
|
+
if (findOnPath("cursor")) return { cmd: "cursor", args: [dir], done };
|
|
34616
35437
|
if (process.platform === "darwin") return { cmd: "open", args: ["-a", "Cursor", dir], done };
|
|
34617
35438
|
return { ok: false, message: `open ${toCells(dir)} in Cursor; the chat is in its agent history`, tone: "dim" };
|
|
34618
35439
|
}
|
|
34619
35440
|
|
|
34620
35441
|
// ../../packages/tui/src/live/workflows.ts
|
|
34621
35442
|
var MAX_EVIDENCE = 12;
|
|
34622
|
-
var plural4 = (n, one, many = `${one}s`) => `${
|
|
35443
|
+
var plural4 = (n, one, many = `${one}s`) => `${count2(n)} ${n === 1 ? one : many}`;
|
|
34623
35444
|
function workflowMarkdown(s) {
|
|
34624
35445
|
const tools = SOURCE_IDS.filter((x2) => s.sources[x2]).map((x2) => `${TOOL_OF[x2]} ${s.sources[x2]}`);
|
|
34625
35446
|
const L3 = [`# ${s.title}`, "", s.description, ""];
|
|
@@ -34627,7 +35448,7 @@ function workflowMarkdown(s) {
|
|
|
34627
35448
|
L3.push(`confidence ${s.confidence.toFixed(2)} \xB7 verified in ${Math.round(s.verifiedRate * 100)}% of runs`);
|
|
34628
35449
|
const cost = [];
|
|
34629
35450
|
if (s.cost?.medianTokens !== void 0) cost.push(`median ${tok2(s.cost.medianTokens)} tokens`);
|
|
34630
|
-
if (s.cost?.medianToolCalls !== void 0) cost.push(`median ${
|
|
35451
|
+
if (s.cost?.medianToolCalls !== void 0) cost.push(`median ${count2(s.cost.medianToolCalls)} tool calls`);
|
|
34631
35452
|
if (s.medianMinutes !== void 0) cost.push(`median ${s.medianMinutes < 120 ? `${Math.round(s.medianMinutes)} min` : `${(s.medianMinutes / 60).toFixed(1)} h`}`);
|
|
34632
35453
|
if (cost.length) L3.push(`${cost.join(" \xB7 ")} per run`);
|
|
34633
35454
|
L3.push("", "## Steps", "");
|
|
@@ -34649,7 +35470,7 @@ function workflowMarkdown(s) {
|
|
|
34649
35470
|
const date5 = e2.date ? dayLabel(new Date(e2.date)) : "\u2014";
|
|
34650
35471
|
L3.push(`- ${date5} ${TOOL_OF[e2.source]} ${e2.project ?? "\u2014"} ${e2.excerpt}`);
|
|
34651
35472
|
}
|
|
34652
|
-
if (s.evidence.length > MAX_EVIDENCE) L3.push(`- +${
|
|
35473
|
+
if (s.evidence.length > MAX_EVIDENCE) L3.push(`- +${count2(s.evidence.length - MAX_EVIDENCE)} more (reflex evidence ${s.slug})`);
|
|
34653
35474
|
return L3.map(toCells);
|
|
34654
35475
|
}
|
|
34655
35476
|
function workflowItems(suggestions, skillOf, skills, foundOn) {
|
|
@@ -34801,21 +35622,21 @@ function addCosts(data, c2) {
|
|
|
34801
35622
|
var uniqueSessions = (traces) => [...new Map(traces.map((t) => [t.sessionId, t])).values()];
|
|
34802
35623
|
function totals(traces) {
|
|
34803
35624
|
const usage2 = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
34804
|
-
let
|
|
35625
|
+
let recorded2 = 0;
|
|
34805
35626
|
for (const t of traces) {
|
|
34806
35627
|
if (!t.usage) continue;
|
|
34807
|
-
|
|
35628
|
+
recorded2++;
|
|
34808
35629
|
usage2.input += t.usage.input;
|
|
34809
35630
|
usage2.output += t.usage.output;
|
|
34810
35631
|
usage2.cacheRead += t.usage.cacheRead;
|
|
34811
35632
|
usage2.cacheWrite += t.usage.cacheWrite;
|
|
34812
35633
|
}
|
|
34813
|
-
return { sessions: traces.length, usage: usage2, measured: traces.length === 0 ||
|
|
35634
|
+
return { sessions: traces.length, usage: usage2, measured: traces.length === 0 || recorded2 > 0 };
|
|
34814
35635
|
}
|
|
34815
35636
|
function cursorModels(traces) {
|
|
34816
35637
|
const counts = /* @__PURE__ */ new Map();
|
|
34817
35638
|
for (const t of traces) {
|
|
34818
|
-
const m2 = t.source === "cursor" ? t.models?.[0] : void 0;
|
|
35639
|
+
const m2 = t.source === "cursor" && !t.usage ? t.models?.[0] : void 0;
|
|
34819
35640
|
if (m2) counts.set(m2, (counts.get(m2) ?? 0) + 1);
|
|
34820
35641
|
}
|
|
34821
35642
|
if (!counts.size) return void 0;
|
|
@@ -34861,9 +35682,9 @@ function attention2(items) {
|
|
|
34861
35682
|
return out2;
|
|
34862
35683
|
}
|
|
34863
35684
|
async function agentMemory(store) {
|
|
34864
|
-
const
|
|
35685
|
+
const entries2 = store.memoryEntries().filter((e2) => e2.status === "active").map((e2) => ({ text: toCells(e2.text), sessions: e2.sessions, origin: e2.origin }));
|
|
34865
35686
|
const files = (await memoryTargets()).filter((t) => t.detected).map((t) => toCells(displayPath(t.file)));
|
|
34866
|
-
return { enabled: store.memoryState().enabled, entries, files };
|
|
35687
|
+
return { enabled: store.memoryState().enabled, entries: entries2, files };
|
|
34867
35688
|
}
|
|
34868
35689
|
|
|
34869
35690
|
// src/commands/tui.ts
|
|
@@ -34906,8 +35727,7 @@ async function tui() {
|
|
|
34906
35727
|
|
|
34907
35728
|
// src/main.ts
|
|
34908
35729
|
quietSqliteWarning();
|
|
34909
|
-
|
|
34910
|
-
if (!fetchingModel) installNetworkGuard();
|
|
35730
|
+
installNetworkGuard();
|
|
34911
35731
|
process.stdout.on("error", (err) => {
|
|
34912
35732
|
if (err.code === "EPIPE") process.exit(0);
|
|
34913
35733
|
throw err;
|
|
@@ -34925,7 +35745,7 @@ function run(fn) {
|
|
|
34925
35745
|
};
|
|
34926
35746
|
}
|
|
34927
35747
|
var program2 = new Command();
|
|
34928
|
-
program2.name("reflex").description("Find workflows you keep re-teaching Claude Code, Codex and Cursor, and turn proven repeats into reusable skills. Everything runs locally.").version("0.5.
|
|
35748
|
+
program2.name("reflex").description("Find workflows you keep re-teaching Claude Code, Codex and Cursor, and turn proven repeats into reusable skills. Everything runs locally.").version("0.5.2").allowExcessArguments().action(
|
|
34929
35749
|
run(async () => {
|
|
34930
35750
|
if (program2.args.length) program2.error(`error: unknown command '${program2.args[0]}'. See \`reflex --help\`.`);
|
|
34931
35751
|
if (process.stdin.isTTY && process.stdout.isTTY) await tui();
|
|
@@ -34940,6 +35760,10 @@ program2.command("scan").description("read recent coding-agent history (asks fir
|
|
|
34940
35760
|
);
|
|
34941
35761
|
program2.command("sessions").description("list sessions from the last scan (redacted)").action(run(sessions));
|
|
34942
35762
|
program2.command("agents").description("sessions that launched agents (Cursor), what kinds, and how much work the agents did").action(run(agents));
|
|
35763
|
+
var handbookCmd = program2.command("handbook").description("how work is done in this repository, learned from past sessions (read-only, safe for agents)").option("--project <name>", "a repository by name instead of the current folder").option("--all", "every repository").option("--json", "machine-readable output").action(run(async (o2) => handbook(o2)));
|
|
35764
|
+
handbookCmd.command("show <id>").description("one practice and the sessions behind it").option("--json", "machine-readable output").action(run(async (id, _o, cmd) => handbookShow(id, cmd.optsWithGlobals())));
|
|
35765
|
+
handbookCmd.command("ask <question...>").description("practices that answer a question, with their sources").option("--project <name>", "a repository by name instead of the current folder").option("--json", "machine-readable output").action(run(async (q2, _o, cmd) => handbookAsk(q2, cmd.optsWithGlobals())));
|
|
35766
|
+
handbookCmd.command("export").description("a Markdown handbook for a teammate or new hire (no request text)").option("--project <name>", "a repository by name instead of the current folder").option("--all", "every repository").action(run(async (_o, cmd) => handbookExport(cmd.optsWithGlobals())));
|
|
34943
35767
|
program2.command("suggest").description("detect repeated workflows and review them").option("--all", "include rejected suggestions").option("--no-interactive", "print suggestions without the review prompt").action(run(suggest));
|
|
34944
35768
|
program2.command("show <suggestion>").description("show a suggestion in detail (number or name)").action(run(show));
|
|
34945
35769
|
program2.command("evidence <suggestion>").description("show the sessions behind a suggestion").action(run(evidence));
|
|
@@ -34971,6 +35795,10 @@ route.command("status", { isDefault: true }).description("show picks, settings,
|
|
|
34971
35795
|
route.command("autopilot <state>").description("on: reflex run starts on the pick without asking; off: it asks").action(run(routeAutopilot));
|
|
34972
35796
|
route.command("explore <percent>").description("try another model you use on this share of reflex runs, chosen at random (off to stop)").option("--protect <kind...>", "kinds of task never explored: review, ci, debug, feature, edit, research, explore").action(run(async (value, o2) => routeExplore(value, o2)));
|
|
34973
35797
|
program2.command("bench <task...>").description("run one task on several Claude Code models, each in a fresh copy of this repository, scored by your check command").requiredOption("--models <model...>", "models to compare, e.g. sonnet opus").requiredOption("--check <command>", 'command that passes (exit 0) when the task is done, e.g. "pnpm test"').option("--setup <command>", 'command to prepare each copy, e.g. "pnpm install --frozen-lockfile"').option("--runs <n>", "runs per model", "1").option("--timeout <minutes>", "time limit per run", "20").option("--keep", "keep the copies for inspection").option("-y, --yes", "start without asking").action(run(async (words2, o2) => bench(words2, o2)));
|
|
35798
|
+
var cursorUsage = program2.command("cursor-usage").description("record Cursor's token counts locally through a Cursor hook (Cursor saves none in its transcripts)");
|
|
35799
|
+
cursorUsage.command("status", { isDefault: true }).description("whether the hook is on and what it has recorded").action(run(cursorUsageStatus));
|
|
35800
|
+
cursorUsage.command("on").description("add Reflex's hook to ~/.cursor/hooks.json (asks first; keeps your other hooks)").option("-y, --yes", "add it without prompting").action(run(cursorUsageOn));
|
|
35801
|
+
cursorUsage.command("off").description("remove Reflex's hook; recorded counts stay").action(run(cursorUsageOff));
|
|
34974
35802
|
program2.command("stats").description("defensible counts from local data").action(run(stats2));
|
|
34975
35803
|
program2.command("reset").description("delete Reflex's own local data (not installed skills)").option("-y, --yes", "consent without prompting").action(run(reset));
|
|
34976
35804
|
await program2.parseAsync(process.argv);
|