@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.
Files changed (62) hide show
  1. package/install.ps1 +92 -33
  2. package/install.sh +15 -1
  3. package/package.json +3 -3
  4. package/packages/client/dist/adapters/adapter-registry.js +1 -106
  5. package/packages/client/dist/adapters/antigravity-adapter.js +2 -77
  6. package/packages/client/dist/adapters/claude-code-adapter.js +3 -79
  7. package/packages/client/dist/adapters/codex-adapter.js +2 -80
  8. package/packages/client/dist/adapters/cursor-adapter.js +4 -115
  9. package/packages/client/dist/adapters/gemini-adapter.js +2 -71
  10. package/packages/client/dist/adapters/index.js +1 -21
  11. package/packages/client/dist/adapters/platform-detector.js +1 -106
  12. package/packages/client/dist/adapters/target-adapter.js +0 -12
  13. package/packages/client/dist/adapters/vscode-adapter.js +2 -72
  14. package/packages/client/dist/agent/refresh-stubs.js +2 -234
  15. package/packages/client/dist/agent/update-agent-yaml.js +1 -102
  16. package/packages/client/dist/agent/update-description.js +1 -251
  17. package/packages/client/dist/cache/crypto-utils.js +1 -76
  18. package/packages/client/dist/cache/encrypted-cache.js +1 -94
  19. package/packages/client/dist/cache/in-memory-asset-cache.js +1 -70
  20. package/packages/client/dist/cache/index.js +1 -13
  21. package/packages/client/dist/cli.js +2 -163
  22. package/packages/client/dist/commands/activate.js +8 -390
  23. package/packages/client/dist/commands/cache-status.js +2 -112
  24. package/packages/client/dist/commands/invoke.js +28 -490
  25. package/packages/client/dist/config/resolver-selection.js +1 -278
  26. package/packages/client/dist/config/secure-config.js +12 -269
  27. package/packages/client/dist/constants.js +1 -25
  28. package/packages/client/dist/context/context-collector.js +2 -222
  29. package/packages/client/dist/context/context-sanitizer.js +1 -145
  30. package/packages/client/dist/index.js +1 -38
  31. package/packages/client/dist/license/index.js +1 -5
  32. package/packages/client/dist/license/license-client.js +1 -257
  33. package/packages/client/dist/machine/fingerprint.js +2 -160
  34. package/packages/client/dist/machine/index.js +1 -5
  35. package/packages/client/dist/resilience/circuit-breaker.js +1 -170
  36. package/packages/client/dist/resilience/degradation-manager.js +1 -164
  37. package/packages/client/dist/resilience/freshness-indicator.js +1 -100
  38. package/packages/client/dist/resilience/index.js +1 -8
  39. package/packages/client/dist/resilience/recovery-detector.js +1 -74
  40. package/packages/client/dist/resolvers/asset-resolver.js +0 -13
  41. package/packages/client/dist/resolvers/local-resolver.js +8 -218
  42. package/packages/client/dist/resolvers/remote-resolver.js +1 -282
  43. package/packages/client/dist/telemetry/index.js +1 -5
  44. package/packages/client/dist/telemetry/offline-queue.js +1 -131
  45. package/packages/client/dist/tier/index.js +1 -5
  46. package/packages/client/dist/tier/tier-aware-client.js +1 -260
  47. package/packages/client/dist/types/index.js +1 -38
  48. package/targets-stubs/antigravity/gemini.md +1 -1
  49. package/targets-stubs/antigravity/install-antigravity.sh +49 -3
  50. package/targets-stubs/antigravity/skill/SKILL.md +23 -4
  51. package/targets-stubs/claude-code/neocortex.agent.yaml +19 -1
  52. package/targets-stubs/claude-code/neocortex.md +64 -29
  53. package/targets-stubs/codex/agents.md +20 -3
  54. package/targets-stubs/codex/config-mcp.toml +5 -0
  55. package/targets-stubs/cursor/agent.md +23 -5
  56. package/targets-stubs/cursor/install-cursor.sh +51 -3
  57. package/targets-stubs/cursor/mcp.json +7 -0
  58. package/targets-stubs/gemini-cli/agent.md +37 -6
  59. package/targets-stubs/gemini-cli/install-gemini.sh +50 -17
  60. package/targets-stubs/vscode/agent.md +47 -10
  61. package/targets-stubs/vscode/install-vscode.sh +50 -3
  62. package/targets-stubs/vscode/mcp.json +8 -0
@@ -1,115 +1,4 @@
1
- /**
2
- * @license FSL-1.1
3
- * Copyright (c) 2026 OrNexus AI
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
- * @license FSL-1.1
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
- * @license FSL-1.1
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
- * @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 - 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};