@ornexus/neocortex 3.8.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 (156) hide show
  1. package/LICENSE +56 -0
  2. package/README.md +661 -0
  3. package/install.js +453 -0
  4. package/install.ps1 +1478 -0
  5. package/install.sh +1409 -0
  6. package/package.json +93 -0
  7. package/packages/client/dist/adapters/adapter-registry.d.ts +62 -0
  8. package/packages/client/dist/adapters/adapter-registry.d.ts.map +1 -0
  9. package/packages/client/dist/adapters/adapter-registry.js +107 -0
  10. package/packages/client/dist/adapters/adapter-registry.js.map +1 -0
  11. package/packages/client/dist/adapters/antigravity-adapter.d.ts +19 -0
  12. package/packages/client/dist/adapters/antigravity-adapter.d.ts.map +1 -0
  13. package/packages/client/dist/adapters/antigravity-adapter.js +78 -0
  14. package/packages/client/dist/adapters/antigravity-adapter.js.map +1 -0
  15. package/packages/client/dist/adapters/claude-code-adapter.d.ts +20 -0
  16. package/packages/client/dist/adapters/claude-code-adapter.d.ts.map +1 -0
  17. package/packages/client/dist/adapters/claude-code-adapter.js +80 -0
  18. package/packages/client/dist/adapters/claude-code-adapter.js.map +1 -0
  19. package/packages/client/dist/adapters/codex-adapter.d.ts +20 -0
  20. package/packages/client/dist/adapters/codex-adapter.d.ts.map +1 -0
  21. package/packages/client/dist/adapters/codex-adapter.js +81 -0
  22. package/packages/client/dist/adapters/codex-adapter.js.map +1 -0
  23. package/packages/client/dist/adapters/cursor-adapter.d.ts +20 -0
  24. package/packages/client/dist/adapters/cursor-adapter.d.ts.map +1 -0
  25. package/packages/client/dist/adapters/cursor-adapter.js +116 -0
  26. package/packages/client/dist/adapters/cursor-adapter.js.map +1 -0
  27. package/packages/client/dist/adapters/gemini-adapter.d.ts +19 -0
  28. package/packages/client/dist/adapters/gemini-adapter.d.ts.map +1 -0
  29. package/packages/client/dist/adapters/gemini-adapter.js +72 -0
  30. package/packages/client/dist/adapters/gemini-adapter.js.map +1 -0
  31. package/packages/client/dist/adapters/index.d.ts +20 -0
  32. package/packages/client/dist/adapters/index.d.ts.map +1 -0
  33. package/packages/client/dist/adapters/index.js +22 -0
  34. package/packages/client/dist/adapters/index.js.map +1 -0
  35. package/packages/client/dist/adapters/platform-detector.d.ts +47 -0
  36. package/packages/client/dist/adapters/platform-detector.d.ts.map +1 -0
  37. package/packages/client/dist/adapters/platform-detector.js +107 -0
  38. package/packages/client/dist/adapters/platform-detector.js.map +1 -0
  39. package/packages/client/dist/adapters/target-adapter.d.ts +71 -0
  40. package/packages/client/dist/adapters/target-adapter.d.ts.map +1 -0
  41. package/packages/client/dist/adapters/target-adapter.js +13 -0
  42. package/packages/client/dist/adapters/target-adapter.js.map +1 -0
  43. package/packages/client/dist/adapters/vscode-adapter.d.ts +20 -0
  44. package/packages/client/dist/adapters/vscode-adapter.d.ts.map +1 -0
  45. package/packages/client/dist/adapters/vscode-adapter.js +73 -0
  46. package/packages/client/dist/adapters/vscode-adapter.js.map +1 -0
  47. package/packages/client/dist/cache/crypto-utils.d.ts +31 -0
  48. package/packages/client/dist/cache/crypto-utils.d.ts.map +1 -0
  49. package/packages/client/dist/cache/crypto-utils.js +77 -0
  50. package/packages/client/dist/cache/crypto-utils.js.map +1 -0
  51. package/packages/client/dist/cache/encrypted-cache.d.ts +31 -0
  52. package/packages/client/dist/cache/encrypted-cache.d.ts.map +1 -0
  53. package/packages/client/dist/cache/encrypted-cache.js +92 -0
  54. package/packages/client/dist/cache/encrypted-cache.js.map +1 -0
  55. package/packages/client/dist/cache/index.d.ts +14 -0
  56. package/packages/client/dist/cache/index.d.ts.map +1 -0
  57. package/packages/client/dist/cache/index.js +14 -0
  58. package/packages/client/dist/cache/index.js.map +1 -0
  59. package/packages/client/dist/cli.d.ts +15 -0
  60. package/packages/client/dist/cli.d.ts.map +1 -0
  61. package/packages/client/dist/cli.js +182 -0
  62. package/packages/client/dist/cli.js.map +1 -0
  63. package/packages/client/dist/commands/activate.d.ts +48 -0
  64. package/packages/client/dist/commands/activate.d.ts.map +1 -0
  65. package/packages/client/dist/commands/activate.js +186 -0
  66. package/packages/client/dist/commands/activate.js.map +1 -0
  67. package/packages/client/dist/commands/cache-status.d.ts +40 -0
  68. package/packages/client/dist/commands/cache-status.d.ts.map +1 -0
  69. package/packages/client/dist/commands/cache-status.js +113 -0
  70. package/packages/client/dist/commands/cache-status.js.map +1 -0
  71. package/packages/client/dist/commands/invoke.d.ts +71 -0
  72. package/packages/client/dist/commands/invoke.d.ts.map +1 -0
  73. package/packages/client/dist/commands/invoke.js +345 -0
  74. package/packages/client/dist/commands/invoke.js.map +1 -0
  75. package/packages/client/dist/config/resolver-selection.d.ts +41 -0
  76. package/packages/client/dist/config/resolver-selection.d.ts.map +1 -0
  77. package/packages/client/dist/config/resolver-selection.js +278 -0
  78. package/packages/client/dist/config/resolver-selection.js.map +1 -0
  79. package/packages/client/dist/context/context-collector.d.ts +29 -0
  80. package/packages/client/dist/context/context-collector.d.ts.map +1 -0
  81. package/packages/client/dist/context/context-collector.js +223 -0
  82. package/packages/client/dist/context/context-collector.js.map +1 -0
  83. package/packages/client/dist/context/context-sanitizer.d.ts +29 -0
  84. package/packages/client/dist/context/context-sanitizer.d.ts.map +1 -0
  85. package/packages/client/dist/context/context-sanitizer.js +146 -0
  86. package/packages/client/dist/context/context-sanitizer.js.map +1 -0
  87. package/packages/client/dist/index.d.ts +55 -0
  88. package/packages/client/dist/index.d.ts.map +1 -0
  89. package/packages/client/dist/index.js +37 -0
  90. package/packages/client/dist/index.js.map +1 -0
  91. package/packages/client/dist/license/index.d.ts +6 -0
  92. package/packages/client/dist/license/index.d.ts.map +1 -0
  93. package/packages/client/dist/license/index.js +6 -0
  94. package/packages/client/dist/license/index.js.map +1 -0
  95. package/packages/client/dist/license/license-client.d.ts +53 -0
  96. package/packages/client/dist/license/license-client.d.ts.map +1 -0
  97. package/packages/client/dist/license/license-client.js +164 -0
  98. package/packages/client/dist/license/license-client.js.map +1 -0
  99. package/packages/client/dist/machine/fingerprint.d.ts +24 -0
  100. package/packages/client/dist/machine/fingerprint.d.ts.map +1 -0
  101. package/packages/client/dist/machine/fingerprint.js +61 -0
  102. package/packages/client/dist/machine/fingerprint.js.map +1 -0
  103. package/packages/client/dist/machine/index.d.ts +6 -0
  104. package/packages/client/dist/machine/index.d.ts.map +1 -0
  105. package/packages/client/dist/machine/index.js +6 -0
  106. package/packages/client/dist/machine/index.js.map +1 -0
  107. package/packages/client/dist/resilience/circuit-breaker.d.ts +71 -0
  108. package/packages/client/dist/resilience/circuit-breaker.d.ts.map +1 -0
  109. package/packages/client/dist/resilience/circuit-breaker.js +171 -0
  110. package/packages/client/dist/resilience/circuit-breaker.js.map +1 -0
  111. package/packages/client/dist/resilience/degradation-manager.d.ts +68 -0
  112. package/packages/client/dist/resilience/degradation-manager.d.ts.map +1 -0
  113. package/packages/client/dist/resilience/degradation-manager.js +165 -0
  114. package/packages/client/dist/resilience/degradation-manager.js.map +1 -0
  115. package/packages/client/dist/resilience/freshness-indicator.d.ts +60 -0
  116. package/packages/client/dist/resilience/freshness-indicator.d.ts.map +1 -0
  117. package/packages/client/dist/resilience/freshness-indicator.js +101 -0
  118. package/packages/client/dist/resilience/freshness-indicator.js.map +1 -0
  119. package/packages/client/dist/resilience/index.d.ts +9 -0
  120. package/packages/client/dist/resilience/index.d.ts.map +1 -0
  121. package/packages/client/dist/resilience/index.js +9 -0
  122. package/packages/client/dist/resilience/index.js.map +1 -0
  123. package/packages/client/dist/resilience/recovery-detector.d.ts +60 -0
  124. package/packages/client/dist/resilience/recovery-detector.d.ts.map +1 -0
  125. package/packages/client/dist/resilience/recovery-detector.js +75 -0
  126. package/packages/client/dist/resilience/recovery-detector.js.map +1 -0
  127. package/packages/client/dist/resolvers/asset-resolver.d.ts +80 -0
  128. package/packages/client/dist/resolvers/asset-resolver.d.ts.map +1 -0
  129. package/packages/client/dist/resolvers/asset-resolver.js +14 -0
  130. package/packages/client/dist/resolvers/asset-resolver.js.map +1 -0
  131. package/packages/client/dist/resolvers/local-resolver.d.ts +27 -0
  132. package/packages/client/dist/resolvers/local-resolver.d.ts.map +1 -0
  133. package/packages/client/dist/resolvers/local-resolver.js +219 -0
  134. package/packages/client/dist/resolvers/local-resolver.js.map +1 -0
  135. package/packages/client/dist/resolvers/remote-resolver.d.ts +63 -0
  136. package/packages/client/dist/resolvers/remote-resolver.d.ts.map +1 -0
  137. package/packages/client/dist/resolvers/remote-resolver.js +207 -0
  138. package/packages/client/dist/resolvers/remote-resolver.js.map +1 -0
  139. package/packages/client/dist/telemetry/index.d.ts +6 -0
  140. package/packages/client/dist/telemetry/index.d.ts.map +1 -0
  141. package/packages/client/dist/telemetry/index.js +6 -0
  142. package/packages/client/dist/telemetry/index.js.map +1 -0
  143. package/packages/client/dist/telemetry/offline-queue.d.ts +58 -0
  144. package/packages/client/dist/telemetry/offline-queue.d.ts.map +1 -0
  145. package/packages/client/dist/telemetry/offline-queue.js +132 -0
  146. package/packages/client/dist/telemetry/offline-queue.js.map +1 -0
  147. package/packages/client/dist/types/index.d.ts +141 -0
  148. package/packages/client/dist/types/index.d.ts.map +1 -0
  149. package/packages/client/dist/types/index.js +39 -0
  150. package/packages/client/dist/types/index.js.map +1 -0
  151. package/targets-stubs/antigravity/README.md +20 -0
  152. package/targets-stubs/claude-code/README.md +20 -0
  153. package/targets-stubs/codex/README.md +20 -0
  154. package/targets-stubs/cursor/README.md +20 -0
  155. package/targets-stubs/gemini-cli/README.md +20 -0
  156. package/targets-stubs/vscode/README.md +20 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license-client.d.ts","sourceRoot":"","sources":["../../src/license/license-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAcH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAYvD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,UAAU,gBAAgB;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAID,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,KAAK,CAAuB;gBAExB,OAAO,EAAE,oBAAoB;IAQzC;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAoCxC;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IA0BlD;;;;OAIG;IACG,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IA0BrE,OAAO,CAAC,kBAAkB;YAcZ,aAAa;CAO5B"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * This file is part of Neocortex CLI, licensed under the
