@nex-ai/nex 0.1.34 → 0.1.36
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 +18 -4
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/workspace-registry.d.ts +47 -0
- package/dist/lib/workspace-registry.js +240 -0
- package/dist/lib/workspace-registry.js.map +1 -0
- package/dist/mcp/channel.d.ts +28 -0
- package/dist/mcp/channel.js +135 -0
- package/dist/mcp/channel.js.map +1 -0
- package/dist/mcp/client.d.ts +20 -0
- package/dist/mcp/client.js +130 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/config.d.ts +14 -0
- package/dist/mcp/config.js +33 -0
- package/dist/mcp/config.js.map +1 -0
- package/dist/mcp/context-files.d.ts +9 -0
- package/dist/mcp/context-files.js +90 -0
- package/dist/mcp/context-files.js.map +1 -0
- package/dist/mcp/file-manifest.d.ts +27 -0
- package/dist/mcp/file-manifest.js +64 -0
- package/dist/mcp/file-manifest.js.map +1 -0
- package/dist/mcp/file-scanner.d.ts +17 -0
- package/dist/mcp/file-scanner.js +77 -0
- package/dist/mcp/file-scanner.js.map +1 -0
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.js +51 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/rate-limiter.d.ts +14 -0
- package/dist/mcp/rate-limiter.js +60 -0
- package/dist/mcp/rate-limiter.js.map +1 -0
- package/dist/mcp/server.d.ts +6 -0
- package/dist/mcp/server.js +42 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/session-store.d.ts +16 -0
- package/dist/mcp/session-store.js +70 -0
- package/dist/mcp/session-store.js.map +1 -0
- package/dist/mcp/tools/context.d.ts +3 -0
- package/dist/mcp/tools/context.js +65 -0
- package/dist/mcp/tools/context.js.map +1 -0
- package/dist/mcp/tools/insights.d.ts +3 -0
- package/dist/mcp/tools/insights.js +24 -0
- package/dist/mcp/tools/insights.js.map +1 -0
- package/dist/mcp/tools/integrations.d.ts +3 -0
- package/dist/mcp/tools/integrations.js +27 -0
- package/dist/mcp/tools/integrations.js.map +1 -0
- package/dist/mcp/tools/lists.d.ts +3 -0
- package/dist/mcp/tools/lists.js +101 -0
- package/dist/mcp/tools/lists.js.map +1 -0
- package/dist/mcp/tools/notes.d.ts +3 -0
- package/dist/mcp/tools/notes.js +52 -0
- package/dist/mcp/tools/notes.js.map +1 -0
- package/dist/mcp/tools/records.d.ts +3 -0
- package/dist/mcp/tools/records.js +74 -0
- package/dist/mcp/tools/records.js.map +1 -0
- package/dist/mcp/tools/register.d.ts +3 -0
- package/dist/mcp/tools/register.js +30 -0
- package/dist/mcp/tools/register.js.map +1 -0
- package/dist/mcp/tools/relationships.d.ts +3 -0
- package/dist/mcp/tools/relationships.js +47 -0
- package/dist/mcp/tools/relationships.js.map +1 -0
- package/dist/mcp/tools/scan.d.ts +3 -0
- package/dist/mcp/tools/scan.js +37 -0
- package/dist/mcp/tools/scan.js.map +1 -0
- package/dist/mcp/tools/schema.d.ts +3 -0
- package/dist/mcp/tools/schema.js +108 -0
- package/dist/mcp/tools/schema.js.map +1 -0
- package/dist/mcp/tools/search.d.ts +3 -0
- package/dist/mcp/tools/search.js +8 -0
- package/dist/mcp/tools/search.js.map +1 -0
- package/dist/mcp/tools/tasks.d.ts +3 -0
- package/dist/mcp/tools/tasks.js +88 -0
- package/dist/mcp/tools/tasks.js.map +1 -0
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -71,18 +71,19 @@ nex ask "what's the latest on the Acme deal?"
|
|
|
71
71
|
| **Claude Desktop** | — | — | — | — | — | `claude_desktop_config.json` |
|
|
72
72
|
| **Aider** | — | — | — | — | `CONVENTIONS.md` | — |
|
|
73
73
|
|
|
74
|
-
All MCP-based platforms use the same server entry:
|
|
74
|
+
All MCP-based platforms use the same server entry (bundled in this package):
|
|
75
75
|
|
|
76
76
|
```json
|
|
77
77
|
{
|
|
78
78
|
"nex": {
|
|
79
|
-
"command": "
|
|
80
|
-
"args": ["-y", "@nex-ai/mcp-server"],
|
|
79
|
+
"command": "nex-mcp",
|
|
81
80
|
"env": { "NEX_API_KEY": "sk-..." }
|
|
82
81
|
}
|
|
83
82
|
}
|
|
84
83
|
```
|
|
85
84
|
|
|
85
|
+
Or without a global install: `"command": "npx", "args": ["-y", "@nex-ai/nex", "mcp"]`
|
|
86
|
+
|
|
86
87
|
## Setup Command
|
|
87
88
|
|
|
88
89
|
```bash
|
|
@@ -104,7 +105,7 @@ nex graph # Open the workspace graph in your browser
|
|
|
104
105
|
- Creates `.nex.toml` project config with commented defaults
|
|
105
106
|
- Stores config in `~/.nex/config.json`
|
|
106
107
|
|
|
107
|
-
**Single install**: `npm install -g @nex-ai/nex` bundles everything — hooks, adapters, platform plugins, slash commands, rules, and
|
|
108
|
+
**Single install**: `npm install -g @nex-ai/nex` bundles everything — hooks, adapters, platform plugins, slash commands, rules, MCP server, and notification channel. No separate packages needed.
|
|
108
109
|
|
|
109
110
|
**Integration hierarchy** (per platform): Hooks > Custom plugins > Custom agents/modes > Workflows > Rules > MCP. Each platform gets every layer it supports.
|
|
110
111
|
|
|
@@ -233,6 +234,19 @@ Context is injected as `<nex-context>` blocks that AI agents use naturally witho
|
|
|
233
234
|
|
|
234
235
|
At session end, the full conversation transcript is automatically ingested into the knowledge graph. This captures complete decision trails, code discussions, and debugging sessions — not just the last message.
|
|
235
236
|
|
|
237
|
+
### MCP Server & Notifications
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
nex mcp # Start the embedded MCP server (stdio)
|
|
241
|
+
MCP_TRANSPORT=http nex mcp # Start with HTTP transport
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
The MCP server includes a built-in notification channel (Claude SDK Channels API) that pushes:
|
|
245
|
+
- **Daily digests**: 24h context summary, pushed once per day
|
|
246
|
+
- **Proactive notifications**: New insights polled every 5 minutes
|
|
247
|
+
|
|
248
|
+
Enable in Claude Code with `claude --channels` or `claude --dangerously-load-development-channels server:nex`.
|
|
249
|
+
|
|
236
250
|
### Config & Sessions
|
|
237
251
|
|
|
238
252
|
```bash
|
package/dist/index.js
CHANGED
|
@@ -74,6 +74,7 @@ Commands:
|
|
|
74
74
|
graph View relationship graph
|
|
75
75
|
detect Detect installed AI coding platforms
|
|
76
76
|
setup Configure API key and workspace
|
|
77
|
+
mcp Start the embedded MCP server (stdio)
|
|
77
78
|
agent templates List available agent templates
|
|
78
79
|
agent create Create a new agent
|
|
79
80
|
|
|
@@ -98,6 +99,11 @@ When no command is given, launches the interactive TUI.`);
|
|
|
98
99
|
// Interactive commands → fall through to Commander (rich TUI with pickers, spinners, workflows)
|
|
99
100
|
const INTERACTIVE_COMMANDS = new Set(["setup", "integrate", "scan", "register", "status"]);
|
|
100
101
|
const firstArg = cleanArgs[0]?.toLowerCase();
|
|
102
|
+
// nex mcp → start embedded MCP server
|
|
103
|
+
if (firstArg === "mcp") {
|
|
104
|
+
await import("./mcp/index.js");
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
101
107
|
if (firstArg && !INTERACTIVE_COMMANDS.has(firstArg)) {
|
|
102
108
|
// Non-interactive subcommand → dispatch and exit
|
|
103
109
|
const result = await dispatchTokens(cleanArgs, ctx);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAgB,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD;;;GAGG;AACH,SAAS,kBAAkB,CAAC,IAAc;IACxC,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,IAAI,MAA0B,CAAC;IAC/B,IAAI,MAA0B,CAAC;IAC/B,IAAI,OAA2B,CAAC;IAEhC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC1C,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACrB,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,WAAW,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAClD,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACrB,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,WAAW,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAClD,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACpC,CAAC;aAAM,CAAC;YACN,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO;QACL,SAAS;QACT,GAAG,EAAE;YACH,MAAM,EAAE,CAAC,MAAM,IAAI,aAAa,EAAE,CAAW;YAC7C,MAAM;YACN,OAAO;SACR;KACF,CAAC;AACJ,CAAC;AAED,wEAAwE;AACxE,SAAS,WAAW,CAAC,MAA4D;IAC/E,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9C,IAAI,MAAM,CAAC,KAAK;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAC5D,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,iBAAiB;IACjB,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACtD,MAAM,GAAG,GAAQ,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,EAAE,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,cAAc;IACd,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace registry — manages multiple Nex workspaces on a single machine.
|
|
3
|
+
*
|
|
4
|
+
* Storage:
|
|
5
|
+
* ~/.nex/config.json → registry (active_workspace + workspace list)
|
|
6
|
+
* ~/.nex/workspaces/<slug>/ → per-workspace credentials + state
|
|
7
|
+
*
|
|
8
|
+
* All functions accept an optional `baseDir` for testing (defaults to ~/.nex).
|
|
9
|
+
*/
|
|
10
|
+
export interface WorkspaceEntry {
|
|
11
|
+
slug: string;
|
|
12
|
+
nickname?: string;
|
|
13
|
+
added_at: number;
|
|
14
|
+
}
|
|
15
|
+
export interface WorkspaceCredentials {
|
|
16
|
+
api_key: string;
|
|
17
|
+
email: string;
|
|
18
|
+
workspace_id: string;
|
|
19
|
+
workspace_slug: string;
|
|
20
|
+
}
|
|
21
|
+
export interface WorkspaceRegistry {
|
|
22
|
+
active_workspace: string;
|
|
23
|
+
workspaces: Record<string, {
|
|
24
|
+
nickname?: string;
|
|
25
|
+
added_at: number;
|
|
26
|
+
}>;
|
|
27
|
+
[key: string]: unknown;
|
|
28
|
+
}
|
|
29
|
+
export declare function loadRegistry(baseDir?: string): WorkspaceRegistry;
|
|
30
|
+
export declare function saveRegistry(registry: WorkspaceRegistry, baseDir?: string): void;
|
|
31
|
+
export declare function addWorkspace(slug: string, credentials: WorkspaceCredentials, nickname?: string, baseDir?: string): void;
|
|
32
|
+
export declare function removeWorkspace(slug: string, baseDir?: string): void;
|
|
33
|
+
export declare function switchWorkspace(slug: string, baseDir?: string): WorkspaceCredentials;
|
|
34
|
+
export declare function renameWorkspace(slug: string, nickname: string, baseDir?: string): void;
|
|
35
|
+
export declare function getActiveCredentials(baseDir?: string): WorkspaceCredentials | undefined;
|
|
36
|
+
export declare function listWorkspaces(baseDir?: string): (WorkspaceEntry & {
|
|
37
|
+
email: string;
|
|
38
|
+
})[];
|
|
39
|
+
export declare function workspaceDataDir(slug?: string, baseDir?: string): string;
|
|
40
|
+
/** Reset cached data dir (for testing or after workspace switch). */
|
|
41
|
+
export declare function resetDataDirCache(): void;
|
|
42
|
+
/**
|
|
43
|
+
* Resolve a workspace slug from a slug-or-nickname input.
|
|
44
|
+
* Resolution: exact slug → case-insensitive nickname → null.
|
|
45
|
+
*/
|
|
46
|
+
export declare function resolveSlug(input: string, baseDir?: string): string | null;
|
|
47
|
+
export declare function migrateIfNeeded(baseDir?: string, legacyMcpPath?: string): void;
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace registry — manages multiple Nex workspaces on a single machine.
|
|
3
|
+
*
|
|
4
|
+
* Storage:
|
|
5
|
+
* ~/.nex/config.json → registry (active_workspace + workspace list)
|
|
6
|
+
* ~/.nex/workspaces/<slug>/ → per-workspace credentials + state
|
|
7
|
+
*
|
|
8
|
+
* All functions accept an optional `baseDir` for testing (defaults to ~/.nex).
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync, rmSync, } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
const DEFAULT_BASE_DIR = process.env.NEX_BASE_DIR || join(homedir(), ".nex");
|
|
14
|
+
// --- State file names that get moved during migration ---
|
|
15
|
+
const STATE_FILES = [
|
|
16
|
+
"file-scan-manifest.json",
|
|
17
|
+
"claude-sessions.json",
|
|
18
|
+
"mcp-sessions.json",
|
|
19
|
+
"cli-sessions.json",
|
|
20
|
+
"recall-state.json",
|
|
21
|
+
"rate-limiter.json",
|
|
22
|
+
];
|
|
23
|
+
// --- Core functions ---
|
|
24
|
+
export function loadRegistry(baseDir = DEFAULT_BASE_DIR) {
|
|
25
|
+
const configPath = join(baseDir, "config.json");
|
|
26
|
+
try {
|
|
27
|
+
const raw = readFileSync(configPath, "utf-8");
|
|
28
|
+
const data = JSON.parse(raw);
|
|
29
|
+
if (data && data.active_workspace !== undefined && data.workspaces) {
|
|
30
|
+
return data;
|
|
31
|
+
}
|
|
32
|
+
// Flat config detected — trigger migration
|
|
33
|
+
if (data && data.api_key) {
|
|
34
|
+
migrateIfNeeded(baseDir);
|
|
35
|
+
return JSON.parse(readFileSync(configPath, "utf-8"));
|
|
36
|
+
}
|
|
37
|
+
return { active_workspace: "", workspaces: {} };
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return { active_workspace: "", workspaces: {} };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function saveRegistry(registry, baseDir = DEFAULT_BASE_DIR) {
|
|
44
|
+
mkdirSync(baseDir, { recursive: true });
|
|
45
|
+
writeFileSync(join(baseDir, "config.json"), JSON.stringify(registry, null, 2), "utf-8");
|
|
46
|
+
}
|
|
47
|
+
export function addWorkspace(slug, credentials, nickname, baseDir = DEFAULT_BASE_DIR) {
|
|
48
|
+
const registry = loadRegistry(baseDir);
|
|
49
|
+
const wsDir = join(baseDir, "workspaces", slug);
|
|
50
|
+
mkdirSync(wsDir, { recursive: true });
|
|
51
|
+
// Write credentials
|
|
52
|
+
writeFileSync(join(wsDir, "credentials.json"), JSON.stringify(credentials, null, 2), "utf-8");
|
|
53
|
+
// Update registry — preserve existing nickname if no new one provided
|
|
54
|
+
const existing = registry.workspaces[slug];
|
|
55
|
+
registry.workspaces[slug] = {
|
|
56
|
+
nickname: nickname ?? existing?.nickname,
|
|
57
|
+
added_at: existing?.added_at ?? Date.now(),
|
|
58
|
+
};
|
|
59
|
+
// Set as active if first workspace or no active set
|
|
60
|
+
if (!registry.active_workspace || Object.keys(registry.workspaces).length === 1) {
|
|
61
|
+
registry.active_workspace = slug;
|
|
62
|
+
}
|
|
63
|
+
saveRegistry(registry, baseDir);
|
|
64
|
+
}
|
|
65
|
+
export function removeWorkspace(slug, baseDir = DEFAULT_BASE_DIR) {
|
|
66
|
+
const registry = loadRegistry(baseDir);
|
|
67
|
+
delete registry.workspaces[slug];
|
|
68
|
+
// Clean up active_workspace pointer
|
|
69
|
+
if (registry.active_workspace === slug) {
|
|
70
|
+
const remaining = Object.keys(registry.workspaces);
|
|
71
|
+
registry.active_workspace = remaining[0] ?? "";
|
|
72
|
+
}
|
|
73
|
+
// Remove workspace directory
|
|
74
|
+
const wsDir = join(baseDir, "workspaces", slug);
|
|
75
|
+
rmSync(wsDir, { recursive: true, force: true });
|
|
76
|
+
saveRegistry(registry, baseDir);
|
|
77
|
+
}
|
|
78
|
+
export function switchWorkspace(slug, baseDir = DEFAULT_BASE_DIR) {
|
|
79
|
+
const registry = loadRegistry(baseDir);
|
|
80
|
+
if (!registry.workspaces[slug]) {
|
|
81
|
+
throw new Error(`Workspace "${slug}" not found`);
|
|
82
|
+
}
|
|
83
|
+
registry.active_workspace = slug;
|
|
84
|
+
saveRegistry(registry, baseDir);
|
|
85
|
+
return loadCredentials(slug, baseDir);
|
|
86
|
+
}
|
|
87
|
+
export function renameWorkspace(slug, nickname, baseDir = DEFAULT_BASE_DIR) {
|
|
88
|
+
const registry = loadRegistry(baseDir);
|
|
89
|
+
if (!registry.workspaces[slug]) {
|
|
90
|
+
throw new Error(`Workspace "${slug}" not found`);
|
|
91
|
+
}
|
|
92
|
+
registry.workspaces[slug].nickname = nickname;
|
|
93
|
+
saveRegistry(registry, baseDir);
|
|
94
|
+
}
|
|
95
|
+
export function getActiveCredentials(baseDir = DEFAULT_BASE_DIR) {
|
|
96
|
+
const registry = loadRegistry(baseDir);
|
|
97
|
+
if (!registry.active_workspace)
|
|
98
|
+
return undefined;
|
|
99
|
+
try {
|
|
100
|
+
return loadCredentials(registry.active_workspace, baseDir);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
export function listWorkspaces(baseDir = DEFAULT_BASE_DIR) {
|
|
107
|
+
const registry = loadRegistry(baseDir);
|
|
108
|
+
return Object.entries(registry.workspaces)
|
|
109
|
+
.map(([slug, meta]) => {
|
|
110
|
+
let email = "";
|
|
111
|
+
try {
|
|
112
|
+
const creds = loadCredentials(slug, baseDir);
|
|
113
|
+
email = creds.email;
|
|
114
|
+
}
|
|
115
|
+
catch { /* missing credentials */ }
|
|
116
|
+
return { slug, nickname: meta.nickname, added_at: meta.added_at, email };
|
|
117
|
+
})
|
|
118
|
+
.sort((a, b) => a.added_at - b.added_at);
|
|
119
|
+
}
|
|
120
|
+
/** Resolve the data directory for a workspace's state files. */
|
|
121
|
+
let _cachedDataDir;
|
|
122
|
+
export function workspaceDataDir(slug, baseDir = DEFAULT_BASE_DIR) {
|
|
123
|
+
if (slug) {
|
|
124
|
+
return join(baseDir, "workspaces", slug);
|
|
125
|
+
}
|
|
126
|
+
if (!_cachedDataDir) {
|
|
127
|
+
const registry = loadRegistry(baseDir);
|
|
128
|
+
if (registry.active_workspace) {
|
|
129
|
+
_cachedDataDir = join(baseDir, "workspaces", registry.active_workspace);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
// Fallback to base dir if no workspace (pre-registration)
|
|
133
|
+
return baseDir;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return _cachedDataDir;
|
|
137
|
+
}
|
|
138
|
+
/** Reset cached data dir (for testing or after workspace switch). */
|
|
139
|
+
export function resetDataDirCache() {
|
|
140
|
+
_cachedDataDir = undefined;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Resolve a workspace slug from a slug-or-nickname input.
|
|
144
|
+
* Resolution: exact slug → case-insensitive nickname → null.
|
|
145
|
+
*/
|
|
146
|
+
export function resolveSlug(input, baseDir = DEFAULT_BASE_DIR) {
|
|
147
|
+
const registry = loadRegistry(baseDir);
|
|
148
|
+
if (registry.workspaces[input])
|
|
149
|
+
return input;
|
|
150
|
+
const lower = input.toLowerCase();
|
|
151
|
+
for (const [slug, meta] of Object.entries(registry.workspaces)) {
|
|
152
|
+
if (meta.nickname?.toLowerCase() === lower)
|
|
153
|
+
return slug;
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
// --- Migration ---
|
|
158
|
+
export function migrateIfNeeded(baseDir = DEFAULT_BASE_DIR, legacyMcpPath) {
|
|
159
|
+
const configPath = join(baseDir, "config.json");
|
|
160
|
+
let data = {};
|
|
161
|
+
try {
|
|
162
|
+
data = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return; // No config file — nothing to migrate
|
|
166
|
+
}
|
|
167
|
+
// Already migrated
|
|
168
|
+
if (data.active_workspace !== undefined)
|
|
169
|
+
return;
|
|
170
|
+
// No api_key — nothing to migrate
|
|
171
|
+
if (!data.api_key)
|
|
172
|
+
return;
|
|
173
|
+
const slug = data.workspace_slug || "default";
|
|
174
|
+
const wsDir = join(baseDir, "workspaces", slug);
|
|
175
|
+
mkdirSync(wsDir, { recursive: true });
|
|
176
|
+
// Write credentials
|
|
177
|
+
const credentials = {
|
|
178
|
+
api_key: data.api_key,
|
|
179
|
+
email: data.email || "",
|
|
180
|
+
workspace_id: String(data.workspace_id || ""),
|
|
181
|
+
workspace_slug: slug,
|
|
182
|
+
};
|
|
183
|
+
writeFileSync(join(wsDir, "credentials.json"), JSON.stringify(credentials, null, 2), "utf-8");
|
|
184
|
+
// Move state files
|
|
185
|
+
for (const file of STATE_FILES) {
|
|
186
|
+
const src = join(baseDir, file);
|
|
187
|
+
const dest = join(wsDir, file);
|
|
188
|
+
if (existsSync(src)) {
|
|
189
|
+
try {
|
|
190
|
+
renameSync(src, dest);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// Cross-device move fallback
|
|
194
|
+
writeFileSync(dest, readFileSync(src));
|
|
195
|
+
rmSync(src);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// Build new config — preserve global settings, remove credential fields
|
|
200
|
+
const { api_key, email, workspace_id, workspace_slug, ...globalSettings } = data;
|
|
201
|
+
const newConfig = {
|
|
202
|
+
...globalSettings,
|
|
203
|
+
active_workspace: slug,
|
|
204
|
+
workspaces: {
|
|
205
|
+
[slug]: { added_at: Date.now() },
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
writeFileSync(configPath, JSON.stringify(newConfig, null, 2), "utf-8");
|
|
209
|
+
// Migrate legacy MCP config if present
|
|
210
|
+
const mcpPath = legacyMcpPath ?? join(homedir(), ".nex-mcp.json");
|
|
211
|
+
try {
|
|
212
|
+
const mcpData = JSON.parse(readFileSync(mcpPath, "utf-8"));
|
|
213
|
+
if (mcpData.api_key && mcpData.workspace_slug && mcpData.workspace_slug !== slug) {
|
|
214
|
+
// Different workspace — add it
|
|
215
|
+
const mcpSlug = mcpData.workspace_slug;
|
|
216
|
+
const mcpWsDir = join(baseDir, "workspaces", mcpSlug);
|
|
217
|
+
mkdirSync(mcpWsDir, { recursive: true });
|
|
218
|
+
const mcpCreds = {
|
|
219
|
+
api_key: mcpData.api_key,
|
|
220
|
+
email: mcpData.email || "",
|
|
221
|
+
workspace_id: String(mcpData.workspace_id || ""),
|
|
222
|
+
workspace_slug: mcpSlug,
|
|
223
|
+
};
|
|
224
|
+
writeFileSync(join(mcpWsDir, "credentials.json"), JSON.stringify(mcpCreds, null, 2), "utf-8");
|
|
225
|
+
newConfig.workspaces[mcpSlug] = { added_at: Date.now() };
|
|
226
|
+
writeFileSync(configPath, JSON.stringify(newConfig, null, 2), "utf-8");
|
|
227
|
+
}
|
|
228
|
+
// Backup legacy file
|
|
229
|
+
renameSync(mcpPath, mcpPath + ".bak");
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
// No MCP config or already backed up — fine
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// --- Helpers ---
|
|
236
|
+
function loadCredentials(slug, baseDir) {
|
|
237
|
+
const credPath = join(baseDir, "workspaces", slug, "credentials.json");
|
|
238
|
+
return JSON.parse(readFileSync(credPath, "utf-8"));
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=workspace-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-registry.js","sourceRoot":"","sources":["../../src/lib/workspace-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nex Channel — pushes daily digests and proactive notifications
|
|
3
|
+
* into active Claude Code sessions via the Channels API.
|
|
4
|
+
*
|
|
5
|
+
* Uses the existing Nex API client to query context and insights,
|
|
6
|
+
* then forwards results as channel notifications.
|
|
7
|
+
*/
|
|
8
|
+
import type { NexApiClient } from "./client.js";
|
|
9
|
+
/**
|
|
10
|
+
* Minimal interface for the underlying MCP Server's notification method.
|
|
11
|
+
* We use this instead of importing the full Server type to avoid coupling
|
|
12
|
+
* to the SDK's internal type hierarchy.
|
|
13
|
+
*/
|
|
14
|
+
interface NotificationSender {
|
|
15
|
+
notification(notification: {
|
|
16
|
+
method: string;
|
|
17
|
+
params?: Record<string, unknown>;
|
|
18
|
+
}): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Start the Nex notification channel. Call this after the MCP server
|
|
22
|
+
* has connected to its transport.
|
|
23
|
+
*
|
|
24
|
+
* @param server The underlying MCP `Server` instance (mcpServer.server)
|
|
25
|
+
* @param client An authenticated NexApiClient
|
|
26
|
+
*/
|
|
27
|
+
export declare function startChannel(server: NotificationSender, client: NexApiClient): void;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nex Channel — pushes daily digests and proactive notifications
|
|
3
|
+
* into active Claude Code sessions via the Channels API.
|
|
4
|
+
*
|
|
5
|
+
* Uses the existing Nex API client to query context and insights,
|
|
6
|
+
* then forwards results as channel notifications.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
9
|
+
import { homedir } from "node:os";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Constants
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
const STATE_DIR = join(homedir(), ".nex");
|
|
15
|
+
const STATE_PATH = join(STATE_DIR, "channel-state.json");
|
|
16
|
+
/** How often to check whether a daily digest is due (1 hour). */
|
|
17
|
+
const DIGEST_CHECK_INTERVAL_MS = 60 * 60 * 1000;
|
|
18
|
+
/** Minimum gap between daily digests (24 hours). */
|
|
19
|
+
const DIGEST_COOLDOWN_MS = 24 * 60 * 60 * 1000;
|
|
20
|
+
/** How often to poll for proactive notifications (5 minutes). */
|
|
21
|
+
const NOTIFY_INTERVAL_MS = 5 * 60 * 1000;
|
|
22
|
+
/** Delay before the first digest check after startup (10 seconds). */
|
|
23
|
+
const INITIAL_DIGEST_DELAY_MS = 10_000;
|
|
24
|
+
/** Delay before the first notification check after startup (15 seconds). */
|
|
25
|
+
const INITIAL_NOTIFY_DELAY_MS = 15_000;
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// State persistence
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
function loadState() {
|
|
30
|
+
try {
|
|
31
|
+
if (existsSync(STATE_PATH)) {
|
|
32
|
+
return JSON.parse(readFileSync(STATE_PATH, "utf-8"));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// Corrupted or unreadable — start fresh
|
|
37
|
+
}
|
|
38
|
+
return { lastDigestAt: 0, lastNotifyCheckAt: 0 };
|
|
39
|
+
}
|
|
40
|
+
function saveState(state) {
|
|
41
|
+
try {
|
|
42
|
+
if (!existsSync(STATE_DIR))
|
|
43
|
+
mkdirSync(STATE_DIR, { recursive: true });
|
|
44
|
+
writeFileSync(STATE_PATH, JSON.stringify(state));
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Best-effort — don't crash if write fails
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// Push helper
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
async function pushChannelEvent(server, content, meta = {}) {
|
|
54
|
+
await server.notification({
|
|
55
|
+
method: "notifications/claude/channel",
|
|
56
|
+
params: { content, meta },
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// Digest logic
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
async function checkDigest(server, client, state) {
|
|
63
|
+
const now = Date.now();
|
|
64
|
+
if (now - state.lastDigestAt < DIGEST_COOLDOWN_MS)
|
|
65
|
+
return;
|
|
66
|
+
try {
|
|
67
|
+
const result = (await client.post("/v1/context/ask", {
|
|
68
|
+
query: "Provide a comprehensive daily digest: summarize all key context " +
|
|
69
|
+
"collected in the last 24 hours, including important updates, new " +
|
|
70
|
+
"relationships, deal changes, upcoming events, and any actionable " +
|
|
71
|
+
"items. Be specific with names, dates, and numbers.",
|
|
72
|
+
}));
|
|
73
|
+
if (result.answer && result.answer.trim().length > 0) {
|
|
74
|
+
await pushChannelEvent(server, result.answer, {
|
|
75
|
+
type: "daily_digest",
|
|
76
|
+
period: "24h",
|
|
77
|
+
});
|
|
78
|
+
state.lastDigestAt = now;
|
|
79
|
+
saveState(state);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
console.error("[nex-channel] digest check failed:", err);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
// Proactive notification logic
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
async function checkNotifications(server, client, state) {
|
|
90
|
+
const now = Date.now();
|
|
91
|
+
try {
|
|
92
|
+
const lastCheck = state.lastNotifyCheckAt || now - NOTIFY_INTERVAL_MS;
|
|
93
|
+
const minutesSinceLastCheck = Math.max(5, Math.ceil((now - lastCheck) / 60_000));
|
|
94
|
+
const result = (await client.get(`/v1/insights?last=${minutesSinceLastCheck}m&limit=10`));
|
|
95
|
+
state.lastNotifyCheckAt = now;
|
|
96
|
+
saveState(state);
|
|
97
|
+
if (result.insights && result.insights.length > 0) {
|
|
98
|
+
const summary = result.insights
|
|
99
|
+
.map((i) => `- [${i.type || "update"}${i.importance ? ` | ${i.importance}` : ""}] ${i.content || JSON.stringify(i)}`)
|
|
100
|
+
.join("\n");
|
|
101
|
+
await pushChannelEvent(server, summary, {
|
|
102
|
+
type: "proactive_notification",
|
|
103
|
+
count: String(result.insights.length),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
console.error("[nex-channel] notification check failed:", err);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// Entry point
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
/**
|
|
115
|
+
* Start the Nex notification channel. Call this after the MCP server
|
|
116
|
+
* has connected to its transport.
|
|
117
|
+
*
|
|
118
|
+
* @param server The underlying MCP `Server` instance (mcpServer.server)
|
|
119
|
+
* @param client An authenticated NexApiClient
|
|
120
|
+
*/
|
|
121
|
+
export function startChannel(server, client) {
|
|
122
|
+
if (!client.isAuthenticated)
|
|
123
|
+
return;
|
|
124
|
+
const state = loadState();
|
|
125
|
+
// --- Daily digest ---
|
|
126
|
+
// Initial check after a short delay to let the session settle
|
|
127
|
+
setTimeout(() => checkDigest(server, client, state), INITIAL_DIGEST_DELAY_MS);
|
|
128
|
+
// Then check hourly (only fires digest if 24h have passed)
|
|
129
|
+
setInterval(() => checkDigest(server, client, state), DIGEST_CHECK_INTERVAL_MS);
|
|
130
|
+
// --- Proactive notifications ---
|
|
131
|
+
setTimeout(() => checkNotifications(server, client, state), INITIAL_NOTIFY_DELAY_MS);
|
|
132
|
+
setInterval(() => checkNotifications(server, client, state), NOTIFY_INTERVAL_MS);
|
|
133
|
+
console.error("[nex-channel] started (digest: 24h, notifications: 5m)");
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/mcp/channel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare class NexApiError extends Error {
|
|
2
|
+
status: number;
|
|
3
|
+
statusText: string;
|
|
4
|
+
body: unknown;
|
|
5
|
+
constructor(status: number, statusText: string, body: unknown);
|
|
6
|
+
}
|
|
7
|
+
export declare class NexApiClient {
|
|
8
|
+
private apiKey;
|
|
9
|
+
constructor(apiKey?: string);
|
|
10
|
+
get isAuthenticated(): boolean;
|
|
11
|
+
setApiKey(key: string): void;
|
|
12
|
+
private requireAuth;
|
|
13
|
+
private request;
|
|
14
|
+
register(email: string, name?: string, companyName?: string, source?: string): Promise<unknown>;
|
|
15
|
+
get(path: string): Promise<unknown>;
|
|
16
|
+
post(path: string, body?: unknown): Promise<unknown>;
|
|
17
|
+
put(path: string, body?: unknown): Promise<unknown>;
|
|
18
|
+
patch(path: string, body?: unknown): Promise<unknown>;
|
|
19
|
+
delete(path: string): Promise<unknown>;
|
|
20
|
+
}
|