@agentmonitors/cli 0.4.0 → 0.6.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/dist/index.cjs +866 -142
- package/dist/index.cjs.map +1 -1
- package/package.json +7 -7
package/dist/index.cjs
CHANGED
|
@@ -1218,7 +1218,7 @@ var require_command = __commonJS({
|
|
|
1218
1218
|
init_cjs_shims();
|
|
1219
1219
|
var EventEmitter2 = require("events").EventEmitter;
|
|
1220
1220
|
var childProcess = require("child_process");
|
|
1221
|
-
var
|
|
1221
|
+
var path13 = require("path");
|
|
1222
1222
|
var fs = require("fs");
|
|
1223
1223
|
var process3 = require("process");
|
|
1224
1224
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
@@ -2231,9 +2231,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2231
2231
|
let launchWithNode = false;
|
|
2232
2232
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
2233
2233
|
function findFile(baseDir, baseName) {
|
|
2234
|
-
const localBin =
|
|
2234
|
+
const localBin = path13.resolve(baseDir, baseName);
|
|
2235
2235
|
if (fs.existsSync(localBin)) return localBin;
|
|
2236
|
-
if (sourceExt.includes(
|
|
2236
|
+
if (sourceExt.includes(path13.extname(baseName))) return void 0;
|
|
2237
2237
|
const foundExt = sourceExt.find(
|
|
2238
2238
|
(ext2) => fs.existsSync(`${localBin}${ext2}`)
|
|
2239
2239
|
);
|
|
@@ -2251,17 +2251,17 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2251
2251
|
} catch {
|
|
2252
2252
|
resolvedScriptPath = this._scriptPath;
|
|
2253
2253
|
}
|
|
2254
|
-
executableDir =
|
|
2255
|
-
|
|
2254
|
+
executableDir = path13.resolve(
|
|
2255
|
+
path13.dirname(resolvedScriptPath),
|
|
2256
2256
|
executableDir
|
|
2257
2257
|
);
|
|
2258
2258
|
}
|
|
2259
2259
|
if (executableDir) {
|
|
2260
2260
|
let localFile = findFile(executableDir, executableFile);
|
|
2261
2261
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
2262
|
-
const legacyName =
|
|
2262
|
+
const legacyName = path13.basename(
|
|
2263
2263
|
this._scriptPath,
|
|
2264
|
-
|
|
2264
|
+
path13.extname(this._scriptPath)
|
|
2265
2265
|
);
|
|
2266
2266
|
if (legacyName !== this._name) {
|
|
2267
2267
|
localFile = findFile(
|
|
@@ -2272,7 +2272,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2272
2272
|
}
|
|
2273
2273
|
executableFile = localFile || executableFile;
|
|
2274
2274
|
}
|
|
2275
|
-
launchWithNode = sourceExt.includes(
|
|
2275
|
+
launchWithNode = sourceExt.includes(path13.extname(executableFile));
|
|
2276
2276
|
let proc2;
|
|
2277
2277
|
if (process3.platform !== "win32") {
|
|
2278
2278
|
if (launchWithNode) {
|
|
@@ -3187,7 +3187,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3187
3187
|
* @return {Command}
|
|
3188
3188
|
*/
|
|
3189
3189
|
nameFromFilename(filename) {
|
|
3190
|
-
this._name =
|
|
3190
|
+
this._name = path13.basename(filename, path13.extname(filename));
|
|
3191
3191
|
return this;
|
|
3192
3192
|
}
|
|
3193
3193
|
/**
|
|
@@ -3201,9 +3201,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3201
3201
|
* @param {string} [path]
|
|
3202
3202
|
* @return {(string|null|Command)}
|
|
3203
3203
|
*/
|
|
3204
|
-
executableDir(
|
|
3205
|
-
if (
|
|
3206
|
-
this._executableDir =
|
|
3204
|
+
executableDir(path14) {
|
|
3205
|
+
if (path14 === void 0) return this._executableDir;
|
|
3206
|
+
this._executableDir = path14;
|
|
3207
3207
|
return this;
|
|
3208
3208
|
}
|
|
3209
3209
|
/**
|
|
@@ -10226,8 +10226,8 @@ var require_utils2 = __commonJS({
|
|
|
10226
10226
|
}
|
|
10227
10227
|
return ind;
|
|
10228
10228
|
}
|
|
10229
|
-
function removeDotSegments(
|
|
10230
|
-
let input =
|
|
10229
|
+
function removeDotSegments(path13) {
|
|
10230
|
+
let input = path13;
|
|
10231
10231
|
const output = [];
|
|
10232
10232
|
let nextSlash = -1;
|
|
10233
10233
|
let len = 0;
|
|
@@ -10427,8 +10427,8 @@ var require_schemes = __commonJS({
|
|
|
10427
10427
|
wsComponent.secure = void 0;
|
|
10428
10428
|
}
|
|
10429
10429
|
if (wsComponent.resourceName) {
|
|
10430
|
-
const [
|
|
10431
|
-
wsComponent.path =
|
|
10430
|
+
const [path13, query] = wsComponent.resourceName.split("?");
|
|
10431
|
+
wsComponent.path = path13 && path13 !== "/" ? path13 : void 0;
|
|
10432
10432
|
wsComponent.query = query;
|
|
10433
10433
|
wsComponent.resourceName = void 0;
|
|
10434
10434
|
}
|
|
@@ -13851,8 +13851,8 @@ var require_dist = __commonJS({
|
|
|
13851
13851
|
|
|
13852
13852
|
// src/index.ts
|
|
13853
13853
|
init_cjs_shims();
|
|
13854
|
-
var
|
|
13855
|
-
var
|
|
13854
|
+
var import_node_fs7 = require("fs");
|
|
13855
|
+
var import_node_path10 = require("path");
|
|
13856
13856
|
var import_node_url4 = require("url");
|
|
13857
13857
|
|
|
13858
13858
|
// ../../node_modules/.pnpm/commander@14.0.3/node_modules/commander/esm.mjs
|
|
@@ -13971,6 +13971,7 @@ Edit the file to configure your monitor, then run:`);
|
|
|
13971
13971
|
|
|
13972
13972
|
// src/commands/validate.ts
|
|
13973
13973
|
init_cjs_shims();
|
|
13974
|
+
var import_node_fs3 = require("fs");
|
|
13974
13975
|
|
|
13975
13976
|
// ../../libs/core/dist/index.js
|
|
13976
13977
|
init_cjs_shims();
|
|
@@ -14468,8 +14469,8 @@ function getErrorMap() {
|
|
|
14468
14469
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
14469
14470
|
init_cjs_shims();
|
|
14470
14471
|
var makeIssue = (params) => {
|
|
14471
|
-
const { data, path:
|
|
14472
|
-
const fullPath = [...
|
|
14472
|
+
const { data, path: path13, errorMaps, issueData } = params;
|
|
14473
|
+
const fullPath = [...path13, ...issueData.path || []];
|
|
14473
14474
|
const fullIssue = {
|
|
14474
14475
|
...issueData,
|
|
14475
14476
|
path: fullPath
|
|
@@ -14589,11 +14590,11 @@ var errorUtil;
|
|
|
14589
14590
|
|
|
14590
14591
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
14591
14592
|
var ParseInputLazyPath = class {
|
|
14592
|
-
constructor(parent, value,
|
|
14593
|
+
constructor(parent, value, path13, key) {
|
|
14593
14594
|
this._cachedPath = [];
|
|
14594
14595
|
this.parent = parent;
|
|
14595
14596
|
this.data = value;
|
|
14596
|
-
this._path =
|
|
14597
|
+
this._path = path13;
|
|
14597
14598
|
this._key = key;
|
|
14598
14599
|
}
|
|
14599
14600
|
get path() {
|
|
@@ -22659,12 +22660,12 @@ var PathBase = class {
|
|
|
22659
22660
|
/**
|
|
22660
22661
|
* Get the Path object referenced by the string path, resolved from this Path
|
|
22661
22662
|
*/
|
|
22662
|
-
resolve(
|
|
22663
|
-
if (!
|
|
22663
|
+
resolve(path13) {
|
|
22664
|
+
if (!path13) {
|
|
22664
22665
|
return this;
|
|
22665
22666
|
}
|
|
22666
|
-
const rootPath = this.getRootString(
|
|
22667
|
-
const dir =
|
|
22667
|
+
const rootPath = this.getRootString(path13);
|
|
22668
|
+
const dir = path13.substring(rootPath.length);
|
|
22668
22669
|
const dirParts = dir.split(this.splitSep);
|
|
22669
22670
|
const result = rootPath ? this.getRoot(rootPath).#resolveParts(dirParts) : this.#resolveParts(dirParts);
|
|
22670
22671
|
return result;
|
|
@@ -23416,8 +23417,8 @@ var PathWin32 = class _PathWin32 extends PathBase {
|
|
|
23416
23417
|
/**
|
|
23417
23418
|
* @internal
|
|
23418
23419
|
*/
|
|
23419
|
-
getRootString(
|
|
23420
|
-
return import_node_path2.win32.parse(
|
|
23420
|
+
getRootString(path13) {
|
|
23421
|
+
return import_node_path2.win32.parse(path13).root;
|
|
23421
23422
|
}
|
|
23422
23423
|
/**
|
|
23423
23424
|
* @internal
|
|
@@ -23463,8 +23464,8 @@ var PathPosix = class _PathPosix extends PathBase {
|
|
|
23463
23464
|
/**
|
|
23464
23465
|
* @internal
|
|
23465
23466
|
*/
|
|
23466
|
-
getRootString(
|
|
23467
|
-
return
|
|
23467
|
+
getRootString(path13) {
|
|
23468
|
+
return path13.startsWith("/") ? "/" : "";
|
|
23468
23469
|
}
|
|
23469
23470
|
/**
|
|
23470
23471
|
* @internal
|
|
@@ -23553,11 +23554,11 @@ var PathScurryBase = class {
|
|
|
23553
23554
|
/**
|
|
23554
23555
|
* Get the depth of a provided path, string, or the cwd
|
|
23555
23556
|
*/
|
|
23556
|
-
depth(
|
|
23557
|
-
if (typeof
|
|
23558
|
-
|
|
23557
|
+
depth(path13 = this.cwd) {
|
|
23558
|
+
if (typeof path13 === "string") {
|
|
23559
|
+
path13 = this.cwd.resolve(path13);
|
|
23559
23560
|
}
|
|
23560
|
-
return
|
|
23561
|
+
return path13.depth();
|
|
23561
23562
|
}
|
|
23562
23563
|
/**
|
|
23563
23564
|
* Return the cache of child entries. Exposed so subclasses can create
|
|
@@ -24044,9 +24045,9 @@ var PathScurryBase = class {
|
|
|
24044
24045
|
process3();
|
|
24045
24046
|
return results;
|
|
24046
24047
|
}
|
|
24047
|
-
chdir(
|
|
24048
|
+
chdir(path13 = this.cwd) {
|
|
24048
24049
|
const oldCwd = this.cwd;
|
|
24049
|
-
this.cwd = typeof
|
|
24050
|
+
this.cwd = typeof path13 === "string" ? this.cwd.resolve(path13) : path13;
|
|
24050
24051
|
this.cwd[setAsCwd](oldCwd);
|
|
24051
24052
|
}
|
|
24052
24053
|
};
|
|
@@ -24408,8 +24409,8 @@ var MatchRecord = class {
|
|
|
24408
24409
|
}
|
|
24409
24410
|
// match, absolute, ifdir
|
|
24410
24411
|
entries() {
|
|
24411
|
-
return [...this.store.entries()].map(([
|
|
24412
|
-
|
|
24412
|
+
return [...this.store.entries()].map(([path13, n]) => [
|
|
24413
|
+
path13,
|
|
24413
24414
|
!!(n & 2),
|
|
24414
24415
|
!!(n & 1)
|
|
24415
24416
|
]);
|
|
@@ -24614,9 +24615,9 @@ var GlobUtil = class {
|
|
|
24614
24615
|
signal;
|
|
24615
24616
|
maxDepth;
|
|
24616
24617
|
includeChildMatches;
|
|
24617
|
-
constructor(patterns,
|
|
24618
|
+
constructor(patterns, path13, opts) {
|
|
24618
24619
|
this.patterns = patterns;
|
|
24619
|
-
this.path =
|
|
24620
|
+
this.path = path13;
|
|
24620
24621
|
this.opts = opts;
|
|
24621
24622
|
this.#sep = !opts.posix && opts.platform === "win32" ? "\\" : "/";
|
|
24622
24623
|
this.includeChildMatches = opts.includeChildMatches !== false;
|
|
@@ -24635,11 +24636,11 @@ var GlobUtil = class {
|
|
|
24635
24636
|
});
|
|
24636
24637
|
}
|
|
24637
24638
|
}
|
|
24638
|
-
#ignored(
|
|
24639
|
-
return this.seen.has(
|
|
24639
|
+
#ignored(path13) {
|
|
24640
|
+
return this.seen.has(path13) || !!this.#ignore?.ignored?.(path13);
|
|
24640
24641
|
}
|
|
24641
|
-
#childrenIgnored(
|
|
24642
|
-
return !!this.#ignore?.childrenIgnored?.(
|
|
24642
|
+
#childrenIgnored(path13) {
|
|
24643
|
+
return !!this.#ignore?.childrenIgnored?.(path13);
|
|
24643
24644
|
}
|
|
24644
24645
|
// backpressure mechanism
|
|
24645
24646
|
pause() {
|
|
@@ -24854,8 +24855,8 @@ var GlobUtil = class {
|
|
|
24854
24855
|
};
|
|
24855
24856
|
var GlobWalker = class extends GlobUtil {
|
|
24856
24857
|
matches = /* @__PURE__ */ new Set();
|
|
24857
|
-
constructor(patterns,
|
|
24858
|
-
super(patterns,
|
|
24858
|
+
constructor(patterns, path13, opts) {
|
|
24859
|
+
super(patterns, path13, opts);
|
|
24859
24860
|
}
|
|
24860
24861
|
matchEmit(e) {
|
|
24861
24862
|
this.matches.add(e);
|
|
@@ -24892,8 +24893,8 @@ var GlobWalker = class extends GlobUtil {
|
|
|
24892
24893
|
};
|
|
24893
24894
|
var GlobStream = class extends GlobUtil {
|
|
24894
24895
|
results;
|
|
24895
|
-
constructor(patterns,
|
|
24896
|
-
super(patterns,
|
|
24896
|
+
constructor(patterns, path13, opts) {
|
|
24897
|
+
super(patterns, path13, opts);
|
|
24897
24898
|
this.results = new Minipass({
|
|
24898
24899
|
signal: this.signal,
|
|
24899
24900
|
objectMode: true
|
|
@@ -26401,7 +26402,7 @@ Subquery.prototype.getSQL = function() {
|
|
|
26401
26402
|
function mapResultRow(columns, row, joinsNotNullableMap) {
|
|
26402
26403
|
const nullifyMap = {};
|
|
26403
26404
|
const result = columns.reduce(
|
|
26404
|
-
(result2, { path:
|
|
26405
|
+
(result2, { path: path13, field }, columnIndex) => {
|
|
26405
26406
|
let decoder;
|
|
26406
26407
|
if (is(field, Column)) {
|
|
26407
26408
|
decoder = field;
|
|
@@ -26413,8 +26414,8 @@ function mapResultRow(columns, row, joinsNotNullableMap) {
|
|
|
26413
26414
|
decoder = field.sql.decoder;
|
|
26414
26415
|
}
|
|
26415
26416
|
let node = result2;
|
|
26416
|
-
for (const [pathChunkIndex, pathChunk] of
|
|
26417
|
-
if (pathChunkIndex <
|
|
26417
|
+
for (const [pathChunkIndex, pathChunk] of path13.entries()) {
|
|
26418
|
+
if (pathChunkIndex < path13.length - 1) {
|
|
26418
26419
|
if (!(pathChunk in node)) {
|
|
26419
26420
|
node[pathChunk] = {};
|
|
26420
26421
|
}
|
|
@@ -26422,8 +26423,8 @@ function mapResultRow(columns, row, joinsNotNullableMap) {
|
|
|
26422
26423
|
} else {
|
|
26423
26424
|
const rawValue = row[columnIndex];
|
|
26424
26425
|
const value = node[pathChunk] = rawValue === null ? null : decoder.mapFromDriverValue(rawValue);
|
|
26425
|
-
if (joinsNotNullableMap && is(field, Column) &&
|
|
26426
|
-
const objectName =
|
|
26426
|
+
if (joinsNotNullableMap && is(field, Column) && path13.length === 2) {
|
|
26427
|
+
const objectName = path13[0];
|
|
26427
26428
|
if (!(objectName in nullifyMap)) {
|
|
26428
26429
|
nullifyMap[objectName] = value === null ? getTableName(field.table) : false;
|
|
26429
26430
|
} else if (typeof nullifyMap[objectName] === "string" && nullifyMap[objectName] !== getTableName(field.table)) {
|
|
@@ -31375,14 +31376,19 @@ function assertValidSegment(path72, segment) {
|
|
|
31375
31376
|
);
|
|
31376
31377
|
}
|
|
31377
31378
|
}
|
|
31378
|
-
function
|
|
31379
|
-
if (path72 === "$") return
|
|
31380
|
-
if (
|
|
31379
|
+
function normalizeDottedPath(path72) {
|
|
31380
|
+
if (path72 === "$" || path72.startsWith("$.")) return path72;
|
|
31381
|
+
if (path72.startsWith("$")) {
|
|
31381
31382
|
throw new Error(
|
|
31382
|
-
`Invalid collection path "${path72}":
|
|
31383
|
+
`Invalid collection path "${path72}": a path beginning with "$" must be explicit-root form ("$" or "$.field"). Write "${path72.slice(1)}" for a bare root-relative path, or "$.${path72.slice(1)}" for explicit-root form.`
|
|
31383
31384
|
);
|
|
31384
31385
|
}
|
|
31385
|
-
|
|
31386
|
+
return `$.${path72}`;
|
|
31387
|
+
}
|
|
31388
|
+
function resolveDottedPath(root, path72) {
|
|
31389
|
+
const normalizedPath = normalizeDottedPath(path72);
|
|
31390
|
+
if (normalizedPath === "$") return root;
|
|
31391
|
+
const segments = normalizedPath.slice(2).split(".");
|
|
31386
31392
|
let current = root;
|
|
31387
31393
|
for (const segment of segments) {
|
|
31388
31394
|
if (segment.length === 0) {
|
|
@@ -31397,13 +31403,9 @@ function resolveDottedPath(root, path72) {
|
|
|
31397
31403
|
return current;
|
|
31398
31404
|
}
|
|
31399
31405
|
function removeDottedPath(value, path72) {
|
|
31400
|
-
|
|
31401
|
-
if (
|
|
31402
|
-
|
|
31403
|
-
`Invalid ignore-paths entry "${path72}": must start with "$." (e.g. "$.fetchedAt")`
|
|
31404
|
-
);
|
|
31405
|
-
}
|
|
31406
|
-
const segments = path72.slice(2).split(".");
|
|
31406
|
+
const normalizedPath = normalizeDottedPath(path72);
|
|
31407
|
+
if (normalizedPath === "$") return;
|
|
31408
|
+
const segments = normalizedPath.slice(2).split(".");
|
|
31407
31409
|
let current = value;
|
|
31408
31410
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
31409
31411
|
const segment = segments[i];
|
|
@@ -31677,6 +31679,11 @@ function rowToEvent(row) {
|
|
|
31677
31679
|
createdAt: row.createdAt
|
|
31678
31680
|
};
|
|
31679
31681
|
}
|
|
31682
|
+
function deliveryStateForRow(row) {
|
|
31683
|
+
if (row.acknowledgedAt) return "acknowledged";
|
|
31684
|
+
if (row.firstNotifiedAt) return "claimed";
|
|
31685
|
+
return "unread";
|
|
31686
|
+
}
|
|
31680
31687
|
function scopeMatches(eventScope, requested) {
|
|
31681
31688
|
if (!requested) return true;
|
|
31682
31689
|
for (const [key, value] of Object.entries(requested)) {
|
|
@@ -31844,6 +31851,13 @@ var RuntimeStore = class {
|
|
|
31844
31851
|
if (query.objectKey)
|
|
31845
31852
|
conditions.push(eq(monitorEvents.objectKey, query.objectKey));
|
|
31846
31853
|
if (query.since) conditions.push(gt(monitorEvents.createdAt, query.since));
|
|
31854
|
+
if (query.workspacePath !== void 0) {
|
|
31855
|
+
const workspaceCondition = or(
|
|
31856
|
+
eq(monitorEvents.workspacePath, query.workspacePath),
|
|
31857
|
+
isNull(monitorEvents.workspacePath)
|
|
31858
|
+
);
|
|
31859
|
+
if (workspaceCondition) conditions.push(workspaceCondition);
|
|
31860
|
+
}
|
|
31847
31861
|
let rows = query.sessionId ? asInternalDb2(this.db).select({
|
|
31848
31862
|
event: monitorEvents,
|
|
31849
31863
|
state: sessionEventState
|
|
@@ -31918,6 +31932,37 @@ var RuntimeStore = class {
|
|
|
31918
31932
|
createdAt: row.createdAt
|
|
31919
31933
|
}));
|
|
31920
31934
|
}
|
|
31935
|
+
listDeliveryProjectionsForMonitor(monitorId, workspacePath) {
|
|
31936
|
+
const conditions = [eq(monitorEvents.monitorId, monitorId)];
|
|
31937
|
+
if (workspacePath !== void 0) {
|
|
31938
|
+
const workspaceCondition = or(
|
|
31939
|
+
eq(agentSessions.workspacePath, workspacePath),
|
|
31940
|
+
isNull(agentSessions.workspacePath)
|
|
31941
|
+
);
|
|
31942
|
+
if (workspaceCondition) conditions.push(workspaceCondition);
|
|
31943
|
+
}
|
|
31944
|
+
const rows = asInternalDb2(this.db).select({
|
|
31945
|
+
event: monitorEvents,
|
|
31946
|
+
state: sessionEventState,
|
|
31947
|
+
session: agentSessions
|
|
31948
|
+
}).from(sessionEventState).innerJoin(monitorEvents, eq(sessionEventState.eventId, monitorEvents.id)).innerJoin(
|
|
31949
|
+
agentSessions,
|
|
31950
|
+
eq(sessionEventState.sessionId, agentSessions.id)
|
|
31951
|
+
).where(and(...conditions)).orderBy(desc(monitorEvents.createdAt)).all();
|
|
31952
|
+
return rows.map(({ event, state, session }) => ({
|
|
31953
|
+
eventId: event.id,
|
|
31954
|
+
sessionId: session.id,
|
|
31955
|
+
sessionRole: session.role,
|
|
31956
|
+
sessionStatus: session.status,
|
|
31957
|
+
deliveryState: deliveryStateForRow(state),
|
|
31958
|
+
workspacePath: session.workspacePath ?? null,
|
|
31959
|
+
createdAt: state.createdAt,
|
|
31960
|
+
...state.firstNotifiedAt ? { firstNotifiedAt: state.firstNotifiedAt } : {},
|
|
31961
|
+
...state.lastClaimAt ? { lastClaimAt: state.lastClaimAt } : {},
|
|
31962
|
+
...state.lastClaimLifecycle ? { lastClaimLifecycle: state.lastClaimLifecycle } : {},
|
|
31963
|
+
...state.acknowledgedAt ? { acknowledgedAt: state.acknowledgedAt } : {}
|
|
31964
|
+
}));
|
|
31965
|
+
}
|
|
31921
31966
|
sessionsForWorkspace(workspacePath) {
|
|
31922
31967
|
return asInternalDb2(this.db).select().from(agentSessions).where(
|
|
31923
31968
|
workspacePath == null ? isNull(agentSessions.workspacePath) : or(
|
|
@@ -32025,6 +32070,14 @@ var DEFAULT_FILE_FINGERPRINT_POLL_MS = 3e4;
|
|
|
32025
32070
|
var DEFAULT_API_POLL_MS = 3e5;
|
|
32026
32071
|
var DEFAULT_HIGH_URGENCY_SETTLE_MS = 15e3;
|
|
32027
32072
|
var MAX_RECAP_EVENTS = 10;
|
|
32073
|
+
var EXPLAIN_STAGE_LABELS = {
|
|
32074
|
+
definition: "Definition",
|
|
32075
|
+
scheduling: "Scheduling",
|
|
32076
|
+
observation: "Observation",
|
|
32077
|
+
notify: "Notify state",
|
|
32078
|
+
materialization: "Materialization",
|
|
32079
|
+
delivery: "Projection and delivery"
|
|
32080
|
+
};
|
|
32028
32081
|
function watchConfig(watch) {
|
|
32029
32082
|
const { type: _type, ...config2 } = watch;
|
|
32030
32083
|
return config2;
|
|
@@ -32043,6 +32096,28 @@ function writeJsonAtomic(filePath2, payload) {
|
|
|
32043
32096
|
(0, import_fs3.writeFileSync)(tmpPath, JSON.stringify(payload, null, 2), "utf-8");
|
|
32044
32097
|
(0, import_fs3.renameSync)(tmpPath, filePath2);
|
|
32045
32098
|
}
|
|
32099
|
+
function monitorIdFromFilePath(filePath2) {
|
|
32100
|
+
const base = import_path4.default.basename(filePath2);
|
|
32101
|
+
return base === "MONITOR.md" ? import_path4.default.basename(import_path4.default.dirname(filePath2)) : import_path4.default.parse(filePath2).name;
|
|
32102
|
+
}
|
|
32103
|
+
function explainStage(id, status, reason, details) {
|
|
32104
|
+
return {
|
|
32105
|
+
id,
|
|
32106
|
+
label: EXPLAIN_STAGE_LABELS[id],
|
|
32107
|
+
status,
|
|
32108
|
+
reason,
|
|
32109
|
+
...details ? { details } : {}
|
|
32110
|
+
};
|
|
32111
|
+
}
|
|
32112
|
+
function explainVerdict(stages) {
|
|
32113
|
+
const stopped = stages.find((stage2) => stage2.status !== "ok");
|
|
32114
|
+
const stage = stopped ?? stages[stages.length - 1];
|
|
32115
|
+
return {
|
|
32116
|
+
status: stage?.status ?? "ok",
|
|
32117
|
+
stage: stage?.id ?? "delivery",
|
|
32118
|
+
reason: stage?.reason ?? "Monitor delivered successfully."
|
|
32119
|
+
};
|
|
32120
|
+
}
|
|
32046
32121
|
function serializeObservation(monitor, observation, observedAt) {
|
|
32047
32122
|
return { monitor, observation, observedAt };
|
|
32048
32123
|
}
|
|
@@ -32157,6 +32232,320 @@ var AgentMonitorRuntime = class {
|
|
|
32157
32232
|
listObservationHistory(query = {}) {
|
|
32158
32233
|
return this.store.listObservationHistory(query);
|
|
32159
32234
|
}
|
|
32235
|
+
async explainMonitor(input) {
|
|
32236
|
+
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
32237
|
+
const historyLimit = input.historyLimit ?? 10;
|
|
32238
|
+
const eventLimit = input.eventLimit ?? 10;
|
|
32239
|
+
const stages = [];
|
|
32240
|
+
const scan = await scanMonitors(input.monitorsDir);
|
|
32241
|
+
const parseError = scan.errors.find(
|
|
32242
|
+
(error2) => monitorIdFromFilePath(error2.filePath) === input.monitorId
|
|
32243
|
+
);
|
|
32244
|
+
const monitor = scan.monitors.find(
|
|
32245
|
+
(candidate) => candidate.monitor.id === input.monitorId
|
|
32246
|
+
)?.monitor;
|
|
32247
|
+
const duplicate = scan.duplicateIds.find(
|
|
32248
|
+
(candidate) => candidate.id === input.monitorId
|
|
32249
|
+
);
|
|
32250
|
+
if (parseError) {
|
|
32251
|
+
stages.push(
|
|
32252
|
+
explainStage(
|
|
32253
|
+
"definition",
|
|
32254
|
+
"failure",
|
|
32255
|
+
`MONITOR.md failed to parse or validate: ${parseError.error}`,
|
|
32256
|
+
{ filePath: parseError.filePath }
|
|
32257
|
+
)
|
|
32258
|
+
);
|
|
32259
|
+
return {
|
|
32260
|
+
monitorId: input.monitorId,
|
|
32261
|
+
generatedAt: now,
|
|
32262
|
+
stages,
|
|
32263
|
+
verdict: explainVerdict(stages),
|
|
32264
|
+
observations: [],
|
|
32265
|
+
events: [],
|
|
32266
|
+
projections: [],
|
|
32267
|
+
leadSessions: []
|
|
32268
|
+
};
|
|
32269
|
+
}
|
|
32270
|
+
if (!monitor) {
|
|
32271
|
+
stages.push(
|
|
32272
|
+
explainStage(
|
|
32273
|
+
"definition",
|
|
32274
|
+
"failure",
|
|
32275
|
+
`Monitor "${input.monitorId}" was not found in ${input.monitorsDir}.`
|
|
32276
|
+
)
|
|
32277
|
+
);
|
|
32278
|
+
return {
|
|
32279
|
+
monitorId: input.monitorId,
|
|
32280
|
+
generatedAt: now,
|
|
32281
|
+
stages,
|
|
32282
|
+
verdict: explainVerdict(stages),
|
|
32283
|
+
observations: [],
|
|
32284
|
+
events: [],
|
|
32285
|
+
projections: [],
|
|
32286
|
+
leadSessions: []
|
|
32287
|
+
};
|
|
32288
|
+
}
|
|
32289
|
+
if (duplicate) {
|
|
32290
|
+
stages.push(
|
|
32291
|
+
explainStage(
|
|
32292
|
+
"definition",
|
|
32293
|
+
"failure",
|
|
32294
|
+
`Monitor id "${input.monitorId}" is duplicated across ${String(duplicate.filePaths.length)} files.`,
|
|
32295
|
+
{ filePaths: duplicate.filePaths }
|
|
32296
|
+
)
|
|
32297
|
+
);
|
|
32298
|
+
return {
|
|
32299
|
+
monitorId: input.monitorId,
|
|
32300
|
+
generatedAt: now,
|
|
32301
|
+
monitor: {
|
|
32302
|
+
id: monitor.id,
|
|
32303
|
+
displayName: monitor.displayName,
|
|
32304
|
+
filePath: monitor.filePath,
|
|
32305
|
+
sourceName: monitor.frontmatter.watch.type,
|
|
32306
|
+
urgency: monitor.frontmatter.urgency
|
|
32307
|
+
},
|
|
32308
|
+
stages,
|
|
32309
|
+
verdict: explainVerdict(stages),
|
|
32310
|
+
observations: [],
|
|
32311
|
+
events: [],
|
|
32312
|
+
projections: [],
|
|
32313
|
+
leadSessions: []
|
|
32314
|
+
};
|
|
32315
|
+
}
|
|
32316
|
+
const sourceName = monitor.frontmatter.watch.type;
|
|
32317
|
+
const source6 = this.registry.get(sourceName);
|
|
32318
|
+
const scopeErrors = source6 ? validateScope(
|
|
32319
|
+
watchConfig(monitor.frontmatter.watch),
|
|
32320
|
+
source6.scopeSchema
|
|
32321
|
+
) : [`Unknown source "${sourceName}".`];
|
|
32322
|
+
if (scopeErrors.length > 0) {
|
|
32323
|
+
stages.push(
|
|
32324
|
+
explainStage(
|
|
32325
|
+
"definition",
|
|
32326
|
+
"failure",
|
|
32327
|
+
`Monitor definition is invalid: ${scopeErrors.join("; ")}`,
|
|
32328
|
+
{ filePath: monitor.filePath, sourceName }
|
|
32329
|
+
)
|
|
32330
|
+
);
|
|
32331
|
+
return {
|
|
32332
|
+
monitorId: input.monitorId,
|
|
32333
|
+
generatedAt: now,
|
|
32334
|
+
monitor: {
|
|
32335
|
+
id: monitor.id,
|
|
32336
|
+
displayName: monitor.displayName,
|
|
32337
|
+
filePath: monitor.filePath,
|
|
32338
|
+
sourceName,
|
|
32339
|
+
urgency: monitor.frontmatter.urgency
|
|
32340
|
+
},
|
|
32341
|
+
stages,
|
|
32342
|
+
verdict: explainVerdict(stages),
|
|
32343
|
+
observations: [],
|
|
32344
|
+
events: [],
|
|
32345
|
+
projections: [],
|
|
32346
|
+
leadSessions: []
|
|
32347
|
+
};
|
|
32348
|
+
}
|
|
32349
|
+
stages.push(
|
|
32350
|
+
explainStage("definition", "ok", "Monitor definition is valid.", {
|
|
32351
|
+
filePath: monitor.filePath,
|
|
32352
|
+
sourceName
|
|
32353
|
+
})
|
|
32354
|
+
);
|
|
32355
|
+
const runtimeState = this.store.getMonitorState(input.monitorId);
|
|
32356
|
+
const schedule = this.scheduleForMonitor(monitor, now);
|
|
32357
|
+
const lastObservationAt = runtimeState.lastObservationAt;
|
|
32358
|
+
const nextDueAt = schedule.due ? now : new Date(
|
|
32359
|
+
(lastObservationAt?.getTime() ?? now.getTime()) + schedule.nextPollMs
|
|
32360
|
+
);
|
|
32361
|
+
stages.push(
|
|
32362
|
+
explainStage(
|
|
32363
|
+
"scheduling",
|
|
32364
|
+
"ok",
|
|
32365
|
+
lastObservationAt ? `Last tick completed at ${lastObservationAt.toISOString()}; next due ${schedule.due ? "now" : nextDueAt.toISOString()}.` : "No completed tick is recorded yet; the monitor is due on the next daemon tick.",
|
|
32366
|
+
{
|
|
32367
|
+
due: schedule.due,
|
|
32368
|
+
nextPollMs: schedule.nextPollMs,
|
|
32369
|
+
nextDueAt: nextDueAt.toISOString(),
|
|
32370
|
+
...lastObservationAt ? { lastObservationAt: lastObservationAt.toISOString() } : {}
|
|
32371
|
+
}
|
|
32372
|
+
)
|
|
32373
|
+
);
|
|
32374
|
+
const observations = this.store.listObservationHistory({
|
|
32375
|
+
monitorId: input.monitorId,
|
|
32376
|
+
limit: historyLimit
|
|
32377
|
+
});
|
|
32378
|
+
const latestObservation = observations[0];
|
|
32379
|
+
if (!latestObservation) {
|
|
32380
|
+
stages.push(
|
|
32381
|
+
explainStage(
|
|
32382
|
+
"observation",
|
|
32383
|
+
"failure",
|
|
32384
|
+
"No observation history has been recorded for this monitor."
|
|
32385
|
+
)
|
|
32386
|
+
);
|
|
32387
|
+
} else if (latestObservation.result === "errored") {
|
|
32388
|
+
stages.push(
|
|
32389
|
+
explainStage(
|
|
32390
|
+
"observation",
|
|
32391
|
+
"failure",
|
|
32392
|
+
"The most recent source observation errored.",
|
|
32393
|
+
latestObservation.observationData
|
|
32394
|
+
)
|
|
32395
|
+
);
|
|
32396
|
+
} else if (latestObservation.result === "no-change") {
|
|
32397
|
+
stages.push(
|
|
32398
|
+
explainStage(
|
|
32399
|
+
"observation",
|
|
32400
|
+
"healthy",
|
|
32401
|
+
"Source ran, observed 0 changes \u2014 your watched target genuinely hasn\u2019t changed (not a bug).",
|
|
32402
|
+
latestObservation.observationData
|
|
32403
|
+
)
|
|
32404
|
+
);
|
|
32405
|
+
} else if (latestObservation.result === "rebaselined") {
|
|
32406
|
+
stages.push(
|
|
32407
|
+
explainStage(
|
|
32408
|
+
"observation",
|
|
32409
|
+
"healthy",
|
|
32410
|
+
"Source rebaselined and emitted no change \u2014 your watched target is being tracked, nothing to report (not a bug).",
|
|
32411
|
+
latestObservation.observationData
|
|
32412
|
+
)
|
|
32413
|
+
);
|
|
32414
|
+
} else {
|
|
32415
|
+
stages.push(
|
|
32416
|
+
explainStage(
|
|
32417
|
+
"observation",
|
|
32418
|
+
"ok",
|
|
32419
|
+
`The latest observation outcome was ${latestObservation.result}.`,
|
|
32420
|
+
latestObservation.observationData
|
|
32421
|
+
)
|
|
32422
|
+
);
|
|
32423
|
+
}
|
|
32424
|
+
const observationHealthy = latestObservation?.result === "no-change" || latestObservation?.result === "rebaselined";
|
|
32425
|
+
const notifyState = runtimeState.notifyState;
|
|
32426
|
+
const pendingDebounce = notifyState.pendingDebounce;
|
|
32427
|
+
const suppressedUntil = notifyState.suppressedUntil ? new Date(notifyState.suppressedUntil) : null;
|
|
32428
|
+
if (pendingDebounce && new Date(pendingDebounce.dueAt) > now) {
|
|
32429
|
+
stages.push(
|
|
32430
|
+
explainStage(
|
|
32431
|
+
"notify",
|
|
32432
|
+
"pending",
|
|
32433
|
+
`debounce is holding ${String(pendingDebounce.observations.length)} observation(s) until ${pendingDebounce.dueAt}.`,
|
|
32434
|
+
{
|
|
32435
|
+
dueAt: pendingDebounce.dueAt,
|
|
32436
|
+
observations: pendingDebounce.observations.length
|
|
32437
|
+
}
|
|
32438
|
+
)
|
|
32439
|
+
);
|
|
32440
|
+
} else if (suppressedUntil && suppressedUntil > now) {
|
|
32441
|
+
stages.push(
|
|
32442
|
+
explainStage(
|
|
32443
|
+
"notify",
|
|
32444
|
+
"pending",
|
|
32445
|
+
`throttle is suppressing new notifications until ${suppressedUntil.toISOString()}.`,
|
|
32446
|
+
{ suppressedUntil: suppressedUntil.toISOString() }
|
|
32447
|
+
)
|
|
32448
|
+
);
|
|
32449
|
+
} else {
|
|
32450
|
+
stages.push(
|
|
32451
|
+
explainStage(
|
|
32452
|
+
"notify",
|
|
32453
|
+
"ok",
|
|
32454
|
+
"No debounce or throttle hold is currently active."
|
|
32455
|
+
)
|
|
32456
|
+
);
|
|
32457
|
+
}
|
|
32458
|
+
const events = this.store.listEvents({
|
|
32459
|
+
monitorId: input.monitorId,
|
|
32460
|
+
// Scope to the explained workspace so a same-id monitor in another
|
|
32461
|
+
// workspace cannot leak its events into this report (issue #94 review).
|
|
32462
|
+
...input.workspacePath !== void 0 ? { workspacePath: input.workspacePath } : {}
|
|
32463
|
+
}).slice(0, eventLimit);
|
|
32464
|
+
if (events.length === 0) {
|
|
32465
|
+
stages.push(
|
|
32466
|
+
observationHealthy ? explainStage(
|
|
32467
|
+
"materialization",
|
|
32468
|
+
"healthy",
|
|
32469
|
+
"No events materialized \u2014 expected, because the source observed no changes (not a bug)."
|
|
32470
|
+
) : explainStage(
|
|
32471
|
+
"materialization",
|
|
32472
|
+
"failure",
|
|
32473
|
+
"No monitor_events rows exist for this monitor."
|
|
32474
|
+
)
|
|
32475
|
+
);
|
|
32476
|
+
} else {
|
|
32477
|
+
stages.push(
|
|
32478
|
+
explainStage(
|
|
32479
|
+
"materialization",
|
|
32480
|
+
"ok",
|
|
32481
|
+
`${String(events.length)} recent monitor_events row(s) found.`,
|
|
32482
|
+
{ eventIds: events.map((event) => event.id) }
|
|
32483
|
+
)
|
|
32484
|
+
);
|
|
32485
|
+
}
|
|
32486
|
+
const projections = this.store.listDeliveryProjectionsForMonitor(
|
|
32487
|
+
input.monitorId,
|
|
32488
|
+
// Scope to the explained workspace's sessions (plus global sessions) so
|
|
32489
|
+
// projections from other workspaces are not overcounted (issue #94 review).
|
|
32490
|
+
input.workspacePath
|
|
32491
|
+
);
|
|
32492
|
+
const leadSessions = this.store.sessionsForWorkspace(input.workspacePath).filter((session) => session.role === "lead");
|
|
32493
|
+
if (events.length > 0 && projections.length === 0) {
|
|
32494
|
+
stages.push(
|
|
32495
|
+
explainStage(
|
|
32496
|
+
"delivery",
|
|
32497
|
+
"failure",
|
|
32498
|
+
leadSessions.length === 0 ? "No lead session is registered for this workspace, so events were not projected." : "No session_event_state projections exist for the materialized events.",
|
|
32499
|
+
{ leadSessions: leadSessions.map((session) => session.id) }
|
|
32500
|
+
)
|
|
32501
|
+
);
|
|
32502
|
+
} else if (events.length > 0) {
|
|
32503
|
+
const counts = projections.reduce(
|
|
32504
|
+
(acc, projection) => {
|
|
32505
|
+
acc[projection.deliveryState] = (acc[projection.deliveryState] ?? 0) + 1;
|
|
32506
|
+
return acc;
|
|
32507
|
+
},
|
|
32508
|
+
{}
|
|
32509
|
+
);
|
|
32510
|
+
stages.push(
|
|
32511
|
+
explainStage(
|
|
32512
|
+
"delivery",
|
|
32513
|
+
"ok",
|
|
32514
|
+
`Events are projected to lead sessions (${Object.entries(counts).map(([state, count]) => `${state}: ${String(count)}`).join(", ")}).`,
|
|
32515
|
+
counts
|
|
32516
|
+
)
|
|
32517
|
+
);
|
|
32518
|
+
} else {
|
|
32519
|
+
stages.push(
|
|
32520
|
+
observationHealthy ? explainStage(
|
|
32521
|
+
"delivery",
|
|
32522
|
+
"healthy",
|
|
32523
|
+
"Nothing to deliver \u2014 the source observed no changes, so there is no signal to project (not a bug)."
|
|
32524
|
+
) : explainStage(
|
|
32525
|
+
"delivery",
|
|
32526
|
+
"pending",
|
|
32527
|
+
"Delivery has not started because no event has materialized yet."
|
|
32528
|
+
)
|
|
32529
|
+
);
|
|
32530
|
+
}
|
|
32531
|
+
return {
|
|
32532
|
+
monitorId: input.monitorId,
|
|
32533
|
+
generatedAt: now,
|
|
32534
|
+
monitor: {
|
|
32535
|
+
id: monitor.id,
|
|
32536
|
+
displayName: monitor.displayName,
|
|
32537
|
+
filePath: monitor.filePath,
|
|
32538
|
+
sourceName,
|
|
32539
|
+
urgency: monitor.frontmatter.urgency
|
|
32540
|
+
},
|
|
32541
|
+
stages,
|
|
32542
|
+
verdict: explainVerdict(stages),
|
|
32543
|
+
observations,
|
|
32544
|
+
events,
|
|
32545
|
+
projections,
|
|
32546
|
+
leadSessions
|
|
32547
|
+
};
|
|
32548
|
+
}
|
|
32160
32549
|
acknowledgeSession(sessionId, eventIds) {
|
|
32161
32550
|
const ids = eventIds ?? this.store.unreadEventsForSession(sessionId).map((e) => e.id);
|
|
32162
32551
|
this.store.acknowledgeEvents(sessionId, ids);
|
|
@@ -32301,6 +32690,7 @@ var AgentMonitorRuntime = class {
|
|
|
32301
32690
|
const now = /* @__PURE__ */ new Date();
|
|
32302
32691
|
const emittedEventIds = [];
|
|
32303
32692
|
const evaluated = [];
|
|
32693
|
+
const erroredObservations = [];
|
|
32304
32694
|
for (const parsed of result.monitors) {
|
|
32305
32695
|
const monitor = parsed.monitor;
|
|
32306
32696
|
const sourceName = monitor.frontmatter.watch.type;
|
|
@@ -32325,13 +32715,15 @@ var AgentMonitorRuntime = class {
|
|
|
32325
32715
|
}
|
|
32326
32716
|
);
|
|
32327
32717
|
} catch (observeError) {
|
|
32718
|
+
const message = observeError instanceof Error ? observeError.message : String(observeError);
|
|
32719
|
+
erroredObservations.push({ monitorId: monitor.id, message });
|
|
32328
32720
|
try {
|
|
32329
32721
|
this.store.recordObservationHistory({
|
|
32330
32722
|
monitorId: monitor.id,
|
|
32331
32723
|
sourceName,
|
|
32332
32724
|
result: "errored",
|
|
32333
32725
|
observationData: {
|
|
32334
|
-
error:
|
|
32726
|
+
error: message
|
|
32335
32727
|
}
|
|
32336
32728
|
});
|
|
32337
32729
|
} catch {
|
|
@@ -32347,13 +32739,15 @@ var AgentMonitorRuntime = class {
|
|
|
32347
32739
|
})
|
|
32348
32740
|
);
|
|
32349
32741
|
} catch (ingestError) {
|
|
32742
|
+
const message = ingestError instanceof Error ? ingestError.message : String(ingestError);
|
|
32743
|
+
erroredObservations.push({ monitorId: monitor.id, message });
|
|
32350
32744
|
try {
|
|
32351
32745
|
this.store.recordObservationHistory({
|
|
32352
32746
|
monitorId: monitor.id,
|
|
32353
32747
|
sourceName,
|
|
32354
32748
|
result: "errored",
|
|
32355
32749
|
observationData: {
|
|
32356
|
-
error:
|
|
32750
|
+
error: message
|
|
32357
32751
|
}
|
|
32358
32752
|
});
|
|
32359
32753
|
} catch {
|
|
@@ -32361,7 +32755,11 @@ var AgentMonitorRuntime = class {
|
|
|
32361
32755
|
}
|
|
32362
32756
|
}
|
|
32363
32757
|
this.refreshWorkspaceSessions(workspacePath);
|
|
32364
|
-
return {
|
|
32758
|
+
return {
|
|
32759
|
+
evaluatedMonitors: evaluated,
|
|
32760
|
+
emittedEventIds,
|
|
32761
|
+
erroredObservations
|
|
32762
|
+
};
|
|
32365
32763
|
}
|
|
32366
32764
|
/**
|
|
32367
32765
|
* Funnel a batch of observations through notify dispatch, persist the updated
|
|
@@ -32969,7 +33367,7 @@ var scopeSchema2 = {
|
|
|
32969
33367
|
properties: {
|
|
32970
33368
|
path: {
|
|
32971
33369
|
type: "string",
|
|
32972
|
-
description: 'Dotted
|
|
33370
|
+
description: 'Dotted path to the array within the parsed JSON (e.g. "tasks" or "$.tasks")'
|
|
32973
33371
|
},
|
|
32974
33372
|
key: {
|
|
32975
33373
|
type: "string",
|
|
@@ -32978,7 +33376,7 @@ var scopeSchema2 = {
|
|
|
32978
33376
|
"ignore-paths": {
|
|
32979
33377
|
type: "array",
|
|
32980
33378
|
items: { type: "string" },
|
|
32981
|
-
description:
|
|
33379
|
+
description: 'Dotted paths (relative to each element, e.g. "fetchedAt" or "$.fetchedAt") removed before comparison'
|
|
32982
33380
|
}
|
|
32983
33381
|
},
|
|
32984
33382
|
required: ["path", "key"]
|
|
@@ -33076,6 +33474,12 @@ function parseScopeConfig3(config2) {
|
|
|
33076
33474
|
const cd = config2["change-detection"];
|
|
33077
33475
|
const rawStrategy = cd?.strategy;
|
|
33078
33476
|
const strategy = rawStrategy === "json-diff" || rawStrategy === "exit-code" ? rawStrategy : "text-diff";
|
|
33477
|
+
const ignorePaths = parseTopLevelIgnorePaths(cd);
|
|
33478
|
+
if (ignorePaths.length > 0 && strategy !== "json-diff") {
|
|
33479
|
+
throw new Error(
|
|
33480
|
+
"change-detection.ignore-paths requires strategy: json-diff"
|
|
33481
|
+
);
|
|
33482
|
+
}
|
|
33079
33483
|
const collection = parseKeyedCollectionConfig(config2["change-detection"]);
|
|
33080
33484
|
if (collection && strategy !== "json-diff") {
|
|
33081
33485
|
throw new Error("change-detection.collection requires strategy: json-diff");
|
|
@@ -33087,7 +33491,16 @@ function parseScopeConfig3(config2) {
|
|
|
33087
33491
|
const timeoutMs = typeof rawTimeout === "string" ? parseDuration(rawTimeout) : DEFAULT_TIMEOUT_MS;
|
|
33088
33492
|
const key = config2["key"];
|
|
33089
33493
|
const objectKey = typeof key === "string" && key.length > 0 ? key : command.join(" ");
|
|
33090
|
-
return {
|
|
33494
|
+
return {
|
|
33495
|
+
command,
|
|
33496
|
+
cwd,
|
|
33497
|
+
env,
|
|
33498
|
+
timeoutMs,
|
|
33499
|
+
objectKey,
|
|
33500
|
+
strategy,
|
|
33501
|
+
ignorePaths,
|
|
33502
|
+
collection
|
|
33503
|
+
};
|
|
33091
33504
|
}
|
|
33092
33505
|
async function runCommand(scope) {
|
|
33093
33506
|
return new Promise((resolve) => {
|
|
@@ -33173,18 +33586,75 @@ function sortKeys3(value) {
|
|
|
33173
33586
|
}
|
|
33174
33587
|
return value;
|
|
33175
33588
|
}
|
|
33176
|
-
function
|
|
33589
|
+
function parseTopLevelIgnorePaths(changeDetection) {
|
|
33590
|
+
const rawIgnorePaths = changeDetection?.["ignore-paths"];
|
|
33591
|
+
if (rawIgnorePaths === void 0) return [];
|
|
33592
|
+
if (!Array.isArray(rawIgnorePaths) || !rawIgnorePaths.every((entry) => typeof entry === "string")) {
|
|
33593
|
+
throw new Error(
|
|
33594
|
+
"change-detection.ignore-paths must be an array of strings"
|
|
33595
|
+
);
|
|
33596
|
+
}
|
|
33597
|
+
return rawIgnorePaths;
|
|
33598
|
+
}
|
|
33599
|
+
function normalizeJsonPath(path13) {
|
|
33600
|
+
if (path13 === "$" || path13.startsWith("$.")) return path13;
|
|
33601
|
+
return `$.${path13}`;
|
|
33602
|
+
}
|
|
33603
|
+
function assertValidJsonPathSegment(path13, segment) {
|
|
33604
|
+
if (segment.length === 0) {
|
|
33605
|
+
throw new Error(
|
|
33606
|
+
`Invalid change-detection.ignore-paths entry "${path13}": empty path segment`
|
|
33607
|
+
);
|
|
33608
|
+
}
|
|
33609
|
+
if (/[.[\]*?]/.test(segment)) {
|
|
33610
|
+
throw new Error(
|
|
33611
|
+
`Invalid change-detection.ignore-paths entry "${path13}": unsupported path segment "${segment}"`
|
|
33612
|
+
);
|
|
33613
|
+
}
|
|
33614
|
+
}
|
|
33615
|
+
function stripIgnoredJsonPaths(value, ignorePaths) {
|
|
33616
|
+
if (ignorePaths.length === 0) return value;
|
|
33617
|
+
const cloned = structuredClone(value);
|
|
33618
|
+
for (const path13 of ignorePaths) {
|
|
33619
|
+
removeJsonPath(cloned, path13);
|
|
33620
|
+
}
|
|
33621
|
+
return cloned;
|
|
33622
|
+
}
|
|
33623
|
+
function removeJsonPath(value, path13) {
|
|
33624
|
+
const normalizedPath = normalizeJsonPath(path13);
|
|
33625
|
+
if (normalizedPath === "$") return;
|
|
33626
|
+
const segments = normalizedPath.slice(2).split(".");
|
|
33627
|
+
let current = value;
|
|
33628
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
33629
|
+
const segment = segments[i];
|
|
33630
|
+
assertValidJsonPathSegment(path13, segment ?? "");
|
|
33631
|
+
if (current === null || typeof current !== "object") return;
|
|
33632
|
+
if (!Object.hasOwn(current, segment ?? "")) return;
|
|
33633
|
+
current = current[segment ?? ""];
|
|
33634
|
+
}
|
|
33635
|
+
const last = segments.at(-1) ?? "";
|
|
33636
|
+
assertValidJsonPathSegment(path13, last);
|
|
33637
|
+
if (current !== null && typeof current === "object") {
|
|
33638
|
+
Reflect.deleteProperty(current, last);
|
|
33639
|
+
}
|
|
33640
|
+
}
|
|
33641
|
+
function hasChanged2(strategy, ignorePaths, prev, curr) {
|
|
33177
33642
|
switch (strategy) {
|
|
33178
33643
|
case "exit-code":
|
|
33179
33644
|
return prev.exitCode !== curr.exitCode;
|
|
33180
|
-
case "json-diff":
|
|
33645
|
+
case "json-diff": {
|
|
33646
|
+
let prevParsed;
|
|
33647
|
+
let currParsed;
|
|
33181
33648
|
try {
|
|
33182
|
-
|
|
33183
|
-
|
|
33184
|
-
return prevJson !== currJson;
|
|
33649
|
+
prevParsed = JSON.parse(prev.stdout);
|
|
33650
|
+
currParsed = JSON.parse(curr.stdout);
|
|
33185
33651
|
} catch {
|
|
33186
33652
|
return prev.stdout !== curr.stdout;
|
|
33187
33653
|
}
|
|
33654
|
+
return JSON.stringify(
|
|
33655
|
+
sortKeys3(stripIgnoredJsonPaths(prevParsed, ignorePaths))
|
|
33656
|
+
) !== JSON.stringify(sortKeys3(stripIgnoredJsonPaths(currParsed, ignorePaths)));
|
|
33657
|
+
}
|
|
33188
33658
|
case "text-diff":
|
|
33189
33659
|
return prev.stdout !== curr.stdout;
|
|
33190
33660
|
}
|
|
@@ -33266,7 +33736,7 @@ var scopeSchema3 = {
|
|
|
33266
33736
|
properties: {
|
|
33267
33737
|
path: {
|
|
33268
33738
|
type: "string",
|
|
33269
|
-
description: 'Dotted
|
|
33739
|
+
description: 'Dotted path to the array within the parsed JSON (e.g. "tasks" or "$.tasks")'
|
|
33270
33740
|
},
|
|
33271
33741
|
key: {
|
|
33272
33742
|
type: "string",
|
|
@@ -33275,20 +33745,38 @@ var scopeSchema3 = {
|
|
|
33275
33745
|
"ignore-paths": {
|
|
33276
33746
|
type: "array",
|
|
33277
33747
|
items: { type: "string" },
|
|
33278
|
-
description:
|
|
33748
|
+
description: 'Dotted paths (relative to each element, e.g. "fetchedAt" or "$.fetchedAt") removed before comparison'
|
|
33279
33749
|
}
|
|
33280
33750
|
},
|
|
33281
|
-
required: ["path", "key"]
|
|
33751
|
+
required: ["path", "key"],
|
|
33752
|
+
additionalProperties: false
|
|
33753
|
+
},
|
|
33754
|
+
"ignore-paths": {
|
|
33755
|
+
type: "array",
|
|
33756
|
+
items: { type: "string" },
|
|
33757
|
+
description: "Dotted paths removed from parsed JSON before plain json-diff comparison"
|
|
33282
33758
|
}
|
|
33283
33759
|
},
|
|
33760
|
+
additionalProperties: false,
|
|
33284
33761
|
// BP3: change-detection.collection requires strategy: json-diff. Under any
|
|
33285
33762
|
// other strategy (or the defaulted text-diff), presence of `collection` is an
|
|
33286
33763
|
// authoring-time error.
|
|
33287
|
-
|
|
33288
|
-
|
|
33289
|
-
|
|
33290
|
-
|
|
33291
|
-
|
|
33764
|
+
allOf: [
|
|
33765
|
+
{
|
|
33766
|
+
if: { required: ["collection"] },
|
|
33767
|
+
then: {
|
|
33768
|
+
properties: { strategy: { const: "json-diff" } },
|
|
33769
|
+
required: ["strategy"]
|
|
33770
|
+
}
|
|
33771
|
+
},
|
|
33772
|
+
{
|
|
33773
|
+
if: { required: ["ignore-paths"] },
|
|
33774
|
+
then: {
|
|
33775
|
+
properties: { strategy: { const: "json-diff" } },
|
|
33776
|
+
required: ["strategy"]
|
|
33777
|
+
}
|
|
33778
|
+
}
|
|
33779
|
+
]
|
|
33292
33780
|
}
|
|
33293
33781
|
},
|
|
33294
33782
|
required: ["command"]
|
|
@@ -33353,7 +33841,7 @@ var source3 = {
|
|
|
33353
33841
|
health: "ok",
|
|
33354
33842
|
baselined: true
|
|
33355
33843
|
};
|
|
33356
|
-
if (prev !== void 0 && hadBaseline && hasChanged2(scope.strategy, prev, result)) {
|
|
33844
|
+
if (prev !== void 0 && hadBaseline && hasChanged2(scope.strategy, scope.ignorePaths, prev, result)) {
|
|
33357
33845
|
observations.push(changedObservation(scope, result));
|
|
33358
33846
|
}
|
|
33359
33847
|
return { observations, nextState };
|
|
@@ -33696,6 +34184,23 @@ function changeDetectionCollectionError(watchConfig2) {
|
|
|
33696
34184
|
if (strategy === "json-diff") return void 0;
|
|
33697
34185
|
return "change-detection.collection requires strategy: json-diff";
|
|
33698
34186
|
}
|
|
34187
|
+
function oldSourceScopeShapeHint(filePath2) {
|
|
34188
|
+
let content;
|
|
34189
|
+
try {
|
|
34190
|
+
content = (0, import_node_fs3.readFileSync)(filePath2, "utf-8");
|
|
34191
|
+
} catch {
|
|
34192
|
+
return null;
|
|
34193
|
+
}
|
|
34194
|
+
const normalised = content.replace(/^\uFEFF/, "").replace(/\r\n/g, "\n");
|
|
34195
|
+
const frontmatter = /^---\n(?<frontmatter>[\s\S]*?)\n---/.exec(normalised)?.groups?.["frontmatter"];
|
|
34196
|
+
if (!frontmatter) return null;
|
|
34197
|
+
const rawSource = /^source:\s*(?<source>[^\n#]+)/m.exec(frontmatter)?.groups?.["source"];
|
|
34198
|
+
const source6 = rawSource?.trim().replace(/^['"]|['"]$/g, "");
|
|
34199
|
+
const hasScope = /^scope\s*:/m.test(frontmatter);
|
|
34200
|
+
const hasWatch = /^watch\s*:/m.test(frontmatter);
|
|
34201
|
+
if (!source6 || !hasScope || hasWatch) return null;
|
|
34202
|
+
return `did you mean to use the current watch shape? Move source/scope into watch:, for example: watch: { type: ${source6}, ... }`;
|
|
34203
|
+
}
|
|
33699
34204
|
var validateCommand = new Command("validate").description("Validate MONITOR.md files in a directory").argument("[path]", "Path to monitors directory", ".claude/monitors").addOption(
|
|
33700
34205
|
new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")
|
|
33701
34206
|
).action(async (monitorPath, options2) => {
|
|
@@ -33728,12 +34233,12 @@ var validateCommand = new Command("validate").description("Validate MONITOR.md f
|
|
|
33728
34233
|
});
|
|
33729
34234
|
const duplicateErrors = result.duplicateIds.map((dup) => ({
|
|
33730
34235
|
filePath: dup.filePaths.join(", "),
|
|
33731
|
-
error: `Duplicate monitor id "${dup.id}"
|
|
34236
|
+
error: `Duplicate monitor id "${dup.id}" -- ids are derived from folder names and must be unique within a tree`
|
|
33732
34237
|
}));
|
|
33733
34238
|
const allErrors = [
|
|
33734
34239
|
...result.errors.map((e) => ({
|
|
33735
34240
|
filePath: e.filePath,
|
|
33736
|
-
error: e.error
|
|
34241
|
+
error: [e.error, oldSourceScopeShapeHint(e.filePath)].filter(Boolean).join("; ")
|
|
33737
34242
|
})),
|
|
33738
34243
|
...scopeErrors.map((e) => ({
|
|
33739
34244
|
filePath: e.id,
|
|
@@ -33983,19 +34488,14 @@ inboxCommand.command("archive").description("Archive a completed or failed inbox
|
|
|
33983
34488
|
|
|
33984
34489
|
// src/commands/monitor-test.ts
|
|
33985
34490
|
init_cjs_shims();
|
|
33986
|
-
var
|
|
34491
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
34492
|
+
var import_node_fs5 = require("fs");
|
|
33987
34493
|
var import_promises4 = require("timers/promises");
|
|
33988
34494
|
|
|
33989
|
-
// src/runtime-client.ts
|
|
33990
|
-
init_cjs_shims();
|
|
33991
|
-
|
|
33992
|
-
// src/runtime.ts
|
|
33993
|
-
init_cjs_shims();
|
|
33994
|
-
|
|
33995
34495
|
// src/daemon-ipc.ts
|
|
33996
34496
|
init_cjs_shims();
|
|
33997
34497
|
var import_node_crypto = require("crypto");
|
|
33998
|
-
var
|
|
34498
|
+
var import_node_fs4 = require("fs");
|
|
33999
34499
|
var import_node_os2 = require("os");
|
|
34000
34500
|
var import_node_path4 = __toESM(require("path"), 1);
|
|
34001
34501
|
var import_node_net = __toESM(require("net"), 1);
|
|
@@ -34018,6 +34518,7 @@ var daemonMethodSchema = external_exports.enum([
|
|
|
34018
34518
|
"events.ack",
|
|
34019
34519
|
"hook.claim",
|
|
34020
34520
|
"history.list",
|
|
34521
|
+
"monitor.explain",
|
|
34021
34522
|
"daemon.tick"
|
|
34022
34523
|
]);
|
|
34023
34524
|
var daemonResponseSchema = external_exports.object({
|
|
@@ -34066,6 +34567,13 @@ var historyListParamsSchema = external_exports.object({
|
|
|
34066
34567
|
monitorId: external_exports.string().optional(),
|
|
34067
34568
|
limit: external_exports.number().int().positive().optional()
|
|
34068
34569
|
});
|
|
34570
|
+
var monitorExplainParamsSchema = external_exports.object({
|
|
34571
|
+
monitorId: external_exports.string(),
|
|
34572
|
+
monitorsDir: external_exports.string(),
|
|
34573
|
+
workspacePath: external_exports.string().optional(),
|
|
34574
|
+
historyLimit: external_exports.number().int().positive().optional(),
|
|
34575
|
+
eventLimit: external_exports.number().int().positive().optional()
|
|
34576
|
+
});
|
|
34069
34577
|
var daemonTickParamsSchema = external_exports.object({
|
|
34070
34578
|
monitorsDir: external_exports.string(),
|
|
34071
34579
|
workspacePath: external_exports.string().optional()
|
|
@@ -34075,6 +34583,13 @@ var daemonRequestSchema = external_exports.object({
|
|
|
34075
34583
|
method: daemonMethodSchema,
|
|
34076
34584
|
params: external_exports.record(external_exports.string(), external_exports.unknown())
|
|
34077
34585
|
});
|
|
34586
|
+
var DaemonConnectionError = class extends Error {
|
|
34587
|
+
constructor(message, cause) {
|
|
34588
|
+
super(message);
|
|
34589
|
+
this.cause = cause;
|
|
34590
|
+
}
|
|
34591
|
+
name = "DaemonConnectionError";
|
|
34592
|
+
};
|
|
34078
34593
|
function isErrnoException(error2) {
|
|
34079
34594
|
return typeof error2 === "object" && error2 !== null && "code" in error2;
|
|
34080
34595
|
}
|
|
@@ -34095,7 +34610,7 @@ function resolveSocketPath(overridePath) {
|
|
|
34095
34610
|
}
|
|
34096
34611
|
function cleanupSocket(socketPath) {
|
|
34097
34612
|
try {
|
|
34098
|
-
(0,
|
|
34613
|
+
(0, import_node_fs4.rmSync)(socketPath);
|
|
34099
34614
|
} catch (error2) {
|
|
34100
34615
|
const code = isErrnoException(error2) ? String(error2.code) : "";
|
|
34101
34616
|
if (code !== "ENOENT") throw error2;
|
|
@@ -34136,8 +34651,8 @@ function acquireStartupLock(socketPath) {
|
|
|
34136
34651
|
const pidFile = import_node_path4.default.join(lock, "pid");
|
|
34137
34652
|
const tryMkdir = () => {
|
|
34138
34653
|
try {
|
|
34139
|
-
(0,
|
|
34140
|
-
(0,
|
|
34654
|
+
(0, import_node_fs4.mkdirSync)(lock);
|
|
34655
|
+
(0, import_node_fs4.writeFileSync)(pidFile, String(process.pid), "utf-8");
|
|
34141
34656
|
return true;
|
|
34142
34657
|
} catch (err) {
|
|
34143
34658
|
if (!isErrnoException(err) || err.code !== "EEXIST") throw err;
|
|
@@ -34147,7 +34662,7 @@ function acquireStartupLock(socketPath) {
|
|
|
34147
34662
|
if (tryMkdir()) return true;
|
|
34148
34663
|
let holderPid;
|
|
34149
34664
|
try {
|
|
34150
|
-
holderPid = parseInt((0,
|
|
34665
|
+
holderPid = parseInt((0, import_node_fs4.readFileSync)(pidFile, "utf-8"), 10);
|
|
34151
34666
|
} catch {
|
|
34152
34667
|
return false;
|
|
34153
34668
|
}
|
|
@@ -34168,11 +34683,11 @@ function acquireStartupLock(socketPath) {
|
|
|
34168
34683
|
return false;
|
|
34169
34684
|
}
|
|
34170
34685
|
try {
|
|
34171
|
-
(0,
|
|
34686
|
+
(0, import_node_fs4.unlinkSync)(pidFile);
|
|
34172
34687
|
} catch {
|
|
34173
34688
|
}
|
|
34174
34689
|
try {
|
|
34175
|
-
(0,
|
|
34690
|
+
(0, import_node_fs4.rmdirSync)(lock);
|
|
34176
34691
|
} catch {
|
|
34177
34692
|
}
|
|
34178
34693
|
return tryMkdir();
|
|
@@ -34181,11 +34696,11 @@ function releaseStartupLock(socketPath) {
|
|
|
34181
34696
|
const lock = lockPath(socketPath);
|
|
34182
34697
|
const pidFile = import_node_path4.default.join(lock, "pid");
|
|
34183
34698
|
try {
|
|
34184
|
-
(0,
|
|
34699
|
+
(0, import_node_fs4.unlinkSync)(pidFile);
|
|
34185
34700
|
} catch {
|
|
34186
34701
|
}
|
|
34187
34702
|
try {
|
|
34188
|
-
(0,
|
|
34703
|
+
(0, import_node_fs4.rmdirSync)(lock);
|
|
34189
34704
|
} catch {
|
|
34190
34705
|
}
|
|
34191
34706
|
}
|
|
@@ -34256,6 +34771,16 @@ function handleRequest(runtime, request, stop) {
|
|
|
34256
34771
|
})
|
|
34257
34772
|
);
|
|
34258
34773
|
}
|
|
34774
|
+
case "monitor.explain": {
|
|
34775
|
+
const params = monitorExplainParamsSchema.parse(request.params);
|
|
34776
|
+
return runtime.explainMonitor({
|
|
34777
|
+
monitorId: params.monitorId,
|
|
34778
|
+
monitorsDir: params.monitorsDir,
|
|
34779
|
+
...params.workspacePath ? { workspacePath: params.workspacePath } : {},
|
|
34780
|
+
...params.historyLimit ? { historyLimit: params.historyLimit } : {},
|
|
34781
|
+
...params.eventLimit ? { eventLimit: params.eventLimit } : {}
|
|
34782
|
+
});
|
|
34783
|
+
}
|
|
34259
34784
|
case "daemon.tick": {
|
|
34260
34785
|
const params = daemonTickParamsSchema.parse(request.params);
|
|
34261
34786
|
return runtime.tick(params.monitorsDir, params.workspacePath);
|
|
@@ -34267,7 +34792,7 @@ function createDaemonServer({
|
|
|
34267
34792
|
socketPath,
|
|
34268
34793
|
onStop
|
|
34269
34794
|
}) {
|
|
34270
|
-
(0,
|
|
34795
|
+
(0, import_node_fs4.mkdirSync)(import_node_path4.default.dirname(socketPath), { recursive: true });
|
|
34271
34796
|
let serverClosed = false;
|
|
34272
34797
|
const server = import_node_net.default.createServer((socket) => {
|
|
34273
34798
|
let buffer = "";
|
|
@@ -34325,7 +34850,7 @@ function createDaemonServer({
|
|
|
34325
34850
|
const live = await probeSocket(socketPath);
|
|
34326
34851
|
if (!live) {
|
|
34327
34852
|
try {
|
|
34328
|
-
(0,
|
|
34853
|
+
(0, import_node_fs4.unlinkSync)(socketPath);
|
|
34329
34854
|
} catch (unlinkErr) {
|
|
34330
34855
|
const code = isErrnoException(unlinkErr) ? String(unlinkErr.code) : "";
|
|
34331
34856
|
if (code !== "ENOENT") throw unlinkErr;
|
|
@@ -34391,11 +34916,20 @@ async function callDaemon(method, params = {}, options2 = {}) {
|
|
|
34391
34916
|
});
|
|
34392
34917
|
};
|
|
34393
34918
|
socket.setTimeout(timeoutMs, () => {
|
|
34394
|
-
fail(
|
|
34919
|
+
fail(
|
|
34920
|
+
new DaemonConnectionError(
|
|
34921
|
+
`Timed out waiting for AgentMon daemon at ${socketPath}`
|
|
34922
|
+
)
|
|
34923
|
+
);
|
|
34395
34924
|
});
|
|
34396
34925
|
socket.setEncoding("utf-8");
|
|
34397
34926
|
socket.on("error", (error2) => {
|
|
34398
|
-
fail(
|
|
34927
|
+
fail(
|
|
34928
|
+
new DaemonConnectionError(
|
|
34929
|
+
error2 instanceof Error ? error2.message : String(error2),
|
|
34930
|
+
error2
|
|
34931
|
+
)
|
|
34932
|
+
);
|
|
34399
34933
|
});
|
|
34400
34934
|
socket.on("data", (chunk) => {
|
|
34401
34935
|
buffer += typeof chunk === "string" ? chunk : chunk.toString("utf-8");
|
|
@@ -34436,7 +34970,11 @@ async function daemonAvailable(socketPath) {
|
|
|
34436
34970
|
}
|
|
34437
34971
|
}
|
|
34438
34972
|
|
|
34973
|
+
// src/runtime-client.ts
|
|
34974
|
+
init_cjs_shims();
|
|
34975
|
+
|
|
34439
34976
|
// src/runtime.ts
|
|
34977
|
+
init_cjs_shims();
|
|
34440
34978
|
function createRuntime(dbPath = resolveDbPath()) {
|
|
34441
34979
|
const db = createDb(dbPath);
|
|
34442
34980
|
const registry2 = new SourceRegistry();
|
|
@@ -34499,6 +35037,13 @@ async function listObservationHistoryClient(query, socketPath) {
|
|
|
34499
35037
|
socketPath ? { socketPath } : {}
|
|
34500
35038
|
);
|
|
34501
35039
|
}
|
|
35040
|
+
async function explainMonitorClient(input, socketPath) {
|
|
35041
|
+
return await callDaemon(
|
|
35042
|
+
"monitor.explain",
|
|
35043
|
+
input,
|
|
35044
|
+
socketPath ? { socketPath } : {}
|
|
35045
|
+
);
|
|
35046
|
+
}
|
|
34502
35047
|
async function daemonStatusClient(socketPath) {
|
|
34503
35048
|
return await callDaemon(
|
|
34504
35049
|
"status",
|
|
@@ -34515,6 +35060,127 @@ async function daemonTickClient(monitorsDir, workspacePath) {
|
|
|
34515
35060
|
var monitorTestCommand = new Command("monitor").description(
|
|
34516
35061
|
"Monitor utilities"
|
|
34517
35062
|
);
|
|
35063
|
+
var EXPLAIN_STAGE_LABELS2 = {
|
|
35064
|
+
definition: "Definition",
|
|
35065
|
+
scheduling: "Scheduling",
|
|
35066
|
+
observation: "Observation",
|
|
35067
|
+
notify: "Notify state",
|
|
35068
|
+
materialization: "Materialization",
|
|
35069
|
+
delivery: "Projection and delivery"
|
|
35070
|
+
};
|
|
35071
|
+
function monitorIdFromFilePath2(filePath2) {
|
|
35072
|
+
const base = import_node_path5.default.basename(filePath2);
|
|
35073
|
+
return base === "MONITOR.md" ? import_node_path5.default.basename(import_node_path5.default.dirname(filePath2)) : import_node_path5.default.parse(filePath2).name;
|
|
35074
|
+
}
|
|
35075
|
+
function explainStage2(id, status, reason, details) {
|
|
35076
|
+
return {
|
|
35077
|
+
id,
|
|
35078
|
+
label: EXPLAIN_STAGE_LABELS2[id],
|
|
35079
|
+
status,
|
|
35080
|
+
reason,
|
|
35081
|
+
...details ? { details } : {}
|
|
35082
|
+
};
|
|
35083
|
+
}
|
|
35084
|
+
function explainVerdict2(stages) {
|
|
35085
|
+
const stopped = stages.find((stage2) => stage2.status !== "ok");
|
|
35086
|
+
const stage = stopped ?? stages[stages.length - 1];
|
|
35087
|
+
return {
|
|
35088
|
+
status: stage?.status ?? "ok",
|
|
35089
|
+
stage: stage?.id ?? "delivery",
|
|
35090
|
+
reason: stage?.reason ?? "Monitor delivered successfully."
|
|
35091
|
+
};
|
|
35092
|
+
}
|
|
35093
|
+
function statusGlyph(status) {
|
|
35094
|
+
if (status === "ok") return "\u2713";
|
|
35095
|
+
if (status === "pending") return "\u23F3";
|
|
35096
|
+
if (status === "healthy") return "\u25CB";
|
|
35097
|
+
return "\u2717";
|
|
35098
|
+
}
|
|
35099
|
+
function printExplainText(report) {
|
|
35100
|
+
console.log(`Monitor ${report.monitorId}`);
|
|
35101
|
+
for (const stage of report.stages) {
|
|
35102
|
+
console.log(`${statusGlyph(stage.status)} ${stage.label}: ${stage.reason}`);
|
|
35103
|
+
}
|
|
35104
|
+
console.log(
|
|
35105
|
+
`Verdict: ${report.verdict.status} at ${EXPLAIN_STAGE_LABELS2[report.verdict.stage]} - ${report.verdict.reason}`
|
|
35106
|
+
);
|
|
35107
|
+
}
|
|
35108
|
+
async function buildDaemonUnavailableReport(input) {
|
|
35109
|
+
const generatedAt = /* @__PURE__ */ new Date();
|
|
35110
|
+
const stages = [];
|
|
35111
|
+
const scan = await scanMonitors(input.monitorsDir);
|
|
35112
|
+
const parseError = scan.errors.find(
|
|
35113
|
+
(error2) => monitorIdFromFilePath2(error2.filePath) === input.monitorId
|
|
35114
|
+
);
|
|
35115
|
+
const monitor = scan.monitors.find(
|
|
35116
|
+
(candidate) => candidate.monitor.id === input.monitorId
|
|
35117
|
+
)?.monitor;
|
|
35118
|
+
if (parseError) {
|
|
35119
|
+
stages.push(
|
|
35120
|
+
explainStage2(
|
|
35121
|
+
"definition",
|
|
35122
|
+
"failure",
|
|
35123
|
+
`MONITOR.md failed to parse or validate: ${parseError.error}`,
|
|
35124
|
+
{ filePath: parseError.filePath }
|
|
35125
|
+
)
|
|
35126
|
+
);
|
|
35127
|
+
} else if (!monitor) {
|
|
35128
|
+
stages.push(
|
|
35129
|
+
explainStage2(
|
|
35130
|
+
"definition",
|
|
35131
|
+
"failure",
|
|
35132
|
+
`Monitor "${input.monitorId}" was not found in ${input.monitorsDir}.`
|
|
35133
|
+
)
|
|
35134
|
+
);
|
|
35135
|
+
} else {
|
|
35136
|
+
const registry2 = new SourceRegistry();
|
|
35137
|
+
registerCoreSources(registry2);
|
|
35138
|
+
const sourceName = monitor.frontmatter.watch.type;
|
|
35139
|
+
const source6 = registry2.get(sourceName);
|
|
35140
|
+
const { type: _type, ...monitorWatchConfig } = monitor.frontmatter.watch;
|
|
35141
|
+
const scopeErrors = source6 ? validateScope(monitorWatchConfig, source6.scopeSchema) : [`Unknown source "${sourceName}".`];
|
|
35142
|
+
stages.push(
|
|
35143
|
+
scopeErrors.length === 0 ? explainStage2("definition", "ok", "Monitor definition is valid.", {
|
|
35144
|
+
filePath: monitor.filePath,
|
|
35145
|
+
sourceName
|
|
35146
|
+
}) : explainStage2(
|
|
35147
|
+
"definition",
|
|
35148
|
+
"failure",
|
|
35149
|
+
`Monitor definition is invalid: ${scopeErrors.join("; ")}`,
|
|
35150
|
+
{ filePath: monitor.filePath, sourceName }
|
|
35151
|
+
)
|
|
35152
|
+
);
|
|
35153
|
+
}
|
|
35154
|
+
if (stages[0]?.status === "ok") {
|
|
35155
|
+
stages.push(
|
|
35156
|
+
explainStage2(
|
|
35157
|
+
"scheduling",
|
|
35158
|
+
"failure",
|
|
35159
|
+
`The daemon is not running or unreachable: ${input.errorMessage}`,
|
|
35160
|
+
{ workspacePath: input.workspacePath }
|
|
35161
|
+
)
|
|
35162
|
+
);
|
|
35163
|
+
}
|
|
35164
|
+
return {
|
|
35165
|
+
monitorId: input.monitorId,
|
|
35166
|
+
generatedAt,
|
|
35167
|
+
...monitor ? {
|
|
35168
|
+
monitor: {
|
|
35169
|
+
id: monitor.id,
|
|
35170
|
+
displayName: monitor.displayName,
|
|
35171
|
+
filePath: monitor.filePath,
|
|
35172
|
+
sourceName: monitor.frontmatter.watch.type,
|
|
35173
|
+
urgency: monitor.frontmatter.urgency
|
|
35174
|
+
}
|
|
35175
|
+
} : {},
|
|
35176
|
+
stages,
|
|
35177
|
+
verdict: explainVerdict2(stages),
|
|
35178
|
+
observations: [],
|
|
35179
|
+
events: [],
|
|
35180
|
+
projections: [],
|
|
35181
|
+
leadSessions: []
|
|
35182
|
+
};
|
|
35183
|
+
}
|
|
34518
35184
|
function printJsonResult(monitorName, sourceName, baseline, observations) {
|
|
34519
35185
|
console.log(
|
|
34520
35186
|
JSON.stringify(
|
|
@@ -34598,13 +35264,13 @@ monitorTestCommand.command("test").description("Dry-run a monitor observation so
|
|
|
34598
35264
|
new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")
|
|
34599
35265
|
).action(async (filePath2, options2) => {
|
|
34600
35266
|
const json = options2.format === "json";
|
|
34601
|
-
if (!(0,
|
|
35267
|
+
if (!(0, import_node_fs5.existsSync)(filePath2)) {
|
|
34602
35268
|
reportError(`Monitor file not found: ${filePath2}`, json);
|
|
34603
35269
|
return;
|
|
34604
35270
|
}
|
|
34605
35271
|
let content;
|
|
34606
35272
|
try {
|
|
34607
|
-
content = (0,
|
|
35273
|
+
content = (0, import_node_fs5.readFileSync)(filePath2, "utf-8");
|
|
34608
35274
|
} catch (err) {
|
|
34609
35275
|
const msg = err instanceof Error ? err.message : String(err);
|
|
34610
35276
|
reportError(`Cannot read monitor file: ${msg}`, json);
|
|
@@ -34660,6 +35326,55 @@ monitorTestCommand.command("test").description("Dry-run a monitor observation so
|
|
|
34660
35326
|
reportError(`Observation failed: ${message}`, json);
|
|
34661
35327
|
}
|
|
34662
35328
|
});
|
|
35329
|
+
monitorTestCommand.command("explain").description("Explain where a monitor's signal currently stops").argument("<monitorId>", "Monitor id to diagnose").option(
|
|
35330
|
+
"--dir <path>",
|
|
35331
|
+
"Directory containing monitor definitions",
|
|
35332
|
+
".claude/monitors"
|
|
35333
|
+
).option("--workspace <path>", "Workspace path used by the daemon").option("--socket <path>", "Unix domain socket path for the daemon").option("--history-limit <n>", "Observation history rows to include", "10").option("--event-limit <n>", "Materialized event rows to include", "10").addOption(
|
|
35334
|
+
new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")
|
|
35335
|
+
).action(
|
|
35336
|
+
async (monitorId, options2) => {
|
|
35337
|
+
const json = options2.format === "json";
|
|
35338
|
+
const monitorsDir = import_node_path5.default.resolve(options2.dir);
|
|
35339
|
+
const workspacePath = import_node_path5.default.resolve(options2.workspace ?? process.cwd());
|
|
35340
|
+
const historyLimit = Number.parseInt(options2.historyLimit, 10);
|
|
35341
|
+
const eventLimit = Number.parseInt(options2.eventLimit, 10);
|
|
35342
|
+
try {
|
|
35343
|
+
const report = await explainMonitorClient(
|
|
35344
|
+
{
|
|
35345
|
+
monitorId,
|
|
35346
|
+
monitorsDir,
|
|
35347
|
+
workspacePath,
|
|
35348
|
+
...Number.isFinite(historyLimit) && historyLimit > 0 ? { historyLimit } : {},
|
|
35349
|
+
...Number.isFinite(eventLimit) && eventLimit > 0 ? { eventLimit } : {}
|
|
35350
|
+
},
|
|
35351
|
+
options2.socket
|
|
35352
|
+
);
|
|
35353
|
+
if (json) {
|
|
35354
|
+
console.log(JSON.stringify(report, null, 2));
|
|
35355
|
+
return;
|
|
35356
|
+
}
|
|
35357
|
+
printExplainText(report);
|
|
35358
|
+
} catch (err) {
|
|
35359
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
35360
|
+
if (!(err instanceof DaemonConnectionError)) {
|
|
35361
|
+
reportError(`Explain failed: ${message}`, json);
|
|
35362
|
+
return;
|
|
35363
|
+
}
|
|
35364
|
+
const report = await buildDaemonUnavailableReport({
|
|
35365
|
+
monitorId,
|
|
35366
|
+
monitorsDir,
|
|
35367
|
+
workspacePath,
|
|
35368
|
+
errorMessage: message
|
|
35369
|
+
});
|
|
35370
|
+
if (json) {
|
|
35371
|
+
console.log(JSON.stringify(report, null, 2));
|
|
35372
|
+
return;
|
|
35373
|
+
}
|
|
35374
|
+
printExplainText(report);
|
|
35375
|
+
}
|
|
35376
|
+
}
|
|
35377
|
+
);
|
|
34663
35378
|
monitorTestCommand.command("history").description(
|
|
34664
35379
|
"Show recent observation outcomes per tick (triggered / suppressed / no-change / errored / rebaselined)"
|
|
34665
35380
|
).argument("[monitorId]", "Filter to a single monitor id").option("--socket <path>", "Unix domain socket path for the daemon").option("--limit <n>", "Maximum rows to return", "50").addOption(
|
|
@@ -34711,9 +35426,11 @@ sourceCommand.command("list").description("List installed observation sources").
|
|
|
34711
35426
|
const output = sources.map((source6) => {
|
|
34712
35427
|
const requiredFields = source6.scopeSchema["required"] ?? [];
|
|
34713
35428
|
const properties = source6.scopeSchema["properties"] ?? {};
|
|
35429
|
+
const configFields = Object.keys(properties);
|
|
34714
35430
|
return {
|
|
34715
35431
|
name: source6.name,
|
|
34716
|
-
|
|
35432
|
+
configFields,
|
|
35433
|
+
scopeFields: configFields,
|
|
34717
35434
|
required: requiredFields
|
|
34718
35435
|
};
|
|
34719
35436
|
});
|
|
@@ -34729,7 +35446,7 @@ sourceCommand.command("list").description("List installed observation sources").
|
|
|
34729
35446
|
const requiredFields = source6.scopeSchema["required"] ?? [];
|
|
34730
35447
|
const properties = source6.scopeSchema["properties"] ?? {};
|
|
34731
35448
|
console.log(` ${source6.name}`);
|
|
34732
|
-
console.log(`
|
|
35449
|
+
console.log(` Config fields: ${Object.keys(properties).join(", ")}`);
|
|
34733
35450
|
console.log(` Required: ${requiredFields.join(", ") || "(none)"}`);
|
|
34734
35451
|
console.log("");
|
|
34735
35452
|
}
|
|
@@ -34817,6 +35534,11 @@ function shouldReap(s) {
|
|
|
34817
35534
|
|
|
34818
35535
|
// src/commands/daemon.ts
|
|
34819
35536
|
var DEFAULT_REAP_AFTER_MS = 5 * 60 * 1e3;
|
|
35537
|
+
function appendErroredLines(summary, errored) {
|
|
35538
|
+
if (errored.length === 0) return summary;
|
|
35539
|
+
const lines = errored.map((e) => ` ${e.monitorId}: ${e.message}`);
|
|
35540
|
+
return [summary, ...lines].join("\n");
|
|
35541
|
+
}
|
|
34820
35542
|
async function runLoop(monitorsDir, workspacePath, pollMs, socketPath, reapAfterMs) {
|
|
34821
35543
|
const runtime = createRuntime();
|
|
34822
35544
|
let stopping = false;
|
|
@@ -34862,10 +35584,12 @@ async function runLoop(monitorsDir, workspacePath, pollMs, socketPath, reapAfter
|
|
|
34862
35584
|
while (!isStoppingRequested()) {
|
|
34863
35585
|
try {
|
|
34864
35586
|
const result = await runtime.tick(monitorsDir, workspacePath);
|
|
34865
|
-
if (result.emittedEventIds.length > 0) {
|
|
34866
|
-
|
|
34867
|
-
`Emitted ${String(result.emittedEventIds.length)} event(s) from ${String(result.evaluatedMonitors.length)} monitor(s)
|
|
35587
|
+
if (result.emittedEventIds.length > 0 || result.erroredObservations.length > 0) {
|
|
35588
|
+
const summary = appendErroredLines(
|
|
35589
|
+
`Emitted ${String(result.emittedEventIds.length)} event(s) from ${String(result.evaluatedMonitors.length)} monitor(s)${result.erroredObservations.length > 0 ? `, ${String(result.erroredObservations.length)} errored:` : "."}`,
|
|
35590
|
+
result.erroredObservations
|
|
34868
35591
|
);
|
|
35592
|
+
console.log(summary);
|
|
34869
35593
|
}
|
|
34870
35594
|
} catch (error2) {
|
|
34871
35595
|
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
@@ -34931,9 +35655,9 @@ daemonCommand.command("once").description("Run one runtime observation cycle").a
|
|
|
34931
35655
|
console.log(JSON.stringify(result, null, 2));
|
|
34932
35656
|
return;
|
|
34933
35657
|
}
|
|
34934
|
-
|
|
34935
|
-
|
|
34936
|
-
);
|
|
35658
|
+
const erroredCount = result.erroredObservations.length;
|
|
35659
|
+
const base = `Evaluated ${String(result.evaluatedMonitors.length)} monitor(s), emitted ${String(result.emittedEventIds.length)} event(s)${erroredCount > 0 ? `, ${String(erroredCount)} errored:` : "."}`;
|
|
35660
|
+
console.log(appendErroredLines(base, result.erroredObservations));
|
|
34937
35661
|
} catch (error2) {
|
|
34938
35662
|
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
34939
35663
|
reportError(message, options2.format === "json");
|
|
@@ -35026,15 +35750,15 @@ daemonCommand.command("stop").description("Ask the local AgentMon daemon to stop
|
|
|
35026
35750
|
|
|
35027
35751
|
// src/commands/session.ts
|
|
35028
35752
|
init_cjs_shims();
|
|
35029
|
-
var
|
|
35753
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
35030
35754
|
|
|
35031
35755
|
// src/local-state.ts
|
|
35032
35756
|
init_cjs_shims();
|
|
35033
|
-
var
|
|
35034
|
-
var
|
|
35757
|
+
var import_node_fs6 = require("fs");
|
|
35758
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
35035
35759
|
var DEFAULT_REAP_AFTER_MS2 = 5 * 60 * 1e3;
|
|
35036
35760
|
function filePath(workspacePath) {
|
|
35037
|
-
return
|
|
35761
|
+
return import_node_path6.default.join(workspacePath, ".claude", "agentmonitors.local.md");
|
|
35038
35762
|
}
|
|
35039
35763
|
function parseFrontmatter(raw) {
|
|
35040
35764
|
const lines = raw.split("\n");
|
|
@@ -35063,7 +35787,7 @@ function parseFrontmatter(raw) {
|
|
|
35063
35787
|
function readLocalState(workspacePath) {
|
|
35064
35788
|
let raw;
|
|
35065
35789
|
try {
|
|
35066
|
-
raw = (0,
|
|
35790
|
+
raw = (0, import_node_fs6.readFileSync)(filePath(workspacePath), "utf-8");
|
|
35067
35791
|
} catch {
|
|
35068
35792
|
return { enabled: false };
|
|
35069
35793
|
}
|
|
@@ -35084,7 +35808,7 @@ function readLocalState(workspacePath) {
|
|
|
35084
35808
|
}
|
|
35085
35809
|
function writeLocalState(workspacePath, state) {
|
|
35086
35810
|
const target = filePath(workspacePath);
|
|
35087
|
-
(0,
|
|
35811
|
+
(0, import_node_fs6.mkdirSync)(import_node_path6.default.dirname(target), { recursive: true });
|
|
35088
35812
|
const lines = [
|
|
35089
35813
|
"---",
|
|
35090
35814
|
`enabled: ${String(state.enabled)}`,
|
|
@@ -35096,25 +35820,25 @@ function writeLocalState(workspacePath, state) {
|
|
|
35096
35820
|
"> Local AgentMon coordination state. Gitignored; safe to delete (it is regenerated).",
|
|
35097
35821
|
""
|
|
35098
35822
|
];
|
|
35099
|
-
(0,
|
|
35823
|
+
(0, import_node_fs6.writeFileSync)(target, lines.join("\n"), "utf-8");
|
|
35100
35824
|
}
|
|
35101
35825
|
|
|
35102
35826
|
// src/workspace-paths.ts
|
|
35103
35827
|
init_cjs_shims();
|
|
35104
35828
|
var import_node_crypto2 = require("crypto");
|
|
35105
35829
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
35106
|
-
var
|
|
35830
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
35107
35831
|
function workspacePaths(workspacePath) {
|
|
35108
|
-
const hash = (0, import_node_crypto2.createHash)("sha256").update(
|
|
35109
|
-
const dataRoot = process.env["XDG_DATA_HOME"] ??
|
|
35110
|
-
const dir =
|
|
35832
|
+
const hash = (0, import_node_crypto2.createHash)("sha256").update(import_node_path7.default.resolve(workspacePath)).digest("hex").slice(0, 16);
|
|
35833
|
+
const dataRoot = process.env["XDG_DATA_HOME"] ?? import_node_path7.default.join(import_node_os3.default.homedir(), ".local", "share");
|
|
35834
|
+
const dir = import_node_path7.default.join(dataRoot, "agentmonitors", "workspaces", hash);
|
|
35111
35835
|
return {
|
|
35112
35836
|
dir,
|
|
35113
|
-
db:
|
|
35837
|
+
db: import_node_path7.default.join(dir, "inbox.db"),
|
|
35114
35838
|
// Keep the socket short: a 16-char hash under the data dir stays well under
|
|
35115
35839
|
// the 100-char limit on most setups; resolveSocketPath's /tmp fallback still
|
|
35116
35840
|
// applies if a deep home dir pushes it over.
|
|
35117
|
-
socket:
|
|
35841
|
+
socket: import_node_path7.default.join(dir, "agentmonitors.sock")
|
|
35118
35842
|
};
|
|
35119
35843
|
}
|
|
35120
35844
|
|
|
@@ -35122,15 +35846,15 @@ function workspacePaths(workspacePath) {
|
|
|
35122
35846
|
init_cjs_shims();
|
|
35123
35847
|
var import_node_child_process = require("child_process");
|
|
35124
35848
|
var import_node_url3 = require("url");
|
|
35125
|
-
var
|
|
35849
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
35126
35850
|
function cliEntry() {
|
|
35127
35851
|
const thisFile = (0, import_node_url3.fileURLToPath)(importMetaUrl);
|
|
35128
|
-
const isBundle =
|
|
35852
|
+
const isBundle = import_node_path8.default.basename(import_node_path8.default.dirname(thisFile)) === "dist";
|
|
35129
35853
|
if (isBundle) {
|
|
35130
35854
|
return thisFile;
|
|
35131
35855
|
}
|
|
35132
|
-
const packageRoot =
|
|
35133
|
-
return
|
|
35856
|
+
const packageRoot = import_node_path8.default.resolve(import_node_path8.default.dirname(thisFile), "..");
|
|
35857
|
+
return import_node_path8.default.join(packageRoot, "dist", "index.cjs");
|
|
35134
35858
|
}
|
|
35135
35859
|
function spawnDetachedDaemon(options2) {
|
|
35136
35860
|
const args = [
|
|
@@ -35337,7 +36061,7 @@ sessionCommand.command("start").description(
|
|
|
35337
36061
|
const paths = workspacePaths(workspacePath);
|
|
35338
36062
|
const socket = resolveSocketPath(state.socket ?? paths.socket);
|
|
35339
36063
|
const db = state.db ?? paths.db;
|
|
35340
|
-
const monitorsDir =
|
|
36064
|
+
const monitorsDir = import_node_path9.default.join(workspacePath, ".claude", "monitors");
|
|
35341
36065
|
const BOOT_TIMEOUT_MS = 8e3;
|
|
35342
36066
|
if (!await daemonAvailable(socket)) {
|
|
35343
36067
|
spawnDetachedDaemon({
|
|
@@ -35771,10 +36495,10 @@ function assignProp(target, prop, value) {
|
|
|
35771
36495
|
configurable: true
|
|
35772
36496
|
});
|
|
35773
36497
|
}
|
|
35774
|
-
function getElementAtPath(obj,
|
|
35775
|
-
if (!
|
|
36498
|
+
function getElementAtPath(obj, path13) {
|
|
36499
|
+
if (!path13)
|
|
35776
36500
|
return obj;
|
|
35777
|
-
return
|
|
36501
|
+
return path13.reduce((acc, key) => acc?.[key], obj);
|
|
35778
36502
|
}
|
|
35779
36503
|
function promiseAllObject(promisesObj) {
|
|
35780
36504
|
const keys = Object.keys(promisesObj);
|
|
@@ -36094,11 +36818,11 @@ function aborted(x2, startIndex = 0) {
|
|
|
36094
36818
|
}
|
|
36095
36819
|
return false;
|
|
36096
36820
|
}
|
|
36097
|
-
function prefixIssues(
|
|
36821
|
+
function prefixIssues(path13, issues) {
|
|
36098
36822
|
return issues.map((iss) => {
|
|
36099
36823
|
var _a2;
|
|
36100
36824
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
36101
|
-
iss.path.unshift(
|
|
36825
|
+
iss.path.unshift(path13);
|
|
36102
36826
|
return iss;
|
|
36103
36827
|
});
|
|
36104
36828
|
}
|
|
@@ -43007,9 +43731,9 @@ async function runChannelServe(options2) {
|
|
|
43007
43731
|
// src/index.ts
|
|
43008
43732
|
function getVersion() {
|
|
43009
43733
|
try {
|
|
43010
|
-
const dir = (0,
|
|
43734
|
+
const dir = (0, import_node_path10.dirname)((0, import_node_url4.fileURLToPath)(importMetaUrl));
|
|
43011
43735
|
const pkg = JSON.parse(
|
|
43012
|
-
(0,
|
|
43736
|
+
(0, import_node_fs7.readFileSync)((0, import_node_path10.join)(dir, "..", "package.json"), "utf8")
|
|
43013
43737
|
);
|
|
43014
43738
|
return typeof pkg.version === "string" ? pkg.version : "0.0.0";
|
|
43015
43739
|
} catch {
|