@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.
Files changed (73) hide show
  1. package/README.md +18 -4
  2. package/dist/index.js +6 -0
  3. package/dist/index.js.map +1 -1
  4. package/dist/lib/workspace-registry.d.ts +47 -0
  5. package/dist/lib/workspace-registry.js +240 -0
  6. package/dist/lib/workspace-registry.js.map +1 -0
  7. package/dist/mcp/channel.d.ts +28 -0
  8. package/dist/mcp/channel.js +135 -0
  9. package/dist/mcp/channel.js.map +1 -0
  10. package/dist/mcp/client.d.ts +20 -0
  11. package/dist/mcp/client.js +130 -0
  12. package/dist/mcp/client.js.map +1 -0
  13. package/dist/mcp/config.d.ts +14 -0
  14. package/dist/mcp/config.js +33 -0
  15. package/dist/mcp/config.js.map +1 -0
  16. package/dist/mcp/context-files.d.ts +9 -0
  17. package/dist/mcp/context-files.js +90 -0
  18. package/dist/mcp/context-files.js.map +1 -0
  19. package/dist/mcp/file-manifest.d.ts +27 -0
  20. package/dist/mcp/file-manifest.js +64 -0
  21. package/dist/mcp/file-manifest.js.map +1 -0
  22. package/dist/mcp/file-scanner.d.ts +17 -0
  23. package/dist/mcp/file-scanner.js +77 -0
  24. package/dist/mcp/file-scanner.js.map +1 -0
  25. package/dist/mcp/index.d.ts +2 -0
  26. package/dist/mcp/index.js +51 -0
  27. package/dist/mcp/index.js.map +1 -0
  28. package/dist/mcp/rate-limiter.d.ts +14 -0
  29. package/dist/mcp/rate-limiter.js +60 -0
  30. package/dist/mcp/rate-limiter.js.map +1 -0
  31. package/dist/mcp/server.d.ts +6 -0
  32. package/dist/mcp/server.js +42 -0
  33. package/dist/mcp/server.js.map +1 -0
  34. package/dist/mcp/session-store.d.ts +16 -0
  35. package/dist/mcp/session-store.js +70 -0
  36. package/dist/mcp/session-store.js.map +1 -0
  37. package/dist/mcp/tools/context.d.ts +3 -0
  38. package/dist/mcp/tools/context.js +65 -0
  39. package/dist/mcp/tools/context.js.map +1 -0
  40. package/dist/mcp/tools/insights.d.ts +3 -0
  41. package/dist/mcp/tools/insights.js +24 -0
  42. package/dist/mcp/tools/insights.js.map +1 -0
  43. package/dist/mcp/tools/integrations.d.ts +3 -0
  44. package/dist/mcp/tools/integrations.js +27 -0
  45. package/dist/mcp/tools/integrations.js.map +1 -0
  46. package/dist/mcp/tools/lists.d.ts +3 -0
  47. package/dist/mcp/tools/lists.js +101 -0
  48. package/dist/mcp/tools/lists.js.map +1 -0
  49. package/dist/mcp/tools/notes.d.ts +3 -0
  50. package/dist/mcp/tools/notes.js +52 -0
  51. package/dist/mcp/tools/notes.js.map +1 -0
  52. package/dist/mcp/tools/records.d.ts +3 -0
  53. package/dist/mcp/tools/records.js +74 -0
  54. package/dist/mcp/tools/records.js.map +1 -0
  55. package/dist/mcp/tools/register.d.ts +3 -0
  56. package/dist/mcp/tools/register.js +30 -0
  57. package/dist/mcp/tools/register.js.map +1 -0
  58. package/dist/mcp/tools/relationships.d.ts +3 -0
  59. package/dist/mcp/tools/relationships.js +47 -0
  60. package/dist/mcp/tools/relationships.js.map +1 -0
  61. package/dist/mcp/tools/scan.d.ts +3 -0
  62. package/dist/mcp/tools/scan.js +37 -0
  63. package/dist/mcp/tools/scan.js.map +1 -0
  64. package/dist/mcp/tools/schema.d.ts +3 -0
  65. package/dist/mcp/tools/schema.js +108 -0
  66. package/dist/mcp/tools/schema.js.map +1 -0
  67. package/dist/mcp/tools/search.d.ts +3 -0
  68. package/dist/mcp/tools/search.js +8 -0
  69. package/dist/mcp/tools/search.js.map +1 -0
  70. package/dist/mcp/tools/tasks.d.ts +3 -0
  71. package/dist/mcp/tools/tasks.js +88 -0
  72. package/dist/mcp/tools/tasks.js.map +1 -0
  73. 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": "npx",
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 MCP server. No separate packages needed.
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":"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"}
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
+ }