@nexrall/code-core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +155 -0
  3. package/dist/agent/agentTypes.d.ts +17 -0
  4. package/dist/agent/agentTypes.d.ts.map +1 -0
  5. package/dist/agent/agentTypes.js +156 -0
  6. package/dist/agent/loop.d.ts +3 -0
  7. package/dist/agent/loop.d.ts.map +1 -0
  8. package/dist/agent/loop.js +775 -0
  9. package/dist/api/client.d.ts +27 -0
  10. package/dist/api/client.d.ts.map +1 -0
  11. package/dist/api/client.js +414 -0
  12. package/dist/auth/index.d.ts +7 -0
  13. package/dist/auth/index.d.ts.map +1 -0
  14. package/dist/auth/index.js +95 -0
  15. package/dist/checkpoint/manager.d.ts +86 -0
  16. package/dist/checkpoint/manager.d.ts.map +1 -0
  17. package/dist/checkpoint/manager.js +409 -0
  18. package/dist/commands/loader.d.ts +18 -0
  19. package/dist/commands/loader.d.ts.map +1 -0
  20. package/dist/commands/loader.js +183 -0
  21. package/dist/index.d.ts +14 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +30 -0
  24. package/dist/mcp/client.d.ts +46 -0
  25. package/dist/mcp/client.d.ts.map +1 -0
  26. package/dist/mcp/client.js +128 -0
  27. package/dist/mcp/httpClient.d.ts +25 -0
  28. package/dist/mcp/httpClient.d.ts.map +1 -0
  29. package/dist/mcp/httpClient.js +143 -0
  30. package/dist/mcp/manager.d.ts +56 -0
  31. package/dist/mcp/manager.d.ts.map +1 -0
  32. package/dist/mcp/manager.js +234 -0
  33. package/dist/mcp/sseClient.d.ts +30 -0
  34. package/dist/mcp/sseClient.d.ts.map +1 -0
  35. package/dist/mcp/sseClient.js +224 -0
  36. package/dist/permissions/rules.d.ts +20 -0
  37. package/dist/permissions/rules.d.ts.map +1 -0
  38. package/dist/permissions/rules.js +218 -0
  39. package/dist/plugins/index.d.ts +18 -0
  40. package/dist/plugins/index.d.ts.map +1 -0
  41. package/dist/plugins/index.js +139 -0
  42. package/dist/tools/executor.d.ts +6 -0
  43. package/dist/tools/executor.d.ts.map +1 -0
  44. package/dist/tools/executor.js +1458 -0
  45. package/dist/tools/sandbox.d.ts +13 -0
  46. package/dist/tools/sandbox.d.ts.map +1 -0
  47. package/dist/tools/sandbox.js +140 -0
  48. package/dist/tools/symbols.d.ts +13 -0
  49. package/dist/tools/symbols.d.ts.map +1 -0
  50. package/dist/tools/symbols.js +279 -0
  51. package/dist/types.d.ts +186 -0
  52. package/dist/types.d.ts.map +1 -0
  53. package/dist/types.js +4 -0
  54. package/package.json +92 -0
