aipeek 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-3NVB3GGE.cjs → chunk-5ZZYOETF.cjs} +99 -131
- package/dist/{chunk-72ZKZ42D.js → chunk-XA2LT6I4.js} +92 -124
- package/dist/index.cjs +2 -2
- package/dist/index.js +1 -1
- package/dist/plugin.cjs +8 -2
- package/dist/plugin.js +9 -3
- package/package.json +2 -1
- package/src/client/client-patch.ts +35 -3
- package/src/client/client.ts +7 -17
- package/src/core/action.ts +54 -1
- package/src/core/compact.ts +4 -30
- package/src/core/detail.ts +10 -26
- package/src/core/util.ts +53 -0
- package/src/server/plugin.ts +39 -93
|
@@ -71,13 +71,54 @@ function check(raw) {
|
|
|
71
71
|
function truncate(s, max) {
|
|
72
72
|
return s.length > max ? `${s.slice(0, max)}\u2026` : s;
|
|
73
73
|
}
|
|
74
|
+
function formatValue(v, seen = /* @__PURE__ */ new Set()) {
|
|
75
|
+
if (v === null || v === void 0)
|
|
76
|
+
return String(v);
|
|
77
|
+
const t = typeof v;
|
|
78
|
+
if (t === "string")
|
|
79
|
+
return v;
|
|
80
|
+
if (t === "number" || t === "boolean" || t === "bigint")
|
|
81
|
+
return String(v);
|
|
82
|
+
if (t === "symbol")
|
|
83
|
+
return v.toString();
|
|
84
|
+
if (t === "function")
|
|
85
|
+
return `[Function: ${v.name || "anonymous"}]`;
|
|
86
|
+
const obj = v;
|
|
87
|
+
if (seen.has(obj))
|
|
88
|
+
return "[Circular]";
|
|
89
|
+
if (v instanceof Error)
|
|
90
|
+
return v.stack || `${v.name}: ${v.message}`;
|
|
91
|
+
seen.add(obj);
|
|
92
|
+
if (v instanceof Map) {
|
|
93
|
+
const items = [...v.entries()].slice(0, 15).map(([k, val]) => `${formatValue(k, seen)} => ${formatValue(val, seen)}`);
|
|
94
|
+
return `Map(${v.size}) {${items.join(", ")}${v.size > 15 ? ", \u2026" : ""}}`;
|
|
95
|
+
}
|
|
96
|
+
if (v instanceof Set) {
|
|
97
|
+
const items = [...v.values()].slice(0, 15).map((val) => formatValue(val, seen));
|
|
98
|
+
return `Set(${v.size}) {${items.join(", ")}${v.size > 15 ? ", \u2026" : ""}}`;
|
|
99
|
+
}
|
|
100
|
+
if (Array.isArray(v)) {
|
|
101
|
+
const items = v.slice(0, 30).map((val) => formatValue(val, seen));
|
|
102
|
+
return `[${items.join(", ")}${v.length > 30 ? ", \u2026" : ""}]`;
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
return JSON.stringify(v);
|
|
106
|
+
} catch (e2) {
|
|
107
|
+
const entries = Object.entries(v).slice(0, 15);
|
|
108
|
+
const parts = entries.map(([k, val]) => `${k}: ${formatValue(val, seen)}`);
|
|
109
|
+
return `{${parts.join(", ")}}`;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function appStackFrames(stack, max) {
|
|
113
|
+
return stack.split("\n").map((l) => l.trim()).filter((l) => l.startsWith("at ") && !l.includes("node_modules") && !l.includes("<anonymous>")).slice(0, max);
|
|
114
|
+
}
|
|
74
115
|
function compactUrl(url, search) {
|
|
75
116
|
try {
|
|
76
117
|
const u = new URL(url);
|
|
77
118
|
if (search && u.search)
|
|
78
119
|
return `${u.pathname}?${truncate(u.search.slice(1), search)}`;
|
|
79
120
|
return u.pathname;
|
|
80
|
-
} catch (
|
|
121
|
+
} catch (e3) {
|
|
81
122
|
return truncate(url, 80);
|
|
82
123
|
}
|
|
83
124
|
}
|
|
@@ -249,7 +290,7 @@ function isApiUrl(url) {
|
|
|
249
290
|
try {
|
|
250
291
|
const u = new URL(url);
|
|
251
292
|
return u.pathname.startsWith("/api") || u.pathname.includes("/graphql");
|
|
252
|
-
} catch (
|
|
293
|
+
} catch (e4) {
|
|
253
294
|
return false;
|
|
254
295
|
}
|
|
255
296
|
}
|
|
@@ -287,17 +328,12 @@ function compactErrors(errors) {
|
|
|
287
328
|
for (const err of seen.values()) {
|
|
288
329
|
lines.push(err.message);
|
|
289
330
|
if (err.stack) {
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
lines.push(` at ${frame}`);
|
|
293
|
-
}
|
|
331
|
+
for (const frame of appStackFrames(err.stack, 5))
|
|
332
|
+
lines.push(` ${frame}`);
|
|
294
333
|
}
|
|
295
334
|
}
|
|
296
335
|
return lines.join("\n");
|
|
297
336
|
}
|
|
298
|
-
function filterStack(stack) {
|
|
299
|
-
return stack.split("\n").map((l) => l.trim()).filter((l) => l.startsWith("at ")).map((l) => l.slice(3)).filter((l) => !l.includes("node_modules") && !l.includes("<anonymous>")).slice(0, 5);
|
|
300
|
-
}
|
|
301
337
|
function compactState(state) {
|
|
302
338
|
if (!state || !Object.keys(state).length)
|
|
303
339
|
return "";
|
|
@@ -306,7 +342,7 @@ function compactState(state) {
|
|
|
306
342
|
lines.push(`${name}:`);
|
|
307
343
|
if (typeof value === "object" && value !== null) {
|
|
308
344
|
for (const [k, v] of Object.entries(value)) {
|
|
309
|
-
lines.push(` ${k}: ${formatValue(v)}`);
|
|
345
|
+
lines.push(` ${k}: ${truncate(formatValue(v), 120)}`);
|
|
310
346
|
}
|
|
311
347
|
} else {
|
|
312
348
|
lines.push(` ${String(value)}`);
|
|
@@ -314,19 +350,6 @@ function compactState(state) {
|
|
|
314
350
|
}
|
|
315
351
|
return lines.join("\n");
|
|
316
352
|
}
|
|
317
|
-
function formatValue(v) {
|
|
318
|
-
if (v === null || v === void 0)
|
|
319
|
-
return String(v);
|
|
320
|
-
if (typeof v === "string")
|
|
321
|
-
return v;
|
|
322
|
-
if (typeof v === "number" || typeof v === "boolean")
|
|
323
|
-
return String(v);
|
|
324
|
-
if (typeof v === "object") {
|
|
325
|
-
const s = JSON.stringify(v);
|
|
326
|
-
return s.length > 120 ? `${s.slice(0, 120)}\u2026` : s;
|
|
327
|
-
}
|
|
328
|
-
return String(v);
|
|
329
|
-
}
|
|
330
353
|
function compact(raw) {
|
|
331
354
|
return {
|
|
332
355
|
url: raw.url,
|
|
@@ -463,12 +486,10 @@ function detailError(errors, index, full) {
|
|
|
463
486
|
}
|
|
464
487
|
const lines = [err.message];
|
|
465
488
|
if (err.stack) {
|
|
466
|
-
const
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
if (totalApp > 3)
|
|
471
|
-
lines.push(` ... ${totalApp - 3} more app frames`);
|
|
489
|
+
const all = appStackFrames(err.stack, Infinity);
|
|
490
|
+
lines.push(...all.slice(0, 3));
|
|
491
|
+
if (all.length > 3)
|
|
492
|
+
lines.push(` ... ${all.length - 3} more app frames`);
|
|
472
493
|
}
|
|
473
494
|
if (err.line != null)
|
|
474
495
|
lines.push(`location: ${err.source || ""}:${err.line}:${_nullishCoalesce(err.column, () => ( 0))}`);
|
|
@@ -486,9 +507,9 @@ function detailState(state, name, full) {
|
|
|
486
507
|
const value = state[name];
|
|
487
508
|
if (full) {
|
|
488
509
|
try {
|
|
489
|
-
return JSON.stringify(value, null, 2);
|
|
490
|
-
} catch (
|
|
491
|
-
return
|
|
510
|
+
return _nullishCoalesce(JSON.stringify(value, null, 2), () => ( formatValue(value)));
|
|
511
|
+
} catch (e5) {
|
|
512
|
+
return formatValue(value);
|
|
492
513
|
}
|
|
493
514
|
}
|
|
494
515
|
if (typeof value !== "object" || value === null)
|
|
@@ -506,25 +527,14 @@ function isArraySentinel(v) {
|
|
|
506
527
|
return digits.length > 0 && [...digits].every((c) => c >= "0" && c <= "9");
|
|
507
528
|
}
|
|
508
529
|
function formatSummaryValue(v) {
|
|
509
|
-
if (v ===
|
|
510
|
-
return
|
|
511
|
-
|
|
512
|
-
if (isArraySentinel(v))
|
|
513
|
-
return v;
|
|
514
|
-
return v.length > 80 ? `${v.slice(0, 80)}\u2026` : v;
|
|
515
|
-
}
|
|
516
|
-
if (typeof v === "number" || typeof v === "boolean")
|
|
517
|
-
return String(v);
|
|
518
|
-
if (typeof v === "object") {
|
|
519
|
-
const s = JSON.stringify(v);
|
|
520
|
-
return s.length > 80 ? `${s.slice(0, 80)}\u2026` : s;
|
|
521
|
-
}
|
|
522
|
-
return String(v);
|
|
530
|
+
if (typeof v === "string" && isArraySentinel(v))
|
|
531
|
+
return v;
|
|
532
|
+
return truncate(formatValue(v), 80);
|
|
523
533
|
}
|
|
524
534
|
function jsonSchema(sample) {
|
|
525
535
|
try {
|
|
526
536
|
return schemaOf(JSON.parse(sample), 0);
|
|
527
|
-
} catch (
|
|
537
|
+
} catch (e6) {
|
|
528
538
|
return null;
|
|
529
539
|
}
|
|
530
540
|
}
|
|
@@ -753,6 +763,10 @@ function readBody(req) {
|
|
|
753
763
|
req.on("end", () => resolve2(s));
|
|
754
764
|
});
|
|
755
765
|
}
|
|
766
|
+
function send(res, status, body) {
|
|
767
|
+
res.writeHead(status, { "Content-Type": "text/plain; charset=utf-8" });
|
|
768
|
+
res.end(body);
|
|
769
|
+
}
|
|
756
770
|
var __dirname = _path.dirname.call(void 0, _url.fileURLToPath.call(void 0, _chunkZ2Y65YOYcjs.importMetaUrl));
|
|
757
771
|
var clientDir = _fs.existsSync.call(void 0, _path.resolve.call(void 0, __dirname, "../client")) ? _path.resolve.call(void 0, __dirname, "../client") : _path.resolve.call(void 0, __dirname, "../src/client");
|
|
758
772
|
var clientPath = _path.resolve.call(void 0, clientDir, "client.ts");
|
|
@@ -830,62 +844,30 @@ JS in the page and returns the result \u2014 for anything the typed endpoints ca
|
|
|
830
844
|
aipeek auto-detects errors after HMR and prints them to the terminal \u2014 watch for \`[aipeek]\` messages.
|
|
831
845
|
`;
|
|
832
846
|
}
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
const i = t.indexOf("localhost:");
|
|
836
|
-
if (i === -1)
|
|
837
|
-
return t;
|
|
838
|
-
let j = i + "localhost:".length;
|
|
839
|
-
while (j < t.length && t[j] >= "0" && t[j] <= "9") j++;
|
|
840
|
-
return `${t.slice(0, i)}localhost:PORT${t.slice(j)}`;
|
|
841
|
-
}
|
|
842
|
-
function stripBlocks(content, snippet) {
|
|
843
|
-
const known = new Set(snippet.split("\n").map(norm).filter((l) => l.length > 3));
|
|
844
|
-
const lines = content.split("\n");
|
|
845
|
-
const keep = [];
|
|
846
|
-
let inside = false;
|
|
847
|
-
let buf = [];
|
|
848
|
-
let hits = 0;
|
|
849
|
-
const flush = () => {
|
|
850
|
-
if (buf.length && hits / buf.length <= 0.5)
|
|
851
|
-
keep.push(...buf);
|
|
852
|
-
buf = [];
|
|
853
|
-
hits = 0;
|
|
854
|
-
inside = false;
|
|
855
|
-
};
|
|
856
|
-
for (const line of lines) {
|
|
857
|
-
const isKnown = known.has(norm(line));
|
|
858
|
-
if (!inside) {
|
|
859
|
-
if (isKnown) {
|
|
860
|
-
inside = true;
|
|
861
|
-
buf = [line];
|
|
862
|
-
hits = 1;
|
|
863
|
-
} else {
|
|
864
|
-
keep.push(line);
|
|
865
|
-
}
|
|
866
|
-
continue;
|
|
867
|
-
}
|
|
868
|
-
buf.push(line);
|
|
869
|
-
if (isKnown)
|
|
870
|
-
hits++;
|
|
871
|
-
else if (buf.slice(-3).every((l) => !known.has(norm(l))))
|
|
872
|
-
flush();
|
|
873
|
-
}
|
|
874
|
-
flush();
|
|
875
|
-
return keep.join("\n");
|
|
876
|
-
}
|
|
847
|
+
var START_TAG = "<!-- AIPEEK:START -->";
|
|
848
|
+
var END_TAG = "<!-- AIPEEK:END -->";
|
|
877
849
|
function injectClaudeMd(root, port) {
|
|
878
850
|
const path = _path.resolve.call(void 0, root, "CLAUDE.md");
|
|
879
|
-
const
|
|
851
|
+
const block = `${START_TAG}
|
|
852
|
+
${aipeekSnippet(port).trim()}
|
|
853
|
+
${END_TAG}
|
|
854
|
+
`;
|
|
880
855
|
try {
|
|
881
856
|
if (!_fs.existsSync.call(void 0, path)) {
|
|
882
|
-
_fs.writeFileSync.call(void 0, path,
|
|
857
|
+
_fs.writeFileSync.call(void 0, path, block);
|
|
883
858
|
return;
|
|
884
859
|
}
|
|
885
|
-
const
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
860
|
+
const content = _fs.readFileSync.call(void 0, path, "utf-8");
|
|
861
|
+
const si = content.indexOf(START_TAG);
|
|
862
|
+
const ei = content.indexOf(END_TAG);
|
|
863
|
+
if (si !== -1 && ei !== -1) {
|
|
864
|
+
_fs.writeFileSync.call(void 0, path, content.slice(0, si) + block.trimEnd() + content.slice(ei + END_TAG.length));
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
const sep = content.endsWith("\n") ? "" : "\n";
|
|
868
|
+
_fs.writeFileSync.call(void 0, path, `${content}${sep}
|
|
869
|
+
${block}`);
|
|
870
|
+
} catch (e7) {
|
|
889
871
|
}
|
|
890
872
|
}
|
|
891
873
|
function aipeekPlugin() {
|
|
@@ -1033,7 +1015,7 @@ function aipeekPlugin() {
|
|
|
1033
1015
|
if (msg)
|
|
1034
1016
|
server.config.logger.warn(msg);
|
|
1035
1017
|
}
|
|
1036
|
-
} catch (
|
|
1018
|
+
} catch (e8) {
|
|
1037
1019
|
}
|
|
1038
1020
|
}, 500);
|
|
1039
1021
|
});
|
|
@@ -1047,13 +1029,11 @@ function aipeekPlugin() {
|
|
|
1047
1029
|
if (!code && req.method === "POST")
|
|
1048
1030
|
code = await readBody(req);
|
|
1049
1031
|
if (!code) {
|
|
1050
|
-
res
|
|
1051
|
-
res.end("eval needs ?code= or a POST body");
|
|
1032
|
+
send(res, 400, "eval needs ?code= or a POST body");
|
|
1052
1033
|
return;
|
|
1053
1034
|
}
|
|
1054
1035
|
const r = await evalInClient(code);
|
|
1055
|
-
res
|
|
1056
|
-
res.end(r.ok ? _nullishCoalesce(r.value, () => ( "undefined")) : `error: ${r.error}`);
|
|
1036
|
+
send(res, r.ok ? 200 : 422, r.ok ? _nullishCoalesce(r.value, () => ( "undefined")) : `error: ${r.error}`);
|
|
1057
1037
|
return;
|
|
1058
1038
|
}
|
|
1059
1039
|
if (parts[0] === "dom") {
|
|
@@ -1061,14 +1041,12 @@ function aipeekPlugin() {
|
|
|
1061
1041
|
url.searchParams.get("scope") || void 0,
|
|
1062
1042
|
url.searchParams.get("sel") || void 0
|
|
1063
1043
|
);
|
|
1064
|
-
res
|
|
1065
|
-
res.end(dom || "(empty)");
|
|
1044
|
+
send(res, 200, dom || "(empty)");
|
|
1066
1045
|
return;
|
|
1067
1046
|
}
|
|
1068
1047
|
if (parts[0] === "screen") {
|
|
1069
1048
|
const screen = await collectScreenFromClient();
|
|
1070
|
-
res
|
|
1071
|
-
res.end(screen || "(empty)");
|
|
1049
|
+
send(res, 200, screen || "(empty)");
|
|
1072
1050
|
return;
|
|
1073
1051
|
}
|
|
1074
1052
|
if (parts[0] === "chain") {
|
|
@@ -1079,8 +1057,7 @@ function aipeekPlugin() {
|
|
|
1079
1057
|
if (!Array.isArray(steps))
|
|
1080
1058
|
throw new Error("body must be a JSON array");
|
|
1081
1059
|
} catch (e) {
|
|
1082
|
-
res
|
|
1083
|
-
res.end(`invalid chain body: ${e instanceof Error ? e.message : String(e)}`);
|
|
1060
|
+
send(res, 400, `invalid chain body: ${e instanceof Error ? e.message : String(e)}`);
|
|
1084
1061
|
return;
|
|
1085
1062
|
}
|
|
1086
1063
|
lastRaw = null;
|
|
@@ -1106,8 +1083,7 @@ function aipeekPlugin() {
|
|
|
1106
1083
|
break;
|
|
1107
1084
|
}
|
|
1108
1085
|
}
|
|
1109
|
-
res
|
|
1110
|
-
res.end(lastUi ? `${lines.join("\n")}
|
|
1086
|
+
send(res, allOk ? 200 : 422, lastUi ? `${lines.join("\n")}
|
|
1111
1087
|
|
|
1112
1088
|
--- ui after ---
|
|
1113
1089
|
${lastUi}` : lines.join("\n"));
|
|
@@ -1125,8 +1101,7 @@ ${lastUi}` : lines.join("\n"));
|
|
|
1125
1101
|
};
|
|
1126
1102
|
const check2 = resolveAction(parts[0], args);
|
|
1127
1103
|
if (!check2.valid) {
|
|
1128
|
-
res
|
|
1129
|
-
res.end(check2.error);
|
|
1104
|
+
send(res, 400, _nullishCoalesce(check2.error, () => ( "invalid action")));
|
|
1130
1105
|
return;
|
|
1131
1106
|
}
|
|
1132
1107
|
const result = await sendAction(parts[0], args);
|
|
@@ -1137,15 +1112,13 @@ ${lastUi}` : lines.join("\n"));
|
|
|
1137
1112
|
const name = q.get("out") || `shot-${result.dataUrl.length}.png`;
|
|
1138
1113
|
const file = _path.resolve.call(void 0, dir, name);
|
|
1139
1114
|
_fs.writeFileSync.call(void 0, file, _buffer.Buffer.from(result.dataUrl.split(",")[1], "base64"));
|
|
1140
|
-
res
|
|
1141
|
-
res.end(`saved: ${file}`);
|
|
1115
|
+
send(res, 200, `saved: ${file}`);
|
|
1142
1116
|
return;
|
|
1143
1117
|
}
|
|
1144
|
-
res.writeHead(result.ok ? 200 : 422, { "Content-Type": "text/plain; charset=utf-8" });
|
|
1145
1118
|
const head = result.ok ? result.detail || "ok" : `${result.error}${result.detail ? `
|
|
1146
1119
|
|
|
1147
1120
|
clickable: ${result.detail}` : ""}`;
|
|
1148
|
-
res.
|
|
1121
|
+
send(res, result.ok ? 200 : 422, result.ui ? `${head}
|
|
1149
1122
|
|
|
1150
1123
|
--- ui after ---
|
|
1151
1124
|
${result.ui}` : head);
|
|
@@ -1156,8 +1129,7 @@ ${result.ui}` : head);
|
|
|
1156
1129
|
lastRaw = raw2;
|
|
1157
1130
|
const result = check(raw2);
|
|
1158
1131
|
const output = emitCheck(result);
|
|
1159
|
-
res
|
|
1160
|
-
res.end(output);
|
|
1132
|
+
send(res, result.pass ? 200 : 417, output);
|
|
1161
1133
|
return;
|
|
1162
1134
|
}
|
|
1163
1135
|
if (parts.length >= 1) {
|
|
@@ -1165,29 +1137,22 @@ ${result.ui}` : head);
|
|
|
1165
1137
|
lastRaw = await collectFromClient();
|
|
1166
1138
|
const result = detail(lastRaw, parts[0], parts[1], full);
|
|
1167
1139
|
if (result !== null) {
|
|
1168
|
-
res
|
|
1169
|
-
res.end(result);
|
|
1140
|
+
send(res, 200, result);
|
|
1170
1141
|
return;
|
|
1171
1142
|
}
|
|
1172
|
-
res
|
|
1173
|
-
res.end(`not found: ${parts.join("/")}`);
|
|
1143
|
+
send(res, 404, `not found: ${parts.join("/")}`);
|
|
1174
1144
|
return;
|
|
1175
1145
|
}
|
|
1176
1146
|
const raw = await collectFromClient();
|
|
1177
1147
|
lastRaw = raw;
|
|
1178
1148
|
if (full) {
|
|
1179
1149
|
const compacted = compact(raw);
|
|
1180
|
-
|
|
1181
|
-
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
|
|
1182
|
-
res.end(output);
|
|
1150
|
+
send(res, 200, emit(compacted));
|
|
1183
1151
|
} else {
|
|
1184
|
-
|
|
1185
|
-
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
|
|
1186
|
-
res.end(output);
|
|
1152
|
+
send(res, 200, emitSummary(raw));
|
|
1187
1153
|
}
|
|
1188
1154
|
} catch (err) {
|
|
1189
|
-
res
|
|
1190
|
-
res.end(err instanceof Error ? err.message : "unknown error");
|
|
1155
|
+
send(res, 504, err instanceof Error ? err.message : "unknown error");
|
|
1191
1156
|
}
|
|
1192
1157
|
});
|
|
1193
1158
|
}
|
|
@@ -1201,4 +1166,7 @@ ${result.ui}` : head);
|
|
|
1201
1166
|
|
|
1202
1167
|
|
|
1203
1168
|
|
|
1204
|
-
|
|
1169
|
+
|
|
1170
|
+
|
|
1171
|
+
|
|
1172
|
+
exports.check = check; exports.diffState = diffState; exports.emitSummary = emitSummary; exports.emitCheck = emitCheck; exports.emitDiff = emitDiff; exports.START_TAG = START_TAG; exports.END_TAG = END_TAG; exports.injectClaudeMd = injectClaudeMd; exports.aipeekPlugin = aipeekPlugin;
|