voyageai-cli 1.27.0 → 1.29.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.
@@ -0,0 +1,112 @@
1
+ 'use strict';
2
+
3
+ const { SSEServerTransport } = require('@modelcontextprotocol/sdk/server/sse.js');
4
+ const { createServer } = require('./server');
5
+
6
+ /** @type {Map<string, { server: any, transport: SSEServerTransport, createdAt: number, lastActivity: number }>} */
7
+ const sessions = new Map();
8
+
9
+ const MAX_SESSIONS = 50;
10
+ const IDLE_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
11
+
12
+ /**
13
+ * Prune idle or expired SSE sessions.
14
+ */
15
+ function pruneSessions() {
16
+ const now = Date.now();
17
+ for (const [id, entry] of sessions) {
18
+ if (now - entry.lastActivity > IDLE_TIMEOUT_MS) {
19
+ if (process.env.VAI_MCP_VERBOSE) {
20
+ process.stderr.write(`SSE session ${id} idle-pruned after ${Math.floor((now - entry.lastActivity) / 1000)}s\n`);
21
+ }
22
+ try { entry.transport.close(); } catch { /* ignore */ }
23
+ sessions.delete(id);
24
+ }
25
+ }
26
+ }
27
+
28
+ // Run pruning every 5 minutes
29
+ let _pruneInterval = null;
30
+
31
+ /**
32
+ * Register SSE transport routes on an Express app.
33
+ *
34
+ * GET /sse — Client opens an SSE stream (returns event stream + session ID)
35
+ * POST /messages — Client sends JSON-RPC messages to a session
36
+ *
37
+ * @param {import('express').Express} app
38
+ * @param {Function} authenticateRequest — Express middleware for bearer auth
39
+ */
40
+ function setupSSE(app, authenticateRequest) {
41
+ // Start the pruning interval
42
+ if (!_pruneInterval) {
43
+ _pruneInterval = setInterval(pruneSessions, 5 * 60 * 1000);
44
+ _pruneInterval.unref(); // Don't keep process alive just for pruning
45
+ }
46
+
47
+ // SSE connection endpoint — client GETs this to open a stream
48
+ app.get('/sse', authenticateRequest, async (req, res) => {
49
+ // Enforce max concurrent sessions
50
+ pruneSessions();
51
+ if (sessions.size >= MAX_SESSIONS) {
52
+ return res.status(503).json({
53
+ error: `Too many active SSE sessions (max ${MAX_SESSIONS}). Try again later.`,
54
+ });
55
+ }
56
+
57
+ const server = createServer();
58
+ const transport = new SSEServerTransport('/messages', res);
59
+ const sessionId = transport.sessionId;
60
+
61
+ sessions.set(sessionId, {
62
+ server,
63
+ transport,
64
+ createdAt: Date.now(),
65
+ lastActivity: Date.now(),
66
+ });
67
+
68
+ if (process.env.VAI_MCP_VERBOSE) {
69
+ process.stderr.write(`SSE session ${sessionId} connected (active: ${sessions.size})\n`);
70
+ }
71
+
72
+ // Clean up on disconnect
73
+ res.on('close', () => {
74
+ sessions.delete(sessionId);
75
+ try { transport.close(); } catch { /* ignore */ }
76
+ if (process.env.VAI_MCP_VERBOSE) {
77
+ process.stderr.write(`SSE session ${sessionId} disconnected (active: ${sessions.size})\n`);
78
+ }
79
+ });
80
+
81
+ await server.connect(transport);
82
+ });
83
+
84
+ // SSE message endpoint — client POSTs JSON-RPC messages here
85
+ app.post('/messages', authenticateRequest, async (req, res) => {
86
+ const sessionId = req.query.sessionId;
87
+ if (!sessionId) {
88
+ return res.status(400).json({ error: 'Missing sessionId query parameter' });
89
+ }
90
+
91
+ const entry = sessions.get(sessionId);
92
+ if (!entry) {
93
+ return res.status(404).json({
94
+ error: 'Session not found. It may have expired or been disconnected.',
95
+ });
96
+ }
97
+
98
+ // Update last activity for idle tracking
99
+ entry.lastActivity = Date.now();
100
+
101
+ await entry.transport.handlePostMessage(req, res, req.body);
102
+ });
103
+ }
104
+
105
+ /**
106
+ * Get current SSE session count (for health endpoint).
107
+ */
108
+ function getSessionCount() {
109
+ return sessions.size;
110
+ }
111
+
112
+ module.exports = { setupSSE, getSessionCount };
@@ -0,0 +1,71 @@
1
+ # VAI Announcements
2
+
3
+ This file contains the announcements displayed on the VAI home page carousel.
4
+ Each announcement is separated by `---` and uses YAML frontmatter for metadata.
5
+
6
+ Format:
7
+ - `id`: Unique identifier (used to track dismissals)
8
+ - `badge`: Label shown on the card (e.g., "New", "Update", "New Model")
9
+ - `published`: Date published (YYYY-MM-DD)
10
+ - `expires`: Date to stop showing (YYYY-MM-DD)
11
+ - `cta_label`: Button text
12
+ - `cta_action`: Either "navigate" (internal tab) or "link" (external URL)
13
+ - `cta_target`: Tab name (e.g., "/benchmark") or full URL
14
+
15
+ The title is the first `## ` heading, and the description is the paragraph below it.
16
+
17
+ ---
18
+
19
+ id: ann-voyage-4
20
+ badge: New Model
21
+ published: 2026-02-14
22
+ expires: 2026-03-15
23
+ cta_label: Try It Now
24
+ cta_action: navigate
25
+ cta_target: /benchmark
26
+
27
+ ## Voyage AI 4 Large Now Available
28
+
29
+ The latest embedding model from Voyage AI is ready to benchmark in VAI. Experience improved accuracy and performance across all embedding tasks.
30
+
31
+ ---
32
+
33
+ id: ann-marketplace-workflows
34
+ badge: New
35
+ published: 2026-02-12
36
+ expires: 2026-03-01
37
+ cta_label: Explore Marketplace
38
+ cta_action: navigate
39
+ cta_target: /workflows
40
+
41
+ ## New Marketplace Workflows
42
+
43
+ HIPAA-compliant document search, legal contract analysis, and more workflows are now available in the VAI Marketplace.
44
+
45
+ ---
46
+
47
+ id: ann-csv-ingestion
48
+ badge: Update
49
+ published: 2026-02-10
50
+ expires: 2026-04-01
51
+ cta_label: Learn More
52
+ cta_action: link
53
+ cta_target: https://docs.vaicli.com/csv-import
54
+
55
+ ## VAI v1.3 Adds Bulk CSV Ingestion
56
+
57
+ Import large datasets efficiently with the new bulk CSV ingestion feature. Process thousands of documents in a single operation.
58
+
59
+ ---
60
+
61
+ id: ann-workflow-store
62
+ badge: New
63
+ published: 2026-02-13
64
+ expires: 2026-03-15
65
+ cta_label: Browse Store
66
+ cta_action: navigate
67
+ cta_target: /workflows
68
+
69
+ ## Workflow Store Now Live
70
+
71
+ Discover, install, and share VAI workflows with the new integrated Workflow Store. Browse featured picks, community contributions, and install with one click.
Binary file