@ornexus/neocortex 4.0.1 → 4.0.2
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/install.ps1 +92 -33
- package/install.sh +15 -1
- package/package.json +3 -3
- package/packages/client/dist/adapters/adapter-registry.js +1 -106
- package/packages/client/dist/adapters/antigravity-adapter.js +2 -77
- package/packages/client/dist/adapters/claude-code-adapter.js +3 -79
- package/packages/client/dist/adapters/codex-adapter.js +2 -80
- package/packages/client/dist/adapters/cursor-adapter.js +4 -115
- package/packages/client/dist/adapters/gemini-adapter.js +2 -71
- package/packages/client/dist/adapters/index.js +1 -21
- package/packages/client/dist/adapters/platform-detector.js +1 -106
- package/packages/client/dist/adapters/target-adapter.js +0 -12
- package/packages/client/dist/adapters/vscode-adapter.js +2 -72
- package/packages/client/dist/agent/refresh-stubs.js +2 -234
- package/packages/client/dist/agent/update-agent-yaml.js +1 -102
- package/packages/client/dist/agent/update-description.js +1 -251
- package/packages/client/dist/cache/crypto-utils.js +1 -76
- package/packages/client/dist/cache/encrypted-cache.js +1 -94
- package/packages/client/dist/cache/in-memory-asset-cache.js +1 -70
- package/packages/client/dist/cache/index.js +1 -13
- package/packages/client/dist/cli.js +2 -163
- package/packages/client/dist/commands/activate.js +8 -390
- package/packages/client/dist/commands/cache-status.js +2 -112
- package/packages/client/dist/commands/invoke.js +28 -490
- package/packages/client/dist/config/resolver-selection.js +1 -278
- package/packages/client/dist/config/secure-config.js +12 -269
- package/packages/client/dist/constants.js +1 -25
- package/packages/client/dist/context/context-collector.js +2 -222
- package/packages/client/dist/context/context-sanitizer.js +1 -145
- package/packages/client/dist/index.js +1 -38
- package/packages/client/dist/license/index.js +1 -5
- package/packages/client/dist/license/license-client.js +1 -257
- package/packages/client/dist/machine/fingerprint.js +2 -160
- package/packages/client/dist/machine/index.js +1 -5
- package/packages/client/dist/resilience/circuit-breaker.js +1 -170
- package/packages/client/dist/resilience/degradation-manager.js +1 -164
- package/packages/client/dist/resilience/freshness-indicator.js +1 -100
- package/packages/client/dist/resilience/index.js +1 -8
- package/packages/client/dist/resilience/recovery-detector.js +1 -74
- package/packages/client/dist/resolvers/asset-resolver.js +0 -13
- package/packages/client/dist/resolvers/local-resolver.js +8 -218
- package/packages/client/dist/resolvers/remote-resolver.js +1 -282
- package/packages/client/dist/telemetry/index.js +1 -5
- package/packages/client/dist/telemetry/offline-queue.js +1 -131
- package/packages/client/dist/tier/index.js +1 -5
- package/packages/client/dist/tier/tier-aware-client.js +1 -260
- package/packages/client/dist/types/index.js +1 -38
- package/targets-stubs/antigravity/gemini.md +1 -1
- package/targets-stubs/antigravity/install-antigravity.sh +49 -3
- package/targets-stubs/antigravity/skill/SKILL.md +23 -4
- package/targets-stubs/claude-code/neocortex.agent.yaml +19 -1
- package/targets-stubs/claude-code/neocortex.md +64 -29
- package/targets-stubs/codex/agents.md +20 -3
- package/targets-stubs/codex/config-mcp.toml +5 -0
- package/targets-stubs/cursor/agent.md +23 -5
- package/targets-stubs/cursor/install-cursor.sh +51 -3
- package/targets-stubs/cursor/mcp.json +7 -0
- package/targets-stubs/gemini-cli/agent.md +37 -6
- package/targets-stubs/gemini-cli/install-gemini.sh +50 -17
- package/targets-stubs/vscode/agent.md +47 -10
- package/targets-stubs/vscode/install-vscode.sh +50 -3
- package/targets-stubs/vscode/mcp.json +8 -0
|
@@ -1,115 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* Cursor Adapter - Formats prompts as .cursorrules content.
|
|
6
|
-
*
|
|
7
|
-
* Cursor reads system instructions from .cursorrules files.
|
|
8
|
-
* This adapter produces concise, directive-style rules optimized
|
|
9
|
-
* for Cursor's instruction format.
|
|
10
|
-
*
|
|
11
|
-
* Story 42.8
|
|
12
|
-
*/
|
|
13
|
-
// ── Constants ───────────────────────────────────────────────────────────────
|
|
14
|
-
const TARGET_ID = 'cursor';
|
|
15
|
-
const MAX_CONTEXT_LENGTH = 100_000;
|
|
16
|
-
const CAPABILITIES = {
|
|
17
|
-
supportsMarkdown: true,
|
|
18
|
-
supportsMultiFile: false,
|
|
19
|
-
supportsMultiTurn: true,
|
|
20
|
-
supportsTools: true,
|
|
21
|
-
maxContextLength: MAX_CONTEXT_LENGTH,
|
|
22
|
-
};
|
|
23
|
-
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
24
|
-
/**
|
|
25
|
-
* Convert verbose markdown prose to concise directive-style rules.
|
|
26
|
-
* Strips excessive headers, converts paragraphs to bullet points.
|
|
27
|
-
*/
|
|
28
|
-
function condenseToCursorFormat(content) {
|
|
29
|
-
const lines = content.split('\n');
|
|
30
|
-
const result = [];
|
|
31
|
-
for (const line of lines) {
|
|
32
|
-
const trimmed = line.trim();
|
|
33
|
-
// Skip empty lines in sequences (collapse to single)
|
|
34
|
-
if (trimmed === '') {
|
|
35
|
-
if (result.length > 0 && result[result.length - 1] !== '') {
|
|
36
|
-
result.push('');
|
|
37
|
-
}
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
// Keep headers but reduce depth (### becomes ##)
|
|
41
|
-
if (trimmed.startsWith('#')) {
|
|
42
|
-
result.push(trimmed);
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
// Keep bullet points, code blocks, and directives
|
|
46
|
-
if (trimmed.startsWith('-') ||
|
|
47
|
-
trimmed.startsWith('*') ||
|
|
48
|
-
trimmed.startsWith('```') ||
|
|
49
|
-
trimmed.startsWith('>')) {
|
|
50
|
-
result.push(trimmed);
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
// Inside code blocks, preserve as-is
|
|
54
|
-
if (result.length > 0 && isInsideCodeBlock(result)) {
|
|
55
|
-
result.push(line);
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
// Convert standalone paragraphs to bullet points
|
|
59
|
-
if (trimmed.length > 0) {
|
|
60
|
-
result.push(`- ${trimmed}`);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return result.join('\n').trim();
|
|
64
|
-
}
|
|
65
|
-
function isInsideCodeBlock(lines) {
|
|
66
|
-
let openCount = 0;
|
|
67
|
-
for (const line of lines) {
|
|
68
|
-
if (line.trim().startsWith('```')) {
|
|
69
|
-
openCount++;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return openCount % 2 !== 0;
|
|
73
|
-
}
|
|
74
|
-
// ── Implementation ──────────────────────────────────────────────────────────
|
|
75
|
-
export class CursorAdapter {
|
|
76
|
-
formatPrompt(assembledPrompt, platformInstructions, config) {
|
|
77
|
-
const sections = [];
|
|
78
|
-
// Condense prompt for Cursor's concise format
|
|
79
|
-
const condensed = config.verbose === true
|
|
80
|
-
? assembledPrompt
|
|
81
|
-
: condenseToCursorFormat(assembledPrompt);
|
|
82
|
-
sections.push(condensed);
|
|
83
|
-
// Add tool hints if available
|
|
84
|
-
if (platformInstructions.tools && platformInstructions.tools.length > 0) {
|
|
85
|
-
sections.push('');
|
|
86
|
-
sections.push('## Tools');
|
|
87
|
-
for (const tool of platformInstructions.tools) {
|
|
88
|
-
sections.push(`- ${tool}`);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
// Add context files as references
|
|
92
|
-
if (platformInstructions.contextFiles && platformInstructions.contextFiles.length > 0) {
|
|
93
|
-
sections.push('');
|
|
94
|
-
sections.push('## Context');
|
|
95
|
-
for (const file of platformInstructions.contextFiles) {
|
|
96
|
-
sections.push(`- @${file}`);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
let result = sections.join('\n');
|
|
100
|
-
const maxLength = config.maxPromptLength ?? MAX_CONTEXT_LENGTH;
|
|
101
|
-
if (result.length > maxLength) {
|
|
102
|
-
result = result.slice(0, maxLength);
|
|
103
|
-
}
|
|
104
|
-
return result;
|
|
105
|
-
}
|
|
106
|
-
getTargetId() {
|
|
107
|
-
return TARGET_ID;
|
|
108
|
-
}
|
|
109
|
-
getCapabilities() {
|
|
110
|
-
return CAPABILITIES;
|
|
111
|
-
}
|
|
112
|
-
getInjectionMethod() {
|
|
113
|
-
return 'file';
|
|
114
|
-
}
|
|
115
|
-
}
|
|
1
|
+
const l="cursor",T=1e5,c={supportsMarkdown:!0,supportsMultiFile:!1,supportsMultiTurn:!0,supportsTools:!0,maxContextLength:1e5};function p(n){const s=n.split(`
|
|
2
|
+
`),t=[];for(const o of s){const e=o.trim();if(e===""){t.length>0&&t[t.length-1]!==""&&t.push("");continue}if(e.startsWith("#")){t.push(e);continue}if(e.startsWith("-")||e.startsWith("*")||e.startsWith("```")||e.startsWith(">")){t.push(e);continue}if(t.length>0&&f(t)){t.push(o);continue}e.length>0&&t.push(`- ${e}`)}return t.join(`
|
|
3
|
+
`).trim()}function f(n){let s=0;for(const t of n)t.trim().startsWith("```")&&s++;return s%2!==0}class g{formatPrompt(s,t,o){const e=[],h=o.verbose===!0?s:p(s);if(e.push(h),t.tools&&t.tools.length>0){e.push(""),e.push("## Tools");for(const r of t.tools)e.push(`- ${r}`)}if(t.contextFiles&&t.contextFiles.length>0){e.push(""),e.push("## Context");for(const r of t.contextFiles)e.push(`- @${r}`)}let i=e.join(`
|
|
4
|
+
`);const u=o.maxPromptLength??1e5;return i.length>u&&(i=i.slice(0,u)),i}getTargetId(){return l}getCapabilities(){return c}getInjectionMethod(){return"file"}}export{g as CursorAdapter};
|
|
@@ -1,71 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* Copyright (c) 2026 OrNexus AI
|
|
4
|
-
*
|
|
5
|
-
* Gemini CLI Adapter - Formats prompts as GEMINI.md system instructions.
|
|
6
|
-
*
|
|
7
|
-
* Gemini CLI reads system instructions from GEMINI.md files
|
|
8
|
-
* with @import directives for referenced standards and skills.
|
|
9
|
-
*
|
|
10
|
-
* Story 42.8
|
|
11
|
-
*/
|
|
12
|
-
// ── Constants ───────────────────────────────────────────────────────────────
|
|
13
|
-
const TARGET_ID = 'gemini-cli';
|
|
14
|
-
const MAX_CONTEXT_LENGTH = 1_000_000;
|
|
15
|
-
const CAPABILITIES = {
|
|
16
|
-
supportsMarkdown: true,
|
|
17
|
-
supportsMultiFile: true,
|
|
18
|
-
supportsMultiTurn: true,
|
|
19
|
-
supportsTools: true,
|
|
20
|
-
maxContextLength: MAX_CONTEXT_LENGTH,
|
|
21
|
-
};
|
|
22
|
-
// ── Implementation ──────────────────────────────────────────────────────────
|
|
23
|
-
export class GeminiAdapter {
|
|
24
|
-
formatPrompt(assembledPrompt, platformInstructions, config) {
|
|
25
|
-
const sections = [];
|
|
26
|
-
// Main prompt content
|
|
27
|
-
sections.push(assembledPrompt);
|
|
28
|
-
// Add @import directives for context files (Gemini-native feature)
|
|
29
|
-
if (platformInstructions.contextFiles && platformInstructions.contextFiles.length > 0) {
|
|
30
|
-
sections.push('');
|
|
31
|
-
sections.push('## Standards');
|
|
32
|
-
sections.push('');
|
|
33
|
-
for (const file of platformInstructions.contextFiles) {
|
|
34
|
-
sections.push(`@import ${file}`);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
// Tool definitions
|
|
38
|
-
if (platformInstructions.tools && platformInstructions.tools.length > 0) {
|
|
39
|
-
sections.push('');
|
|
40
|
-
sections.push('## Available Tools');
|
|
41
|
-
sections.push('');
|
|
42
|
-
for (const tool of platformInstructions.tools) {
|
|
43
|
-
sections.push(`- ${tool}`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
// MCP configuration (Gemini supports MCP servers)
|
|
47
|
-
if (platformInstructions.mcpConfig && Object.keys(platformInstructions.mcpConfig).length > 0) {
|
|
48
|
-
sections.push('');
|
|
49
|
-
sections.push('## MCP Servers');
|
|
50
|
-
sections.push('');
|
|
51
|
-
sections.push('```json');
|
|
52
|
-
sections.push(JSON.stringify(platformInstructions.mcpConfig, null, 2));
|
|
53
|
-
sections.push('```');
|
|
54
|
-
}
|
|
55
|
-
let result = sections.join('\n');
|
|
56
|
-
const maxLength = config.maxPromptLength ?? MAX_CONTEXT_LENGTH;
|
|
57
|
-
if (result.length > maxLength) {
|
|
58
|
-
result = result.slice(0, maxLength);
|
|
59
|
-
}
|
|
60
|
-
return result;
|
|
61
|
-
}
|
|
62
|
-
getTargetId() {
|
|
63
|
-
return TARGET_ID;
|
|
64
|
-
}
|
|
65
|
-
getCapabilities() {
|
|
66
|
-
return CAPABILITIES;
|
|
67
|
-
}
|
|
68
|
-
getInjectionMethod() {
|
|
69
|
-
return 'file';
|
|
70
|
-
}
|
|
71
|
-
}
|
|
1
|
+
const i="gemini-cli",g=1e6,n={supportsMarkdown:!0,supportsMultiFile:!0,supportsMultiTurn:!0,supportsTools:!0,maxContextLength:1e6};class r{formatPrompt(u,t,h){const e=[];if(e.push(u),t.contextFiles&&t.contextFiles.length>0){e.push(""),e.push("## Standards"),e.push("");for(const o of t.contextFiles)e.push(`@import ${o}`)}if(t.tools&&t.tools.length>0){e.push(""),e.push("## Available Tools"),e.push("");for(const o of t.tools)e.push(`- ${o}`)}t.mcpConfig&&Object.keys(t.mcpConfig).length>0&&(e.push(""),e.push("## MCP Servers"),e.push(""),e.push("```json"),e.push(JSON.stringify(t.mcpConfig,null,2)),e.push("```"));let s=e.join(`
|
|
2
|
+
`);const p=h.maxPromptLength??1e6;return s.length>p&&(s=s.slice(0,p)),s}getTargetId(){return i}getCapabilities(){return n}getInjectionMethod(){return"file"}}export{r as GeminiAdapter};
|
|
@@ -1,21 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* @license FSL-1.1
|
|
3
|
-
* Copyright (c) 2026 OrNexus AI
|
|
4
|
-
*
|
|
5
|
-
* @neocortex/client - Target Adapters
|
|
6
|
-
*
|
|
7
|
-
* Platform-specific prompt formatting for 6 supported targets.
|
|
8
|
-
*
|
|
9
|
-
* Story 42.8
|
|
10
|
-
*/
|
|
11
|
-
// ── Adapter Implementations ─────────────────────────────────────────────────
|
|
12
|
-
export { ClaudeCodeAdapter } from './claude-code-adapter.js';
|
|
13
|
-
export { CursorAdapter } from './cursor-adapter.js';
|
|
14
|
-
export { VSCodeAdapter } from './vscode-adapter.js';
|
|
15
|
-
export { GeminiAdapter } from './gemini-adapter.js';
|
|
16
|
-
export { CodexAdapter } from './codex-adapter.js';
|
|
17
|
-
export { AntigravityAdapter } from './antigravity-adapter.js';
|
|
18
|
-
// ── Platform Detection ──────────────────────────────────────────────────────
|
|
19
|
-
export { detectPlatform, isValidTargetId, } from './platform-detector.js';
|
|
20
|
-
// ── Registry ────────────────────────────────────────────────────────────────
|
|
21
|
-
export { AdapterRegistry, createDefaultRegistry, UnknownTargetError, } from './adapter-registry.js';
|
|
1
|
+
import{ClaudeCodeAdapter as t}from"./claude-code-adapter.js";import{CursorAdapter as a}from"./cursor-adapter.js";import{VSCodeAdapter as d}from"./vscode-adapter.js";import{GeminiAdapter as m}from"./gemini-adapter.js";import{CodexAdapter as i}from"./codex-adapter.js";import{AntigravityAdapter as g}from"./antigravity-adapter.js";import{detectPlatform as C,isValidTargetId as l}from"./platform-detector.js";import{AdapterRegistry as u,createDefaultRegistry as y,UnknownTargetError as c}from"./adapter-registry.js";export{u as AdapterRegistry,g as AntigravityAdapter,t as ClaudeCodeAdapter,i as CodexAdapter,a as CursorAdapter,m as GeminiAdapter,c as UnknownTargetError,d as VSCodeAdapter,y as createDefaultRegistry,C as detectPlatform,l as isValidTargetId};
|
|
@@ -1,106 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* @license FSL-1.1
|
|
3
|
-
* Copyright (c) 2026 OrNexus AI
|
|
4
|
-
*
|
|
5
|
-
* Platform Detector - Auto-detects the current platform target.
|
|
6
|
-
*
|
|
7
|
-
* Uses a priority-ordered detection chain to identify which AI coding
|
|
8
|
-
* platform the CLI is running within, based on filesystem markers
|
|
9
|
-
* and environment variables.
|
|
10
|
-
*
|
|
11
|
-
* Detection priority:
|
|
12
|
-
* 1. --target flag (explicit override)
|
|
13
|
-
* 2. .cursorrules file -> Cursor
|
|
14
|
-
* 3. CLAUDE.md file -> Claude Code
|
|
15
|
-
* 4. .vscode/ directory -> VS Code
|
|
16
|
-
* 5. GEMINI_CLI env var -> Gemini CLI
|
|
17
|
-
* 6. CODEX_ env var prefix -> Codex
|
|
18
|
-
* 7. Default fallback -> Claude Code
|
|
19
|
-
*
|
|
20
|
-
* Story 42.8
|
|
21
|
-
*/
|
|
22
|
-
import { existsSync } from 'node:fs';
|
|
23
|
-
import { join } from 'node:path';
|
|
24
|
-
// ── Valid Target IDs ────────────────────────────────────────────────────────
|
|
25
|
-
const VALID_TARGETS = new Set([
|
|
26
|
-
'claude-code',
|
|
27
|
-
'cursor',
|
|
28
|
-
'vscode',
|
|
29
|
-
'gemini-cli',
|
|
30
|
-
'codex',
|
|
31
|
-
'antigravity',
|
|
32
|
-
]);
|
|
33
|
-
/** Check if a string is a valid TargetId */
|
|
34
|
-
export function isValidTargetId(value) {
|
|
35
|
-
return VALID_TARGETS.has(value);
|
|
36
|
-
}
|
|
37
|
-
const defaultFileExists = (path) => existsSync(path);
|
|
38
|
-
// ── Detection Function ──────────────────────────────────────────────────────
|
|
39
|
-
/**
|
|
40
|
-
* Detect the current platform target based on the execution context.
|
|
41
|
-
*
|
|
42
|
-
* @param context - Detection context with cwd, env, and optional target flag
|
|
43
|
-
* @param fileExists - Injectable filesystem check (for testing)
|
|
44
|
-
* @returns Detection result with target ID, confidence, and reason
|
|
45
|
-
*/
|
|
46
|
-
export function detectPlatform(context, fileExists = defaultFileExists) {
|
|
47
|
-
// 1. Explicit --target flag (highest priority)
|
|
48
|
-
if (context.targetFlag) {
|
|
49
|
-
const normalized = context.targetFlag.toLowerCase().trim();
|
|
50
|
-
if (isValidTargetId(normalized)) {
|
|
51
|
-
return {
|
|
52
|
-
targetId: normalized,
|
|
53
|
-
confidence: 1.0,
|
|
54
|
-
reason: `Explicit --target=${normalized} flag`,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
// Invalid target flag falls through to auto-detection
|
|
58
|
-
}
|
|
59
|
-
// 2. .cursorrules file -> Cursor
|
|
60
|
-
if (fileExists(join(context.cwd, '.cursorrules'))) {
|
|
61
|
-
return {
|
|
62
|
-
targetId: 'cursor',
|
|
63
|
-
confidence: 0.95,
|
|
64
|
-
reason: 'Found .cursorrules file in project root',
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
// 3. CLAUDE.md file -> Claude Code
|
|
68
|
-
if (fileExists(join(context.cwd, 'CLAUDE.md'))) {
|
|
69
|
-
return {
|
|
70
|
-
targetId: 'claude-code',
|
|
71
|
-
confidence: 0.9,
|
|
72
|
-
reason: 'Found CLAUDE.md file in project root',
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
// 4. .vscode/ directory -> VS Code
|
|
76
|
-
if (fileExists(join(context.cwd, '.vscode'))) {
|
|
77
|
-
return {
|
|
78
|
-
targetId: 'vscode',
|
|
79
|
-
confidence: 0.7,
|
|
80
|
-
reason: 'Found .vscode/ directory in project root',
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
// 5. GEMINI_CLI env var -> Gemini CLI
|
|
84
|
-
if (context.env['GEMINI_CLI'] !== undefined) {
|
|
85
|
-
return {
|
|
86
|
-
targetId: 'gemini-cli',
|
|
87
|
-
confidence: 0.9,
|
|
88
|
-
reason: 'GEMINI_CLI environment variable is set',
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
// 6. Any env var with CODEX_ prefix -> Codex
|
|
92
|
-
const hasCodexEnv = Object.keys(context.env).some((key) => key.startsWith('CODEX_'));
|
|
93
|
-
if (hasCodexEnv) {
|
|
94
|
-
return {
|
|
95
|
-
targetId: 'codex',
|
|
96
|
-
confidence: 0.85,
|
|
97
|
-
reason: 'Found environment variable with CODEX_ prefix',
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
// 7. Default fallback -> Claude Code
|
|
101
|
-
return {
|
|
102
|
-
targetId: 'claude-code',
|
|
103
|
-
confidence: 0.5,
|
|
104
|
-
reason: 'Default fallback (no platform markers detected)',
|
|
105
|
-
};
|
|
106
|
-
}
|
|
1
|
+
import{existsSync as t}from"node:fs";import{join as n}from"node:path";const d=new Set(["claude-code","cursor","vscode","gemini-cli","codex","antigravity"]);function i(e){return d.has(e)}const c=e=>t(e);function u(e,o=c){if(e.targetFlag){const r=e.targetFlag.toLowerCase().trim();if(i(r))return{targetId:r,confidence:1,reason:`Explicit --target=${r} flag`}}return o(n(e.cwd,".cursorrules"))?{targetId:"cursor",confidence:.95,reason:"Found .cursorrules file in project root"}:o(n(e.cwd,"CLAUDE.md"))?{targetId:"claude-code",confidence:.9,reason:"Found CLAUDE.md file in project root"}:o(n(e.cwd,".vscode"))?{targetId:"vscode",confidence:.7,reason:"Found .vscode/ directory in project root"}:e.env.GEMINI_CLI!==void 0?{targetId:"gemini-cli",confidence:.9,reason:"GEMINI_CLI environment variable is set"}:Object.keys(e.env).some(r=>r.startsWith("CODEX_"))?{targetId:"codex",confidence:.85,reason:"Found environment variable with CODEX_ prefix"}:{targetId:"claude-code",confidence:.5,reason:"Default fallback (no platform markers detected)"}}export{u as detectPlatform,i as isValidTargetId};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license FSL-1.1
|
|
3
|
-
* Copyright (c) 2026 OrNexus AI
|
|
4
|
-
*
|
|
5
|
-
* TargetAdapter Interface - Core abstraction for platform-specific prompt formatting.
|
|
6
|
-
*
|
|
7
|
-
* Each platform target (Claude Code, Cursor, VS Code, Gemini CLI, Codex, Antigravity)
|
|
8
|
-
* implements this interface to transform assembled prompts into platform-native format.
|
|
9
|
-
*
|
|
10
|
-
* Story 42.8
|
|
11
|
-
*/
|
|
12
|
-
export {};
|
|
@@ -1,72 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* Copyright (c) 2026 OrNexus AI
|
|
4
|
-
*
|
|
5
|
-
* VS Code Adapter - Formats prompts for VS Code extension chat participant API.
|
|
6
|
-
*
|
|
7
|
-
* VS Code uses extensions and the chat API for AI interactions.
|
|
8
|
-
* This adapter formats prompts as system messages with structured
|
|
9
|
-
* instruction blocks suitable for the chat participant API.
|
|
10
|
-
*
|
|
11
|
-
* Story 42.8
|
|
12
|
-
*/
|
|
13
|
-
// ── Constants ───────────────────────────────────────────────────────────────
|
|
14
|
-
const TARGET_ID = 'vscode';
|
|
15
|
-
const MAX_CONTEXT_LENGTH = 128_000;
|
|
16
|
-
const CAPABILITIES = {
|
|
17
|
-
supportsMarkdown: true,
|
|
18
|
-
supportsMultiFile: true,
|
|
19
|
-
supportsMultiTurn: true,
|
|
20
|
-
supportsTools: true,
|
|
21
|
-
maxContextLength: MAX_CONTEXT_LENGTH,
|
|
22
|
-
};
|
|
23
|
-
// ── Implementation ──────────────────────────────────────────────────────────
|
|
24
|
-
export class VSCodeAdapter {
|
|
25
|
-
formatPrompt(assembledPrompt, platformInstructions, config) {
|
|
26
|
-
const sections = [];
|
|
27
|
-
// System instruction block for VS Code chat
|
|
28
|
-
sections.push('<system-instructions>');
|
|
29
|
-
sections.push(assembledPrompt);
|
|
30
|
-
sections.push('</system-instructions>');
|
|
31
|
-
// Tool definitions block
|
|
32
|
-
if (platformInstructions.tools && platformInstructions.tools.length > 0) {
|
|
33
|
-
sections.push('');
|
|
34
|
-
sections.push('<available-tools>');
|
|
35
|
-
for (const tool of platformInstructions.tools) {
|
|
36
|
-
sections.push(`- ${tool}`);
|
|
37
|
-
}
|
|
38
|
-
sections.push('</available-tools>');
|
|
39
|
-
}
|
|
40
|
-
// MCP configuration block
|
|
41
|
-
if (platformInstructions.mcpConfig && Object.keys(platformInstructions.mcpConfig).length > 0) {
|
|
42
|
-
sections.push('');
|
|
43
|
-
sections.push('<mcp-config>');
|
|
44
|
-
sections.push(JSON.stringify(platformInstructions.mcpConfig, null, 2));
|
|
45
|
-
sections.push('</mcp-config>');
|
|
46
|
-
}
|
|
47
|
-
// Context files as instruction references
|
|
48
|
-
if (platformInstructions.contextFiles && platformInstructions.contextFiles.length > 0) {
|
|
49
|
-
sections.push('');
|
|
50
|
-
sections.push('<context-files>');
|
|
51
|
-
for (const file of platformInstructions.contextFiles) {
|
|
52
|
-
sections.push(file);
|
|
53
|
-
}
|
|
54
|
-
sections.push('</context-files>');
|
|
55
|
-
}
|
|
56
|
-
let result = sections.join('\n');
|
|
57
|
-
const maxLength = config.maxPromptLength ?? MAX_CONTEXT_LENGTH;
|
|
58
|
-
if (result.length > maxLength) {
|
|
59
|
-
result = result.slice(0, maxLength);
|
|
60
|
-
}
|
|
61
|
-
return result;
|
|
62
|
-
}
|
|
63
|
-
getTargetId() {
|
|
64
|
-
return TARGET_ID;
|
|
65
|
-
}
|
|
66
|
-
getCapabilities() {
|
|
67
|
-
return CAPABILITIES;
|
|
68
|
-
}
|
|
69
|
-
getInjectionMethod() {
|
|
70
|
-
return 'api';
|
|
71
|
-
}
|
|
72
|
-
}
|
|
1
|
+
const u="vscode",c=128e3,h={supportsMarkdown:!0,supportsMultiFile:!0,supportsMultiTurn:!0,supportsTools:!0,maxContextLength:128e3};class g{formatPrompt(n,t,p){const e=[];if(e.push("<system-instructions>"),e.push(n),e.push("</system-instructions>"),t.tools&&t.tools.length>0){e.push(""),e.push("<available-tools>");for(const o of t.tools)e.push(`- ${o}`);e.push("</available-tools>")}if(t.mcpConfig&&Object.keys(t.mcpConfig).length>0&&(e.push(""),e.push("<mcp-config>"),e.push(JSON.stringify(t.mcpConfig,null,2)),e.push("</mcp-config>")),t.contextFiles&&t.contextFiles.length>0){e.push(""),e.push("<context-files>");for(const o of t.contextFiles)e.push(o);e.push("</context-files>")}let s=e.join(`
|
|
2
|
+
`);const i=p.maxPromptLength??128e3;return s.length>i&&(s=s.slice(0,i)),s}getTargetId(){return u}getCapabilities(){return h}getInjectionMethod(){return"api"}}export{g as VSCodeAdapter};
|
|
@@ -1,234 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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 - Stub Refresh Module
|
|
15
|
-
*
|
|
16
|
-
* Detects version mismatch between installed stubs and CLI version.
|
|
17
|
-
* Re-copies full stub files from the package when outdated.
|
|
18
|
-
*
|
|
19
|
-
* Called by activate.ts BEFORE updateAgentDescription() to ensure
|
|
20
|
-
* the stub file has all current sections (Banner, Plugin Guard, etc.)
|
|
21
|
-
* before the regex patcher runs.
|
|
22
|
-
*
|
|
23
|
-
* Never throws -- stub refresh is non-critical.
|
|
24
|
-
*
|
|
25
|
-
* Story 55.1
|
|
26
|
-
*/
|
|
27
|
-
import { readFileSync, writeFileSync, copyFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
28
|
-
import { join, dirname } from 'node:path';
|
|
29
|
-
import { homedir } from 'node:os';
|
|
30
|
-
import { fileURLToPath } from 'node:url';
|
|
31
|
-
import { setSecureFilePermissions } from '../config/secure-config.js';
|
|
32
|
-
// -- Banner Frame Constants ---------------------------------------------------
|
|
33
|
-
const BANNER_INNER = 60;
|
|
34
|
-
const BANNER_PREFIX_INNER = 25;
|
|
35
|
-
// -- Version Patching ---------------------------------------------------------
|
|
36
|
-
/**
|
|
37
|
-
* Replace all version strings in a stub file with the given version.
|
|
38
|
-
* Handles 4 patterns:
|
|
39
|
-
* 1. Emoji description: 🧠 Neocortex vX.Y.Z
|
|
40
|
-
* 2. Plain markdown header: # Neocortex vX.Y.Z
|
|
41
|
-
* 3. Banner line: │ ### ######## vX.Y.Z ...│
|
|
42
|
-
* 4. YAML version field: version: 'X.Y.Z'
|
|
43
|
-
*
|
|
44
|
-
* Never throws -- version patching is best-effort.
|
|
45
|
-
* Story 71.2
|
|
46
|
-
*/
|
|
47
|
-
export function patchVersionInFile(filePath, version) {
|
|
48
|
-
try {
|
|
49
|
-
let content = readFileSync(filePath, 'utf-8');
|
|
50
|
-
const original = content;
|
|
51
|
-
// Pattern 1: Emoji description/header (🧠 Neocortex vX.Y.Z)
|
|
52
|
-
content = content.replace(/🧠 Neocortex v[\d.]+/g, `🧠 Neocortex v${version}`);
|
|
53
|
-
// Pattern 2: Plain markdown header (# Neocortex vX.Y.Z)
|
|
54
|
-
content = content.replace(/# Neocortex v[\d.]+/g, `# Neocortex v${version}`);
|
|
55
|
-
// Pattern 3: Banner version line (│ ### ######## vX.Y.Z ...│)
|
|
56
|
-
content = content.replace(/^(│ ### ######## v)[\d.]+(\s*│)$/gm, () => {
|
|
57
|
-
const ver = `v${version}`;
|
|
58
|
-
const pad = BANNER_INNER - BANNER_PREFIX_INNER - ver.length;
|
|
59
|
-
return `\u2502 ### ######## ${ver}${' '.repeat(Math.max(0, pad))}\u2502`;
|
|
60
|
-
});
|
|
61
|
-
// Pattern 4: YAML version field (version: 'X.Y.Z')
|
|
62
|
-
content = content.replace(/version: '[\d.]+'/g, `version: '${version}'`);
|
|
63
|
-
if (content !== original) {
|
|
64
|
-
writeFileSync(filePath, content, 'utf-8');
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
catch {
|
|
68
|
-
// Non-critical -- version patching is best-effort
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
const STUB_TARGETS = [
|
|
72
|
-
{
|
|
73
|
-
destDir: join(homedir(), '.claude', 'agents', 'neocortex'),
|
|
74
|
-
sourceDir: 'claude-code',
|
|
75
|
-
files: ['neocortex.md', 'neocortex.agent.yaml'],
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
destDir: join(homedir(), '.gemini', 'agents'),
|
|
79
|
-
sourceDir: 'gemini-cli',
|
|
80
|
-
files: ['agent.md'],
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
destDir: join(homedir(), '.cursor', 'agents'),
|
|
84
|
-
sourceDir: 'cursor',
|
|
85
|
-
files: ['agent.md'],
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
destDir: join(homedir(), '.codex'),
|
|
89
|
-
sourceDir: 'codex',
|
|
90
|
-
files: ['agents.md'],
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
destDir: join(homedir(), '.vscode'),
|
|
94
|
-
sourceDir: 'vscode',
|
|
95
|
-
files: ['agent.md'],
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
destDir: join(homedir(), '.agent', 'skills', 'neocortex'),
|
|
99
|
-
sourceDir: 'antigravity',
|
|
100
|
-
files: ['skill/SKILL.md'],
|
|
101
|
-
},
|
|
102
|
-
];
|
|
103
|
-
// -- Package Root Resolution --------------------------------------------------
|
|
104
|
-
/**
|
|
105
|
-
* Find the monorepo / npm package root by walking up from this file's location.
|
|
106
|
-
* Looks for a package.json with name '@ornexus/neocortex' (monorepo root) or
|
|
107
|
-
* '@neocortex/client' (client package root that contains targets-stubs after build).
|
|
108
|
-
*
|
|
109
|
-
* Returns null if not found within 10 levels.
|
|
110
|
-
*/
|
|
111
|
-
export function findPackageRoot() {
|
|
112
|
-
try {
|
|
113
|
-
const thisFile = fileURLToPath(import.meta.url);
|
|
114
|
-
let dir = dirname(thisFile);
|
|
115
|
-
for (let i = 0; i < 10; i++) {
|
|
116
|
-
try {
|
|
117
|
-
const pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf-8'));
|
|
118
|
-
if (pkg.name === '@ornexus/neocortex') {
|
|
119
|
-
return dir;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
catch { /* no package.json at this level */ }
|
|
123
|
-
dir = dirname(dir);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
catch { /* fallback */ }
|
|
127
|
-
return null;
|
|
128
|
-
}
|
|
129
|
-
// -- Version Comparison -------------------------------------------------------
|
|
130
|
-
/**
|
|
131
|
-
* Read the installed version from .version file in the dest directory.
|
|
132
|
-
* Returns null if file doesn't exist or is unreadable.
|
|
133
|
-
*/
|
|
134
|
-
function readInstalledVersion(destDir) {
|
|
135
|
-
try {
|
|
136
|
-
const versionFile = join(destDir, '.version');
|
|
137
|
-
if (existsSync(versionFile)) {
|
|
138
|
-
return readFileSync(versionFile, 'utf-8').trim() || null;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
catch { /* unreadable */ }
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Refresh installed stubs if CLI version differs from installed version.
|
|
146
|
-
*
|
|
147
|
-
* For each stub target:
|
|
148
|
-
* 1. Read .version from install dir
|
|
149
|
-
* 2. Compare with cliVersion
|
|
150
|
-
* 3. If different (or .version missing): re-copy all stub files + write .version
|
|
151
|
-
* 4. If same: skip (no-op)
|
|
152
|
-
*
|
|
153
|
-
* When options.forceCreate is true, creates destDir if it doesn't exist.
|
|
154
|
-
* When options.targetFilter is set, only processes matching target.
|
|
155
|
-
*
|
|
156
|
-
* Never throws -- stub refresh is non-critical.
|
|
157
|
-
* Returns the number of targets that were refreshed.
|
|
158
|
-
*/
|
|
159
|
-
export function refreshStubs(cliVersion, options) {
|
|
160
|
-
try {
|
|
161
|
-
const forceCreate = options?.forceCreate ?? false;
|
|
162
|
-
const targetFilter = options?.targetFilter;
|
|
163
|
-
const packageRoot = findPackageRoot();
|
|
164
|
-
if (!packageRoot) {
|
|
165
|
-
return 0;
|
|
166
|
-
}
|
|
167
|
-
// targets-stubs/ is at the package root level
|
|
168
|
-
const stubsRoot = join(packageRoot, 'targets-stubs');
|
|
169
|
-
if (!existsSync(stubsRoot)) {
|
|
170
|
-
return 0;
|
|
171
|
-
}
|
|
172
|
-
let refreshed = 0;
|
|
173
|
-
for (const target of STUB_TARGETS) {
|
|
174
|
-
try {
|
|
175
|
-
// If targetFilter is set, skip non-matching targets
|
|
176
|
-
if (targetFilter && target.sourceDir !== targetFilter) {
|
|
177
|
-
continue;
|
|
178
|
-
}
|
|
179
|
-
// Epic 67 - Story 67.3: If forceCreate, create destDir when it doesn't exist
|
|
180
|
-
if (!existsSync(target.destDir)) {
|
|
181
|
-
if (forceCreate) {
|
|
182
|
-
mkdirSync(target.destDir, { recursive: true });
|
|
183
|
-
}
|
|
184
|
-
else {
|
|
185
|
-
continue;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
const installedVersion = readInstalledVersion(target.destDir);
|
|
189
|
-
if (installedVersion === cliVersion) {
|
|
190
|
-
continue; // Already up to date
|
|
191
|
-
}
|
|
192
|
-
// Source directory for this target
|
|
193
|
-
const sourceDir = join(stubsRoot, target.sourceDir);
|
|
194
|
-
if (!existsSync(sourceDir)) {
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
// Copy each file
|
|
198
|
-
let copiedAny = false;
|
|
199
|
-
for (const file of target.files) {
|
|
200
|
-
const src = join(sourceDir, file);
|
|
201
|
-
const dest = join(target.destDir, file);
|
|
202
|
-
if (existsSync(src)) {
|
|
203
|
-
// Ensure parent directory exists (handles nested paths like skill/SKILL.md)
|
|
204
|
-
mkdirSync(dirname(dest), { recursive: true });
|
|
205
|
-
copyFileSync(src, dest);
|
|
206
|
-
// Story 71.2: Substitute version strings in copied stubs
|
|
207
|
-
if (file.endsWith('.md') || file.endsWith('.yaml') || file.endsWith('.yml')) {
|
|
208
|
-
patchVersionInFile(dest, cliVersion);
|
|
209
|
-
}
|
|
210
|
-
// Story 66.3 AC1: Apply ACL/chmod after copy (runs after patchVersionInFile rewrite)
|
|
211
|
-
setSecureFilePermissions(dest);
|
|
212
|
-
copiedAny = true;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
// Write .version file
|
|
216
|
-
if (copiedAny) {
|
|
217
|
-
const versionPath = join(target.destDir, '.version');
|
|
218
|
-
writeFileSync(versionPath, cliVersion + '\n', 'utf-8');
|
|
219
|
-
// Story 66.3 AC2: Apply ACL/chmod on .version file
|
|
220
|
-
setSecureFilePermissions(versionPath);
|
|
221
|
-
refreshed++;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
catch {
|
|
225
|
-
// Non-critical -- continue with next target
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
return refreshed;
|
|
229
|
-
}
|
|
230
|
-
catch {
|
|
231
|
-
// Non-critical -- entire function is best-effort
|
|
232
|
-
return 0;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
1
|
+
import{readFileSync as d,writeFileSync as x,copyFileSync as N,existsSync as l,mkdirSync as y}from"node:fs";import{join as r,dirname as m}from"node:path";import{homedir as s}from"node:os";import{fileURLToPath as S}from"node:url";import{setSecureFilePermissions as v}from"../config/secure-config.js";const F=60,R=25;function k(o,t){try{let e=d(o,"utf-8");const c=e;e=e.replace(/🧠 Neocortex v[\d.]+/g,`\u{1F9E0} Neocortex v${t}`),e=e.replace(/# Neocortex v[\d.]+/g,`# Neocortex v${t}`),e=e.replace(/^(│ ### ######## v)[\d.]+(\s*│)$/gm,()=>{const a=`v${t}`,u=F-R-a.length;return`\u2502 ### ######## ${a}${" ".repeat(Math.max(0,u))}\u2502`}),e=e.replace(/version: '[\d.]+'/g,`version: '${t}'`),e!==c&&x(o,e,"utf-8")}catch{}}const $=[{destDir:r(s(),".claude","agents","neocortex"),sourceDir:"claude-code",files:["neocortex.md","neocortex.agent.yaml"]},{destDir:r(s(),".gemini","agents"),sourceDir:"gemini-cli",files:["agent.md"]},{destDir:r(s(),".cursor","agents"),sourceDir:"cursor",files:["agent.md"]},{destDir:r(s(),".codex"),sourceDir:"codex",files:["agents.md"]},{destDir:r(s(),".vscode"),sourceDir:"vscode",files:["agent.md"]},{destDir:r(s(),".agent","skills","neocortex"),sourceDir:"antigravity",files:["skill/SKILL.md"]}];function E(){try{const o=S(import.meta.url);let t=m(o);for(let e=0;e<10;e++){try{if(JSON.parse(d(r(t,"package.json"),"utf-8")).name==="@ornexus/neocortex")return t}catch{}t=m(t)}}catch{}return null}function I(o){try{const t=r(o,".version");if(l(t))return d(t,"utf-8").trim()||null}catch{}return null}function L(o,t){try{const e=t?.forceCreate??!1,c=t?.targetFilter,a=E();if(!a)return 0;const u=r(a,"targets-stubs");if(!l(u))return 0;let g=0;for(const i of $)try{if(c&&i.sourceDir!==c)continue;if(!l(i.destDir))if(e)y(i.destDir,{recursive:!0});else continue;if(I(i.destDir)===o)continue;const p=r(u,i.sourceDir);if(!l(p))continue;let D=!1;for(const n of i.files){const h=r(p,n),f=r(i.destDir,n);l(h)&&(y(m(f),{recursive:!0}),N(h,f),(n.endsWith(".md")||n.endsWith(".yaml")||n.endsWith(".yml"))&&k(f,o),v(f),D=!0)}if(D){const n=r(i.destDir,".version");x(n,o+`
|
|
2
|
+
`,"utf-8"),v(n),g++}}catch{}return g}catch{return 0}}export{E as findPackageRoot,k as patchVersionInFile,L as refreshStubs};
|