@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,186 @@
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 - Activate Command
15
+ *
16
+ * Manages license activation for the Neocortex CLI.
17
+ * Validates license key with the IP Protection Server,
18
+ * caches JWT token, and creates user config file.
19
+ *
20
+ * Story 43.3 - AC1, AC3, AC4, AC5
21
+ */
22
+ import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
23
+ import { join } from 'node:path';
24
+ import { homedir } from 'node:os';
25
+ import { LicenseClient } from '../license/license-client.js';
26
+ import { getMachineFingerprint } from '../machine/fingerprint.js';
27
+ // ── Constants ─────────────────────────────────────────────────────────────
28
+ const CONFIG_DIR = join(homedir(), '.neocortex');
29
+ const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
30
+ const DEFAULT_SERVER_URL = 'https://api.neocortex.ornexus.com';
31
+ // License key format: NX-{TIER}-{random}-{random}
32
+ const LICENSE_KEY_PATTERN = /^NX-(FREE|PRO|ENT)-[A-Z0-9]+-[A-Z0-9]+$/i;
33
+ // ── Validation ────────────────────────────────────────────────────────────
34
+ /**
35
+ * Validate license key format.
36
+ * Format: NX-{TIER}-{random}-{random}
37
+ * Tiers: FREE, PRO, ENT
38
+ */
39
+ export function validateLicenseKeyFormat(key) {
40
+ if (!key || key.trim().length === 0) {
41
+ return { valid: false, error: 'License key cannot be empty' };
42
+ }
43
+ const trimmed = key.trim().toUpperCase();
44
+ if (!trimmed.startsWith('NX-')) {
45
+ return { valid: false, error: 'License key must start with "NX-"' };
46
+ }
47
+ if (!LICENSE_KEY_PATTERN.test(trimmed)) {
48
+ return {
49
+ valid: false,
50
+ error: 'Invalid license key format. Expected: NX-{TIER}-{ID} (e.g., NX-PRO-ABC-123)',
51
+ };
52
+ }
53
+ return { valid: true };
54
+ }
55
+ // ── Config Management ─────────────────────────────────────────────────────
56
+ /**
57
+ * Load existing user config, if any.
58
+ */
59
+ function loadExistingConfig() {
60
+ try {
61
+ if (existsSync(CONFIG_FILE)) {
62
+ const raw = readFileSync(CONFIG_FILE, 'utf-8');
63
+ return JSON.parse(raw);
64
+ }
65
+ }
66
+ catch {
67
+ // Corrupted config - will be overwritten
68
+ }
69
+ return null;
70
+ }
71
+ /**
72
+ * Save user config after successful activation.
73
+ * NOTE: License key is NOT stored - only JWT is cached by LicenseClient.
74
+ */
75
+ function saveConfig(config) {
76
+ mkdirSync(CONFIG_DIR, { recursive: true });
77
+ writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + '\n', 'utf-8');
78
+ }
79
+ // ── Activate Command ──────────────────────────────────────────────────────
80
+ /**
81
+ * Activate a Neocortex license.
82
+ *
83
+ * Flow:
84
+ * 1. Validate license key format
85
+ * 2. Call IP Protection Server to activate
86
+ * 3. Cache JWT token via LicenseClient
87
+ * 4. Create/update ~/.neocortex/config.json
88
+ * 5. Return result with feedback
89
+ */
90
+ export async function activate(options) {
91
+ const { licenseKey, serverUrl = DEFAULT_SERVER_URL } = options;
92
+ // 1. Validate license key
93
+ if (!licenseKey) {
94
+ return {
95
+ success: false,
96
+ message: 'No license key provided. Usage: neocortex activate NX-PRO-xxx',
97
+ };
98
+ }
99
+ const validation = validateLicenseKeyFormat(licenseKey);
100
+ if (!validation.valid) {
101
+ return {
102
+ success: false,
103
+ message: `Invalid license key: ${validation.error}`,
104
+ };
105
+ }
106
+ const normalizedKey = licenseKey.trim().toUpperCase();
107
+ // 2. Extract tier from key
108
+ const tierMatch = normalizedKey.match(/^NX-(FREE|PRO|ENT)-/);
109
+ const tier = tierMatch?.[1]?.toLowerCase() ?? 'unknown';
110
+ // 3. Attempt activation via LicenseClient
111
+ const client = new LicenseClient({
112
+ serverUrl,
113
+ licenseKey: normalizedKey,
114
+ });
115
+ let activationResult;
116
+ try {
117
+ activationResult = await client.activate();
118
+ }
119
+ catch {
120
+ return {
121
+ success: false,
122
+ message: [
123
+ 'Failed to connect to IP Protection Server.',
124
+ '',
125
+ 'Possible causes:',
126
+ ` - Server at ${serverUrl} is unreachable`,
127
+ ' - Network connectivity issue',
128
+ ' - Server is still being deployed',
129
+ '',
130
+ 'Workaround: Use --local flag to run in local mode',
131
+ ].join('\n'),
132
+ };
133
+ }
134
+ if (!activationResult) {
135
+ return {
136
+ success: false,
137
+ message: [
138
+ 'License activation failed.',
139
+ '',
140
+ 'Possible causes:',
141
+ ' - Invalid or expired license key',
142
+ ' - License already activated on another machine',
143
+ ' - Server rejected the activation request',
144
+ '',
145
+ 'Check your license key and try again.',
146
+ 'Contact support if the problem persists.',
147
+ ].join('\n'),
148
+ };
149
+ }
150
+ // 4. Save config (without license key for security)
151
+ const config = {
152
+ serverUrl,
153
+ mode: 'remote',
154
+ machineId: getMachineFingerprint(),
155
+ activatedAt: new Date().toISOString(),
156
+ tier,
157
+ };
158
+ try {
159
+ saveConfig(config);
160
+ }
161
+ catch (err) {
162
+ return {
163
+ success: false,
164
+ message: `Failed to save config to ${CONFIG_FILE}: ${err instanceof Error ? err.message : String(err)}`,
165
+ };
166
+ }
167
+ // 5. Return success
168
+ return {
169
+ success: true,
170
+ message: [
171
+ `License activated successfully!`,
172
+ '',
173
+ ` Tier: ${tier}`,
174
+ ` Server: ${serverUrl}`,
175
+ ` Config: ${CONFIG_FILE}`,
176
+ ` Expires: ${Math.floor(activationResult.expiresIn / 3600)}h`,
177
+ '',
178
+ 'You can now use Neocortex in remote mode.',
179
+ 'The CLI will automatically fetch content from the server.',
180
+ ].join('\n'),
181
+ tier,
182
+ serverUrl,
183
+ configPath: CONFIG_FILE,
184
+ };
185
+ }
186
+ //# sourceMappingURL=activate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activate.js","sourceRoot":"","sources":["../../src/commands/activate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
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
+ import type { ClientCircuitBreaker, CircuitState } from '../resilience/circuit-breaker.js';
14
+ import type { OfflineTelemetryQueue } from '../telemetry/offline-queue.js';
15
+ export interface CacheStatusInfo {
16
+ totalEntries: number;
17
+ totalSizeBytes: number;
18
+ totalSizeFormatted: string;
19
+ oldestEntry: Date | null;
20
+ newestEntry: Date | null;
21
+ staleEntries: number;
22
+ circuitState: CircuitState;
23
+ lastSync: Date | null;
24
+ telemetryQueueSize: number;
25
+ }
26
+ export interface CacheStatusOptions {
27
+ cacheDir: string;
28
+ circuitBreaker: ClientCircuitBreaker;
29
+ telemetryQueue: OfflineTelemetryQueue;
30
+ staleThresholdMs?: number;
31
+ }
32
+ /**
33
+ * Gather comprehensive cache status information.
34
+ */
35
+ export declare function getCacheStatus(options: CacheStatusOptions): Promise<CacheStatusInfo>;
36
+ /**
37
+ * Format cache status as a human-readable string for terminal output.
38
+ */
39
+ export declare function formatCacheStatus(info: CacheStatusInfo): string;
40
+ //# sourceMappingURL=cache-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-status.d.ts","sourceRoot":"","sources":["../../src/commands/cache-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAcH,OAAO,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAC3F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAI3E,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,oBAAoB,CAAC;IACrC,cAAc,EAAE,qBAAqB,CAAC;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAID;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,eAAe,CAAC,CA0D1F;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAkB/D"}
@@ -0,0 +1,113 @@
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 - Cache Status Command
15
+ *
16
+ * Displays comprehensive cache and circuit breaker status information.
17
+ * Shows entry count, total size, age range, stale entries, circuit state,
18
+ * and telemetry queue stats.
19
+ *
20
+ * Story 42.9 - AC7
21
+ */
22
+ import { readdir, stat } from 'node:fs/promises';
23
+ import { join } from 'node:path';
24
+ // ── Implementation ──────────────────────────────────────────────────────
25
+ /**
26
+ * Gather comprehensive cache status information.
27
+ */
28
+ export async function getCacheStatus(options) {
29
+ const staleThreshold = options.staleThresholdMs ?? 86_400_000; // 24h default
30
+ let totalEntries = 0;
31
+ let totalSizeBytes = 0;
32
+ let staleEntries = 0;
33
+ let oldestEntry = null;
34
+ let newestEntry = null;
35
+ try {
36
+ const entries = await readdir(options.cacheDir);
37
+ const encFiles = entries.filter((e) => e.endsWith('.enc'));
38
+ totalEntries = encFiles.length;
39
+ const now = Date.now();
40
+ for (const file of encFiles) {
41
+ try {
42
+ const filePath = join(options.cacheDir, file);
43
+ const fileStat = await stat(filePath);
44
+ totalSizeBytes += fileStat.size;
45
+ const mtime = fileStat.mtime;
46
+ if (!oldestEntry || mtime < oldestEntry)
47
+ oldestEntry = mtime;
48
+ if (!newestEntry || mtime > newestEntry)
49
+ newestEntry = mtime;
50
+ if (now - mtime.getTime() > staleThreshold) {
51
+ staleEntries++;
52
+ }
53
+ }
54
+ catch {
55
+ // Skip files that can't be stat'd
56
+ }
57
+ }
58
+ }
59
+ catch {
60
+ // Cache directory doesn't exist or can't be read
61
+ }
62
+ const circuitState = options.circuitBreaker.getState().state;
63
+ let telemetryQueueSize = 0;
64
+ try {
65
+ const queueStats = await options.telemetryQueue.getStats();
66
+ telemetryQueueSize = queueStats.count;
67
+ }
68
+ catch {
69
+ // Queue unavailable
70
+ }
71
+ return {
72
+ totalEntries,
73
+ totalSizeBytes,
74
+ totalSizeFormatted: formatBytes(totalSizeBytes),
75
+ oldestEntry,
76
+ newestEntry,
77
+ staleEntries,
78
+ circuitState,
79
+ lastSync: newestEntry, // Most recent cache write approximates last sync
80
+ telemetryQueueSize,
81
+ };
82
+ }
83
+ /**
84
+ * Format cache status as a human-readable string for terminal output.
85
+ */
86
+ export function formatCacheStatus(info) {
87
+ const lines = [
88
+ '+-------------------------------------------------+',
89
+ '| NEOCORTEX CACHE STATUS |',
90
+ '+-------------------------------------------------+',
91
+ `| Total entries: ${String(info.totalEntries).padEnd(29)}|`,
92
+ `| Total size: ${info.totalSizeFormatted.padEnd(29)}|`,
93
+ `| Oldest entry: ${(info.oldestEntry?.toISOString() ?? 'N/A').padEnd(29)}|`,
94
+ `| Newest entry: ${(info.newestEntry?.toISOString() ?? 'N/A').padEnd(29)}|`,
95
+ `| Stale entries: ${String(info.staleEntries).padEnd(29)}|`,
96
+ '|-------------------------------------------------|',
97
+ `| Circuit breaker: ${info.circuitState.padEnd(29)}|`,
98
+ `| Last sync: ${(info.lastSync?.toISOString() ?? 'N/A').padEnd(29)}|`,
99
+ `| Telemetry queue: ${(info.telemetryQueueSize + ' events').padEnd(29)}|`,
100
+ '+-------------------------------------------------+',
101
+ ];
102
+ return lines.join('\n');
103
+ }
104
+ // ── Helpers ─────────────────────────────────────────────────────────────
105
+ function formatBytes(bytes) {
106
+ if (bytes === 0)
107
+ return '0 B';
108
+ const units = ['B', 'KB', 'MB', 'GB'];
109
+ const i = Math.floor(Math.log(bytes) / Math.log(1024));
110
+ const value = bytes / Math.pow(1024, i);
111
+ return `${value.toFixed(i === 0 ? 0 : 1)} ${units[i]}`;
112
+ }
113
+ //# sourceMappingURL=cache-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-status.js","sourceRoot":"","sources":["../../src/commands/cache-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAyBjC,2EAA2E;AAE3E;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAA2B;IAC9D,MAAM,cAAc,GAAG,OAAO,CAAC,gBAAgB,IAAI,UAAU,CAAC,CAAC,cAAc;IAE7E,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,WAAW,GAAgB,IAAI,CAAC;IACpC,IAAI,WAAW,GAAgB,IAAI,CAAC;IAEpC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAC3D,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC;QAE/B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBAC9C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACtC,cAAc,IAAI,QAAQ,CAAC,IAAI,CAAC;gBAEhC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;gBAC7B,IAAI,CAAC,WAAW,IAAI,KAAK,GAAG,WAAW;oBAAE,WAAW,GAAG,KAAK,CAAC;gBAC7D,IAAI,CAAC,WAAW,IAAI,KAAK,GAAG,WAAW;oBAAE,WAAW,GAAG,KAAK,CAAC;gBAE7D,IAAI,GAAG,GAAG,KAAK,CAAC,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;oBAC3C,YAAY,EAAE,CAAC;gBACjB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,kCAAkC;YACpC,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,iDAAiD;IACnD,CAAC;IAED,MAAM,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC;IAE7D,IAAI,kBAAkB,GAAG,CAAC,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC;QAC3D,kBAAkB,GAAG,UAAU,CAAC,KAAK,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,oBAAoB;IACtB,CAAC;IAED,OAAO;QACL,YAAY;QACZ,cAAc;QACd,kBAAkB,EAAE,WAAW,CAAC,cAAc,CAAC;QAC/C,WAAW;QACX,WAAW;QACX,YAAY;QACZ,YAAY;QACZ,QAAQ,EAAE,WAAW,EAAE,iDAAiD;QACxE,kBAAkB;KACnB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAqB;IACrD,MAAM,KAAK,GAAa;QACtB,qDAAqD;QACrD,qDAAqD;QACrD,qDAAqD;QACrD,wBAAwB,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;QAC/D,wBAAwB,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;QAC7D,wBAAwB,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,IAAI,KAAK,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;QAChF,wBAAwB,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,IAAI,KAAK,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;QAChF,wBAAwB,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;QAC/D,qDAAqD;QACrD,wBAAwB,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;QACvD,wBAAwB,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,KAAK,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;QAC7E,wBAAwB,CAAC,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;QAC3E,qDAAqD;KACtD,CAAC;IAEF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,2EAA2E;AAE3E,SAAS,WAAW,CAAC,KAAa;IAChC,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9B,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACtC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACvD,MAAM,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACxC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AACzD,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 interface InvokeOptions {
14
+ /** Raw args from the user (e.g., "*yolo @docs/stories/1.1.story.md") */
15
+ readonly args: string;
16
+ /** Project root directory (default: cwd) */
17
+ readonly projectRoot?: string;
18
+ /** Output format: 'json' for full response, 'plain' for instructions only */
19
+ readonly format?: 'json' | 'plain';
20
+ /** Server URL override */
21
+ readonly serverUrl?: string;
22
+ /** Platform target (default: 'claude-code') */
23
+ readonly platformTarget?: string;
24
+ }
25
+ export interface InvokeResult {
26
+ readonly success: boolean;
27
+ readonly instructions?: string;
28
+ readonly metadata?: Record<string, unknown>;
29
+ readonly error?: string;
30
+ readonly exitCode: number;
31
+ }
32
+ interface StateSnapshot {
33
+ readonly config: {
34
+ readonly project_name: string;
35
+ readonly default_branch: string;
36
+ readonly language: string;
37
+ readonly yolo_mode?: boolean;
38
+ readonly user_name?: string;
39
+ readonly worktree_base?: string;
40
+ readonly max_parallel_stories?: number;
41
+ };
42
+ readonly stories: Record<string, Record<string, unknown>>;
43
+ readonly epics: Record<string, Record<string, unknown>>;
44
+ }
45
+ /**
46
+ * Read state.json and construct a sanitized snapshot for the server.
47
+ * Relative paths only - no absolute paths sent to server.
48
+ */
49
+ export declare function collectStateSnapshot(projectRoot: string): StateSnapshot;
50
+ /**
51
+ * Execute the invoke command.
52
+ *
53
+ * Flow:
54
+ * 1. Load config to get server URL
55
+ * 2. Collect state snapshot from project root
56
+ * 3. Check menu cache for empty invocations
57
+ * 4. Send POST /api/v1/invoke
58
+ * 5. Format and return result
59
+ */
60
+ export declare function invoke(options: InvokeOptions): Promise<InvokeResult>;
61
+ /**
62
+ * CLI handler for the invoke command.
63
+ * Parses CLI args and delegates to invoke().
64
+ *
65
+ * Usage:
66
+ * neocortex-client invoke --args "*yolo @story.md" --project-root /path
67
+ * neocortex-client invoke --args "*status" --format json
68
+ */
69
+ export declare function invokeCliHandler(argv: string[]): Promise<number>;
70
+ export {};
71
+ //# sourceMappingURL=invoke.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoke.d.ts","sourceRoot":"","sources":["../../src/commands/invoke.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA+BH,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACnC,0BAA0B;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,+CAA+C;IAC/C,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,UAAU,aAAa;IACrB,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;QAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;QAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;QAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAChC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;KACxC,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACzD;AAqBD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,CAiFvE;AA8HD;;;;;;;;;GASG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAwE1E;AAID;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAkDtE"}