@ornexus/neocortex 4.59.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/LICENSE +56 -0
- package/LICENSE-COMMERCIAL.md +70 -0
- package/README.md +58 -0
- package/dist/sbom.cdx.json +7067 -0
- package/docs/install/coderabbit-manual-setup.md +86 -0
- package/docs/install/installer-diagnostics.md +107 -0
- package/docs/install/linux-global-install.md +97 -0
- package/install.js +572 -0
- package/install.ps1 +2214 -0
- package/install.sh +2013 -0
- package/package.json +118 -0
- package/packages/client/dist/adapters/adapter-registry.d.ts +61 -0
- package/packages/client/dist/adapters/adapter-registry.js +1 -0
- package/packages/client/dist/adapters/antigravity-adapter.d.ts +18 -0
- package/packages/client/dist/adapters/antigravity-adapter.js +2 -0
- package/packages/client/dist/adapters/claude-code-adapter.d.ts +19 -0
- package/packages/client/dist/adapters/claude-code-adapter.js +3 -0
- package/packages/client/dist/adapters/codex-adapter.d.ts +19 -0
- package/packages/client/dist/adapters/codex-adapter.js +2 -0
- package/packages/client/dist/adapters/cursor-adapter.d.ts +19 -0
- package/packages/client/dist/adapters/cursor-adapter.js +4 -0
- package/packages/client/dist/adapters/gemini-adapter.d.ts +18 -0
- package/packages/client/dist/adapters/gemini-adapter.js +2 -0
- package/packages/client/dist/adapters/index.d.ts +19 -0
- package/packages/client/dist/adapters/index.js +1 -0
- package/packages/client/dist/adapters/platform-detector.d.ts +48 -0
- package/packages/client/dist/adapters/platform-detector.js +1 -0
- package/packages/client/dist/adapters/target-adapter.d.ts +70 -0
- package/packages/client/dist/adapters/target-adapter.js +0 -0
- package/packages/client/dist/adapters/vscode-adapter.d.ts +19 -0
- package/packages/client/dist/adapters/vscode-adapter.js +2 -0
- package/packages/client/dist/agent/refresh-stubs.d.ts +80 -0
- package/packages/client/dist/agent/refresh-stubs.js +2 -0
- package/packages/client/dist/agent/update-agent-yaml.d.ts +26 -0
- package/packages/client/dist/agent/update-agent-yaml.js +1 -0
- package/packages/client/dist/agent/update-description.d.ts +45 -0
- package/packages/client/dist/agent/update-description.js +1 -0
- package/packages/client/dist/cache/crypto-utils.d.ts +30 -0
- package/packages/client/dist/cache/crypto-utils.js +1 -0
- package/packages/client/dist/cache/encrypted-cache.d.ts +30 -0
- package/packages/client/dist/cache/encrypted-cache.js +1 -0
- package/packages/client/dist/cache/in-memory-asset-cache.d.ts +62 -0
- package/packages/client/dist/cache/in-memory-asset-cache.js +1 -0
- package/packages/client/dist/cache/index.d.ts +13 -0
- package/packages/client/dist/cache/index.js +1 -0
- package/packages/client/dist/cache/protected-pi-boundary.d.ts +19 -0
- package/packages/client/dist/cache/protected-pi-boundary.js +1 -0
- package/packages/client/dist/checkpoint/checkpoint-client-reader.d.ts +45 -0
- package/packages/client/dist/checkpoint/checkpoint-client-reader.js +2 -0
- package/packages/client/dist/checkpoint/index.d.ts +12 -0
- package/packages/client/dist/checkpoint/index.js +1 -0
- package/packages/client/dist/checkpoint/shared-checkpoint-types.d.ts +85 -0
- package/packages/client/dist/checkpoint/shared-checkpoint-types.js +1 -0
- package/packages/client/dist/cli.d.ts +14 -0
- package/packages/client/dist/cli.js +48 -0
- package/packages/client/dist/commands/activate.d.ts +55 -0
- package/packages/client/dist/commands/activate.js +8 -0
- package/packages/client/dist/commands/cache-status.d.ts +39 -0
- package/packages/client/dist/commands/cache-status.js +2 -0
- package/packages/client/dist/commands/invoke.d.ts +229 -0
- package/packages/client/dist/commands/invoke.js +63 -0
- package/packages/client/dist/commands/refresh-memory.d.ts +11 -0
- package/packages/client/dist/commands/refresh-memory.js +1 -0
- package/packages/client/dist/config/resolver-selection.d.ts +40 -0
- package/packages/client/dist/config/resolver-selection.js +1 -0
- package/packages/client/dist/config/secure-config.d.ts +78 -0
- package/packages/client/dist/config/secure-config.js +12 -0
- package/packages/client/dist/constants.d.ts +25 -0
- package/packages/client/dist/constants.js +1 -0
- package/packages/client/dist/context/context-collector.d.ts +28 -0
- package/packages/client/dist/context/context-collector.js +2 -0
- package/packages/client/dist/context/context-sanitizer.d.ts +28 -0
- package/packages/client/dist/context/context-sanitizer.js +1 -0
- package/packages/client/dist/continuity/continuity-client-state-store.d.ts +183 -0
- package/packages/client/dist/continuity/continuity-client-state-store.js +1 -0
- package/packages/client/dist/continuity/invoke-hooks.d.ts +18 -0
- package/packages/client/dist/continuity/invoke-hooks.js +1 -0
- package/packages/client/dist/continuity/migrations/001-initial-schema.d.ts +11 -0
- package/packages/client/dist/continuity/migrations/001-initial-schema.js +263 -0
- package/packages/client/dist/continuity/sqlite-store.d.ts +409 -0
- package/packages/client/dist/continuity/sqlite-store.js +226 -0
- package/packages/client/dist/errors/error-messages.d.ts +40 -0
- package/packages/client/dist/errors/error-messages.js +2 -0
- package/packages/client/dist/graph-retrieval/pre-command-hook.d.ts +31 -0
- package/packages/client/dist/graph-retrieval/pre-command-hook.js +1 -0
- package/packages/client/dist/graph-retrieval/shared-graph-retrieval-contract.d.ts +77 -0
- package/packages/client/dist/graph-retrieval/shared-graph-retrieval-contract.js +1 -0
- package/packages/client/dist/i18n/first-run.d.ts +23 -0
- package/packages/client/dist/i18n/first-run.js +2 -0
- package/packages/client/dist/index.d.ts +56 -0
- package/packages/client/dist/index.js +1 -0
- package/packages/client/dist/license/index.d.ts +5 -0
- package/packages/client/dist/license/index.js +1 -0
- package/packages/client/dist/license/license-client.d.ts +79 -0
- package/packages/client/dist/license/license-client.js +1 -0
- package/packages/client/dist/machine/fingerprint.d.ts +34 -0
- package/packages/client/dist/machine/fingerprint.js +2 -0
- package/packages/client/dist/machine/index.d.ts +5 -0
- package/packages/client/dist/machine/index.js +1 -0
- package/packages/client/dist/memory/project-memory-writer.d.ts +74 -0
- package/packages/client/dist/memory/project-memory-writer.js +36 -0
- package/packages/client/dist/memory/shared-project-memory-types.d.ts +370 -0
- package/packages/client/dist/memory/shared-project-memory-types.js +2 -0
- package/packages/client/dist/policy/architecture-policy.d.ts +40 -0
- package/packages/client/dist/policy/architecture-policy.js +2 -0
- package/packages/client/dist/policy/index.d.ts +8 -0
- package/packages/client/dist/policy/index.js +1 -0
- package/packages/client/dist/policy/shared-policy-types.d.ts +89 -0
- package/packages/client/dist/policy/shared-policy-types.js +0 -0
- package/packages/client/dist/resilience/circuit-breaker.d.ts +70 -0
- package/packages/client/dist/resilience/circuit-breaker.js +1 -0
- package/packages/client/dist/resilience/degradation-manager.d.ts +67 -0
- package/packages/client/dist/resilience/degradation-manager.js +1 -0
- package/packages/client/dist/resilience/freshness-indicator.d.ts +59 -0
- package/packages/client/dist/resilience/freshness-indicator.js +1 -0
- package/packages/client/dist/resilience/index.d.ts +8 -0
- package/packages/client/dist/resilience/index.js +1 -0
- package/packages/client/dist/resilience/recovery-detector.d.ts +59 -0
- package/packages/client/dist/resilience/recovery-detector.js +1 -0
- package/packages/client/dist/resolvers/asset-resolver.d.ts +79 -0
- package/packages/client/dist/resolvers/asset-resolver.js +0 -0
- package/packages/client/dist/resolvers/local-resolver.d.ts +26 -0
- package/packages/client/dist/resolvers/local-resolver.js +8 -0
- package/packages/client/dist/resolvers/remote-resolver.d.ts +91 -0
- package/packages/client/dist/resolvers/remote-resolver.js +1 -0
- package/packages/client/dist/runner/cli.d.ts +121 -0
- package/packages/client/dist/runner/cli.js +20 -0
- package/packages/client/dist/runner/scheduler.d.ts +116 -0
- package/packages/client/dist/runner/scheduler.js +6 -0
- package/packages/client/dist/runner-cli.d.ts +9 -0
- package/packages/client/dist/runner-cli.js +3 -0
- package/packages/client/dist/state/project-state-snapshot.d.ts +15 -0
- package/packages/client/dist/state/project-state-snapshot.js +1 -0
- package/packages/client/dist/state/state-json-repair.d.ts +17 -0
- package/packages/client/dist/state/state-json-repair.js +3 -0
- package/packages/client/dist/telemetry/index.d.ts +5 -0
- package/packages/client/dist/telemetry/index.js +1 -0
- package/packages/client/dist/telemetry/offline-queue.d.ts +57 -0
- package/packages/client/dist/telemetry/offline-queue.js +1 -0
- package/packages/client/dist/tier/index.d.ts +5 -0
- package/packages/client/dist/tier/index.js +1 -0
- package/packages/client/dist/tier/tier-aware-client.d.ts +105 -0
- package/packages/client/dist/tier/tier-aware-client.js +1 -0
- package/packages/client/dist/types/index.d.ts +140 -0
- package/packages/client/dist/types/index.js +1 -0
- package/packages/client/dist/yoloop/discovery-hook.d.ts +85 -0
- package/packages/client/dist/yoloop/discovery-hook.js +2 -0
- package/packages/client/dist/yoloop/index.d.ts +10 -0
- package/packages/client/dist/yoloop/index.js +1 -0
- package/packages/client/dist/yoloop/invoke-hooks.d.ts +125 -0
- package/packages/client/dist/yoloop/invoke-hooks.js +5 -0
- package/packages/client/dist/yoloop/shared-discover-epics.d.ts +289 -0
- package/packages/client/dist/yoloop/shared-discover-epics.js +1 -0
- package/packages/client/dist/yoloop/shared-yoloop-types.d.ts +172 -0
- package/packages/client/dist/yoloop/shared-yoloop-types.js +1 -0
- package/packages/client/dist/yoloop/yoloop-client-state-store.d.ts +124 -0
- package/packages/client/dist/yoloop/yoloop-client-state-store.js +1 -0
- package/postinstall.js +754 -0
- package/targets-stubs/antigravity/README.md +36 -0
- package/targets-stubs/antigravity/gemini.md +29 -0
- package/targets-stubs/antigravity/install-antigravity.sh +153 -0
- package/targets-stubs/antigravity/mcp-config.json +30 -0
- package/targets-stubs/antigravity/skill/SKILL.md +159 -0
- package/targets-stubs/claude-code/.mcp.json +32 -0
- package/targets-stubs/claude-code/README.md +20 -0
- package/targets-stubs/claude-code/neocortex-root.agent.yaml +42 -0
- package/targets-stubs/claude-code/neocortex-root.md +310 -0
- package/targets-stubs/claude-code/neocortex.agent.yaml +42 -0
- package/targets-stubs/claude-code/neocortex.md +378 -0
- package/targets-stubs/codex/AGENTS.md +244 -0
- package/targets-stubs/codex/README.md +47 -0
- package/targets-stubs/codex/config-mcp.toml +22 -0
- package/targets-stubs/codex/install-codex.sh +63 -0
- package/targets-stubs/codex/neocortex.toml +29 -0
- package/targets-stubs/cursor/README.md +33 -0
- package/targets-stubs/cursor/agent.md +204 -0
- package/targets-stubs/cursor/install-cursor.sh +50 -0
- package/targets-stubs/cursor/mcp.json +30 -0
- package/targets-stubs/gemini-cli/README.md +34 -0
- package/targets-stubs/gemini-cli/agent.md +234 -0
- package/targets-stubs/gemini-cli/agents/neocortex.md +54 -0
- package/targets-stubs/gemini-cli/gemini.md +46 -0
- package/targets-stubs/gemini-cli/install-gemini.sh +70 -0
- package/targets-stubs/gemini-cli/settings-mcp.json +30 -0
- package/targets-stubs/kimi/mcp.json +33 -0
- package/targets-stubs/kimi/neocortex.md +54 -0
- package/targets-stubs/lib/mcp-merge.js +189 -0
- package/targets-stubs/openclaw/README.md +12 -0
- package/targets-stubs/openclaw/SKILL.md +88 -0
- package/targets-stubs/opencode/neocortex-root.md +261 -0
- package/targets-stubs/opencode/neocortex.md +59 -0
- package/targets-stubs/opencode/opencode-mcp.json +35 -0
- package/targets-stubs/vscode/README.md +34 -0
- package/targets-stubs/vscode/copilot-instructions.md +47 -0
- package/targets-stubs/vscode/install-vscode.sh +72 -0
- package/targets-stubs/vscode/mcp.json +36 -0
- package/targets-stubs/vscode/neocortex.agent.md +245 -0
|
@@ -0,0 +1,45 @@
|
|
|
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
|
+
* Build the banner version line with correct padding.
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildBannerVersionLine(version: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Build the banner tier line with correct padding.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildBannerTierLine(tier: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Build the dynamic description string (without quotes/prefix).
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildDescription(version: string, tier: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Read the current tier from ~/.neocortex/config.json.
|
|
27
|
+
* Returns 'free' if config doesn't exist or tier is missing.
|
|
28
|
+
*/
|
|
29
|
+
export declare function readTierFromConfig(): string;
|
|
30
|
+
/**
|
|
31
|
+
* Update agent descriptions across ALL known platform files:
|
|
32
|
+
* 1. Home-level files (Claude Code, Gemini CLI)
|
|
33
|
+
* 2. Project-level files (Cursor, VSCode, Codex, Antigravity) -- discovered via git root
|
|
34
|
+
*
|
|
35
|
+
* Never throws -- description update is non-critical.
|
|
36
|
+
* Returns count of files updated.
|
|
37
|
+
*/
|
|
38
|
+
export declare function updateAgentDescription(version: string, tier?: string): number;
|
|
39
|
+
/**
|
|
40
|
+
* Update agent description for a specific file path (used by install scripts
|
|
41
|
+
* for project-level files where paths are dynamic).
|
|
42
|
+
*
|
|
43
|
+
* Never throws -- description update is non-critical.
|
|
44
|
+
*/
|
|
45
|
+
export declare function updateAgentDescriptionAt(filePath: string, type: 'yaml' | 'h1', version: string, tier?: string): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{readFileSync as l,writeFileSync as _,existsSync as f}from"node:fs";import{execSync as A}from"node:child_process";import{join as c}from"node:path";import{homedir as p}from"node:os";const m=c(p(),".neocortex","config.json"),d={free:"Free",pro:"Pro",enterprise:"Enterprise"},I=60,L=25,N=/^description:\s*".*"$/m,E=/^# 🧠 Neocortex v[\d.]+(?:\s*\([^)]+\)\s*\| OrNexus Team|\s*-\s*Development Orchestrator \| OrNexus Team \([^)]+\))$/m,T=/^│ ### ######## v[\d.]+\s*│$/m,x=/^│ ## ### ###### ## OrNexus Team \([^)]*\)\s*│$/m,P=[{path:c(p(),".claude","agents","neocortex","neocortex.md"),type:"yaml"},{path:c(p(),".gemini","agents","agent.md"),type:"yaml"}],F=[{relativePath:c(".cursor","agents","neocortex.md"),type:"yaml"},{relativePath:c(".github","agents","neocortex.md"),type:"yaml"},{relativePath:"AGENTS.md",type:"h1"},{relativePath:c(".agent","skills","neocortex","SKILL.md"),type:"yaml"}];function O(){try{return A("git rev-parse --show-toplevel",{encoding:"utf-8",timeout:5e3,stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}}function y(e,o){const t=I-L-o.length,r=t>0?" ".repeat(t):"";return`${e}${o}${r}\u2502`}function S(e){return y("\u2502 ### ######## ",`v${e}`)}function $(e){const o=d[e.toLowerCase()]??"Free";return y("\u2502 ## ### ###### ## ",`OrNexus Team (${o})`)}function g(e,o){const t=d[o.toLowerCase()]??"Free";return`\u{1F9E0} Neocortex v${e} (${t}) | OrNexus Team`}function R(){try{if(f(m)){const e=l(m,"utf-8");return JSON.parse(e).tier??"free"}}catch{}return"free"}function v(e,o,t){let r=e;return T.test(r)&&(r=r.replace(T,S(o))),x.test(r)&&(r=r.replace(x,$(t))),r}function u(e,o,t,r,i){try{if(!f(e))return!1;let n=l(e,"utf-8");const s=n;return o==="yaml"?N.test(n)&&(n=n.replace(N,`description: "${t}"`)):E.test(n)&&(n=n.replace(E,`# ${t}`)),n=v(n,r,i),n===s?!1:(_(e,n,"utf-8"),!0)}catch{return!1}}function w(e,o){const t=o??R(),r=g(e,t);let i=0;for(const{path:s,type:a}of P)u(s,a,r,e,t)&&i++;const n=O();if(n)for(const{relativePath:s,type:a}of F){const h=c(n,s);u(h,a,r,e,t)&&i++}return i}function j(e,o,t,r){const i=r??R(),n=g(t,i);return u(e,o,n,t,i)}export{$ as buildBannerTierLine,S as buildBannerVersionLine,g as buildDescription,R as readTierFromConfig,w as updateAgentDescription,j as updateAgentDescriptionAt};
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
/** On-disk envelope format. expiresAt is inside the encrypted data payload. */
|
|
14
|
+
export interface EncryptedEnvelope {
|
|
15
|
+
/** Base64-encoded initialization vector (12 bytes) */
|
|
16
|
+
iv: string;
|
|
17
|
+
/** Base64-encoded PBKDF2 salt */
|
|
18
|
+
salt: string;
|
|
19
|
+
/** Base64-encoded GCM auth tag */
|
|
20
|
+
tag: string;
|
|
21
|
+
/** Base64-encoded encrypted data (contains plaintext + expiresAt) */
|
|
22
|
+
data: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function deriveKey(passphrase: string, salt: Buffer): Buffer;
|
|
25
|
+
export declare function encrypt(plaintext: string, passphrase: string, ttlMs?: number): string;
|
|
26
|
+
export interface DecryptResult {
|
|
27
|
+
plaintext: string;
|
|
28
|
+
expired: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare function decrypt(envelopeJson: string, passphrase: string): DecryptResult;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{randomBytes as d,pbkdf2Sync as h,createCipheriv as S,createDecipheriv as m}from"node:crypto";import{assertPublicSafeCachePayload as v}from"./protected-pi-boundary.js";const l="aes-256-gcm",b=12,A=32,B=32,g=16,N=1e5,x="sha512";function y(e,n){return h(e,n,N,B,x)}function _(e,n,t){v(e);const s=d(b),c=d(A),i=y(n,c),f=t!=null?Date.now()+t:null,a=JSON.stringify({plaintext:e,expiresAt:f}),o=S(l,i,s,{authTagLength:g}),r=Buffer.concat([o.update(a,"utf8"),o.final()]),p=o.getAuthTag(),T={iv:s.toString("base64"),salt:c.toString("base64"),tag:p.toString("base64"),data:r.toString("base64")};return JSON.stringify(T)}function G(e,n){const t=JSON.parse(e);if(!t.iv||!t.salt||!t.tag||!t.data)throw new Error("Invalid cache envelope: missing required fields");const s=Buffer.from(t.iv,"base64"),c=Buffer.from(t.salt,"base64"),i=Buffer.from(t.tag,"base64"),f=Buffer.from(t.data,"base64"),u=y(n,c),a=m(l,u,s,{authTagLength:g});a.setAuthTag(i);const o=Buffer.concat([a.update(f),a.final()]),r=JSON.parse(o.toString("utf8")),p=r.expiresAt!=null&&Date.now()>r.expiresAt;return{plaintext:r.plaintext,expired:p}}export{G as decrypt,y as deriveKey,_ as encrypt};
|
|
@@ -0,0 +1,30 @@
|
|
|
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 { CacheProvider } from '../types/index.js';
|
|
14
|
+
export interface EncryptedCacheOptions {
|
|
15
|
+
/** Directory where encrypted cache files are stored */
|
|
16
|
+
cacheDir: string;
|
|
17
|
+
/** Passphrase for encryption (typically the license key) */
|
|
18
|
+
passphrase: string;
|
|
19
|
+
}
|
|
20
|
+
export declare class EncryptedCache implements CacheProvider {
|
|
21
|
+
private readonly cacheDir;
|
|
22
|
+
private readonly passphrase;
|
|
23
|
+
private initPromise;
|
|
24
|
+
constructor(options: EncryptedCacheOptions);
|
|
25
|
+
get(key: string): Promise<string | null>;
|
|
26
|
+
set(key: string, value: string, ttlMs?: number): Promise<void>;
|
|
27
|
+
clear(): Promise<void>;
|
|
28
|
+
private keyToPath;
|
|
29
|
+
private ensureDir;
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{mkdir as n,writeFile as o,readFile as p,rm as s,readdir as m}from"node:fs/promises";import{join as a}from"node:path";import{createHash as u}from"node:crypto";import{encrypt as l,decrypt as f}from"./crypto-utils.js";import{setSecureFilePermissions as d}from"../config/secure-config.js";import{hasProtectedCachePayloadMarker as y}from"./protected-pi-boundary.js";const c=".enc";class F{cacheDir;passphrase;initPromise=null;constructor(t){this.cacheDir=t.cacheDir,this.passphrase=t.passphrase}async get(t){try{const r=this.keyToPath(t),e=await p(r,"utf8"),i=f(e,this.passphrase);return i.expired?(s(r,{force:!0}).catch(()=>{}),null):i.plaintext}catch{return null}}async set(t,r,e){try{if(y(r))return;await this.ensureDir();const i=this.keyToPath(t),h=l(r,this.passphrase,e);await o(i,h,"utf8"),d(i)}catch{}}async clear(){try{const r=(await m(this.cacheDir).catch(()=>[])).filter(e=>e.endsWith(c)).map(e=>s(a(this.cacheDir,e),{force:!0}).catch(()=>{}));await Promise.all(r)}catch{}}keyToPath(t){const r=u("sha256").update(t).digest("hex");return a(this.cacheDir,`${r}${c}`)}ensureDir(){return this.initPromise||(this.initPromise=n(this.cacheDir,{recursive:!0}).then(()=>{}).catch(t=>{throw this.initPromise=null,t})),this.initPromise}}export{F as EncryptedCache};
|
|
@@ -0,0 +1,62 @@
|
|
|
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
|
+
* InMemoryAssetCache - volatile LRU cache for asset content (Epic P70.06).
|
|
15
|
+
*
|
|
16
|
+
* Purpose: protect IP assets (step/skill/standard prompt content) from being
|
|
17
|
+
* persisted to the client filesystem. Unlike `EncryptedCache`, entries here
|
|
18
|
+
* live ONLY in the running process memory and are discarded on exit.
|
|
19
|
+
*
|
|
20
|
+
* Implements the {@link CacheProvider} interface so it can be drop-in
|
|
21
|
+
* substituted for `EncryptedCache` when resolving asset content, while
|
|
22
|
+
* `EncryptedCache` remains in use for JWTs and the menu cache.
|
|
23
|
+
*
|
|
24
|
+
* Configuration:
|
|
25
|
+
* - `maxSize` entries (default 50) -- small bound keeps memory flat even
|
|
26
|
+
* under heavy use.
|
|
27
|
+
* - `ttlMs` milliseconds (default 5 min) -- defense-in-depth against stale
|
|
28
|
+
* assets being reused after the server updates its version.
|
|
29
|
+
* - Never writes to disk, never throws.
|
|
30
|
+
* - P176.05: bounded volatile cache only; synthetic protected PI markers are
|
|
31
|
+
* rejected so tests cannot turn it into a public distribution path. Exact
|
|
32
|
+
* production asset TTL policy beyond the default remains [TBD].
|
|
33
|
+
*/
|
|
34
|
+
import type { CacheProvider } from '../types/index.js';
|
|
35
|
+
export interface InMemoryAssetCacheOptions {
|
|
36
|
+
/** Maximum number of entries before eviction (default: 50) */
|
|
37
|
+
readonly maxSize?: number;
|
|
38
|
+
/** Time-to-live in ms (default: 5 minutes) */
|
|
39
|
+
readonly ttlMs?: number;
|
|
40
|
+
}
|
|
41
|
+
export declare class InMemoryAssetCache implements CacheProvider {
|
|
42
|
+
private readonly store;
|
|
43
|
+
private readonly maxSize;
|
|
44
|
+
private readonly ttlMs;
|
|
45
|
+
constructor(options?: InMemoryAssetCacheOptions);
|
|
46
|
+
/**
|
|
47
|
+
* Retrieve a value by key. Returns null if missing or expired.
|
|
48
|
+
* Accessing a key moves it to the end of the LRU ordering.
|
|
49
|
+
*/
|
|
50
|
+
get(key: string): Promise<string | null>;
|
|
51
|
+
/**
|
|
52
|
+
* Store a value by key. Evicts the least-recently-used entry if the
|
|
53
|
+
* cache is at capacity.
|
|
54
|
+
*
|
|
55
|
+
* @param ttlMs - optional override of the default TTL
|
|
56
|
+
*/
|
|
57
|
+
set(key: string, value: string, ttlMs?: number): Promise<void>;
|
|
58
|
+
/** Drop all entries. Safe to call at any time. */
|
|
59
|
+
clear(): Promise<void>;
|
|
60
|
+
/** Internal: number of live entries (for diagnostics / tests). */
|
|
61
|
+
size(): number;
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{hasProtectedCachePayloadMarker as n}from"./protected-pi-boundary.js";const a=50,h=300*1e3;class u{store=new Map;maxSize;ttlMs;constructor(t={}){this.maxSize=t.maxSize??a,this.ttlMs=t.ttlMs??h}async get(t){const e=this.store.get(t);return e?Date.now()>=e.expiresAt?(this.store.delete(t),null):(this.store.delete(t),this.store.set(t,e),e.value):null}async set(t,e,r){if(n(e))return;const i=r??this.ttlMs,o=Date.now()+i;if(this.store.has(t))this.store.delete(t);else if(this.store.size>=this.maxSize){const s=this.store.keys().next().value;s!==void 0&&this.store.delete(s)}this.store.set(t,{value:e,expiresAt:o})}async clear(){this.store.clear()}size(){return this.store.size}}export{u as InMemoryAssetCache};
|
|
@@ -0,0 +1,13 @@
|
|
|
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 { EncryptedCache, type EncryptedCacheOptions } from './encrypted-cache.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{EncryptedCache as c}from"./encrypted-cache.js";export{c as EncryptedCache};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license FSL-1.1
|
|
3
|
+
* Copyright (c) 2026 OrNexus AI
|
|
4
|
+
*
|
|
5
|
+
* Public-safe client cache PI boundary checks.
|
|
6
|
+
*/
|
|
7
|
+
/** Public reason code used when a synthetic protected PI marker is detected. */
|
|
8
|
+
export declare const PROTECTED_CACHE_PAYLOAD_REASON = "protected-cache-payload-rejected";
|
|
9
|
+
/**
|
|
10
|
+
* Returns true only for synthetic protected markers or explicit protected field
|
|
11
|
+
* names. Generic words like "prompt" or "workflow" are intentionally not
|
|
12
|
+
* rejected because cache keys and README-grade metadata may use them safely.
|
|
13
|
+
*/
|
|
14
|
+
export declare function hasProtectedCachePayloadMarker(value: string): boolean;
|
|
15
|
+
export declare class ProtectedCachePayloadError extends Error {
|
|
16
|
+
readonly code = "protected-cache-payload-rejected";
|
|
17
|
+
constructor();
|
|
18
|
+
}
|
|
19
|
+
export declare function assertPublicSafeCachePayload(value: string): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const t="protected-cache-payload-rejected",a=/P176_SYNTHETIC_PROTECTED_(?:PROMPT|PROMPT_BODY|WORKFLOW|WORKFLOW_GRAPH|STEP_BODY|RAW_LOG|PRIVATE_URL|SECRET|PROPRIETARY_ASSET)/i,n=/^(?:promptBody|workflowBody|workflowGraph|stepBody|privateUrl|rawLog|secret|credential|licenseKey|apiKey|internalRouting|serverOnly|proprietary|protected)$/i;function r(e){return!e||typeof e!="object"?!1:Array.isArray(e)?e.some(r):Object.entries(e).some(([o,c])=>n.test(o)||r(c))}function s(e){if(a.test(e))return!0;try{return r(JSON.parse(e))}catch{return!1}}class E extends Error{code=t;constructor(){super(t),this.name="ProtectedCachePayloadError"}}function P(e){if(s(e))throw new E}export{t as PROTECTED_CACHE_PAYLOAD_REASON,E as ProtectedCachePayloadError,P as assertPublicSafeCachePayload,s as hasProtectedCachePayloadMarker};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Epic P109.05: Checkpoint client-side reader (fail-soft).
|
|
3
|
+
*
|
|
4
|
+
* Reads `.neocortex/checkpoint-pending.json` (written by agent per P109.04
|
|
5
|
+
* step prompt instructions), validates shape against ImplementCheckpointSnapshot
|
|
6
|
+
* (P109.02), and consumes (deletes) the file to prevent re-send.
|
|
7
|
+
*
|
|
8
|
+
* Cross-refs: P107.02 (architecture-policy reader pattern), P101.06 (atomic
|
|
9
|
+
* file ops), P63.01 (UTF-8 BOM strip), P103.06 (CRLF normalize).
|
|
10
|
+
*/
|
|
11
|
+
import type { ImplementCheckpointSnapshot } from './shared-checkpoint-types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Canonical pending-checkpoint path (relative to projectRoot).
|
|
14
|
+
* Matches P109.04 step prompt instruction literal.
|
|
15
|
+
*/
|
|
16
|
+
export declare const CHECKPOINT_PENDING_PATH = ".neocortex/checkpoint-pending.json";
|
|
17
|
+
export interface ValidationResult {
|
|
18
|
+
readonly valid: boolean;
|
|
19
|
+
readonly errors: readonly string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Pure validation (zero I/O). Deterministic.
|
|
23
|
+
*
|
|
24
|
+
* Checks all required fields of ImplementCheckpointSnapshot shape. Extra fields
|
|
25
|
+
* are ignored (forward-compat). Does NOT enforce MAX_SNAPSHOT_SIZE_BYTES on
|
|
26
|
+
* snapshotMd length -- that is the reader's responsibility and server's
|
|
27
|
+
* final truncation (P109.06).
|
|
28
|
+
*/
|
|
29
|
+
export declare function validateSnapshot(candidate: unknown): ValidationResult;
|
|
30
|
+
/**
|
|
31
|
+
* Read + validate + consume (delete) the pending checkpoint file.
|
|
32
|
+
*
|
|
33
|
+
* Fail-soft contract:
|
|
34
|
+
* - ENOENT (common case -- no checkpoint pending) -> undefined, silent.
|
|
35
|
+
* - Any other read error -> undefined + console.warn.
|
|
36
|
+
* - Malformed JSON or schema invalid -> undefined + console.warn.
|
|
37
|
+
* - Oversized file -> undefined + console.warn.
|
|
38
|
+
* - Unlink failure -> caller still receives snapshot; warn logged.
|
|
39
|
+
*
|
|
40
|
+
* **File consume is critical (AC4)**: after first successful read (regardless
|
|
41
|
+
* of validation outcome), the file is deleted to prevent re-send on next
|
|
42
|
+
* invoke. This avoids infinite checkpoint-loop scenarios from malformed
|
|
43
|
+
* agent-produced content.
|
|
44
|
+
*/
|
|
45
|
+
export declare function readAndConsumeCheckpoint(projectRoot: string): Promise<ImplementCheckpointSnapshot | undefined>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{promises as c}from"node:fs";import f from"node:path";import{MAX_SNAPSHOT_SIZE_BYTES as d}from"./shared-checkpoint-types.js";const u=".neocortex/checkpoint-pending.json",p=1e4,a=["FASE_1","FASE_2","FASE_3","FASE_4"];function l(o){if(o===null||typeof o!="object")return{valid:!1,errors:["payload must be object"]};const e=o,t=[];return(typeof e.storyId!="string"||e.storyId.length===0)&&t.push("storyId must be non-empty string"),(typeof e.turn!="number"||!Number.isFinite(e.turn)||e.turn<0)&&t.push("turn must be non-negative finite number"),(!Array.isArray(e.filesModified)||!e.filesModified.every(n=>typeof n=="string"))&&t.push("filesModified must be string[]"),(!Array.isArray(e.testsModified)||!e.testsModified.every(n=>typeof n=="string"))&&t.push("testsModified must be string[]"),(typeof e.currentPhase!="string"||!a.includes(e.currentPhase))&&t.push(`currentPhase must be one of ${a.join("|")}`),typeof e.snapshotMd!="string"&&t.push("snapshotMd must be string"),{valid:t.length===0,errors:Object.freeze(t)}}async function y(o){const e=f.join(o,u);let t;try{t=await c.readFile(e,"utf-8")}catch(r){if(r.code==="ENOENT")return;console.warn(`[Neocortex] checkpoint read failed: ${r instanceof Error?r.message:String(r)}`);return}c.unlink(e).catch(r=>{console.warn(`[Neocortex] checkpoint unlink failed: ${r instanceof Error?r.message:String(r)}`)});const n=t.replace(/^/,"").replace(/\r\n/g,`
|
|
2
|
+
`);if(n.length>d+p){console.warn(`[Neocortex] checkpoint oversized (${n.length} bytes), skipping`);return}let s;try{s=JSON.parse(n)}catch(r){console.warn(`[Neocortex] checkpoint malformed JSON: ${r instanceof Error?r.message:String(r)}`);return}const i=l(s);if(!i.valid){console.warn(`[Neocortex] checkpoint schema invalid: ${i.errors.join("; ")}`);return}return s}export{u as CHECKPOINT_PENDING_PATH,y as readAndConsumeCheckpoint,l as validateSnapshot};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Epic P109.05: Checkpoint client-side module barrel.
|
|
3
|
+
*
|
|
4
|
+
* Exports the fail-soft reader + validator + canonical path const.
|
|
5
|
+
* Re-exports wire-format types from local SSoT-Shadow inline (P117.01) so
|
|
6
|
+
* the published client tarball never references `@neocortex/shared` at
|
|
7
|
+
* runtime. Type identity stays in sync with `@neocortex/shared` via
|
|
8
|
+
* `checkpoint-shared-sync.test.ts` drift test.
|
|
9
|
+
*/
|
|
10
|
+
export * from './checkpoint-client-reader.js';
|
|
11
|
+
export type { ImplementCheckpoint, ImplementCheckpointSnapshot, CheckpointPhase, CheckpointResumeContext, } from './shared-checkpoint-types.js';
|
|
12
|
+
export { MAX_SNAPSHOT_SIZE_BYTES } from './shared-checkpoint-types.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export*from"./checkpoint-client-reader.js";import{MAX_SNAPSHOT_SIZE_BYTES as _}from"./shared-checkpoint-types.js";export{_ as MAX_SNAPSHOT_SIZE_BYTES};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* P117.01: Inlined byte-identical types from `@neocortex/shared/checkpoints`.
|
|
3
|
+
*
|
|
4
|
+
* SSoT-Shadow pattern (P92.01 server precedent — server `shared-types.ts` does
|
|
5
|
+
* the same for tier-config). Client tarball is published standalone via
|
|
6
|
+
* `@ornexus/neocortex` and does NOT include `@neocortex/shared` as a runtime
|
|
7
|
+
* dependency (workspace package, excluded from tarball per `.npmignore` +
|
|
8
|
+
* `tsconfig.build.json`). Any non-erased import of `@neocortex/shared` in
|
|
9
|
+
* `packages/client/dist/**` causes runtime `ERR_MODULE_NOT_FOUND` on globally
|
|
10
|
+
* installed `@ornexus/neocortex`.
|
|
11
|
+
*
|
|
12
|
+
* Live regression reproduced 2026-04-25 (Epic P117 origin):
|
|
13
|
+
* `[Neocortex] checkpoint hook failed: Cannot find package '@neocortex/shared'
|
|
14
|
+
* imported from .../checkpoint/checkpoint-client-reader.js. Proceeding without
|
|
15
|
+
* checkpoint.`
|
|
16
|
+
*
|
|
17
|
+
* Sync responsibility: `shared-types-sync.test.ts` (P117.01 describe block) +
|
|
18
|
+
* `checkpoint-shared-sync.test.ts` (client-side drift test). Drift test fails
|
|
19
|
+
* CI if these diverge from SSoT.
|
|
20
|
+
*
|
|
21
|
+
* Defense-in-depth: `validate-pre-publish.js` ships
|
|
22
|
+
* `validateClientNoSharedImport()` (P117.01) scanning client dist for
|
|
23
|
+
* `@neocortex/shared` runtime references — match = exit 1 (publish blocked).
|
|
24
|
+
*
|
|
25
|
+
* DO NOT EDIT WITHOUT also editing `packages/shared/src/checkpoints/types.ts`.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* 4-phase state machine mirroring step-c-06-implement Double Diamond phases.
|
|
29
|
+
* Auto-detected from prompt progression (P109.04 wires).
|
|
30
|
+
*
|
|
31
|
+
* Canonical mapping:
|
|
32
|
+
* - FASE_1: Discovery/Analysis
|
|
33
|
+
* - FASE_2: Implementation/Test writing
|
|
34
|
+
* - FASE_3: Validation/Refactor
|
|
35
|
+
* - FASE_4: Cleanup/Update memory
|
|
36
|
+
*/
|
|
37
|
+
export type CheckpointPhase = 'FASE_1' | 'FASE_2' | 'FASE_3' | 'FASE_4';
|
|
38
|
+
/**
|
|
39
|
+
* Full checkpoint record (server → DB persistence shape).
|
|
40
|
+
* Mirror of implement_checkpoints table (P109.01).
|
|
41
|
+
* Wire-format uses ISO strings for timestamps (NOT Date objects).
|
|
42
|
+
*/
|
|
43
|
+
export interface ImplementCheckpoint {
|
|
44
|
+
readonly id: string;
|
|
45
|
+
readonly licenseId: string;
|
|
46
|
+
readonly storyId: string;
|
|
47
|
+
readonly turn: number;
|
|
48
|
+
readonly filesModified: readonly string[];
|
|
49
|
+
readonly testsModified: readonly string[];
|
|
50
|
+
readonly currentPhase: CheckpointPhase;
|
|
51
|
+
readonly snapshotMd: string;
|
|
52
|
+
readonly createdAt: string;
|
|
53
|
+
readonly updatedAt: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Client → Server payload (POST /api/v1/invoke body enrichment).
|
|
57
|
+
* Omits id, licenseId, createdAt, updatedAt (server-set, never trust client).
|
|
58
|
+
*/
|
|
59
|
+
export interface ImplementCheckpointSnapshot {
|
|
60
|
+
readonly storyId: string;
|
|
61
|
+
readonly turn: number;
|
|
62
|
+
readonly filesModified: readonly string[];
|
|
63
|
+
readonly testsModified: readonly string[];
|
|
64
|
+
readonly currentPhase: CheckpointPhase;
|
|
65
|
+
readonly snapshotMd: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Server → Client resume injection shape.
|
|
69
|
+
* Server builds this from latest checkpoint row; client-facing prompt gets `summary`.
|
|
70
|
+
*/
|
|
71
|
+
export interface CheckpointResumeContext {
|
|
72
|
+
readonly storyId: string;
|
|
73
|
+
readonly turn: number;
|
|
74
|
+
readonly maxTurns: number;
|
|
75
|
+
readonly currentPhase: CheckpointPhase;
|
|
76
|
+
readonly filesModifiedCount: number;
|
|
77
|
+
readonly testsModifiedCount: number;
|
|
78
|
+
readonly summary: string;
|
|
79
|
+
readonly resumeAt: string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Snapshot size guard: prevents PG bloat from pathological code-paste scenarios.
|
|
83
|
+
* Truncate snapshot_md at this byte count (P109.06 enforces).
|
|
84
|
+
*/
|
|
85
|
+
export declare const MAX_SNAPSHOT_SIZE_BYTES: 50000;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const S=5e4;export{S as MAX_SNAPSHOT_SIZE_BYTES};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @license FSL-1.1
|
|
4
|
+
* Copyright (c) 2026 OrNexus AI
|
|
5
|
+
*
|
|
6
|
+
* This file is part of Neocortex CLI, licensed under the
|
|
7
|
+
* Functional Source License, Version 1.1 (FSL-1.1).
|
|
8
|
+
*
|
|
9
|
+
* Change Date: February 20, 2029
|
|
10
|
+
* Change License: MIT
|
|
11
|
+
*
|
|
12
|
+
* See the LICENSE file in the project root for full license text.
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{readFileSync as u}from"node:fs";import{fileURLToPath as m}from"node:url";import{dirname as l,join as d}from"node:path";function g(){try{const r=m(import.meta.url);let e=l(r);for(let s=0;s<5;s++){try{const o=JSON.parse(u(d(e,"package.json"),"utf-8"));if(o.name==="@ornexus/neocortex"||o.name==="@neocortex/client")return o.version??"0.0.0"}catch{}e=l(e)}}catch{}return"0.0.0"}const p=`
|
|
3
|
+
neocortex-client - Neocortex Client CLI
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
neocortex-client <command> [options]
|
|
7
|
+
|
|
8
|
+
Commands:
|
|
9
|
+
invoke Send orchestration request to server
|
|
10
|
+
activate Activate license key
|
|
11
|
+
refresh-memory Create/repair canonical NEOCORTEX.md links and wrappers
|
|
12
|
+
cache-status Show cache and circuit breaker status
|
|
13
|
+
update Update to latest version (use 'neocortex update' instead)
|
|
14
|
+
|
|
15
|
+
Options:
|
|
16
|
+
--help, -h Show this help message
|
|
17
|
+
--version, -v Show version number
|
|
18
|
+
|
|
19
|
+
Invoke Options:
|
|
20
|
+
--args <string> Raw args to send (e.g., "*status")
|
|
21
|
+
--stdin Read raw args as UTF-8 text from stdin
|
|
22
|
+
--args-file <path> Read raw args as UTF-8 text from a local file
|
|
23
|
+
--project-root <path> Project root directory (default: cwd; Git repo not required)
|
|
24
|
+
--format <type> Output format: json | plain (default: plain)
|
|
25
|
+
--server-url <url> Server URL override
|
|
26
|
+
|
|
27
|
+
Refresh Memory Options:
|
|
28
|
+
--project-root <path> Project root directory (default: cwd)
|
|
29
|
+
--targets <csv> Target ids (default: all project-memory targets)
|
|
30
|
+
--dry-run, --preview Print files that would change without writing
|
|
31
|
+
|
|
32
|
+
Activate Options:
|
|
33
|
+
<license-key> License key (e.g., NX-PRO-ABC-123)
|
|
34
|
+
--server-url <url> Server URL override
|
|
35
|
+
--non-interactive Skip interactive prompts
|
|
36
|
+
|
|
37
|
+
Examples:
|
|
38
|
+
neocortex-client invoke --args "*status"
|
|
39
|
+
neocortex-client invoke --args "*yolo @docs/stories/1.1.story.md" --format json
|
|
40
|
+
neocortex-client invoke --stdin < synthetic.story.md
|
|
41
|
+
neocortex-client invoke --args-file ./synthetic.story.md
|
|
42
|
+
neocortex-client activate NX-PRO-ABC-123
|
|
43
|
+
neocortex-client cache-status
|
|
44
|
+
|
|
45
|
+
License:
|
|
46
|
+
Licensed under BSL-1.1 (Business Source License 1.1)
|
|
47
|
+
`.trim(),h=new Set(["pm","install","postinstall","preinstall","prepublish","postpublish","preuninstall","postuninstall","preprepare","prepare","postprepare"]);async function f(){const r=process.argv.slice(2),e=r[0];e&&h.has(e.toLowerCase())&&process.exit(0),(!e||e==="--help"||e==="-h")&&(console.log(p),process.exit(0)),(e==="--version"||e==="-v")&&(console.log(g()),process.stderr.write(`Licensed under BSL-1.1 (Business Source License 1.1)
|
|
48
|
+
`),process.exit(0));const s=r.slice(1);switch(e){case"invoke":{const{invokeCliHandler:o}=await import("./commands/invoke.js"),i=await o(s);process.exit(i);break}case"activate":{const{activate:o}=await import("./commands/activate.js");let i,c,a=!1;for(let t=0;t<s.length;t++){const n=s[t];n==="--server-url"?c=s[++t]:n==="--non-interactive"?a=!0:n==="--help"||n==="-h"?(console.log(p),process.exit(0)):n.startsWith("-")||(i=n)}i||(console.error("Error: License key is required."),console.error("Usage: neocortex-client activate <license-key>"),console.error("Example: neocortex-client activate NX-PRO-ABC-123"),process.exit(1));try{const t=await o({licenseKey:i,serverUrl:c,nonInteractive:a});t.success?(console.log(t.message),process.exit(0)):(console.error(t.message),process.exit(1))}catch(t){const n=t instanceof Error?t.message:String(t);console.error(`Activation failed: ${n}`),process.exit(1)}break}case"cache-status":{console.log("Cache status requires an active client session."),console.log("Use this command within a running Neocortex client context."),process.exit(0);break}case"refresh-memory":{const{refreshMemoryCliHandler:o}=await import("./commands/refresh-memory.js"),i=await o(s);process.exit(i);break}case"update":{console.log("To update Neocortex, run:"),console.log(" neocortex update"),console.log(""),console.log("Or manually:"),console.log(" npm install -g @ornexus/neocortex@latest"),process.exit(0);break}default:console.error(`Unknown command: ${e}`),console.error('Run "neocortex-client --help" for usage information.'),process.exit(1)}}f().catch(r=>{console.error(`Fatal error: ${r instanceof Error?r.message:String(r)}`),process.exit(1)});
|
|
@@ -0,0 +1,55 @@
|
|
|
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 ActivateOptions {
|
|
14
|
+
/** License key or API key to activate */
|
|
15
|
+
readonly licenseKey?: string;
|
|
16
|
+
/** Server URL override (default: production server) */
|
|
17
|
+
readonly serverUrl?: string;
|
|
18
|
+
/** Skip interactive prompt */
|
|
19
|
+
readonly nonInteractive?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface ActivateResult {
|
|
22
|
+
readonly success: boolean;
|
|
23
|
+
readonly message: string;
|
|
24
|
+
readonly tier?: string;
|
|
25
|
+
readonly serverUrl?: string;
|
|
26
|
+
readonly configPath?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Validate license key format.
|
|
30
|
+
* Format: NX-{TIER}-{random}-{random}
|
|
31
|
+
* Tiers: FREE, PRO, ENT
|
|
32
|
+
*/
|
|
33
|
+
export declare function validateLicenseKeyFormat(key: string): {
|
|
34
|
+
valid: boolean;
|
|
35
|
+
error?: string;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Validate API key format.
|
|
39
|
+
* Format: nxk_{tier}_{random}_{check}
|
|
40
|
+
*/
|
|
41
|
+
export declare function validateApiKeyFormat(key: string): {
|
|
42
|
+
valid: boolean;
|
|
43
|
+
error?: string;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Activate a Neocortex license.
|
|
47
|
+
*
|
|
48
|
+
* Flow:
|
|
49
|
+
* 1. Validate license key format
|
|
50
|
+
* 2. Call IP Protection Server to activate
|
|
51
|
+
* 3. Cache JWT token via LicenseClient
|
|
52
|
+
* 4. Create/update ~/.neocortex/config.json
|
|
53
|
+
* 5. Return result with feedback
|
|
54
|
+
*/
|
|
55
|
+
export declare function activate(options: ActivateOptions): Promise<ActivateResult>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import{existsSync as $,mkdirSync as C,writeFileSync as V,readFileSync as x}from"node:fs";import{join as a,dirname as P}from"node:path";import{homedir as Y}from"node:os";import{fileURLToPath as X}from"node:url";import{LicenseClient as M}from"../license/license-client.js";import{EncryptedCache as S}from"../cache/encrypted-cache.js";import{getMachineFingerprint as E}from"../machine/fingerprint.js";import{updateAgentDescription as N}from"../agent/update-description.js";import{refreshStubs as h}from"../agent/refresh-stubs.js";import{updateAgentYaml as _}from"../agent/update-agent-yaml.js";import{saveSecureConfig as W,setSecureDirPermissions as w}from"../config/secure-config.js";import{DEFAULT_SERVER_URL as J}from"../constants.js";function b(){try{const e=X(import.meta.url);let t=P(e);for(let r=0;r<5;r++){try{const n=JSON.parse(x(a(t,"package.json"),"utf-8"));if(n.name==="@ornexus/neocortex"||n.name==="@neocortex/client")return n.version??"0.0.0"}catch{}t=P(t)}}catch{}return"0.0.0"}const i=a(Y(),".neocortex"),c=a(i,"config.json"),B=/^NX-(F|P|E)-[a-f0-9]+-[a-f0-9]+$/i,G=/^nxk_(?:[a-z]+_)?[a-f0-9]+_[a-f0-9]+$/;function z(e){if(!e||e.trim().length===0)return{valid:!1,error:"License key cannot be empty"};const t=e.trim().toUpperCase();return t.startsWith("NX-")?B.test(t)?{valid:!0}:{valid:!1,error:"Invalid license key format. Expected: NX-{TIER}-{ID} (e.g., NX-PRO-ABC-123)"}:{valid:!1,error:'License key must start with "NX-"'}}function q(e){if(!e||e.trim().length===0)return{valid:!1,error:"API key cannot be empty"};const t=e.trim();return t.startsWith("nxk_")?t.length<20?{valid:!1,error:"API key is too short"}:G.test(t)?{valid:!0}:{valid:!1,error:"Invalid API key format. Expected: nxk_{id}_{check} (e.g., nxk_abc123def456...)"}:{valid:!1,error:'API key must start with "nxk_"'}}function pe(){try{if($(c)){const e=x(c,"utf-8");return JSON.parse(e)}}catch{}return null}function A(e){C(i,{recursive:!0}),w(i);const t=a(i,"cache");if(C(t,{recursive:!0}),w(t),e.licenseKey||e.apiKey)W({serverUrl:e.serverUrl,mode:e.mode,machineId:e.machineId,activatedAt:e.activatedAt,tier:e.tier,licenseKey:e.licenseKey??e.apiKey});else{const r={configVersion:1,...e};V(c,JSON.stringify(r,null,2)+`
|
|
2
|
+
`,"utf-8")}}async function he(e){const{licenseKey:t,serverUrl:r=J}=e;if(!t)return{success:!1,message:["No key provided.","","Get your license key at https://neocortex.sh/portal/login","","Usage:"," neocortex activate YOUR-LICENSE-KEY"," neocortex activate YOUR-API-KEY"].join(`
|
|
3
|
+
`)};const n=t.trim();if(n.startsWith("nxk_")){const o=q(n);if(!o.valid)return{success:!1,message:`Invalid API key: ${o.error}`};const k=n.match(/^nxk_(free|pro|ent)_/),O={free:"free",pro:"pro",ent:"enterprise"},R=k?.[1]?O[k[1]]??"unknown":"unknown",I=E(),l=b();let m;try{const s=await fetch(`${r}/api/v1/license/activate-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({api_key:n,machine_id:I,client_version:l})});if(!s.ok)return{success:!1,message:`API key activation failed: ${(await s.json().catch(()=>({}))).message??`HTTP ${s.status}`}`};m=await s.json()}catch{return{success:!1,message:["Failed to connect to IP Protection Server.","","Possible causes:",` - Server at ${r} is unreachable`," - Network connectivity issue","","Workaround: Use --local flag to run in local mode"].join(`
|
|
4
|
+
`)}}const p=m.tier??R,T=a(i,"cache");try{await new S({cacheDir:T,passphrase:n}).set("neocortex:jwt:token",m.token,m.expires_in*1e3)}catch{}const L={serverUrl:r,mode:"remote",machineId:I,activatedAt:new Date().toISOString(),tier:p,apiKey:n};try{A(L)}catch(s){return{success:!1,message:`Failed to save configuration: ${s instanceof Error?s.message:"unknown error"}`}}const Z=h(l,{forceCreate:!0,targetFilter:"claude-code"});return h(l),N(l,p),_(l,p),{success:!0,message:["Neocortex activated successfully.","","Open your preferred platform (Claude Code, Cursor, VS Code, etc.)","and reference the Neocortex agent.","","Use *menu to see available commands or check the Docs in your Dashboard."].join(`
|
|
5
|
+
`),tier:p,serverUrl:r,configPath:c}}const y=z(n);if(!y.valid)return{success:!1,message:`Invalid license key: ${y.error}`};const u=n,v=u.match(/^NX-(F|P|E)-/i),F={F:"free",P:"pro",E:"enterprise"},d=v?.[1]?F[v[1].toUpperCase()]??"unknown":"unknown",K=a(i,"cache"),U=new S({cacheDir:K,passphrase:u}),j=new M({serverUrl:r,licenseKey:u,cacheProvider:U});let g;try{g=await j.activate()}catch{return{success:!1,message:["Failed to connect to IP Protection Server.","","Possible causes:",` - Server at ${r} is unreachable`," - Network connectivity issue"," - Server is still being deployed","","Workaround: Use --local flag to run in local mode"].join(`
|
|
6
|
+
`)}}if(!g)return{success:!1,message:["License activation failed.","","Possible causes:"," - Invalid or expired license key"," - License already activated on another machine"," - Server rejected the activation request","","Check your license key and try again.","Contact support if the problem persists."].join(`
|
|
7
|
+
`)};const D={serverUrl:r,mode:"remote",machineId:E(),activatedAt:new Date().toISOString(),tier:d,licenseKey:u};try{A(D)}catch(o){return{success:!1,message:`Failed to save config to ${c}: ${o instanceof Error?o.message:String(o)}`}}const f=b(),Q=h(f,{forceCreate:!0,targetFilter:"claude-code"});return h(f),N(f,d),_(f,d),{success:!0,message:["Neocortex activated successfully.","","Open your preferred platform (Claude Code, Cursor, VS Code, etc.)","and reference the Neocortex agent.","","Use *menu to see available commands or check the Docs in your Dashboard."].join(`
|
|
8
|
+
`),tier:d,serverUrl:r,configPath:c}}export{he as activate,q as validateApiKeyFormat,z as validateLicenseKeyFormat};
|
|
@@ -0,0 +1,39 @@
|
|
|
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;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{readdir as y,stat as g}from"node:fs/promises";import{join as f}from"node:path";async function T(t){const r=t.staleThresholdMs??864e5;let e=0,s=0,c=0,i=null,a=null;try{const u=(await y(t.cacheDir)).filter(l=>l.endsWith(".enc"));e=u.length;const h=Date.now();for(const l of u)try{const m=f(t.cacheDir,l),d=await g(m);s+=d.size;const n=d.mtime;(!i||n<i)&&(i=n),(!a||n>a)&&(a=n),h-n.getTime()>r&&c++}catch{}}catch{}const S=t.circuitBreaker.getState().state;let o=0;try{o=(await t.telemetryQueue.getStats()).count}catch{}return{totalEntries:e,totalSizeBytes:s,totalSizeFormatted:$(s),oldestEntry:i,newestEntry:a,staleEntries:c,circuitState:S,lastSync:a,telemetryQueueSize:o}}function B(t){return["+-------------------------------------------------+","| NEOCORTEX CACHE STATUS |","+-------------------------------------------------+",`| Total entries: ${String(t.totalEntries).padEnd(29)}|`,`| Total size: ${t.totalSizeFormatted.padEnd(29)}|`,`| Oldest entry: ${(t.oldestEntry?.toISOString()??"N/A").padEnd(29)}|`,`| Newest entry: ${(t.newestEntry?.toISOString()??"N/A").padEnd(29)}|`,`| Stale entries: ${String(t.staleEntries).padEnd(29)}|`,"|-------------------------------------------------|",`| Circuit breaker: ${t.circuitState.padEnd(29)}|`,`| Last sync: ${(t.lastSync?.toISOString()??"N/A").padEnd(29)}|`,`| Telemetry queue: ${(t.telemetryQueueSize+" events").padEnd(29)}|`,"+-------------------------------------------------+"].join(`
|
|
2
|
+
`)}function $(t){if(t===0)return"0 B";const r=["B","KB","MB","GB"],e=Math.floor(Math.log(t)/Math.log(1024));return`${(t/Math.pow(1024,e)).toFixed(e===0?0:1)} ${r[e]}`}export{B as formatCacheStatus,T as getCacheStatus};
|