@sonde/agent 0.2.3 → 0.2.5
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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-test.log +14 -12
- package/.turbo/turbo-typecheck.log +1 -1
- package/CHANGELOG.md +20 -0
- package/dist/cli/mcp-bridge.d.ts +2 -0
- package/dist/cli/mcp-bridge.d.ts.map +1 -0
- package/dist/cli/mcp-bridge.js +193 -0
- package/dist/cli/mcp-bridge.js.map +1 -0
- package/dist/cli/mcp-bridge.test.d.ts +2 -0
- package/dist/cli/mcp-bridge.test.d.ts.map +1 -0
- package/dist/cli/mcp-bridge.test.js +54 -0
- package/dist/cli/mcp-bridge.test.js.map +1 -0
- package/dist/cli/update.d.ts +18 -0
- package/dist/cli/update.d.ts.map +1 -0
- package/dist/cli/update.js +71 -0
- package/dist/cli/update.js.map +1 -0
- package/dist/cli/update.test.d.ts +2 -0
- package/dist/cli/update.test.d.ts.map +1 -0
- package/dist/cli/update.test.js +55 -0
- package/dist/cli/update.test.js.map +1 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +16 -2
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +59 -5
- package/dist/index.js.map +1 -1
- package/dist/runtime/connection.d.ts +1 -0
- package/dist/runtime/connection.d.ts.map +1 -1
- package/dist/runtime/connection.js +30 -5
- package/dist/runtime/connection.js.map +1 -1
- package/dist/runtime/executor.d.ts +6 -0
- package/dist/runtime/executor.d.ts.map +1 -1
- package/dist/runtime/executor.js +2 -2
- package/dist/runtime/executor.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/mcp-bridge.test.ts +58 -0
- package/src/cli/mcp-bridge.ts +217 -0
- package/src/cli/update.test.ts +69 -0
- package/src/cli/update.ts +78 -0
- package/src/config.ts +16 -2
- package/src/index.ts +66 -7
- package/src/runtime/connection.ts +39 -6
- package/src/runtime/executor.ts +14 -1
- package/tsconfig.tsbuildinfo +1 -1
package/.turbo/turbo-build.log
CHANGED
package/.turbo/turbo-test.log
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
|
|
2
|
-
> @sonde/agent@0.2.
|
|
2
|
+
> @sonde/agent@0.2.4 test
|
|
3
3
|
> vitest run
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
RUN v2.1.9 /Users/joshowen/Library/CloudStorage/ProtonDrive-joshowen@protonmail.com-folder/AI/ClaudeCode/sonde/packages/agent
|
|
7
7
|
|
|
8
|
-
✓ src/
|
|
9
|
-
✓ src/
|
|
10
|
-
✓ src/
|
|
11
|
-
✓ src/runtime/
|
|
12
|
-
✓ src/
|
|
13
|
-
✓ src/runtime/
|
|
8
|
+
✓ src/cli/mcp-bridge.test.ts (5 tests) 2ms
|
|
9
|
+
✓ src/runtime/scrubber.test.ts (11 tests) 4ms
|
|
10
|
+
✓ src/system/scanner.test.ts (10 tests) 5ms
|
|
11
|
+
✓ src/runtime/audit.test.ts (5 tests) 4ms
|
|
12
|
+
✓ src/cli/update.test.ts (9 tests) 3ms
|
|
13
|
+
✓ src/runtime/privilege.test.ts (4 tests) 80ms
|
|
14
|
+
✓ src/runtime/attestation.test.ts (8 tests) 2ms
|
|
14
15
|
✓ src/cli/packs.test.ts (11 tests) 4ms
|
|
15
|
-
✓ src/runtime/
|
|
16
|
+
✓ src/runtime/executor.test.ts (7 tests) 3ms
|
|
17
|
+
✓ src/runtime/connection.test.ts (11 tests) 12ms
|
|
16
18
|
|
|
17
|
-
Test Files
|
|
18
|
-
Tests
|
|
19
|
-
Start at
|
|
20
|
-
Duration
|
|
19
|
+
Test Files 10 passed (10)
|
|
20
|
+
Tests 81 passed (81)
|
|
21
|
+
Start at 15:54:24
|
|
22
|
+
Duration 2.37s (transform 1.89s, setup 0ms, collect 6.78s, tests 120ms, environment 1ms, prepare 3.41s)
|
|
21
23
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @sonde/agent
|
|
2
2
|
|
|
3
|
+
## 0.2.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- updates
|
|
8
|
+
|
|
9
|
+
- Updated dependencies []:
|
|
10
|
+
- @sonde/shared@0.1.2
|
|
11
|
+
- @sonde/packs@0.1.2
|
|
12
|
+
|
|
13
|
+
## 0.2.4
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- latest updates
|
|
18
|
+
|
|
19
|
+
- Updated dependencies []:
|
|
20
|
+
- @sonde/shared@0.1.1
|
|
21
|
+
- @sonde/packs@0.1.1
|
|
22
|
+
|
|
3
23
|
## 0.2.3
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-bridge.d.ts","sourceRoot":"","sources":["../../src/cli/mcp-bridge.ts"],"names":[],"mappings":"AAsJA,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAkEpD"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* stdio → StreamableHTTP MCP bridge.
|
|
3
|
+
*
|
|
4
|
+
* Claude Code spawns `sonde mcp-bridge` and speaks MCP over stdin/stdout.
|
|
5
|
+
* This bridge forwards every JSON-RPC message to the hub's /mcp endpoint
|
|
6
|
+
* using the StreamableHTTP transport and relays responses back on stdout.
|
|
7
|
+
*
|
|
8
|
+
* Protocol details:
|
|
9
|
+
* stdin – newline-delimited JSON-RPC (MCP stdio transport)
|
|
10
|
+
* stdout – newline-delimited JSON-RPC (MCP stdio transport)
|
|
11
|
+
* hub – HTTP POST /mcp with JSON body, response is JSON or SSE
|
|
12
|
+
*/
|
|
13
|
+
import { loadConfig } from '../config.js';
|
|
14
|
+
// ── stdio helpers ──────────────────────────────────────────────────────
|
|
15
|
+
/** Write a JSON-RPC message to stdout (newline-delimited). */
|
|
16
|
+
function writeMessage(msg) {
|
|
17
|
+
const json = JSON.stringify(msg);
|
|
18
|
+
process.stdout.write(`${json}\n`);
|
|
19
|
+
}
|
|
20
|
+
/** Log to stderr so it doesn't interfere with the JSON-RPC channel. */
|
|
21
|
+
function log(msg) {
|
|
22
|
+
process.stderr.write(`[sonde-bridge] ${msg}\n`);
|
|
23
|
+
}
|
|
24
|
+
// ── SSE parsing ────────────────────────────────────────────────────────
|
|
25
|
+
/** Parse SSE text into individual data payloads. */
|
|
26
|
+
function parseSseEvents(text) {
|
|
27
|
+
const payloads = [];
|
|
28
|
+
let currentData = '';
|
|
29
|
+
for (const line of text.split('\n')) {
|
|
30
|
+
if (line.startsWith('data: ')) {
|
|
31
|
+
currentData += line.slice(6);
|
|
32
|
+
}
|
|
33
|
+
else if (line === '' && currentData) {
|
|
34
|
+
payloads.push(currentData);
|
|
35
|
+
currentData = '';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Flush any remaining data (stream may not end with blank line)
|
|
39
|
+
if (currentData) {
|
|
40
|
+
payloads.push(currentData);
|
|
41
|
+
}
|
|
42
|
+
return payloads;
|
|
43
|
+
}
|
|
44
|
+
class McpHttpTransport {
|
|
45
|
+
sessionId;
|
|
46
|
+
mcpUrl;
|
|
47
|
+
apiKey;
|
|
48
|
+
constructor(opts) {
|
|
49
|
+
this.mcpUrl = opts.mcpUrl;
|
|
50
|
+
this.apiKey = opts.apiKey;
|
|
51
|
+
}
|
|
52
|
+
/** Send a JSON-RPC message to the hub and relay response(s) to stdout. */
|
|
53
|
+
async send(message) {
|
|
54
|
+
const headers = {
|
|
55
|
+
'Content-Type': 'application/json',
|
|
56
|
+
Accept: 'application/json, text/event-stream',
|
|
57
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
58
|
+
};
|
|
59
|
+
if (this.sessionId) {
|
|
60
|
+
headers['Mcp-Session-Id'] = this.sessionId;
|
|
61
|
+
}
|
|
62
|
+
const res = await fetch(this.mcpUrl, {
|
|
63
|
+
method: 'POST',
|
|
64
|
+
headers,
|
|
65
|
+
body: JSON.stringify(message),
|
|
66
|
+
});
|
|
67
|
+
// Capture session ID from response
|
|
68
|
+
const newSessionId = res.headers.get('mcp-session-id');
|
|
69
|
+
if (newSessionId) {
|
|
70
|
+
this.sessionId = newSessionId;
|
|
71
|
+
}
|
|
72
|
+
if (!res.ok) {
|
|
73
|
+
const text = await res.text();
|
|
74
|
+
log(`Hub returned ${res.status}: ${text}`);
|
|
75
|
+
// Send JSON-RPC error response if the message had an id
|
|
76
|
+
const msg = message;
|
|
77
|
+
if (msg.id !== undefined) {
|
|
78
|
+
writeMessage({
|
|
79
|
+
jsonrpc: '2.0',
|
|
80
|
+
id: msg.id,
|
|
81
|
+
error: { code: -32603, message: `Hub returned HTTP ${res.status}` },
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const contentType = res.headers.get('content-type') ?? '';
|
|
87
|
+
if (contentType.includes('text/event-stream')) {
|
|
88
|
+
// SSE response — parse events and forward each as a JSON-RPC message
|
|
89
|
+
const text = await res.text();
|
|
90
|
+
for (const payload of parseSseEvents(text)) {
|
|
91
|
+
try {
|
|
92
|
+
const parsed = JSON.parse(payload);
|
|
93
|
+
writeMessage(parsed);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
log(`Failed to parse SSE payload: ${payload.slice(0, 200)}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
// JSON response — forward directly
|
|
102
|
+
const text = await res.text();
|
|
103
|
+
if (text) {
|
|
104
|
+
try {
|
|
105
|
+
const parsed = JSON.parse(text);
|
|
106
|
+
writeMessage(parsed);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
log(`Failed to parse JSON response: ${text.slice(0, 200)}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/** Terminate the session cleanly. */
|
|
115
|
+
async close() {
|
|
116
|
+
if (!this.sessionId)
|
|
117
|
+
return;
|
|
118
|
+
try {
|
|
119
|
+
await fetch(this.mcpUrl, {
|
|
120
|
+
method: 'DELETE',
|
|
121
|
+
headers: {
|
|
122
|
+
'Mcp-Session-Id': this.sessionId,
|
|
123
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// Best-effort cleanup
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// ── Main ───────────────────────────────────────────────────────────────
|
|
133
|
+
export async function startMcpBridge() {
|
|
134
|
+
const config = loadConfig();
|
|
135
|
+
if (!config) {
|
|
136
|
+
log('Agent not enrolled. Run "sonde enroll" first.');
|
|
137
|
+
process.exit(1);
|
|
138
|
+
}
|
|
139
|
+
if (!config.apiKey) {
|
|
140
|
+
log('No API key found in agent config. Re-enroll the agent with "sonde enroll".');
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
const mcpUrl = `${config.hubUrl}/mcp`;
|
|
144
|
+
log(`Bridging stdio ↔ ${mcpUrl}`);
|
|
145
|
+
const transport = new McpHttpTransport({
|
|
146
|
+
mcpUrl,
|
|
147
|
+
apiKey: config.apiKey,
|
|
148
|
+
});
|
|
149
|
+
// Read newline-delimited JSON-RPC from stdin
|
|
150
|
+
let buffer = '';
|
|
151
|
+
process.stdin.setEncoding('utf-8');
|
|
152
|
+
process.stdin.on('data', (chunk) => {
|
|
153
|
+
buffer += chunk;
|
|
154
|
+
// Process complete lines
|
|
155
|
+
let newlineIdx;
|
|
156
|
+
while ((newlineIdx = buffer.indexOf('\n')) !== -1) {
|
|
157
|
+
const line = buffer.slice(0, newlineIdx).trim();
|
|
158
|
+
buffer = buffer.slice(newlineIdx + 1);
|
|
159
|
+
if (!line)
|
|
160
|
+
continue;
|
|
161
|
+
let message;
|
|
162
|
+
try {
|
|
163
|
+
message = JSON.parse(line);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
log(`Failed to parse stdin message: ${line.slice(0, 200)}`);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
// Fire and forget — errors are handled inside send()
|
|
170
|
+
transport.send(message).catch((err) => {
|
|
171
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
172
|
+
log(`Transport error: ${errorMsg}`);
|
|
173
|
+
// Try to send a JSON-RPC error if we can extract the message id
|
|
174
|
+
const msg = message;
|
|
175
|
+
if (msg.id !== undefined) {
|
|
176
|
+
writeMessage({
|
|
177
|
+
jsonrpc: '2.0',
|
|
178
|
+
id: msg.id,
|
|
179
|
+
error: { code: -32603, message: `Bridge transport error: ${errorMsg}` },
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
process.stdin.on('end', async () => {
|
|
186
|
+
log('stdin closed, shutting down');
|
|
187
|
+
await transport.close();
|
|
188
|
+
process.exit(0);
|
|
189
|
+
});
|
|
190
|
+
// Keep the process alive
|
|
191
|
+
process.stdin.resume();
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=mcp-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-bridge.js","sourceRoot":"","sources":["../../src/cli/mcp-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,0EAA0E;AAE1E,8DAA8D;AAC9D,SAAS,YAAY,CAAC,GAAY;IAChC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;AACpC,CAAC;AAED,uEAAuE;AACvE,SAAS,GAAG,CAAC,GAAW;IACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;AAClD,CAAC;AAED,0EAA0E;AAE1E,oDAAoD;AACpD,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9B,WAAW,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/B,CAAC;aAAM,IAAI,IAAI,KAAK,EAAE,IAAI,WAAW,EAAE,CAAC;YACtC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC3B,WAAW,GAAG,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;IACD,gEAAgE;IAChE,IAAI,WAAW,EAAE,CAAC;QAChB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AASD,MAAM,gBAAgB;IACZ,SAAS,CAAqB;IAC9B,MAAM,CAAS;IACf,MAAM,CAAS;IAEvB,YAAY,IAAmB;QAC7B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED,0EAA0E;IAC1E,KAAK,CAAC,IAAI,CAAC,OAAgB;QACzB,MAAM,OAAO,GAA2B;YACtC,cAAc,EAAE,kBAAkB;YAClC,MAAM,EAAE,qCAAqC;YAC7C,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;SACvC,CAAC;QAEF,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC;QAC7C,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE;YACnC,MAAM,EAAE,MAAM;YACd,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,CAAC,CAAC;QAEH,mCAAmC;QACnC,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QACvD,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC,SAAS,GAAG,YAAY,CAAC;QAChC,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,GAAG,CAAC,gBAAgB,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;YAC3C,wDAAwD;YACxD,MAAM,GAAG,GAAG,OAAmC,CAAC;YAChD,IAAI,GAAG,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;gBACzB,YAAY,CAAC;oBACX,OAAO,EAAE,KAAK;oBACd,EAAE,EAAE,GAAG,CAAC,EAAE;oBACV,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,qBAAqB,GAAG,CAAC,MAAM,EAAE,EAAE;iBACpE,CAAC,CAAC;YACL,CAAC;YACD,OAAO;QACT,CAAC;QAED,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAE1D,IAAI,WAAW,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC9C,qEAAqE;YACrE,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,KAAK,MAAM,OAAO,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3C,IAAI,CAAC;oBACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;oBAC5C,YAAY,CAAC,MAAM,CAAC,CAAC;gBACvB,CAAC;gBAAC,MAAM,CAAC;oBACP,GAAG,CAAC,gCAAgC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC/D,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,mCAAmC;YACnC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC;oBACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACzC,YAAY,CAAC,MAAM,CAAC,CAAC;gBACvB,CAAC;gBAAC,MAAM,CAAC;oBACP,GAAG,CAAC,kCAAkC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC9D,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,qCAAqC;IACrC,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO;QAC5B,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE;gBACvB,MAAM,EAAE,QAAQ;gBAChB,OAAO,EAAE;oBACP,gBAAgB,EAAE,IAAI,CAAC,SAAS;oBAChC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;iBACvC;aACF,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,sBAAsB;QACxB,CAAC;IACH,CAAC;CACF;AAED,0EAA0E;AAE1E,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,+CAA+C,CAAC,CAAC;QACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,GAAG,CAAC,4EAA4E,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,MAAM,CAAC;IACtC,GAAG,CAAC,oBAAoB,MAAM,EAAE,CAAC,CAAC;IAElC,MAAM,SAAS,GAAG,IAAI,gBAAgB,CAAC;QACrC,MAAM;QACN,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC,CAAC;IAEH,6CAA6C;IAC7C,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACnC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;QACzC,MAAM,IAAI,KAAK,CAAC;QAChB,yBAAyB;QACzB,IAAI,UAAkB,CAAC;QACvB,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;YAChD,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;YACtC,IAAI,CAAC,IAAI;gBAAE,SAAS;YAEpB,IAAI,OAAgB,CAAC;YACrB,IAAI,CAAC;gBACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC7B,CAAC;YAAC,MAAM,CAAC;gBACP,GAAG,CAAC,kCAAkC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC5D,SAAS;YACX,CAAC;YAED,qDAAqD;YACrD,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;gBAC7C,MAAM,QAAQ,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAClE,GAAG,CAAC,oBAAoB,QAAQ,EAAE,CAAC,CAAC;gBACpC,gEAAgE;gBAChE,MAAM,GAAG,GAAG,OAAmC,CAAC;gBAChD,IAAI,GAAG,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;oBACzB,YAAY,CAAC;wBACX,OAAO,EAAE,KAAK;wBACd,EAAE,EAAE,GAAG,CAAC,EAAE;wBACV,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,2BAA2B,QAAQ,EAAE,EAAE;qBACxE,CAAC,CAAC;gBACL,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;QACjC,GAAG,CAAC,6BAA6B,CAAC,CAAC;QACnC,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,yBAAyB;IACzB,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-bridge.test.d.ts","sourceRoot":"","sources":["../../src/cli/mcp-bridge.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
// Test the SSE parsing logic (extracted for testability)
|
|
3
|
+
function parseSseEvents(text) {
|
|
4
|
+
const payloads = [];
|
|
5
|
+
let currentData = '';
|
|
6
|
+
for (const line of text.split('\n')) {
|
|
7
|
+
if (line.startsWith('data: ')) {
|
|
8
|
+
currentData += line.slice(6);
|
|
9
|
+
}
|
|
10
|
+
else if (line === '' && currentData) {
|
|
11
|
+
payloads.push(currentData);
|
|
12
|
+
currentData = '';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
if (currentData) {
|
|
16
|
+
payloads.push(currentData);
|
|
17
|
+
}
|
|
18
|
+
return payloads;
|
|
19
|
+
}
|
|
20
|
+
describe('parseSseEvents', () => {
|
|
21
|
+
it('parses a single event', () => {
|
|
22
|
+
const text = 'event: message\ndata: {"jsonrpc":"2.0","id":1,"result":{}}\n\n';
|
|
23
|
+
const events = parseSseEvents(text);
|
|
24
|
+
expect(events).toEqual(['{"jsonrpc":"2.0","id":1,"result":{}}']);
|
|
25
|
+
});
|
|
26
|
+
it('parses multiple events', () => {
|
|
27
|
+
const text = [
|
|
28
|
+
'event: message',
|
|
29
|
+
'data: {"jsonrpc":"2.0","id":1,"result":{"tools":[]}}',
|
|
30
|
+
'',
|
|
31
|
+
'event: message',
|
|
32
|
+
'data: {"jsonrpc":"2.0","method":"notifications/tools/list_changed"}',
|
|
33
|
+
'',
|
|
34
|
+
].join('\n');
|
|
35
|
+
const events = parseSseEvents(text);
|
|
36
|
+
expect(events).toHaveLength(2);
|
|
37
|
+
expect(JSON.parse(events[0])).toHaveProperty('id', 1);
|
|
38
|
+
expect(JSON.parse(events[1])).toHaveProperty('method', 'notifications/tools/list_changed');
|
|
39
|
+
});
|
|
40
|
+
it('handles data without trailing blank line', () => {
|
|
41
|
+
const text = 'data: {"jsonrpc":"2.0","id":2,"result":{}}';
|
|
42
|
+
const events = parseSseEvents(text);
|
|
43
|
+
expect(events).toEqual(['{"jsonrpc":"2.0","id":2,"result":{}}']);
|
|
44
|
+
});
|
|
45
|
+
it('handles empty input', () => {
|
|
46
|
+
expect(parseSseEvents('')).toEqual([]);
|
|
47
|
+
});
|
|
48
|
+
it('ignores non-data lines', () => {
|
|
49
|
+
const text = 'event: message\nid: 123\ndata: {"ok":true}\n\n';
|
|
50
|
+
const events = parseSseEvents(text);
|
|
51
|
+
expect(events).toEqual(['{"ok":true}']);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=mcp-bridge.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-bridge.test.js","sourceRoot":"","sources":["../../src/cli/mcp-bridge.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,yDAAyD;AACzD,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9B,WAAW,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/B,CAAC;aAAM,IAAI,IAAI,KAAK,EAAE,IAAI,WAAW,EAAE,CAAC;YACtC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC3B,WAAW,GAAG,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;IACD,IAAI,WAAW,EAAE,CAAC;QAChB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,IAAI,GAAG,gEAAgE,CAAC;QAC9E,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,sCAAsC,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,IAAI,GAAG;YACX,gBAAgB;YAChB,sDAAsD;YACtD,EAAE;YACF,gBAAgB;YAChB,qEAAqE;YACrE,EAAE;SACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACvD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,EAAE,kCAAkC,CAAC,CAAC;IAC9F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,IAAI,GAAG,4CAA4C,CAAC;QAC1D,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,sCAAsC,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,IAAI,GAAG,gDAAgD,CAAC;QAC9D,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight semver comparison: returns true if a < b.
|
|
3
|
+
*/
|
|
4
|
+
export declare function semverLt(a: string, b: string): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Check for available updates by querying the npm registry.
|
|
7
|
+
*/
|
|
8
|
+
export declare function checkForUpdate(): Promise<{
|
|
9
|
+
currentVersion: string;
|
|
10
|
+
latestVersion: string;
|
|
11
|
+
updateAvailable: boolean;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* Perform the update by running npm install -g.
|
|
15
|
+
* After install, tries to restart the systemd service (best-effort).
|
|
16
|
+
*/
|
|
17
|
+
export declare function performUpdate(targetVersion: string): void;
|
|
18
|
+
//# sourceMappingURL=update.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/cli/update.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAUtD;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC;IAC9C,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC,CAmBD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CA2BzD"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { VERSION } from '../version.js';
|
|
3
|
+
/**
|
|
4
|
+
* Lightweight semver comparison: returns true if a < b.
|
|
5
|
+
*/
|
|
6
|
+
export function semverLt(a, b) {
|
|
7
|
+
const pa = a.split('.').map(Number);
|
|
8
|
+
const pb = b.split('.').map(Number);
|
|
9
|
+
for (let i = 0; i < 3; i++) {
|
|
10
|
+
const av = pa[i] ?? 0;
|
|
11
|
+
const bv = pb[i] ?? 0;
|
|
12
|
+
if (av < bv)
|
|
13
|
+
return true;
|
|
14
|
+
if (av > bv)
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Check for available updates by querying the npm registry.
|
|
21
|
+
*/
|
|
22
|
+
export async function checkForUpdate() {
|
|
23
|
+
const res = await fetch('https://registry.npmjs.org/@sonde/agent/latest', {
|
|
24
|
+
headers: { Accept: 'application/json' },
|
|
25
|
+
signal: AbortSignal.timeout(10_000),
|
|
26
|
+
});
|
|
27
|
+
if (!res.ok) {
|
|
28
|
+
throw new Error(`Failed to check npm registry (HTTP ${res.status})`);
|
|
29
|
+
}
|
|
30
|
+
const data = (await res.json());
|
|
31
|
+
const latestVersion = data.version;
|
|
32
|
+
if (!latestVersion) {
|
|
33
|
+
throw new Error('No version found in npm registry response');
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
currentVersion: VERSION,
|
|
37
|
+
latestVersion,
|
|
38
|
+
updateAvailable: semverLt(VERSION, latestVersion),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Perform the update by running npm install -g.
|
|
43
|
+
* After install, tries to restart the systemd service (best-effort).
|
|
44
|
+
*/
|
|
45
|
+
export function performUpdate(targetVersion) {
|
|
46
|
+
console.log(`Installing @sonde/agent@${targetVersion}...`);
|
|
47
|
+
execFileSync('npm', ['install', '-g', `@sonde/agent@${targetVersion}`], {
|
|
48
|
+
stdio: 'inherit',
|
|
49
|
+
timeout: 120_000,
|
|
50
|
+
});
|
|
51
|
+
// Verify the installed version
|
|
52
|
+
const output = execFileSync('sonde', ['--version'], {
|
|
53
|
+
encoding: 'utf-8',
|
|
54
|
+
timeout: 5_000,
|
|
55
|
+
}).trim();
|
|
56
|
+
if (output !== targetVersion) {
|
|
57
|
+
throw new Error(`Version mismatch after install: expected ${targetVersion}, got ${output}`);
|
|
58
|
+
}
|
|
59
|
+
console.log(`Successfully updated to v${targetVersion}`);
|
|
60
|
+
// Best-effort systemd restart
|
|
61
|
+
try {
|
|
62
|
+
execFileSync('systemctl', ['restart', 'sonde-agent'], {
|
|
63
|
+
timeout: 10_000,
|
|
64
|
+
});
|
|
65
|
+
console.log('Restarted sonde-agent systemd service');
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// systemd not available or service not installed — that's fine
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/cli/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,CAAS,EAAE,CAAS;IAC3C,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtB,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtB,IAAI,EAAE,GAAG,EAAE;YAAE,OAAO,IAAI,CAAC;QACzB,IAAI,EAAE,GAAG,EAAE;YAAE,OAAO,KAAK,CAAC;IAC5B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAKlC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,gDAAgD,EAAE;QACxE,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;QACvC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;KACpC,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,sCAAsC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IACvE,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAyB,CAAC;IACxD,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC;IACnC,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO;QACL,cAAc,EAAE,OAAO;QACvB,aAAa;QACb,eAAe,EAAE,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;KAClD,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,aAAqB;IACjD,OAAO,CAAC,GAAG,CAAC,2BAA2B,aAAa,KAAK,CAAC,CAAC;IAC3D,YAAY,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,gBAAgB,aAAa,EAAE,CAAC,EAAE;QACtE,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,+BAA+B;IAC/B,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE;QAClD,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,KAAK;KACf,CAAC,CAAC,IAAI,EAAE,CAAC;IACV,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,4CAA4C,aAAa,SAAS,MAAM,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,4BAA4B,aAAa,EAAE,CAAC,CAAC;IAEzD,8BAA8B;IAC9B,IAAI,CAAC;QACH,YAAY,CAAC,WAAW,EAAE,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE;YACpD,OAAO,EAAE,MAAM;SAChB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,+DAA+D;IACjE,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.test.d.ts","sourceRoot":"","sources":["../../src/cli/update.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { checkForUpdate, semverLt } from './update.js';
|
|
3
|
+
describe('semverLt', () => {
|
|
4
|
+
it('returns true when a < b (major)', () => {
|
|
5
|
+
expect(semverLt('0.1.0', '1.0.0')).toBe(true);
|
|
6
|
+
});
|
|
7
|
+
it('returns true when a < b (minor)', () => {
|
|
8
|
+
expect(semverLt('1.0.0', '1.1.0')).toBe(true);
|
|
9
|
+
});
|
|
10
|
+
it('returns true when a < b (patch)', () => {
|
|
11
|
+
expect(semverLt('1.1.0', '1.1.1')).toBe(true);
|
|
12
|
+
});
|
|
13
|
+
it('returns false when equal', () => {
|
|
14
|
+
expect(semverLt('1.2.3', '1.2.3')).toBe(false);
|
|
15
|
+
});
|
|
16
|
+
it('returns false when a > b', () => {
|
|
17
|
+
expect(semverLt('2.0.0', '1.9.9')).toBe(false);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
describe('checkForUpdate', () => {
|
|
21
|
+
const originalFetch = globalThis.fetch;
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
globalThis.fetch = originalFetch;
|
|
24
|
+
});
|
|
25
|
+
it('returns update info when newer version is available', async () => {
|
|
26
|
+
globalThis.fetch = vi.fn().mockResolvedValue({
|
|
27
|
+
ok: true,
|
|
28
|
+
json: async () => ({ version: '99.0.0' }),
|
|
29
|
+
});
|
|
30
|
+
const result = await checkForUpdate();
|
|
31
|
+
expect(result.latestVersion).toBe('99.0.0');
|
|
32
|
+
expect(result.updateAvailable).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
it('returns no update when on latest version', async () => {
|
|
35
|
+
// Use 0.0.0 which is lower than any real version
|
|
36
|
+
globalThis.fetch = vi.fn().mockResolvedValue({
|
|
37
|
+
ok: true,
|
|
38
|
+
json: async () => ({ version: '0.0.0' }),
|
|
39
|
+
});
|
|
40
|
+
const result = await checkForUpdate();
|
|
41
|
+
expect(result.updateAvailable).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
it('throws on network error', async () => {
|
|
44
|
+
globalThis.fetch = vi.fn().mockRejectedValue(new Error('Network error'));
|
|
45
|
+
await expect(checkForUpdate()).rejects.toThrow('Network error');
|
|
46
|
+
});
|
|
47
|
+
it('throws on non-ok response', async () => {
|
|
48
|
+
globalThis.fetch = vi.fn().mockResolvedValue({
|
|
49
|
+
ok: false,
|
|
50
|
+
status: 500,
|
|
51
|
+
});
|
|
52
|
+
await expect(checkForUpdate()).rejects.toThrow('Failed to check npm registry');
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=update.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.test.js","sourceRoot":"","sources":["../../src/cli/update.test.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAKD,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,UAAU,IAAI,WAAW,GAAG,SAAS,CAoBpD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAGpD;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,uEAAuE;AACvE,wBAAgB,SAAS,CACvB,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,IAAI,CAcN"}
|
package/dist/config.js
CHANGED
|
@@ -7,12 +7,26 @@ export function getConfigPath() {
|
|
|
7
7
|
return CONFIG_FILE;
|
|
8
8
|
}
|
|
9
9
|
export function loadConfig() {
|
|
10
|
+
let raw;
|
|
11
|
+
try {
|
|
12
|
+
raw = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
const code = err.code;
|
|
16
|
+
if (code === 'ENOENT')
|
|
17
|
+
return undefined;
|
|
18
|
+
if (code === 'EACCES') {
|
|
19
|
+
console.error(`Cannot read config at ${CONFIG_FILE}. Check file permissions.`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
10
24
|
try {
|
|
11
|
-
const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
12
25
|
return JSON.parse(raw);
|
|
13
26
|
}
|
|
14
27
|
catch {
|
|
15
|
-
|
|
28
|
+
console.error(`Config file corrupted at ${CONFIG_FILE}. Re-enroll with "sonde enroll".`);
|
|
29
|
+
process.exit(1);
|
|
16
30
|
}
|
|
17
31
|
}
|
|
18
32
|
export function saveConfig(config) {
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAe7B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AACrD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAEzD,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,IAAI,GAAI,GAAyB,CAAC,IAAI,CAAC;QAC7C,IAAI,IAAI,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QACxC,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,yBAAyB,WAAW,2BAA2B,CAAC,CAAC;YAC/E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,4BAA4B,WAAW,kCAAkC,CAAC,CAAC;QACzF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAmB;IAC5C,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACjF,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,SAAS,CACvB,MAAmB,EACnB,OAAe,EACf,MAAc,EACd,SAAiB;IAEjB,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAEnD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAEjD,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;AACjC,CAAC"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAKA,OAAO,EAAE,KAAK,WAAW,EAAyC,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAiB,MAAM,yBAAyB,CAAC;AAChG,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAyCtD,UAAU,OAAO;IACf,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,aAAa,CAAC;IACxB,UAAU,EAAE,eAAe,CAAC;CAC7B;AAED,iBAAS,aAAa,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAaxD;AAiOD,OAAO,EAAE,aAAa,EAAE,CAAC;AACzB,YAAY,EAAE,OAAO,EAAE,CAAC"}
|