@aiassesstech/nole 0.4.14 → 0.5.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.
Files changed (39) hide show
  1. package/agent/AGENTS.md +4 -0
  2. package/agent/SOUL.md +9 -0
  3. package/agent/decisions.md +20 -0
  4. package/dist/plugin.d.ts.map +1 -1
  5. package/dist/plugin.js +51 -1
  6. package/dist/plugin.js.map +1 -1
  7. package/dist/resilience/circuit-breaker.d.ts +46 -0
  8. package/dist/resilience/circuit-breaker.d.ts.map +1 -0
  9. package/dist/resilience/circuit-breaker.js +102 -0
  10. package/dist/resilience/circuit-breaker.js.map +1 -0
  11. package/dist/resilience/index.d.ts +8 -0
  12. package/dist/resilience/index.d.ts.map +1 -0
  13. package/dist/resilience/index.js +8 -0
  14. package/dist/resilience/index.js.map +1 -0
  15. package/dist/resilience/post-queue.d.ts +41 -0
  16. package/dist/resilience/post-queue.d.ts.map +1 -0
  17. package/dist/resilience/post-queue.js +106 -0
  18. package/dist/resilience/post-queue.js.map +1 -0
  19. package/dist/resilience/queue-drain.d.ts +35 -0
  20. package/dist/resilience/queue-drain.d.ts.map +1 -0
  21. package/dist/resilience/queue-drain.js +92 -0
  22. package/dist/resilience/queue-drain.js.map +1 -0
  23. package/dist/resilience/resilient-client.d.ts +54 -0
  24. package/dist/resilience/resilient-client.d.ts.map +1 -0
  25. package/dist/resilience/resilient-client.js +120 -0
  26. package/dist/resilience/resilient-client.js.map +1 -0
  27. package/dist/resilience/retry.d.ts +22 -0
  28. package/dist/resilience/retry.d.ts.map +1 -0
  29. package/dist/resilience/retry.js +68 -0
  30. package/dist/resilience/retry.js.map +1 -0
  31. package/dist/resilience/service-configs.d.ts +14 -0
  32. package/dist/resilience/service-configs.d.ts.map +1 -0
  33. package/dist/resilience/service-configs.js +45 -0
  34. package/dist/resilience/service-configs.js.map +1 -0
  35. package/dist/resilience/service-registry.d.ts +39 -0
  36. package/dist/resilience/service-registry.d.ts.map +1 -0
  37. package/dist/resilience/service-registry.js +82 -0
  38. package/dist/resilience/service-registry.js.map +1 -0
  39. package/package.json +1 -1
