@agentmonitors/cli 0.5.0 → 0.6.1

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 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.15__jiti@2.7.0_postcss@8.5.8_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js
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.9.0/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.15__jiti@2.7.0_postcss@8.5.8_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js"() {
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.9.0/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();
@@ -30757,16 +30757,60 @@ var notifySchema = external_exports.discriminatedUnion("strategy", [
30757
30757
  debounceNotifySchema,
30758
30758
  throttleNotifySchema
30759
30759
  ]);
30760
+ var urgencyLevels = ["low", "normal", "high"];
30761
+ var urgencyRank = {
30762
+ low: 0,
30763
+ normal: 1,
30764
+ high: 2
30765
+ };
30766
+ var urgencyBandSchema = external_exports.string().transform((raw, ctx) => {
30767
+ const text2 = raw.trim();
30768
+ const parts = text2.includes("..") ? text2.split("..").map((part) => part.trim()) : [text2, text2];
30769
+ if (parts.length !== 2) {
30770
+ ctx.addIssue({
30771
+ code: external_exports.ZodIssueCode.custom,
30772
+ message: 'urgency must be a single level (e.g. "normal") or a range "lo..hi" (e.g. "normal..high")'
30773
+ });
30774
+ return external_exports.NEVER;
30775
+ }
30776
+ const [loRaw, hiRaw] = parts;
30777
+ const isLevel = (value) => value !== void 0 && urgencyLevels.includes(value);
30778
+ if (!isLevel(loRaw) || !isLevel(hiRaw)) {
30779
+ ctx.addIssue({
30780
+ code: external_exports.ZodIssueCode.custom,
30781
+ message: `urgency bounds must each be one of ${urgencyLevels.map((level) => `"${level}"`).join(", ")}`
30782
+ });
30783
+ return external_exports.NEVER;
30784
+ }
30785
+ if (urgencyRank[loRaw] > urgencyRank[hiRaw]) {
30786
+ ctx.addIssue({
30787
+ code: external_exports.ZodIssueCode.custom,
30788
+ message: `urgency range "${loRaw}..${hiRaw}" is inverted \u2014 the low bound must not exceed the high bound`
30789
+ });
30790
+ return external_exports.NEVER;
30791
+ }
30792
+ return { lo: loRaw, hi: hiRaw };
30793
+ });
30760
30794
  var watchSchema = external_exports.object({
30761
30795
  type: external_exports.string().min(1).regex(/^[a-z][a-z0-9-]*$/, "watch.type must be kebab-case")
30762
30796
  }).catchall(external_exports.unknown());
30763
30797
  var monitorFrontmatterSchema = external_exports.object({
30764
30798
  name: external_exports.string().min(1, "Monitor name must be non-empty when present").optional(),
30765
30799
  watch: watchSchema,
30766
- urgency: external_exports.enum(["low", "normal", "high"]),
30800
+ urgency: urgencyBandSchema,
30767
30801
  notify: notifySchema.optional(),
30768
30802
  tags: external_exports.array(external_exports.string()).optional()
30769
- });
30803
+ }).transform(({ urgency, ...rest }) => ({
30804
+ ...rest,
30805
+ // Flatten the parsed band: `urgency` is the band's low bound — the base /
30806
+ // default effective urgency used when no source `salience` is present (kept
30807
+ // under this key for backward compatibility with every existing consumer) —
30808
+ // and `urgencyMax` is the band's high bound (equal to `urgency` for a
30809
+ // scalar). Source salience may escalate the effective urgency between these
30810
+ // two, clamping outside the band. See 002 §4.1 / 003 §2.3.
30811
+ urgency: urgency.lo,
30812
+ urgencyMax: urgency.hi
30813
+ }));
30770
30814
  function validateScope(scope, scopeSchema6) {
30771
30815
  const validator = new Validator(scopeSchema6, "7", false);
30772
30816
  const result = validator.validate(scope);
@@ -31298,7 +31342,18 @@ function generateMonitorSchema(sources) {
31298
31342
  type: { type: "string", enum: sourceNames }
31299
31343
  }
31300
31344
  },