6
+ * Functional Source License, Version 1.1 (FSL-1.1).
7
+ *
8
+ * Change Date: February 20, 2029
9
+ * Change License: MIT
10
+ *
11
+ * See the LICENSE file in the project root for full license text.
12
+ */
13
+ /**
14
+ * @neocortex/client - License Client
15
+ *
16
+ * Manages license activation, JWT token caching, and proactive refresh.
17
+ * Integrates with the IP Protection Server's license endpoints and
18
+ * uses EncryptedCache for persistent token storage.
19
+ *
20
+ * NEVER throws exceptions - returns null on failure (graceful degradation).
21
+ */
22
+ import { decodeJwt } from 'jose';
23
+ import { NoOpCache } from '../types/index.js';
24
+ import { getMachineFingerprint } from '../machine/fingerprint.js';
25
+ // ── Constants ────────────────────────────────────────────────────────────
26
+ const CACHE_KEY = 'neocortex:jwt:token';
27
+ const REFRESH_THRESHOLD_S = 3600; // 1 hour before expiry
28
+ const DEFAULT_CLIENT_VERSION = '0.1.0';
29
+ // ── LicenseClient ────────────────────────────────────────────────────────
30
+ export class LicenseClient {
31
+ serverUrl;
32
+ licenseKey;
33
+ cache;
34
+ clientVersion;
35
+ machineId;
36
+ token = null;
37
+ constructor(options) {
38
+ this.serverUrl = options.serverUrl.replace(/\/+$/, '');
39
+ this.licenseKey = options.licenseKey;
40
+ this.cache = options.cacheProvider ?? new NoOpCache();
41
+ this.clientVersion = options.clientVersion ?? DEFAULT_CLIENT_VERSION;
42
+ this.machineId = getMachineFingerprint();
43
+ }
44
+ /**
45
+ * Get a valid JWT token. Checks memory, cache, refresh, then activation.
46
+ * NEVER throws - returns null on failure.
47
+ */
48
+ async getToken() {
49
+ try {
50
+ // 1. Check in-memory token
51
+ if (this.token) {
52
+ const validity = this.checkTokenValidity(this.token);
53
+ if (validity === 'valid')
54
+ return this.token;
55
+ if (validity === 'needs-refresh') {
56
+ const refreshed = await this.refresh(this.token);
57
+ return refreshed?.token ?? this.token;
58
+ }
59
+ // expired or invalid - clear memory
60
+ this.token = null;
61
+ }
62
+ // 2. Check cache
63
+ const cached = await this.loadFromCache();
64
+ if (cached) {
65
+ this.token = cached;
66
+ const validity = this.checkTokenValidity(cached);
67
+ if (validity === 'valid')
68
+ return cached;
69
+ if (validity === 'needs-refresh') {
70
+ const refreshed = await this.refresh(cached);
71
+ return refreshed?.token ?? cached;
72
+ }
73
+ // expired - clear
74
+ this.token = null;
75
+ }
76
+ // 3. Activate
77
+ const result = await this.activate();
78
+ return result?.token ?? null;
79
+ }
80
+ catch {
81
+ return null;
82
+ }
83
+ }
84
+ /**
85
+ * Activate the license by calling POST /api/v1/license/activate.
86
+ * Stores token in memory and cache on success.
87
+ * NEVER throws - returns null on failure.
88
+ */
89
+ async activate() {
90
+ try {
91
+ const response = await fetch(`${this.serverUrl}/api/v1/license/activate`, {
92
+ method: 'POST',
93
+ headers: { 'Content-Type': 'application/json' },
94
+ body: JSON.stringify({
95
+ license_key: this.licenseKey,
96
+ machine_id: this.machineId,
97
+ client_version: this.clientVersion,
98
+ }),
99
+ });
100
+ if (!response.ok)
101
+ return null;
102
+ const data = (await response.json());
103
+ this.token = data.token;
104
+ // Persist to cache (fire-and-forget)
105
+ this.cache.set(CACHE_KEY, data.token, data.expires_in * 1000).catch(() => { });
106
+ return { token: data.token, expiresIn: data.expires_in };
107
+ }
108
+ catch {
109
+ return null;
110
+ }
111
+ }
112
+ /**
113
+ * Refresh an expiring token by calling POST /api/v1/license/refresh.
114
+ * Stores new token in memory and cache on success.
115
+ * NEVER throws - returns null on failure.
116
+ */
117
+ async refresh(currentToken) {
118
+ try {
119
+ const response = await fetch(`${this.serverUrl}/api/v1/license/refresh`, {
120
+ method: 'POST',
121
+ headers: {
122
+ 'Content-Type': 'application/json',
123
+ 'Authorization': `Bearer ${currentToken}`,
124
+ },
125
+ });
126
+ if (!response.ok)
127
+ return null;
128
+ const data = (await response.json());
129
+ this.token = data.token;
130
+ // Persist to cache (fire-and-forget)
131
+ this.cache.set(CACHE_KEY, data.token, data.expires_in * 1000).catch(() => { });
132
+ return { token: data.token, expiresIn: data.expires_in };
133
+ }
134
+ catch {
135
+ return null;
136
+ }
137
+ }
138
+ // ── Private Methods ─────────────────────────────────────────────────
139
+ checkTokenValidity(token) {
140
+ try {
141
+ const payload = decodeJwt(token);
142
+ if (!payload.exp)
143
+ return 'expired';
144
+ const now = Math.floor(Date.now() / 1000);
145
+ if (payload.exp <= now)
146
+ return 'expired';
147
+ if (payload.exp - now <= REFRESH_THRESHOLD_S)
148
+ return 'needs-refresh';
149
+ return 'valid';
150
+ }
151
+ catch {
152
+ return 'expired';
153
+ }
154
+ }
155
+ async loadFromCache() {
156
+ try {
157
+ return await this.cache.get(CACHE_KEY);
158
+ }
159
+ catch {
160
+ return null;
161
+ }
162
+ }
163
+ }
164
+ //# sourceMappingURL=license-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license-client.js","sourceRoot":"","sources":["../../src/license/license-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * This file is part of Neocortex CLI, licensed under the
6
+ * Functional Source License, Version 1.1 (FSL-1.1).
7
+ *
8
+ * Change Date: February 20, 2029
9
+ * Change License: MIT
10
+ *
11
+ * See the LICENSE file in the project root for full license text.
12
+ */
13
+ /**
14
+ * Generate a stable machine fingerprint as a SHA-256 hex digest.
15
+ *
16
+ * Combines: hostname | platform | arch | cpu model | sorted MAC addresses
17
+ *
18
+ * The fingerprint is deterministic and stable across process restarts
19
+ * and reboots on the same machine. Minor OS updates should not change it.
20
+ *
21
+ * @returns 64-character hex string (SHA-256 digest)
22
+ */
23
+ export declare function getMachineFingerprint(): string;
24
+ //# sourceMappingURL=fingerprint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../src/machine/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAmCH;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAW9C"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * This file is part of Neocortex CLI, licensed under the
6
+ * Functional Source License, Version 1.1 (FSL-1.1).
7
+ *
8
+ * Change Date: February 20, 2029
9
+ * Change License: MIT
10
+ *
11
+ * See the LICENSE file in the project root for full license text.
12
+ */
13
+ /**
14
+ * @neocortex/client - Machine Fingerprint
15
+ *
16
+ * Generates a stable, deterministic machine identifier from hardware/OS
17
+ * attributes using SHA-256. Used for license activation machine tracking.
18
+ */
19
+ import { createHash } from 'node:crypto';
20
+ import { arch, cpus, hostname, networkInterfaces, platform } from 'node:os';
21
+ const ALL_ZEROS_MAC = '00:00:00:00:00:00';
22
+ /**
23
+ * Collect sorted, non-internal MAC addresses from network interfaces.
24
+ * Filters out internal/loopback interfaces and all-zeros MACs.
25
+ */
26
+ function collectMacAddresses() {
27
+ const interfaces = networkInterfaces();
28
+ const macs = [];
29
+ for (const entries of Object.values(interfaces)) {
30
+ if (!entries)
31
+ continue;
32
+ for (const entry of entries) {
33
+ if (!entry.internal && entry.mac !== ALL_ZEROS_MAC) {
34
+ macs.push(entry.mac);
35
+ }
36
+ }
37
+ }
38
+ // Sort for determinism regardless of NIC enumeration order
39
+ return [...new Set(macs)].sort();
40
+ }
41
+ /**
42
+ * Generate a stable machine fingerprint as a SHA-256 hex digest.
43
+ *
44
+ * Combines: hostname | platform | arch | cpu model | sorted MAC addresses
45
+ *
46
+ * The fingerprint is deterministic and stable across process restarts
47
+ * and reboots on the same machine. Minor OS updates should not change it.
48
+ *
49
+ * @returns 64-character hex string (SHA-256 digest)
50
+ */
51
+ export function getMachineFingerprint() {
52
+ const host = hostname();
53
+ const plat = platform();
54
+ const architecture = arch();
55
+ const cpuList = cpus();
56
+ const cpuModel = cpuList.length > 0 ? cpuList[0].model : '';
57
+ const macs = collectMacAddresses();
58
+ const input = `${host}|${plat}|${architecture}|${cpuModel}|${macs.join(',')}`;
59
+ return createHash('sha256').update(input).digest('hex');
60
+ }
61
+ //# sourceMappingURL=fingerprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/machine/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE5E,MAAM,aAAa,GAAG,mBAAmB,CAAC;AAE1C;;;GAGG;AACH,SAAS,mBAAmB;IAC1B,MAAM,UAAU,GAAG,iBAAiB,EAAE,CAAC;IACvC,MAAM,IAAI,GAAa,EAAE,CAAC;IAE1B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;QAChD,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,GAAG,KAAK,aAAa,EAAE,CAAC;gBACnD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAED,2DAA2D;IAC3D,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACnC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,MAAM,YAAY,GAAG,IAAI,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,IAAI,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,MAAM,IAAI,GAAG,mBAAmB,EAAE,CAAC;IAEnC,MAAM,KAAK,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,YAAY,IAAI,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IAE9E,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ */
5
+ export { getMachineFingerprint } from './fingerprint.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/machine/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ */
5
+ export { getMachineFingerprint } from './fingerprint.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/machine/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * This file is part of Neocortex CLI, licensed under the
6
+ * Functional Source License, Version 1.1 (FSL-1.1).
7
+ *
8
+ * Change Date: February 20, 2029
9
+ * Change License: MIT
10
+ *
11
+ * See the LICENSE file in the project root for full license text.
12
+ */
13
+ export type CircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN';
14
+ export interface CircuitBreakerConfig {
15
+ /** Number of failures within window to trip circuit. Default: 3 */
16
+ failureThreshold: number;
17
+ /** Window in ms for counting failures. Default: 60_000 (60s) */
18
+ failureWindowMs: number;
19
+ /** Time in ms before OPEN transitions to HALF_OPEN. Default: 60_000 (60s) */
20
+ halfOpenAfterMs: number;
21
+ /** Path to persist circuit state. Default: ~/.neocortex/.circuit-state */
22
+ stateFilePath: string;
23
+ }
24
+ export interface FailureRecord {
25
+ timestamp: number;
26
+ }
27
+ export interface CircuitBreakerState {
28
+ state: CircuitState;
29
+ failures: FailureRecord[];
30
+ openedAt: number | null;
31
+ lastProbeAt: number | null;
32
+ }
33
+ export declare class ClientCircuitBreaker {
34
+ private readonly config;
35
+ private internalState;
36
+ constructor(config?: Partial<CircuitBreakerConfig>, initialState?: CircuitBreakerState);
37
+ /**
38
+ * Check if a request can be made to the server.
39
+ * Returns false if circuit is OPEN (fail-fast to cache).
40
+ */
41
+ canCall(): boolean;
42
+ /**
43
+ * Record a successful server response. Closes the circuit.
44
+ */
45
+ recordSuccess(): Promise<void>;
46
+ /**
47
+ * Record a failed server response. Opens circuit after threshold failures in window.
48
+ */
49
+ recordFailure(): Promise<void>;
50
+ /**
51
+ * Get current circuit breaker state (copy).
52
+ */
53
+ getState(): CircuitBreakerState;
54
+ /**
55
+ * Reset circuit breaker to initial CLOSED state.
56
+ */
57
+ reset(): Promise<void>;
58
+ /**
59
+ * Load circuit breaker state from disk.
60
+ */
61
+ static loadFromDisk(path?: string): Promise<ClientCircuitBreaker>;
62
+ /**
63
+ * Remove failures outside the counting window.
64
+ */
65
+ private pruneExpiredFailures;
66
+ /**
67
+ * Persist state to disk with atomic write.
68
+ */
69
+ private saveToDisk;
70
+ }
71
+ //# sourceMappingURL=circuit-breaker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../../src/resilience/circuit-breaker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAwBH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAE3D,MAAM,WAAW,oBAAoB;IACnC,mEAAmE;IACnE,gBAAgB,EAAE,MAAM,CAAC;IACzB,gEAAgE;IAChE,eAAe,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,eAAe,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,YAAY,CAAC;IACpB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAoBD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,aAAa,CAAsB;gBAE/B,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,EAAE,YAAY,CAAC,EAAE,mBAAmB;IAKtF;;;OAGG;IACH,OAAO,IAAI,OAAO;IA0BlB;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAQpC;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBpC;;OAEG;IACH,QAAQ,IAAI,mBAAmB;IAU/B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B;;OAEG;WACU,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAoBvE;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAO5B;;OAEG;YACW,UAAU;CAiBzB"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * This file is part of Neocortex CLI, licensed under the
6
+ * Functional Source License, Version 1.1 (FSL-1.1).
7
+ *
8
+ * Change Date: February 20, 2029
9
+ * Change License: MIT
10
+ *
11
+ * See the LICENSE file in the project root for full license text.
12
+ */
13
+ /**
14
+ * @neocortex/client - Persistent Circuit Breaker
15
+ *
16
+ * Circuit breaker with file-based state persistence for the CLI client.
17
+ * Tracks server health using window-based failure counting and persists
18
+ * state between CLI invocations at ~/.neocortex/.circuit-state.
19
+ *
20
+ * States:
21
+ * CLOSED - Normal operation, requests pass through
22
+ * OPEN - Circuit tripped, requests fail immediately (use cache)
23
+ * HALF_OPEN - Testing if server recovered (one probe request allowed)
24
+ *
25
+ * Story 42.9
26
+ */
27
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
28
+ import { dirname } from 'node:path';
29
+ import { homedir } from 'node:os';
30
+ import { join } from 'node:path';
31
+ // ── Defaults ──────────────────────────────────────────────────────────────
32
+ const DEFAULT_CONFIG = {
33
+ failureThreshold: 3,
34
+ failureWindowMs: 60_000,
35
+ halfOpenAfterMs: 60_000,
36
+ stateFilePath: join(homedir(), '.neocortex', '.circuit-state'),
37
+ };
38
+ const INITIAL_STATE = {
39
+ state: 'CLOSED',
40
+ failures: [],
41
+ openedAt: null,
42
+ lastProbeAt: null,
43
+ };
44
+ // ── ClientCircuitBreaker ──────────────────────────────────────────────────
45
+ export class ClientCircuitBreaker {
46
+ config;
47
+ internalState;
48
+ constructor(config, initialState) {
49
+ this.config = { ...DEFAULT_CONFIG, ...config };
50
+ this.internalState = initialState ? { ...initialState } : { ...INITIAL_STATE, failures: [] };
51
+ }
52
+ /**
53
+ * Check if a request can be made to the server.
54
+ * Returns false if circuit is OPEN (fail-fast to cache).
55
+ */
56
+ canCall() {
57
+ this.pruneExpiredFailures();
58
+ switch (this.internalState.state) {
59
+ case 'CLOSED':
60
+ return true;
61
+ case 'OPEN': {
62
+ const now = Date.now();
63
+ const openedAt = this.internalState.openedAt ?? 0;
64
+ if (now - openedAt >= this.config.halfOpenAfterMs) {
65
+ this.internalState.state = 'HALF_OPEN';
66
+ this.internalState.lastProbeAt = now;
67
+ return true;
68
+ }
69
+ return false;
70
+ }
71
+ case 'HALF_OPEN':
72
+ return true;
73
+ default:
74
+ return true;
75
+ }
76
+ }
77
+ /**
78
+ * Record a successful server response. Closes the circuit.
79
+ */
80
+ async recordSuccess() {
81
+ this.internalState.state = 'CLOSED';
82
+ this.internalState.failures = [];
83
+ this.internalState.openedAt = null;
84
+ this.internalState.lastProbeAt = null;
85
+ await this.saveToDisk();
86
+ }
87
+ /**
88
+ * Record a failed server response. Opens circuit after threshold failures in window.
89
+ */
90
+ async recordFailure() {
91
+ const now = Date.now();
92
+ this.internalState.failures.push({ timestamp: now });
93
+ this.pruneExpiredFailures();
94
+ if (this.internalState.failures.length >= this.config.failureThreshold) {
95
+ this.internalState.state = 'OPEN';
96
+ this.internalState.openedAt = now;
97
+ }
98
+ // If in HALF_OPEN and probe fails, go back to OPEN
99
+ if (this.internalState.state === 'HALF_OPEN') {
100
+ this.internalState.state = 'OPEN';
101
+ this.internalState.openedAt = now;
102
+ }
103
+ await this.saveToDisk();
104
+ }
105
+ /**
106
+ * Get current circuit breaker state (copy).
107
+ */
108
+ getState() {
109
+ this.pruneExpiredFailures();
110
+ return {
111
+ state: this.internalState.state,
112
+ failures: [...this.internalState.failures],
113
+ openedAt: this.internalState.openedAt,
114
+ lastProbeAt: this.internalState.lastProbeAt,
115
+ };
116
+ }
117
+ /**
118
+ * Reset circuit breaker to initial CLOSED state.
119
+ */
120
+ async reset() {
121
+ this.internalState = { ...INITIAL_STATE, failures: [] };
122
+ await this.saveToDisk();
123
+ }
124
+ /**
125
+ * Load circuit breaker state from disk.
126
+ */
127
+ static async loadFromDisk(path) {
128
+ const filePath = path ?? DEFAULT_CONFIG.stateFilePath;
129
+ try {
130
+ const raw = await readFile(filePath, 'utf8');
131
+ const data = JSON.parse(raw);
132
+ // Validate loaded state
133
+ if (!data.state || !Array.isArray(data.failures)) {
134
+ return new ClientCircuitBreaker({ stateFilePath: filePath });
135
+ }
136
+ return new ClientCircuitBreaker({ stateFilePath: filePath }, data);
137
+ }
138
+ catch {
139
+ // File doesn't exist or is corrupted - start fresh
140
+ return new ClientCircuitBreaker({ stateFilePath: filePath });
141
+ }
142
+ }
143
+ // ── Private ─────────────────────────────────────────────────────────
144
+ /**
145
+ * Remove failures outside the counting window.
146
+ */
147
+ pruneExpiredFailures() {
148
+ const cutoff = Date.now() - this.config.failureWindowMs;
149
+ this.internalState.failures = this.internalState.failures.filter((f) => f.timestamp > cutoff);
150
+ }
151
+ /**
152
+ * Persist state to disk with atomic write.
153
+ */
154
+ async saveToDisk() {
155
+ try {
156
+ const dir = dirname(this.config.stateFilePath);
157
+ await mkdir(dir, { recursive: true });
158
+ const tmpPath = `${this.config.stateFilePath}.tmp`;
159
+ const data = JSON.stringify(this.internalState, null, 2);
160
+ await writeFile(tmpPath, data, 'utf8');
161
+ // Atomic rename
162
+ const { rename } = await import('node:fs/promises');
163
+ await rename(tmpPath, this.config.stateFilePath);
164
+ }
165
+ catch {
166
+ // Persistence failures are non-critical - circuit breaker
167
+ // still works in-memory for current session
168
+ }
169
+ }
170
+ }
171
+ //# sourceMappingURL=circuit-breaker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../../src/resilience/circuit-breaker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AA4BjC,6EAA6E;AAE7E,MAAM,cAAc,GAAyB;IAC3C,gBAAgB,EAAE,CAAC;IACnB,eAAe,EAAE,MAAM;IACvB,eAAe,EAAE,MAAM;IACvB,aAAa,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,gBAAgB,CAAC;CAC/D,CAAC;AAEF,MAAM,aAAa,GAAwB;IACzC,KAAK,EAAE,QAAQ;IACf,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,IAAI;IACd,WAAW,EAAE,IAAI;CAClB,CAAC;AAEF,6EAA6E;AAE7E,MAAM,OAAO,oBAAoB;IACd,MAAM,CAAuB;IACtC,aAAa,CAAsB;IAE3C,YAAY,MAAsC,EAAE,YAAkC;QACpF,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,EAAE,CAAC;QAC/C,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,aAAa,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC/F,CAAC;IAED;;;OAGG;IACH,OAAO;QACL,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAE5B,QAAQ,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;YACjC,KAAK,QAAQ;gBACX,OAAO,IAAI,CAAC;YAEd,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,IAAI,CAAC,CAAC;gBAClD,IAAI,GAAG,GAAG,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;oBAClD,IAAI,CAAC,aAAa,CAAC,KAAK,GAAG,WAAW,CAAC;oBACvC,IAAI,CAAC,aAAa,CAAC,WAAW,GAAG,GAAG,CAAC;oBACrC,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,OAAO,KAAK,CAAC;YACf,CAAC;YAED,KAAK,WAAW;gBACd,OAAO,IAAI,CAAC;YAEd;gBACE,OAAO,IAAI,CAAC;QAChB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa;QACjB,IAAI,CAAC,aAAa,CAAC,KAAK,GAAG,QAAQ,CAAC;QACpC,IAAI,CAAC,aAAa,CAAC,QAAQ,GAAG,EAAE,CAAC;QACjC,IAAI,CAAC,aAAa,CAAC,QAAQ,GAAG,IAAI,CAAC;QACnC,IAAI,CAAC,aAAa,CAAC,WAAW,GAAG,IAAI,CAAC;QACtC,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa;QACjB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;QACrD,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAE5B,IAAI,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;YACvE,IAAI,CAAC,aAAa,CAAC,KAAK,GAAG,MAAM,CAAC;YAClC,IAAI,CAAC,aAAa,CAAC,QAAQ,GAAG,GAAG,CAAC;QACpC,CAAC;QAED,mDAAmD;QACnD,IAAI,IAAI,CAAC,aAAa,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;YAC7C,IAAI,CAAC,aAAa,CAAC,KAAK,GAAG,MAAM,CAAC;YAClC,IAAI,CAAC,aAAa,CAAC,QAAQ,GAAG,GAAG,CAAC;QACpC,CAAC;QAED,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5B,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,KAAK;YAC/B,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC;YAC1C,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ;YACrC,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,WAAW;SAC5C,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,aAAa,GAAG,EAAE,GAAG,aAAa,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACxD,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,IAAa;QACrC,MAAM,QAAQ,GAAG,IAAI,IAAI,cAAc,CAAC,aAAa,CAAC;QACtD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAwB,CAAC;YAEpD,wBAAwB;YACxB,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACjD,OAAO,IAAI,oBAAoB,CAAC,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC/D,CAAC;YAED,OAAO,IAAI,oBAAoB,CAAC,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,IAAI,CAAC,CAAC;QACrE,CAAC;QAAC,MAAM,CAAC;YACP,mDAAmD;YACnD,OAAO,IAAI,oBAAoB,CAAC,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,uEAAuE;IAEvE;;OAEG;IACK,oBAAoB;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC;QACxD,IAAI,CAAC,aAAa,CAAC,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,MAAM,CAC9D,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,MAAM,CAC5B,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,UAAU;QACtB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAC/C,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAEtC,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,MAAM,CAAC;YACnD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACzD,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAEvC,gBAAgB;YAChB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;YACpD,MAAM,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,0DAA0D;YAC1D,4CAA4C;QAC9C,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * This file is part of Neocortex CLI, licensed under the
6
+ * Functional Source License, Version 1.1 (FSL-1.1).
7
+ *
8
+ * Change Date: February 20, 2029
9
+ * Change License: MIT
10
+ *
11
+ * See the LICENSE file in the project root for full license text.
12
+ */
13
+ /**
14
+ * @neocortex/client - Degradation Manager
15
+ *
16
+ * Evaluates current degradation level (L0-L4) based on circuit breaker state,
17
+ * measured latency, cache availability and freshness. Returns a decision
18
+ * object that tells the resolver how to behave.
19
+ *
20
+ * Story 42.9
21
+ */
22
+ import type { CircuitState } from './circuit-breaker.js';
23
+ export declare enum DegradationLevel {
24
+ /** Server available, fresh data, optimal performance */
25
+ ONLINE = 0,
26
+ /** Server slow (>2s), use cache when available */
27
+ HIGH_LATENCY = 1,
28
+ /** Server down, use cache exclusively */
29
+ SERVER_DOWN = 2,
30
+ /** Cache expired (>24h), use with warning */
31
+ STALE_CACHE = 3,
32
+ /** No cache and no server - error state */
33
+ NO_CACHE = 4
34
+ }
35
+ export interface DegradationContext {
36
+ circuitState: CircuitState;
37
+ latencyMs?: number;
38
+ cacheAvailable: boolean;
39
+ cacheAgeMs?: number;
40
+ forceOffline: boolean;
41
+ }
42
+ export interface DegradationDecision {
43
+ level: DegradationLevel;
44
+ useCache: boolean;
45
+ useServer: boolean;
46
+ prefix: string;
47
+ warning: string | null;
48
+ }
49
+ export interface DegradationManagerConfig {
50
+ /** Cache age threshold for STALE warning. Default: 86_400_000 (24h) */
51
+ staleThresholdMs: number;
52
+ /** Cache age threshold for initial warning. Default: 43_200_000 (12h) */
53
+ warningThresholdMs: number;
54
+ /** Latency threshold for HIGH_LATENCY level. Default: 2000 (2s) */
55
+ latencyThresholdMs: number;
56
+ }
57
+ export declare class DegradationManager {
58
+ private readonly config;
59
+ constructor(config?: Partial<DegradationManagerConfig>);
60
+ /**
61
+ * Evaluate the current degradation level based on context.
62
+ */
63
+ evaluate(context: DegradationContext): DegradationDecision;
64
+ private buildServerDownDecision;
65
+ private buildCacheOnlyDecision;
66
+ private formatAge;
67
+ }
68
+ //# sourceMappingURL=degradation-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"degradation-manager.d.ts","sourceRoot":"","sources":["../../src/resilience/degradation-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIzD,oBAAY,gBAAgB;IAC1B,wDAAwD;IACxD,MAAM,IAAI;IACV,kDAAkD;IAClD,YAAY,IAAI;IAChB,yCAAyC;IACzC,WAAW,IAAI;IACf,6CAA6C;IAC7C,WAAW,IAAI;IACf,2CAA2C;IAC3C,QAAQ,IAAI;CACb;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,YAAY,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,uEAAuE;IACvE,gBAAgB,EAAE,MAAM,CAAC;IACzB,yEAAyE;IACzE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mEAAmE;IACnE,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAYD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;gBAEtC,MAAM,CAAC,EAAE,OAAO,CAAC,wBAAwB,CAAC;IAItD;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,kBAAkB,GAAG,mBAAmB;IAyD1D,OAAO,CAAC,uBAAuB;IAmC/B,OAAO,CAAC,sBAAsB;IAiC9B,OAAO,CAAC,SAAS;CAQlB"}