@@ -0,0 +1,120 @@
1
+ /**
2
+ * ResilientClient — Unified wrapper combining circuit breaker + retry.
3
+ *
4
+ * Replaces raw fetch() calls in Nole's service clients with
5
+ * protection against transient failures and cascading outages.
6
+ *
7
+ * @see SPEC-nole-operational-resilience.md §5
8
+ */
9
+ import { CircuitBreaker } from './circuit-breaker.js';
10
+ import { DEFAULT_RETRY_CONFIG, calculateDelay, isRetryable, extractRetryAfter, sleep, } from './retry.js';
11
+ export class CircuitOpenError extends Error {
12
+ service;
13
+ state;
14
+ cooldownRemainingMs;
15
+ constructor(service, cooldownRemainingMs) {
16
+ super(`Circuit breaker OPEN for ${service} — next probe in ${Math.ceil(cooldownRemainingMs / 1000)}s`);
17
+ this.name = 'CircuitOpenError';
18
+ this.service = service;
19
+ this.state = 'open';
20
+ this.cooldownRemainingMs = cooldownRemainingMs;
21
+ }
22
+ }
23
+ export class ResilientClient {
24
+ config;
25
+ breaker;
26
+ retryConfig;
27
+ timeoutMs;
28
+ logger;
29
+ fetchFn;
30
+ constructor(config) {
31
+ this.config = config;
32
+ this.breaker = new CircuitBreaker(config.circuitBreaker);
33
+ this.retryConfig = config.retry ?? DEFAULT_RETRY_CONFIG;
34
+ this.timeoutMs = config.timeoutMs;
35
+ this.fetchFn = config.fetchFn ?? globalThis.fetch;
36
+ this.logger = config.logger ?? {
37
+ debug: () => { },
38
+ warn: () => { },
39
+ error: () => { },
40
+ };
41
+ }
42
+ async execute(url, init) {
43
+ const startTime = Date.now();
44
+ const service = this.config.circuitBreaker.name;
45
+ if (!this.breaker.canExecute()) {
46
+ const status = this.breaker.getStatus();
47
+ const remaining = status.currentCooldownMs - (Date.now() - status.lastStateChange);
48
+ throw new CircuitOpenError(service, Math.max(0, remaining));
49
+ }
50
+ let lastError = null;
51
+ const maxAttempts = 1 + this.retryConfig.maxRetries;
52
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
53
+ try {
54
+ this.logger.debug(`${service}: attempt ${attempt + 1}/${maxAttempts}`, { url });
55
+ const controller = new AbortController();
56
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
57
+ const resp = await this.fetchFn(url, {
58
+ ...init,
59
+ signal: controller.signal,
60
+ });
61
+ clearTimeout(timeout);
62
+ if (this.breaker.isFailureStatus(resp.status)) {
63
+ const body = await resp.text().catch(() => '');
64
+ this.breaker.recordFailure(`HTTP ${resp.status}: ${body.slice(0, 200)}`);
65
+ if (isRetryable(resp.status, this.retryConfig) && attempt < maxAttempts - 1) {
66
+ const delay = resp.status === 429
67
+ ? (extractRetryAfter(resp.headers) ?? calculateDelay(attempt, this.retryConfig))
68
+ : calculateDelay(attempt, this.retryConfig);
69
+ this.logger.warn(`${service}: HTTP ${resp.status}, retrying in ${delay}ms`, {
70
+ attempt: attempt + 1, url,
71
+ });
72
+ await sleep(delay);
73
+ continue;
74
+ }
75
+ throw new Error(`${service}: HTTP ${resp.status} after ${attempt + 1} attempts`);
76
+ }
77
+ if (resp.status >= 200 && resp.status < 500) {
78
+ this.breaker.recordSuccess();
79
+ }
80
+ if (resp.status === 429 && attempt < maxAttempts - 1) {
81
+ const delay = extractRetryAfter(resp.headers) ?? calculateDelay(attempt, this.retryConfig);
82
+ this.logger.warn(`${service}: rate limited (429), waiting ${delay}ms`, { url });
83
+ await sleep(delay);
84
+ continue;
85
+ }
86
+ const body = await resp.text();
87
+ return {
88
+ status: resp.status,
89
+ headers: resp.headers,
90
+ body,
91
+ attempts: attempt + 1,
92
+ totalDurationMs: Date.now() - startTime,
93
+ };
94
+ }
95
+ catch (err) {
96
+ if (err instanceof CircuitOpenError)
97
+ throw err;
98
+ const error = err instanceof Error ? err : new Error(String(err));
99
+ lastError = error;
100
+ this.breaker.recordFailure(error.message.slice(0, 200));
101
+ if (isRetryable(error, this.retryConfig) && attempt < maxAttempts - 1) {
102
+ const delay = calculateDelay(attempt, this.retryConfig);
103
+ this.logger.warn(`${service}: network error, retrying in ${delay}ms`, {
104
+ attempt: attempt + 1, error: error.message.slice(0, 100),
105
+ });
106
+ await sleep(delay);
107
+ continue;
108
+ }
109
+ }
110
+ }
111
+ throw lastError ?? new Error(`${service}: all ${maxAttempts} attempts failed`);
112
+ }
113
+ getCircuitStatus() {
114
+ return this.breaker.getStatus();
115
+ }
116
+ get serviceName() {
117
+ return this.config.circuitBreaker.name;
118
+ }
119
+ }
120
+ //# sourceMappingURL=resilient-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resilient-client.js","sourceRoot":"","sources":["../../src/resilience/resilient-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Retry logic — exponential backoff with jitter, Retry-After support.
3
+ *
4
+ * Retry is separate from the circuit breaker: the breaker decides whether
5
+ * to attempt at all, retry decides how many times to reattempt on failure.
6
+ *
7
+ * @see SPEC-nole-operational-resilience.md §4
8
+ */
9
+ export interface RetryConfig {
10
+ maxRetries: number;
11
+ baseDelayMs: number;
12
+ maxDelayMs: number;
13
+ jitterFactor: number;
14
+ retryableStatusCodes: number[];
15
+ retryOnNetworkError: boolean;
16
+ }
17
+ export declare const DEFAULT_RETRY_CONFIG: RetryConfig;
18
+ export declare function calculateDelay(attempt: number, config: RetryConfig): number;
19
+ export declare function isRetryable(statusOrError: number | Error, config: RetryConfig): boolean;
20
+ export declare function extractRetryAfter(headers: Headers | Record<string, string>): number | null;
21
+ export declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
22
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/resilience/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED,eAAO,MAAM,oBAAoB,EAAE,WAOlC,CAAC;AAEF,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAK3E;AAED,wBAAgB,WAAW,CACzB,aAAa,EAAE,MAAM,GAAG,KAAK,EAC7B,MAAM,EAAE,WAAW,GAClB,OAAO,CAkBT;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAkB1F;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAYrE"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Retry logic — exponential backoff with jitter, Retry-After support.
3
+ *
4
+ * Retry is separate from the circuit breaker: the breaker decides whether
5
+ * to attempt at all, retry decides how many times to reattempt on failure.
6
+ *
7
+ * @see SPEC-nole-operational-resilience.md §4
8
+ */
9
+ export const DEFAULT_RETRY_CONFIG = {
10
+ maxRetries: 3,
11
+ baseDelayMs: 1_000,
12
+ maxDelayMs: 30_000,
13
+ jitterFactor: 0.25,
14
+ retryableStatusCodes: [429, 500, 502, 503, 504],
15
+ retryOnNetworkError: true,
16
+ };
17
+ export function calculateDelay(attempt, config) {
18
+ const exponentialDelay = config.baseDelayMs * Math.pow(2, attempt);
19
+ const cappedDelay = Math.min(exponentialDelay, config.maxDelayMs);
20
+ const jitter = cappedDelay * config.jitterFactor * (Math.random() * 2 - 1);
21
+ return Math.max(0, Math.round(cappedDelay + jitter));
22
+ }
23
+ export function isRetryable(statusOrError, config) {
24
+ if (typeof statusOrError === 'number') {
25
+ return config.retryableStatusCodes.includes(statusOrError);
26
+ }
27
+ if (!config.retryOnNetworkError)
28
+ return false;
29
+ const msg = statusOrError.message.toLowerCase();
30
+ return (msg.includes('econnrefused') ||
31
+ msg.includes('econnreset') ||
32
+ msg.includes('etimedout') ||
33
+ msg.includes('enotfound') ||
34
+ msg.includes('epipe') ||
35
+ msg.includes('socket hang up') ||
36
+ msg.includes('fetch failed') ||
37
+ msg.includes('abort'));
38
+ }
39
+ export function extractRetryAfter(headers) {
40
+ const value = headers instanceof Headers
41
+ ? headers.get('retry-after')
42
+ : headers['retry-after'];
43
+ if (!value)
44
+ return null;
45
+ const seconds = parseInt(value, 10);
46
+ if (!isNaN(seconds)) {
47
+ return seconds * 1000;
48
+ }
49
+ const date = new Date(value);
50
+ if (!isNaN(date.getTime())) {
51
+ return Math.max(0, date.getTime() - Date.now());
52
+ }
53
+ return null;
54
+ }
55
+ export function sleep(ms, signal) {
56
+ return new Promise((resolve, reject) => {
57
+ if (signal?.aborted) {
58
+ reject(new Error('Aborted'));
59
+ return;
60
+ }
61
+ const timer = setTimeout(resolve, ms);
62
+ signal?.addEventListener('abort', () => {
63
+ clearTimeout(timer);
64
+ reject(new Error('Aborted'));
65
+ }, { once: true });
66
+ });
67
+ }
68
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/resilience/retry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Per-service circuit breaker configurations.
3
+ *
4
+ * Each service has different failure characteristics — these configs
5
+ * are tuned to match expected behavior and recovery patterns.
6
+ *
7
+ * @see SPEC-nole-operational-resilience.md §3.3
8
+ */
9
+ import type { CircuitBreakerConfig } from './circuit-breaker.js';
10
+ export declare const PLATFORM_API_BREAKER: Omit<CircuitBreakerConfig, 'onStateChange'>;
11
+ export declare const X_API_BREAKER: Omit<CircuitBreakerConfig, 'onStateChange'>;
12
+ export declare const MOLTBOOK_API_BREAKER: Omit<CircuitBreakerConfig, 'onStateChange'>;
13
+ export declare const BLOCKCHAIN_BREAKER: Omit<CircuitBreakerConfig, 'onStateChange'>;
14
+ //# sourceMappingURL=service-configs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-configs.d.ts","sourceRoot":"","sources":["../../src/resilience/service-configs.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEjE,eAAO,MAAM,oBAAoB,EAAE,IAAI,CAAC,oBAAoB,EAAE,eAAe,CAQ5E,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,IAAI,CAAC,oBAAoB,EAAE,eAAe,CAQrE,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,IAAI,CAAC,oBAAoB,EAAE,eAAe,CAQ5E,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,IAAI,CAAC,oBAAoB,EAAE,eAAe,CAQ1E,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Per-service circuit breaker configurations.
3
+ *
4
+ * Each service has different failure characteristics — these configs
5
+ * are tuned to match expected behavior and recovery patterns.
6
+ *
7
+ * @see SPEC-nole-operational-resilience.md §3.3
8
+ */
9
+ export const PLATFORM_API_BREAKER = {
10
+ name: 'platform-api',
11
+ failureThreshold: 3,
12
+ failureWindowMs: 60_000,
13
+ cooldownMs: 30_000,
14
+ maxCooldownMs: 5 * 60_000,
15
+ cooldownMultiplier: 2,
16
+ failureStatusCodes: [500, 502, 503, 504],
17
+ };
18
+ export const X_API_BREAKER = {
19
+ name: 'x-twitter',
20
+ failureThreshold: 5,
21
+ failureWindowMs: 5 * 60_000,
22
+ cooldownMs: 2 * 60_000,
23
+ maxCooldownMs: 30 * 60_000,
24
+ cooldownMultiplier: 2,
25
+ failureStatusCodes: [500, 502, 503, 504],
26
+ };
27
+ export const MOLTBOOK_API_BREAKER = {
28
+ name: 'moltbook',
29
+ failureThreshold: 3,
30
+ failureWindowMs: 2 * 60_000,
31
+ cooldownMs: 60_000,
32
+ maxCooldownMs: 10 * 60_000,
33
+ cooldownMultiplier: 2,
34
+ failureStatusCodes: [500, 502, 503, 504],
35
+ };
36
+ export const BLOCKCHAIN_BREAKER = {
37
+ name: 'blockchain',
38
+ failureThreshold: 5,
39
+ failureWindowMs: 10 * 60_000,
40
+ cooldownMs: 5 * 60_000,
41
+ maxCooldownMs: 60 * 60_000,
42
+ cooldownMultiplier: 2,
43
+ failureStatusCodes: [500, 502, 503, 504],
44
+ };
45
+ //# sourceMappingURL=service-configs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-configs.js","sourceRoot":"","sources":["../../src/resilience/service-configs.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,CAAC,MAAM,oBAAoB,GAAgD;IAC/E,IAAI,EAAE,cAAc;IACpB,gBAAgB,EAAE,CAAC;IACnB,eAAe,EAAE,MAAM;IACvB,UAAU,EAAE,MAAM;IAClB,aAAa,EAAE,CAAC,GAAG,MAAM;IACzB,kBAAkB,EAAE,CAAC;IACrB,kBAAkB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;CACzC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAgD;IACxE,IAAI,EAAE,WAAW;IACjB,gBAAgB,EAAE,CAAC;IACnB,eAAe,EAAE,CAAC,GAAG,MAAM;IAC3B,UAAU,EAAE,CAAC,GAAG,MAAM;IACtB,aAAa,EAAE,EAAE,GAAG,MAAM;IAC1B,kBAAkB,EAAE,CAAC;IACrB,kBAAkB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;CACzC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAgD;IAC/E,IAAI,EAAE,UAAU;IAChB,gBAAgB,EAAE,CAAC;IACnB,eAAe,EAAE,CAAC,GAAG,MAAM;IAC3B,UAAU,EAAE,MAAM;IAClB,aAAa,EAAE,EAAE,GAAG,MAAM;IAC1B,kBAAkB,EAAE,CAAC;IACrB,kBAAkB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;CACzC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAgD;IAC7E,IAAI,EAAE,YAAY;IAClB,gBAAgB,EAAE,CAAC;IACnB,eAAe,EAAE,EAAE,GAAG,MAAM;IAC5B,UAAU,EAAE,CAAC,GAAG,MAAM;IACtB,aAAa,EAAE,EAAE,GAAG,MAAM;IAC1B,kBAAkB,EAAE,CAAC;IACrB,kBAAkB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;CACzC,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Service Registry — Degraded-mode management.
3
+ *
4
+ * Tracks which external services are healthy, degraded, or down.
5
+ * Nole's business logic queries this to adapt behavior.
6
+ * Writes a status file that Mighty Mark can read (read-only contract).
7
+ *
8
+ * @see SPEC-nole-operational-resilience.md §6
9
+ */
10
+ import type { ResilientClient } from './resilient-client.js';
11
+ export type ServiceHealth = 'healthy' | 'degraded' | 'down';
12
+ export interface ServiceStatus {
13
+ name: string;
14
+ health: ServiceHealth;
15
+ circuitState: string;
16
+ failureCount: number;
17
+ lastSuccessfulCall: number | null;
18
+ lastFailedCall: number | null;
19
+ recentErrors: string[];
20
+ }
21
+ export interface RegistrySnapshot {
22
+ timestamp: number;
23
+ overallHealth: ServiceHealth;
24
+ services: Record<string, ServiceStatus>;
25
+ }
26
+ export declare class ServiceRegistry {
27
+ private clients;
28
+ private lastSuccess;
29
+ private lastFailure;
30
+ register(client: ResilientClient): void;
31
+ recordSuccess(serviceName: string): void;
32
+ recordFailure(serviceName: string): void;
33
+ getHealth(serviceName: string): ServiceHealth;
34
+ getOverallHealth(): ServiceHealth;
35
+ getSnapshot(): RegistrySnapshot;
36
+ writeStatusFile(dataDir: string): Promise<void>;
37
+ isAvailable(serviceName: string): boolean;
38
+ }
39
+ //# sourceMappingURL=service-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-registry.d.ts","sourceRoot":"","sources":["../../src/resilience/service-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,aAAa,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CACzC;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAAsC;IACrD,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,WAAW,CAA6B;IAEhD,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAIvC,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAIxC,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAIxC,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa;IAc7C,gBAAgB,IAAI,aAAa;IAUjC,WAAW,IAAI,gBAAgB;IAuBzB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAerD,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;CAG1C"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Service Registry — Degraded-mode management.
3
+ *
4
+ * Tracks which external services are healthy, degraded, or down.
5
+ * Nole's business logic queries this to adapt behavior.
6
+ * Writes a status file that Mighty Mark can read (read-only contract).
7
+ *
8
+ * @see SPEC-nole-operational-resilience.md §6
9
+ */
10
+ import fs from 'node:fs';
11
+ import path from 'node:path';
12
+ export class ServiceRegistry {
13
+ clients = new Map();
14
+ lastSuccess = new Map();
15
+ lastFailure = new Map();
16
+ register(client) {
17
+ this.clients.set(client.serviceName, client);
18
+ }
19
+ recordSuccess(serviceName) {
20
+ this.lastSuccess.set(serviceName, Date.now());
21
+ }
22
+ recordFailure(serviceName) {
23
+ this.lastFailure.set(serviceName, Date.now());
24
+ }
25
+ getHealth(serviceName) {
26
+ const client = this.clients.get(serviceName);
27
+ if (!client)
28
+ return 'down';
29
+ const status = client.getCircuitStatus();
30
+ switch (status.state) {
31
+ case 'open': return 'down';
32
+ case 'half-open': return 'degraded';
33
+ case 'closed':
34
+ return status.failureCount > 0 ? 'degraded' : 'healthy';
35
+ }
36
+ }
37
+ getOverallHealth() {
38
+ let worst = 'healthy';
39
+ for (const [name] of this.clients) {
40
+ const health = this.getHealth(name);
41
+ if (health === 'down')
42
+ return 'down';
43
+ if (health === 'degraded')
44
+ worst = 'degraded';
45
+ }
46
+ return worst;
47
+ }
48
+ getSnapshot() {
49
+ const services = {};
50
+ for (const [name, client] of this.clients) {
51
+ const circuit = client.getCircuitStatus();
52
+ services[name] = {
53
+ name,
54
+ health: this.getHealth(name),
55
+ circuitState: circuit.state,
56
+ failureCount: circuit.failureCount,
57
+ lastSuccessfulCall: this.lastSuccess.get(name) ?? null,
58
+ lastFailedCall: this.lastFailure.get(name) ?? null,
59
+ recentErrors: circuit.recentFailures,
60
+ };
61
+ }
62
+ return {
63
+ timestamp: Date.now(),
64
+ overallHealth: this.getOverallHealth(),
65
+ services,
66
+ };
67
+ }
68
+ async writeStatusFile(dataDir) {
69
+ const snapshot = this.getSnapshot();
70
+ const statusPath = path.join(dataDir, 'service-health.json');
71
+ try {
72
+ await fs.promises.writeFile(statusPath, JSON.stringify(snapshot, null, 2), 'utf-8');
73
+ }
74
+ catch {
75
+ // Non-fatal — status file is informational
76
+ }
77
+ }
78
+ isAvailable(serviceName) {
79
+ return this.getHealth(serviceName) !== 'down';
80
+ }
81
+ }
82
+ //# sourceMappingURL=service-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-registry.js","sourceRoot":"","sources":["../../src/resilience/service-registry.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiassesstech/nole",
3
- "version": "0.4.14",
3
+ "version": "0.5.0",
4
4
  "description": "Nole — Autonomous Trust Evangelist & Intelligence Operative for AI. Economic agency, social presence, and autonomous decision-making within a governed hierarchy.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",