31301
- urgency: { type: "string", enum: ["low", "normal", "high"] },
31345
+ // A bare level (`normal`) or an authored band `lo..hi` (`normal..high`).
31346
+ // This editor-hint schema enforces only the *shape* of each bound; the
31347
+ // authoritative parser (`monitorFrontmatterSchema`) additionally rejects
31348
+ // an inverted range (`lo > hi`). See 001 §3.2.
31349
+ //
31350
+ // Leading/trailing whitespace is allowed (`\s*` anchors at both ends)
31351
+ // to mirror the Zod parser, which calls `.trim()` on the raw value
31352
+ // before validating bounds. Whitespace around `..` was already allowed.
31353
+ urgency: {
31354
+ type: "string",
31355
+ pattern: "^\\s*(low|normal|high)(\\s*\\.\\.\\s*(low|normal|high))?\\s*$"
31356
+ },
31302
31357
  notify: {
31303
31358
  type: "object",
31304
31359
  required: ["strategy"],
@@ -32118,14 +32173,46 @@ function explainVerdict(stages) {
32118
32173
  reason: stage?.reason ?? "Monitor delivered successfully."
32119
32174
  };
32120
32175
  }
32176
+ var URGENCY_BY_RANK = ["low", "normal", "high"];
32177
+ var URGENCY_RANK = {
32178
+ low: 0,
32179
+ normal: 1,
32180
+ high: 2
32181
+ };
32182
+ function effectiveObservationUrgency(monitor, observation) {
32183
+ const lo = monitor.frontmatter.urgency;
32184
+ const hi = monitor.frontmatter.urgencyMax ?? lo;
32185
+ const desired = observation.salience ?? lo;
32186
+ const rank = Math.min(
32187
+ Math.max(URGENCY_RANK[desired], URGENCY_RANK[lo]),
32188
+ URGENCY_RANK[hi]
32189
+ );
32190
+ return URGENCY_BY_RANK[rank] ?? lo;
32191
+ }
32121
32192
  function serializeObservation(monitor, observation, observedAt) {
32122
- return { monitor, observation, observedAt };
32193
+ return {
32194
+ monitor,
32195
+ observation,
32196
+ observedAt,
32197
+ effectiveUrgency: effectiveObservationUrgency(monitor, observation)
32198
+ };
32123
32199
  }
32124
32200
  function hydrateStoredObservationEnvelope(envelope) {
32125
32201
  return {
32126
32202
  monitor: envelope.monitor,
32127
32203
  observation: envelope.observation,
32128
- observedAt: envelope.observedAt instanceof Date ? envelope.observedAt : new Date(envelope.observedAt)
32204
+ observedAt: envelope.observedAt instanceof Date ? envelope.observedAt : new Date(envelope.observedAt),
32205
+ // Restart-safety / upgrade backfill (002 §3, issue #109): a debounce batch
32206
+ // persisted BEFORE the range-urgency upgrade will have no `effectiveUrgency`
32207
+ // field on its envelopes. Recompute it from the envelope's `monitor` +
32208
+ // `observation` so the materialized event row is never written with
32209
+ // `undefined` urgency. `effectiveObservationUrgency` degrades cleanly when
32210
+ // the hydrated monitor snapshot itself lacks `urgencyMax` (old monitor).
32211
+ // The cast to `Urgency | undefined` is intentional: at compile time
32212
+ // `StoredObservationEnvelope.effectiveUrgency` is always `Urgency`, but
32213
+ // pre-upgrade deserialized JSON may lack the field entirely.
32214
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
32215
+ effectiveUrgency: envelope.effectiveUrgency ?? effectiveObservationUrgency(envelope.monitor, envelope.observation)
32129
32216
  };
32130
32217
  }
