@agentmonitors/cli 0.3.1 → 0.4.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 +824 -208
- package/dist/index.cjs.map +1 -1
- package/package.json +7 -6
package/dist/index.cjs
CHANGED
|
@@ -33,10 +33,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
33
33
|
mod
|
|
34
34
|
));
|
|
35
35
|
|
|
36
|
-
// ../../node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.7_@types+node@22.19.
|
|
36
|
+
// ../../node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.7_@types+node@22.19.15__jiti@2.7.0_postcss@8.5.8_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js
|
|
37
37
|
var getImportMetaUrl, importMetaUrl;
|
|
38
38
|
var init_cjs_shims = __esm({
|
|
39
|
-
"../../node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.7_@types+node@22.19.
|
|
39
|
+
"../../node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.7_@types+node@22.19.15__jiti@2.7.0_postcss@8.5.8_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js"() {
|
|
40
40
|
"use strict";
|
|
41
41
|
getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
|
|
42
42
|
importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
@@ -2020,13 +2020,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2020
2020
|
* @param {string} source - expected values are default/config/env/cli/implied
|
|
2021
2021
|
* @return {Command} `this` command for chaining
|
|
2022
2022
|
*/
|
|
2023
|
-
setOptionValueWithSource(key, value,
|
|
2023
|
+
setOptionValueWithSource(key, value, source6) {
|
|
2024
2024
|
if (this._storeOptionsAsProperties) {
|
|
2025
2025
|
this[key] = value;
|
|
2026
2026
|
} else {
|
|
2027
2027
|
this._optionValues[key] = value;
|
|
2028
2028
|
}
|
|
2029
|
-
this._optionValueSources[key] =
|
|
2029
|
+
this._optionValueSources[key] = source6;
|
|
2030
2030
|
return this;
|
|
2031
2031
|
}
|
|
2032
2032
|
/**
|
|
@@ -2047,13 +2047,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2047
2047
|
* @return {string}
|
|
2048
2048
|
*/
|
|
2049
2049
|
getOptionValueSourceWithGlobals(key) {
|
|
2050
|
-
let
|
|
2050
|
+
let source6;
|
|
2051
2051
|
this._getCommandAndAncestors().forEach((cmd) => {
|
|
2052
2052
|
if (cmd.getOptionValueSource(key) !== void 0) {
|
|
2053
|
-
|
|
2053
|
+
source6 = cmd.getOptionValueSource(key);
|
|
2054
2054
|
}
|
|
2055
2055
|
});
|
|
2056
|
-
return
|
|
2056
|
+
return source6;
|
|
2057
2057
|
}
|
|
2058
2058
|
/**
|
|
2059
2059
|
* Get user arguments from implied or explicit arguments.
|
|
@@ -2922,8 +2922,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2922
2922
|
const getErrorMessage = (option2) => {
|
|
2923
2923
|
const bestOption = findBestOptionFromValue(option2);
|
|
2924
2924
|
const optionKey = bestOption.attributeName();
|
|
2925
|
-
const
|
|
2926
|
-
if (
|
|
2925
|
+
const source6 = this.getOptionValueSource(optionKey);
|
|
2926
|
+
if (source6 === "env") {
|
|
2927
2927
|
return `environment variable '${bestOption.envVar}'`;
|
|
2928
2928
|
}
|
|
2929
2929
|
return `option '${bestOption.flags}'`;
|
|
@@ -3773,13 +3773,13 @@ var require_common = __commonJS({
|
|
|
3773
3773
|
else if (isNothing(sequence)) return [];
|
|
3774
3774
|
return [sequence];
|
|
3775
3775
|
}
|
|
3776
|
-
function extend2(target,
|
|
3776
|
+
function extend2(target, source6) {
|
|
3777
3777
|
var index, length, key, sourceKeys;
|
|
3778
|
-
if (
|
|
3779
|
-
sourceKeys = Object.keys(
|
|
3778
|
+
if (source6) {
|
|
3779
|
+
sourceKeys = Object.keys(source6);
|
|
3780
3780
|
for (index = 0, length = sourceKeys.length; index < length; index += 1) {
|
|
3781
3781
|
key = sourceKeys[index];
|
|
3782
|
-
target[key] =
|
|
3782
|
+
target[key] = source6[key];
|
|
3783
3783
|
}
|
|
3784
3784
|
}
|
|
3785
3785
|
return target;
|
|
@@ -4837,7 +4837,7 @@ var require_function = __commonJS({
|
|
|
4837
4837
|
function resolveJavascriptFunction(data) {
|
|
4838
4838
|
if (data === null) return false;
|
|
4839
4839
|
try {
|
|
4840
|
-
var
|
|
4840
|
+
var source6 = "(" + data + ")", ast = esprima.parse(source6, { range: true });
|
|
4841
4841
|
if (ast.type !== "Program" || ast.body.length !== 1 || ast.body[0].type !== "ExpressionStatement" || ast.body[0].expression.type !== "ArrowFunctionExpression" && ast.body[0].expression.type !== "FunctionExpression") {
|
|
4842
4842
|
return false;
|
|
4843
4843
|
}
|
|
@@ -4847,7 +4847,7 @@ var require_function = __commonJS({
|
|
|
4847
4847
|
}
|
|
4848
4848
|
}
|
|
4849
4849
|
function constructJavascriptFunction(data) {
|
|
4850
|
-
var
|
|
4850
|
+
var source6 = "(" + data + ")", ast = esprima.parse(source6, { range: true }), params = [], body;
|
|
4851
4851
|
if (ast.type !== "Program" || ast.body.length !== 1 || ast.body[0].type !== "ExpressionStatement" || ast.body[0].expression.type !== "ArrowFunctionExpression" && ast.body[0].expression.type !== "FunctionExpression") {
|
|
4852
4852
|
throw new Error("Failed to resolve function");
|
|
4853
4853
|
}
|
|
@@ -4856,9 +4856,9 @@ var require_function = __commonJS({
|
|
|
4856
4856
|
});
|
|
4857
4857
|
body = ast.body[0].expression.body.range;
|
|
4858
4858
|
if (ast.body[0].expression.body.type === "BlockStatement") {
|
|
4859
|
-
return new Function(params,
|
|
4859
|
+
return new Function(params, source6.slice(body[0] + 1, body[1] - 1));
|
|
4860
4860
|
}
|
|
4861
|
-
return new Function(params, "return " +
|
|
4861
|
+
return new Function(params, "return " + source6.slice(body[0], body[1]));
|
|
4862
4862
|
}
|
|
4863
4863
|
function representJavascriptFunction(object3) {
|
|
4864
4864
|
return object3.toString();
|
|
@@ -5084,16 +5084,16 @@ var require_loader = __commonJS({
|
|
|
5084
5084
|
state.result += _result;
|
|
5085
5085
|
}
|
|
5086
5086
|
}
|
|
5087
|
-
function mergeMappings(state, destination,
|
|
5087
|
+
function mergeMappings(state, destination, source6, overridableKeys) {
|
|
5088
5088
|
var sourceKeys, key, index, quantity;
|
|
5089
|
-
if (!common.isObject(
|
|
5089
|
+
if (!common.isObject(source6)) {
|
|
5090
5090
|
throwError(state, "cannot merge mappings; the provided source object is unacceptable");
|
|
5091
5091
|
}
|
|
5092
|
-
sourceKeys = Object.keys(
|
|
5092
|
+
sourceKeys = Object.keys(source6);
|
|
5093
5093
|
for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
|
|
5094
5094
|
key = sourceKeys[index];
|
|
5095
5095
|
if (!_hasOwnProperty.call(destination, key)) {
|
|
5096
|
-
setProperty(destination, key,
|
|
5096
|
+
setProperty(destination, key, source6[key]);
|
|
5097
5097
|
overridableKeys[key] = true;
|
|
5098
5098
|
}
|
|
5099
5099
|
}
|
|
@@ -10581,10 +10581,10 @@ var require_fast_uri = __commonJS({
|
|
|
10581
10581
|
function normalize2(uri2, options2) {
|
|
10582
10582
|
if (typeof uri2 === "string") {
|
|
10583
10583
|
uri2 = /** @type {T} */
|
|
10584
|
-
|
|
10584
|
+
serialize2(parse4(uri2, options2), options2);
|
|
10585
10585
|
} else if (typeof uri2 === "object") {
|
|
10586
10586
|
uri2 = /** @type {T} */
|
|
10587
|
-
parse4(
|
|
10587
|
+
parse4(serialize2(uri2, options2), options2);
|
|
10588
10588
|
}
|
|
10589
10589
|
return uri2;
|
|
10590
10590
|
}
|
|
@@ -10592,13 +10592,13 @@ var require_fast_uri = __commonJS({
|
|
|
10592
10592
|
const schemelessOptions = options2 ? Object.assign({ scheme: "null" }, options2) : { scheme: "null" };
|
|
10593
10593
|
const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
10594
10594
|
schemelessOptions.skipEscape = true;
|
|
10595
|
-
return
|
|
10595
|
+
return serialize2(resolved, schemelessOptions);
|
|
10596
10596
|
}
|
|
10597
10597
|
function resolveComponent(base, relative, options2, skipNormalization) {
|
|
10598
10598
|
const target = {};
|
|
10599
10599
|
if (!skipNormalization) {
|
|
10600
|
-
base = parse4(
|
|
10601
|
-
relative = parse4(
|
|
10600
|
+
base = parse4(serialize2(base, options2), options2);
|
|
10601
|
+
relative = parse4(serialize2(relative, options2), options2);
|
|
10602
10602
|
}
|
|
10603
10603
|
options2 = options2 || {};
|
|
10604
10604
|
if (!options2.tolerant && relative.scheme) {
|
|
@@ -10650,19 +10650,19 @@ var require_fast_uri = __commonJS({
|
|
|
10650
10650
|
function equal(uriA, uriB, options2) {
|
|
10651
10651
|
if (typeof uriA === "string") {
|
|
10652
10652
|
uriA = unescape(uriA);
|
|
10653
|
-
uriA =
|
|
10653
|
+
uriA = serialize2(normalizeComponentEncoding(parse4(uriA, options2), true), { ...options2, skipEscape: true });
|
|
10654
10654
|
} else if (typeof uriA === "object") {
|
|
10655
|
-
uriA =
|
|
10655
|
+
uriA = serialize2(normalizeComponentEncoding(uriA, true), { ...options2, skipEscape: true });
|
|
10656
10656
|
}
|
|
10657
10657
|
if (typeof uriB === "string") {
|
|
10658
10658
|
uriB = unescape(uriB);
|
|
10659
|
-
uriB =
|
|
10659
|
+
uriB = serialize2(normalizeComponentEncoding(parse4(uriB, options2), true), { ...options2, skipEscape: true });
|
|
10660
10660
|
} else if (typeof uriB === "object") {
|
|
10661
|
-
uriB =
|
|
10661
|
+
uriB = serialize2(normalizeComponentEncoding(uriB, true), { ...options2, skipEscape: true });
|
|
10662
10662
|
}
|
|
10663
10663
|
return uriA.toLowerCase() === uriB.toLowerCase();
|
|
10664
10664
|
}
|
|
10665
|
-
function
|
|
10665
|
+
function serialize2(cmpts, opts) {
|
|
10666
10666
|
const component = {
|
|
10667
10667
|
host: cmpts.host,
|
|
10668
10668
|
scheme: cmpts.scheme,
|
|
@@ -10818,7 +10818,7 @@ var require_fast_uri = __commonJS({
|
|
|
10818
10818
|
resolve,
|
|
10819
10819
|
resolveComponent,
|
|
10820
10820
|
equal,
|
|
10821
|
-
serialize,
|
|
10821
|
+
serialize: serialize2,
|
|
10822
10822
|
parse: parse4
|
|
10823
10823
|
};
|
|
10824
10824
|
module2.exports = fastUri;
|
|
@@ -11553,12 +11553,12 @@ var require_ref = __commonJS({
|
|
|
11553
11553
|
function callSyncRef() {
|
|
11554
11554
|
cxt.result((0, code_1.callValidateCode)(cxt, v, passCxt), () => addEvaluatedFrom(v), () => addErrorsFrom(v));
|
|
11555
11555
|
}
|
|
11556
|
-
function addErrorsFrom(
|
|
11557
|
-
const errs = (0, codegen_1._)`${
|
|
11556
|
+
function addErrorsFrom(source6) {
|
|
11557
|
+
const errs = (0, codegen_1._)`${source6}.errors`;
|
|
11558
11558
|
gen.assign(names_1.default.vErrors, (0, codegen_1._)`${names_1.default.vErrors} === null ? ${errs} : ${names_1.default.vErrors}.concat(${errs})`);
|
|
11559
11559
|
gen.assign(names_1.default.errors, (0, codegen_1._)`${names_1.default.vErrors}.length`);
|
|
11560
11560
|
}
|
|
11561
|
-
function addEvaluatedFrom(
|
|
11561
|
+
function addEvaluatedFrom(source6) {
|
|
11562
11562
|
var _a2;
|
|
11563
11563
|
if (!it.opts.unevaluated)
|
|
11564
11564
|
return;
|
|
@@ -11569,7 +11569,7 @@ var require_ref = __commonJS({
|
|
|
11569
11569
|
it.props = util_1.mergeEvaluated.props(gen, schEvaluated.props, it.props);
|
|
11570
11570
|
}
|
|
11571
11571
|
} else {
|
|
11572
|
-
const props = gen.var("props", (0, codegen_1._)`${
|
|
11572
|
+
const props = gen.var("props", (0, codegen_1._)`${source6}.evaluated.props`);
|
|
11573
11573
|
it.props = util_1.mergeEvaluated.props(gen, props, it.props, codegen_1.Name);
|
|
11574
11574
|
}
|
|
11575
11575
|
}
|
|
@@ -11579,7 +11579,7 @@ var require_ref = __commonJS({
|
|
|
11579
11579
|
it.items = util_1.mergeEvaluated.items(gen, schEvaluated.items, it.items);
|
|
11580
11580
|
}
|
|
11581
11581
|
} else {
|
|
11582
|
-
const items = gen.var("items", (0, codegen_1._)`${
|
|
11582
|
+
const items = gen.var("items", (0, codegen_1._)`${source6}.evaluated.items`);
|
|
11583
11583
|
it.items = util_1.mergeEvaluated.items(gen, items, it.items, codegen_1.Name);
|
|
11584
11584
|
}
|
|
11585
11585
|
}
|
|
@@ -13905,6 +13905,23 @@ urgency: normal
|
|
|
13905
13905
|
---
|
|
13906
13906
|
|
|
13907
13907
|
When the API response changes, review the differences and take appropriate action.
|
|
13908
|
+
`.trimStart(),
|
|
13909
|
+
"command-poll": yaml2`
|
|
13910
|
+
---
|
|
13911
|
+
name: My command monitor
|
|
13912
|
+
watch:
|
|
13913
|
+
type: command-poll
|
|
13914
|
+
command:
|
|
13915
|
+
- git
|
|
13916
|
+
- status
|
|
13917
|
+
- --porcelain
|
|
13918
|
+
interval: 5m
|
|
13919
|
+
change-detection:
|
|
13920
|
+
strategy: text-diff
|
|
13921
|
+
urgency: normal
|
|
13922
|
+
---
|
|
13923
|
+
|
|
13924
|
+
When the command output changes, review the differences and take appropriate action.
|
|
13908
13925
|
`.trimStart(),
|
|
13909
13926
|
schedule: yaml2`
|
|
13910
13927
|
---
|
|
@@ -28669,24 +28686,24 @@ var SQLiteSelectBuilder = class {
|
|
|
28669
28686
|
this.withList = config2.withList;
|
|
28670
28687
|
this.distinct = config2.distinct;
|
|
28671
28688
|
}
|
|
28672
|
-
from(
|
|
28689
|
+
from(source6) {
|
|
28673
28690
|
const isPartialSelect = !!this.fields;
|
|
28674
28691
|
let fields;
|
|
28675
28692
|
if (this.fields) {
|
|
28676
28693
|
fields = this.fields;
|
|
28677
|
-
} else if (is(
|
|
28694
|
+
} else if (is(source6, Subquery)) {
|
|
28678
28695
|
fields = Object.fromEntries(
|
|
28679
|
-
Object.keys(
|
|
28696
|
+
Object.keys(source6._.selectedFields).map((key) => [key, source6[key]])
|
|
28680
28697
|
);
|
|
28681
|
-
} else if (is(
|
|
28682
|
-
fields =
|
|
28683
|
-
} else if (is(
|
|
28698
|
+
} else if (is(source6, SQLiteViewBase)) {
|
|
28699
|
+
fields = source6[ViewBaseConfig].selectedFields;
|
|
28700
|
+
} else if (is(source6, SQL)) {
|
|
28684
28701
|
fields = {};
|
|
28685
28702
|
} else {
|
|
28686
|
-
fields = getTableColumns(
|
|
28703
|
+
fields = getTableColumns(source6);
|
|
28687
28704
|
}
|
|
28688
28705
|
return new SQLiteSelectBase({
|
|
28689
|
-
table:
|
|
28706
|
+
table: source6,
|
|
28690
28707
|
fields,
|
|
28691
28708
|
isPartialSelect,
|
|
28692
28709
|
session: this.session,
|
|
@@ -29590,8 +29607,8 @@ var SQLiteUpdateBase = class extends QueryPromise {
|
|
|
29590
29607
|
static [entityKind] = "SQLiteUpdate";
|
|
29591
29608
|
/** @internal */
|
|
29592
29609
|
config;
|
|
29593
|
-
from(
|
|
29594
|
-
this.config.from =
|
|
29610
|
+
from(source6) {
|
|
29611
|
+
this.config.from = source6;
|
|
29595
29612
|
return this;
|
|
29596
29613
|
}
|
|
29597
29614
|
createJoin(joinType) {
|
|
@@ -29743,11 +29760,11 @@ var SQLiteCountBuilder = class _SQLiteCountBuilder extends SQL {
|
|
|
29743
29760
|
static [entityKind] = "SQLiteCountBuilderAsync";
|
|
29744
29761
|
[Symbol.toStringTag] = "SQLiteCountBuilderAsync";
|
|
29745
29762
|
session;
|
|
29746
|
-
static buildEmbeddedCount(
|
|
29747
|
-
return sql`(select count(*) from ${
|
|
29763
|
+
static buildEmbeddedCount(source6, filters) {
|
|
29764
|
+
return sql`(select count(*) from ${source6}${sql.raw(" where ").if(filters)}${filters})`;
|
|
29748
29765
|
}
|
|
29749
|
-
static buildCount(
|
|
29750
|
-
return sql`select count(*) from ${
|
|
29766
|
+
static buildCount(source6, filters) {
|
|
29767
|
+
return sql`select count(*) from ${source6}${sql.raw(" where ").if(filters)}${filters}`;
|
|
29751
29768
|
}
|
|
29752
29769
|
then(onfulfilled, onrejected) {
|
|
29753
29770
|
return Promise.resolve(this.session.count(this.sql)).then(
|
|
@@ -30032,8 +30049,8 @@ var BaseSQLiteDatabase = class {
|
|
|
30032
30049
|
};
|
|
30033
30050
|
return { as };
|
|
30034
30051
|
};
|
|
30035
|
-
$count(
|
|
30036
|
-
return new SQLiteCountBuilder({ source:
|
|
30052
|
+
$count(source6, filters) {
|
|
30053
|
+
return new SQLiteCountBuilder({ source: source6, filters, session: this.session });
|
|
30037
30054
|
}
|
|
30038
30055
|
/**
|
|
30039
30056
|
* Incorporates a previously defined CTE (using `$with`) into the main query.
|
|
@@ -30607,8 +30624,8 @@ function drizzle(...params) {
|
|
|
30607
30624
|
const { connection, client, ...drizzleConfig } = params[0];
|
|
30608
30625
|
if (client) return construct(client, drizzleConfig);
|
|
30609
30626
|
if (typeof connection === "object") {
|
|
30610
|
-
const { source:
|
|
30611
|
-
const instance2 = new import_better_sqlite3.default(
|
|
30627
|
+
const { source: source6, ...options2 } = connection;
|
|
30628
|
+
const instance2 = new import_better_sqlite3.default(source6, options2);
|
|
30612
30629
|
return construct(instance2, drizzleConfig);
|
|
30613
30630
|
}
|
|
30614
30631
|
const instance = new import_better_sqlite3.default(connection);
|
|
@@ -30749,8 +30766,8 @@ var monitorFrontmatterSchema = external_exports.object({
|
|
|
30749
30766
|
notify: notifySchema.optional(),
|
|
30750
30767
|
tags: external_exports.array(external_exports.string()).optional()
|
|
30751
30768
|
});
|
|
30752
|
-
function validateScope(scope,
|
|
30753
|
-
const validator = new Validator(
|
|
30769
|
+
function validateScope(scope, scopeSchema6) {
|
|
30770
|
+
const validator = new Validator(scopeSchema6, "7", false);
|
|
30754
30771
|
const result = validator.validate(scope);
|
|
30755
30772
|
if (result.valid) return [];
|
|
30756
30773
|
const messages = result.errors.map((unit) => {
|
|
@@ -31224,13 +31241,13 @@ var InboxService = class {
|
|
|
31224
31241
|
};
|
|
31225
31242
|
var SourceRegistry = class {
|
|
31226
31243
|
sources = /* @__PURE__ */ new Map();
|
|
31227
|
-
register(
|
|
31228
|
-
if (this.sources.has(
|
|
31244
|
+
register(source6) {
|
|
31245
|
+
if (this.sources.has(source6.name)) {
|
|
31229
31246
|
throw new Error(
|
|
31230
|
-
`Observation source "${
|
|
31247
|
+
`Observation source "${source6.name}" is already registered`
|
|
31231
31248
|
);
|
|
31232
31249
|
}
|
|
31233
|
-
this.sources.set(
|
|
31250
|
+
this.sources.set(source6.name, source6);
|
|
31234
31251
|
}
|
|
31235
31252
|
get(name) {
|
|
31236
31253
|
return this.sources.get(name);
|
|
@@ -31247,7 +31264,7 @@ var SourceRegistry = class {
|
|
|
31247
31264
|
};
|
|
31248
31265
|
function generateMonitorSchema(sources) {
|
|
31249
31266
|
const sourceNames = sources.map((s) => s.name);
|
|
31250
|
-
const conditionals = sources.map((
|
|
31267
|
+
const conditionals = sources.map((source6) => ({
|
|
31251
31268
|
if: {
|
|
31252
31269
|
// `required: ['type']` on the inner `watch` is essential: JSON Schema
|
|
31253
31270
|
// `properties` constraints are vacuously satisfied when the property is
|
|
@@ -31256,14 +31273,14 @@ function generateMonitorSchema(sources) {
|
|
|
31256
31273
|
// instead of a clean "watch.type is required".
|
|
31257
31274
|
properties: {
|
|
31258
31275
|
watch: {
|
|
31259
|
-
properties: { type: { const:
|
|
31276
|
+
properties: { type: { const: source6.name } },
|
|
31260
31277
|
required: ["type"]
|
|
31261
31278
|
}
|
|
31262
31279
|
},
|
|
31263
31280
|
required: ["watch"]
|
|
31264
31281
|
},
|
|
31265
31282
|
then: {
|
|
31266
|
-
properties: { watch:
|
|
31283
|
+
properties: { watch: source6.scopeSchema }
|
|
31267
31284
|
}
|
|
31268
31285
|
}));
|
|
31269
31286
|
return {
|
|
@@ -31315,6 +31332,194 @@ function generateMonitorSchema(sources) {
|
|
|
31315
31332
|
allOf: conditionals
|
|
31316
31333
|
};
|
|
31317
31334
|
}
|
|
31335
|
+
function parseKeyedCollectionConfig(changeDetection) {
|
|
31336
|
+
if (changeDetection === null || typeof changeDetection !== "object" || Array.isArray(changeDetection)) {
|
|
31337
|
+
return void 0;
|
|
31338
|
+
}
|
|
31339
|
+
const collection = changeDetection["collection"];
|
|
31340
|
+
if (collection === void 0) return void 0;
|
|
31341
|
+
if (collection === null || typeof collection !== "object" || Array.isArray(collection)) {
|
|
31342
|
+
throw new Error(
|
|
31343
|
+
'change-detection.collection must be an object with "path" and "key"'
|
|
31344
|
+
);
|
|
31345
|
+
}
|
|
31346
|
+
const c = collection;
|
|
31347
|
+
const path72 = c["path"];
|
|
31348
|
+
if (typeof path72 !== "string" || path72.length === 0) {
|
|
31349
|
+
throw new Error(
|
|
31350
|
+
"change-detection.collection.path must be a non-empty string"
|
|
31351
|
+
);
|
|
31352
|
+
}
|
|
31353
|
+
const key = c["key"];
|
|
31354
|
+
if (typeof key !== "string" || key.length === 0) {
|
|
31355
|
+
throw new Error(
|
|
31356
|
+
"change-detection.collection.key must be a non-empty string"
|
|
31357
|
+
);
|
|
31358
|
+
}
|
|
31359
|
+
const rawIgnore = c["ignore-paths"];
|
|
31360
|
+
let ignorePaths;
|
|
31361
|
+
if (rawIgnore !== void 0) {
|
|
31362
|
+
if (!Array.isArray(rawIgnore) || !rawIgnore.every((p) => typeof p === "string")) {
|
|
31363
|
+
throw new Error(
|
|
31364
|
+
"change-detection.collection.ignore-paths must be an array of strings"
|
|
31365
|
+
);
|
|
31366
|
+
}
|
|
31367
|
+
ignorePaths = rawIgnore;
|
|
31368
|
+
}
|
|
31369
|
+
return ignorePaths ? { path: path72, key, ignorePaths } : { path: path72, key };
|
|
31370
|
+
}
|
|
31371
|
+
function assertValidSegment(path72, segment) {
|
|
31372
|
+
if (/[[\]*?\s]/.test(segment)) {
|
|
31373
|
+
throw new Error(
|
|
31374
|
+
`Invalid collection path "${path72}": segment "${segment}" contains unsupported syntax (only plain field names are allowed \u2014 no "[index]", wildcards, or filters)`
|
|
31375
|
+
);
|
|
31376
|
+
}
|
|
31377
|
+
}
|
|
31378
|
+
function resolveDottedPath(root, path72) {
|
|
31379
|
+
if (path72 === "$") return root;
|
|
31380
|
+
if (!path72.startsWith("$.")) {
|
|
31381
|
+
throw new Error(
|
|
31382
|
+
`Invalid collection path "${path72}": must start with "$." (e.g. "$.tasks")`
|
|
31383
|
+
);
|
|
31384
|
+
}
|
|
31385
|
+
const segments = path72.slice(2).split(".");
|
|
31386
|
+
let current = root;
|
|
31387
|
+
for (const segment of segments) {
|
|
31388
|
+
if (segment.length === 0) {
|
|
31389
|
+
throw new Error(`Invalid collection path "${path72}": empty path segment`);
|
|
31390
|
+
}
|
|
31391
|
+
assertValidSegment(path72, segment);
|
|
31392
|
+
if (current === null || typeof current !== "object" || Array.isArray(current)) {
|
|
31393
|
+
return void 0;
|
|
31394
|
+
}
|
|
31395
|
+
current = current[segment];
|
|
31396
|
+
}
|
|
31397
|
+
return current;
|
|
31398
|
+
}
|
|
31399
|
+
function removeDottedPath(value, path72) {
|
|
31400
|
+
if (path72 === "$") return;
|
|
31401
|
+
if (!path72.startsWith("$.")) {
|
|
31402
|
+
throw new Error(
|
|
31403
|
+
`Invalid ignore-paths entry "${path72}": must start with "$." (e.g. "$.fetchedAt")`
|
|
31404
|
+
);
|
|
31405
|
+
}
|
|
31406
|
+
const segments = path72.slice(2).split(".");
|
|
31407
|
+
let current = value;
|
|
31408
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
31409
|
+
const segment = segments[i];
|
|
31410
|
+
if (segment === void 0 || segment.length === 0) {
|
|
31411
|
+
throw new Error(
|
|
31412
|
+
`Invalid ignore-paths entry "${path72}": empty path segment`
|
|
31413
|
+
);
|
|
31414
|
+
}
|
|
31415
|
+
assertValidSegment(path72, segment);
|
|
31416
|
+
if (current === null || typeof current !== "object" || Array.isArray(current)) {
|
|
31417
|
+
return;
|
|
31418
|
+
}
|
|
31419
|
+
current = current[segment];
|
|
31420
|
+
}
|
|
31421
|
+
const last = segments[segments.length - 1];
|
|
31422
|
+
if (last === void 0 || last.length === 0) {
|
|
31423
|
+
throw new Error(`Invalid ignore-paths entry "${path72}": empty path segment`);
|
|
31424
|
+
}
|
|
31425
|
+
assertValidSegment(path72, last);
|
|
31426
|
+
if (current !== null && typeof current === "object" && !Array.isArray(current)) {
|
|
31427
|
+
Reflect.deleteProperty(current, last);
|
|
31428
|
+
}
|
|
31429
|
+
}
|
|
31430
|
+
function sortKeys(value) {
|
|
31431
|
+
if (Array.isArray(value)) return value.map(sortKeys);
|
|
31432
|
+
if (value !== null && typeof value === "object") {
|
|
31433
|
+
const sorted = {};
|
|
31434
|
+
for (const k of Object.keys(value).sort()) {
|
|
31435
|
+
sorted[k] = sortKeys(value[k]);
|
|
31436
|
+
}
|
|
31437
|
+
return sorted;
|
|
31438
|
+
}
|
|
31439
|
+
return value;
|
|
31440
|
+
}
|
|
31441
|
+
function normalizeElement(element, ignorePaths) {
|
|
31442
|
+
const clone2 = structuredClone(element);
|
|
31443
|
+
if (ignorePaths) {
|
|
31444
|
+
for (const p of ignorePaths) removeDottedPath(clone2, p);
|
|
31445
|
+
}
|
|
31446
|
+
return sortKeys(clone2);
|
|
31447
|
+
}
|
|
31448
|
+
function serialize(value) {
|
|
31449
|
+
return JSON.stringify(value);
|
|
31450
|
+
}
|
|
31451
|
+
function keyValueOf(element, keyField) {
|
|
31452
|
+
if (element === null || typeof element !== "object" || Array.isArray(element)) {
|
|
31453
|
+
throw new Error(
|
|
31454
|
+
`collection element is not an object (cannot read key "${keyField}")`
|
|
31455
|
+
);
|
|
31456
|
+
}
|
|
31457
|
+
const raw = element[keyField];
|
|
31458
|
+
if (typeof raw === "string") return raw;
|
|
31459
|
+
if (typeof raw === "number" || typeof raw === "boolean") return String(raw);
|
|
31460
|
+
throw new Error(
|
|
31461
|
+
`collection element is missing a scalar key field "${keyField}"`
|
|
31462
|
+
);
|
|
31463
|
+
}
|
|
31464
|
+
function diffKeyedCollection(parsedOutput, config2, monitorObjectKey, previousSnapshot, observationFields) {
|
|
31465
|
+
const resolved = resolveDottedPath(parsedOutput, config2.path);
|
|
31466
|
+
if (!Array.isArray(resolved)) {
|
|
31467
|
+
throw new Error(
|
|
31468
|
+
`collection path "${config2.path}" must select an array (got ${resolved === void 0 ? "nothing" : typeof resolved})`
|
|
31469
|
+
);
|
|
31470
|
+
}
|
|
31471
|
+
const current = {};
|
|
31472
|
+
for (const element of resolved) {
|
|
31473
|
+
const keyValue = keyValueOf(element, config2.key);
|
|
31474
|
+
if (Object.prototype.hasOwnProperty.call(current, keyValue)) {
|
|
31475
|
+
throw new Error(
|
|
31476
|
+
`collection key "${config2.key}" value "${keyValue}" is not unique within the collection`
|
|
31477
|
+
);
|
|
31478
|
+
}
|
|
31479
|
+
current[keyValue] = normalizeElement(element, config2.ignorePaths);
|
|
31480
|
+
}
|
|
31481
|
+
if (previousSnapshot === void 0) {
|
|
31482
|
+
return { observations: [], snapshot: current };
|
|
31483
|
+
}
|
|
31484
|
+
const observations = [];
|
|
31485
|
+
const emit = (keyValue, changeKind) => {
|
|
31486
|
+
const objectKey = `${monitorObjectKey}#${keyValue}`;
|
|
31487
|
+
const title = `${titleVerb(changeKind)}: ${objectKey}`;
|
|
31488
|
+
observations.push({
|
|
31489
|
+
title,
|
|
31490
|
+
summary: title,
|
|
31491
|
+
objectKey,
|
|
31492
|
+
changeKind,
|
|
31493
|
+
payload: { ...observationFields?.payload, key: keyValue, changeKind },
|
|
31494
|
+
queryScope: { ...observationFields?.queryScope, objectKey }
|
|
31495
|
+
});
|
|
31496
|
+
};
|
|
31497
|
+
for (const keyValue of Object.keys(current)) {
|
|
31498
|
+
if (!Object.prototype.hasOwnProperty.call(previousSnapshot, keyValue)) {
|
|
31499
|
+
emit(keyValue, "created");
|
|
31500
|
+
} else if (serialize(current[keyValue]) !== serialize(previousSnapshot[keyValue])) {
|
|
31501
|
+
emit(keyValue, "modified");
|
|
31502
|
+
}
|
|
31503
|
+
}
|
|
31504
|
+
for (const keyValue of Object.keys(previousSnapshot)) {
|
|
31505
|
+
if (!Object.prototype.hasOwnProperty.call(current, keyValue)) {
|
|
31506
|
+
emit(keyValue, "descoped");
|
|
31507
|
+
}
|
|
31508
|
+
}
|
|
31509
|
+
return { observations, snapshot: current };
|
|
31510
|
+
}
|
|
31511
|
+
function titleVerb(changeKind) {
|
|
31512
|
+
switch (changeKind) {
|
|
31513
|
+
case "created":
|
|
31514
|
+
return "Item added";
|
|
31515
|
+
case "modified":
|
|
31516
|
+
return "Item changed";
|
|
31517
|
+
case "descoped":
|
|
31518
|
+
return "Item removed";
|
|
31519
|
+
case "deleted":
|
|
31520
|
+
return "Item deleted";
|
|
31521
|
+
}
|
|
31522
|
+
}
|
|
31318
31523
|
function parseDuration(duration3) {
|
|
31319
31524
|
const match2 = /^(?<digits>\d+)(?<unit>[smhd])$/.exec(duration3);
|
|
31320
31525
|
const digits = match2?.groups?.["digits"];
|
|
@@ -32099,8 +32304,8 @@ var AgentMonitorRuntime = class {
|
|
|
32099
32304
|
for (const parsed of result.monitors) {
|
|
32100
32305
|
const monitor = parsed.monitor;
|
|
32101
32306
|
const sourceName = monitor.frontmatter.watch.type;
|
|
32102
|
-
const
|
|
32103
|
-
if (!
|
|
32307
|
+
const source6 = this.registry.get(sourceName);
|
|
32308
|
+
if (!source6) {
|
|
32104
32309
|
throw new Error(
|
|
32105
32310
|
`Monitor "${monitor.id}" references unknown source "${sourceName}".`
|
|
32106
32311
|
);
|
|
@@ -32112,7 +32317,7 @@ var AgentMonitorRuntime = class {
|
|
|
32112
32317
|
let observationResult;
|
|
32113
32318
|
try {
|
|
32114
32319
|
const monitorState2 = this.store.getMonitorState(monitor.id);
|
|
32115
|
-
observationResult = await
|
|
32320
|
+
observationResult = await source6.observe(
|
|
32116
32321
|
watchConfig(monitor.frontmatter.watch),
|
|
32117
32322
|
{
|
|
32118
32323
|
previousState: monitorState2.sourceState,
|
|
@@ -32263,18 +32468,18 @@ var AgentMonitorRuntime = class {
|
|
|
32263
32468
|
for (const parsed of result.monitors) {
|
|
32264
32469
|
const monitor = parsed.monitor;
|
|
32265
32470
|
const sourceName = monitor.frontmatter.watch.type;
|
|
32266
|
-
const
|
|
32267
|
-
if (!
|
|
32471
|
+
const source6 = this.registry.get(sourceName);
|
|
32472
|
+
if (!source6) {
|
|
32268
32473
|
throw new Error(
|
|
32269
32474
|
`Monitor "${monitor.id}" references unknown source "${sourceName}".`
|
|
32270
32475
|
);
|
|
32271
32476
|
}
|
|
32272
|
-
if (!
|
|
32477
|
+
if (!source6.watch) continue;
|
|
32273
32478
|
if (this.activeWatchers.has(monitor.id)) continue;
|
|
32274
32479
|
const controller = new AbortController();
|
|
32275
32480
|
controllers.set(monitor.id, controller);
|
|
32276
32481
|
this.activeWatchers.add(monitor.id);
|
|
32277
|
-
const watch =
|
|
32482
|
+
const watch = source6.watch.bind(source6);
|
|
32278
32483
|
tasks.push(
|
|
32279
32484
|
this.consumeWatch(
|
|
32280
32485
|
monitor,
|
|
@@ -32668,12 +32873,17 @@ function parseScopeConfig2(config2) {
|
|
|
32668
32873
|
const cd = config2["change-detection"];
|
|
32669
32874
|
const strategy = cd?.strategy;
|
|
32670
32875
|
const changeDetection = strategy === "status-code" || strategy === "json-diff" ? strategy : "text-diff";
|
|
32876
|
+
const collection = parseKeyedCollectionConfig(config2["change-detection"]);
|
|
32877
|
+
if (collection && changeDetection !== "json-diff") {
|
|
32878
|
+
throw new Error("change-detection.collection requires strategy: json-diff");
|
|
32879
|
+
}
|
|
32671
32880
|
return {
|
|
32672
32881
|
url,
|
|
32673
32882
|
auth: config2["auth"],
|
|
32674
32883
|
headers: config2["headers"],
|
|
32675
32884
|
method: typeof config2["method"] === "string" ? config2["method"] : void 0,
|
|
32676
|
-
changeDetection
|
|
32885
|
+
changeDetection,
|
|
32886
|
+
collection
|
|
32677
32887
|
};
|
|
32678
32888
|
}
|
|
32679
32889
|
function resolveAuth(auth) {
|
|
@@ -32693,12 +32903,12 @@ function resolveAuth(auth) {
|
|
|
32693
32903
|
const encoded = Buffer.from(`${username}:${password}`).toString("base64");
|
|
32694
32904
|
return { Authorization: `Basic ${encoded}` };
|
|
32695
32905
|
}
|
|
32696
|
-
function
|
|
32697
|
-
if (Array.isArray(value)) return value.map(
|
|
32906
|
+
function sortKeys2(value) {
|
|
32907
|
+
if (Array.isArray(value)) return value.map(sortKeys2);
|
|
32698
32908
|
if (value !== null && typeof value === "object") {
|
|
32699
32909
|
const sorted = {};
|
|
32700
32910
|
for (const key of Object.keys(value).sort()) {
|
|
32701
|
-
sorted[key] =
|
|
32911
|
+
sorted[key] = sortKeys2(value[key]);
|
|
32702
32912
|
}
|
|
32703
32913
|
return sorted;
|
|
32704
32914
|
}
|
|
@@ -32710,8 +32920,8 @@ function hasChanged(strategy, prev, curr) {
|
|
|
32710
32920
|
return prev.status !== curr.status;
|
|
32711
32921
|
case "json-diff":
|
|
32712
32922
|
try {
|
|
32713
|
-
const prevJson = JSON.stringify(
|
|
32714
|
-
const currJson = JSON.stringify(
|
|
32923
|
+
const prevJson = JSON.stringify(sortKeys2(JSON.parse(prev.body)));
|
|
32924
|
+
const currJson = JSON.stringify(sortKeys2(JSON.parse(curr.body)));
|
|
32715
32925
|
return prevJson !== currJson;
|
|
32716
32926
|
} catch {
|
|
32717
32927
|
return prev.body !== curr.body;
|
|
@@ -32750,7 +32960,37 @@ var scopeSchema2 = {
|
|
|
32750
32960
|
strategy: {
|
|
32751
32961
|
type: "string",
|
|
32752
32962
|
enum: ["json-diff", "text-diff", "status-code"]
|
|
32963
|
+
},
|
|
32964
|
+
// Keyed-collection mode (003 §12). The `collection` block is only valid
|
|
32965
|
+
// under `strategy: json-diff`; the `if/then` below enforces that at
|
|
32966
|
+
// authoring time (BP3).
|
|
32967
|
+
collection: {
|
|
32968
|
+
type: "object",
|
|
32969
|
+
properties: {
|
|
32970
|
+
path: {
|
|
32971
|
+
type: "string",
|
|
32972
|
+
description: 'Dotted $.-path to the array within the parsed JSON (e.g. "$.tasks")'
|
|
32973
|
+
},
|
|
32974
|
+
key: {
|
|
32975
|
+
type: "string",
|
|
32976
|
+
description: "Field on each element used as the per-object identity"
|
|
32977
|
+
},
|
|
32978
|
+
"ignore-paths": {
|
|
32979
|
+
type: "array",
|
|
32980
|
+
items: { type: "string" },
|
|
32981
|
+
description: "Dotted $.-paths (relative to each element) removed before comparison"
|
|
32982
|
+
}
|
|
32983
|
+
},
|
|
32984
|
+
required: ["path", "key"]
|
|
32753
32985
|
}
|
|
32986
|
+
},
|
|
32987
|
+
// BP3: change-detection.collection requires strategy: json-diff. Under any
|
|
32988
|
+
// other strategy (or the defaulted text-diff), presence of `collection` is an
|
|
32989
|
+
// authoring-time error.
|
|
32990
|
+
if: { required: ["collection"] },
|
|
32991
|
+
then: {
|
|
32992
|
+
properties: { strategy: { const: "json-diff" } },
|
|
32993
|
+
required: ["strategy"]
|
|
32754
32994
|
}
|
|
32755
32995
|
}
|
|
32756
32996
|
},
|
|
@@ -32761,15 +33001,30 @@ var source2 = {
|
|
|
32761
33001
|
stateful: true,
|
|
32762
33002
|
scopeSchema: scopeSchema2,
|
|
32763
33003
|
async observe(config2, context = { now: /* @__PURE__ */ new Date() }) {
|
|
32764
|
-
const { url, auth, headers, method, changeDetection } = parseScopeConfig2(config2);
|
|
33004
|
+
const { url, auth, headers, method, changeDetection, collection } = parseScopeConfig2(config2);
|
|
32765
33005
|
const authHeaders = resolveAuth(auth);
|
|
32766
33006
|
const response = await fetch(url, {
|
|
32767
33007
|
method: method ?? "GET",
|
|
32768
33008
|
headers: { ...authHeaders, ...headers }
|
|
32769
33009
|
});
|
|
32770
33010
|
const body = await response.text();
|
|
32771
|
-
const curr = { body, status: response.status };
|
|
32772
33011
|
const prev = context.previousState && typeof context.previousState === "object" && !Array.isArray(context.previousState) ? context.previousState : void 0;
|
|
33012
|
+
if (collection) {
|
|
33013
|
+
const result = diffKeyedCollection(
|
|
33014
|
+
JSON.parse(body),
|
|
33015
|
+
collection,
|
|
33016
|
+
url,
|
|
33017
|
+
prev?.keyedSnapshot,
|
|
33018
|
+
{ payload: { url }, queryScope: { url } }
|
|
33019
|
+
);
|
|
33020
|
+
const curr2 = {
|
|
33021
|
+
body,
|
|
33022
|
+
status: response.status,
|
|
33023
|
+
keyedSnapshot: result.snapshot
|
|
33024
|
+
};
|
|
33025
|
+
return { observations: result.observations, nextState: curr2 };
|
|
33026
|
+
}
|
|
33027
|
+
const curr = { body, status: response.status };
|
|
32773
33028
|
if (prev !== void 0 && hasChanged(changeDetection, prev, curr)) {
|
|
32774
33029
|
return {
|
|
32775
33030
|
observations: [
|
|
@@ -32804,9 +33059,335 @@ var source2 = {
|
|
|
32804
33059
|
};
|
|
32805
33060
|
var index_default2 = source2;
|
|
32806
33061
|
|
|
32807
|
-
// ../../plugins/source-
|
|
33062
|
+
// ../../plugins/source-command-poll/dist/index.js
|
|
32808
33063
|
init_cjs_shims();
|
|
33064
|
+
var import_child_process = require("child_process");
|
|
33065
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
33066
|
+
var SIGKILL_GRACE_MS = 5e3;
|
|
33067
|
+
var STDOUT_CAP_BYTES = 1024 * 1024;
|
|
33068
|
+
var STDERR_TAIL_CHARS = 2e3;
|
|
32809
33069
|
function parseScopeConfig3(config2) {
|
|
33070
|
+
const command = config2["command"];
|
|
33071
|
+
if (!Array.isArray(command) || command.length === 0 || !command.every((c) => typeof c === "string")) {
|
|
33072
|
+
throw new Error(
|
|
33073
|
+
'scope.command must be a non-empty array of strings (argv form, e.g. ["git", "status"])'
|
|
33074
|
+
);
|
|
33075
|
+
}
|
|
33076
|
+
const cd = config2["change-detection"];
|
|
33077
|
+
const rawStrategy = cd?.strategy;
|
|
33078
|
+
const strategy = rawStrategy === "json-diff" || rawStrategy === "exit-code" ? rawStrategy : "text-diff";
|
|
33079
|
+
const collection = parseKeyedCollectionConfig(config2["change-detection"]);
|
|
33080
|
+
if (collection && strategy !== "json-diff") {
|
|
33081
|
+
throw new Error("change-detection.collection requires strategy: json-diff");
|
|
33082
|
+
}
|
|
33083
|
+
const cwd = typeof config2["cwd"] === "string" ? config2["cwd"] : void 0;
|
|
33084
|
+
const rawEnv = config2["env"];
|
|
33085
|
+
const env = rawEnv !== null && typeof rawEnv === "object" && !Array.isArray(rawEnv) && Object.values(rawEnv).every((v) => typeof v === "string") ? rawEnv : void 0;
|
|
33086
|
+
const rawTimeout = config2["timeout"];
|
|
33087
|
+
const timeoutMs = typeof rawTimeout === "string" ? parseDuration(rawTimeout) : DEFAULT_TIMEOUT_MS;
|
|
33088
|
+
const key = config2["key"];
|
|
33089
|
+
const objectKey = typeof key === "string" && key.length > 0 ? key : command.join(" ");
|
|
33090
|
+
return { command, cwd, env, timeoutMs, objectKey, strategy, collection };
|
|
33091
|
+
}
|
|
33092
|
+
async function runCommand(scope) {
|
|
33093
|
+
return new Promise((resolve) => {
|
|
33094
|
+
const [file, ...args] = scope.command;
|
|
33095
|
+
const child = (0, import_child_process.execFile)(
|
|
33096
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
33097
|
+
file,
|
|
33098
|
+
args,
|
|
33099
|
+
{
|
|
33100
|
+
cwd: scope.cwd,
|
|
33101
|
+
// `env` is merged over the inherited daemon environment (003 §11.1).
|
|
33102
|
+
env: scope.env ? { ...process.env, ...scope.env } : process.env,
|
|
33103
|
+
// We enforce the timeout ourselves (SIGTERM→SIGKILL) rather than relying on
|
|
33104
|
+
// execFile's `timeout`, so the grace escalation matches the spec exactly.
|
|
33105
|
+
shell: false,
|
|
33106
|
+
// Bound stdout capture at the 1 MiB cap (003 §11.2). When the child overruns,
|
|
33107
|
+
// execFile kills it and reports ERR_CHILD_PROCESS_STDIO_MAXBUFFER with the
|
|
33108
|
+
// captured-so-far bytes — we treat that as a truncated result, not a failure.
|
|
33109
|
+
maxBuffer: STDOUT_CAP_BYTES,
|
|
33110
|
+
encoding: "buffer"
|
|
33111
|
+
},
|
|
33112
|
+
(error2, stdoutBuf, stderrBuf) => {
|
|
33113
|
+
if (settled) return;
|
|
33114
|
+
settled = true;
|
|
33115
|
+
clearTimeout(killTimer);
|
|
33116
|
+
clearTimeout(graceTimer);
|
|
33117
|
+
const stderrFull = stderrBuf instanceof Buffer ? stderrBuf.toString("utf8") : "";
|
|
33118
|
+
const stderrTail = stderrFull.slice(-STDERR_TAIL_CHARS);
|
|
33119
|
+
const err = error2;
|
|
33120
|
+
const overflowed = err?.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER";
|
|
33121
|
+
if (timedOut) {
|
|
33122
|
+
resolve({
|
|
33123
|
+
kind: "failure",
|
|
33124
|
+
error: `Command timed out after ${String(scope.timeoutMs)}ms`,
|
|
33125
|
+
stderrTail
|
|
33126
|
+
});
|
|
33127
|
+
return;
|
|
33128
|
+
}
|
|
33129
|
+
if (err !== null && typeof err.code === "string" && !overflowed) {
|
|
33130
|
+
resolve({
|
|
33131
|
+
kind: "failure",
|
|
33132
|
+
error: err.message,
|
|
33133
|
+
stderrTail
|
|
33134
|
+
});
|
|
33135
|
+
return;
|
|
33136
|
+
}
|
|
33137
|
+
const buf = Buffer.isBuffer(stdoutBuf) ? stdoutBuf : Buffer.from(String(stdoutBuf), "utf8");
|
|
33138
|
+
const { text: text2, truncated } = capStdout(buf, overflowed);
|
|
33139
|
+
const exitCode = err != null && typeof err.code === "number" ? err.code : 0;
|
|
33140
|
+
resolve({
|
|
33141
|
+
kind: "result",
|
|
33142
|
+
result: { stdout: text2, exitCode, truncated }
|
|
33143
|
+
});
|
|
33144
|
+
}
|
|
33145
|
+
);
|
|
33146
|
+
let settled = false;
|
|
33147
|
+
let timedOut = false;
|
|
33148
|
+
let graceTimer;
|
|
33149
|
+
const killTimer = setTimeout(() => {
|
|
33150
|
+
timedOut = true;
|
|
33151
|
+
child.kill("SIGTERM");
|
|
33152
|
+
graceTimer = setTimeout(() => {
|
|
33153
|
+
child.kill("SIGKILL");
|
|
33154
|
+
}, SIGKILL_GRACE_MS);
|
|
33155
|
+
graceTimer.unref();
|
|
33156
|
+
}, scope.timeoutMs);
|
|
33157
|
+
killTimer.unref();
|
|
33158
|
+
});
|
|
33159
|
+
}
|
|
33160
|
+
function capStdout(stdout, overflowed) {
|
|
33161
|
+
const truncated = overflowed || stdout.length > STDOUT_CAP_BYTES;
|
|
33162
|
+
const slice = stdout.length > STDOUT_CAP_BYTES ? stdout.subarray(0, STDOUT_CAP_BYTES) : stdout;
|
|
33163
|
+
return { text: slice.toString("utf8"), truncated };
|
|
33164
|
+
}
|
|
33165
|
+
function sortKeys3(value) {
|
|
33166
|
+
if (Array.isArray(value)) return value.map(sortKeys3);
|
|
33167
|
+
if (value !== null && typeof value === "object") {
|
|
33168
|
+
const sorted = {};
|
|
33169
|
+
for (const key of Object.keys(value).sort()) {
|
|
33170
|
+
sorted[key] = sortKeys3(value[key]);
|
|
33171
|
+
}
|
|
33172
|
+
return sorted;
|
|
33173
|
+
}
|
|
33174
|
+
return value;
|
|
33175
|
+
}
|
|
33176
|
+
function hasChanged2(strategy, prev, curr) {
|
|
33177
|
+
switch (strategy) {
|
|
33178
|
+
case "exit-code":
|
|
33179
|
+
return prev.exitCode !== curr.exitCode;
|
|
33180
|
+
case "json-diff":
|
|
33181
|
+
try {
|
|
33182
|
+
const prevJson = JSON.stringify(sortKeys3(JSON.parse(prev.stdout)));
|
|
33183
|
+
const currJson = JSON.stringify(sortKeys3(JSON.parse(curr.stdout)));
|
|
33184
|
+
return prevJson !== currJson;
|
|
33185
|
+
} catch {
|
|
33186
|
+
return prev.stdout !== curr.stdout;
|
|
33187
|
+
}
|
|
33188
|
+
case "text-diff":
|
|
33189
|
+
return prev.stdout !== curr.stdout;
|
|
33190
|
+
}
|
|
33191
|
+
}
|
|
33192
|
+
function isCommandState(value) {
|
|
33193
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
33194
|
+
return false;
|
|
33195
|
+
}
|
|
33196
|
+
const v = value;
|
|
33197
|
+
return typeof v["stdout"] === "string" && typeof v["exitCode"] === "number" && typeof v["truncated"] === "boolean" && (v["health"] === "ok" || v["health"] === "failing") && typeof v["baselined"] === "boolean";
|
|
33198
|
+
}
|
|
33199
|
+
function changedObservation(scope, result) {
|
|
33200
|
+
return {
|
|
33201
|
+
title: `Command output changed: ${scope.objectKey}`,
|
|
33202
|
+
summary: `Command output changed: ${scope.objectKey}`,
|
|
33203
|
+
payload: {
|
|
33204
|
+
command: scope.command,
|
|
33205
|
+
exitCode: result.exitCode,
|
|
33206
|
+
strategy: scope.strategy,
|
|
33207
|
+
stdout: result.stdout,
|
|
33208
|
+
truncated: result.truncated
|
|
33209
|
+
},
|
|
33210
|
+
snapshotText: result.stdout,
|
|
33211
|
+
objectKey: scope.objectKey,
|
|
33212
|
+
queryScope: { command: scope.objectKey },
|
|
33213
|
+
snapshot: {
|
|
33214
|
+
command: scope.command,
|
|
33215
|
+
exitCode: result.exitCode,
|
|
33216
|
+
stdoutLength: result.stdout.length,
|
|
33217
|
+
strategy: scope.strategy
|
|
33218
|
+
},
|
|
33219
|
+
changeKind: "modified"
|
|
33220
|
+
};
|
|
33221
|
+
}
|
|
33222
|
+
var scopeSchema3 = {
|
|
33223
|
+
type: "object",
|
|
33224
|
+
properties: {
|
|
33225
|
+
command: {
|
|
33226
|
+
type: "array",
|
|
33227
|
+
items: { type: "string" },
|
|
33228
|
+
minItems: 1,
|
|
33229
|
+
description: "Argv array; command[0] is the executable (resolved via PATH). Spawned directly, never via a shell."
|
|
33230
|
+
},
|
|
33231
|
+
cwd: {
|
|
33232
|
+
type: "string",
|
|
33233
|
+
description: "Working directory for the child process"
|
|
33234
|
+
},
|
|
33235
|
+
env: {
|
|
33236
|
+
type: "object",
|
|
33237
|
+
additionalProperties: { type: "string" },
|
|
33238
|
+
description: "Literal env vars merged over the inherited daemon environment"
|
|
33239
|
+
},
|
|
33240
|
+
timeout: {
|
|
33241
|
+
type: "string",
|
|
33242
|
+
pattern: "^\\d+[smhd]$",
|
|
33243
|
+
description: 'Wall-clock limit (e.g. "30s"). Expiry is an execution failure.'
|
|
33244
|
+
},
|
|
33245
|
+
key: {
|
|
33246
|
+
type: "string",
|
|
33247
|
+
description: "Overrides the observation objectKey (defaults to the joined argv)"
|
|
33248
|
+
},
|
|
33249
|
+
interval: {
|
|
33250
|
+
type: "string",
|
|
33251
|
+
pattern: "^\\d+[smhd]$",
|
|
33252
|
+
description: 'Polling interval (e.g., "5m"). Used by the scheduling engine, not by this plugin directly.'
|
|
33253
|
+
},
|
|
33254
|
+
"change-detection": {
|
|
33255
|
+
type: "object",
|
|
33256
|
+
properties: {
|
|
33257
|
+
strategy: {
|
|
33258
|
+
type: "string",
|
|
33259
|
+
enum: ["text-diff", "json-diff", "exit-code"]
|
|
33260
|
+
},
|
|
33261
|
+
// Keyed-collection mode (003 §12). The `collection` block is only valid
|
|
33262
|
+
// under `strategy: json-diff`; the `if/then` below enforces that at
|
|
33263
|
+
// authoring time (BP3).
|
|
33264
|
+
collection: {
|
|
33265
|
+
type: "object",
|
|
33266
|
+
properties: {
|
|
33267
|
+
path: {
|
|
33268
|
+
type: "string",
|
|
33269
|
+
description: 'Dotted $.-path to the array within the parsed JSON (e.g. "$.tasks")'
|
|
33270
|
+
},
|
|
33271
|
+
key: {
|
|
33272
|
+
type: "string",
|
|
33273
|
+
description: "Field on each element used as the per-object identity"
|
|
33274
|
+
},
|
|
33275
|
+
"ignore-paths": {
|
|
33276
|
+
type: "array",
|
|
33277
|
+
items: { type: "string" },
|
|
33278
|
+
description: "Dotted $.-paths (relative to each element) removed before comparison"
|
|
33279
|
+
}
|
|
33280
|
+
},
|
|
33281
|
+
required: ["path", "key"]
|
|
33282
|
+
}
|
|
33283
|
+
},
|
|
33284
|
+
// BP3: change-detection.collection requires strategy: json-diff. Under any
|
|
33285
|
+
// other strategy (or the defaulted text-diff), presence of `collection` is an
|
|
33286
|
+
// authoring-time error.
|
|
33287
|
+
if: { required: ["collection"] },
|
|
33288
|
+
then: {
|
|
33289
|
+
properties: { strategy: { const: "json-diff" } },
|
|
33290
|
+
required: ["strategy"]
|
|
33291
|
+
}
|
|
33292
|
+
}
|
|
33293
|
+
},
|
|
33294
|
+
required: ["command"]
|
|
33295
|
+
};
|
|
33296
|
+
var source3 = {
|
|
33297
|
+
name: "command-poll",
|
|
33298
|
+
stateful: true,
|
|
33299
|
+
scopeSchema: scopeSchema3,
|
|
33300
|
+
async observe(config2, context = { now: /* @__PURE__ */ new Date() }) {
|
|
33301
|
+
const scope = parseScopeConfig3(config2);
|
|
33302
|
+
const prev = isCommandState(context.previousState) ? context.previousState : void 0;
|
|
33303
|
+
const outcome = await runCommand(scope);
|
|
33304
|
+
if (outcome.kind === "failure") {
|
|
33305
|
+
const wasFailing = prev?.health === "failing";
|
|
33306
|
+
const nextState2 = {
|
|
33307
|
+
stdout: prev?.stdout ?? "",
|
|
33308
|
+
exitCode: prev?.exitCode ?? 0,
|
|
33309
|
+
truncated: prev?.truncated ?? false,
|
|
33310
|
+
health: "failing",
|
|
33311
|
+
baselined: prev?.baselined ?? false,
|
|
33312
|
+
// Carry the keyed baseline forward untouched so recovery diffs against it.
|
|
33313
|
+
...prev?.keyedSnapshot ? { keyedSnapshot: prev.keyedSnapshot } : {}
|
|
33314
|
+
};
|
|
33315
|
+
return {
|
|
33316
|
+
observations: wasFailing ? [] : [failingObservation(scope, outcome)],
|
|
33317
|
+
nextState: nextState2
|
|
33318
|
+
};
|
|
33319
|
+
}
|
|
33320
|
+
const result = outcome.result;
|
|
33321
|
+
const recovered = prev?.health === "failing";
|
|
33322
|
+
const hadBaseline = prev?.baselined ?? false;
|
|
33323
|
+
const observations = [];
|
|
33324
|
+
if (recovered) {
|
|
33325
|
+
observations.push(recoveredObservation(scope));
|
|
33326
|
+
}
|
|
33327
|
+
if (scope.collection) {
|
|
33328
|
+
const result2 = diffKeyedCollection(
|
|
33329
|
+
JSON.parse(result.stdout),
|
|
33330
|
+
scope.collection,
|
|
33331
|
+
scope.objectKey,
|
|
33332
|
+
hadBaseline ? prev?.keyedSnapshot : void 0,
|
|
33333
|
+
{
|
|
33334
|
+
payload: { command: scope.command },
|
|
33335
|
+
queryScope: { command: scope.objectKey }
|
|
33336
|
+
}
|
|
33337
|
+
);
|
|
33338
|
+
observations.push(...result2.observations);
|
|
33339
|
+
const nextState2 = {
|
|
33340
|
+
stdout: result.stdout,
|
|
33341
|
+
exitCode: result.exitCode,
|
|
33342
|
+
truncated: result.truncated,
|
|
33343
|
+
health: "ok",
|
|
33344
|
+
baselined: true,
|
|
33345
|
+
keyedSnapshot: result2.snapshot
|
|
33346
|
+
};
|
|
33347
|
+
return { observations, nextState: nextState2 };
|
|
33348
|
+
}
|
|
33349
|
+
const nextState = {
|
|
33350
|
+
stdout: result.stdout,
|
|
33351
|
+
exitCode: result.exitCode,
|
|
33352
|
+
truncated: result.truncated,
|
|
33353
|
+
health: "ok",
|
|
33354
|
+
baselined: true
|
|
33355
|
+
};
|
|
33356
|
+
if (prev !== void 0 && hadBaseline && hasChanged2(scope.strategy, prev, result)) {
|
|
33357
|
+
observations.push(changedObservation(scope, result));
|
|
33358
|
+
}
|
|
33359
|
+
return { observations, nextState };
|
|
33360
|
+
}
|
|
33361
|
+
};
|
|
33362
|
+
function failingObservation(scope, outcome) {
|
|
33363
|
+
return {
|
|
33364
|
+
title: `Command failing: ${scope.objectKey}`,
|
|
33365
|
+
summary: `Command failing: ${scope.objectKey}`,
|
|
33366
|
+
payload: {
|
|
33367
|
+
command: scope.command,
|
|
33368
|
+
error: outcome.error,
|
|
33369
|
+
stderrTail: outcome.stderrTail
|
|
33370
|
+
},
|
|
33371
|
+
objectKey: scope.objectKey,
|
|
33372
|
+
queryScope: { command: scope.objectKey },
|
|
33373
|
+
changeKind: "modified"
|
|
33374
|
+
};
|
|
33375
|
+
}
|
|
33376
|
+
function recoveredObservation(scope) {
|
|
33377
|
+
return {
|
|
33378
|
+
title: `Command recovered: ${scope.objectKey}`,
|
|
33379
|
+
summary: `Command recovered: ${scope.objectKey}`,
|
|
33380
|
+
payload: { command: scope.command },
|
|
33381
|
+
objectKey: scope.objectKey,
|
|
33382
|
+
queryScope: { command: scope.objectKey },
|
|
33383
|
+
changeKind: "modified"
|
|
33384
|
+
};
|
|
33385
|
+
}
|
|
33386
|
+
var index_default3 = source3;
|
|
33387
|
+
|
|
33388
|
+
// ../../plugins/source-schedule/dist/index.js
|
|
33389
|
+
init_cjs_shims();
|
|
33390
|
+
function parseScopeConfig4(config2) {
|
|
32810
33391
|
const cron = config2["cron"];
|
|
32811
33392
|
if (typeof cron !== "string") {
|
|
32812
33393
|
throw new Error("scope.cron must be a string");
|
|
@@ -32817,7 +33398,7 @@ function parseScopeConfig3(config2) {
|
|
|
32817
33398
|
label: typeof config2["label"] === "string" ? config2["label"] : void 0
|
|
32818
33399
|
};
|
|
32819
33400
|
}
|
|
32820
|
-
var
|
|
33401
|
+
var scopeSchema4 = {
|
|
32821
33402
|
type: "object",
|
|
32822
33403
|
properties: {
|
|
32823
33404
|
cron: {
|
|
@@ -32835,11 +33416,11 @@ var scopeSchema3 = {
|
|
|
32835
33416
|
},
|
|
32836
33417
|
required: ["cron"]
|
|
32837
33418
|
};
|
|
32838
|
-
var
|
|
33419
|
+
var source4 = {
|
|
32839
33420
|
name: "schedule",
|
|
32840
|
-
scopeSchema:
|
|
33421
|
+
scopeSchema: scopeSchema4,
|
|
32841
33422
|
observe(config2, context = { now: /* @__PURE__ */ new Date() }) {
|
|
32842
|
-
const { cron, timezone, label } =
|
|
33423
|
+
const { cron, timezone, label } = parseScopeConfig4(config2);
|
|
32843
33424
|
return Promise.resolve({
|
|
32844
33425
|
observations: [
|
|
32845
33426
|
{
|
|
@@ -32861,12 +33442,12 @@ var source3 = {
|
|
|
32861
33442
|
});
|
|
32862
33443
|
}
|
|
32863
33444
|
};
|
|
32864
|
-
var
|
|
33445
|
+
var index_default4 = source4;
|
|
32865
33446
|
|
|
32866
33447
|
// ../../plugins/source-incoming-changes/dist/index.js
|
|
32867
33448
|
init_cjs_shims();
|
|
32868
|
-
var
|
|
32869
|
-
function
|
|
33449
|
+
var import_child_process2 = require("child_process");
|
|
33450
|
+
function parseScopeConfig5(config2) {
|
|
32870
33451
|
const paths = config2["paths"];
|
|
32871
33452
|
if (!Array.isArray(paths) || !paths.every((p) => typeof p === "string")) {
|
|
32872
33453
|
throw new Error("scope.paths must be an array of strings");
|
|
@@ -32882,7 +33463,7 @@ var MAX_BUFFER = 64 * 1024 * 1024;
|
|
|
32882
33463
|
function tryResolveCurrentRef(cwd, branch) {
|
|
32883
33464
|
const ref = branch ?? "HEAD";
|
|
32884
33465
|
try {
|
|
32885
|
-
const raw = (0,
|
|
33466
|
+
const raw = (0, import_child_process2.execFileSync)("git", ["rev-parse", "--end-of-options", ref], {
|
|
32886
33467
|
cwd,
|
|
32887
33468
|
encoding: "utf-8",
|
|
32888
33469
|
maxBuffer: MAX_BUFFER
|
|
@@ -32907,7 +33488,7 @@ function tryGetDiffEntries(cwd, fromRef, toRef, paths) {
|
|
|
32907
33488
|
];
|
|
32908
33489
|
let output;
|
|
32909
33490
|
try {
|
|
32910
|
-
output = (0,
|
|
33491
|
+
output = (0, import_child_process2.execFileSync)("git", args, {
|
|
32911
33492
|
cwd,
|
|
32912
33493
|
encoding: "buffer",
|
|
32913
33494
|
maxBuffer: MAX_BUFFER
|
|
@@ -32943,7 +33524,7 @@ function tryGetDiffEntries(cwd, fromRef, toRef, paths) {
|
|
|
32943
33524
|
}
|
|
32944
33525
|
function getFileContent(cwd, ref, filePath2) {
|
|
32945
33526
|
try {
|
|
32946
|
-
const content = (0,
|
|
33527
|
+
const content = (0, import_child_process2.execFileSync)("git", ["show", `${ref}:${filePath2}`], {
|
|
32947
33528
|
cwd,
|
|
32948
33529
|
encoding: "buffer",
|
|
32949
33530
|
maxBuffer: MAX_BUFFER
|
|
@@ -32985,7 +33566,7 @@ function buildObservation(entry, fromRef, toRef, cwd) {
|
|
|
32985
33566
|
}
|
|
32986
33567
|
return observation;
|
|
32987
33568
|
}
|
|
32988
|
-
var
|
|
33569
|
+
var scopeSchema5 = {
|
|
32989
33570
|
$schema: "http://json-schema.org/draft-07/schema#",
|
|
32990
33571
|
type: "object",
|
|
32991
33572
|
properties: {
|
|
@@ -33010,13 +33591,13 @@ var scopeSchema4 = {
|
|
|
33010
33591
|
},
|
|
33011
33592
|
required: ["paths"]
|
|
33012
33593
|
};
|
|
33013
|
-
var
|
|
33594
|
+
var source5 = {
|
|
33014
33595
|
name: "incoming-changes",
|
|
33015
33596
|
stateful: true,
|
|
33016
|
-
scopeSchema:
|
|
33597
|
+
scopeSchema: scopeSchema5,
|
|
33017
33598
|
observe(config2, context = { now: /* @__PURE__ */ new Date() }) {
|
|
33018
33599
|
try {
|
|
33019
|
-
const { paths, branch, cwd } =
|
|
33600
|
+
const { paths, branch, cwd } = parseScopeConfig5(config2);
|
|
33020
33601
|
const currentRef = tryResolveCurrentRef(cwd, branch);
|
|
33021
33602
|
if (currentRef === void 0) {
|
|
33022
33603
|
return Promise.resolve({ observations: [] });
|
|
@@ -33056,7 +33637,7 @@ var source4 = {
|
|
|
33056
33637
|
}
|
|
33057
33638
|
}
|
|
33058
33639
|
};
|
|
33059
|
-
var
|
|
33640
|
+
var index_default5 = source5;
|
|
33060
33641
|
|
|
33061
33642
|
// src/sources.ts
|
|
33062
33643
|
function registerCoreSources(registry2) {
|
|
@@ -33064,6 +33645,7 @@ function registerCoreSources(registry2) {
|
|
|
33064
33645
|
registry2.register(index_default2);
|
|
33065
33646
|
registry2.register(index_default3);
|
|
33066
33647
|
registry2.register(index_default4);
|
|
33648
|
+
registry2.register(index_default5);
|
|
33067
33649
|
}
|
|
33068
33650
|
|
|
33069
33651
|
// src/validation.ts
|
|
@@ -33104,6 +33686,16 @@ function requireDirectory(dirPath, json) {
|
|
|
33104
33686
|
}
|
|
33105
33687
|
|
|
33106
33688
|
// src/commands/validate.ts
|
|
33689
|
+
function changeDetectionCollectionError(watchConfig2) {
|
|
33690
|
+
const cd = watchConfig2["change-detection"];
|
|
33691
|
+
if (cd === null || typeof cd !== "object" || Array.isArray(cd))
|
|
33692
|
+
return void 0;
|
|
33693
|
+
const cdObj = cd;
|
|
33694
|
+
if (cdObj["collection"] === void 0) return void 0;
|
|
33695
|
+
const strategy = cdObj["strategy"];
|
|
33696
|
+
if (strategy === "json-diff") return void 0;
|
|
33697
|
+
return "change-detection.collection requires strategy: json-diff";
|
|
33698
|
+
}
|
|
33107
33699
|
var validateCommand = new Command("validate").description("Validate MONITOR.md files in a directory").argument("[path]", "Path to monitors directory", ".claude/monitors").addOption(
|
|
33108
33700
|
new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")
|
|
33109
33701
|
).action(async (monitorPath, options2) => {
|
|
@@ -33114,8 +33706,8 @@ var validateCommand = new Command("validate").description("Validate MONITOR.md f
|
|
|
33114
33706
|
const scopeErrors = [];
|
|
33115
33707
|
const validMonitors = result.monitors.filter((m) => {
|
|
33116
33708
|
const sourceName = m.monitor.frontmatter.watch.type;
|
|
33117
|
-
const
|
|
33118
|
-
if (!
|
|
33709
|
+
const source6 = registry2.get(sourceName);
|
|
33710
|
+
if (!source6) {
|
|
33119
33711
|
scopeErrors.push({
|
|
33120
33712
|
id: m.monitor.id,
|
|
33121
33713
|
errors: [
|
|
@@ -33125,9 +33717,11 @@ var validateCommand = new Command("validate").description("Validate MONITOR.md f
|
|
|
33125
33717
|
return false;
|
|
33126
33718
|
}
|
|
33127
33719
|
const { type: _type, ...watchConfig2 } = m.monitor.frontmatter.watch;
|
|
33128
|
-
const errors = validateScope(watchConfig2,
|
|
33129
|
-
|
|
33130
|
-
|
|
33720
|
+
const errors = validateScope(watchConfig2, source6.scopeSchema);
|
|
33721
|
+
const collectionError = changeDetectionCollectionError(watchConfig2);
|
|
33722
|
+
const allScopeErrors = collectionError ? [collectionError, ...errors.filter((e) => !e.includes("then"))] : errors;
|
|
33723
|
+
if (allScopeErrors.length > 0) {
|
|
33724
|
+
scopeErrors.push({ id: m.monitor.id, errors: allScopeErrors });
|
|
33131
33725
|
return false;
|
|
33132
33726
|
}
|
|
33133
33727
|
return true;
|
|
@@ -33967,24 +34561,24 @@ function createFollowupObservationContext(context) {
|
|
|
33967
34561
|
previousState: context.previousState
|
|
33968
34562
|
};
|
|
33969
34563
|
}
|
|
33970
|
-
async function handleStatefulSource(
|
|
34564
|
+
async function handleStatefulSource(source6, scope, monitorName, json, context) {
|
|
33971
34565
|
if (!json) {
|
|
33972
34566
|
console.log(
|
|
33973
34567
|
`
|
|
33974
|
-
Baseline established. The "${
|
|
34568
|
+
Baseline established. The "${source6.name}" source requires a prior baseline before it can detect changes.`
|
|
33975
34569
|
);
|
|
33976
34570
|
console.log(
|
|
33977
34571
|
"Running a second observation to demonstrate change detection...\n"
|
|
33978
34572
|
);
|
|
33979
34573
|
}
|
|
33980
34574
|
await (0, import_promises4.setTimeout)(100);
|
|
33981
|
-
const secondResult = await
|
|
34575
|
+
const secondResult = await source6.observe(
|
|
33982
34576
|
scope,
|
|
33983
34577
|
createFollowupObservationContext(context)
|
|
33984
34578
|
);
|
|
33985
34579
|
const secondObservations = secondResult.observations;
|
|
33986
34580
|
if (json) {
|
|
33987
|
-
printJsonResult(monitorName,
|
|
34581
|
+
printJsonResult(monitorName, source6.name, true, secondObservations);
|
|
33988
34582
|
return;
|
|
33989
34583
|
}
|
|
33990
34584
|
if (secondObservations.length > 0) {
|
|
@@ -33994,7 +34588,7 @@ Baseline established. The "${source5.name}" source requires a prior baseline bef
|
|
|
33994
34588
|
console.log(
|
|
33995
34589
|
"No changes detected since baseline. This is expected \u2014 both observations happened within the same command invocation."
|
|
33996
34590
|
);
|
|
33997
|
-
const messages = SOURCE_TEST_MESSAGES[
|
|
34591
|
+
const messages = SOURCE_TEST_MESSAGES[source6.name] ?? DEFAULT_TEST_MESSAGES;
|
|
33998
34592
|
for (const msg of messages) {
|
|
33999
34593
|
console.log(`
|
|
34000
34594
|
${msg}`);
|
|
@@ -34023,8 +34617,8 @@ monitorTestCommand.command("test").description("Dry-run a monitor observation so
|
|
|
34023
34617
|
}
|
|
34024
34618
|
const registry2 = new SourceRegistry();
|
|
34025
34619
|
registerCoreSources(registry2);
|
|
34026
|
-
const
|
|
34027
|
-
if (!
|
|
34620
|
+
const source6 = registry2.get(result.monitor.frontmatter.watch.type);
|
|
34621
|
+
if (!source6) {
|
|
34028
34622
|
reportError(
|
|
34029
34623
|
`Unknown source: "${result.monitor.frontmatter.watch.type}". Available: ${registry2.names().join(", ")}`,
|
|
34030
34624
|
json
|
|
@@ -34035,27 +34629,27 @@ monitorTestCommand.command("test").description("Dry-run a monitor observation so
|
|
|
34035
34629
|
const { type: _type, ...monitorWatchConfig } = result.monitor.frontmatter.watch;
|
|
34036
34630
|
if (!json) {
|
|
34037
34631
|
console.log(
|
|
34038
|
-
`Testing monitor "${monitorName}" (source: ${
|
|
34632
|
+
`Testing monitor "${monitorName}" (source: ${source6.name})...`
|
|
34039
34633
|
);
|
|
34040
34634
|
}
|
|
34041
34635
|
try {
|
|
34042
34636
|
let context = { now: /* @__PURE__ */ new Date() };
|
|
34043
|
-
const firstResult = await
|
|
34637
|
+
const firstResult = await source6.observe(monitorWatchConfig, context);
|
|
34044
34638
|
const observations = firstResult.observations;
|
|
34045
34639
|
context = {
|
|
34046
34640
|
now: /* @__PURE__ */ new Date(),
|
|
34047
34641
|
previousState: firstResult.nextState
|
|
34048
34642
|
};
|
|
34049
|
-
if (observations.length === 0 &&
|
|
34643
|
+
if (observations.length === 0 && source6.stateful) {
|
|
34050
34644
|
await handleStatefulSource(
|
|
34051
|
-
|
|
34645
|
+
source6,
|
|
34052
34646
|
monitorWatchConfig,
|
|
34053
34647
|
monitorName,
|
|
34054
34648
|
json,
|
|
34055
34649
|
context
|
|
34056
34650
|
);
|
|
34057
34651
|
} else if (json) {
|
|
34058
|
-
printJsonResult(monitorName,
|
|
34652
|
+
printJsonResult(monitorName, source6.name, false, observations);
|
|
34059
34653
|
} else if (observations.length === 0) {
|
|
34060
34654
|
console.log("No observations produced.");
|
|
34061
34655
|
} else {
|
|
@@ -34114,11 +34708,11 @@ sourceCommand.command("list").description("List installed observation sources").
|
|
|
34114
34708
|
registerCoreSources(registry2);
|
|
34115
34709
|
const sources = registry2.list();
|
|
34116
34710
|
if (options2.format === "json") {
|
|
34117
|
-
const output = sources.map((
|
|
34118
|
-
const requiredFields =
|
|
34119
|
-
const properties =
|
|
34711
|
+
const output = sources.map((source6) => {
|
|
34712
|
+
const requiredFields = source6.scopeSchema["required"] ?? [];
|
|
34713
|
+
const properties = source6.scopeSchema["properties"] ?? {};
|
|
34120
34714
|
return {
|
|
34121
|
-
name:
|
|
34715
|
+
name: source6.name,
|
|
34122
34716
|
scopeFields: Object.keys(properties),
|
|
34123
34717
|
required: requiredFields
|
|
34124
34718
|
};
|
|
@@ -34131,10 +34725,10 @@ sourceCommand.command("list").description("List installed observation sources").
|
|
|
34131
34725
|
return;
|
|
34132
34726
|
}
|
|
34133
34727
|
console.log("Installed sources:\n");
|
|
34134
|
-
for (const
|
|
34135
|
-
const requiredFields =
|
|
34136
|
-
const properties =
|
|
34137
|
-
console.log(` ${
|
|
34728
|
+
for (const source6 of sources) {
|
|
34729
|
+
const requiredFields = source6.scopeSchema["required"] ?? [];
|
|
34730
|
+
const properties = source6.scopeSchema["properties"] ?? {};
|
|
34731
|
+
console.log(` ${source6.name}`);
|
|
34138
34732
|
console.log(` Scope fields: ${Object.keys(properties).join(", ")}`);
|
|
34139
34733
|
console.log(` Required: ${requiredFields.join(", ") || "(none)"}`);
|
|
34140
34734
|
console.log("");
|
|
@@ -34569,6 +35163,96 @@ function spawnDetachedDaemon(options2) {
|
|
|
34569
35163
|
child.unref();
|
|
34570
35164
|
}
|
|
34571
35165
|
|
|
35166
|
+
// src/hook-payload.ts
|
|
35167
|
+
init_cjs_shims();
|
|
35168
|
+
async function readHookPayload() {
|
|
35169
|
+
const stdin = process.stdin;
|
|
35170
|
+
if (stdin.isTTY) return {};
|
|
35171
|
+
const raw = await new Promise((resolve) => {
|
|
35172
|
+
let data = "";
|
|
35173
|
+
let settled = false;
|
|
35174
|
+
const finish = () => {
|
|
35175
|
+
if (settled) return;
|
|
35176
|
+
settled = true;
|
|
35177
|
+
resolve(data);
|
|
35178
|
+
};
|
|
35179
|
+
stdin.setEncoding("utf8");
|
|
35180
|
+
stdin.on("data", (chunk) => {
|
|
35181
|
+
data += chunk;
|
|
35182
|
+
});
|
|
35183
|
+
stdin.on("end", finish);
|
|
35184
|
+
stdin.on("error", finish);
|
|
35185
|
+
});
|
|
35186
|
+
const trimmed = raw.trim();
|
|
35187
|
+
if (trimmed === "") return {};
|
|
35188
|
+
try {
|
|
35189
|
+
const parsed = JSON.parse(trimmed);
|
|
35190
|
+
if (typeof parsed !== "object" || parsed === null) return {};
|
|
35191
|
+
const record2 = parsed;
|
|
35192
|
+
const pickString = (key) => {
|
|
35193
|
+
const value = record2[key];
|
|
35194
|
+
return typeof value === "string" ? value : void 0;
|
|
35195
|
+
};
|
|
35196
|
+
const payload = {};
|
|
35197
|
+
const sessionId = pickString("session_id");
|
|
35198
|
+
if (sessionId !== void 0) payload.session_id = sessionId;
|
|
35199
|
+
const eventName = pickString("hook_event_name");
|
|
35200
|
+
if (eventName !== void 0) payload.hook_event_name = eventName;
|
|
35201
|
+
const cwd = pickString("cwd");
|
|
35202
|
+
if (cwd !== void 0) payload.cwd = cwd;
|
|
35203
|
+
return payload;
|
|
35204
|
+
} catch {
|
|
35205
|
+
return {};
|
|
35206
|
+
}
|
|
35207
|
+
}
|
|
35208
|
+
|
|
35209
|
+
// src/hook-deliver-render.ts
|
|
35210
|
+
init_cjs_shims();
|
|
35211
|
+
var MAX_ADDITIONAL_CONTEXT = 4e3;
|
|
35212
|
+
var TRUNCATION_MARKER = "\n\n[truncated \u2014 more monitor updates are pending; run `agentmonitors events list --unread` to see the rest]";
|
|
35213
|
+
function sanitize(value) {
|
|
35214
|
+
let out = "";
|
|
35215
|
+
for (const ch of value) {
|
|
35216
|
+
const code = ch.codePointAt(0) ?? 0;
|
|
35217
|
+
const isControl = code < 32 && ch !== "\n" && ch !== " " || code >= 127 && code <= 159;
|
|
35218
|
+
if (!isControl) out += ch;
|
|
35219
|
+
}
|
|
35220
|
+
return out;
|
|
35221
|
+
}
|
|
35222
|
+
function truncateForCap(value, cap) {
|
|
35223
|
+
if (value.length <= cap) return value;
|
|
35224
|
+
const budget = Math.max(0, cap - TRUNCATION_MARKER.length);
|
|
35225
|
+
let out = "";
|
|
35226
|
+
for (const ch of value) {
|
|
35227
|
+
if (out.length + ch.length > budget) break;
|
|
35228
|
+
out += ch;
|
|
35229
|
+
}
|
|
35230
|
+
return out + TRUNCATION_MARKER;
|
|
35231
|
+
}
|
|
35232
|
+
function renderHookDelivery(claim, hookEventName) {
|
|
35233
|
+
if (!claim || claim.events.length === 0) return null;
|
|
35234
|
+
const leadLine = "AgentMon: monitored changes are pending \u2014 consider handling them before continuing.";
|
|
35235
|
+
const blocks = claim.events.map((e) => {
|
|
35236
|
+
const id = sanitize(e.monitorId);
|
|
35237
|
+
const urgency = sanitize(e.urgency);
|
|
35238
|
+
const title = sanitize(e.title);
|
|
35239
|
+
const body = sanitize(e.body);
|
|
35240
|
+
return `### ${id} (${urgency})
|
|
35241
|
+
${title}
|
|
35242
|
+
|
|
35243
|
+
${body}`;
|
|
35244
|
+
});
|
|
35245
|
+
const full = [leadLine, "", ...blocks].join("\n");
|
|
35246
|
+
const additionalContext = truncateForCap(full, MAX_ADDITIONAL_CONTEXT);
|
|
35247
|
+
return {
|
|
35248
|
+
continue: true,
|
|
35249
|
+
hookSpecificOutput: {
|
|
35250
|
+
hookEventName,
|
|
35251
|
+
additionalContext
|
|
35252
|
+
}
|
|
35253
|
+
};
|
|
35254
|
+
}
|
|
35255
|
+
|
|
34572
35256
|
// src/commands/session.ts
|
|
34573
35257
|
var sessionCommand = new Command("session").description(
|
|
34574
35258
|
"Manage agent sessions tracked by AgentMon"
|
|
@@ -34644,9 +35328,10 @@ sessionCommand.command("list").description("List known agent sessions").option("
|
|
|
34644
35328
|
sessionCommand.command("start").description(
|
|
34645
35329
|
"Lazy-boot the project daemon (if needed) and register this session"
|
|
34646
35330
|
).action(async () => {
|
|
34647
|
-
const
|
|
34648
|
-
const hostSessionId =
|
|
35331
|
+
const payload = await readHookPayload();
|
|
35332
|
+
const hostSessionId = payload.session_id;
|
|
34649
35333
|
if (!hostSessionId) return;
|
|
35334
|
+
const workspacePath = payload.cwd ?? process.env["CLAUDE_PROJECT_DIR"] ?? process.cwd();
|
|
34650
35335
|
const state = readLocalState(workspacePath);
|
|
34651
35336
|
if (!state.enabled) return;
|
|
34652
35337
|
const paths = workspacePaths(workspacePath);
|
|
@@ -34677,22 +35362,32 @@ sessionCommand.command("start").description(
|
|
|
34677
35362
|
}
|
|
34678
35363
|
writeLocalState(workspacePath, { ...state, socket, db });
|
|
34679
35364
|
try {
|
|
34680
|
-
await openSessionClient(
|
|
35365
|
+
const opened = await openSessionClient(
|
|
34681
35366
|
claudeCodeAdapter.createSessionInput({
|
|
34682
35367
|
hostSessionId,
|
|
34683
35368
|
workspacePath
|
|
34684
35369
|
}),
|
|
34685
35370
|
socket
|
|
34686
35371
|
);
|
|
35372
|
+
const claim = await claimDeliveryClient(
|
|
35373
|
+
opened.id,
|
|
35374
|
+
"post-compact",
|
|
35375
|
+
socket
|
|
35376
|
+
);
|
|
35377
|
+
const delivery = renderHookDelivery(claim, "SessionStart");
|
|
35378
|
+
if (delivery !== null) {
|
|
35379
|
+
process.stdout.write(JSON.stringify(delivery));
|
|
35380
|
+
}
|
|
34687
35381
|
} catch (error2) {
|
|
34688
35382
|
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
34689
35383
|
reportError(message, false);
|
|
34690
35384
|
}
|
|
34691
35385
|
});
|
|
34692
35386
|
sessionCommand.command("end").description("Deregister this session (lets the idle daemon reap itself)").action(async () => {
|
|
34693
|
-
const
|
|
34694
|
-
const hostSessionId =
|
|
35387
|
+
const payload = await readHookPayload();
|
|
35388
|
+
const hostSessionId = payload.session_id;
|
|
34695
35389
|
if (!hostSessionId) return;
|
|
35390
|
+
const workspacePath = payload.cwd ?? process.env["CLAUDE_PROJECT_DIR"] ?? process.cwd();
|
|
34696
35391
|
const state = readLocalState(workspacePath);
|
|
34697
35392
|
if (!state.enabled || !state.socket) return;
|
|
34698
35393
|
const socket = resolveSocketPath(state.socket);
|
|
@@ -34777,55 +35472,6 @@ eventsCommand.command("ack").description("Acknowledge one or more events for a s
|
|
|
34777
35472
|
|
|
34778
35473
|
// src/commands/hook.ts
|
|
34779
35474
|
init_cjs_shims();
|
|
34780
|
-
|
|
34781
|
-
// src/hook-deliver-render.ts
|
|
34782
|
-
init_cjs_shims();
|
|
34783
|
-
var MAX_ADDITIONAL_CONTEXT = 4e3;
|
|
34784
|
-
var TRUNCATION_MARKER = "\n\n[truncated \u2014 more monitor updates are pending; run `agentmonitors events list --unread` to see the rest]";
|
|
34785
|
-
function sanitize(value) {
|
|
34786
|
-
let out = "";
|
|
34787
|
-
for (const ch of value) {
|
|
34788
|
-
const code = ch.codePointAt(0) ?? 0;
|
|
34789
|
-
const isControl = code < 32 && ch !== "\n" && ch !== " " || code >= 127 && code <= 159;
|
|
34790
|
-
if (!isControl) out += ch;
|
|
34791
|
-
}
|
|
34792
|
-
return out;
|
|
34793
|
-
}
|
|
34794
|
-
function truncateForCap(value, cap) {
|
|
34795
|
-
if (value.length <= cap) return value;
|
|
34796
|
-
const budget = Math.max(0, cap - TRUNCATION_MARKER.length);
|
|
34797
|
-
let out = "";
|
|
34798
|
-
for (const ch of value) {
|
|
34799
|
-
if (out.length + ch.length > budget) break;
|
|
34800
|
-
out += ch;
|
|
34801
|
-
}
|
|
34802
|
-
return out + TRUNCATION_MARKER;
|
|
34803
|
-
}
|
|
34804
|
-
function renderHookDelivery(claim, hookEventName) {
|
|
34805
|
-
if (!claim || claim.events.length === 0) return null;
|
|
34806
|
-
const leadLine = "AgentMon: monitored changes are pending \u2014 consider handling them before continuing.";
|
|
34807
|
-
const blocks = claim.events.map((e) => {
|
|
34808
|
-
const id = sanitize(e.monitorId);
|
|
34809
|
-
const urgency = sanitize(e.urgency);
|
|
34810
|
-
const title = sanitize(e.title);
|
|
34811
|
-
const body = sanitize(e.body);
|
|
34812
|
-
return `### ${id} (${urgency})
|
|
34813
|
-
${title}
|
|
34814
|
-
|
|
34815
|
-
${body}`;
|
|
34816
|
-
});
|
|
34817
|
-
const full = [leadLine, "", ...blocks].join("\n");
|
|
34818
|
-
const additionalContext = truncateForCap(full, MAX_ADDITIONAL_CONTEXT);
|
|
34819
|
-
return {
|
|
34820
|
-
continue: true,
|
|
34821
|
-
hookSpecificOutput: {
|
|
34822
|
-
hookEventName,
|
|
34823
|
-
additionalContext
|
|
34824
|
-
}
|
|
34825
|
-
};
|
|
34826
|
-
}
|
|
34827
|
-
|
|
34828
|
-
// src/commands/hook.ts
|
|
34829
35475
|
var hookCommand = new Command("hook").description(
|
|
34830
35476
|
"Claim hook-delivery payloads from the runtime"
|
|
34831
35477
|
);
|
|
@@ -34867,36 +35513,6 @@ function lifecycleForEvent(hookEventName) {
|
|
|
34867
35513
|
return void 0;
|
|
34868
35514
|
}
|
|
34869
35515
|
}
|
|
34870
|
-
async function readHookPayload() {
|
|
34871
|
-
const stdin = process.stdin;
|
|
34872
|
-
if (stdin.isTTY) return {};
|
|
34873
|
-
const raw = await new Promise((resolve) => {
|
|
34874
|
-
let data = "";
|
|
34875
|
-
let settled = false;
|
|
34876
|
-
const finish = () => {
|
|
34877
|
-
if (settled) return;
|
|
34878
|
-
settled = true;
|
|
34879
|
-
resolve(data);
|
|
34880
|
-
};
|
|
34881
|
-
stdin.setEncoding("utf8");
|
|
34882
|
-
stdin.on("data", (chunk) => {
|
|
34883
|
-
data += chunk;
|
|
34884
|
-
});
|
|
34885
|
-
stdin.on("end", finish);
|
|
34886
|
-
stdin.on("error", finish);
|
|
34887
|
-
});
|
|
34888
|
-
const trimmed = raw.trim();
|
|
34889
|
-
if (trimmed === "") return {};
|
|
34890
|
-
try {
|
|
34891
|
-
const parsed = JSON.parse(trimmed);
|
|
34892
|
-
if (typeof parsed === "object" && parsed !== null) {
|
|
34893
|
-
return parsed;
|
|
34894
|
-
}
|
|
34895
|
-
return {};
|
|
34896
|
-
} catch {
|
|
34897
|
-
return {};
|
|
34898
|
-
}
|
|
34899
|
-
}
|
|
34900
35516
|
hookCommand.command("deliver").description(
|
|
34901
35517
|
"Claim pending events and emit advisory hook context at a turn boundary"
|
|
34902
35518
|
).addOption(
|
|
@@ -35114,10 +35730,10 @@ function cached(getter) {
|
|
|
35114
35730
|
function nullish(input) {
|
|
35115
35731
|
return input === null || input === void 0;
|
|
35116
35732
|
}
|
|
35117
|
-
function cleanRegex(
|
|
35118
|
-
const start =
|
|
35119
|
-
const end =
|
|
35120
|
-
return
|
|
35733
|
+
function cleanRegex(source6) {
|
|
35734
|
+
const start = source6.startsWith("^") ? 1 : 0;
|
|
35735
|
+
const end = source6.endsWith("$") ? source6.length - 1 : source6.length;
|
|
35736
|
+
return source6.slice(start, end);
|
|
35121
35737
|
}
|
|
35122
35738
|
function floatSafeRemainder2(val, step) {
|
|
35123
35739
|
const valDecCount = (val.toString().split(".")[1] || "").length;
|