@novaluna/agent 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -0
- package/dist/agent.d.ts +25 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +108 -0
- package/dist/agent.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +186 -0
- package/dist/cli.js.map +1 -0
- package/dist/config-file.d.ts +5 -0
- package/dist/config-file.d.ts.map +1 -0
- package/dist/config-file.js +30 -0
- package/dist/config-file.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-process.d.ts +17 -0
- package/dist/mcp-process.d.ts.map +1 -0
- package/dist/mcp-process.js +89 -0
- package/dist/mcp-process.js.map +1 -0
- package/dist/types.d.ts +60 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/ws-client.d.ts +20 -0
- package/dist/ws-client.d.ts.map +1 -0
- package/dist/ws-client.js +111 -0
- package/dist/ws-client.js.map +1 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# @novaluna/agent
|
|
2
|
+
|
|
3
|
+
Connects local MCP servers (Bloomberg Terminal, etc.) on your desktop to Novaluna cloud.
|
|
4
|
+
|
|
5
|
+
## Quick start
|
|
6
|
+
|
|
7
|
+
Your Novaluna admin will give you a setup file. Double-click it — that's it.
|
|
8
|
+
|
|
9
|
+
If you prefer the command line:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx @novaluna/agent start --token nvl_YOUR_TOKEN
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Add a data source (Bloomberg)
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx @novaluna/agent mcp add \
|
|
19
|
+
--id bloomberg \
|
|
20
|
+
--name "Bloomberg Terminal" \
|
|
21
|
+
--command python \
|
|
22
|
+
--args -m bloomberg_mcp
|
|
23
|
+
|
|
24
|
+
npx @novaluna/agent start
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Commands
|
|
28
|
+
|
|
29
|
+
| Command | Description |
|
|
30
|
+
|---|---|
|
|
31
|
+
| `start [--token nvl_xxx]` | Start and connect the agent |
|
|
32
|
+
| `mcp add --id ... --name ... --command ...` | Add an MCP server |
|
|
33
|
+
| `mcp list` | Show configured MCP servers |
|
|
34
|
+
| `mcp remove <id>` | Remove an MCP server |
|
|
35
|
+
| `config` | Show current config file path and contents |
|
|
36
|
+
|
|
37
|
+
## Config file
|
|
38
|
+
|
|
39
|
+
All config lives at `~/.novaluna/agent.json` (Windows: `%USERPROFILE%\.novaluna\agent.json`).
|
|
40
|
+
The token is saved on first run — subsequent runs don't need `--token`.
|
|
41
|
+
|
|
42
|
+
## Requirements
|
|
43
|
+
|
|
44
|
+
- Node.js 18+
|
|
45
|
+
- The data source you want to connect (e.g. Bloomberg Terminal must be running)
|
package/dist/agent.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NovalunaAgent — orchestrates McpProcess instances and GatewayClient.
|
|
3
|
+
* Plugin-based: additional capabilities (RAG, CMEK) register via agent.use()
|
|
4
|
+
*/
|
|
5
|
+
import { EventEmitter } from 'events';
|
|
6
|
+
import { AgentConfig } from './types';
|
|
7
|
+
export interface AgentPlugin {
|
|
8
|
+
name: string;
|
|
9
|
+
onConnected?(agentId: string): Promise<void>;
|
|
10
|
+
onDisconnected?(): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare class NovalunaAgent extends EventEmitter {
|
|
13
|
+
private config;
|
|
14
|
+
private gateway;
|
|
15
|
+
private mcpProcesses;
|
|
16
|
+
private plugins;
|
|
17
|
+
constructor(config: AgentConfig);
|
|
18
|
+
use(plugin: AgentPlugin): this;
|
|
19
|
+
start(): Promise<void>;
|
|
20
|
+
stop(): void;
|
|
21
|
+
private startMcpProcesses;
|
|
22
|
+
private registerMcps;
|
|
23
|
+
private handleMcpCall;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,WAAW,EAAmB,MAAM,SAAS,CAAC;AAIvD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,cAAc,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AAED,qBAAa,aAAc,SAAQ,YAAY;IAKjC,OAAO,CAAC,MAAM;IAJ1B,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,OAAO,CAAqB;gBAEhB,MAAM,EAAE,WAAW;IAKvC,GAAG,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAKxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgC5B,IAAI,IAAI,IAAI;YAKE,iBAAiB;YAgBjB,YAAY;YASZ,aAAa;CA6B5B"}
|
package/dist/agent.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NovalunaAgent = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* NovalunaAgent — orchestrates McpProcess instances and GatewayClient.
|
|
6
|
+
* Plugin-based: additional capabilities (RAG, CMEK) register via agent.use()
|
|
7
|
+
*/
|
|
8
|
+
const events_1 = require("events");
|
|
9
|
+
const mcp_process_1 = require("./mcp-process");
|
|
10
|
+
const ws_client_1 = require("./ws-client");
|
|
11
|
+
class NovalunaAgent extends events_1.EventEmitter {
|
|
12
|
+
config;
|
|
13
|
+
gateway;
|
|
14
|
+
mcpProcesses = new Map();
|
|
15
|
+
plugins = [];
|
|
16
|
+
constructor(config) {
|
|
17
|
+
super();
|
|
18
|
+
this.config = config;
|
|
19
|
+
this.gateway = new ws_client_1.GatewayClient(config);
|
|
20
|
+
}
|
|
21
|
+
use(plugin) {
|
|
22
|
+
this.plugins.push(plugin);
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
async start() {
|
|
26
|
+
// Start all configured MCP processes first
|
|
27
|
+
await this.startMcpProcesses();
|
|
28
|
+
// Wire up gateway events
|
|
29
|
+
this.gateway.on('connected', async ({ agentId, orgId }) => {
|
|
30
|
+
this.emit('connected', { agentId, orgId });
|
|
31
|
+
await this.registerMcps();
|
|
32
|
+
for (const p of this.plugins)
|
|
33
|
+
await p.onConnected?.(agentId);
|
|
34
|
+
});
|
|
35
|
+
this.gateway.on('disconnected', async () => {
|
|
36
|
+
this.emit('disconnected');
|
|
37
|
+
for (const p of this.plugins)
|
|
38
|
+
await p.onDisconnected?.();
|
|
39
|
+
});
|
|
40
|
+
this.gateway.on('reconnecting', (delay) => {
|
|
41
|
+
this.emit('reconnecting', delay);
|
|
42
|
+
});
|
|
43
|
+
this.gateway.on('mcp_call', async (msg) => {
|
|
44
|
+
await this.handleMcpCall(msg);
|
|
45
|
+
});
|
|
46
|
+
this.gateway.on('error', (err) => {
|
|
47
|
+
this.emit('error', err);
|
|
48
|
+
});
|
|
49
|
+
// Connect (throws on auth failure)
|
|
50
|
+
await this.gateway.connect();
|
|
51
|
+
}
|
|
52
|
+
stop() {
|
|
53
|
+
this.gateway.stop();
|
|
54
|
+
for (const proc of this.mcpProcesses.values())
|
|
55
|
+
proc.stop();
|
|
56
|
+
}
|
|
57
|
+
async startMcpProcesses() {
|
|
58
|
+
for (const serverConfig of this.config.mcpServers) {
|
|
59
|
+
const proc = new mcp_process_1.McpProcess(serverConfig);
|
|
60
|
+
try {
|
|
61
|
+
await proc.start();
|
|
62
|
+
this.mcpProcesses.set(serverConfig.id, proc);
|
|
63
|
+
proc.on('exit', (code) => {
|
|
64
|
+
this.emit('mcp_exit', { id: serverConfig.id, code });
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
// Non-fatal: report unavailable, continue with others
|
|
69
|
+
this.emit('mcp_start_error', { id: serverConfig.id, err });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async registerMcps() {
|
|
74
|
+
const mcps = [];
|
|
75
|
+
for (const [id, proc] of this.mcpProcesses) {
|
|
76
|
+
const serverConfig = this.config.mcpServers.find((s) => s.id === id);
|
|
77
|
+
mcps.push({ id, name: serverConfig.name, tools: proc.getTools() });
|
|
78
|
+
}
|
|
79
|
+
this.gateway.send({ type: 'register', mcps });
|
|
80
|
+
}
|
|
81
|
+
async handleMcpCall(msg) {
|
|
82
|
+
const { call_id, mcp_id, method, params } = msg;
|
|
83
|
+
const proc = this.mcpProcesses.get(mcp_id);
|
|
84
|
+
if (!proc) {
|
|
85
|
+
this.gateway.send({ type: 'mcp_error', call_id, error: `MCP ${mcp_id} not connected` });
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
let result;
|
|
90
|
+
if (method === 'tools/list') {
|
|
91
|
+
result = { tools: proc.getTools() };
|
|
92
|
+
}
|
|
93
|
+
else if (method === 'tools/call') {
|
|
94
|
+
const { name, arguments: args = {} } = params;
|
|
95
|
+
result = await proc.callTool(name, args);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
throw new Error(`Unsupported method: ${method}`);
|
|
99
|
+
}
|
|
100
|
+
this.gateway.send({ type: 'mcp_response', call_id, result });
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
this.gateway.send({ type: 'mcp_error', call_id, error: err.message ?? 'unknown error' });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.NovalunaAgent = NovalunaAgent;
|
|
108
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
/**
|
|
8
|
+
* novaluna-agent CLI
|
|
9
|
+
*
|
|
10
|
+
* Config lives at ~/.novaluna/agent.json — the same file the setup wizard
|
|
11
|
+
* generates, so double-clicking the setup script and running this CLI
|
|
12
|
+
* always share the same configuration.
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* npx @novaluna/agent start [--token nvl_xxx]
|
|
16
|
+
* npx @novaluna/agent mcp add --id bloomberg --name "Bloomberg Terminal" --command python --args -m bloomberg_mcp
|
|
17
|
+
* npx @novaluna/agent mcp list
|
|
18
|
+
* npx @novaluna/agent mcp remove bloomberg
|
|
19
|
+
*/
|
|
20
|
+
const commander_1 = require("commander");
|
|
21
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
22
|
+
const ora_1 = __importDefault(require("ora"));
|
|
23
|
+
const agent_1 = require("./agent");
|
|
24
|
+
const config_file_1 = require("./config-file");
|
|
25
|
+
const VERSION = '1.0.0';
|
|
26
|
+
const program = new commander_1.Command()
|
|
27
|
+
.name('novaluna-agent')
|
|
28
|
+
.description('Novaluna desktop agent — connects local MCP servers to Novaluna cloud')
|
|
29
|
+
.version(VERSION);
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// start
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
program
|
|
34
|
+
.command('start')
|
|
35
|
+
.description('Start the agent and connect to Novaluna')
|
|
36
|
+
.option('-t, --token <token>', 'Registration token (nvl_xxx) — only needed on first run')
|
|
37
|
+
.option('-g, --gateway <url>', 'Override gateway URL')
|
|
38
|
+
.action(async (opts) => {
|
|
39
|
+
const saved = (0, config_file_1.readConfig)();
|
|
40
|
+
const token = opts.token ?? saved.token;
|
|
41
|
+
if (!token) {
|
|
42
|
+
console.error(chalk_1.default.red('\nError: no registration token found.'));
|
|
43
|
+
console.error(chalk_1.default.dim(' Pass one with --token nvl_xxx, or run the setup script from'));
|
|
44
|
+
console.error(chalk_1.default.dim(' workbench.novaluna.ai → MCP Servers → Desktop Agents → New token\n'));
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
const config = {
|
|
48
|
+
token,
|
|
49
|
+
gatewayUrl: opts.gateway ?? saved.gatewayUrl,
|
|
50
|
+
mcpServers: saved.mcpServers ?? [],
|
|
51
|
+
};
|
|
52
|
+
// Persist token so future runs don't need --token
|
|
53
|
+
if (!saved.token || saved.token !== token) {
|
|
54
|
+
(0, config_file_1.writeConfig)({ token });
|
|
55
|
+
}
|
|
56
|
+
// -----------------------------------------------------------------------
|
|
57
|
+
// Print startup banner
|
|
58
|
+
// -----------------------------------------------------------------------
|
|
59
|
+
console.log(chalk_1.default.bold('\nNovaluna Agent ' + VERSION));
|
|
60
|
+
console.log(chalk_1.default.dim('─'.repeat(40)));
|
|
61
|
+
if (config.mcpServers.length === 0) {
|
|
62
|
+
console.log(chalk_1.default.yellow(' No MCP servers configured.\n' +
|
|
63
|
+
' Add Bloomberg with:\n' +
|
|
64
|
+
' novaluna-agent mcp add --id bloomberg --name "Bloomberg Terminal" \\\n' +
|
|
65
|
+
' --command python --args -m bloomberg_mcp\n'));
|
|
66
|
+
}
|
|
67
|
+
const spinner = (0, ora_1.default)('Connecting to Novaluna...').start();
|
|
68
|
+
const agent = new agent_1.NovalunaAgent(config);
|
|
69
|
+
agent.on('connected', ({ agentId, orgId }) => {
|
|
70
|
+
spinner.succeed(chalk_1.default.green(`Connected (agent: ${agentId}, org: ${orgId})`));
|
|
71
|
+
console.log(chalk_1.default.dim('\n Agent is live. Return to workbench.novaluna.ai'));
|
|
72
|
+
console.log(chalk_1.default.dim(` Config: ${config_file_1.CONFIG_PATH}`));
|
|
73
|
+
console.log(chalk_1.default.dim(' Press Ctrl+C to stop.\n'));
|
|
74
|
+
});
|
|
75
|
+
agent.on('mcp_start_error', ({ id, err }) => {
|
|
76
|
+
console.log(chalk_1.default.yellow(` ${id.padEnd(24)} ✗ ${err.message}`));
|
|
77
|
+
});
|
|
78
|
+
agent.on('reconnecting', (delay) => {
|
|
79
|
+
console.log(chalk_1.default.dim(` Reconnecting in ${delay / 1000}s...`));
|
|
80
|
+
});
|
|
81
|
+
agent.on('disconnected', () => {
|
|
82
|
+
console.log(chalk_1.default.yellow(' Disconnected from Novaluna — will reconnect automatically.'));
|
|
83
|
+
});
|
|
84
|
+
agent.on('error', (err) => {
|
|
85
|
+
spinner.fail(chalk_1.default.red(`Error: ${err.message}`));
|
|
86
|
+
});
|
|
87
|
+
try {
|
|
88
|
+
await agent.start();
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
spinner.fail(chalk_1.default.red(`Failed to connect: ${err.message}`));
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
process.on('SIGINT', () => {
|
|
95
|
+
console.log(chalk_1.default.dim('\nStopping agent...'));
|
|
96
|
+
agent.stop();
|
|
97
|
+
process.exit(0);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
// mcp (nested subcommands: add / list / remove)
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
const mcp = program
|
|
104
|
+
.command('mcp')
|
|
105
|
+
.description('Manage local MCP servers (data sources)');
|
|
106
|
+
mcp
|
|
107
|
+
.command('add')
|
|
108
|
+
.description('Register a local MCP server')
|
|
109
|
+
.requiredOption('--id <id>', 'Unique MCP id (e.g. bloomberg)')
|
|
110
|
+
.requiredOption('--name <name>', 'Display name (e.g. "Bloomberg Terminal")')
|
|
111
|
+
.requiredOption('--command <cmd>', 'Executable to run (e.g. python)')
|
|
112
|
+
.option('--args <args...>', 'Arguments (e.g. -m bloomberg_mcp)')
|
|
113
|
+
.action((opts) => {
|
|
114
|
+
const { mcpServers = [] } = (0, config_file_1.readConfig)();
|
|
115
|
+
const entry = {
|
|
116
|
+
id: opts.id,
|
|
117
|
+
name: opts.name,
|
|
118
|
+
command: opts.command,
|
|
119
|
+
args: opts.args ?? [],
|
|
120
|
+
};
|
|
121
|
+
const idx = mcpServers.findIndex((s) => s.id === opts.id);
|
|
122
|
+
if (idx >= 0) {
|
|
123
|
+
mcpServers[idx] = entry;
|
|
124
|
+
console.log(chalk_1.default.green(`Updated MCP: ${opts.id}`));
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
mcpServers.push(entry);
|
|
128
|
+
console.log(chalk_1.default.green(`Added MCP: ${opts.id}`));
|
|
129
|
+
}
|
|
130
|
+
(0, config_file_1.writeConfig)({ mcpServers });
|
|
131
|
+
console.log(chalk_1.default.dim(` Saved to: ${config_file_1.CONFIG_PATH}`));
|
|
132
|
+
console.log(chalk_1.default.dim(' Run "novaluna-agent start" to connect.'));
|
|
133
|
+
});
|
|
134
|
+
mcp
|
|
135
|
+
.command('list')
|
|
136
|
+
.description('List configured MCP servers')
|
|
137
|
+
.action(() => {
|
|
138
|
+
const { mcpServers = [] } = (0, config_file_1.readConfig)();
|
|
139
|
+
if (mcpServers.length === 0) {
|
|
140
|
+
console.log(chalk_1.default.dim('No MCP servers configured. Run: novaluna-agent mcp add'));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
console.log(chalk_1.default.bold('\nConfigured MCP servers:'));
|
|
144
|
+
for (const s of mcpServers) {
|
|
145
|
+
console.log(` ${chalk_1.default.cyan(s.id.padEnd(20))} ${s.name}`);
|
|
146
|
+
console.log(chalk_1.default.dim(` ${''.padEnd(22)}${s.command} ${(s.args ?? []).join(' ')}`));
|
|
147
|
+
}
|
|
148
|
+
console.log(chalk_1.default.dim(`\nConfig: ${config_file_1.CONFIG_PATH}`));
|
|
149
|
+
});
|
|
150
|
+
mcp
|
|
151
|
+
.command('remove <id>')
|
|
152
|
+
.description('Remove a configured MCP server')
|
|
153
|
+
.action((id) => {
|
|
154
|
+
const { mcpServers = [] } = (0, config_file_1.readConfig)();
|
|
155
|
+
const filtered = mcpServers.filter((s) => s.id !== id);
|
|
156
|
+
if (filtered.length === mcpServers.length) {
|
|
157
|
+
console.log(chalk_1.default.yellow(`MCP not found: ${id}`));
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
(0, config_file_1.writeConfig)({ mcpServers: filtered });
|
|
161
|
+
console.log(chalk_1.default.green(`Removed: ${id}`));
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
// ---------------------------------------------------------------------------
|
|
165
|
+
// config show
|
|
166
|
+
// ---------------------------------------------------------------------------
|
|
167
|
+
program
|
|
168
|
+
.command('config')
|
|
169
|
+
.description('Show current configuration')
|
|
170
|
+
.action(() => {
|
|
171
|
+
const config = (0, config_file_1.readConfig)();
|
|
172
|
+
console.log(chalk_1.default.bold(`\nConfig file: ${config_file_1.CONFIG_PATH}\n`));
|
|
173
|
+
if (!config.token) {
|
|
174
|
+
console.log(chalk_1.default.yellow(' No token configured. Run with --token nvl_xxx'));
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
console.log(` Token: ${chalk_1.default.green(config.token.slice(0, 10) + '...')}`);
|
|
178
|
+
}
|
|
179
|
+
if (config.gatewayUrl) {
|
|
180
|
+
console.log(` Gateway: ${config.gatewayUrl}`);
|
|
181
|
+
}
|
|
182
|
+
const n = config.mcpServers?.length ?? 0;
|
|
183
|
+
console.log(` MCPs: ${n} configured\n`);
|
|
184
|
+
});
|
|
185
|
+
program.parse(process.argv);
|
|
186
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-file.d.ts","sourceRoot":"","sources":["../src/config-file.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG3C,eAAO,MAAM,WAAW,QAAiC,CAAC;AAE1D,wBAAgB,UAAU,IAAI,OAAO,CAAC,WAAW,CAAC,CAOjD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAI/D"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CONFIG_PATH = void 0;
|
|
4
|
+
exports.readConfig = readConfig;
|
|
5
|
+
exports.writeConfig = writeConfig;
|
|
6
|
+
/**
|
|
7
|
+
* File-based config for the Novaluna Agent.
|
|
8
|
+
* Reads and writes ~/.novaluna/agent.json — the same file the setup wizard generates.
|
|
9
|
+
*/
|
|
10
|
+
const os_1 = require("os");
|
|
11
|
+
const path_1 = require("path");
|
|
12
|
+
const fs_1 = require("fs");
|
|
13
|
+
const CONFIG_DIR = (0, path_1.join)((0, os_1.homedir)(), '.novaluna');
|
|
14
|
+
exports.CONFIG_PATH = (0, path_1.join)(CONFIG_DIR, 'agent.json');
|
|
15
|
+
function readConfig() {
|
|
16
|
+
if (!(0, fs_1.existsSync)(exports.CONFIG_PATH))
|
|
17
|
+
return {};
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse((0, fs_1.readFileSync)(exports.CONFIG_PATH, 'utf8'));
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return {};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function writeConfig(updates) {
|
|
26
|
+
const current = readConfig();
|
|
27
|
+
(0, fs_1.mkdirSync)(CONFIG_DIR, { recursive: true });
|
|
28
|
+
(0, fs_1.writeFileSync)(exports.CONFIG_PATH, JSON.stringify({ ...current, ...updates }, null, 2), 'utf8');
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=config-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-file.js","sourceRoot":"","sources":["../src/config-file.ts"],"names":[],"mappings":";;;AAYA,gCAOC;AAED,kCAIC;AAzBD;;;GAGG;AACH,2BAA6B;AAC7B,+BAA4B;AAC5B,2BAAwE;AAGxE,MAAM,UAAU,GAAG,IAAA,WAAI,EAAC,IAAA,YAAO,GAAE,EAAE,WAAW,CAAC,CAAC;AACnC,QAAA,WAAW,GAAG,IAAA,WAAI,EAAC,UAAU,EAAE,YAAY,CAAC,CAAC;AAE1D,SAAgB,UAAU;IACxB,IAAI,CAAC,IAAA,eAAU,EAAC,mBAAW,CAAC;QAAE,OAAO,EAAE,CAAC;IACxC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAY,EAAC,mBAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAgB,WAAW,CAAC,OAA6B;IACvD,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,IAAA,cAAS,EAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,IAAA,kBAAa,EAAC,mBAAW,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAC1F,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { NovalunaAgent } from './agent';
|
|
2
|
+
export type { AgentPlugin } from './agent';
|
|
3
|
+
export { McpProcess } from './mcp-process';
|
|
4
|
+
export { GatewayClient } from './ws-client';
|
|
5
|
+
export type { AgentConfig, McpServerConfig, McpTool, McpRegistration } from './types';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GatewayClient = exports.McpProcess = exports.NovalunaAgent = void 0;
|
|
4
|
+
var agent_1 = require("./agent");
|
|
5
|
+
Object.defineProperty(exports, "NovalunaAgent", { enumerable: true, get: function () { return agent_1.NovalunaAgent; } });
|
|
6
|
+
var mcp_process_1 = require("./mcp-process");
|
|
7
|
+
Object.defineProperty(exports, "McpProcess", { enumerable: true, get: function () { return mcp_process_1.McpProcess; } });
|
|
8
|
+
var ws_client_1 = require("./ws-client");
|
|
9
|
+
Object.defineProperty(exports, "GatewayClient", { enumerable: true, get: function () { return ws_client_1.GatewayClient; } });
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iCAAwC;AAA/B,sGAAA,aAAa,OAAA;AAEtB,6CAA2C;AAAlC,yGAAA,UAAU,OAAA;AACnB,yCAA4C;AAAnC,0GAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { McpServerConfig, McpTool } from './types';
|
|
3
|
+
export declare class McpProcess extends EventEmitter {
|
|
4
|
+
private config;
|
|
5
|
+
private proc;
|
|
6
|
+
private nextId;
|
|
7
|
+
private pending;
|
|
8
|
+
private tools;
|
|
9
|
+
constructor(config: McpServerConfig);
|
|
10
|
+
start(): Promise<void>;
|
|
11
|
+
getTools(): McpTool[];
|
|
12
|
+
callTool(name: string, args: Record<string, unknown>): Promise<unknown>;
|
|
13
|
+
private handleLine;
|
|
14
|
+
private request;
|
|
15
|
+
stop(): void;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=mcp-process.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-process.d.ts","sourceRoot":"","sources":["../src/mcp-process.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAgBnD,qBAAa,UAAW,SAAQ,YAAY;IAM9B,OAAO,CAAC,MAAM;IAL1B,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAAoF;IACnG,OAAO,CAAC,KAAK,CAAiB;gBAEV,MAAM,EAAE,eAAe;IAIrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB5B,QAAQ,IAAI,OAAO,EAAE;IAIf,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7E,OAAO,CAAC,UAAU;IAkBlB,OAAO,CAAC,OAAO;IAgBf,IAAI,IAAI,IAAI;CAIb"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.McpProcess = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Manages a single stdio MCP server process.
|
|
6
|
+
* Sends JSON-RPC requests and receives responses over stdin/stdout.
|
|
7
|
+
*/
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
const readline_1 = require("readline");
|
|
10
|
+
const events_1 = require("events");
|
|
11
|
+
class McpProcess extends events_1.EventEmitter {
|
|
12
|
+
config;
|
|
13
|
+
proc = null;
|
|
14
|
+
nextId = 1;
|
|
15
|
+
pending = new Map();
|
|
16
|
+
tools = [];
|
|
17
|
+
constructor(config) {
|
|
18
|
+
super();
|
|
19
|
+
this.config = config;
|
|
20
|
+
}
|
|
21
|
+
async start() {
|
|
22
|
+
this.proc = (0, child_process_1.spawn)(this.config.command, this.config.args ?? [], {
|
|
23
|
+
env: { ...process.env, ...this.config.env },
|
|
24
|
+
stdio: ['pipe', 'pipe', 'inherit'],
|
|
25
|
+
});
|
|
26
|
+
const rl = (0, readline_1.createInterface)({ input: this.proc.stdout });
|
|
27
|
+
rl.on('line', (line) => this.handleLine(line));
|
|
28
|
+
this.proc.on('exit', (code) => {
|
|
29
|
+
this.emit('exit', code);
|
|
30
|
+
});
|
|
31
|
+
// Initialize MCP session
|
|
32
|
+
await this.request('initialize', {
|
|
33
|
+
protocolVersion: '2024-11-05',
|
|
34
|
+
capabilities: {},
|
|
35
|
+
clientInfo: { name: 'novaluna-agent', version: '1.0.0' },
|
|
36
|
+
});
|
|
37
|
+
// Discover tools
|
|
38
|
+
const result = await this.request('tools/list', {});
|
|
39
|
+
this.tools = result?.tools ?? [];
|
|
40
|
+
}
|
|
41
|
+
getTools() {
|
|
42
|
+
return this.tools;
|
|
43
|
+
}
|
|
44
|
+
async callTool(name, args) {
|
|
45
|
+
return this.request('tools/call', { name, arguments: args });
|
|
46
|
+
}
|
|
47
|
+
handleLine(line) {
|
|
48
|
+
if (!line.trim())
|
|
49
|
+
return;
|
|
50
|
+
let msg;
|
|
51
|
+
try {
|
|
52
|
+
msg = JSON.parse(line);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return; // Ignore non-JSON lines (stderr-like noise on stdout)
|
|
56
|
+
}
|
|
57
|
+
const pending = this.pending.get(msg.id);
|
|
58
|
+
if (!pending)
|
|
59
|
+
return;
|
|
60
|
+
this.pending.delete(msg.id);
|
|
61
|
+
if (msg.error) {
|
|
62
|
+
pending.reject(new Error(msg.error.message));
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
pending.resolve(msg.result);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
request(method, params) {
|
|
69
|
+
return new Promise((resolve, reject) => {
|
|
70
|
+
const id = this.nextId++;
|
|
71
|
+
const req = { jsonrpc: '2.0', id, method, params };
|
|
72
|
+
this.pending.set(id, { resolve, reject });
|
|
73
|
+
this.proc.stdin.write(JSON.stringify(req) + '\n');
|
|
74
|
+
// Timeout individual requests after 30s
|
|
75
|
+
setTimeout(() => {
|
|
76
|
+
if (this.pending.has(id)) {
|
|
77
|
+
this.pending.delete(id);
|
|
78
|
+
reject(new Error(`MCP request ${method} timed out`));
|
|
79
|
+
}
|
|
80
|
+
}, 30_000);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
stop() {
|
|
84
|
+
this.proc?.kill();
|
|
85
|
+
this.proc = null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.McpProcess = McpProcess;
|
|
89
|
+
//# sourceMappingURL=mcp-process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-process.js","sourceRoot":"","sources":["../src/mcp-process.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export interface McpServerConfig {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
command: string;
|
|
5
|
+
args?: string[];
|
|
6
|
+
env?: Record<string, string>;
|
|
7
|
+
}
|
|
8
|
+
export interface AgentConfig {
|
|
9
|
+
token: string;
|
|
10
|
+
gatewayUrl?: string;
|
|
11
|
+
mcpServers: McpServerConfig[];
|
|
12
|
+
}
|
|
13
|
+
export type GatewayInbound = {
|
|
14
|
+
type: 'auth_ok';
|
|
15
|
+
jwt: string;
|
|
16
|
+
agent_id: string;
|
|
17
|
+
org_id: number;
|
|
18
|
+
} | {
|
|
19
|
+
type: 'auth_error';
|
|
20
|
+
reason: string;
|
|
21
|
+
} | {
|
|
22
|
+
type: 'mcp_call';
|
|
23
|
+
call_id: string;
|
|
24
|
+
mcp_id: string;
|
|
25
|
+
method: string;
|
|
26
|
+
params: Record<string, unknown>;
|
|
27
|
+
} | {
|
|
28
|
+
type: 'disconnect';
|
|
29
|
+
reason: string;
|
|
30
|
+
};
|
|
31
|
+
export type GatewayOutbound = {
|
|
32
|
+
type: 'auth';
|
|
33
|
+
token: string;
|
|
34
|
+
version: string;
|
|
35
|
+
} | {
|
|
36
|
+
type: 'register';
|
|
37
|
+
mcps: McpRegistration[];
|
|
38
|
+
} | {
|
|
39
|
+
type: 'heartbeat';
|
|
40
|
+
ts: number;
|
|
41
|
+
} | {
|
|
42
|
+
type: 'mcp_response';
|
|
43
|
+
call_id: string;
|
|
44
|
+
result: unknown;
|
|
45
|
+
} | {
|
|
46
|
+
type: 'mcp_error';
|
|
47
|
+
call_id: string;
|
|
48
|
+
error: string;
|
|
49
|
+
};
|
|
50
|
+
export interface McpRegistration {
|
|
51
|
+
id: string;
|
|
52
|
+
name: string;
|
|
53
|
+
tools: McpTool[];
|
|
54
|
+
}
|
|
55
|
+
export interface McpTool {
|
|
56
|
+
name: string;
|
|
57
|
+
description?: string;
|
|
58
|
+
inputSchema?: Record<string, unknown>;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AAID,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAG,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GACvG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3C,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAS,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAK,IAAI,EAAE,eAAe,EAAE,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,WAAW,CAAC;IAAI,EAAE,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,WAAW,CAAC;IAAI,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { AgentConfig, GatewayOutbound } from './types';
|
|
3
|
+
export declare class GatewayClient extends EventEmitter {
|
|
4
|
+
private config;
|
|
5
|
+
private ws;
|
|
6
|
+
private jwt;
|
|
7
|
+
private agentId;
|
|
8
|
+
private heartbeatTimer;
|
|
9
|
+
private reconnectDelay;
|
|
10
|
+
private stopped;
|
|
11
|
+
constructor(config: AgentConfig);
|
|
12
|
+
get id(): string | null;
|
|
13
|
+
connect(): Promise<void>;
|
|
14
|
+
send(msg: GatewayOutbound): void;
|
|
15
|
+
stop(): void;
|
|
16
|
+
private startHeartbeat;
|
|
17
|
+
private stopHeartbeat;
|
|
18
|
+
private scheduleReconnect;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=ws-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-client.d.ts","sourceRoot":"","sources":["../src/ws-client.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,WAAW,EAAkB,eAAe,EAAE,MAAM,SAAS,CAAC;AAMvE,qBAAa,aAAc,SAAQ,YAAY;IAQjC,OAAO,CAAC,MAAM;IAP1B,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,GAAG,CAAuB;IAClC,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,OAAO,CAAS;gBAEJ,MAAM,EAAE,WAAW;IAIvC,IAAI,EAAE,IAAI,MAAM,GAAG,IAAI,CAAyB;IAE1C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAiD9B,IAAI,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;IAMhC,IAAI,IAAI,IAAI;IAMZ,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,iBAAiB;CAU1B"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.GatewayClient = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Authenticated WebSocket client to Novaluna agent-gateway.
|
|
9
|
+
* Handles auth handshake, reconnect with exponential backoff, and heartbeats.
|
|
10
|
+
*/
|
|
11
|
+
const ws_1 = __importDefault(require("ws"));
|
|
12
|
+
const events_1 = require("events");
|
|
13
|
+
const DEFAULT_GATEWAY_URL = 'wss://agents.novaluna.ai/ws/agent';
|
|
14
|
+
const HEARTBEAT_INTERVAL_MS = 25_000;
|
|
15
|
+
const VERSION = '1.0.0';
|
|
16
|
+
class GatewayClient extends events_1.EventEmitter {
|
|
17
|
+
config;
|
|
18
|
+
ws = null;
|
|
19
|
+
jwt = null;
|
|
20
|
+
agentId = null;
|
|
21
|
+
heartbeatTimer = null;
|
|
22
|
+
reconnectDelay = 1_000;
|
|
23
|
+
stopped = false;
|
|
24
|
+
constructor(config) {
|
|
25
|
+
super();
|
|
26
|
+
this.config = config;
|
|
27
|
+
}
|
|
28
|
+
get id() { return this.agentId; }
|
|
29
|
+
async connect() {
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
const url = this.config.gatewayUrl ?? DEFAULT_GATEWAY_URL;
|
|
32
|
+
this.ws = new ws_1.default(url);
|
|
33
|
+
const onOpen = () => {
|
|
34
|
+
this.send({ type: 'auth', token: this.config.token, version: VERSION });
|
|
35
|
+
};
|
|
36
|
+
const onMessage = (data) => {
|
|
37
|
+
let msg;
|
|
38
|
+
try {
|
|
39
|
+
msg = JSON.parse(data.toString());
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (msg.type === 'auth_ok') {
|
|
45
|
+
this.jwt = msg.jwt;
|
|
46
|
+
this.agentId = msg.agent_id;
|
|
47
|
+
this.reconnectDelay = 1_000; // reset backoff on success
|
|
48
|
+
this.startHeartbeat();
|
|
49
|
+
this.emit('connected', { agentId: msg.agent_id, orgId: msg.org_id });
|
|
50
|
+
resolve();
|
|
51
|
+
}
|
|
52
|
+
else if (msg.type === 'auth_error') {
|
|
53
|
+
reject(new Error(`Auth failed: ${msg.reason}`));
|
|
54
|
+
}
|
|
55
|
+
else if (msg.type === 'mcp_call') {
|
|
56
|
+
this.emit('mcp_call', msg);
|
|
57
|
+
}
|
|
58
|
+
else if (msg.type === 'disconnect') {
|
|
59
|
+
this.emit('disconnect', msg.reason);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const onClose = () => {
|
|
63
|
+
this.stopHeartbeat();
|
|
64
|
+
this.emit('disconnected');
|
|
65
|
+
if (!this.stopped)
|
|
66
|
+
this.scheduleReconnect();
|
|
67
|
+
};
|
|
68
|
+
const onError = (err) => {
|
|
69
|
+
this.emit('error', err);
|
|
70
|
+
reject(err);
|
|
71
|
+
};
|
|
72
|
+
this.ws.once('open', onOpen);
|
|
73
|
+
this.ws.on('message', onMessage);
|
|
74
|
+
this.ws.once('close', onClose);
|
|
75
|
+
this.ws.once('error', onError);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
send(msg) {
|
|
79
|
+
if (this.ws?.readyState === ws_1.default.OPEN) {
|
|
80
|
+
this.ws.send(JSON.stringify(msg));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
stop() {
|
|
84
|
+
this.stopped = true;
|
|
85
|
+
this.stopHeartbeat();
|
|
86
|
+
this.ws?.close();
|
|
87
|
+
}
|
|
88
|
+
startHeartbeat() {
|
|
89
|
+
this.heartbeatTimer = setInterval(() => {
|
|
90
|
+
this.send({ type: 'heartbeat', ts: Math.floor(Date.now() / 1000) });
|
|
91
|
+
}, HEARTBEAT_INTERVAL_MS);
|
|
92
|
+
}
|
|
93
|
+
stopHeartbeat() {
|
|
94
|
+
if (this.heartbeatTimer) {
|
|
95
|
+
clearInterval(this.heartbeatTimer);
|
|
96
|
+
this.heartbeatTimer = null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
scheduleReconnect() {
|
|
100
|
+
const delay = this.reconnectDelay;
|
|
101
|
+
this.reconnectDelay = Math.min(this.reconnectDelay * 2, 30_000);
|
|
102
|
+
setTimeout(() => {
|
|
103
|
+
if (!this.stopped) {
|
|
104
|
+
this.emit('reconnecting', delay);
|
|
105
|
+
this.connect().catch(() => { });
|
|
106
|
+
}
|
|
107
|
+
}, delay);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
exports.GatewayClient = GatewayClient;
|
|
111
|
+
//# sourceMappingURL=ws-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-client.js","sourceRoot":"","sources":["../src/ws-client.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@novaluna/agent",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Novaluna desktop agent — connects local MCP servers (Bloomberg Terminal, etc.) to Novaluna cloud",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"novaluna-agent": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "ts-node src/cli.ts",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist/",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"novaluna",
|
|
24
|
+
"mcp",
|
|
25
|
+
"bloomberg",
|
|
26
|
+
"fixed-income",
|
|
27
|
+
"agent"
|
|
28
|
+
],
|
|
29
|
+
"license": "UNLICENSED",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/novaluna-ai/novaluna-agent.git"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://workbench.novaluna.ai",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"ws": "^8.18.0",
|
|
37
|
+
"commander": "^12.1.0",
|
|
38
|
+
"chalk": "^4.1.2",
|
|
39
|
+
"ora": "^5.4.1"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/ws": "^8.5.13",
|
|
43
|
+
"@types/node": "^22.0.0",
|
|
44
|
+
"typescript": "^5.6.0"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=18.0.0"
|
|
48
|
+
}
|
|
49
|
+
}
|