32131
32218
  var WEEKDAY_INDEX = {
@@ -32690,6 +32777,7 @@ var AgentMonitorRuntime = class {
32690
32777
  const now = /* @__PURE__ */ new Date();
32691
32778
  const emittedEventIds = [];
32692
32779
  const evaluated = [];
32780
+ const erroredObservations = [];
32693
32781
  for (const parsed of result.monitors) {
32694
32782
  const monitor = parsed.monitor;
32695
32783
  const sourceName = monitor.frontmatter.watch.type;
@@ -32714,13 +32802,15 @@ var AgentMonitorRuntime = class {
32714
32802
  }
32715
32803
  );
32716
32804
  } catch (observeError) {
32805
+ const message = observeError instanceof Error ? observeError.message : String(observeError);
32806
+ erroredObservations.push({ monitorId: monitor.id, message });
32717
32807
  try {
32718
32808
  this.store.recordObservationHistory({
32719
32809
  monitorId: monitor.id,
32720
32810
  sourceName,
32721
32811
  result: "errored",
32722
32812
  observationData: {
32723
- error: observeError instanceof Error ? observeError.message : String(observeError)
32813
+ error: message
32724
32814
  }
32725
32815
  });
32726
32816
  } catch {
@@ -32736,13 +32826,15 @@ var AgentMonitorRuntime = class {
32736
32826
  })
32737
32827
  );
32738
32828
  } catch (ingestError) {
32829
+ const message = ingestError instanceof Error ? ingestError.message : String(ingestError);
32830
+ erroredObservations.push({ monitorId: monitor.id, message });
32739
32831
  try {
32740
32832
  this.store.recordObservationHistory({
32741
32833
  monitorId: monitor.id,
32742
32834
  sourceName,
32743
32835
  result: "errored",
32744
32836
  observationData: {
32745
- error: ingestError instanceof Error ? ingestError.message : String(ingestError)
32837
+ error: message
32746
32838
  }
32747
32839
  });
32748
32840
  } catch {
@@ -32750,7 +32842,11 @@ var AgentMonitorRuntime = class {
32750
32842
  }
32751
32843
  }
32752
32844
  this.refreshWorkspaceSessions(workspacePath);
32753
- return { evaluatedMonitors: evaluated, emittedEventIds };
32845
+ return {
32846
+ evaluatedMonitors: evaluated,
32847
+ emittedEventIds,
32848
+ erroredObservations
32849
+ };
32754
32850
  }