@@ -0,0 +1,13 @@
1
+ export interface SandboxConfig {
2
+ enabled: boolean;
3
+ network: boolean;
4
+ writePaths: string[];
5
+ }
6
+ export declare function parseSandboxConfig(raw: unknown): SandboxConfig | null;
7
+ export interface WrapResult {
8
+ command: string;
9
+ sandboxed: boolean;
10
+ note?: string;
11
+ }
12
+ export declare function wrapCommandForSandbox(command: string, workDir: string, cfg: SandboxConfig): WrapResult;
13
+ //# sourceMappingURL=sandbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/tools/sandbox.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAarE;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAiCD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,GAAG,UAAU,CAoDtG"}
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parseSandboxConfig = parseSandboxConfig;
37
+ exports.wrapCommandForSandbox = wrapCommandForSandbox;
38
+ const child_process_1 = require("child_process");
39
+ const os = __importStar(require("os"));
40
+ function parseSandboxConfig(raw) {
41
+ if (raw === undefined || raw === null || raw === false || raw === 'off')
42
+ return null;
43
+ if (raw === true || raw === 'workspace-write')
44
+ return { enabled: true, network: false, writePaths: [] };
45
+ if (typeof raw === 'object') {
46
+ const o = raw;
47
+ if (o.enabled === false)
48
+ return null;
49
+ return {
50
+ enabled: true,
51
+ network: o.network === true,
52
+ writePaths: Array.isArray(o.writePaths) ? o.writePaths.filter((x) => typeof x === 'string') : [],
53
+ };
54
+ }
55
+ return null;
56
+ }
57
+ let _bwrapChecked = false;
58
+ let _bwrapAvailable = false;
59
+ function commandExists(cmd) {
60
+ try {
61
+ (0, child_process_1.execSync)(`command -v ${cmd}`, { stdio: 'ignore' });
62
+ return true;
63
+ }
64
+ catch {
65
+ return false;
66
+ }
67
+ }
68
+ function shQuote(s) {
69
+ return `'${s.replace(/'/g, `'\\''`)}'`;
70
+ }
71
+ function buildSeatbeltProfile(writePaths, allowNetwork) {
72
+ // Seatbelt evaluates rules top-down, last match wins:
73
+ // allow everything, revoke all writes, then re-grant writes to specific roots.
74
+ const writeRules = writePaths.map((p) => `(subpath ${JSON.stringify(p)})`).join(' ');
75
+ const lines = [
76
+ '(version 1)',
77
+ '(allow default)',
78
+ '(deny file-write*)',
79
+ `(allow file-write* ${writeRules})`,
80
+ '(allow file-write-data (literal "/dev/null") (literal "/dev/stdout") (literal "/dev/stderr") (literal "/dev/dtracehelper") (literal "/dev/tty"))',
81
+ ];
82
+ if (!allowNetwork)
83
+ lines.push('(deny network*)');
84
+ return lines.join('\n');
85
+ }
86
+ function wrapCommandForSandbox(command, workDir, cfg) {
87
+ const platform = os.platform();
88
+ if (platform === 'darwin') {
89
+ const writePaths = Array.from(new Set([workDir, '/tmp', '/private/tmp', '/private/var/folders', os.tmpdir(), ...cfg.writePaths]));
90
+ const profile = buildSeatbeltProfile(writePaths, cfg.network);
91
+ return {
92
+ command: `sandbox-exec -p ${shQuote(profile)} /bin/sh -c ${shQuote(command)}`,
93
+ sandboxed: true,
94
+ };
95
+ }
96
+ if (platform === 'linux') {
97
+ if (!_bwrapChecked) {
98
+ _bwrapAvailable = commandExists('bwrap');
99
+ _bwrapChecked = true;
100
+ }
101
+ if (!_bwrapAvailable) {
102
+ return { command, sandboxed: false, note: 'sandbox requested but bubblewrap (bwrap) is not installed — running unsandboxed.' };
103
+ }
104
+ const args = [
105
+ '--ro-bind / /',
106
+ '--dev /dev',
107
+ '--proc /proc',
108
+ '--tmpfs /tmp',
109
+ `--bind ${shQuote(workDir)} ${shQuote(workDir)}`,
110
+ ];
111
+ for (const p of cfg.writePaths)
112
+ args.push(`--bind ${shQuote(p)} ${shQuote(p)}`);
113
+ if (!cfg.network)
114
+ args.push('--unshare-net');
115
+ args.push('--die-with-parent', `--chdir ${shQuote(workDir)}`);
116
+ return {
117
+ command: `bwrap ${args.join(' ')} /bin/sh -c ${shQuote(command)}`,
118
+ sandboxed: true,
119
+ };
120
+ }
121
+ if (platform === 'win32') {
122
+ // Windows has no lightweight in-process sandbox primitive equivalent to
123
+ // Seatbelt (macOS) or bubblewrap (Linux):
124
+ // - AppContainer / job objects need native code + token manipulation, not
125
+ // something we can wrap a shell string with.
126
+ // - Windows Sandbox (WSB) is full-VM, per-invocation boot ≈ seconds, and
127
+ // is unavailable on Home editions — unusable per bash call.
128
+ // Claude Code has the same limitation (no sandbox on Windows).
129
+ // Practical guidance: run inside WSL where bwrap works, so tell the user.
130
+ return {
131
+ command,
132
+ sandboxed: false,
133
+ note: 'sandbox requested but Windows has no supported OS sandbox — running unsandboxed. ' +
134
+ 'Tip: run Nexrall Code inside WSL to get bubblewrap sandboxing, and rely on ' +
135
+ 'permission rules (.nexrall/settings.json) for command gating on native Windows.',
136
+ };
137
+ }
138
+ return { command, sandboxed: false, note: `sandbox not supported on ${platform} — running unsandboxed.` };
139
+ }
140
+ //# sourceMappingURL=sandbox.js.map
@@ -0,0 +1,13 @@
1
+ import type { ToolResult } from '../types';
2
+ interface SymbolHit {
3
+ name: string;
4
+ kind: string;
5
+ line: number;
6
+ }
7
+ export declare function supportedSymbolExts(): Set<string>;
8
+ /** Extract top-level-ish symbols from source text. Regex-based, best-effort. */
9
+ export declare function extractSymbols(filePath: string, source: string): SymbolHit[];
10
+ export declare function getSymbols(input: Record<string, unknown>, workDir?: string): Promise<ToolResult>;
11
+ export declare function getWorkspaceSymbols(input: Record<string, unknown>, workDir?: string): Promise<ToolResult>;
12
+ export {};
13
+ //# sourceMappingURL=symbols.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbols.d.ts","sourceRoot":"","sources":["../../src/tools/symbols.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAY3C,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAuGD,wBAAgB,mBAAmB,IAAI,GAAG,CAAC,MAAM,CAAC,CAEjD;AAID,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,CA6B5E;AASD,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAoBtG;AAQD,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAmD/G"}
@@ -0,0 +1,279 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.supportedSymbolExts = supportedSymbolExts;
37
+ exports.extractSymbols = extractSymbols;
38
+ exports.getSymbols = getSymbols;
39
+ exports.getWorkspaceSymbols = getWorkspaceSymbols;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ // NOTE: patterns are matched per-line against trimmed lines; ^ anchors the
43
+ // trimmed line start, so indented (nested/exported) declarations still match.
44
+ const LANGS = [
45
+ {
46
+ exts: ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.mts', '.cts'],
47
+ patterns: [
48
+ { re: /^export\s+default\s+(?:async\s+)?function\s*\*?\s*([A-Za-z_$][\w$]*)/, kind: 'function' },
49
+ { re: /^(?:export\s+)?(?:async\s+)?function\s*\*?\s*([A-Za-z_$][\w$]*)/, kind: 'function' },
50
+ { re: /^(?:export\s+)?(?:abstract\s+)?class\s+([A-Za-z_$][\w$]*)/, kind: 'class' },
51
+ { re: /^(?:export\s+)?interface\s+([A-Za-z_$][\w$]*)/, kind: 'interface' },
52
+ { re: /^(?:export\s+)?type\s+([A-Za-z_$][\w$]*)\s*=/, kind: 'type' },
53
+ { re: /^(?:export\s+)?(?:const\s+)?enum\s+([A-Za-z_$][\w$]*)/, kind: 'enum' },
54
+ { re: /^(?:export\s+)?const\s+([A-Za-z_$][\w$]*)\s*(?::[^=]+)?=\s*(?:async\s*)?\(/, kind: 'function' },
55
+ { re: /^(?:export\s+)?(?:const|let|var)\s+([A-Za-z_$][\w$]*)/, kind: 'variable' },
56
+ ],
57
+ },
58
+ {
59
+ exts: ['.py'],
60
+ patterns: [
61
+ { re: /^(?:async\s+)?def\s+([A-Za-z_]\w*)/, kind: 'function' },
62
+ { re: /^class\s+([A-Za-z_]\w*)/, kind: 'class' },
63
+ { re: /^([A-Z][A-Z0-9_]*)\s*(?::[^=]+)?=/, kind: 'constant' },
64
+ ],
65
+ },
66
+ {
67
+ exts: ['.go'],
68
+ patterns: [
69
+ { re: /^func\s+(?:\([^)]*\)\s*)?([A-Za-z_]\w*)/, kind: 'function' },
70
+ { re: /^type\s+([A-Za-z_]\w*)\s+struct\b/, kind: 'struct' },
71
+ { re: /^type\s+([A-Za-z_]\w*)\s+interface\b/, kind: 'interface' },
72
+ { re: /^type\s+([A-Za-z_]\w*)/, kind: 'type' },
73
+ { re: /^(?:var|const)\s+([A-Za-z_]\w*)/, kind: 'variable' },
74
+ ],
75
+ },
76
+ {
77
+ exts: ['.rs'],
78
+ patterns: [
79
+ { re: /^(?:pub(?:\([^)]*\))?\s+)?(?:async\s+)?fn\s+([A-Za-z_]\w*)/, kind: 'function' },
80
+ { re: /^(?:pub(?:\([^)]*\))?\s+)?struct\s+([A-Za-z_]\w*)/, kind: 'struct' },
81
+ { re: /^(?:pub(?:\([^)]*\))?\s+)?enum\s+([A-Za-z_]\w*)/, kind: 'enum' },
82
+ { re: /^(?:pub(?:\([^)]*\))?\s+)?trait\s+([A-Za-z_]\w*)/, kind: 'trait' },
83
+ { re: /^impl(?:<[^>]*>)?\s+(?:[\w:]+\s+for\s+)?([A-Za-z_]\w*)/, kind: 'impl' },
84
+ { re: /^(?:pub(?:\([^)]*\))?\s+)?(?:const|static)\s+([A-Za-z_]\w*)/, kind: 'constant' },
85
+ ],
86
+ },
87
+ {
88
+ exts: ['.java', '.kt', '.kts', '.scala'],
89
+ patterns: [
90
+ { re: /^(?:public|private|protected|internal)?\s*(?:static\s+)?(?:abstract\s+)?(?:final\s+)?(?:data\s+)?class\s+([A-Za-z_]\w*)/, kind: 'class' },
91
+ { re: /^(?:public|private|protected|internal)?\s*interface\s+([A-Za-z_]\w*)/, kind: 'interface' },
92
+ { re: /^(?:public|private|protected|internal)?\s*enum(?:\s+class)?\s+([A-Za-z_]\w*)/, kind: 'enum' },
93
+ { re: /^(?:public|private|protected|internal)?\s*(?:suspend\s+)?fun\s+([A-Za-z_]\w*)/, kind: 'function' },
94
+ { re: /^(?:public|private|protected|internal)?\s*(?:object|trait)\s+([A-Za-z_]\w*)/, kind: 'object' },
95
+ { re: /^def\s+([A-Za-z_]\w*)/, kind: 'function' },
96
+ ],
97
+ },
98
+ {
99
+ exts: ['.rb'],
100
+ patterns: [
101
+ { re: /^(?:def\s+(?:self\.)?)([A-Za-z_]\w*[?!=]?)/, kind: 'method' },
102
+ { re: /^class\s+([A-Z]\w*)/, kind: 'class' },
103
+ { re: /^module\s+([A-Z]\w*)/, kind: 'module' },
104
+ ],
105
+ },
106
+ {
107
+ exts: ['.php'],
108
+ patterns: [
109
+ { re: /^(?:abstract\s+|final\s+)?class\s+([A-Za-z_]\w*)/, kind: 'class' },
110
+ { re: /^interface\s+([A-Za-z_]\w*)/, kind: 'interface' },
111
+ { re: /^trait\s+([A-Za-z_]\w*)/, kind: 'trait' },
112
+ { re: /^(?:public\s+|private\s+|protected\s+|static\s+)*function\s+([A-Za-z_]\w*)/, kind: 'function' },
113
+ ],
114
+ },
115
+ {
116
+ exts: ['.c', '.h', '.cpp', '.hpp', '.cc', '.hh', '.m', '.mm'],
117
+ patterns: [
118
+ { re: /^(?:typedef\s+)?struct\s+([A-Za-z_]\w*)/, kind: 'struct' },
119
+ { re: /^(?:typedef\s+)?enum\s+([A-Za-z_]\w*)/, kind: 'enum' },
120
+ { re: /^class\s+([A-Za-z_]\w*)/, kind: 'class' },
121
+ { re: /^namespace\s+([A-Za-z_]\w*)/, kind: 'namespace' },
122
+ { re: /^#define\s+([A-Za-z_]\w*)/, kind: 'macro' },
123
+ // Function definitions: return-type + name + ( … no trailing ; on the line
124
+ { re: /^(?:static\s+|inline\s+|extern\s+|virtual\s+)*[A-Za-z_][\w:<>*&\s]*[\s*&]([A-Za-z_]\w*)\s*\([^;]*$/, kind: 'function' },
125
+ ],
126
+ },
127
+ {
128
+ exts: ['.sh', '.bash', '.zsh'],
129
+ patterns: [
130
+ { re: /^(?:function\s+)?([A-Za-z_][\w-]*)\s*\(\)\s*\{?/, kind: 'function' },
131
+ ],
132
+ },
133
+ ];
134
+ const EXT_TO_LANG = new Map();
135
+ for (const lang of LANGS)
136
+ for (const ext of lang.exts)
137
+ EXT_TO_LANG.set(ext, lang);
138
+ function supportedSymbolExts() {
139
+ return new Set(EXT_TO_LANG.keys());
140
+ }
141
+ const MAX_FILE_BYTES = 1024 * 1024; // 1 MB — bigger files are skipped in workspace scan
142
+ /** Extract top-level-ish symbols from source text. Regex-based, best-effort. */
143
+ function extractSymbols(filePath, source) {
144
+ const lang = EXT_TO_LANG.get(path.extname(filePath).toLowerCase());
145
+ if (!lang)
146
+ return [];
147
+ const hits = [];
148
+ const lines = source.split('\n');
149
+ let inBlockComment = false;
150
+ for (let i = 0; i < lines.length; i++) {
151
+ const trimmed = lines[i].trim();
152
+ if (!trimmed)
153
+ continue;
154
+ // Cheap comment skipping (good enough for symbol scanning)
155
+ if (inBlockComment) {
156
+ if (trimmed.includes('*/'))
157
+ inBlockComment = false;
158
+ continue;
159
+ }
160
+ if (trimmed.startsWith('/*')) {
161
+ if (!trimmed.includes('*/'))
162
+ inBlockComment = true;
163
+ continue;
164
+ }
165
+ // Skip line comments. '#' is a comment in py/rb/sh, but their declaration
166
+ // patterns all start with keywords (def/class/module/function) so '#' lines
167
+ // never match anyway — only '//' and doc-block continuation need skipping.
168
+ // '#define' must pass through for the C macro pattern.
169
+ if (trimmed.startsWith('//') || trimmed.startsWith('* '))
170
+ continue;
171
+ for (const { re, kind } of lang.patterns) {
172
+ const m = re.exec(trimmed);
173
+ if (m && m[1]) {
174
+ hits.push({ name: m[1], kind, line: i + 1 });
175
+ break; // first matching pattern wins for a line
176
+ }
177
+ }
178
+ }
179
+ return hits;
180
+ }
181
+ function resolveIn(workDir, p) {
182
+ const base = workDir ?? process.cwd();
183
+ return path.isAbsolute(p) ? p : path.resolve(base, p);
184
+ }
185
+ // ─── get_symbols (single file) ────────────────────────────────────────────────
186
+ async function getSymbols(input, workDir) {
187
+ const rel = typeof input.path === 'string' ? input.path : '';
188
+ if (!rel)
189
+ return { error: 'path is required' };
190
+ const abs = resolveIn(workDir, rel);
191
+ let source;
192
+ try {
193
+ const st = fs.statSync(abs);
194
+ if (!st.isFile())
195
+ return { error: `Not a file: ${rel}` };
196
+ if (st.size > MAX_FILE_BYTES)
197
+ return { error: `File too large for symbol scan (${Math.round(st.size / 1024)} KB > 1024 KB)` };
198
+ source = fs.readFileSync(abs, 'utf-8');
199
+ }
200
+ catch (err) {
201
+ return { error: `Cannot read ${rel}: ${err.message}` };
202
+ }
203
+ if (!EXT_TO_LANG.has(path.extname(abs).toLowerCase())) {
204
+ return { output: `No symbol support for ${path.extname(abs) || 'this file type'} (regex-based scanner). Use search_files instead.` };
205
+ }
206
+ const hits = extractSymbols(abs, source);
207
+ if (!hits.length)
208
+ return { output: `No symbols found in ${rel}.` };
209
+ const lines = hits.map((h) => `${h.kind.padEnd(10)} ${h.name} (line ${h.line})`);
210
+ return { output: `Symbols in ${rel} (${hits.length}):\n${lines.join('\n')}` };
211
+ }
212
+ // ─── get_workspace_symbols (project-wide) ─────────────────────────────────────
213
+ const SKIP_DIRS = new Set(['.git', 'node_modules', 'dist', 'build', 'out', '.next', '__pycache__', '.turbo', 'coverage', 'vendor', 'target', '.venv', 'venv']);
214
+ const MAX_RESULTS = 100;
215
+ const MAX_FILES_SCANNED = 20000;
216
+ async function getWorkspaceSymbols(input, workDir) {
217
+ const query = typeof input.query === 'string' ? input.query.trim() : '';
218
+ if (!query)
219
+ return { error: 'query is required' };
220
+ const root = workDir ?? process.cwd();
221
+ const q = query.toLowerCase();
222
+ const exts = supportedSymbolExts();
223
+ const results = [];
224
+ let scanned = 0;
225
+ const walk = (dir) => {
226
+ if (results.length >= MAX_RESULTS || scanned >= MAX_FILES_SCANNED)
227
+ return;
228
+ let entries;
229
+ try {
230
+ entries = fs.readdirSync(dir, { withFileTypes: true });
231
+ }
232
+ catch {
233
+ return;
234
+ }
235
+ for (const entry of entries) {
236
+ if (results.length >= MAX_RESULTS || scanned >= MAX_FILES_SCANNED)
237
+ return;
238
+ const full = path.join(dir, entry.name);
239
+ if (entry.isDirectory()) {
240
+ if (SKIP_DIRS.has(entry.name) || entry.name.startsWith('.'))
241
+ continue;
242
+ walk(full);
243
+ }
244
+ else if (entry.isFile() && exts.has(path.extname(entry.name).toLowerCase())) {
245
+ scanned++;
246
+ try {
247
+ const st = fs.statSync(full);
248
+ if (st.size > MAX_FILE_BYTES)
249
+ continue;
250
+ const source = fs.readFileSync(full, 'utf-8');
251
+ // Cheap pre-filter: skip files that don't even contain the query text
252
+ if (!source.toLowerCase().includes(q))
253
+ continue;
254
+ for (const h of extractSymbols(full, source)) {
255
+ if (h.name.toLowerCase().includes(q)) {
256
+ results.push({ ...h, file: path.relative(root, full) });
257
+ if (results.length >= MAX_RESULTS)
258
+ break;
259
+ }
260
+ }
261
+ }
262
+ catch { /* unreadable file — skip */ }
263
+ }
264
+ }
265
+ };
266
+ walk(root);
267
+ if (!results.length)
268
+ return { output: `No symbols matching "${query}" found (regex-based scan).` };
269
+ // Exact-name matches first, then partial, alphabetical within groups.
270
+ results.sort((a, b) => {
271
+ const aExact = a.name.toLowerCase() === q ? 0 : 1;
272
+ const bExact = b.name.toLowerCase() === q ? 0 : 1;
273
+ return aExact - bExact || a.name.localeCompare(b.name);
274
+ });
275
+ const lines = results.map((r) => `${r.kind.padEnd(10)} ${r.name} ${r.file}:${r.line}`);
276
+ const capNote = results.length >= MAX_RESULTS ? `\n[Capped at ${MAX_RESULTS} results]` : '';
277
+ return { output: `Symbols matching "${query}" (${results.length}):\n${lines.join('\n')}${capNote}` };
278
+ }
279
+ //# sourceMappingURL=symbols.js.map
@@ -0,0 +1,186 @@
1
+ export interface TextBlock {
2
+ type: 'text';
3
+ text: string;
4
+ }
5
+ export interface ToolUseBlock {
6
+ type: 'tool_use';
7
+ id: string;
8
+ name: string;
9
+ input: Record<string, unknown>;
10
+ }
11
+ export interface ToolResultBlock {
12
+ type: 'tool_result';
13
+ tool_use_id: string;
14
+ content: string;
15
+ is_error?: boolean;
16
+ }
17
+ export type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock;
18
+ export interface Message {
19
+ role: 'user' | 'assistant';
20
+ content: ContentBlock[];
21
+ }
22
+ export interface SSETextEvent {
23
+ type: 'text';
24
+ text: string;
25
+ }
26
+ export interface SSEToolUseEvent {
27
+ type: 'tool_use';
28
+ id: string;
29
+ name: string;
30
+ input: Record<string, unknown>;
31
+ }
32
+ export interface SSEMessageCompleteEvent {
33
+ type: 'message_complete';
34
+ message: Message;
35
+ }
36
+ export interface SSEUsageEvent {
37
+ type: 'usage';
38
+ usage: UsageInfo;
39
+ }
40
+ export interface SSEDoneEvent {
41
+ type: 'done';
42
+ }
43
+ export interface SSEErrorEvent {
44
+ type: 'error';
45
+ message: string;
46
+ }
47
+ export interface SSEThinkingEvent {
48
+ type: 'thinking';
49
+ text: string;
50
+ }
51
+ export interface SSEThinkingProgressEvent {
52
+ type: 'thinking_progress';
53
+ tokens: number;
54
+ }
55
+ export interface SSEThinkingDeltaEvent {
56
+ type: 'thinking_delta';
57
+ text: string;
58
+ }
59
+ export type SSEEvent = SSETextEvent | SSEToolUseEvent | SSEMessageCompleteEvent | SSEUsageEvent | SSEDoneEvent | SSEErrorEvent | SSEThinkingEvent | SSEThinkingProgressEvent | SSEThinkingDeltaEvent;
60
+ export interface UsageInfo {
61
+ input_tokens: number;
62
+ output_tokens: number;
63
+ cache_creation_input_tokens?: number;
64
+ cache_read_input_tokens?: number;
65
+ }
66
+ export interface ToolResult {
67
+ output?: string;
68
+ error?: string;
69
+ interrupted?: boolean;
70
+ }
71
+ export interface AuthConfig {
72
+ token: string;
73
+ email?: string;
74
+ }
75
+ export interface PermissionRequest {
76
+ tool: string;
77
+ input: Record<string, unknown>;
78
+ description: string;
79
+ }
80
+ export interface EnvContext {
81
+ cwd?: string;
82
+ platform?: string;
83
+ shell?: string;
84
+ gitBranch?: string;
85
+ gitStatus?: string;
86
+ gitDiff?: string;
87
+ date?: string;
88
+ recentCommits?: string;
89
+ }
90
+ export interface EditorContext {
91
+ activeFile?: string;
92
+ selectedText?: string;
93
+ cursorLine?: number;
94
+ openTabs?: string[];
95
+ /** Diagnostics for the active file only (errors + warnings). */
96
+ diagnostics?: Array<{
97
+ severity: string;
98
+ file: string;
99
+ line: number;
100
+ message: string;
101
+ }>;
102
+ /** Workspace-wide diagnostics aggregated across all files. */
103
+ workspaceDiagnostics?: Array<{
104
+ severity: string;
105
+ file: string;
106
+ line: number;
107
+ column: number;
108
+ message: string;
109
+ }>;
110
+ /** Shallow project file tree (2 levels, noise-filtered). */
111
+ projectTree?: string;
112
+ /** Symbols (functions, classes, etc.) in the currently active file. */
113
+ currentFileSymbols?: string;
114
+ }
115
+ export interface AgentLoopOptions {
116
+ workDir: string;
117
+ abortSignal?: {
118
+ aborted: boolean;
119
+ };
120
+ onText: (t: string) => void;
121
+ onThinking?: (text: string) => void;
122
+ onThinkingDelta?: (text: string) => void;
123
+ onThinkingProgress?: (tokens: number) => void;
124
+ onToolUse: (name: string, input: Record<string, unknown>, isSubTask?: boolean) => void;
125
+ onToolResult: (name: string, result: ToolResult, isSubTask?: boolean) => void;
126
+ onUsage: (u: UsageInfo) => void;
127
+ model?: 'turbo' | 'pro' | 'ultra';
128
+ mode?: string;
129
+ effort?: string;
130
+ requestPermission: (req: PermissionRequest) => Promise<boolean>;
131
+ env?: EnvContext;
132
+ editorContext?: EditorContext | null;
133
+ nexrallMd?: string;
134
+ /** Client type — controls which tools Claude is told about. */
135
+ clientType?: string;
136
+ /**
137
+ * Optional executor for platform-specific tools (e.g. VS Code semantic tools).
138
+ * Return null to fall through to the default executor.
139
+ */
140
+ executeExternalTool?: (name: string, input: Record<string, unknown>) => Promise<ToolResult | null>;
141
+ /** MCP manager — provides extra tool definitions + executes MCP tool calls. */
142
+ mcpManager?: import('./mcp/manager').McpManager;
143
+ /** Checkpoint manager — snapshots files before mutations so the user can /rewind. */
144
+ checkpointManager?: import('./checkpoint/manager').CheckpointManager;
145
+ /**
146
+ * Drain follow-up messages the user queued WHILE the agent was working (Claude-Code
147
+ * style). Called at turn boundaries inside the loop; returned strings are folded into
148
+ * the conversation so the agent picks them up at the next step — mid-task, without
149
+ * waiting for the whole turn to finish. Return [] when nothing is queued.
150
+ */
151
+ takePendingInput?: () => string[];
152
+ /** Notify that a queued follow-up was injected into the conversation (for UI echo/logging). */
153
+ onInjectedInput?: (text: string) => void;
154
+ /**
155
+ * Max agent iterations (model response + tool round) before the runaway-loop
156
+ * backstop trips. Overrides the NEXRALL_MAX_ITERATIONS env var and the
157
+ * `maxIterations` setting in .nexrall/settings.json. Defaults to 500 (capped
158
+ * at 1000). Not a task-size budget — large tasks legitimately need many rounds.
159
+ */
160
+ maxIterations?: number;
161
+ /**
162
+ * When the soft `maxIterations` budget runs out with work still pending, keep
163
+ * going (extend the budget in segments up to an absolute 2000-step ceiling)
164
+ * instead of stopping, so long tasks finish without the user typing "continue".
165
+ * A stall guard stops it if consecutive tool rounds all fail. Overrides the
166
+ * NEXRALL_AUTO_CONTINUE env var and `autoContinue` in .nexrall/settings.json.
167
+ * Defaults to true.
168
+ */
169
+ autoContinue?: boolean;
170
+ /**
171
+ * Automatically summarise older conversation history when the prompt exceeds
172
+ * ~80% of the model's context window, so long sessions never hit the wall.
173
+ * Overrides NEXRALL_AUTO_COMPACT env var and `autoCompact` in settings.json.
174
+ * Defaults to true.
175
+ */
176
+ autoCompact?: boolean;
177
+ /** Internal: recursion depth for sub-agents. Main agent = 0. */
178
+ _depth?: number;
179
+ /**
180
+ * Internal: isolation key for per-agent tool state (todo lists). The main
181
+ * agent uses 'root'; each sub-agent gets a unique key so concurrent
182
+ * sub-agents don't clobber each other's todo lists.
183
+ */
184
+ _agentScope?: string;
185
+ }
186
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ // ─── Content Blocks ───────────────────────────────────────────────────────────
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=types.js.map