@wrongstack/plugins 0.310.1 → 0.313.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.js CHANGED
@@ -12795,7 +12795,10 @@ var WebhookNotificationChannel = class {
12795
12795
  #headers;
12796
12796
  #timeoutMs;
12797
12797
  #maxFailures;
12798
+ #resetMs;
12798
12799
  #circuit;
12800
+ /** Timestamp (ms) when the circuit last opened — for time-based half-open. */
12801
+ #openedAt = 0;
12799
12802
  /** Total deliveries attempted (across all resets). */
12800
12803
  #totalAttempted = 0;
12801
12804
  /** Total successful deliveries. */
@@ -12809,6 +12812,7 @@ var WebhookNotificationChannel = class {
12809
12812
  this.#headers = opts.headers ?? {};
12810
12813
  this.#timeoutMs = opts.timeoutMs ?? 5e3;
12811
12814
  this.#maxFailures = opts.maxConsecutiveFailures ?? 5;
12815
+ this.#resetMs = opts.circuitResetMs ?? 3e4;
12812
12816
  this.#circuit = freshCircuit();
12813
12817
  }
12814
12818
  // -----------------------------------------------------------------------
@@ -12816,7 +12820,8 @@ var WebhookNotificationChannel = class {
12816
12820
  // -----------------------------------------------------------------------
12817
12821
  async deliver(msg) {
12818
12822
  const deliveredAt = (/* @__PURE__ */ new Date()).toISOString();
12819
- if (this.#circuit.open && this.#maxFailures > 0) {
12823
+ const inCooldown = this.#resetMs > 0 && Date.now() - this.#openedAt < this.#resetMs;
12824
+ if (this.#circuit.open && this.#maxFailures > 0 && inCooldown) {
12820
12825
  this.#totalSuppressed += 1;
12821
12826
  return {
12822
12827
  ok: false,
@@ -12858,6 +12863,7 @@ var WebhookNotificationChannel = class {
12858
12863
  this.#circuit.consecutiveFailures += 1;
12859
12864
  if (this.#maxFailures > 0 && this.#circuit.consecutiveFailures >= this.#maxFailures) {
12860
12865
  this.#circuit.open = true;
12866
+ this.#openedAt = Date.now();
12861
12867
  }
12862
12868
  return {
12863
12869
  ok: false,
@@ -27,6 +27,12 @@ export interface WebhookChannelOptions {
27
27
  * failures. Default 5. Set to 0 to disable the circuit breaker.
28
28
  */
29
29
  readonly maxConsecutiveFailures?: number | undefined;
30
+ /**
31
+ * How long (ms) the circuit breaker stays open before allowing a retry
32
+ * probe. Default 30_000. Set to 0 to disable automatic recovery (keep
33
+ * the breaker latched until `resetCircuit()` is called).
34
+ */
35
+ readonly circuitResetMs?: number | undefined;
30
36
  }
31
37
  export declare class WebhookNotificationChannel implements NotificationChannel {
32
38
  #private;
@@ -31,7 +31,10 @@ var WebhookNotificationChannel = class {
31
31
  #headers;
32
32
  #timeoutMs;
33
33
  #maxFailures;
34
+ #resetMs;
34
35
  #circuit;
36
+ /** Timestamp (ms) when the circuit last opened — for time-based half-open. */
37
+ #openedAt = 0;
35
38
  /** Total deliveries attempted (across all resets). */
36
39
  #totalAttempted = 0;
37
40
  /** Total successful deliveries. */
@@ -45,6 +48,7 @@ var WebhookNotificationChannel = class {
45
48
  this.#headers = opts.headers ?? {};
46
49
  this.#timeoutMs = opts.timeoutMs ?? 5e3;
47
50
  this.#maxFailures = opts.maxConsecutiveFailures ?? 5;
51
+ this.#resetMs = opts.circuitResetMs ?? 3e4;
48
52
  this.#circuit = freshCircuit();
49
53
  }
50
54
  // -----------------------------------------------------------------------
@@ -52,7 +56,8 @@ var WebhookNotificationChannel = class {
52
56
  // -----------------------------------------------------------------------
53
57
  async deliver(msg) {
54
58
  const deliveredAt = (/* @__PURE__ */ new Date()).toISOString();
55
- if (this.#circuit.open && this.#maxFailures > 0) {
59
+ const inCooldown = this.#resetMs > 0 && Date.now() - this.#openedAt < this.#resetMs;
60
+ if (this.#circuit.open && this.#maxFailures > 0 && inCooldown) {
56
61
  this.#totalSuppressed += 1;
57
62
  return {
58
63
  ok: false,
@@ -94,6 +99,7 @@ var WebhookNotificationChannel = class {
94
99
  this.#circuit.consecutiveFailures += 1;
95
100
  if (this.#maxFailures > 0 && this.#circuit.consecutiveFailures >= this.#maxFailures) {
96
101
  this.#circuit.open = true;
102
+ this.#openedAt = Date.now();
97
103
  }
98
104
  return {
99
105
  ok: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/plugins",
3
- "version": "0.310.1",
3
+ "version": "0.313.1",
4
4
  "description": "Official WrongStack collection of focused plugins for code quality, security, observability, planning, and agent coordination",
5
5
  "license": "MIT",
6
6
  "author": "ECOSTACK TECHNOLOGY OÜ",
@@ -303,10 +303,10 @@
303
303
  "vitest": "^4.1.11"
304
304
  },
305
305
  "dependencies": {
306
- "@wrongstack/core": "0.310.1",
307
- "@wrongstack/plugin-sdk": "0.310.1",
308
- "@wrongstack/primitives": "0.310.1",
309
- "@wrongstack/tools": "0.310.1"
306
+ "@wrongstack/core": "0.313.1",
307
+ "@wrongstack/plugin-sdk": "0.313.1",
308
+ "@wrongstack/primitives": "0.313.1",
309
+ "@wrongstack/tools": "0.313.1"
310
310
  },
311
311
  "scripts": {
312
312
  "build": "node ../../scripts/build-package.mjs",