eminiar 0.10.0 → 0.11.0
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/.claude-plugin/plugin.json +1 -1
- package/.cursor-plugin/mcp.json +11 -0
- package/.cursor-plugin/plugin.json +23 -0
- package/README.md +12 -8
- package/dist/cli.js +809 -451
- package/dist/hook.js +848 -504
- package/dist/server.js +247 -57
- package/hooks/cursor.json +36 -0
- package/package.json +7 -4
- package/rules/eminiar.mdc +15 -0
- package/skills/em-docs/SKILL.md +3 -1
package/dist/hook.js
CHANGED
|
@@ -174,14 +174,14 @@ var require_is_extglob = __commonJS({
|
|
|
174
174
|
"node_modules/is-extglob/index.js"(exports, module) {
|
|
175
175
|
"use strict";
|
|
176
176
|
init_esm_shims();
|
|
177
|
-
module.exports = function isExtglob(
|
|
178
|
-
if (typeof
|
|
177
|
+
module.exports = function isExtglob(str3) {
|
|
178
|
+
if (typeof str3 !== "string" || str3 === "") {
|
|
179
179
|
return false;
|
|
180
180
|
}
|
|
181
181
|
var match;
|
|
182
|
-
while (match = /(\\).|([@?!+*]\(.*\))/g.exec(
|
|
182
|
+
while (match = /(\\).|([@?!+*]\(.*\))/g.exec(str3)) {
|
|
183
183
|
if (match[2]) return true;
|
|
184
|
-
|
|
184
|
+
str3 = str3.slice(match.index + match[0].length);
|
|
185
185
|
}
|
|
186
186
|
return false;
|
|
187
187
|
};
|
|
@@ -195,8 +195,8 @@ var require_is_glob = __commonJS({
|
|
|
195
195
|
init_esm_shims();
|
|
196
196
|
var isExtglob = require_is_extglob();
|
|
197
197
|
var chars = { "{": "}", "(": ")", "[": "]" };
|
|
198
|
-
var strictCheck = function(
|
|
199
|
-
if (
|
|
198
|
+
var strictCheck = function(str3) {
|
|
199
|
+
if (str3[0] === "!") {
|
|
200
200
|
return true;
|
|
201
201
|
}
|
|
202
202
|
var index = 0;
|
|
@@ -205,70 +205,70 @@ var require_is_glob = __commonJS({
|
|
|
205
205
|
var closeCurlyIndex = -2;
|
|
206
206
|
var closeParenIndex = -2;
|
|
207
207
|
var backSlashIndex = -2;
|
|
208
|
-
while (index <
|
|
209
|
-
if (
|
|
208
|
+
while (index < str3.length) {
|
|
209
|
+
if (str3[index] === "*") {
|
|
210
210
|
return true;
|
|
211
211
|
}
|
|
212
|
-
if (
|
|
212
|
+
if (str3[index + 1] === "?" && /[\].+)]/.test(str3[index])) {
|
|
213
213
|
return true;
|
|
214
214
|
}
|
|
215
|
-
if (closeSquareIndex !== -1 &&
|
|
215
|
+
if (closeSquareIndex !== -1 && str3[index] === "[" && str3[index + 1] !== "]") {
|
|
216
216
|
if (closeSquareIndex < index) {
|
|
217
|
-
closeSquareIndex =
|
|
217
|
+
closeSquareIndex = str3.indexOf("]", index);
|
|
218
218
|
}
|
|
219
219
|
if (closeSquareIndex > index) {
|
|
220
220
|
if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) {
|
|
221
221
|
return true;
|
|
222
222
|
}
|
|
223
|
-
backSlashIndex =
|
|
223
|
+
backSlashIndex = str3.indexOf("\\", index);
|
|
224
224
|
if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) {
|
|
225
225
|
return true;
|
|
226
226
|
}
|
|
227
227
|
}
|
|
228
228
|
}
|
|
229
|
-
if (closeCurlyIndex !== -1 &&
|
|
230
|
-
closeCurlyIndex =
|
|
229
|
+
if (closeCurlyIndex !== -1 && str3[index] === "{" && str3[index + 1] !== "}") {
|
|
230
|
+
closeCurlyIndex = str3.indexOf("}", index);
|
|
231
231
|
if (closeCurlyIndex > index) {
|
|
232
|
-
backSlashIndex =
|
|
232
|
+
backSlashIndex = str3.indexOf("\\", index);
|
|
233
233
|
if (backSlashIndex === -1 || backSlashIndex > closeCurlyIndex) {
|
|
234
234
|
return true;
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
|
-
if (closeParenIndex !== -1 &&
|
|
239
|
-
closeParenIndex =
|
|
238
|
+
if (closeParenIndex !== -1 && str3[index] === "(" && str3[index + 1] === "?" && /[:!=]/.test(str3[index + 2]) && str3[index + 3] !== ")") {
|
|
239
|
+
closeParenIndex = str3.indexOf(")", index);
|
|
240
240
|
if (closeParenIndex > index) {
|
|
241
|
-
backSlashIndex =
|
|
241
|
+
backSlashIndex = str3.indexOf("\\", index);
|
|
242
242
|
if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) {
|
|
243
243
|
return true;
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
246
|
}
|
|
247
|
-
if (pipeIndex !== -1 &&
|
|
247
|
+
if (pipeIndex !== -1 && str3[index] === "(" && str3[index + 1] !== "|") {
|
|
248
248
|
if (pipeIndex < index) {
|
|
249
|
-
pipeIndex =
|
|
249
|
+
pipeIndex = str3.indexOf("|", index);
|
|
250
250
|
}
|
|
251
|
-
if (pipeIndex !== -1 &&
|
|
252
|
-
closeParenIndex =
|
|
251
|
+
if (pipeIndex !== -1 && str3[pipeIndex + 1] !== ")") {
|
|
252
|
+
closeParenIndex = str3.indexOf(")", pipeIndex);
|
|
253
253
|
if (closeParenIndex > pipeIndex) {
|
|
254
|
-
backSlashIndex =
|
|
254
|
+
backSlashIndex = str3.indexOf("\\", pipeIndex);
|
|
255
255
|
if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) {
|
|
256
256
|
return true;
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
259
|
}
|
|
260
260
|
}
|
|
261
|
-
if (
|
|
262
|
-
var open4 =
|
|
261
|
+
if (str3[index] === "\\") {
|
|
262
|
+
var open4 = str3[index + 1];
|
|
263
263
|
index += 2;
|
|
264
264
|
var close = chars[open4];
|
|
265
265
|
if (close) {
|
|
266
|
-
var n =
|
|
266
|
+
var n = str3.indexOf(close, index);
|
|
267
267
|
if (n !== -1) {
|
|
268
268
|
index = n + 1;
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
|
-
if (
|
|
271
|
+
if (str3[index] === "!") {
|
|
272
272
|
return true;
|
|
273
273
|
}
|
|
274
274
|
} else {
|
|
@@ -277,26 +277,26 @@ var require_is_glob = __commonJS({
|
|
|
277
277
|
}
|
|
278
278
|
return false;
|
|
279
279
|
};
|
|
280
|
-
var relaxedCheck = function(
|
|
281
|
-
if (
|
|
280
|
+
var relaxedCheck = function(str3) {
|
|
281
|
+
if (str3[0] === "!") {
|
|
282
282
|
return true;
|
|
283
283
|
}
|
|
284
284
|
var index = 0;
|
|
285
|
-
while (index <
|
|
286
|
-
if (/[*?{}()[\]]/.test(
|
|
285
|
+
while (index < str3.length) {
|
|
286
|
+
if (/[*?{}()[\]]/.test(str3[index])) {
|
|
287
287
|
return true;
|
|
288
288
|
}
|
|
289
|
-
if (
|
|
290
|
-
var open4 =
|
|
289
|
+
if (str3[index] === "\\") {
|
|
290
|
+
var open4 = str3[index + 1];
|
|
291
291
|
index += 2;
|
|
292
292
|
var close = chars[open4];
|
|
293
293
|
if (close) {
|
|
294
|
-
var n =
|
|
294
|
+
var n = str3.indexOf(close, index);
|
|
295
295
|
if (n !== -1) {
|
|
296
296
|
index = n + 1;
|
|
297
297
|
}
|
|
298
298
|
}
|
|
299
|
-
if (
|
|
299
|
+
if (str3[index] === "!") {
|
|
300
300
|
return true;
|
|
301
301
|
}
|
|
302
302
|
} else {
|
|
@@ -305,18 +305,18 @@ var require_is_glob = __commonJS({
|
|
|
305
305
|
}
|
|
306
306
|
return false;
|
|
307
307
|
};
|
|
308
|
-
module.exports = function isGlob(
|
|
309
|
-
if (typeof
|
|
308
|
+
module.exports = function isGlob(str3, options) {
|
|
309
|
+
if (typeof str3 !== "string" || str3 === "") {
|
|
310
310
|
return false;
|
|
311
311
|
}
|
|
312
|
-
if (isExtglob(
|
|
312
|
+
if (isExtglob(str3)) {
|
|
313
313
|
return true;
|
|
314
314
|
}
|
|
315
315
|
var check2 = strictCheck;
|
|
316
316
|
if (options && options.strict === false) {
|
|
317
317
|
check2 = relaxedCheck;
|
|
318
318
|
}
|
|
319
|
-
return check2(
|
|
319
|
+
return check2(str3);
|
|
320
320
|
};
|
|
321
321
|
}
|
|
322
322
|
});
|
|
@@ -334,19 +334,19 @@ var require_glob_parent = __commonJS({
|
|
|
334
334
|
var enclosure = /[\{\[].*[\}\]]$/;
|
|
335
335
|
var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/;
|
|
336
336
|
var escaped = /\\([\!\*\?\|\[\]\(\)\{\}])/g;
|
|
337
|
-
module.exports = function globParent(
|
|
337
|
+
module.exports = function globParent(str3, opts) {
|
|
338
338
|
var options = Object.assign({ flipBackslashes: true }, opts);
|
|
339
|
-
if (options.flipBackslashes && isWin32 &&
|
|
340
|
-
|
|
339
|
+
if (options.flipBackslashes && isWin32 && str3.indexOf(slash) < 0) {
|
|
340
|
+
str3 = str3.replace(backslash, slash);
|
|
341
341
|
}
|
|
342
|
-
if (enclosure.test(
|
|
343
|
-
|
|
342
|
+
if (enclosure.test(str3)) {
|
|
343
|
+
str3 += slash;
|
|
344
344
|
}
|
|
345
|
-
|
|
345
|
+
str3 += "a";
|
|
346
346
|
do {
|
|
347
|
-
|
|
348
|
-
} while (isGlob(
|
|
349
|
-
return
|
|
347
|
+
str3 = pathPosixDirname(str3);
|
|
348
|
+
} while (isGlob(str3) || globby.test(str3));
|
|
349
|
+
return str3.replace(escaped, "$1");
|
|
350
350
|
};
|
|
351
351
|
}
|
|
352
352
|
});
|
|
@@ -668,8 +668,8 @@ var require_to_regex_range = __commonJS({
|
|
|
668
668
|
function toCharacterClass(a, b, options) {
|
|
669
669
|
return `[${a}${b - a === 1 ? "" : "-"}${b}]`;
|
|
670
670
|
}
|
|
671
|
-
function hasPadding(
|
|
672
|
-
return /^-?(0+)\d/.test(
|
|
671
|
+
function hasPadding(str3) {
|
|
672
|
+
return /^-?(0+)\d/.test(str3);
|
|
673
673
|
}
|
|
674
674
|
function padZeros(value, tok2, options) {
|
|
675
675
|
if (!tok2.isPadded) {
|
|
@@ -1659,12 +1659,12 @@ var require_utils2 = __commonJS({
|
|
|
1659
1659
|
REGEX_SPECIAL_CHARS_GLOBAL
|
|
1660
1660
|
} = require_constants2();
|
|
1661
1661
|
exports.isObject = (val) => val !== null && typeof val === "object" && !Array.isArray(val);
|
|
1662
|
-
exports.hasRegexChars = (
|
|
1663
|
-
exports.isRegexChar = (
|
|
1664
|
-
exports.escapeRegex = (
|
|
1665
|
-
exports.toPosixSlashes = (
|
|
1666
|
-
exports.removeBackslashes = (
|
|
1667
|
-
return
|
|
1662
|
+
exports.hasRegexChars = (str3) => REGEX_SPECIAL_CHARS.test(str3);
|
|
1663
|
+
exports.isRegexChar = (str3) => str3.length === 1 && exports.hasRegexChars(str3);
|
|
1664
|
+
exports.escapeRegex = (str3) => str3.replace(REGEX_SPECIAL_CHARS_GLOBAL, "\\$1");
|
|
1665
|
+
exports.toPosixSlashes = (str3) => str3.replace(REGEX_BACKSLASH, "/");
|
|
1666
|
+
exports.removeBackslashes = (str3) => {
|
|
1667
|
+
return str3.replace(REGEX_REMOVE_BACKSLASH, (match) => {
|
|
1668
1668
|
return match === "\\" ? "" : match;
|
|
1669
1669
|
});
|
|
1670
1670
|
};
|
|
@@ -1760,7 +1760,7 @@ var require_scan = __commonJS({
|
|
|
1760
1760
|
const slashes = [];
|
|
1761
1761
|
const tokens = [];
|
|
1762
1762
|
const parts = [];
|
|
1763
|
-
let
|
|
1763
|
+
let str3 = input2;
|
|
1764
1764
|
let index = -1;
|
|
1765
1765
|
let start = 0;
|
|
1766
1766
|
let lastIndex = 0;
|
|
@@ -1779,10 +1779,10 @@ var require_scan = __commonJS({
|
|
|
1779
1779
|
let code;
|
|
1780
1780
|
let token = { value: "", depth: 0, isGlob: false };
|
|
1781
1781
|
const eos = () => index >= length;
|
|
1782
|
-
const peek = () =>
|
|
1782
|
+
const peek = () => str3.charCodeAt(index + 1);
|
|
1783
1783
|
const advance = () => {
|
|
1784
1784
|
prev = code;
|
|
1785
|
-
return
|
|
1785
|
+
return str3.charCodeAt(++index);
|
|
1786
1786
|
};
|
|
1787
1787
|
while (index < length) {
|
|
1788
1788
|
code = advance();
|
|
@@ -1950,24 +1950,24 @@ var require_scan = __commonJS({
|
|
|
1950
1950
|
isExtglob = false;
|
|
1951
1951
|
isGlob = false;
|
|
1952
1952
|
}
|
|
1953
|
-
let base =
|
|
1953
|
+
let base = str3;
|
|
1954
1954
|
let prefix = "";
|
|
1955
1955
|
let glob = "";
|
|
1956
1956
|
if (start > 0) {
|
|
1957
|
-
prefix =
|
|
1958
|
-
|
|
1957
|
+
prefix = str3.slice(0, start);
|
|
1958
|
+
str3 = str3.slice(start);
|
|
1959
1959
|
lastIndex -= start;
|
|
1960
1960
|
}
|
|
1961
1961
|
if (base && isGlob === true && lastIndex > 0) {
|
|
1962
|
-
base =
|
|
1963
|
-
glob =
|
|
1962
|
+
base = str3.slice(0, lastIndex);
|
|
1963
|
+
glob = str3.slice(lastIndex);
|
|
1964
1964
|
} else if (isGlob === true) {
|
|
1965
1965
|
base = "";
|
|
1966
|
-
glob =
|
|
1966
|
+
glob = str3;
|
|
1967
1967
|
} else {
|
|
1968
|
-
base =
|
|
1968
|
+
base = str3;
|
|
1969
1969
|
}
|
|
1970
|
-
if (base && base !== "" && base !== "/" && base !==
|
|
1970
|
+
if (base && base !== "" && base !== "/" && base !== str3) {
|
|
1971
1971
|
if (isPathSeparator(base.charCodeAt(base.length - 1))) {
|
|
1972
1972
|
base = base.slice(0, -1);
|
|
1973
1973
|
}
|
|
@@ -3003,8 +3003,8 @@ var require_parse2 = __commonJS({
|
|
|
3003
3003
|
if (opts2.noglobstar === true) return star;
|
|
3004
3004
|
return `(${capture}(?:(?!${START_ANCHOR}${opts2.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`;
|
|
3005
3005
|
};
|
|
3006
|
-
const create = (
|
|
3007
|
-
switch (
|
|
3006
|
+
const create = (str3) => {
|
|
3007
|
+
switch (str3) {
|
|
3008
3008
|
case "*":
|
|
3009
3009
|
return `${nodot}${ONE_CHAR}${star}`;
|
|
3010
3010
|
case ".*":
|
|
@@ -3022,7 +3022,7 @@ var require_parse2 = __commonJS({
|
|
|
3022
3022
|
case "**/.*":
|
|
3023
3023
|
return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${DOT_LITERAL}${ONE_CHAR}${star}`;
|
|
3024
3024
|
default: {
|
|
3025
|
-
const match = /^(.*?)\.(\w+)$/.exec(
|
|
3025
|
+
const match = /^(.*?)\.(\w+)$/.exec(str3);
|
|
3026
3026
|
if (!match) return;
|
|
3027
3027
|
const source2 = create(match[1]);
|
|
3028
3028
|
if (!source2) return;
|
|
@@ -3055,9 +3055,9 @@ var require_picomatch = __commonJS({
|
|
|
3055
3055
|
var picomatch = (glob, options, returnState = false) => {
|
|
3056
3056
|
if (Array.isArray(glob)) {
|
|
3057
3057
|
const fns = glob.map((input2) => picomatch(input2, options, returnState));
|
|
3058
|
-
const arrayMatcher = (
|
|
3058
|
+
const arrayMatcher = (str3) => {
|
|
3059
3059
|
for (const isMatch of fns) {
|
|
3060
|
-
const state2 = isMatch(
|
|
3060
|
+
const state2 = isMatch(str3);
|
|
3061
3061
|
if (state2) return state2;
|
|
3062
3062
|
}
|
|
3063
3063
|
return false;
|
|
@@ -3133,7 +3133,7 @@ var require_picomatch = __commonJS({
|
|
|
3133
3133
|
const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options);
|
|
3134
3134
|
return regex.test(path2.basename(input2));
|
|
3135
3135
|
};
|
|
3136
|
-
picomatch.isMatch = (
|
|
3136
|
+
picomatch.isMatch = (str3, patterns, options) => picomatch(patterns, options)(str3);
|
|
3137
3137
|
picomatch.parse = (pattern, options) => {
|
|
3138
3138
|
if (Array.isArray(pattern)) return pattern.map((p) => picomatch.parse(p, options));
|
|
3139
3139
|
return parse4(pattern, { ...options, fastpaths: false });
|
|
@@ -3249,7 +3249,7 @@ var require_micromatch = __commonJS({
|
|
|
3249
3249
|
};
|
|
3250
3250
|
micromatch.match = micromatch;
|
|
3251
3251
|
micromatch.matcher = (pattern, options) => picomatch(pattern, options);
|
|
3252
|
-
micromatch.isMatch = (
|
|
3252
|
+
micromatch.isMatch = (str3, patterns, options) => picomatch(patterns, options)(str3);
|
|
3253
3253
|
micromatch.any = micromatch.isMatch;
|
|
3254
3254
|
micromatch.not = (list, patterns, options = {}) => {
|
|
3255
3255
|
patterns = [].concat(patterns).map(String);
|
|
@@ -3267,22 +3267,22 @@ var require_micromatch = __commonJS({
|
|
|
3267
3267
|
}
|
|
3268
3268
|
return [...result];
|
|
3269
3269
|
};
|
|
3270
|
-
micromatch.contains = (
|
|
3271
|
-
if (typeof
|
|
3272
|
-
throw new TypeError(`Expected a string: "${util.inspect(
|
|
3270
|
+
micromatch.contains = (str3, pattern, options) => {
|
|
3271
|
+
if (typeof str3 !== "string") {
|
|
3272
|
+
throw new TypeError(`Expected a string: "${util.inspect(str3)}"`);
|
|
3273
3273
|
}
|
|
3274
3274
|
if (Array.isArray(pattern)) {
|
|
3275
|
-
return pattern.some((p) => micromatch.contains(
|
|
3275
|
+
return pattern.some((p) => micromatch.contains(str3, p, options));
|
|
3276
3276
|
}
|
|
3277
3277
|
if (typeof pattern === "string") {
|
|
3278
|
-
if (isEmptyString(
|
|
3278
|
+
if (isEmptyString(str3) || isEmptyString(pattern)) {
|
|
3279
3279
|
return false;
|
|
3280
3280
|
}
|
|
3281
|
-
if (
|
|
3281
|
+
if (str3.includes(pattern) || str3.startsWith("./") && str3.slice(2).includes(pattern)) {
|
|
3282
3282
|
return true;
|
|
3283
3283
|
}
|
|
3284
3284
|
}
|
|
3285
|
-
return micromatch.isMatch(
|
|
3285
|
+
return micromatch.isMatch(str3, pattern, { ...options, contains: true });
|
|
3286
3286
|
};
|
|
3287
3287
|
micromatch.matchKeys = (obj, patterns, options) => {
|
|
3288
3288
|
if (!utils.isObject(obj)) {
|
|
@@ -3313,11 +3313,11 @@ var require_micromatch = __commonJS({
|
|
|
3313
3313
|
}
|
|
3314
3314
|
return true;
|
|
3315
3315
|
};
|
|
3316
|
-
micromatch.all = (
|
|
3317
|
-
if (typeof
|
|
3318
|
-
throw new TypeError(`Expected a string: "${util.inspect(
|
|
3316
|
+
micromatch.all = (str3, patterns, options) => {
|
|
3317
|
+
if (typeof str3 !== "string") {
|
|
3318
|
+
throw new TypeError(`Expected a string: "${util.inspect(str3)}"`);
|
|
3319
3319
|
}
|
|
3320
|
-
return [].concat(patterns).every((p) => picomatch(p, options)(
|
|
3320
|
+
return [].concat(patterns).every((p) => picomatch(p, options)(str3));
|
|
3321
3321
|
};
|
|
3322
3322
|
micromatch.capture = (glob, input2, options) => {
|
|
3323
3323
|
let posix = utils.isWindows(options);
|
|
@@ -3332,8 +3332,8 @@ var require_micromatch = __commonJS({
|
|
|
3332
3332
|
micromatch.parse = (patterns, options) => {
|
|
3333
3333
|
let res = [];
|
|
3334
3334
|
for (let pattern of [].concat(patterns || [])) {
|
|
3335
|
-
for (let
|
|
3336
|
-
res.push(picomatch.parse(
|
|
3335
|
+
for (let str3 of braces(String(pattern), options)) {
|
|
3336
|
+
res.push(picomatch.parse(str3, options));
|
|
3337
3337
|
}
|
|
3338
3338
|
}
|
|
3339
3339
|
return res;
|
|
@@ -5873,246 +5873,8 @@ var require_out4 = __commonJS({
|
|
|
5873
5873
|
// src/hook.ts
|
|
5874
5874
|
init_esm_shims();
|
|
5875
5875
|
|
|
5876
|
-
// src/hooks/
|
|
5877
|
-
init_esm_shims();
|
|
5878
|
-
|
|
5879
|
-
// src/hooks/capture.ts
|
|
5880
|
-
init_esm_shims();
|
|
5881
|
-
|
|
5882
|
-
// src/capture/classify.ts
|
|
5883
|
-
init_esm_shims();
|
|
5884
|
-
import { createHash } from "crypto";
|
|
5885
|
-
import { realpathSync } from "fs";
|
|
5886
|
-
import { isAbsolute, relative } from "path";
|
|
5887
|
-
|
|
5888
|
-
// src/capture/categories.ts
|
|
5876
|
+
// src/hooks/dispatch.ts
|
|
5889
5877
|
init_esm_shims();
|
|
5890
|
-
var CATEGORIES = {
|
|
5891
|
-
// P1
|
|
5892
|
-
files: 1,
|
|
5893
|
-
tasks: 1,
|
|
5894
|
-
plans: 1,
|
|
5895
|
-
rules: 1,
|
|
5896
|
-
user_prompt: 1,
|
|
5897
|
-
// P2
|
|
5898
|
-
decision: 2,
|
|
5899
|
-
git: 2,
|
|
5900
|
-
error: 2,
|
|
5901
|
-
error_resolution: 2,
|
|
5902
|
-
constraint: 2,
|
|
5903
|
-
blocker: 2,
|
|
5904
|
-
rejected: 2,
|
|
5905
|
-
environment: 2,
|
|
5906
|
-
agent_findings: 2,
|
|
5907
|
-
iteration_loop: 2,
|
|
5908
|
-
assistant_summary: 2,
|
|
5909
|
-
// P3
|
|
5910
|
-
latency: 3,
|
|
5911
|
-
mcp_tool: 3,
|
|
5912
|
-
subagent: 3,
|
|
5913
|
-
skill: 3,
|
|
5914
|
-
external_ref: 3,
|
|
5915
|
-
role: 3,
|
|
5916
|
-
// P4
|
|
5917
|
-
intent: 4,
|
|
5918
|
-
data: 4,
|
|
5919
|
-
tool_call: 4,
|
|
5920
|
-
session_start: 4,
|
|
5921
|
-
/** A proactive recall decision (fired or quiet) and what it showed; never in the guide. */
|
|
5922
|
-
recall: 4,
|
|
5923
|
-
/** A routing decision (allow / annotate / deny) for one native call; never in the guide. */
|
|
5924
|
-
routing: 4
|
|
5925
|
-
};
|
|
5926
|
-
var GUIDE_ORDER = [
|
|
5927
|
-
{ title: "Last Request", categories: ["user_prompt"] },
|
|
5928
|
-
{ title: "Tasks", categories: ["tasks"] },
|
|
5929
|
-
{ title: "Plans", categories: ["plans"] },
|
|
5930
|
-
{ title: "Key Decisions", categories: ["decision"] },
|
|
5931
|
-
{ title: "Files Modified", categories: ["files"] },
|
|
5932
|
-
{ title: "Unresolved Errors", categories: ["error"] },
|
|
5933
|
-
{ title: "Resolved", categories: ["error_resolution"] },
|
|
5934
|
-
{ title: "Constraints", categories: ["constraint"] },
|
|
5935
|
-
{ title: "Blockers", categories: ["blocker"] },
|
|
5936
|
-
{ title: "Git", categories: ["git"] },
|
|
5937
|
-
{ title: "Project Rules", categories: ["rules"] },
|
|
5938
|
-
{ title: "Loops", categories: ["iteration_loop"] },
|
|
5939
|
-
{ title: "Last Reply", categories: ["assistant_summary"] },
|
|
5940
|
-
{ title: "MCP Tools Used", categories: ["mcp_tool"] },
|
|
5941
|
-
{ title: "Subagent Tasks", categories: ["subagent", "agent_findings"] },
|
|
5942
|
-
{ title: "Skills", categories: ["skill"] },
|
|
5943
|
-
{ title: "Rejected Approaches", categories: ["rejected"] },
|
|
5944
|
-
{ title: "External Refs", categories: ["external_ref"] },
|
|
5945
|
-
{ title: "Environment", categories: ["environment"] },
|
|
5946
|
-
{ title: "Slow Calls", categories: ["latency"] },
|
|
5947
|
-
{ title: "Data refs", categories: ["data"] },
|
|
5948
|
-
{ title: "Intent", categories: ["intent"] }
|
|
5949
|
-
];
|
|
5950
|
-
|
|
5951
|
-
// src/capture/classify.ts
|
|
5952
|
-
function relPath(root, fp) {
|
|
5953
|
-
const tryRel = (base, p) => {
|
|
5954
|
-
const r = relative(base, p);
|
|
5955
|
-
return r && !r.startsWith("..") && !isAbsolute(r) ? r : void 0;
|
|
5956
|
-
};
|
|
5957
|
-
const direct = tryRel(root, fp);
|
|
5958
|
-
if (direct) return direct;
|
|
5959
|
-
try {
|
|
5960
|
-
const real = tryRel(realpathSync(root), realpathSync(fp));
|
|
5961
|
-
if (real) return real;
|
|
5962
|
-
} catch {
|
|
5963
|
-
}
|
|
5964
|
-
return fp;
|
|
5965
|
-
}
|
|
5966
|
-
function ev(category, payload, tool) {
|
|
5967
|
-
return { category, payload, tool };
|
|
5968
|
-
}
|
|
5969
|
-
function withPriority(sessionId, drafts) {
|
|
5970
|
-
return drafts.map((d) => ({ ...d, sessionId, priority: CATEGORIES[d.category] }));
|
|
5971
|
-
}
|
|
5972
|
-
var clip = (s, n) => {
|
|
5973
|
-
const str2 = typeof s === "string" ? s : JSON.stringify(s ?? "");
|
|
5974
|
-
return str2.length > n ? `${str2.slice(0, n - 1)}\u2026` : str2;
|
|
5975
|
-
};
|
|
5976
|
-
var DECISION = /\b(let'?s go with|we'?ll use|decided|decision:|go with|use (?:the )?\w+ instead|stick with|switch(?:ing)? to|chose|prefer(?:red)?)\b/i;
|
|
5977
|
-
var CONSTRAINT = /\b(must(?: not)?|never|always|only|do not|don'?t|should not|required?|hard requirement|no\s+\w+ allowed)\b/i;
|
|
5978
|
-
var REJECTED = /\b(instead of|rather than|not \w+ing|don'?t use|drop(?:ped)?|revert(?:ed)?|abandon(?:ed)?|scrap(?:ped)?)\b/i;
|
|
5979
|
-
var BLOCKER = /\b(blocked|blocker|can'?t (?:proceed|continue)|waiting (?:on|for)|need(?:s)? (?:access|permission|approval))\b/i;
|
|
5980
|
-
var RESOLVED = /\b(fixed|resolved|now passes|passing now|works now|solved|green)\b/i;
|
|
5981
|
-
var INTENT = /^\s*(?:(?:please|can you|could you|let'?s|i want to|i'?d like to|help me)\s+)?(\w+(?:\s+\w+){0,5})/i;
|
|
5982
|
-
function classifyPrompt(prompt) {
|
|
5983
|
-
const out = [ev("user_prompt", { text: clip(prompt, 600) })];
|
|
5984
|
-
const first = prompt.split("\n").find((l) => l.trim()) ?? "";
|
|
5985
|
-
if (DECISION.test(prompt))
|
|
5986
|
-
out.push(ev("decision", { text: clip(firstMatchLine(prompt, DECISION), 300), by: "user" }));
|
|
5987
|
-
if (CONSTRAINT.test(prompt) && prompt.length < 2e3)
|
|
5988
|
-
out.push(ev("constraint", { text: clip(firstMatchLine(prompt, CONSTRAINT), 300) }));
|
|
5989
|
-
if (REJECTED.test(prompt))
|
|
5990
|
-
out.push(ev("rejected", { text: clip(firstMatchLine(prompt, REJECTED), 300) }));
|
|
5991
|
-
if (BLOCKER.test(prompt))
|
|
5992
|
-
out.push(ev("blocker", { text: clip(firstMatchLine(prompt, BLOCKER), 300) }));
|
|
5993
|
-
const m = INTENT.exec(first);
|
|
5994
|
-
if (m?.[1]) out.push(ev("intent", { text: clip(m[1], 80) }));
|
|
5995
|
-
return out;
|
|
5996
|
-
}
|
|
5997
|
-
function firstMatchLine(text, re) {
|
|
5998
|
-
return text.split("\n").find((l) => re.test(l)) ?? text;
|
|
5999
|
-
}
|
|
6000
|
-
var EDIT_TOOLS = /* @__PURE__ */ new Set(["Edit", "Write", "MultiEdit", "NotebookEdit"]);
|
|
6001
|
-
var GIT_OP = /^\s*git\s+(commit|checkout|switch|merge|rebase|push|pull|stash|reset|revert|cherry-pick|tag|branch\s+-[dD])/;
|
|
6002
|
-
function callKey(toolName, toolInput) {
|
|
6003
|
-
return `${toolName}:${createHash("sha1").update(JSON.stringify(toolInput)).digest("hex").slice(0, 12)}`;
|
|
6004
|
-
}
|
|
6005
|
-
function responseText(r) {
|
|
6006
|
-
if (typeof r === "string") return r;
|
|
6007
|
-
if (r && typeof r === "object") {
|
|
6008
|
-
const o = r;
|
|
6009
|
-
if (typeof o.stdout === "string")
|
|
6010
|
-
return `${o.stdout}
|
|
6011
|
-
${typeof o.stderr === "string" ? o.stderr : ""}`;
|
|
6012
|
-
if (Array.isArray(o.content)) {
|
|
6013
|
-
return o.content.map(
|
|
6014
|
-
(c) => c && typeof c === "object" && typeof c.text === "string" ? c.text : ""
|
|
6015
|
-
).join("\n");
|
|
6016
|
-
}
|
|
6017
|
-
if (typeof o.error === "string") return o.error;
|
|
6018
|
-
}
|
|
6019
|
-
return "";
|
|
6020
|
-
}
|
|
6021
|
-
function responseFailed(r) {
|
|
6022
|
-
if (!r || typeof r !== "object") return void 0;
|
|
6023
|
-
const o = r;
|
|
6024
|
-
if (o.is_error === true || o.isError === true) return clip(responseText(r), 400);
|
|
6025
|
-
if (typeof o.exit_code === "number" && o.exit_code !== 0) return clip(responseText(r), 400);
|
|
6026
|
-
if (typeof o.interrupted === "boolean" && o.interrupted) return "interrupted";
|
|
6027
|
-
return void 0;
|
|
6028
|
-
}
|
|
6029
|
-
function classifyToolCall(info) {
|
|
6030
|
-
const { toolName, toolInput, root } = info;
|
|
6031
|
-
const out = [];
|
|
6032
|
-
const key = callKey(toolName, toolInput);
|
|
6033
|
-
out.push(ev("tool_call", { key, summary: summarizeInput(toolName, toolInput) }, toolName));
|
|
6034
|
-
if (EDIT_TOOLS.has(toolName)) {
|
|
6035
|
-
const fp = String(toolInput.file_path ?? toolInput.notebook_path ?? "");
|
|
6036
|
-
if (fp) {
|
|
6037
|
-
const rel = relPath(root, fp);
|
|
6038
|
-
if (/\.claude\/plans\/|\/plans\/.*\.md$/.test(fp))
|
|
6039
|
-
out.push(ev("plans", { path: rel, action: toolName }, toolName));
|
|
6040
|
-
else out.push(ev("files", { path: rel, action: toolName }, toolName));
|
|
6041
|
-
if (/(^|\/)(CLAUDE|AGENTS)\.md$|\.claude\/settings/.test(fp))
|
|
6042
|
-
out.push(ev("rules", { path: rel, action: toolName }, toolName));
|
|
6043
|
-
}
|
|
6044
|
-
}
|
|
6045
|
-
if (toolName === "Bash") {
|
|
6046
|
-
const cmd = String(toolInput.command ?? "");
|
|
6047
|
-
if (GIT_OP.test(cmd)) out.push(ev("git", { command: clip(cmd, 200) }, toolName));
|
|
6048
|
-
}
|
|
6049
|
-
if (toolName === "TodoWrite" && Array.isArray(toolInput.todos)) {
|
|
6050
|
-
const todos = toolInput.todos;
|
|
6051
|
-
out.push(
|
|
6052
|
-
ev(
|
|
6053
|
-
"tasks",
|
|
6054
|
-
{
|
|
6055
|
-
todos: todos.slice(0, 12).map(
|
|
6056
|
-
(t) => `${t.status === "completed" ? "x" : t.status === "in_progress" ? ">" : " "} ${clip(t.content, 80)}`
|
|
6057
|
-
)
|
|
6058
|
-
},
|
|
6059
|
-
toolName
|
|
6060
|
-
)
|
|
6061
|
-
);
|
|
6062
|
-
}
|
|
6063
|
-
if (toolName === "ExitPlanMode") out.push(ev("plans", { action: "plan approved" }, toolName));
|
|
6064
|
-
if (toolName === "Agent" || toolName === "Task") {
|
|
6065
|
-
out.push(
|
|
6066
|
-
ev(
|
|
6067
|
-
"subagent",
|
|
6068
|
-
{ description: clip(toolInput.description, 120), type: toolInput.subagent_type },
|
|
6069
|
-
toolName
|
|
6070
|
-
)
|
|
6071
|
-
);
|
|
6072
|
-
}
|
|
6073
|
-
if (toolName === "Skill") out.push(ev("skill", { skill: clip(toolInput.skill, 80) }, toolName));
|
|
6074
|
-
if (toolName === "WebFetch" || toolName === "WebSearch") {
|
|
6075
|
-
out.push(ev("external_ref", { url: clip(toolInput.url ?? toolInput.query, 200) }, toolName));
|
|
6076
|
-
}
|
|
6077
|
-
if (toolName.startsWith("mcp__")) out.push(ev("mcp_tool", { tool: toolName }, toolName));
|
|
6078
|
-
if (info.durationMs && info.durationMs > 5e3) {
|
|
6079
|
-
out.push(
|
|
6080
|
-
ev(
|
|
6081
|
-
"latency",
|
|
6082
|
-
{ ms: info.durationMs, summary: summarizeInput(toolName, toolInput) },
|
|
6083
|
-
toolName
|
|
6084
|
-
)
|
|
6085
|
-
);
|
|
6086
|
-
}
|
|
6087
|
-
const failure2 = info.error ?? responseFailed(info.toolResponse);
|
|
6088
|
-
if (failure2)
|
|
6089
|
-
out.push(
|
|
6090
|
-
ev(
|
|
6091
|
-
"error",
|
|
6092
|
-
{ tool: toolName, summary: summarizeInput(toolName, toolInput), error: clip(failure2, 400) },
|
|
6093
|
-
toolName
|
|
6094
|
-
)
|
|
6095
|
-
);
|
|
6096
|
-
return out;
|
|
6097
|
-
}
|
|
6098
|
-
function summarizeInput(toolName, input2) {
|
|
6099
|
-
const pick2 = input2.command ?? input2.file_path ?? input2.pattern ?? input2.url ?? input2.prompt ?? input2.query ?? input2.description ?? input2.skill;
|
|
6100
|
-
return clip(`${toolName} ${pick2 ?? ""}`.trim(), 160);
|
|
6101
|
-
}
|
|
6102
|
-
function classifyAssistant(message) {
|
|
6103
|
-
const out = [];
|
|
6104
|
-
if (!message.trim()) return out;
|
|
6105
|
-
out.push(ev("assistant_summary", { text: clip(message.replace(/\s+/g, " "), 500) }));
|
|
6106
|
-
if (DECISION.test(message))
|
|
6107
|
-
out.push(
|
|
6108
|
-
ev("decision", { text: clip(firstMatchLine(message, DECISION), 300), by: "assistant" })
|
|
6109
|
-
);
|
|
6110
|
-
if (RESOLVED.test(message))
|
|
6111
|
-
out.push(ev("error_resolution", { text: clip(firstMatchLine(message, RESOLVED), 300) }));
|
|
6112
|
-
if (BLOCKER.test(message))
|
|
6113
|
-
out.push(ev("blocker", { text: clip(firstMatchLine(message, BLOCKER), 300), by: "assistant" }));
|
|
6114
|
-
return out;
|
|
6115
|
-
}
|
|
6116
5878
|
|
|
6117
5879
|
// src/context.ts
|
|
6118
5880
|
init_esm_shims();
|
|
@@ -6966,14 +6728,14 @@ function promiseAllObject(promisesObj) {
|
|
|
6966
6728
|
}
|
|
6967
6729
|
function randomString(length = 10) {
|
|
6968
6730
|
const chars = "abcdefghijklmnopqrstuvwxyz";
|
|
6969
|
-
let
|
|
6731
|
+
let str3 = "";
|
|
6970
6732
|
for (let i = 0; i < length; i++) {
|
|
6971
|
-
|
|
6733
|
+
str3 += chars[Math.floor(Math.random() * chars.length)];
|
|
6972
6734
|
}
|
|
6973
|
-
return
|
|
6735
|
+
return str3;
|
|
6974
6736
|
}
|
|
6975
|
-
function esc(
|
|
6976
|
-
return JSON.stringify(
|
|
6737
|
+
function esc(str3) {
|
|
6738
|
+
return JSON.stringify(str3);
|
|
6977
6739
|
}
|
|
6978
6740
|
function slugify(input2) {
|
|
6979
6741
|
return input2.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -7087,8 +6849,8 @@ var primitiveTypes = /* @__PURE__ */ new Set([
|
|
|
7087
6849
|
"symbol",
|
|
7088
6850
|
"undefined"
|
|
7089
6851
|
]);
|
|
7090
|
-
function escapeRegex(
|
|
7091
|
-
return
|
|
6852
|
+
function escapeRegex(str3) {
|
|
6853
|
+
return str3.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7092
6854
|
}
|
|
7093
6855
|
function clone(inst, def, params) {
|
|
7094
6856
|
const cl = new inst._zod.constr(def ?? inst._zod.def);
|
|
@@ -7354,13 +7116,13 @@ function getSizableOrigin(input2) {
|
|
|
7354
7116
|
return "unknown";
|
|
7355
7117
|
}
|
|
7356
7118
|
var highSurrogate = /[\uD800-\uDBFF]/;
|
|
7357
|
-
function codePointLength(
|
|
7358
|
-
const units =
|
|
7359
|
-
if (!highSurrogate.test(
|
|
7119
|
+
function codePointLength(str3) {
|
|
7120
|
+
const units = str3.length;
|
|
7121
|
+
if (!highSurrogate.test(str3))
|
|
7360
7122
|
return units;
|
|
7361
7123
|
let count = units;
|
|
7362
7124
|
for (let i = 0; i < units - 1; i++) {
|
|
7363
|
-
if ((
|
|
7125
|
+
if ((str3.charCodeAt(i) & 64512) === 55296 && (str3.charCodeAt(i + 1) & 64512) === 56320) {
|
|
7364
7126
|
count--;
|
|
7365
7127
|
i++;
|
|
7366
7128
|
}
|
|
@@ -26219,8 +25981,8 @@ function loadConfig(projectRoot) {
|
|
|
26219
25981
|
|
|
26220
25982
|
// src/project.ts
|
|
26221
25983
|
init_esm_shims();
|
|
26222
|
-
import { createHash
|
|
26223
|
-
import { existsSync as existsSync2, realpathSync
|
|
25984
|
+
import { createHash } from "crypto";
|
|
25985
|
+
import { existsSync as existsSync2, realpathSync } from "fs";
|
|
26224
25986
|
import { dirname, join as join3, resolve } from "path";
|
|
26225
25987
|
var ROOT_MARKERS = [
|
|
26226
25988
|
".git",
|
|
@@ -26245,13 +26007,13 @@ function resolveProjectRoot(hint) {
|
|
|
26245
26007
|
const candidate = hint || process.env.EMINIAR_PROJECT_ROOT || process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
26246
26008
|
const root = findProjectRoot(candidate);
|
|
26247
26009
|
try {
|
|
26248
|
-
return
|
|
26010
|
+
return realpathSync(root);
|
|
26249
26011
|
} catch {
|
|
26250
26012
|
return root;
|
|
26251
26013
|
}
|
|
26252
26014
|
}
|
|
26253
26015
|
function projectId(root) {
|
|
26254
|
-
return
|
|
26016
|
+
return createHash("sha256").update(root).digest("hex").slice(0, 16);
|
|
26255
26017
|
}
|
|
26256
26018
|
|
|
26257
26019
|
// src/context.ts
|
|
@@ -26267,25 +26029,459 @@ function getContext(rootHint) {
|
|
|
26267
26029
|
return ctx;
|
|
26268
26030
|
}
|
|
26269
26031
|
|
|
26270
|
-
// src/
|
|
26271
|
-
init_esm_shims();
|
|
26272
|
-
var import_fast_glob = __toESM(require_out4(), 1);
|
|
26273
|
-
import { readFileSync as readFileSync2, statSync } from "fs";
|
|
26274
|
-
import { relative as relative2, resolve as resolve2 } from "path";
|
|
26275
|
-
|
|
26276
|
-
// src/chunker/index.ts
|
|
26277
|
-
init_esm_shims();
|
|
26278
|
-
import { extname } from "path";
|
|
26279
|
-
|
|
26280
|
-
// src/chunker/code.ts
|
|
26281
|
-
init_esm_shims();
|
|
26282
|
-
|
|
26283
|
-
// src/chunker/types.ts
|
|
26032
|
+
// src/hooks/cursor.ts
|
|
26284
26033
|
init_esm_shims();
|
|
26285
|
-
import {
|
|
26286
|
-
|
|
26287
|
-
|
|
26288
|
-
|
|
26034
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, rmSync, writeFileSync } from "fs";
|
|
26035
|
+
import { homedir as homedir2 } from "os";
|
|
26036
|
+
import { join as join4 } from "path";
|
|
26037
|
+
var CURSOR_EVENTS = {
|
|
26038
|
+
sessionStart: "SessionStart",
|
|
26039
|
+
beforeSubmitPrompt: "UserPromptSubmit",
|
|
26040
|
+
preToolUse: "PreToolUse",
|
|
26041
|
+
postToolUse: "PostToolUse",
|
|
26042
|
+
postToolUseFailure: "PostToolUseFailure",
|
|
26043
|
+
subagentStop: "SubagentStop",
|
|
26044
|
+
preCompact: "PreCompact",
|
|
26045
|
+
// afterAgentResponse carries the assistant text that Claude Code's Stop event carries.
|
|
26046
|
+
afterAgentResponse: "Stop",
|
|
26047
|
+
stop: "Stop",
|
|
26048
|
+
afterFileEdit: "PostToolUse",
|
|
26049
|
+
sessionEnd: "SessionEnd"
|
|
26050
|
+
};
|
|
26051
|
+
var TOOL_NAMES = { Shell: "Bash" };
|
|
26052
|
+
var PENDING_TTL_MS = 10 * 6e4;
|
|
26053
|
+
var PENDING_MAX = 8e3;
|
|
26054
|
+
function cursorDir() {
|
|
26055
|
+
return process.env.CURSOR_CONFIG_DIR || join4(homedir2(), ".cursor");
|
|
26056
|
+
}
|
|
26057
|
+
function detectClient(input2, argv) {
|
|
26058
|
+
const i = argv.indexOf("--client");
|
|
26059
|
+
if (i !== -1 && argv[i + 1]) return argv[i + 1] === "cursor" ? "cursor" : "claude";
|
|
26060
|
+
const ev3 = typeof input2.hook_event_name === "string" ? input2.hook_event_name : "";
|
|
26061
|
+
if (typeof input2.cursor_version === "string" || Array.isArray(input2.workspace_roots) || typeof input2.conversation_id === "string" && !input2.session_id || ev3 in CURSOR_EVENTS)
|
|
26062
|
+
return "cursor";
|
|
26063
|
+
return "claude";
|
|
26064
|
+
}
|
|
26065
|
+
var str = (v) => typeof v === "string" && v.length ? v : void 0;
|
|
26066
|
+
function mapToolName(name) {
|
|
26067
|
+
if (name in TOOL_NAMES) return TOOL_NAMES[name];
|
|
26068
|
+
const mcp = /^MCP:(.+)$/.exec(name);
|
|
26069
|
+
if (mcp) return `mcp__cursor__${mcp[1]}`;
|
|
26070
|
+
return name;
|
|
26071
|
+
}
|
|
26072
|
+
function toolInputOf(v) {
|
|
26073
|
+
let obj = v;
|
|
26074
|
+
if (typeof obj === "string") {
|
|
26075
|
+
try {
|
|
26076
|
+
obj = JSON.parse(obj);
|
|
26077
|
+
} catch {
|
|
26078
|
+
return void 0;
|
|
26079
|
+
}
|
|
26080
|
+
}
|
|
26081
|
+
if (!obj || typeof obj !== "object" || Array.isArray(obj)) return void 0;
|
|
26082
|
+
const input2 = { ...obj };
|
|
26083
|
+
if (typeof input2.path === "string" && input2.file_path === void 0) input2.file_path = input2.path;
|
|
26084
|
+
return input2;
|
|
26085
|
+
}
|
|
26086
|
+
function toolResponseOf(v) {
|
|
26087
|
+
if (typeof v !== "string") return v;
|
|
26088
|
+
try {
|
|
26089
|
+
return JSON.parse(v);
|
|
26090
|
+
} catch {
|
|
26091
|
+
return v;
|
|
26092
|
+
}
|
|
26093
|
+
}
|
|
26094
|
+
function fromCursor(raw) {
|
|
26095
|
+
const event = str(raw.hook_event_name) ?? "";
|
|
26096
|
+
const roots = Array.isArray(raw.workspace_roots) ? raw.workspace_roots.filter((r) => typeof r === "string") : [];
|
|
26097
|
+
const cwd = str(raw.cwd) ?? roots[0] ?? process.env.CURSOR_PROJECT_DIR ?? process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
|
|
26098
|
+
const input2 = {
|
|
26099
|
+
session_id: str(raw.session_id) ?? str(raw.conversation_id) ?? process.env.EMINIAR_SESSION_ID ?? "cursor",
|
|
26100
|
+
cwd,
|
|
26101
|
+
hook_event_name: CURSOR_EVENTS[event] ?? event
|
|
26102
|
+
};
|
|
26103
|
+
const transcript = str(raw.transcript_path);
|
|
26104
|
+
if (transcript) input2.transcript_path = transcript;
|
|
26105
|
+
if (input2.hook_event_name === "SessionStart") input2.source = "startup";
|
|
26106
|
+
const prompt = str(raw.prompt);
|
|
26107
|
+
if (prompt) input2.prompt = prompt;
|
|
26108
|
+
if (event === "afterFileEdit") {
|
|
26109
|
+
input2.tool_name = "Edit";
|
|
26110
|
+
const ti = {};
|
|
26111
|
+
if (str(raw.file_path)) ti.file_path = raw.file_path;
|
|
26112
|
+
if (Array.isArray(raw.edits)) ti.edits = raw.edits;
|
|
26113
|
+
input2.tool_input = ti;
|
|
26114
|
+
} else {
|
|
26115
|
+
const tool = str(raw.tool_name);
|
|
26116
|
+
if (tool) input2.tool_name = mapToolName(tool);
|
|
26117
|
+
const ti = toolInputOf(raw.tool_input);
|
|
26118
|
+
if (ti) input2.tool_input = ti;
|
|
26119
|
+
}
|
|
26120
|
+
const useId = str(raw.tool_use_id);
|
|
26121
|
+
if (useId) input2.tool_use_id = useId;
|
|
26122
|
+
if (raw.tool_output !== void 0) input2.tool_response = toolResponseOf(raw.tool_output);
|
|
26123
|
+
const dur = typeof raw.duration === "number" ? raw.duration : raw.duration_ms;
|
|
26124
|
+
if (typeof dur === "number") input2.duration_ms = dur;
|
|
26125
|
+
const err = str(raw.error_message) ?? str(raw.error);
|
|
26126
|
+
if (err) input2.error = err;
|
|
26127
|
+
const text = str(raw.text) ?? str(raw.summary) ?? str(raw.last_assistant_message);
|
|
26128
|
+
if (text) input2.last_assistant_message = text;
|
|
26129
|
+
const agent = str(raw.subagent_type) ?? str(raw.agent_type);
|
|
26130
|
+
if (agent) input2.agent_type = agent;
|
|
26131
|
+
const agentTranscript = str(raw.agent_transcript_path);
|
|
26132
|
+
if (agentTranscript) input2.agent_transcript_path = agentTranscript;
|
|
26133
|
+
if (raw.trigger === "manual" || raw.trigger === "auto") input2.trigger = raw.trigger;
|
|
26134
|
+
const reason = str(raw.reason);
|
|
26135
|
+
if (reason) input2.reason = reason;
|
|
26136
|
+
return input2;
|
|
26137
|
+
}
|
|
26138
|
+
function pendingFile(root, sessionId) {
|
|
26139
|
+
const id = getContext(root).id;
|
|
26140
|
+
return join4(projectDir(id), "pending-context", `${sessionId.replace(/[^\w.-]/g, "_")}.json`);
|
|
26141
|
+
}
|
|
26142
|
+
function readPending(file3) {
|
|
26143
|
+
try {
|
|
26144
|
+
const list = JSON.parse(readFileSync2(file3, "utf8"));
|
|
26145
|
+
return Array.isArray(list) ? list : [];
|
|
26146
|
+
} catch {
|
|
26147
|
+
return [];
|
|
26148
|
+
}
|
|
26149
|
+
}
|
|
26150
|
+
function stashContext(root, sessionId, text) {
|
|
26151
|
+
if (!text.trim()) return;
|
|
26152
|
+
const file3 = pendingFile(root, sessionId);
|
|
26153
|
+
mkdirSync2(join4(file3, ".."), { recursive: true });
|
|
26154
|
+
const now = Date.now();
|
|
26155
|
+
const list = readPending(file3).filter((p) => now - p.t < PENDING_TTL_MS);
|
|
26156
|
+
list.push({ t: now, text });
|
|
26157
|
+
writeFileSync(file3, JSON.stringify(list));
|
|
26158
|
+
}
|
|
26159
|
+
function takeContext(root, sessionId) {
|
|
26160
|
+
const file3 = pendingFile(root, sessionId);
|
|
26161
|
+
if (!existsSync3(file3)) return void 0;
|
|
26162
|
+
const now = Date.now();
|
|
26163
|
+
const list = readPending(file3).filter((p) => now - p.t < PENDING_TTL_MS);
|
|
26164
|
+
rmSync(file3, { force: true });
|
|
26165
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26166
|
+
const texts = list.map((p) => p.text).filter((t) => !seen.has(t) && seen.add(t));
|
|
26167
|
+
const joined = texts.join("\n\n").slice(0, PENDING_MAX);
|
|
26168
|
+
return joined || void 0;
|
|
26169
|
+
}
|
|
26170
|
+
function cursorHasServer() {
|
|
26171
|
+
try {
|
|
26172
|
+
const raw = readFileSync2(join4(cursorDir(), "mcp.json"), "utf8");
|
|
26173
|
+
return raw.includes("em-server");
|
|
26174
|
+
} catch {
|
|
26175
|
+
return false;
|
|
26176
|
+
}
|
|
26177
|
+
}
|
|
26178
|
+
var joinText = (...parts) => {
|
|
26179
|
+
const kept = parts.filter((p) => !!p?.trim());
|
|
26180
|
+
return kept.length ? kept.join("\n\n") : void 0;
|
|
26181
|
+
};
|
|
26182
|
+
function toCursor(event, out, scope) {
|
|
26183
|
+
const specific2 = out?.hookSpecificOutput;
|
|
26184
|
+
const context = specific2?.additionalContext;
|
|
26185
|
+
switch (event) {
|
|
26186
|
+
case "PreToolUse": {
|
|
26187
|
+
if (specific2?.permissionDecision === "deny") {
|
|
26188
|
+
if (!cursorHasServer()) {
|
|
26189
|
+
stashContext(
|
|
26190
|
+
scope.root,
|
|
26191
|
+
scope.sessionId,
|
|
26192
|
+
`${specific2.permissionDecisionReason ?? ""} (eminiar MCP server is not registered with Cursor, so the call was allowed; run \`npx eminiar install --cursor\`)`.trim()
|
|
26193
|
+
);
|
|
26194
|
+
return { permission: "allow" };
|
|
26195
|
+
}
|
|
26196
|
+
const reason = joinText(specific2.permissionDecisionReason, context) ?? "eminiar: denied";
|
|
26197
|
+
return { permission: "deny", user_message: reason, agent_message: reason };
|
|
26198
|
+
}
|
|
26199
|
+
const res = { permission: "allow" };
|
|
26200
|
+
if (specific2?.updatedInput) res.updated_input = specific2.updatedInput;
|
|
26201
|
+
if (context) stashContext(scope.root, scope.sessionId, context);
|
|
26202
|
+
return res;
|
|
26203
|
+
}
|
|
26204
|
+
case "PostToolUse":
|
|
26205
|
+
case "PostToolUseFailure": {
|
|
26206
|
+
const text = joinText(takeContext(scope.root, scope.sessionId), context);
|
|
26207
|
+
return text ? { additional_context: text } : {};
|
|
26208
|
+
}
|
|
26209
|
+
case "SessionStart": {
|
|
26210
|
+
const res = {
|
|
26211
|
+
env: { EMINIAR_SESSION_ID: scope.sessionId, EMINIAR_PROJECT_ROOT: scope.root }
|
|
26212
|
+
};
|
|
26213
|
+
if (context) res.additional_context = context;
|
|
26214
|
+
return res;
|
|
26215
|
+
}
|
|
26216
|
+
case "UserPromptSubmit": {
|
|
26217
|
+
if (context) stashContext(scope.root, scope.sessionId, context);
|
|
26218
|
+
return { continue: true };
|
|
26219
|
+
}
|
|
26220
|
+
default:
|
|
26221
|
+
return {};
|
|
26222
|
+
}
|
|
26223
|
+
}
|
|
26224
|
+
|
|
26225
|
+
// src/hooks/index.ts
|
|
26226
|
+
init_esm_shims();
|
|
26227
|
+
|
|
26228
|
+
// src/hooks/capture.ts
|
|
26229
|
+
init_esm_shims();
|
|
26230
|
+
|
|
26231
|
+
// src/capture/classify.ts
|
|
26232
|
+
init_esm_shims();
|
|
26233
|
+
import { createHash as createHash2 } from "crypto";
|
|
26234
|
+
import { realpathSync as realpathSync2 } from "fs";
|
|
26235
|
+
import { isAbsolute, relative } from "path";
|
|
26236
|
+
|
|
26237
|
+
// src/capture/categories.ts
|
|
26238
|
+
init_esm_shims();
|
|
26239
|
+
var CATEGORIES = {
|
|
26240
|
+
// P1
|
|
26241
|
+
files: 1,
|
|
26242
|
+
tasks: 1,
|
|
26243
|
+
plans: 1,
|
|
26244
|
+
rules: 1,
|
|
26245
|
+
user_prompt: 1,
|
|
26246
|
+
// P2
|
|
26247
|
+
decision: 2,
|
|
26248
|
+
git: 2,
|
|
26249
|
+
error: 2,
|
|
26250
|
+
error_resolution: 2,
|
|
26251
|
+
constraint: 2,
|
|
26252
|
+
blocker: 2,
|
|
26253
|
+
rejected: 2,
|
|
26254
|
+
environment: 2,
|
|
26255
|
+
agent_findings: 2,
|
|
26256
|
+
iteration_loop: 2,
|
|
26257
|
+
assistant_summary: 2,
|
|
26258
|
+
// P3
|
|
26259
|
+
latency: 3,
|
|
26260
|
+
mcp_tool: 3,
|
|
26261
|
+
subagent: 3,
|
|
26262
|
+
skill: 3,
|
|
26263
|
+
external_ref: 3,
|
|
26264
|
+
role: 3,
|
|
26265
|
+
// P4
|
|
26266
|
+
intent: 4,
|
|
26267
|
+
data: 4,
|
|
26268
|
+
tool_call: 4,
|
|
26269
|
+
session_start: 4,
|
|
26270
|
+
/** A proactive recall decision (fired or quiet) and what it showed; never in the guide. */
|
|
26271
|
+
recall: 4,
|
|
26272
|
+
/** A routing decision (allow / annotate / deny) for one native call; never in the guide. */
|
|
26273
|
+
routing: 4
|
|
26274
|
+
};
|
|
26275
|
+
var GUIDE_ORDER = [
|
|
26276
|
+
{ title: "Last Request", categories: ["user_prompt"] },
|
|
26277
|
+
{ title: "Tasks", categories: ["tasks"] },
|
|
26278
|
+
{ title: "Plans", categories: ["plans"] },
|
|
26279
|
+
{ title: "Key Decisions", categories: ["decision"] },
|
|
26280
|
+
{ title: "Files Modified", categories: ["files"] },
|
|
26281
|
+
{ title: "Unresolved Errors", categories: ["error"] },
|
|
26282
|
+
{ title: "Resolved", categories: ["error_resolution"] },
|
|
26283
|
+
{ title: "Constraints", categories: ["constraint"] },
|
|
26284
|
+
{ title: "Blockers", categories: ["blocker"] },
|
|
26285
|
+
{ title: "Git", categories: ["git"] },
|
|
26286
|
+
{ title: "Project Rules", categories: ["rules"] },
|
|
26287
|
+
{ title: "Loops", categories: ["iteration_loop"] },
|
|
26288
|
+
{ title: "Last Reply", categories: ["assistant_summary"] },
|
|
26289
|
+
{ title: "MCP Tools Used", categories: ["mcp_tool"] },
|
|
26290
|
+
{ title: "Subagent Tasks", categories: ["subagent", "agent_findings"] },
|
|
26291
|
+
{ title: "Skills", categories: ["skill"] },
|
|
26292
|
+
{ title: "Rejected Approaches", categories: ["rejected"] },
|
|
26293
|
+
{ title: "External Refs", categories: ["external_ref"] },
|
|
26294
|
+
{ title: "Environment", categories: ["environment"] },
|
|
26295
|
+
{ title: "Slow Calls", categories: ["latency"] },
|
|
26296
|
+
{ title: "Data refs", categories: ["data"] },
|
|
26297
|
+
{ title: "Intent", categories: ["intent"] }
|
|
26298
|
+
];
|
|
26299
|
+
|
|
26300
|
+
// src/capture/classify.ts
|
|
26301
|
+
function relPath(root, fp) {
|
|
26302
|
+
const tryRel = (base, p) => {
|
|
26303
|
+
const r = relative(base, p);
|
|
26304
|
+
return r && !r.startsWith("..") && !isAbsolute(r) ? r : void 0;
|
|
26305
|
+
};
|
|
26306
|
+
const direct = tryRel(root, fp);
|
|
26307
|
+
if (direct) return direct;
|
|
26308
|
+
try {
|
|
26309
|
+
const real = tryRel(realpathSync2(root), realpathSync2(fp));
|
|
26310
|
+
if (real) return real;
|
|
26311
|
+
} catch {
|
|
26312
|
+
}
|
|
26313
|
+
return fp;
|
|
26314
|
+
}
|
|
26315
|
+
function ev(category, payload, tool) {
|
|
26316
|
+
return { category, payload, tool };
|
|
26317
|
+
}
|
|
26318
|
+
function withPriority(sessionId, drafts) {
|
|
26319
|
+
return drafts.map((d) => ({ ...d, sessionId, priority: CATEGORIES[d.category] }));
|
|
26320
|
+
}
|
|
26321
|
+
var clip = (s, n) => {
|
|
26322
|
+
const str3 = typeof s === "string" ? s : JSON.stringify(s ?? "");
|
|
26323
|
+
return str3.length > n ? `${str3.slice(0, n - 1)}\u2026` : str3;
|
|
26324
|
+
};
|
|
26325
|
+
var DECISION = /\b(let'?s go with|we'?ll use|decided|decision:|go with|use (?:the )?\w+ instead|stick with|switch(?:ing)? to|chose|prefer(?:red)?)\b/i;
|
|
26326
|
+
var CONSTRAINT = /\b(must(?: not)?|never|always|only|do not|don'?t|should not|required?|hard requirement|no\s+\w+ allowed)\b/i;
|
|
26327
|
+
var REJECTED = /\b(instead of|rather than|not \w+ing|don'?t use|drop(?:ped)?|revert(?:ed)?|abandon(?:ed)?|scrap(?:ped)?)\b/i;
|
|
26328
|
+
var BLOCKER = /\b(blocked|blocker|can'?t (?:proceed|continue)|waiting (?:on|for)|need(?:s)? (?:access|permission|approval))\b/i;
|
|
26329
|
+
var RESOLVED = /\b(fixed|resolved|now passes|passing now|works now|solved|green)\b/i;
|
|
26330
|
+
var INTENT = /^\s*(?:(?:please|can you|could you|let'?s|i want to|i'?d like to|help me)\s+)?(\w+(?:\s+\w+){0,5})/i;
|
|
26331
|
+
function classifyPrompt(prompt) {
|
|
26332
|
+
const out = [ev("user_prompt", { text: clip(prompt, 600) })];
|
|
26333
|
+
const first = prompt.split("\n").find((l) => l.trim()) ?? "";
|
|
26334
|
+
if (DECISION.test(prompt))
|
|
26335
|
+
out.push(ev("decision", { text: clip(firstMatchLine(prompt, DECISION), 300), by: "user" }));
|
|
26336
|
+
if (CONSTRAINT.test(prompt) && prompt.length < 2e3)
|
|
26337
|
+
out.push(ev("constraint", { text: clip(firstMatchLine(prompt, CONSTRAINT), 300) }));
|
|
26338
|
+
if (REJECTED.test(prompt))
|
|
26339
|
+
out.push(ev("rejected", { text: clip(firstMatchLine(prompt, REJECTED), 300) }));
|
|
26340
|
+
if (BLOCKER.test(prompt))
|
|
26341
|
+
out.push(ev("blocker", { text: clip(firstMatchLine(prompt, BLOCKER), 300) }));
|
|
26342
|
+
const m = INTENT.exec(first);
|
|
26343
|
+
if (m?.[1]) out.push(ev("intent", { text: clip(m[1], 80) }));
|
|
26344
|
+
return out;
|
|
26345
|
+
}
|
|
26346
|
+
function firstMatchLine(text, re) {
|
|
26347
|
+
return text.split("\n").find((l) => re.test(l)) ?? text;
|
|
26348
|
+
}
|
|
26349
|
+
var EDIT_TOOLS = /* @__PURE__ */ new Set(["Edit", "Write", "MultiEdit", "NotebookEdit"]);
|
|
26350
|
+
var GIT_OP = /^\s*git\s+(commit|checkout|switch|merge|rebase|push|pull|stash|reset|revert|cherry-pick|tag|branch\s+-[dD])/;
|
|
26351
|
+
function callKey(toolName, toolInput) {
|
|
26352
|
+
return `${toolName}:${createHash2("sha1").update(JSON.stringify(toolInput)).digest("hex").slice(0, 12)}`;
|
|
26353
|
+
}
|
|
26354
|
+
function responseText(r) {
|
|
26355
|
+
if (typeof r === "string") return r;
|
|
26356
|
+
if (r && typeof r === "object") {
|
|
26357
|
+
const o = r;
|
|
26358
|
+
if (typeof o.stdout === "string")
|
|
26359
|
+
return `${o.stdout}
|
|
26360
|
+
${typeof o.stderr === "string" ? o.stderr : ""}`;
|
|
26361
|
+
if (Array.isArray(o.content)) {
|
|
26362
|
+
return o.content.map(
|
|
26363
|
+
(c) => c && typeof c === "object" && typeof c.text === "string" ? c.text : ""
|
|
26364
|
+
).join("\n");
|
|
26365
|
+
}
|
|
26366
|
+
if (typeof o.error === "string") return o.error;
|
|
26367
|
+
}
|
|
26368
|
+
return "";
|
|
26369
|
+
}
|
|
26370
|
+
function responseFailed(r) {
|
|
26371
|
+
if (!r || typeof r !== "object") return void 0;
|
|
26372
|
+
const o = r;
|
|
26373
|
+
if (o.is_error === true || o.isError === true) return clip(responseText(r), 400);
|
|
26374
|
+
if (typeof o.exit_code === "number" && o.exit_code !== 0) return clip(responseText(r), 400);
|
|
26375
|
+
if (typeof o.interrupted === "boolean" && o.interrupted) return "interrupted";
|
|
26376
|
+
return void 0;
|
|
26377
|
+
}
|
|
26378
|
+
function classifyToolCall(info) {
|
|
26379
|
+
const { toolName, toolInput, root } = info;
|
|
26380
|
+
const out = [];
|
|
26381
|
+
const key = callKey(toolName, toolInput);
|
|
26382
|
+
out.push(ev("tool_call", { key, summary: summarizeInput(toolName, toolInput) }, toolName));
|
|
26383
|
+
if (EDIT_TOOLS.has(toolName)) {
|
|
26384
|
+
const fp = String(toolInput.file_path ?? toolInput.notebook_path ?? "");
|
|
26385
|
+
if (fp) {
|
|
26386
|
+
const rel = relPath(root, fp);
|
|
26387
|
+
if (/\.claude\/plans\/|\/plans\/.*\.md$/.test(fp))
|
|
26388
|
+
out.push(ev("plans", { path: rel, action: toolName }, toolName));
|
|
26389
|
+
else out.push(ev("files", { path: rel, action: toolName }, toolName));
|
|
26390
|
+
if (/(^|\/)(CLAUDE|AGENTS)\.md$|\.claude\/settings/.test(fp))
|
|
26391
|
+
out.push(ev("rules", { path: rel, action: toolName }, toolName));
|
|
26392
|
+
}
|
|
26393
|
+
}
|
|
26394
|
+
if (toolName === "Bash") {
|
|
26395
|
+
const cmd = String(toolInput.command ?? "");
|
|
26396
|
+
if (GIT_OP.test(cmd)) out.push(ev("git", { command: clip(cmd, 200) }, toolName));
|
|
26397
|
+
}
|
|
26398
|
+
if (toolName === "TodoWrite" && Array.isArray(toolInput.todos)) {
|
|
26399
|
+
const todos = toolInput.todos;
|
|
26400
|
+
out.push(
|
|
26401
|
+
ev(
|
|
26402
|
+
"tasks",
|
|
26403
|
+
{
|
|
26404
|
+
todos: todos.slice(0, 12).map(
|
|
26405
|
+
(t) => `${t.status === "completed" ? "x" : t.status === "in_progress" ? ">" : " "} ${clip(t.content, 80)}`
|
|
26406
|
+
)
|
|
26407
|
+
},
|
|
26408
|
+
toolName
|
|
26409
|
+
)
|
|
26410
|
+
);
|
|
26411
|
+
}
|
|
26412
|
+
if (toolName === "ExitPlanMode") out.push(ev("plans", { action: "plan approved" }, toolName));
|
|
26413
|
+
if (toolName === "Agent" || toolName === "Task") {
|
|
26414
|
+
out.push(
|
|
26415
|
+
ev(
|
|
26416
|
+
"subagent",
|
|
26417
|
+
{ description: clip(toolInput.description, 120), type: toolInput.subagent_type },
|
|
26418
|
+
toolName
|
|
26419
|
+
)
|
|
26420
|
+
);
|
|
26421
|
+
}
|
|
26422
|
+
if (toolName === "Skill") out.push(ev("skill", { skill: clip(toolInput.skill, 80) }, toolName));
|
|
26423
|
+
if (toolName === "WebFetch" || toolName === "WebSearch") {
|
|
26424
|
+
out.push(ev("external_ref", { url: clip(toolInput.url ?? toolInput.query, 200) }, toolName));
|
|
26425
|
+
}
|
|
26426
|
+
if (toolName.startsWith("mcp__")) out.push(ev("mcp_tool", { tool: toolName }, toolName));
|
|
26427
|
+
if (info.durationMs && info.durationMs > 5e3) {
|
|
26428
|
+
out.push(
|
|
26429
|
+
ev(
|
|
26430
|
+
"latency",
|
|
26431
|
+
{ ms: info.durationMs, summary: summarizeInput(toolName, toolInput) },
|
|
26432
|
+
toolName
|
|
26433
|
+
)
|
|
26434
|
+
);
|
|
26435
|
+
}
|
|
26436
|
+
const failure2 = info.error ?? responseFailed(info.toolResponse);
|
|
26437
|
+
if (failure2)
|
|
26438
|
+
out.push(
|
|
26439
|
+
ev(
|
|
26440
|
+
"error",
|
|
26441
|
+
{ tool: toolName, summary: summarizeInput(toolName, toolInput), error: clip(failure2, 400) },
|
|
26442
|
+
toolName
|
|
26443
|
+
)
|
|
26444
|
+
);
|
|
26445
|
+
return out;
|
|
26446
|
+
}
|
|
26447
|
+
function summarizeInput(toolName, input2) {
|
|
26448
|
+
const pick2 = input2.command ?? input2.file_path ?? input2.pattern ?? input2.url ?? input2.prompt ?? input2.query ?? input2.description ?? input2.skill;
|
|
26449
|
+
return clip(`${toolName} ${pick2 ?? ""}`.trim(), 160);
|
|
26450
|
+
}
|
|
26451
|
+
function classifyAssistant(message) {
|
|
26452
|
+
const out = [];
|
|
26453
|
+
if (!message.trim()) return out;
|
|
26454
|
+
out.push(ev("assistant_summary", { text: clip(message.replace(/\s+/g, " "), 500) }));
|
|
26455
|
+
if (DECISION.test(message))
|
|
26456
|
+
out.push(
|
|
26457
|
+
ev("decision", { text: clip(firstMatchLine(message, DECISION), 300), by: "assistant" })
|
|
26458
|
+
);
|
|
26459
|
+
if (RESOLVED.test(message))
|
|
26460
|
+
out.push(ev("error_resolution", { text: clip(firstMatchLine(message, RESOLVED), 300) }));
|
|
26461
|
+
if (BLOCKER.test(message))
|
|
26462
|
+
out.push(ev("blocker", { text: clip(firstMatchLine(message, BLOCKER), 300), by: "assistant" }));
|
|
26463
|
+
return out;
|
|
26464
|
+
}
|
|
26465
|
+
|
|
26466
|
+
// src/index/indexer.ts
|
|
26467
|
+
init_esm_shims();
|
|
26468
|
+
var import_fast_glob = __toESM(require_out4(), 1);
|
|
26469
|
+
import { readFileSync as readFileSync3, statSync } from "fs";
|
|
26470
|
+
import { relative as relative2, resolve as resolve2 } from "path";
|
|
26471
|
+
|
|
26472
|
+
// src/chunker/index.ts
|
|
26473
|
+
init_esm_shims();
|
|
26474
|
+
import { extname } from "path";
|
|
26475
|
+
|
|
26476
|
+
// src/chunker/code.ts
|
|
26477
|
+
init_esm_shims();
|
|
26478
|
+
|
|
26479
|
+
// src/chunker/types.ts
|
|
26480
|
+
init_esm_shims();
|
|
26481
|
+
import { createHash as createHash3 } from "crypto";
|
|
26482
|
+
var DEFAULT_CHUNKER = { maxChars: 1800, overlapLines: 5 };
|
|
26483
|
+
function hashText(s) {
|
|
26484
|
+
return createHash3("sha1").update(s).digest("hex");
|
|
26289
26485
|
}
|
|
26290
26486
|
function finalize2(raw, contentType) {
|
|
26291
26487
|
return raw.filter((r) => r.body.trim().length > 0).map((r, ord) => ({
|
|
@@ -26434,7 +26630,7 @@ function chunkMarkdown(text, baseTitle, opts = DEFAULT_CHUNKER) {
|
|
|
26434
26630
|
if (/^\s*(```|~~~)/.test(line2)) inFence = !inFence;
|
|
26435
26631
|
const m = !inFence && /^(#{1,6})\s+(.+?)\s*#*\s*$/.exec(line2);
|
|
26436
26632
|
if (m) {
|
|
26437
|
-
|
|
26633
|
+
sections.push(current);
|
|
26438
26634
|
const level = m[1].length;
|
|
26439
26635
|
while (stack.length && stack[stack.length - 1].level >= level) stack.pop();
|
|
26440
26636
|
stack.push({ level, text: m[2] });
|
|
@@ -26443,14 +26639,23 @@ function chunkMarkdown(text, baseTitle, opts = DEFAULT_CHUNKER) {
|
|
|
26443
26639
|
}
|
|
26444
26640
|
current.lines.push(line2);
|
|
26445
26641
|
});
|
|
26446
|
-
|
|
26642
|
+
sections.push(current);
|
|
26447
26643
|
const out = [];
|
|
26448
|
-
|
|
26644
|
+
sections.forEach((s, k) => {
|
|
26449
26645
|
const title = s.path.length ? `${baseTitle} > ${s.path.join(" > ")}` : baseTitle;
|
|
26450
26646
|
const body = s.lines.join("\n");
|
|
26647
|
+
if (!body.trim()) {
|
|
26648
|
+
const next = sections[k + 1];
|
|
26649
|
+
const isParent = next !== void 0 && next.path.length > s.path.length && s.path.every((p, j) => next.path[j] === p);
|
|
26650
|
+
if (s.path.length && !isParent) {
|
|
26651
|
+
const heading = s.path[s.path.length - 1];
|
|
26652
|
+
out.push({ title, body: heading, startLine: s.startLine, endLine: s.startLine });
|
|
26653
|
+
}
|
|
26654
|
+
return;
|
|
26655
|
+
}
|
|
26451
26656
|
if (body.length <= opts.maxChars) {
|
|
26452
26657
|
out.push({ title, body, startLine: s.startLine, endLine: s.startLine + s.lines.length - 1 });
|
|
26453
|
-
|
|
26658
|
+
return;
|
|
26454
26659
|
}
|
|
26455
26660
|
let fence = false;
|
|
26456
26661
|
const fenceState = s.lines.map((l) => {
|
|
@@ -26466,7 +26671,7 @@ function chunkMarkdown(text, baseTitle, opts = DEFAULT_CHUNKER) {
|
|
|
26466
26671
|
s.startLine - 1
|
|
26467
26672
|
)
|
|
26468
26673
|
);
|
|
26469
|
-
}
|
|
26674
|
+
});
|
|
26470
26675
|
return out;
|
|
26471
26676
|
}
|
|
26472
26677
|
|
|
@@ -26549,7 +26754,20 @@ function chunk(content, baseTitle, kind, uri, opts = DEFAULT_CHUNKER) {
|
|
|
26549
26754
|
// src/index/indexer.ts
|
|
26550
26755
|
function indexContent(db, input2) {
|
|
26551
26756
|
const kind = input2.kind ?? (input2.contentType === "code" ? "code" : input2.contentType === "json" ? "json" : void 0);
|
|
26552
|
-
const
|
|
26757
|
+
const cut = input2.chunks ? { chunks: finalize2(input2.chunks, input2.contentType ?? "code"), kind: kind ?? "code" } : chunk(input2.content, input2.title, kind, input2.uri);
|
|
26758
|
+
const k = cut.kind;
|
|
26759
|
+
const fallback = cut.chunks.length === 0 && input2.content.trim().length > 0;
|
|
26760
|
+
const chunks = fallback ? finalize2(
|
|
26761
|
+
[
|
|
26762
|
+
{
|
|
26763
|
+
title: input2.title,
|
|
26764
|
+
body: input2.content,
|
|
26765
|
+
startLine: 1,
|
|
26766
|
+
endLine: input2.content.split("\n").length
|
|
26767
|
+
}
|
|
26768
|
+
],
|
|
26769
|
+
kindToContentType(k)
|
|
26770
|
+
) : cut.chunks;
|
|
26553
26771
|
const contentHash = hashText(input2.content);
|
|
26554
26772
|
const existing = input2.uri ? db.findDocumentByUri(input2.uri) : void 0;
|
|
26555
26773
|
if (existing && existing.content_hash === contentHash) {
|
|
@@ -26559,7 +26777,8 @@ function indexContent(db, input2) {
|
|
|
26559
26777
|
created: false,
|
|
26560
26778
|
chunks: chunks.length,
|
|
26561
26779
|
chars: input2.content.length,
|
|
26562
|
-
kind: k
|
|
26780
|
+
kind: k,
|
|
26781
|
+
fallback
|
|
26563
26782
|
};
|
|
26564
26783
|
}
|
|
26565
26784
|
db.deleteDocument(existing.id);
|
|
@@ -26576,7 +26795,14 @@ function indexContent(db, input2) {
|
|
|
26576
26795
|
},
|
|
26577
26796
|
chunks
|
|
26578
26797
|
);
|
|
26579
|
-
return {
|
|
26798
|
+
return {
|
|
26799
|
+
documentId: id,
|
|
26800
|
+
created,
|
|
26801
|
+
chunks: chunks.length,
|
|
26802
|
+
chars: input2.content.length,
|
|
26803
|
+
kind: k,
|
|
26804
|
+
fallback
|
|
26805
|
+
};
|
|
26580
26806
|
}
|
|
26581
26807
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
26582
26808
|
|
|
@@ -26597,6 +26823,23 @@ function fileOf(id) {
|
|
|
26597
26823
|
return void 0;
|
|
26598
26824
|
}
|
|
26599
26825
|
|
|
26826
|
+
// src/graph/metrics.ts
|
|
26827
|
+
init_esm_shims();
|
|
26828
|
+
|
|
26829
|
+
// src/graph/clusters.ts
|
|
26830
|
+
init_esm_shims();
|
|
26831
|
+
|
|
26832
|
+
// src/graph/metrics.ts
|
|
26833
|
+
var DEPENDENCY_KINDS = [
|
|
26834
|
+
"calls",
|
|
26835
|
+
"references",
|
|
26836
|
+
"extends",
|
|
26837
|
+
"implements",
|
|
26838
|
+
"imports",
|
|
26839
|
+
"reexports",
|
|
26840
|
+
"handles"
|
|
26841
|
+
];
|
|
26842
|
+
|
|
26600
26843
|
// src/history/model.ts
|
|
26601
26844
|
init_esm_shims();
|
|
26602
26845
|
|
|
@@ -27298,6 +27541,9 @@ function memoriesForFile(db, rel, opts = {}) {
|
|
|
27298
27541
|
}
|
|
27299
27542
|
var RISKY = 0.3;
|
|
27300
27543
|
var FAN_IN = 5;
|
|
27544
|
+
function dependentFiles(db, paths2) {
|
|
27545
|
+
return db.graphDependentFileCounts(paths2, DEPENDENCY_KINDS);
|
|
27546
|
+
}
|
|
27301
27547
|
function riskLine(path2, f) {
|
|
27302
27548
|
if (f.risk < RISKY && !f.bugOrigins) return void 0;
|
|
27303
27549
|
const parts = [`${f.fixes}/${f.commits} commits were fixes`];
|
|
@@ -27325,10 +27571,10 @@ function fileContext(db, rel, opts = {}) {
|
|
|
27325
27571
|
}
|
|
27326
27572
|
const fanKey = `fanin:${rel}`;
|
|
27327
27573
|
if (opts.edit && !seen.has(fanKey)) {
|
|
27328
|
-
const
|
|
27329
|
-
if (
|
|
27574
|
+
const dependents = dependentFiles(db, [rel]).get(rel) ?? 0;
|
|
27575
|
+
if (dependents >= FAN_IN) {
|
|
27330
27576
|
lines.push(
|
|
27331
|
-
`eminiar graph: ${rel} is imported by ${
|
|
27577
|
+
`eminiar graph: ${rel} is imported by ${dependents} files; em_graph_impact {node:"${fileId(rel)}"} lists them before you change an exported signature.`
|
|
27332
27578
|
);
|
|
27333
27579
|
keys.push(fanKey);
|
|
27334
27580
|
}
|
|
@@ -27340,7 +27586,7 @@ function commitContext(db, files) {
|
|
|
27340
27586
|
if (!files.length) return "";
|
|
27341
27587
|
const table = readFileRisk(db);
|
|
27342
27588
|
const risky = files.map((p) => table[p] ? riskLine(p, table[p]) : void 0).filter((l) => !!l).slice(0, 4);
|
|
27343
|
-
const wide = db
|
|
27589
|
+
const wide = [...dependentFiles(db, files)].filter(([, n]) => n >= FAN_IN).sort((a, b) => b[1] - a[1]).slice(0, 4).map(([p, n]) => `${p} (${n} importers)`);
|
|
27344
27590
|
if (!risky.length && !wide.length) return "";
|
|
27345
27591
|
const lines = ["eminiar history: this commit includes files that deserve a second look:"];
|
|
27346
27592
|
for (const r of risky) lines.push(`- ${r}`);
|
|
@@ -27624,6 +27870,10 @@ function topTermsOf(bodies, limit) {
|
|
|
27624
27870
|
|
|
27625
27871
|
// src/storage/sqlite/schema.ts
|
|
27626
27872
|
init_esm_shims();
|
|
27873
|
+
function hasColumn(db, table, column) {
|
|
27874
|
+
const cols = db.pragma(`table_info(${table})`);
|
|
27875
|
+
return cols.some((c) => c.name === column);
|
|
27876
|
+
}
|
|
27627
27877
|
var migrations = [
|
|
27628
27878
|
{
|
|
27629
27879
|
version: 1,
|
|
@@ -27958,7 +28208,6 @@ CREATE TABLE IF NOT EXISTS transcript_files (
|
|
|
27958
28208
|
offset INTEGER NOT NULL DEFAULT 0,
|
|
27959
28209
|
size INTEGER NOT NULL DEFAULT 0,
|
|
27960
28210
|
mtime INTEGER NOT NULL DEFAULT 0,
|
|
27961
|
-
head_hash TEXT,
|
|
27962
28211
|
ingested_at INTEGER NOT NULL
|
|
27963
28212
|
);
|
|
27964
28213
|
|
|
@@ -27986,6 +28235,16 @@ CREATE TABLE IF NOT EXISTS statusline_snapshots (
|
|
|
27986
28235
|
CREATE INDEX IF NOT EXISTS statusline_snapshots_session_ts ON statusline_snapshots(session_id, ts);
|
|
27987
28236
|
CREATE INDEX IF NOT EXISTS statusline_snapshots_ts ON statusline_snapshots(ts);
|
|
27988
28237
|
`
|
|
28238
|
+
},
|
|
28239
|
+
{
|
|
28240
|
+
// transcript_files.head_hash (fingerprint of the file head, so a rewrite with the same
|
|
28241
|
+
// size is noticed) was first added to v5 after v5 had already run on real databases, so
|
|
28242
|
+
// version-5 databases exist both with and without the column. Add it only when missing.
|
|
28243
|
+
version: 6,
|
|
28244
|
+
up(db) {
|
|
28245
|
+
if (!hasColumn(db, "transcript_files", "head_hash"))
|
|
28246
|
+
db.exec("ALTER TABLE transcript_files ADD COLUMN head_hash TEXT");
|
|
28247
|
+
}
|
|
27989
28248
|
}
|
|
27990
28249
|
];
|
|
27991
28250
|
function vecTableSql(dims) {
|
|
@@ -28097,7 +28356,8 @@ var SqliteAdapter = class _SqliteAdapter {
|
|
|
28097
28356
|
if (pending.length) {
|
|
28098
28357
|
this.transaction(() => {
|
|
28099
28358
|
for (const m of pending) {
|
|
28100
|
-
this.db.exec(m.sql);
|
|
28359
|
+
if (m.sql) this.db.exec(m.sql);
|
|
28360
|
+
m.up?.(this.db);
|
|
28101
28361
|
this.metaSet("schema_version", String(m.version));
|
|
28102
28362
|
}
|
|
28103
28363
|
});
|
|
@@ -28316,18 +28576,42 @@ var SqliteAdapter = class _SqliteAdapter {
|
|
|
28316
28576
|
}
|
|
28317
28577
|
vecSearch(embedding, k, filters) {
|
|
28318
28578
|
if (!this.vectors) return [];
|
|
28319
|
-
const raw = this.db.prepare(
|
|
28320
|
-
"SELECT chunk_id id, distance FROM chunk_vec WHERE embedding MATCH ? AND k = ? ORDER BY distance"
|
|
28321
|
-
).all(embedding, BigInt(filters ? k * 4 : k));
|
|
28322
|
-
if (!filters || !raw.length) return raw.map((r) => ({ chunkId: r.id, distance: r.distance }));
|
|
28323
28579
|
const { where, params } = filterSql(filters);
|
|
28324
|
-
|
|
28325
|
-
|
|
28326
|
-
|
|
28327
|
-
|
|
28328
|
-
|
|
28329
|
-
|
|
28330
|
-
|
|
28580
|
+
if (!where) return this.knn(embedding, k);
|
|
28581
|
+
try {
|
|
28582
|
+
return this.knn(
|
|
28583
|
+
embedding,
|
|
28584
|
+
k,
|
|
28585
|
+
`AND chunk_id IN (SELECT c.id FROM chunks c JOIN documents d ON d.id = c.document_id WHERE 1=1${where})`,
|
|
28586
|
+
params
|
|
28587
|
+
);
|
|
28588
|
+
} catch {
|
|
28589
|
+
return this.vecSearchWidening(embedding, k, where, params);
|
|
28590
|
+
}
|
|
28591
|
+
}
|
|
28592
|
+
knn(embedding, k, extra = "", params = []) {
|
|
28593
|
+
return this.db.prepare(
|
|
28594
|
+
`SELECT chunk_id id, distance FROM chunk_vec WHERE embedding MATCH ? AND k = ? ${extra} ORDER BY distance`
|
|
28595
|
+
).all(embedding, BigInt(k), ...params).map((r) => ({ chunkId: r.id, distance: r.distance }));
|
|
28596
|
+
}
|
|
28597
|
+
/** Fallback filtered KNN: fetch k*4, k*16, ... nearest until k pass the filter or all were seen. */
|
|
28598
|
+
vecSearchWidening(embedding, k, where, params) {
|
|
28599
|
+
const total = this.vecCount();
|
|
28600
|
+
for (let fetch = k * 4; ; fetch *= 4) {
|
|
28601
|
+
const raw = this.knn(embedding, Math.min(fetch, total));
|
|
28602
|
+
if (!raw.length) return [];
|
|
28603
|
+
const allowed = /* @__PURE__ */ new Set();
|
|
28604
|
+
for (let i = 0; i < raw.length; i += 400) {
|
|
28605
|
+
const ids = raw.slice(i, i + 400).map((r) => r.chunkId);
|
|
28606
|
+
for (const r of this.db.prepare(
|
|
28607
|
+
`SELECT c.id FROM chunks c JOIN documents d ON d.id = c.document_id
|
|
28608
|
+
WHERE c.id IN (${ids.map(() => "?").join(",")})${where}`
|
|
28609
|
+
).all(...ids, ...params))
|
|
28610
|
+
allowed.add(r.id);
|
|
28611
|
+
}
|
|
28612
|
+
const hits = raw.filter((r) => allowed.has(r.chunkId)).slice(0, k);
|
|
28613
|
+
if (hits.length >= k || fetch >= total) return hits;
|
|
28614
|
+
}
|
|
28331
28615
|
}
|
|
28332
28616
|
unembeddedChunkIds(limit) {
|
|
28333
28617
|
return this.db.prepare("SELECT id FROM chunks WHERE embedded = 0 ORDER BY id LIMIT ?").all(limit).map((r) => r.id);
|
|
@@ -28606,6 +28890,26 @@ var SqliteAdapter = class _SqliteAdapter {
|
|
|
28606
28890
|
}
|
|
28607
28891
|
return out;
|
|
28608
28892
|
}
|
|
28893
|
+
graphDependentFileCounts(paths2, kinds) {
|
|
28894
|
+
const out = /* @__PURE__ */ new Map();
|
|
28895
|
+
if (!paths2.length || !kinds.length) return out;
|
|
28896
|
+
const kph = kinds.map(() => "?").join(",");
|
|
28897
|
+
for (let i = 0; i < paths2.length; i += 400) {
|
|
28898
|
+
const batch = paths2.slice(i, i + 400);
|
|
28899
|
+
const pph = batch.map(() => "?").join(",");
|
|
28900
|
+
for (const r of this.db.prepare(
|
|
28901
|
+
`SELECT d.path p, COUNT(DISTINCT s.path) n
|
|
28902
|
+
FROM graph_nodes d
|
|
28903
|
+
JOIN graph_edges e ON e.dst = d.id AND e.kind IN (${kph})
|
|
28904
|
+
JOIN graph_nodes s ON s.id = e.src
|
|
28905
|
+
WHERE d.path IN (${pph}) AND s.path IS NOT NULL AND s.path <> d.path
|
|
28906
|
+
GROUP BY d.path`
|
|
28907
|
+
).all(...kinds, ...batch)) {
|
|
28908
|
+
out.set(r.p, r.n);
|
|
28909
|
+
}
|
|
28910
|
+
}
|
|
28911
|
+
return out;
|
|
28912
|
+
}
|
|
28609
28913
|
edgesWhere(col, ids, kinds) {
|
|
28610
28914
|
if (!ids.length) return [];
|
|
28611
28915
|
const out = [];
|
|
@@ -30274,9 +30578,9 @@ function budgetWarnings(db, ctx, sessionId, now = Date.now()) {
|
|
|
30274
30578
|
// src/usage/ingest.ts
|
|
30275
30579
|
init_esm_shims();
|
|
30276
30580
|
import { createHash as createHash4 } from "crypto";
|
|
30277
|
-
import { closeSync, existsSync as
|
|
30278
|
-
import { homedir as
|
|
30279
|
-
import { basename, dirname as dirname2, join as
|
|
30581
|
+
import { closeSync, existsSync as existsSync4, openSync, readdirSync, readSync, statSync as statSync2 } from "fs";
|
|
30582
|
+
import { homedir as homedir3 } from "os";
|
|
30583
|
+
import { basename, dirname as dirname2, join as join5, resolve as resolve3, sep } from "path";
|
|
30280
30584
|
|
|
30281
30585
|
// src/usage/transcript.ts
|
|
30282
30586
|
init_esm_shims();
|
|
@@ -30285,7 +30589,7 @@ var DENIAL_RE = /^\s*PreToolUse:|hook error|\bdenied\b/i;
|
|
|
30285
30589
|
function isObj(v) {
|
|
30286
30590
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
30287
30591
|
}
|
|
30288
|
-
function
|
|
30592
|
+
function str2(v) {
|
|
30289
30593
|
return typeof v === "string" && v.length ? v : null;
|
|
30290
30594
|
}
|
|
30291
30595
|
function num3(v) {
|
|
@@ -30313,8 +30617,8 @@ function resultChars(content) {
|
|
|
30313
30617
|
n += safeJsonLength(part);
|
|
30314
30618
|
continue;
|
|
30315
30619
|
}
|
|
30316
|
-
const kind =
|
|
30317
|
-
if (kind === "text" || typeof part.text === "string") n +=
|
|
30620
|
+
const kind = str2(part.type);
|
|
30621
|
+
if (kind === "text" || typeof part.text === "string") n += str2(part.text)?.length ?? 0;
|
|
30318
30622
|
else if (kind === "image" || kind === "document" || kind === "tool_reference")
|
|
30319
30623
|
n += NON_TEXT_PART_CHARS;
|
|
30320
30624
|
else n += safeJsonLength(part);
|
|
@@ -30359,10 +30663,10 @@ function parseTranscriptLines(lines, ctx) {
|
|
|
30359
30663
|
continue;
|
|
30360
30664
|
}
|
|
30361
30665
|
if (!isObj(e)) continue;
|
|
30362
|
-
const type =
|
|
30666
|
+
const type = str2(e.type);
|
|
30363
30667
|
if (!type) continue;
|
|
30364
|
-
const sessionId =
|
|
30365
|
-
const agentId =
|
|
30668
|
+
const sessionId = str2(e.sessionId) ?? ctx.sessionId;
|
|
30669
|
+
const agentId = str2(e.agentId);
|
|
30366
30670
|
const sidechain = e.isSidechain === true ? 1 : 0;
|
|
30367
30671
|
const real = tsOf(e);
|
|
30368
30672
|
const ts = real ?? prevTs ?? fallbackTs;
|
|
@@ -30371,12 +30675,12 @@ function parseTranscriptLines(lines, ctx) {
|
|
|
30371
30675
|
if (type === "assistant") {
|
|
30372
30676
|
const msg = isObj(e.message) ? e.message : void 0;
|
|
30373
30677
|
if (!msg) continue;
|
|
30374
|
-
const messageId =
|
|
30375
|
-
const requestId =
|
|
30678
|
+
const messageId = str2(msg.id);
|
|
30679
|
+
const requestId = str2(e.requestId) ?? messageId;
|
|
30376
30680
|
if (Array.isArray(msg.content)) {
|
|
30377
30681
|
for (const block of msg.content) {
|
|
30378
30682
|
if (!isObj(block) || block.type !== "tool_use") continue;
|
|
30379
|
-
const id =
|
|
30683
|
+
const id = str2(block.id);
|
|
30380
30684
|
if (!id) continue;
|
|
30381
30685
|
const prev2 = toolUses.get(id);
|
|
30382
30686
|
toolUses.set(id, {
|
|
@@ -30384,7 +30688,7 @@ function parseTranscriptLines(lines, ctx) {
|
|
|
30384
30688
|
session_id: prev2?.session_id ?? sessionId,
|
|
30385
30689
|
agent_id: prev2?.agent_id ?? agentId,
|
|
30386
30690
|
ts: prev2?.ts ?? ts,
|
|
30387
|
-
tool:
|
|
30691
|
+
tool: str2(block.name) ?? prev2?.tool ?? "",
|
|
30388
30692
|
input_chars: block.input === void 0 ? 0 : safeJsonLength(block.input),
|
|
30389
30693
|
result_chars: prev2?.result_chars ?? null,
|
|
30390
30694
|
is_error: prev2?.is_error ?? 0,
|
|
@@ -30394,7 +30698,7 @@ function parseTranscriptLines(lines, ctx) {
|
|
|
30394
30698
|
}
|
|
30395
30699
|
const usage = isObj(msg.usage) ? msg.usage : void 0;
|
|
30396
30700
|
if (!usage || !messageId || !requestId) continue;
|
|
30397
|
-
const model =
|
|
30701
|
+
const model = str2(msg.model) ?? "unknown";
|
|
30398
30702
|
const cc = isObj(usage.cache_creation) ? usage.cache_creation : void 0;
|
|
30399
30703
|
const create5m = cc ? num3(cc.ephemeral_5m_input_tokens) : num3(usage.cache_creation_input_tokens);
|
|
30400
30704
|
const create1h = cc ? num3(cc.ephemeral_1h_input_tokens) : 0;
|
|
@@ -30418,15 +30722,15 @@ function parseTranscriptLines(lines, ctx) {
|
|
|
30418
30722
|
thinking_tokens: details ? num3(details.thinking_tokens) : 0,
|
|
30419
30723
|
web_searches: server ? num3(server.web_search_requests) : 0,
|
|
30420
30724
|
web_fetches: server ? num3(server.web_fetch_requests) : 0,
|
|
30421
|
-
service_tier:
|
|
30422
|
-
speed:
|
|
30423
|
-
stop_reason:
|
|
30424
|
-
prompt_id:
|
|
30425
|
-
git_branch:
|
|
30426
|
-
cwd:
|
|
30427
|
-
effort:
|
|
30428
|
-
version:
|
|
30429
|
-
entrypoint:
|
|
30725
|
+
service_tier: str2(usage.service_tier),
|
|
30726
|
+
speed: str2(usage.speed),
|
|
30727
|
+
stop_reason: str2(msg.stop_reason) ?? prev?.stop_reason ?? null,
|
|
30728
|
+
prompt_id: str2(e.promptId) ?? prev?.prompt_id ?? null,
|
|
30729
|
+
git_branch: str2(e.gitBranch) ?? prev?.git_branch ?? null,
|
|
30730
|
+
cwd: str2(e.cwd) ?? prev?.cwd ?? null,
|
|
30731
|
+
effort: str2(e.effort) ?? prev?.effort ?? null,
|
|
30732
|
+
version: str2(e.version) ?? prev?.version ?? null,
|
|
30733
|
+
entrypoint: str2(e.entrypoint) ?? prev?.entrypoint ?? null
|
|
30430
30734
|
});
|
|
30431
30735
|
continue;
|
|
30432
30736
|
}
|
|
@@ -30435,7 +30739,7 @@ function parseTranscriptLines(lines, ctx) {
|
|
|
30435
30739
|
if (!msg || !Array.isArray(msg.content)) continue;
|
|
30436
30740
|
for (const block of msg.content) {
|
|
30437
30741
|
if (!isObj(block) || block.type !== "tool_result") continue;
|
|
30438
|
-
const id =
|
|
30742
|
+
const id = str2(block.tool_use_id);
|
|
30439
30743
|
if (!id) continue;
|
|
30440
30744
|
const prev = toolUses.get(id);
|
|
30441
30745
|
let isError = prev?.is_error ?? 0;
|
|
@@ -30458,20 +30762,20 @@ function parseTranscriptLines(lines, ctx) {
|
|
|
30458
30762
|
continue;
|
|
30459
30763
|
}
|
|
30460
30764
|
if (type === "system") {
|
|
30461
|
-
const subtype =
|
|
30765
|
+
const subtype = str2(e.subtype);
|
|
30462
30766
|
if (subtype === "compact_boundary") {
|
|
30463
30767
|
const meta3 = isObj(e.compactMetadata) ? e.compactMetadata : void 0;
|
|
30464
30768
|
contextEvents.push({
|
|
30465
30769
|
session_id: sessionId,
|
|
30466
30770
|
ts,
|
|
30467
30771
|
kind: "compact",
|
|
30468
|
-
trigger: meta3 ?
|
|
30772
|
+
trigger: meta3 ? str2(meta3.trigger) : null,
|
|
30469
30773
|
pre_tokens: meta3 ? numOrNull(meta3.preTokens) : null,
|
|
30470
30774
|
post_tokens: meta3 ? numOrNull(meta3.postTokens) : null
|
|
30471
30775
|
});
|
|
30472
30776
|
} else if (subtype === "local_command") {
|
|
30473
30777
|
const run = isObj(e.commandRun) ? e.commandRun : void 0;
|
|
30474
|
-
if (run &&
|
|
30778
|
+
if (run && str2(run.command) === "clear") {
|
|
30475
30779
|
contextEvents.push({
|
|
30476
30780
|
session_id: sessionId,
|
|
30477
30781
|
ts,
|
|
@@ -30504,7 +30808,7 @@ function isValidSessionId(id) {
|
|
|
30504
30808
|
return SESSION_ID_RE.test(id);
|
|
30505
30809
|
}
|
|
30506
30810
|
function claudeDir() {
|
|
30507
|
-
return process.env.EMINIAR_CLAUDE_DIR ||
|
|
30811
|
+
return process.env.EMINIAR_CLAUDE_DIR || join5(homedir3(), ".claude");
|
|
30508
30812
|
}
|
|
30509
30813
|
function insideDir(path2, dir) {
|
|
30510
30814
|
const d = resolve3(dir);
|
|
@@ -30523,7 +30827,7 @@ function transcriptSlug(root) {
|
|
|
30523
30827
|
return root.replace(/[^A-Za-z0-9]/g, "-");
|
|
30524
30828
|
}
|
|
30525
30829
|
function transcriptDirFor(root) {
|
|
30526
|
-
return
|
|
30830
|
+
return join5(claudeDir(), "projects", transcriptSlug(root));
|
|
30527
30831
|
}
|
|
30528
30832
|
function usageEnabled(ctx) {
|
|
30529
30833
|
return ctx.config.usage.enabled !== false;
|
|
@@ -30693,7 +30997,7 @@ function add(a, b) {
|
|
|
30693
30997
|
}
|
|
30694
30998
|
function listJsonl(dir) {
|
|
30695
30999
|
try {
|
|
30696
|
-
return readdirSync(dir).filter((f) => f.endsWith(".jsonl")).map((f) =>
|
|
31000
|
+
return readdirSync(dir).filter((f) => f.endsWith(".jsonl")).map((f) => join5(dir, f));
|
|
30697
31001
|
} catch {
|
|
30698
31002
|
return [];
|
|
30699
31003
|
}
|
|
@@ -30713,7 +31017,7 @@ function firstEntrySessionId(path2) {
|
|
|
30713
31017
|
function sidechainFilesFor(db, dir, sessionId) {
|
|
30714
31018
|
if (!isValidSessionId(sessionId)) return [];
|
|
30715
31019
|
const inside = (p) => insideDir(p, dir) && p.endsWith(".jsonl");
|
|
30716
|
-
const out = listJsonl(
|
|
31020
|
+
const out = listJsonl(join5(dir, sessionId, "subagents")).filter(inside);
|
|
30717
31021
|
for (const path2 of listJsonl(dir)) {
|
|
30718
31022
|
if (!inside(path2) || !basename(path2).startsWith("agent-")) continue;
|
|
30719
31023
|
const known = db.transcriptFileGet(path2)?.session_id;
|
|
@@ -30755,6 +31059,18 @@ function ingestSession(db, root, sessionId, transcriptPath, opts = {}) {
|
|
|
30755
31059
|
return total;
|
|
30756
31060
|
}
|
|
30757
31061
|
|
|
31062
|
+
// src/hooks/log.ts
|
|
31063
|
+
init_esm_shims();
|
|
31064
|
+
import { appendFileSync } from "fs";
|
|
31065
|
+
function hookLog(level, msg) {
|
|
31066
|
+
try {
|
|
31067
|
+
const p = ensureDirs();
|
|
31068
|
+
appendFileSync(p.hookLog, `${(/* @__PURE__ */ new Date()).toISOString()} ${level} ${msg}
|
|
31069
|
+
`);
|
|
31070
|
+
} catch {
|
|
31071
|
+
}
|
|
31072
|
+
}
|
|
31073
|
+
|
|
30758
31074
|
// src/hooks/capture.ts
|
|
30759
31075
|
var INDEXED = /* @__PURE__ */ new Set([
|
|
30760
31076
|
"decision",
|
|
@@ -30797,6 +31113,7 @@ function open3(input2) {
|
|
|
30797
31113
|
});
|
|
30798
31114
|
return { db, root: ctx.root, sessionId };
|
|
30799
31115
|
}
|
|
31116
|
+
var usageFailureLogged = false;
|
|
30800
31117
|
function ingestUsage(db, input2, sessionId) {
|
|
30801
31118
|
try {
|
|
30802
31119
|
const ctx = getContext(input2.cwd);
|
|
@@ -30805,7 +31122,13 @@ function ingestUsage(db, input2, sessionId) {
|
|
|
30805
31122
|
ingestSession(db, ctx.root, sessionId, input2.transcript_path, { overrides });
|
|
30806
31123
|
if (input2.agent_transcript_path)
|
|
30807
31124
|
ingestTranscript(db, input2.agent_transcript_path, { sessionId, overrides });
|
|
30808
|
-
} catch {
|
|
31125
|
+
} catch (err) {
|
|
31126
|
+
if (usageFailureLogged) return;
|
|
31127
|
+
usageFailureLogged = true;
|
|
31128
|
+
hookLog(
|
|
31129
|
+
"error",
|
|
31130
|
+
`usage ingest failed (session ${sessionId}): ${err.message}; run \`eminiar usage ingest\` to see the error`
|
|
31131
|
+
);
|
|
30809
31132
|
}
|
|
30810
31133
|
}
|
|
30811
31134
|
var userPromptSubmit = async (input2) => {
|
|
@@ -31065,19 +31388,20 @@ var preCompact = (input2) => {
|
|
|
31065
31388
|
// src/hooks/routing.ts
|
|
31066
31389
|
init_esm_shims();
|
|
31067
31390
|
import { realpathSync as realpathSync4, statSync as statSync5 } from "fs";
|
|
31068
|
-
import { homedir as
|
|
31069
|
-
import { extname as extname2, join as
|
|
31391
|
+
import { homedir as homedir6 } from "os";
|
|
31392
|
+
import { extname as extname2, join as join13, relative as relative4, resolve as resolve4 } from "path";
|
|
31070
31393
|
|
|
31071
31394
|
// src/docs/manifest.ts
|
|
31072
31395
|
init_esm_shims();
|
|
31073
|
-
import { existsSync as
|
|
31074
|
-
import { dirname as dirname3, join as
|
|
31396
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
31397
|
+
import { dirname as dirname3, join as join6 } from "path";
|
|
31398
|
+
var DOCS_PREFIX = "docs:";
|
|
31075
31399
|
var NAME_RE = /^[a-z0-9][a-z0-9._-]{0,63}$/;
|
|
31076
31400
|
function isValidName(name) {
|
|
31077
31401
|
return NAME_RE.test(name);
|
|
31078
31402
|
}
|
|
31079
31403
|
function manifestPathAt(root, rel = ".eminiar/docs.json") {
|
|
31080
|
-
return
|
|
31404
|
+
return join6(root, rel);
|
|
31081
31405
|
}
|
|
31082
31406
|
function manifestPath(ctx) {
|
|
31083
31407
|
return manifestPathAt(ctx.root, ctx.config.docs.manifest);
|
|
@@ -31105,9 +31429,9 @@ function normalize(raw) {
|
|
|
31105
31429
|
return { version: 1, sources: out };
|
|
31106
31430
|
}
|
|
31107
31431
|
function readManifestAt(file3) {
|
|
31108
|
-
if (!
|
|
31432
|
+
if (!existsSync5(file3)) return empty();
|
|
31109
31433
|
try {
|
|
31110
|
-
return normalize(JSON.parse(
|
|
31434
|
+
return normalize(JSON.parse(readFileSync4(file3, "utf8")));
|
|
31111
31435
|
} catch {
|
|
31112
31436
|
return empty();
|
|
31113
31437
|
}
|
|
@@ -31118,9 +31442,9 @@ function readManifest(ctx) {
|
|
|
31118
31442
|
|
|
31119
31443
|
// src/permissions/settings.ts
|
|
31120
31444
|
init_esm_shims();
|
|
31121
|
-
import { existsSync as
|
|
31122
|
-
import { homedir as
|
|
31123
|
-
import { join as
|
|
31445
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5, realpathSync as realpathSync3, statSync as statSync3 } from "fs";
|
|
31446
|
+
import { homedir as homedir4 } from "os";
|
|
31447
|
+
import { join as join7 } from "path";
|
|
31124
31448
|
|
|
31125
31449
|
// src/permissions/rules.ts
|
|
31126
31450
|
init_esm_shims();
|
|
@@ -31157,9 +31481,9 @@ init_esm_shims();
|
|
|
31157
31481
|
|
|
31158
31482
|
// src/permissions/settings.ts
|
|
31159
31483
|
function readRules(file3) {
|
|
31160
|
-
if (!
|
|
31484
|
+
if (!existsSync6(file3)) return {};
|
|
31161
31485
|
try {
|
|
31162
|
-
const s = JSON.parse(
|
|
31486
|
+
const s = JSON.parse(readFileSync5(file3, "utf8"));
|
|
31163
31487
|
return s.permissions ?? {};
|
|
31164
31488
|
} catch {
|
|
31165
31489
|
return {};
|
|
@@ -31175,9 +31499,9 @@ function stamp(file3) {
|
|
|
31175
31499
|
var cache2 = /* @__PURE__ */ new Map();
|
|
31176
31500
|
function loadPermissionRules(root, extraDeny = []) {
|
|
31177
31501
|
const files = [
|
|
31178
|
-
|
|
31179
|
-
|
|
31180
|
-
|
|
31502
|
+
join7(homedir4(), ".claude", "settings.json"),
|
|
31503
|
+
join7(root, ".claude", "settings.json"),
|
|
31504
|
+
join7(root, ".claude", "settings.local.json")
|
|
31181
31505
|
];
|
|
31182
31506
|
const key = `${root}\0${extraDeny.join("\0")}`;
|
|
31183
31507
|
const stamps = files.map(stamp);
|
|
@@ -31215,8 +31539,8 @@ function checkReadPath(rules, abs) {
|
|
|
31215
31539
|
|
|
31216
31540
|
// src/session/brief.ts
|
|
31217
31541
|
init_esm_shims();
|
|
31218
|
-
import { existsSync as
|
|
31219
|
-
import { join as
|
|
31542
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
|
|
31543
|
+
import { join as join9 } from "path";
|
|
31220
31544
|
|
|
31221
31545
|
// src/memory/frontmatter.ts
|
|
31222
31546
|
init_esm_shims();
|
|
@@ -31250,15 +31574,15 @@ function parseMemoryFile(text) {
|
|
|
31250
31574
|
init_esm_shims();
|
|
31251
31575
|
var import_fast_glob2 = __toESM(require_out4(), 1);
|
|
31252
31576
|
import {
|
|
31253
|
-
existsSync as
|
|
31254
|
-
mkdirSync as
|
|
31255
|
-
readFileSync as
|
|
31577
|
+
existsSync as existsSync7,
|
|
31578
|
+
mkdirSync as mkdirSync4,
|
|
31579
|
+
readFileSync as readFileSync6,
|
|
31256
31580
|
renameSync,
|
|
31257
31581
|
statSync as statSync4,
|
|
31258
31582
|
unlinkSync,
|
|
31259
|
-
writeFileSync as
|
|
31583
|
+
writeFileSync as writeFileSync3
|
|
31260
31584
|
} from "fs";
|
|
31261
|
-
import { dirname as dirname4, join as
|
|
31585
|
+
import { dirname as dirname4, join as join8, relative as relative3, sep as sep2 } from "path";
|
|
31262
31586
|
|
|
31263
31587
|
// src/storage/types.ts
|
|
31264
31588
|
init_esm_shims();
|
|
@@ -31270,7 +31594,7 @@ function memoriesRel(ctx) {
|
|
|
31270
31594
|
return ctx.config.memories.dir.replace(/^\.\//, "").replace(/\/+$/, "");
|
|
31271
31595
|
}
|
|
31272
31596
|
function memoriesDir(ctx) {
|
|
31273
|
-
return
|
|
31597
|
+
return join8(ctx.root, memoriesRel(ctx));
|
|
31274
31598
|
}
|
|
31275
31599
|
|
|
31276
31600
|
// src/session/brief.ts
|
|
@@ -31313,10 +31637,10 @@ function historyLine(db) {
|
|
|
31313
31637
|
return `${parts.join("; ")}. em_history {action:"file", path} before editing, {action:"risk"} before committing.`;
|
|
31314
31638
|
}
|
|
31315
31639
|
function overviewParagraph(ctx) {
|
|
31316
|
-
const file3 =
|
|
31317
|
-
if (!
|
|
31640
|
+
const file3 = join9(memoriesDir(ctx), "onboarding", "overview.md");
|
|
31641
|
+
if (!existsSync8(file3)) return void 0;
|
|
31318
31642
|
try {
|
|
31319
|
-
const body = parseMemoryFile(
|
|
31643
|
+
const body = parseMemoryFile(readFileSync7(file3, "utf8")).body.trim();
|
|
31320
31644
|
const para = body.split(/\n\s*\n/).map(
|
|
31321
31645
|
(p) => p.replace(/^#+\s.*$/m, "").replace(/\s+/g, " ").trim()
|
|
31322
31646
|
).find((p) => p.length > 20);
|
|
@@ -31385,10 +31709,10 @@ function recordRouting(db, sessionId, e) {
|
|
|
31385
31709
|
|
|
31386
31710
|
// src/session/server-alive.ts
|
|
31387
31711
|
init_esm_shims();
|
|
31388
|
-
import { existsSync as
|
|
31389
|
-
import { join as
|
|
31712
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync5, readdirSync as readdirSync2, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
31713
|
+
import { join as join10 } from "path";
|
|
31390
31714
|
function markersDir(ctx) {
|
|
31391
|
-
return
|
|
31715
|
+
return join10(projectDir(ctx.id), "servers");
|
|
31392
31716
|
}
|
|
31393
31717
|
function processAlive(pid) {
|
|
31394
31718
|
try {
|
|
@@ -31400,13 +31724,13 @@ function processAlive(pid) {
|
|
|
31400
31724
|
}
|
|
31401
31725
|
function liveServers(ctx) {
|
|
31402
31726
|
const dir = markersDir(ctx);
|
|
31403
|
-
if (!
|
|
31727
|
+
if (!existsSync9(dir)) return [];
|
|
31404
31728
|
const live2 = [];
|
|
31405
31729
|
for (const name of readdirSync2(dir)) {
|
|
31406
31730
|
const pid = Number(name);
|
|
31407
31731
|
if (!Number.isInteger(pid) || pid <= 0) continue;
|
|
31408
31732
|
if (processAlive(pid)) live2.push(pid);
|
|
31409
|
-
else
|
|
31733
|
+
else rmSync2(join10(dir, name), { force: true });
|
|
31410
31734
|
}
|
|
31411
31735
|
return live2;
|
|
31412
31736
|
}
|
|
@@ -31416,30 +31740,30 @@ function serverAlive(ctx) {
|
|
|
31416
31740
|
|
|
31417
31741
|
// src/hooks/coexist.ts
|
|
31418
31742
|
init_esm_shims();
|
|
31419
|
-
import { readFileSync as
|
|
31420
|
-
import { join as
|
|
31743
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
31744
|
+
import { join as join12 } from "path";
|
|
31421
31745
|
|
|
31422
31746
|
// src/install/claude-config.ts
|
|
31423
31747
|
init_esm_shims();
|
|
31424
31748
|
import {
|
|
31425
31749
|
copyFileSync,
|
|
31426
|
-
existsSync as
|
|
31427
|
-
mkdirSync as
|
|
31750
|
+
existsSync as existsSync10,
|
|
31751
|
+
mkdirSync as mkdirSync6,
|
|
31428
31752
|
readdirSync as readdirSync3,
|
|
31429
|
-
readFileSync as
|
|
31430
|
-
writeFileSync as
|
|
31753
|
+
readFileSync as readFileSync8,
|
|
31754
|
+
writeFileSync as writeFileSync5
|
|
31431
31755
|
} from "fs";
|
|
31432
|
-
import { homedir as
|
|
31433
|
-
import { dirname as dirname5, join as
|
|
31434
|
-
var claudeDir2 = () => process.env.CLAUDE_CONFIG_DIR ||
|
|
31435
|
-
var pluginsDir = () =>
|
|
31756
|
+
import { homedir as homedir5 } from "os";
|
|
31757
|
+
import { dirname as dirname5, join as join11 } from "path";
|
|
31758
|
+
var claudeDir2 = () => process.env.CLAUDE_CONFIG_DIR || join11(homedir5(), ".claude");
|
|
31759
|
+
var pluginsDir = () => join11(claudeDir2(), "plugins");
|
|
31436
31760
|
|
|
31437
31761
|
// src/hooks/coexist.ts
|
|
31438
31762
|
var cached2;
|
|
31439
31763
|
function contextModeInstalled() {
|
|
31440
31764
|
if (cached2 !== void 0) return cached2;
|
|
31441
31765
|
try {
|
|
31442
|
-
const reg = JSON.parse(
|
|
31766
|
+
const reg = JSON.parse(readFileSync9(join12(pluginsDir(), "installed_plugins.json"), "utf8"));
|
|
31443
31767
|
cached2 = Object.keys(reg.plugins ?? {}).some((id) => id.startsWith("context-mode@"));
|
|
31444
31768
|
} catch {
|
|
31445
31769
|
cached2 = false;
|
|
@@ -31451,18 +31775,6 @@ function effectiveRoutingMode(config2) {
|
|
|
31451
31775
|
return contextModeInstalled() ? "annotate" : "enforce";
|
|
31452
31776
|
}
|
|
31453
31777
|
|
|
31454
|
-
// src/hooks/log.ts
|
|
31455
|
-
init_esm_shims();
|
|
31456
|
-
import { appendFileSync } from "fs";
|
|
31457
|
-
function hookLog(level, msg) {
|
|
31458
|
-
try {
|
|
31459
|
-
const p = ensureDirs();
|
|
31460
|
-
appendFileSync(p.hookLog, `${(/* @__PURE__ */ new Date()).toISOString()} ${level} ${msg}
|
|
31461
|
-
`);
|
|
31462
|
-
} catch {
|
|
31463
|
-
}
|
|
31464
|
-
}
|
|
31465
|
-
|
|
31466
31778
|
// src/hooks/routing.ts
|
|
31467
31779
|
var SYMBOL_KINDS2 = [
|
|
31468
31780
|
"function",
|
|
@@ -31535,7 +31847,7 @@ function historyCall(cmd) {
|
|
|
31535
31847
|
}
|
|
31536
31848
|
function docsSources(root) {
|
|
31537
31849
|
try {
|
|
31538
|
-
return readManifestAt(
|
|
31850
|
+
return readManifestAt(join13(root, ".eminiar", "docs.json")).sources;
|
|
31539
31851
|
} catch {
|
|
31540
31852
|
return [];
|
|
31541
31853
|
}
|
|
@@ -31573,6 +31885,7 @@ var BIG_TEXT_EXT = /* @__PURE__ */ new Set([
|
|
|
31573
31885
|
".sql",
|
|
31574
31886
|
".har"
|
|
31575
31887
|
]);
|
|
31888
|
+
var VISUAL_EXT = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp", ".pdf"]);
|
|
31576
31889
|
function withoutHeredocs(cmd) {
|
|
31577
31890
|
return cmd.replace(/<<-?\s*(['"]?)(\w+)\1[^\n]*\n[\s\S]*?\n\s*\2\s*(?=\n|$)/g, "<<$2");
|
|
31578
31891
|
}
|
|
@@ -31682,7 +31995,7 @@ function fileOperands(stage, cwd) {
|
|
|
31682
31995
|
for (let f of files) {
|
|
31683
31996
|
if (/[*?[\]{}$`\\]/.test(f)) return void 0;
|
|
31684
31997
|
f = f.replace(/^['"]|['"]$/g, "");
|
|
31685
|
-
if (f.startsWith("~/")) f =
|
|
31998
|
+
if (f.startsWith("~/")) f = join13(homedir6(), f.slice(2));
|
|
31686
31999
|
out.push(resolve4(cwd, f));
|
|
31687
32000
|
}
|
|
31688
32001
|
return out;
|
|
@@ -31774,10 +32087,11 @@ function suggest(toolName, input2, root, extra = {}) {
|
|
|
31774
32087
|
case "Read": {
|
|
31775
32088
|
const fp = String(input2.file_path ?? "");
|
|
31776
32089
|
if (!fp) return void 0;
|
|
32090
|
+
const ext = extname2(fp).toLowerCase();
|
|
32091
|
+
if (VISUAL_EXT.has(ext)) return void 0;
|
|
31777
32092
|
try {
|
|
31778
32093
|
const abs = resolve4(root, fp);
|
|
31779
32094
|
const st = statSync5(abs);
|
|
31780
|
-
const ext = extname2(fp).toLowerCase();
|
|
31781
32095
|
if (st.size > 200 * 1024 || BIG_TEXT_EXT.has(ext) && st.size > 20 * 1024) {
|
|
31782
32096
|
if (!checkReadPath(loadPermissionRules(root), abs).allowed) return void 0;
|
|
31783
32097
|
return {
|
|
@@ -32087,18 +32401,18 @@ function annotate(s, note = "") {
|
|
|
32087
32401
|
|
|
32088
32402
|
// src/hooks/session-start.ts
|
|
32089
32403
|
init_esm_shims();
|
|
32090
|
-
import { appendFileSync as appendFileSync2, existsSync as
|
|
32091
|
-
import { join as
|
|
32404
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync11, readdirSync as readdirSync4 } from "fs";
|
|
32405
|
+
import { join as join15 } from "path";
|
|
32092
32406
|
|
|
32093
32407
|
// src/session/current.ts
|
|
32094
32408
|
init_esm_shims();
|
|
32095
|
-
import { readFileSync as
|
|
32096
|
-
import { join as
|
|
32409
|
+
import { readFileSync as readFileSync10, statSync as statSync6, writeFileSync as writeFileSync6 } from "fs";
|
|
32410
|
+
import { join as join14 } from "path";
|
|
32097
32411
|
function file2(ctx) {
|
|
32098
|
-
return
|
|
32412
|
+
return join14(projectDir(ctx.id), "current-session");
|
|
32099
32413
|
}
|
|
32100
32414
|
function setCurrentSession(ctx, sessionId) {
|
|
32101
|
-
|
|
32415
|
+
writeFileSync6(file2(ctx), sessionId);
|
|
32102
32416
|
}
|
|
32103
32417
|
|
|
32104
32418
|
// src/hooks/session-start.ts
|
|
@@ -32187,20 +32501,22 @@ ${guide}`);
|
|
|
32187
32501
|
} catch {
|
|
32188
32502
|
}
|
|
32189
32503
|
try {
|
|
32190
|
-
const onboarding =
|
|
32191
|
-
const onboarded =
|
|
32504
|
+
const onboarding = join15(memoriesDir(ctx), "onboarding");
|
|
32505
|
+
const onboarded = existsSync11(onboarding) && readdirSync4(onboarding).some((f) => f.endsWith(".md"));
|
|
32192
32506
|
if (!onboarded)
|
|
32193
32507
|
parts.push(
|
|
32194
32508
|
"No onboarding memories yet: run /eminiar:em-onboard once so future sessions start with the project's structure, build and test commands."
|
|
32195
32509
|
);
|
|
32196
|
-
else if (!readManifest(ctx).sources.length)
|
|
32510
|
+
else if (!readManifest(ctx).sources.length) {
|
|
32511
|
+
const orphaned = db.documentSourceStats(DOCS_PREFIX).length;
|
|
32197
32512
|
parts.push(
|
|
32198
|
-
`No documentation sources registered yet: em_docs {action:"discover"} maps this project's libraries, services and APIs to their documentation, and {action:"add", pick:"recommended"} indexes it for em_docs lookup.`
|
|
32513
|
+
orphaned ? `No documentation sources registered (${orphaned} orphaned docs:* source(s) still in the index; em_docs {action:"list"} shows them, {action:"remove"} drops them, {action:"add", pick:"recommended"} re-registers).` : `No documentation sources registered yet: em_docs {action:"discover"} maps this project's libraries, services and APIs to their documentation, and {action:"add", pick:"recommended"} indexes it for em_docs lookup.`
|
|
32199
32514
|
);
|
|
32515
|
+
}
|
|
32200
32516
|
} catch {
|
|
32201
32517
|
}
|
|
32202
32518
|
try {
|
|
32203
|
-
if (
|
|
32519
|
+
if (existsSync11(join15(ctx.root, ".git")) && !db.metaGet("history_files"))
|
|
32204
32520
|
parts.push(
|
|
32205
32521
|
'Git history is not classified yet: em_history {action:"overview"} builds it (the server also does this in the background shortly after start); bug-prone files are flagged before you read or edit them once it exists.'
|
|
32206
32522
|
);
|
|
@@ -32236,37 +32552,65 @@ var handlers = {
|
|
|
32236
32552
|
SessionEnd: sessionEnd
|
|
32237
32553
|
};
|
|
32238
32554
|
|
|
32239
|
-
// src/
|
|
32240
|
-
async function
|
|
32241
|
-
|
|
32242
|
-
for await (const chunk2 of process.stdin) chunks.push(chunk2);
|
|
32243
|
-
return Buffer.concat(chunks).toString("utf8");
|
|
32244
|
-
}
|
|
32245
|
-
function emit(out) {
|
|
32246
|
-
process.stdout.write(JSON.stringify(out));
|
|
32247
|
-
}
|
|
32248
|
-
async function main() {
|
|
32249
|
-
const forced = process.argv.indexOf("--event");
|
|
32250
|
-
const raw = await readStdin();
|
|
32251
|
-
let input2;
|
|
32555
|
+
// src/hooks/dispatch.ts
|
|
32556
|
+
async function dispatch(raw, argv) {
|
|
32557
|
+
let parsed;
|
|
32252
32558
|
try {
|
|
32253
|
-
|
|
32559
|
+
parsed = raw.trim() ? JSON.parse(raw) : {};
|
|
32254
32560
|
} catch (err) {
|
|
32255
32561
|
hookLog("error", `bad stdin JSON: ${err.message}`);
|
|
32256
|
-
return
|
|
32562
|
+
return "{}";
|
|
32257
32563
|
}
|
|
32258
|
-
|
|
32259
|
-
if (
|
|
32564
|
+
const forced = argv.indexOf("--event");
|
|
32565
|
+
if (forced !== -1 && argv[forced + 1]) parsed.hook_event_name = argv[forced + 1];
|
|
32566
|
+
if (argv.includes("--selftest")) return JSON.stringify({ systemMessage: "eminiar hook ok" });
|
|
32567
|
+
if (detectClient(parsed, argv) === "cursor") return runCursor(parsed);
|
|
32568
|
+
const input2 = parsed;
|
|
32260
32569
|
const handler = handlers[input2.hook_event_name];
|
|
32261
|
-
if (!handler) return
|
|
32570
|
+
if (!handler) return "{}";
|
|
32262
32571
|
try {
|
|
32263
32572
|
const out = await handler(input2);
|
|
32264
|
-
|
|
32573
|
+
return JSON.stringify(out ?? {});
|
|
32265
32574
|
} catch (err) {
|
|
32266
32575
|
hookLog("error", `${input2.hook_event_name}: ${err.stack ?? String(err)}`);
|
|
32267
|
-
|
|
32576
|
+
return "{}";
|
|
32577
|
+
}
|
|
32578
|
+
}
|
|
32579
|
+
async function runCursor(parsed) {
|
|
32580
|
+
const input2 = fromCursor(parsed);
|
|
32581
|
+
const event = input2.hook_event_name;
|
|
32582
|
+
let out;
|
|
32583
|
+
const handler = handlers[event];
|
|
32584
|
+
if (handler) {
|
|
32585
|
+
try {
|
|
32586
|
+
out = await handler(input2);
|
|
32587
|
+
} catch (err) {
|
|
32588
|
+
hookLog("error", `cursor ${event}: ${err.stack ?? String(err)}`);
|
|
32589
|
+
}
|
|
32590
|
+
}
|
|
32591
|
+
let root = input2.cwd;
|
|
32592
|
+
try {
|
|
32593
|
+
root = getContext(input2.cwd).root;
|
|
32594
|
+
} catch {
|
|
32595
|
+
}
|
|
32596
|
+
try {
|
|
32597
|
+
return JSON.stringify(toCursor(event, out, { root, sessionId: input2.session_id }));
|
|
32598
|
+
} catch (err) {
|
|
32599
|
+
hookLog("error", `cursor ${event} output: ${err.stack ?? String(err)}`);
|
|
32600
|
+
return event === "PreToolUse" ? '{"permission":"allow"}' : "{}";
|
|
32268
32601
|
}
|
|
32269
32602
|
}
|
|
32603
|
+
|
|
32604
|
+
// src/hook.ts
|
|
32605
|
+
async function readStdin() {
|
|
32606
|
+
const chunks = [];
|
|
32607
|
+
for await (const chunk2 of process.stdin) chunks.push(chunk2);
|
|
32608
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
32609
|
+
}
|
|
32610
|
+
async function main() {
|
|
32611
|
+
const raw = await readStdin();
|
|
32612
|
+
process.stdout.write(await dispatch(raw, process.argv.slice(2)));
|
|
32613
|
+
}
|
|
32270
32614
|
main().catch((err) => {
|
|
32271
32615
|
hookLog("error", `fatal: ${err.stack ?? String(err)}`);
|
|
32272
32616
|
process.stdout.write("{}");
|