32755
32851
  /**
32756
32852
  * Funnel a batch of observations through notify dispatch, persist the updated
@@ -32802,7 +32898,8 @@ var AgentMonitorRuntime = class {
32802
32898
  sourceName: emitted.monitor.frontmatter.watch.type,
32803
32899
  observation: emitted.observation,
32804
32900
  observedAt: emitted.observedAt,
32805
- workspacePath: options2.workspacePath
32901
+ workspacePath: options2.workspacePath,
32902
+ effectiveUrgency: emitted.effectiveUrgency
32806
32903
  });
32807
32904
  emittedEventIds.push(event.id);
32808
32905
  } catch (materializeError) {
@@ -33002,11 +33099,22 @@ var AgentMonitorRuntime = class {
33002
33099
  }
33003
33100
  }
33004
33101
  for (const observation of observations) {
33102
+ const envelope = serializeObservation(monitor, observation, observedAt);
33005
33103
  const notify = defaultNotifyConfigForUrgency(
33006
- monitor.frontmatter.urgency,
33104
+ envelope.effectiveUrgency,
33007
33105
  monitor.frontmatter.notify
33008
33106
  );
33009
- const envelope = serializeObservation(monitor, observation, observedAt);
33107
+ const isEscalated = URGENCY_RANK[envelope.effectiveUrgency] > URGENCY_RANK[monitor.frontmatter.urgency];
33108
+ if (isEscalated && nextState.pendingDebounce) {
33109
+ emitted.push(
33110
+ ...nextState.pendingDebounce.observations.map(
33111
+ hydrateStoredObservationEnvelope
33112
+ ),
33113
+ envelope
33114
+ );
33115
+ delete nextState.pendingDebounce;
33116
+ continue;
33117
+ }
33010
33118
  if (!notify) {
33011
33119
  emitted.push(envelope);
33012
33120
  continue;
@@ -33060,7 +33168,7 @@ var AgentMonitorRuntime = class {
33060
33168
  workspacePath: input.workspacePath ?? null,
33061
33169
  monitorId: input.monitor.id,
33062
33170
  sourceName: input.sourceName,
33063
- urgency: input.monitor.frontmatter.urgency,
33171
+ urgency: input.effectiveUrgency,
33064
33172
  title: input.observation.title,
33065
33173
  body: input.observation.body ?? input.monitor.instructions,
33066
33174
  summary: input.observation.summary ?? input.observation.body ?? input.observation.title,
@@ -35525,6 +35633,11 @@ function shouldReap(s) {
35525
35633
 
35526
35634
  // src/commands/daemon.ts
35527
35635
  var DEFAULT_REAP_AFTER_MS = 5 * 60 * 1e3;
35636
+ function appendErroredLines(summary, errored) {
35637
+ if (errored.length === 0) return summary;
35638
+ const lines = errored.map((e) => ` ${e.monitorId}: ${e.message}`);
35639
+ return [summary, ...lines].join("\n");
35640
+ }
35528
35641
  async function runLoop(monitorsDir, workspacePath, pollMs, socketPath, reapAfterMs) {
35529
35642
  const runtime = createRuntime();
35530
35643
  let stopping = false;
@@ -35570,10 +35683,12 @@ async function runLoop(monitorsDir, workspacePath, pollMs, socketPath, reapAfter
35570
35683
  while (!isStoppingRequested()) {
35571
35684
  try {
35572
35685
  const result = await runtime.tick(monitorsDir, workspacePath);
35573
- if (result.emittedEventIds.length > 0) {
35574
- console.log(
35575
- `Emitted ${String(result.emittedEventIds.length)} event(s) from ${String(result.evaluatedMonitors.length)} monitor(s).`
35686
+ if (result.emittedEventIds.length > 0 || result.erroredObservations.length > 0) {
35687
+ const summary = appendErroredLines(
35688
+ `Emitted ${String(result.emittedEventIds.length)} event(s) from ${String(result.evaluatedMonitors.length)} monitor(s)${result.erroredObservations.length > 0 ? `, ${String(result.erroredObservations.length)} errored:` : "."}`,
35689
+ result.erroredObservations
35576
35690
  );
35691
+ console.log(summary);
35577
35692
  }
35578
35693
  } catch (error2) {
35579
35694
  const message = error2 instanceof Error ? error2.message : String(error2);
@@ -35639,9 +35754,9 @@ daemonCommand.command("once").description("Run one runtime observation cycle").a
35639
35754
  console.log(JSON.stringify(result, null, 2));
35640
35755
  return;
35641
35756
  }
35642
- console.log(
35643
- `Evaluated ${String(result.evaluatedMonitors.length)} monitor(s), emitted ${String(result.emittedEventIds.length)} event(s).`
35644
- );
35757
+ const erroredCount = result.erroredObservations.length;
35758
+ const base = `Evaluated ${String(result.evaluatedMonitors.length)} monitor(s), emitted ${String(result.emittedEventIds.length)} event(s)${erroredCount > 0 ? `, ${String(erroredCount)} errored:` : "."}`;
35759
+ console.log(appendErroredLines(base, result.erroredObservations));
35645
35760
  } catch (error2) {
35646
35761
  const message = error2 instanceof Error ? error2.message : String(error2);
35647
35762
  reportError(message, options2.format === "json");