@nex-ai/nex 0.1.7
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/README.md +228 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.js +18 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/attribute.d.ts +4 -0
- package/dist/commands/attribute.js +75 -0
- package/dist/commands/attribute.js.map +1 -0
- package/dist/commands/config-cmd.d.ts +4 -0
- package/dist/commands/config-cmd.js +53 -0
- package/dist/commands/config-cmd.js.map +1 -0
- package/dist/commands/context.d.ts +4 -0
- package/dist/commands/context.js +135 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/insight.d.ts +4 -0
- package/dist/commands/insight.js +39 -0
- package/dist/commands/insight.js.map +1 -0
- package/dist/commands/integrate.d.ts +4 -0
- package/dist/commands/integrate.js +136 -0
- package/dist/commands/integrate.js.map +1 -0
- package/dist/commands/list-job.d.ts +4 -0
- package/dist/commands/list-job.js +41 -0
- package/dist/commands/list-job.js.map +1 -0
- package/dist/commands/list.d.ts +4 -0
- package/dist/commands/list.js +148 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/note.d.ts +4 -0
- package/dist/commands/note.js +77 -0
- package/dist/commands/note.js.map +1 -0
- package/dist/commands/object.d.ts +4 -0
- package/dist/commands/object.js +78 -0
- package/dist/commands/object.js.map +1 -0
- package/dist/commands/record.d.ts +4 -0
- package/dist/commands/record.js +126 -0
- package/dist/commands/record.js.map +1 -0
- package/dist/commands/register.d.ts +4 -0
- package/dist/commands/register.js +23 -0
- package/dist/commands/register.js.map +1 -0
- package/dist/commands/relationship.d.ts +4 -0
- package/dist/commands/relationship.js +80 -0
- package/dist/commands/relationship.js.map +1 -0
- package/dist/commands/scan.d.ts +4 -0
- package/dist/commands/scan.js +58 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/search.d.ts +4 -0
- package/dist/commands/search.js +22 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/session.d.ts +4 -0
- package/dist/commands/session.js +31 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/setup.d.ts +10 -0
- package/dist/commands/setup.js +254 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/task.d.ts +4 -0
- package/dist/commands/task.js +114 -0
- package/dist/commands/task.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/capture-filter.d.ts +9 -0
- package/dist/lib/capture-filter.js +14 -0
- package/dist/lib/capture-filter.js.map +1 -0
- package/dist/lib/client.d.ts +19 -0
- package/dist/lib/client.js +115 -0
- package/dist/lib/client.js.map +1 -0
- package/dist/lib/config.d.ts +34 -0
- package/dist/lib/config.js +59 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/context-format.d.ts +7 -0
- package/dist/lib/context-format.js +21 -0
- package/dist/lib/context-format.js.map +1 -0
- package/dist/lib/errors.d.ts +18 -0
- package/dist/lib/errors.js +30 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/file-scanner.d.ts +38 -0
- package/dist/lib/file-scanner.js +178 -0
- package/dist/lib/file-scanner.js.map +1 -0
- package/dist/lib/installers.d.ts +19 -0
- package/dist/lib/installers.js +205 -0
- package/dist/lib/installers.js.map +1 -0
- package/dist/lib/output.d.ts +7 -0
- package/dist/lib/output.js +50 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/lib/platform-detect.d.ts +16 -0
- package/dist/lib/platform-detect.js +188 -0
- package/dist/lib/platform-detect.js.map +1 -0
- package/dist/lib/project-config.d.ts +53 -0
- package/dist/lib/project-config.js +151 -0
- package/dist/lib/project-config.js.map +1 -0
- package/dist/lib/prompt.d.ts +4 -0
- package/dist/lib/prompt.js +21 -0
- package/dist/lib/prompt.js.map +1 -0
- package/dist/lib/rate-limiter.d.ts +13 -0
- package/dist/lib/rate-limiter.js +49 -0
- package/dist/lib/rate-limiter.js.map +1 -0
- package/dist/lib/recall-filter.d.ts +6 -0
- package/dist/lib/recall-filter.js +58 -0
- package/dist/lib/recall-filter.js.map +1 -0
- package/dist/lib/session-store.d.ts +15 -0
- package/dist/lib/session-store.js +62 -0
- package/dist/lib/session-store.js.map +1 -0
- package/package.json +32 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration resolution: CLI flags > env vars > config file.
|
|
3
|
+
* Base URL is hardcoded to production (NEX_DEV_URL escape hatch for local dev).
|
|
4
|
+
*/
|
|
5
|
+
export declare const CONFIG_PATH: string;
|
|
6
|
+
export declare const BASE_URL: string;
|
|
7
|
+
export declare const API_BASE: string;
|
|
8
|
+
export declare const REGISTER_URL: string;
|
|
9
|
+
export interface NexConfig {
|
|
10
|
+
api_key?: string;
|
|
11
|
+
workspace_id?: string;
|
|
12
|
+
workspace_slug?: string;
|
|
13
|
+
default_format?: string;
|
|
14
|
+
default_timeout?: number;
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
}
|
|
17
|
+
export declare function loadConfig(): NexConfig;
|
|
18
|
+
export declare function saveConfig(config: NexConfig): void;
|
|
19
|
+
/**
|
|
20
|
+
* Resolve API key from: flag > env > config file.
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveApiKey(flagValue?: string): string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Resolve output format from: flag > config file > default.
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveFormat(flagValue?: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Resolve timeout from: flag > config file > default.
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveTimeout(flagValue?: string): number;
|
|
31
|
+
/**
|
|
32
|
+
* Persist registration data to config file.
|
|
33
|
+
*/
|
|
34
|
+
export declare function persistRegistration(data: Record<string, unknown>): void;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration resolution: CLI flags > env vars > config file.
|
|
3
|
+
* Base URL is hardcoded to production (NEX_DEV_URL escape hatch for local dev).
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
6
|
+
import { join, dirname } from "node:path";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
export const CONFIG_PATH = join(homedir(), ".nex", "config.json");
|
|
9
|
+
export const BASE_URL = process.env.NEX_DEV_URL ?? "https://app.nex.ai";
|
|
10
|
+
export const API_BASE = `${BASE_URL}/api/developers`;
|
|
11
|
+
export const REGISTER_URL = `${BASE_URL}/api/v1/agents/register`;
|
|
12
|
+
export function loadConfig() {
|
|
13
|
+
try {
|
|
14
|
+
const raw = readFileSync(CONFIG_PATH, "utf-8");
|
|
15
|
+
return JSON.parse(raw);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function saveConfig(config) {
|
|
22
|
+
mkdirSync(dirname(CONFIG_PATH), { recursive: true });
|
|
23
|
+
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Resolve API key from: flag > env > config file.
|
|
27
|
+
*/
|
|
28
|
+
export function resolveApiKey(flagValue) {
|
|
29
|
+
return flagValue || process.env.NEX_API_KEY || loadConfig().api_key || undefined;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolve output format from: flag > config file > default.
|
|
33
|
+
*/
|
|
34
|
+
export function resolveFormat(flagValue) {
|
|
35
|
+
return flagValue || loadConfig().default_format || "json";
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolve timeout from: flag > config file > default.
|
|
39
|
+
*/
|
|
40
|
+
export function resolveTimeout(flagValue) {
|
|
41
|
+
if (flagValue)
|
|
42
|
+
return parseInt(flagValue, 10);
|
|
43
|
+
return loadConfig().default_timeout ?? 120_000;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Persist registration data to config file.
|
|
47
|
+
*/
|
|
48
|
+
export function persistRegistration(data) {
|
|
49
|
+
const existing = loadConfig();
|
|
50
|
+
if (typeof data.api_key === "string")
|
|
51
|
+
existing.api_key = data.api_key;
|
|
52
|
+
if (typeof data.workspace_id === "string" || typeof data.workspace_id === "number") {
|
|
53
|
+
existing.workspace_id = String(data.workspace_id);
|
|
54
|
+
}
|
|
55
|
+
if (typeof data.workspace_slug === "string")
|
|
56
|
+
existing.workspace_slug = data.workspace_slug;
|
|
57
|
+
saveConfig(existing);
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;AAClE,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,oBAAoB,CAAC;AACxE,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,QAAQ,iBAAiB,CAAC;AACrD,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,QAAQ,yBAAyB,CAAC;AAWjE,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAc,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAiB;IAC1C,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AAC9E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,SAAkB;IAC9C,OAAO,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,UAAU,EAAE,CAAC,OAAO,IAAI,SAAS,CAAC;AACnF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,SAAkB;IAC9C,OAAO,SAAS,IAAI,UAAU,EAAE,CAAC,cAAc,IAAI,MAAM,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,SAAkB;IAC/C,IAAI,SAAS;QAAE,OAAO,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAC9C,OAAO,UAAU,EAAE,CAAC,eAAe,IAAI,OAAO,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAA6B;IAC/D,MAAM,QAAQ,GAAG,UAAU,EAAE,CAAC;IAC9B,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ;QAAE,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IACtE,IAAI,OAAO,IAAI,CAAC,YAAY,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;QACnF,QAAQ,CAAC,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,OAAO,IAAI,CAAC,cAAc,KAAK,QAAQ;QAAE,QAAQ,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC;IAC3F,UAAU,CAAC,QAAQ,CAAC,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const OPEN_TAG = "<nex-context>";
|
|
2
|
+
const CLOSE_TAG = "</nex-context>";
|
|
3
|
+
export function formatNexContext(result) {
|
|
4
|
+
const parts = [
|
|
5
|
+
OPEN_TAG,
|
|
6
|
+
"The following is relevant context from the user's knowledge base. Use it to inform your response, but do not mention this block directly.",
|
|
7
|
+
];
|
|
8
|
+
if (result.entityCount > 0) {
|
|
9
|
+
parts.push(`[${result.entityCount} related entities found]`);
|
|
10
|
+
}
|
|
11
|
+
parts.push("");
|
|
12
|
+
parts.push(result.answer);
|
|
13
|
+
parts.push(CLOSE_TAG);
|
|
14
|
+
return parts.join("\n");
|
|
15
|
+
}
|
|
16
|
+
export function stripNexContext(text) {
|
|
17
|
+
let result = text.replace(/<nex-context>[\s\S]*?<\/nex-context>/g, "");
|
|
18
|
+
result = result.replace(/<nex-context>[\s\S]*/g, "");
|
|
19
|
+
return result.trim();
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=context-format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-format.js","sourceRoot":"","sources":["../../src/lib/context-format.ts"],"names":[],"mappings":"AAAA,MAAM,QAAQ,GAAG,eAAe,CAAC;AACjC,MAAM,SAAS,GAAG,gBAAgB,CAAC;AAQnC,MAAM,UAAU,gBAAgB,CAAC,MAAuB;IACtD,MAAM,KAAK,GAAa;QACtB,QAAQ;QACR,2IAA2I;KAC5I,CAAC;IACF,IAAI,MAAM,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,WAAW,0BAA0B,CAAC,CAAC;IAC/D,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC1B,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACtB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,uCAAuC,EAAE,EAAE,CAAC,CAAC;IACvE,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC;IACrD,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error types for Nex CLI.
|
|
3
|
+
* Exit codes: 0 = success, 1 = general error, 2 = auth error.
|
|
4
|
+
*/
|
|
5
|
+
export declare class AuthError extends Error {
|
|
6
|
+
exitCode: number;
|
|
7
|
+
constructor(message?: string);
|
|
8
|
+
}
|
|
9
|
+
export declare class RateLimitError extends Error {
|
|
10
|
+
exitCode: number;
|
|
11
|
+
retryAfterMs: number;
|
|
12
|
+
constructor(retryAfterMs?: number);
|
|
13
|
+
}
|
|
14
|
+
export declare class ServerError extends Error {
|
|
15
|
+
exitCode: number;
|
|
16
|
+
status: number;
|
|
17
|
+
constructor(status: number, body?: string);
|
|
18
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error types for Nex CLI.
|
|
3
|
+
* Exit codes: 0 = success, 1 = general error, 2 = auth error.
|
|
4
|
+
*/
|
|
5
|
+
export class AuthError extends Error {
|
|
6
|
+
exitCode = 2;
|
|
7
|
+
constructor(message = "No API key configured. Run 'nex register' or set NEX_API_KEY.") {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "AuthError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class RateLimitError extends Error {
|
|
13
|
+
exitCode = 1;
|
|
14
|
+
retryAfterMs;
|
|
15
|
+
constructor(retryAfterMs = 60_000) {
|
|
16
|
+
super(`Rate limited — retry after ${Math.ceil(retryAfterMs / 1000)}s`);
|
|
17
|
+
this.name = "RateLimitError";
|
|
18
|
+
this.retryAfterMs = retryAfterMs;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class ServerError extends Error {
|
|
22
|
+
exitCode = 1;
|
|
23
|
+
status;
|
|
24
|
+
constructor(status, body) {
|
|
25
|
+
super(`Nex API error ${status}${body ? `: ${body}` : ""}`);
|
|
26
|
+
this.name = "ServerError";
|
|
27
|
+
this.status = status;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,OAAO,SAAU,SAAQ,KAAK;IAC3B,QAAQ,GAAG,CAAC,CAAC;IAEpB,YAAY,OAAO,GAAG,+DAA+D;QACnF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,OAAO,cAAe,SAAQ,KAAK;IAChC,QAAQ,GAAG,CAAC,CAAC;IACb,YAAY,CAAS;IAE5B,YAAY,YAAY,GAAG,MAAM;QAC/B,KAAK,CAAC,8BAA8B,IAAI,CAAC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACvE,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC7B,QAAQ,GAAG,CAAC,CAAC;IACb,MAAM,CAAS;IAEtB,YAAY,MAAc,EAAE,IAAa;QACvC,KAAK,CAAC,iBAAiB,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File scanner — discovers text files, tracks changes via content hash,
|
|
3
|
+
* and ingests new/changed files into Nex via POST /v1/context/text.
|
|
4
|
+
*
|
|
5
|
+
* Manifest stored at ~/.nex/file-scan-manifest.json.
|
|
6
|
+
*/
|
|
7
|
+
export interface ManifestEntry {
|
|
8
|
+
hash: string;
|
|
9
|
+
size: number;
|
|
10
|
+
scanned_at: string;
|
|
11
|
+
}
|
|
12
|
+
export interface Manifest {
|
|
13
|
+
version: number;
|
|
14
|
+
files: Record<string, ManifestEntry>;
|
|
15
|
+
}
|
|
16
|
+
export interface ScanOptions {
|
|
17
|
+
extensions: string[];
|
|
18
|
+
maxFiles: number;
|
|
19
|
+
depth: number;
|
|
20
|
+
force: boolean;
|
|
21
|
+
dryRun: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface ScanResult {
|
|
24
|
+
scanned: number;
|
|
25
|
+
skipped: number;
|
|
26
|
+
errors: number;
|
|
27
|
+
files: Array<{
|
|
28
|
+
path: string;
|
|
29
|
+
status: "ingested" | "skipped" | "error";
|
|
30
|
+
reason?: string;
|
|
31
|
+
}>;
|
|
32
|
+
}
|
|
33
|
+
export declare const MANIFEST_PATH: string;
|
|
34
|
+
export declare function loadScanConfig(overrides?: Partial<ScanOptions>): ScanOptions;
|
|
35
|
+
export declare function isScanEnabled(): boolean;
|
|
36
|
+
export declare function loadManifest(): Manifest;
|
|
37
|
+
export declare function saveManifest(manifest: Manifest): void;
|
|
38
|
+
export declare function scanFiles(dir: string, opts: ScanOptions, ingestFn: (content: string, context: string) => Promise<unknown>): Promise<ScanResult>;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File scanner — discovers text files, tracks changes via content hash,
|
|
3
|
+
* and ingests new/changed files into Nex via POST /v1/context/text.
|
|
4
|
+
*
|
|
5
|
+
* Manifest stored at ~/.nex/file-scan-manifest.json.
|
|
6
|
+
*/
|
|
7
|
+
import { createHash } from "node:crypto";
|
|
8
|
+
import { readFileSync, writeFileSync, mkdirSync, statSync, readdirSync } from "node:fs";
|
|
9
|
+
import { join, extname, resolve, dirname } from "node:path";
|
|
10
|
+
import { homedir } from "node:os";
|
|
11
|
+
// --- Constants ---
|
|
12
|
+
export const MANIFEST_PATH = join(homedir(), ".nex", "file-scan-manifest.json");
|
|
13
|
+
const DEFAULT_EXTENSIONS = [
|
|
14
|
+
// Documents
|
|
15
|
+
".md", ".txt", ".rtf", ".html", ".htm",
|
|
16
|
+
// Data / config
|
|
17
|
+
".csv", ".tsv", ".json", ".yaml", ".yml", ".toml", ".xml",
|
|
18
|
+
// Code / scripts
|
|
19
|
+
".js", ".ts", ".jsx", ".tsx", ".py", ".rb", ".go", ".rs", ".java",
|
|
20
|
+
".sh", ".bash", ".zsh", ".fish",
|
|
21
|
+
// Markup / notes
|
|
22
|
+
".org", ".rst", ".adoc", ".tex", ".log",
|
|
23
|
+
// Config / CI
|
|
24
|
+
".env", ".ini", ".cfg", ".conf", ".properties",
|
|
25
|
+
];
|
|
26
|
+
const SKIP_DIRS = new Set([
|
|
27
|
+
"node_modules", ".git", "dist", "build", ".next", "__pycache__", ".venv",
|
|
28
|
+
".cache", ".turbo", "coverage", ".nyc_output",
|
|
29
|
+
]);
|
|
30
|
+
// --- Config from env ---
|
|
31
|
+
export function loadScanConfig(overrides) {
|
|
32
|
+
const envEnabled = process.env.NEX_SCAN_ENABLED;
|
|
33
|
+
if (envEnabled === "false" || envEnabled === "0") {
|
|
34
|
+
// Caller should check this separately; config still resolves
|
|
35
|
+
}
|
|
36
|
+
const envExts = process.env.NEX_SCAN_EXTENSIONS;
|
|
37
|
+
const extensions = overrides?.extensions
|
|
38
|
+
?? (envExts ? envExts.split(",").map((e) => e.trim()) : DEFAULT_EXTENSIONS);
|
|
39
|
+
const envMaxFiles = process.env.NEX_SCAN_MAX_FILES;
|
|
40
|
+
const maxFiles = overrides?.maxFiles
|
|
41
|
+
?? (envMaxFiles ? parseInt(envMaxFiles, 10) : 5);
|
|
42
|
+
const envDepth = process.env.NEX_SCAN_DEPTH;
|
|
43
|
+
const depth = overrides?.depth
|
|
44
|
+
?? (envDepth ? parseInt(envDepth, 10) : 20);
|
|
45
|
+
return {
|
|
46
|
+
extensions,
|
|
47
|
+
maxFiles,
|
|
48
|
+
depth,
|
|
49
|
+
force: overrides?.force ?? false,
|
|
50
|
+
dryRun: overrides?.dryRun ?? false,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export function isScanEnabled() {
|
|
54
|
+
const v = process.env.NEX_SCAN_ENABLED;
|
|
55
|
+
return v !== "false" && v !== "0";
|
|
56
|
+
}
|
|
57
|
+
// --- Manifest ---
|
|
58
|
+
export function loadManifest() {
|
|
59
|
+
try {
|
|
60
|
+
const raw = readFileSync(MANIFEST_PATH, "utf-8");
|
|
61
|
+
const data = JSON.parse(raw);
|
|
62
|
+
if (data.version === 1 && typeof data.files === "object")
|
|
63
|
+
return data;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// missing or corrupt
|
|
67
|
+
}
|
|
68
|
+
return { version: 1, files: {} };
|
|
69
|
+
}
|
|
70
|
+
export function saveManifest(manifest) {
|
|
71
|
+
mkdirSync(dirname(MANIFEST_PATH), { recursive: true });
|
|
72
|
+
writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
|
|
73
|
+
}
|
|
74
|
+
function discoverFiles(dir, extensions, maxDepth, currentDepth = 0) {
|
|
75
|
+
if (currentDepth > maxDepth)
|
|
76
|
+
return [];
|
|
77
|
+
const results = [];
|
|
78
|
+
let entries;
|
|
79
|
+
try {
|
|
80
|
+
entries = readdirSync(dir);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return results;
|
|
84
|
+
}
|
|
85
|
+
for (const entry of entries) {
|
|
86
|
+
if (entry.startsWith(".") && SKIP_DIRS.has(entry))
|
|
87
|
+
continue;
|
|
88
|
+
if (SKIP_DIRS.has(entry))
|
|
89
|
+
continue;
|
|
90
|
+
const fullPath = join(dir, entry);
|
|
91
|
+
let stat;
|
|
92
|
+
try {
|
|
93
|
+
stat = statSync(fullPath);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (stat.isDirectory()) {
|
|
99
|
+
results.push(...discoverFiles(fullPath, extensions, maxDepth, currentDepth + 1));
|
|
100
|
+
}
|
|
101
|
+
else if (stat.isFile() && extensions.has(extname(entry).toLowerCase())) {
|
|
102
|
+
results.push({ path: fullPath, size: stat.size, mtime: stat.mtimeMs });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return results;
|
|
106
|
+
}
|
|
107
|
+
// --- Hashing ---
|
|
108
|
+
function hashFile(filePath) {
|
|
109
|
+
const content = readFileSync(filePath);
|
|
110
|
+
return "sha256-" + createHash("sha256").update(content).digest("hex");
|
|
111
|
+
}
|
|
112
|
+
// --- Scanner ---
|
|
113
|
+
export async function scanFiles(dir, opts, ingestFn) {
|
|
114
|
+
const absDir = resolve(dir);
|
|
115
|
+
const extSet = new Set(opts.extensions.map((e) => (e.startsWith(".") ? e : `.${e}`).toLowerCase()));
|
|
116
|
+
// Discover files
|
|
117
|
+
const discovered = discoverFiles(absDir, extSet, opts.depth);
|
|
118
|
+
// Sort by mtime descending (newest first), cap at maxFiles
|
|
119
|
+
discovered.sort((a, b) => b.mtime - a.mtime);
|
|
120
|
+
const candidates = discovered.slice(0, opts.maxFiles);
|
|
121
|
+
const manifest = opts.force ? { version: 1, files: {} } : loadManifest();
|
|
122
|
+
const result = { scanned: 0, skipped: 0, errors: 0, files: [] };
|
|
123
|
+
for (const file of candidates) {
|
|
124
|
+
const hash = hashFile(file.path);
|
|
125
|
+
const existing = manifest.files[file.path];
|
|
126
|
+
// Skip if hash matches (already ingested)
|
|
127
|
+
if (existing && existing.hash === hash && !opts.force) {
|
|
128
|
+
result.skipped++;
|
|
129
|
+
result.files.push({ path: file.path, status: "skipped", reason: "unchanged" });
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
if (opts.dryRun) {
|
|
133
|
+
result.scanned++;
|
|
134
|
+
result.files.push({
|
|
135
|
+
path: file.path,
|
|
136
|
+
status: "ingested",
|
|
137
|
+
reason: existing ? "changed" : "new",
|
|
138
|
+
});
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
// Read and ingest
|
|
142
|
+
try {
|
|
143
|
+
const content = readFileSync(file.path, "utf-8");
|
|
144
|
+
if (!content.trim()) {
|
|
145
|
+
result.skipped++;
|
|
146
|
+
result.files.push({ path: file.path, status: "skipped", reason: "empty" });
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
await ingestFn(content, `file-scan:${file.path}`);
|
|
150
|
+
// Update manifest
|
|
151
|
+
manifest.files[file.path] = {
|
|
152
|
+
hash,
|
|
153
|
+
size: file.size,
|
|
154
|
+
scanned_at: new Date().toISOString(),
|
|
155
|
+
};
|
|
156
|
+
result.scanned++;
|
|
157
|
+
result.files.push({
|
|
158
|
+
path: file.path,
|
|
159
|
+
status: "ingested",
|
|
160
|
+
reason: existing ? "changed" : "new",
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
result.errors++;
|
|
165
|
+
result.files.push({
|
|
166
|
+
path: file.path,
|
|
167
|
+
status: "error",
|
|
168
|
+
reason: err instanceof Error ? err.message : String(err),
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Persist manifest (unless dry-run)
|
|
173
|
+
if (!opts.dryRun) {
|
|
174
|
+
saveManifest(manifest);
|
|
175
|
+
}
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=file-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-scanner.js","sourceRoot":"","sources":["../../src/lib/file-scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform-specific installers for Nex MCP server and Claude Code plugin.
|
|
3
|
+
*
|
|
4
|
+
* - Generic MCP installer handles 9/12 platforms (same JSON mcpServers format)
|
|
5
|
+
* - Claude Code installer handles hooks + slash commands
|
|
6
|
+
* - Zed installer uses context_servers instead of mcpServers
|
|
7
|
+
* - Continue.dev writes YAML config
|
|
8
|
+
*/
|
|
9
|
+
import type { Platform } from "./platform-detect.js";
|
|
10
|
+
export declare function installMcpServer(platform: Platform, apiKey: string): {
|
|
11
|
+
installed: boolean;
|
|
12
|
+
configPath: string;
|
|
13
|
+
};
|
|
14
|
+
export declare function installClaudeCodePlugin(pluginDir?: string): {
|
|
15
|
+
installed: boolean;
|
|
16
|
+
hooksAdded: string[];
|
|
17
|
+
commandsLinked: string[];
|
|
18
|
+
};
|
|
19
|
+
export declare function syncApiKeyToMcpConfig(apiKey: string): void;
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform-specific installers for Nex MCP server and Claude Code plugin.
|
|
3
|
+
*
|
|
4
|
+
* - Generic MCP installer handles 9/12 platforms (same JSON mcpServers format)
|
|
5
|
+
* - Claude Code installer handles hooks + slash commands
|
|
6
|
+
* - Zed installer uses context_servers instead of mcpServers
|
|
7
|
+
* - Continue.dev writes YAML config
|
|
8
|
+
*/
|
|
9
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, symlinkSync, readdirSync } from "node:fs";
|
|
10
|
+
import { join, dirname, resolve } from "node:path";
|
|
11
|
+
import { homedir } from "node:os";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = dirname(__filename);
|
|
15
|
+
const MCP_SERVER_ENTRY = {
|
|
16
|
+
command: "npx",
|
|
17
|
+
args: ["-y", "@nex-crm/mcp-server"],
|
|
18
|
+
env: {},
|
|
19
|
+
};
|
|
20
|
+
// --- Generic MCP Installer ---
|
|
21
|
+
function readJsonFile(path) {
|
|
22
|
+
try {
|
|
23
|
+
const raw = readFileSync(path, "utf-8");
|
|
24
|
+
return JSON.parse(raw);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function writeJsonFile(path, data) {
|
|
31
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
32
|
+
writeFileSync(path, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
33
|
+
}
|
|
34
|
+
export function installMcpServer(platform, apiKey) {
|
|
35
|
+
const entry = {
|
|
36
|
+
...MCP_SERVER_ENTRY,
|
|
37
|
+
env: { NEX_API_KEY: apiKey },
|
|
38
|
+
};
|
|
39
|
+
if (platform.configFormat === "zed") {
|
|
40
|
+
return installZedMcp(platform.configPath, entry);
|
|
41
|
+
}
|
|
42
|
+
if (platform.configFormat === "continue") {
|
|
43
|
+
return installContinueMcp(platform.configPath, apiKey);
|
|
44
|
+
}
|
|
45
|
+
// Standard JSON format (Cursor, Claude Desktop, VS Code, Windsurf, Cline, Kilo Code, OpenCode)
|
|
46
|
+
const config = readJsonFile(platform.configPath);
|
|
47
|
+
if (!config.mcpServers || typeof config.mcpServers !== "object") {
|
|
48
|
+
config.mcpServers = {};
|
|
49
|
+
}
|
|
50
|
+
config.mcpServers.nex = entry;
|
|
51
|
+
writeJsonFile(platform.configPath, config);
|
|
52
|
+
return { installed: true, configPath: platform.configPath };
|
|
53
|
+
}
|
|
54
|
+
function installZedMcp(configPath, entry) {
|
|
55
|
+
const config = readJsonFile(configPath);
|
|
56
|
+
if (!config.context_servers || typeof config.context_servers !== "object") {
|
|
57
|
+
config.context_servers = {};
|
|
58
|
+
}
|
|
59
|
+
config.context_servers.nex = {
|
|
60
|
+
command: { path: entry.command, args: entry.args, env: entry.env },
|
|
61
|
+
};
|
|
62
|
+
writeJsonFile(configPath, config);
|
|
63
|
+
return { installed: true, configPath };
|
|
64
|
+
}
|
|
65
|
+
function installContinueMcp(configPath, apiKey) {
|
|
66
|
+
// Continue.dev can also accept JSON in a separate mcpServers config
|
|
67
|
+
// Write a simple JSON file alongside the YAML
|
|
68
|
+
const mcpPath = configPath.replace("config.yaml", "mcp.json");
|
|
69
|
+
const config = readJsonFile(mcpPath);
|
|
70
|
+
if (!config.mcpServers || typeof config.mcpServers !== "object") {
|
|
71
|
+
config.mcpServers = {};
|
|
72
|
+
}
|
|
73
|
+
config.mcpServers.nex = {
|
|
74
|
+
...MCP_SERVER_ENTRY,
|
|
75
|
+
env: { NEX_API_KEY: apiKey },
|
|
76
|
+
};
|
|
77
|
+
writeJsonFile(mcpPath, config);
|
|
78
|
+
return { installed: true, configPath: mcpPath };
|
|
79
|
+
}
|
|
80
|
+
export function installClaudeCodePlugin(pluginDir) {
|
|
81
|
+
const home = homedir();
|
|
82
|
+
const claudeDir = join(home, ".claude");
|
|
83
|
+
const settingsPath = join(claudeDir, "settings.json");
|
|
84
|
+
// Resolve plugin directory — find it relative to the CLI package
|
|
85
|
+
const resolvedPluginDir = pluginDir ?? findPluginDir();
|
|
86
|
+
if (!resolvedPluginDir) {
|
|
87
|
+
return { installed: false, hooksAdded: [], commandsLinked: [] };
|
|
88
|
+
}
|
|
89
|
+
// 1. Read existing settings.json
|
|
90
|
+
let settings = {};
|
|
91
|
+
try {
|
|
92
|
+
const raw = readFileSync(settingsPath, "utf-8");
|
|
93
|
+
settings = JSON.parse(raw);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// Start fresh
|
|
97
|
+
}
|
|
98
|
+
if (!settings.hooks) {
|
|
99
|
+
settings.hooks = {};
|
|
100
|
+
}
|
|
101
|
+
const hooksAdded = [];
|
|
102
|
+
const distDir = join(resolvedPluginDir, "dist");
|
|
103
|
+
// 2. Add hooks (idempotent — check if nex hooks already exist)
|
|
104
|
+
const hookDefs = [
|
|
105
|
+
{
|
|
106
|
+
event: "SessionStart",
|
|
107
|
+
script: join(distDir, "auto-session-start.js"),
|
|
108
|
+
timeout: 120000,
|
|
109
|
+
statusMessage: "Loading knowledge context...",
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
event: "UserPromptSubmit",
|
|
113
|
+
script: join(distDir, "auto-recall.js"),
|
|
114
|
+
timeout: 10000,
|
|
115
|
+
statusMessage: "Recalling relevant memories...",
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
event: "Stop",
|
|
119
|
+
script: join(distDir, "auto-capture.js"),
|
|
120
|
+
timeout: 10000,
|
|
121
|
+
async: true,
|
|
122
|
+
},
|
|
123
|
+
];
|
|
124
|
+
for (const def of hookDefs) {
|
|
125
|
+
if (!settings.hooks[def.event]) {
|
|
126
|
+
settings.hooks[def.event] = [];
|
|
127
|
+
}
|
|
128
|
+
const groups = settings.hooks[def.event];
|
|
129
|
+
const alreadyInstalled = groups.some((g) => g.hooks.some((h) => h.command.includes("nex") || h.command.includes("auto-recall") || h.command.includes("auto-capture") || h.command.includes("auto-session-start")));
|
|
130
|
+
if (!alreadyInstalled) {
|
|
131
|
+
const hookEntry = {
|
|
132
|
+
type: "command",
|
|
133
|
+
command: `node ${def.script}`,
|
|
134
|
+
timeout: def.timeout,
|
|
135
|
+
};
|
|
136
|
+
if (def.statusMessage)
|
|
137
|
+
hookEntry.statusMessage = def.statusMessage;
|
|
138
|
+
if (def.async)
|
|
139
|
+
hookEntry.async = true;
|
|
140
|
+
groups.push({ matcher: "", hooks: [hookEntry] });
|
|
141
|
+
hooksAdded.push(def.event);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// 3. Write settings.json
|
|
145
|
+
mkdirSync(claudeDir, { recursive: true });
|
|
146
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
147
|
+
// 4. Symlink slash commands
|
|
148
|
+
const commandsLinked = [];
|
|
149
|
+
const commandsDir = join(claudeDir, "commands");
|
|
150
|
+
const sourceCommandsDir = join(resolvedPluginDir, "commands");
|
|
151
|
+
if (existsSync(sourceCommandsDir)) {
|
|
152
|
+
mkdirSync(commandsDir, { recursive: true });
|
|
153
|
+
try {
|
|
154
|
+
const entries = readdirSync(sourceCommandsDir);
|
|
155
|
+
for (const entry of entries) {
|
|
156
|
+
if (!entry.endsWith(".md"))
|
|
157
|
+
continue;
|
|
158
|
+
const target = join(commandsDir, entry);
|
|
159
|
+
const source = join(sourceCommandsDir, entry);
|
|
160
|
+
if (!existsSync(target)) {
|
|
161
|
+
try {
|
|
162
|
+
symlinkSync(source, target, "file");
|
|
163
|
+
commandsLinked.push(entry);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
// May fail if file already exists as regular file — skip
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
// Commands dir read failed — non-critical
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return { installed: true, hooksAdded, commandsLinked };
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Find the claude-code-plugin directory relative to the CLI install.
|
|
179
|
+
* Looks for it as a sibling package in the monorepo.
|
|
180
|
+
*/
|
|
181
|
+
function findPluginDir() {
|
|
182
|
+
// Try common locations
|
|
183
|
+
const candidates = [
|
|
184
|
+
// Sibling in monorepo (development)
|
|
185
|
+
resolve(__dirname, "..", "..", "..", "claude-code-plugin"),
|
|
186
|
+
// npm global install (node_modules sibling)
|
|
187
|
+
resolve(__dirname, "..", "..", "..", "..", "@nex-crm", "claude-code-nex-plugin"),
|
|
188
|
+
// Relative to cli package
|
|
189
|
+
resolve(__dirname, "..", "..", "claude-code-plugin"),
|
|
190
|
+
];
|
|
191
|
+
for (const candidate of candidates) {
|
|
192
|
+
if (existsSync(join(candidate, "package.json"))) {
|
|
193
|
+
return candidate;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
// --- Sync API key to ~/.nex-mcp.json ---
|
|
199
|
+
export function syncApiKeyToMcpConfig(apiKey) {
|
|
200
|
+
const mcpConfigPath = join(homedir(), ".nex-mcp.json");
|
|
201
|
+
const config = readJsonFile(mcpConfigPath);
|
|
202
|
+
config.api_key = apiKey;
|
|
203
|
+
writeJsonFile(mcpConfigPath, config);
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=installers.js.map
|