agentic-flow 2.1.4 → 2.1.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/CHANGELOG.md +6 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/federation/FederationHubServer.d.ts +5 -0
- package/dist/federation/FederationHubServer.d.ts.map +1 -1
- package/dist/federation/FederationHubServer.js +25 -7
- package/dist/federation/FederationHubServer.js.map +1 -1
- package/dist/federation/SecurityManager.d.ts +1 -1
- package/dist/federation/SecurityManager.d.ts.map +1 -1
- package/dist/federation/SecurityManager.js +9 -4
- package/dist/federation/SecurityManager.js.map +1 -1
- package/package.json +1 -1
- package/wasm/reasoningbank/reasoningbank_wasm_bg.js +36 -36
- package/wasm/reasoningbank/reasoningbank_wasm_bg.wasm +0 -0
- package/wasm/reasoningbank/reasoningbank_wasm_bg.wasm.d.ts +3 -3
|
@@ -10,6 +10,10 @@ export interface HubConfig {
|
|
|
10
10
|
dbPath?: string;
|
|
11
11
|
maxAgents?: number;
|
|
12
12
|
syncInterval?: number;
|
|
13
|
+
/** Interface to listen on. Loopback unless set: the hub is not safe to expose without TLS in front. */
|
|
14
|
+
host?: string;
|
|
15
|
+
/** HMAC secret agent tokens are verified with (default: JWT_SECRET). */
|
|
16
|
+
jwtSecret?: string;
|
|
13
17
|
}
|
|
14
18
|
export interface AgentConnection {
|
|
15
19
|
ws: WebSocket;
|
|
@@ -31,6 +35,7 @@ export interface SyncMessage {
|
|
|
31
35
|
}
|
|
32
36
|
export declare class FederationHubServer {
|
|
33
37
|
private config;
|
|
38
|
+
private security;
|
|
34
39
|
private wss?;
|
|
35
40
|
private server?;
|
|
36
41
|
private connections;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FederationHubServer.d.ts","sourceRoot":"","sources":["../../src/federation/FederationHubServer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAmB,SAAS,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"FederationHubServer.d.ts","sourceRoot":"","sources":["../../src/federation/FederationHubServer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAmB,SAAS,EAAE,MAAM,IAAI,CAAC;AAQhD,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uGAAuG;IACvG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,SAAS,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,GAAG,CAAC,CAAkB;IAC9B,OAAO,CAAC,MAAM,CAAC,CAAkC;IACjD,OAAO,CAAC,WAAW,CAA2C;IAC9D,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,iBAAiB,CAA8B;gBAE3C,MAAM,EAAE,SAAS;IAwB7B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAqD1B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAqC5B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA0ExB;;OAEG;YACW,UAAU;IA8CxB;;OAEG;YACW,UAAU;IAiCxB;;OAEG;YACW,UAAU;IAoHxB;;;OAGG;YACW,eAAe;IA6B7B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAsBzB;;OAEG;IACH,OAAO,CAAC,IAAI;IAMZ;;OAEG;IACH,OAAO,CAAC,SAAS;IAQjB;;OAEG;IACH,QAAQ,IAAI;QACV,eAAe,EAAE,MAAM,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;QACtB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;KAChB;IAYD;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA0B3B;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,GAAE,MAAU,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;CAiBnF"}
|
|
@@ -7,9 +7,11 @@
|
|
|
7
7
|
import { WebSocketServer, WebSocket } from 'ws';
|
|
8
8
|
import { createServer } from 'http';
|
|
9
9
|
import { logger } from '../utils/logger.js';
|
|
10
|
+
import { SecurityManager } from './SecurityManager.js';
|
|
10
11
|
import Database from 'better-sqlite3';
|
|
11
12
|
export class FederationHubServer {
|
|
12
13
|
config;
|
|
14
|
+
security;
|
|
13
15
|
wss;
|
|
14
16
|
server;
|
|
15
17
|
connections = new Map();
|
|
@@ -19,11 +21,16 @@ export class FederationHubServer {
|
|
|
19
21
|
constructor(config) {
|
|
20
22
|
this.config = {
|
|
21
23
|
port: 8443,
|
|
24
|
+
host: '127.0.0.1',
|
|
22
25
|
dbPath: ':memory:',
|
|
23
26
|
maxAgents: 1000,
|
|
24
27
|
syncInterval: 5000,
|
|
25
28
|
...config
|
|
26
29
|
};
|
|
30
|
+
if (!this.config.jwtSecret && !process.env.JWT_SECRET) {
|
|
31
|
+
logger.warn('No jwtSecret or JWT_SECRET set: the hub uses a random secret, so no agent can authenticate until you set one');
|
|
32
|
+
}
|
|
33
|
+
this.security = new SecurityManager(this.config.jwtSecret);
|
|
27
34
|
// Initialize hub database (SQLite for metadata)
|
|
28
35
|
this.db = new Database(this.config.dbPath);
|
|
29
36
|
this.initializeDatabase();
|
|
@@ -100,7 +107,7 @@ export class FederationHubServer {
|
|
|
100
107
|
this.handleConnection(ws);
|
|
101
108
|
});
|
|
102
109
|
// Start listening
|
|
103
|
-
this.server.listen(this.config.port, () => {
|
|
110
|
+
this.server.listen(this.config.port, this.config.host, () => {
|
|
104
111
|
logger.info('Federation hub server started', {
|
|
105
112
|
port: this.config.port,
|
|
106
113
|
protocol: 'WebSocket',
|
|
@@ -193,21 +200,32 @@ export class FederationHubServer {
|
|
|
193
200
|
this.sendError(ws, 'Missing authentication credentials');
|
|
194
201
|
return null;
|
|
195
202
|
}
|
|
196
|
-
//
|
|
197
|
-
|
|
203
|
+
// Identity comes from the verified token, never from what the client claims.
|
|
204
|
+
let identity;
|
|
205
|
+
try {
|
|
206
|
+
identity = await this.security.verifyAgentToken(message.token);
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
this.sendError(ws, 'Authentication failed');
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
if (identity.agentId !== message.agentId || identity.tenantId !== message.tenantId) {
|
|
213
|
+
this.sendError(ws, 'Authentication failed');
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
198
216
|
// Register agent
|
|
199
217
|
this.db.prepare(`
|
|
200
218
|
INSERT OR REPLACE INTO agents (agent_id, tenant_id, connected_at, last_sync_at, vector_clock)
|
|
201
219
|
VALUES (?, ?, ?, ?, ?)
|
|
202
|
-
`).run(
|
|
220
|
+
`).run(identity.agentId, identity.tenantId, Date.now(), Date.now(), JSON.stringify(message.vectorClock || {}));
|
|
203
221
|
// Send acknowledgment
|
|
204
222
|
this.send(ws, {
|
|
205
223
|
type: 'ack',
|
|
206
224
|
timestamp: Date.now()
|
|
207
225
|
});
|
|
208
226
|
return {
|
|
209
|
-
agentId:
|
|
210
|
-
tenantId:
|
|
227
|
+
agentId: identity.agentId,
|
|
228
|
+
tenantId: identity.tenantId
|
|
211
229
|
};
|
|
212
230
|
}
|
|
213
231
|
/**
|
|
@@ -412,7 +430,7 @@ export class FederationHubServer {
|
|
|
412
430
|
}
|
|
413
431
|
// Close databases
|
|
414
432
|
this.db.close();
|
|
415
|
-
await this.agentDB
|
|
433
|
+
await this.agentDB?.close();
|
|
416
434
|
logger.info('Federation hub server stopped');
|
|
417
435
|
}
|
|
418
436
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FederationHubServer.js","sourceRoot":"","sources":["../../src/federation/FederationHubServer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Federation Hub Server - WebSocket-based hub for agent synchronization\n *\n * This is a production-ready implementation using WebSocket (HTTP/2 upgrade)\n * as a fallback until native QUIC is implemented.\n */\n\nimport { WebSocketServer, WebSocket } from 'ws';\nimport { createServer } from 'http';\nimport { logger } from '../utils/logger.js';\nimport Database from 'better-sqlite3';\n// AgentDB is optional - federation works with SQLite only\ntype AgentDB = any;\n\nexport interface HubConfig {\n port?: number;\n dbPath?: string;\n maxAgents?: number;\n syncInterval?: number;\n}\n\nexport interface AgentConnection {\n ws: WebSocket;\n agentId: string;\n tenantId: string;\n connectedAt: number;\n lastSyncAt: number;\n vectorClock: Record<string, number>;\n}\n\nexport interface SyncMessage {\n type: 'auth' | 'pull' | 'push' | 'ack' | 'error';\n agentId?: string;\n tenantId?: string;\n token?: string;\n vectorClock?: Record<string, number>;\n data?: any[];\n error?: string;\n timestamp: number;\n}\n\nexport class FederationHubServer {\n private config: HubConfig;\n private wss?: WebSocketServer;\n private server?: ReturnType<typeof createServer>;\n private connections: Map<string, AgentConnection> = new Map();\n private db: Database.Database;\n private agentDB: AgentDB;\n private globalVectorClock: Record<string, number> = {};\n\n constructor(config: HubConfig) {\n this.config = {\n port: 8443,\n dbPath: ':memory:',\n maxAgents: 1000,\n syncInterval: 5000,\n ...config\n };\n\n // Initialize hub database (SQLite for metadata)\n this.db = new Database(this.config.dbPath!);\n this.initializeDatabase();\n\n // AgentDB integration optional - using SQLite for now\n this.agentDB = null as any;\n logger.info('Federation hub initialized with SQLite');\n }\n\n /**\n * Initialize hub database schema\n */\n private initializeDatabase(): void {\n // Memory store: tenant-isolated episodes\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS episodes (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n tenant_id TEXT NOT NULL,\n agent_id TEXT NOT NULL,\n session_id TEXT NOT NULL,\n task TEXT NOT NULL,\n input TEXT NOT NULL,\n output TEXT NOT NULL,\n reward REAL NOT NULL,\n critique TEXT,\n success INTEGER NOT NULL,\n tokens_used INTEGER DEFAULT 0,\n latency_ms INTEGER DEFAULT 0,\n vector_clock TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n UNIQUE(tenant_id, agent_id, session_id, task)\n );\n\n CREATE INDEX IF NOT EXISTS idx_episodes_tenant ON episodes(tenant_id);\n CREATE INDEX IF NOT EXISTS idx_episodes_task ON episodes(tenant_id, task);\n CREATE INDEX IF NOT EXISTS idx_episodes_created ON episodes(created_at);\n\n -- Change log for sync\n CREATE TABLE IF NOT EXISTS change_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n tenant_id TEXT NOT NULL,\n agent_id TEXT NOT NULL,\n operation TEXT NOT NULL,\n episode_id INTEGER,\n vector_clock TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n FOREIGN KEY(episode_id) REFERENCES episodes(id)\n );\n\n CREATE INDEX IF NOT EXISTS idx_changes_tenant ON change_log(tenant_id);\n CREATE INDEX IF NOT EXISTS idx_changes_created ON change_log(created_at);\n\n -- Agent registry\n CREATE TABLE IF NOT EXISTS agents (\n agent_id TEXT PRIMARY KEY,\n tenant_id TEXT NOT NULL,\n connected_at INTEGER NOT NULL,\n last_sync_at INTEGER NOT NULL,\n vector_clock TEXT NOT NULL\n );\n `);\n\n logger.info('Federation hub database initialized');\n }\n\n /**\n * Start the hub server\n */\n async start(): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n // Create HTTP server\n this.server = createServer();\n\n // Create WebSocket server\n this.wss = new WebSocketServer({ server: this.server });\n\n // Handle connections\n this.wss.on('connection', (ws: WebSocket) => {\n this.handleConnection(ws);\n });\n\n // Start listening\n this.server.listen(this.config.port, () => {\n logger.info('Federation hub server started', {\n port: this.config.port,\n protocol: 'WebSocket',\n maxAgents: this.config.maxAgents\n });\n resolve();\n });\n\n // Error handling\n this.server.on('error', (error) => {\n logger.error('Hub server error', { error: error.message });\n reject(error);\n });\n\n } catch (error: any) {\n logger.error('Failed to start hub server', { error: error.message });\n reject(error);\n }\n });\n }\n\n /**\n * Handle new agent connection\n */\n private handleConnection(ws: WebSocket): void {\n let agentId: string | undefined;\n let tenantId: string | undefined;\n let authenticated = false;\n\n logger.info('New connection attempt');\n\n ws.on('message', async (data: Buffer) => {\n try {\n const message: SyncMessage = JSON.parse(data.toString());\n\n // Authentication required first\n if (!authenticated && message.type !== 'auth') {\n this.sendError(ws, 'Authentication required');\n ws.close();\n return;\n }\n\n switch (message.type) {\n case 'auth':\n const authResult = await this.handleAuth(ws, message);\n if (authResult) {\n agentId = authResult.agentId;\n tenantId = authResult.tenantId;\n authenticated = true;\n\n // Register connection\n this.connections.set(agentId, {\n ws,\n agentId,\n tenantId,\n connectedAt: Date.now(),\n lastSyncAt: Date.now(),\n vectorClock: message.vectorClock || {}\n });\n\n logger.info('Agent authenticated', { agentId, tenantId });\n }\n break;\n\n case 'pull':\n if (agentId && tenantId) {\n await this.handlePull(ws, agentId, tenantId, message);\n }\n break;\n\n case 'push':\n if (agentId && tenantId) {\n await this.handlePush(ws, agentId, tenantId, message);\n }\n break;\n\n default:\n this.sendError(ws, `Unknown message type: ${message.type}`);\n }\n\n } catch (error: any) {\n logger.error('Message handling error', { error: error.message });\n this.sendError(ws, error.message);\n }\n });\n\n ws.on('close', () => {\n if (agentId) {\n this.connections.delete(agentId);\n logger.info('Agent disconnected', { agentId, tenantId });\n }\n });\n\n ws.on('error', (error) => {\n logger.error('WebSocket error', { error: error.message, agentId });\n });\n }\n\n /**\n * Handle authentication\n */\n private async handleAuth(\n ws: WebSocket,\n message: SyncMessage\n ): Promise<{ agentId: string; tenantId: string } | null> {\n if (!message.agentId || !message.tenantId || !message.token) {\n this.sendError(ws, 'Missing authentication credentials');\n return null;\n }\n\n // TODO: Verify JWT token (for now, accept all)\n // In production, verify JWT signature and expiration\n\n // Register agent\n this.db.prepare(`\n INSERT OR REPLACE INTO agents (agent_id, tenant_id, connected_at, last_sync_at, vector_clock)\n VALUES (?, ?, ?, ?, ?)\n `).run(\n message.agentId,\n message.tenantId,\n Date.now(),\n Date.now(),\n JSON.stringify(message.vectorClock || {})\n );\n\n // Send acknowledgment\n this.send(ws, {\n type: 'ack',\n timestamp: Date.now()\n });\n\n return {\n agentId: message.agentId,\n tenantId: message.tenantId\n };\n }\n\n /**\n * Handle pull request (agent wants updates from hub)\n */\n private async handlePull(\n ws: WebSocket,\n agentId: string,\n tenantId: string,\n message: SyncMessage\n ): Promise<void> {\n const conn = this.connections.get(agentId);\n if (!conn) {\n this.sendError(ws, 'Agent not connected');\n return;\n }\n\n // Get changes since agent's last vector clock\n const changes = await this.getChangesSince(tenantId, message.vectorClock || {});\n\n // Update last sync time\n conn.lastSyncAt = Date.now();\n\n // Send changes to agent\n this.send(ws, {\n type: 'ack',\n data: changes,\n vectorClock: this.globalVectorClock,\n timestamp: Date.now()\n });\n\n logger.info('Pull completed', {\n agentId,\n tenantId,\n changeCount: changes.length\n });\n }\n\n /**\n * Handle push request (agent sending updates to hub)\n */\n private async handlePush(\n ws: WebSocket,\n agentId: string,\n tenantId: string,\n message: SyncMessage\n ): Promise<void> {\n const conn = this.connections.get(agentId);\n if (!conn) {\n this.sendError(ws, 'Agent not connected');\n return;\n }\n\n if (!message.data || message.data.length === 0) {\n this.send(ws, { type: 'ack', timestamp: Date.now() });\n return;\n }\n\n // Store episodes in both SQLite (metadata) and AgentDB (vector memory)\n const stmt = this.db.prepare(`\n INSERT OR REPLACE INTO episodes\n (tenant_id, agent_id, session_id, task, input, output, reward, critique, success, tokens_used, latency_ms, vector_clock, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n const changeStmt = this.db.prepare(`\n INSERT INTO change_log (tenant_id, agent_id, operation, episode_id, vector_clock, created_at)\n VALUES (?, ?, 'insert', last_insert_rowid(), ?, ?)\n `);\n\n let insertCount = 0;\n\n for (const episode of message.data) {\n try {\n // Store in SQLite for metadata\n stmt.run(\n tenantId,\n agentId,\n episode.sessionId || agentId,\n episode.task,\n episode.input,\n episode.output,\n episode.reward,\n episode.critique || '',\n episode.success ? 1 : 0,\n episode.tokensUsed || 0,\n episode.latencyMs || 0,\n JSON.stringify(message.vectorClock),\n Date.now()\n );\n\n changeStmt.run(\n tenantId,\n agentId,\n JSON.stringify(message.vectorClock),\n Date.now()\n );\n\n // Store in AgentDB for vector memory (with tenant isolation)\n await this.agentDB.storePattern({\n sessionId: `${tenantId}/${episode.sessionId || agentId}`,\n task: episode.task,\n input: episode.input,\n output: episode.output,\n reward: episode.reward,\n critique: episode.critique || '',\n success: episode.success,\n tokensUsed: episode.tokensUsed || 0,\n latencyMs: episode.latencyMs || 0,\n metadata: {\n tenantId,\n agentId,\n vectorClock: message.vectorClock\n }\n });\n\n insertCount++;\n } catch (error: any) {\n logger.error('Failed to insert episode', { error: error.message });\n }\n }\n\n // Update global vector clock\n if (message.vectorClock) {\n for (const [agent, ts] of Object.entries(message.vectorClock)) {\n this.globalVectorClock[agent] = Math.max(\n this.globalVectorClock[agent] || 0,\n ts\n );\n }\n }\n\n // Update connection vector clock\n conn.vectorClock = { ...this.globalVectorClock };\n conn.lastSyncAt = Date.now();\n\n // Send acknowledgment\n this.send(ws, {\n type: 'ack',\n timestamp: Date.now()\n });\n\n logger.info('Push completed', {\n agentId,\n tenantId,\n episodeCount: insertCount\n });\n\n // Broadcast to other agents in same tenant (optional real-time sync)\n this.broadcastToTenant(tenantId, agentId, {\n type: 'push',\n agentId,\n data: message.data,\n timestamp: Date.now()\n });\n }\n\n /**\n * Get changes since a given vector clock\n * Returns memories from other agents in the same tenant\n */\n private async getChangesSince(\n tenantId: string,\n vectorClock: Record<string, number>\n ): Promise<any[]> {\n // Get all episodes for tenant from SQLite\n const episodes = this.db.prepare(`\n SELECT * FROM episodes\n WHERE tenant_id = ?\n ORDER BY created_at DESC\n LIMIT 100\n `).all(tenantId);\n\n return episodes.map((row: any) => ({\n id: row.id,\n agentId: row.agent_id,\n sessionId: row.session_id,\n task: row.task,\n input: row.input,\n output: row.output,\n reward: row.reward,\n critique: row.critique,\n success: row.success === 1,\n tokensUsed: row.tokens_used,\n latencyMs: row.latency_ms,\n vectorClock: JSON.parse(row.vector_clock),\n createdAt: row.created_at\n }));\n }\n\n /**\n * Broadcast message to all agents in a tenant (except sender)\n */\n private broadcastToTenant(\n tenantId: string,\n senderAgentId: string,\n message: SyncMessage\n ): void {\n let broadcastCount = 0;\n\n for (const [agentId, conn] of this.connections.entries()) {\n if (conn.tenantId === tenantId && agentId !== senderAgentId) {\n this.send(conn.ws, message);\n broadcastCount++;\n }\n }\n\n if (broadcastCount > 0) {\n logger.debug('Broadcasted to tenant agents', {\n tenantId,\n recipientCount: broadcastCount\n });\n }\n }\n\n /**\n * Send message to WebSocket\n */\n private send(ws: WebSocket, message: SyncMessage): void {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(message));\n }\n }\n\n /**\n * Send error message\n */\n private sendError(ws: WebSocket, error: string): void {\n this.send(ws, {\n type: 'error',\n error,\n timestamp: Date.now()\n });\n }\n\n /**\n * Get hub statistics\n */\n getStats(): {\n connectedAgents: number;\n totalEpisodes: number;\n tenants: number;\n uptime: number;\n } {\n const totalEpisodes = this.db.prepare('SELECT COUNT(*) as count FROM episodes').get() as any;\n const tenants = this.db.prepare('SELECT COUNT(DISTINCT tenant_id) as count FROM episodes').get() as any;\n\n return {\n connectedAgents: this.connections.size,\n totalEpisodes: totalEpisodes.count,\n tenants: tenants.count,\n uptime: process.uptime()\n };\n }\n\n /**\n * Stop the hub server\n */\n async stop(): Promise<void> {\n logger.info('Stopping federation hub server');\n\n // Close all connections\n for (const [agentId, conn] of this.connections.entries()) {\n conn.ws.close();\n }\n this.connections.clear();\n\n // Close WebSocket server\n if (this.wss) {\n this.wss.close();\n }\n\n // Close HTTP server\n if (this.server) {\n this.server.close();\n }\n\n // Close databases\n this.db.close();\n await this.agentDB.close();\n\n logger.info('Federation hub server stopped');\n }\n\n /**\n * Query patterns from AgentDB with tenant isolation\n */\n async queryPatterns(tenantId: string, task: string, k: number = 5): Promise<any[]> {\n try {\n const results = await this.agentDB.searchPatterns({\n task,\n k,\n minReward: 0.0\n });\n\n // Filter by tenant (session ID contains tenant prefix)\n return results.filter((r: any) =>\n r.sessionId?.startsWith(`${tenantId}/`)\n );\n } catch (error: any) {\n logger.error('Pattern query failed', { error: error.message });\n return [];\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"FederationHubServer.js","sourceRoot":"","sources":["../../src/federation/FederationHubServer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Federation Hub Server - WebSocket-based hub for agent synchronization\n *\n * This is a production-ready implementation using WebSocket (HTTP/2 upgrade)\n * as a fallback until native QUIC is implemented.\n */\n\nimport { WebSocketServer, WebSocket } from 'ws';\nimport { createServer } from 'http';\nimport { logger } from '../utils/logger.js';\nimport { SecurityManager } from './SecurityManager.js';\nimport Database from 'better-sqlite3';\n// AgentDB is optional - federation works with SQLite only\ntype AgentDB = any;\n\nexport interface HubConfig {\n port?: number;\n dbPath?: string;\n maxAgents?: number;\n syncInterval?: number;\n /** Interface to listen on. Loopback unless set: the hub is not safe to expose without TLS in front. */\n host?: string;\n /** HMAC secret agent tokens are verified with (default: JWT_SECRET). */\n jwtSecret?: string;\n}\n\nexport interface AgentConnection {\n ws: WebSocket;\n agentId: string;\n tenantId: string;\n connectedAt: number;\n lastSyncAt: number;\n vectorClock: Record<string, number>;\n}\n\nexport interface SyncMessage {\n type: 'auth' | 'pull' | 'push' | 'ack' | 'error';\n agentId?: string;\n tenantId?: string;\n token?: string;\n vectorClock?: Record<string, number>;\n data?: any[];\n error?: string;\n timestamp: number;\n}\n\nexport class FederationHubServer {\n private config: HubConfig;\n private security: SecurityManager;\n private wss?: WebSocketServer;\n private server?: ReturnType<typeof createServer>;\n private connections: Map<string, AgentConnection> = new Map();\n private db: Database.Database;\n private agentDB: AgentDB;\n private globalVectorClock: Record<string, number> = {};\n\n constructor(config: HubConfig) {\n this.config = {\n port: 8443,\n host: '127.0.0.1',\n dbPath: ':memory:',\n maxAgents: 1000,\n syncInterval: 5000,\n ...config\n };\n\n if (!this.config.jwtSecret && !process.env.JWT_SECRET) {\n logger.warn('No jwtSecret or JWT_SECRET set: the hub uses a random secret, so no agent can authenticate until you set one');\n }\n this.security = new SecurityManager(this.config.jwtSecret);\n\n // Initialize hub database (SQLite for metadata)\n this.db = new Database(this.config.dbPath!);\n this.initializeDatabase();\n\n // AgentDB integration optional - using SQLite for now\n this.agentDB = null as any;\n logger.info('Federation hub initialized with SQLite');\n }\n\n /**\n * Initialize hub database schema\n */\n private initializeDatabase(): void {\n // Memory store: tenant-isolated episodes\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS episodes (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n tenant_id TEXT NOT NULL,\n agent_id TEXT NOT NULL,\n session_id TEXT NOT NULL,\n task TEXT NOT NULL,\n input TEXT NOT NULL,\n output TEXT NOT NULL,\n reward REAL NOT NULL,\n critique TEXT,\n success INTEGER NOT NULL,\n tokens_used INTEGER DEFAULT 0,\n latency_ms INTEGER DEFAULT 0,\n vector_clock TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n UNIQUE(tenant_id, agent_id, session_id, task)\n );\n\n CREATE INDEX IF NOT EXISTS idx_episodes_tenant ON episodes(tenant_id);\n CREATE INDEX IF NOT EXISTS idx_episodes_task ON episodes(tenant_id, task);\n CREATE INDEX IF NOT EXISTS idx_episodes_created ON episodes(created_at);\n\n -- Change log for sync\n CREATE TABLE IF NOT EXISTS change_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n tenant_id TEXT NOT NULL,\n agent_id TEXT NOT NULL,\n operation TEXT NOT NULL,\n episode_id INTEGER,\n vector_clock TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n FOREIGN KEY(episode_id) REFERENCES episodes(id)\n );\n\n CREATE INDEX IF NOT EXISTS idx_changes_tenant ON change_log(tenant_id);\n CREATE INDEX IF NOT EXISTS idx_changes_created ON change_log(created_at);\n\n -- Agent registry\n CREATE TABLE IF NOT EXISTS agents (\n agent_id TEXT PRIMARY KEY,\n tenant_id TEXT NOT NULL,\n connected_at INTEGER NOT NULL,\n last_sync_at INTEGER NOT NULL,\n vector_clock TEXT NOT NULL\n );\n `);\n\n logger.info('Federation hub database initialized');\n }\n\n /**\n * Start the hub server\n */\n async start(): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n // Create HTTP server\n this.server = createServer();\n\n // Create WebSocket server\n this.wss = new WebSocketServer({ server: this.server });\n\n // Handle connections\n this.wss.on('connection', (ws: WebSocket) => {\n this.handleConnection(ws);\n });\n\n // Start listening\n this.server.listen(this.config.port, this.config.host, () => {\n logger.info('Federation hub server started', {\n port: this.config.port,\n protocol: 'WebSocket',\n maxAgents: this.config.maxAgents\n });\n resolve();\n });\n\n // Error handling\n this.server.on('error', (error) => {\n logger.error('Hub server error', { error: error.message });\n reject(error);\n });\n\n } catch (error: any) {\n logger.error('Failed to start hub server', { error: error.message });\n reject(error);\n }\n });\n }\n\n /**\n * Handle new agent connection\n */\n private handleConnection(ws: WebSocket): void {\n let agentId: string | undefined;\n let tenantId: string | undefined;\n let authenticated = false;\n\n logger.info('New connection attempt');\n\n ws.on('message', async (data: Buffer) => {\n try {\n const message: SyncMessage = JSON.parse(data.toString());\n\n // Authentication required first\n if (!authenticated && message.type !== 'auth') {\n this.sendError(ws, 'Authentication required');\n ws.close();\n return;\n }\n\n switch (message.type) {\n case 'auth':\n const authResult = await this.handleAuth(ws, message);\n if (authResult) {\n agentId = authResult.agentId;\n tenantId = authResult.tenantId;\n authenticated = true;\n\n // Register connection\n this.connections.set(agentId, {\n ws,\n agentId,\n tenantId,\n connectedAt: Date.now(),\n lastSyncAt: Date.now(),\n vectorClock: message.vectorClock || {}\n });\n\n logger.info('Agent authenticated', { agentId, tenantId });\n }\n break;\n\n case 'pull':\n if (agentId && tenantId) {\n await this.handlePull(ws, agentId, tenantId, message);\n }\n break;\n\n case 'push':\n if (agentId && tenantId) {\n await this.handlePush(ws, agentId, tenantId, message);\n }\n break;\n\n default:\n this.sendError(ws, `Unknown message type: ${message.type}`);\n }\n\n } catch (error: any) {\n logger.error('Message handling error', { error: error.message });\n this.sendError(ws, error.message);\n }\n });\n\n ws.on('close', () => {\n if (agentId) {\n this.connections.delete(agentId);\n logger.info('Agent disconnected', { agentId, tenantId });\n }\n });\n\n ws.on('error', (error) => {\n logger.error('WebSocket error', { error: error.message, agentId });\n });\n }\n\n /**\n * Handle authentication\n */\n private async handleAuth(\n ws: WebSocket,\n message: SyncMessage\n ): Promise<{ agentId: string; tenantId: string } | null> {\n if (!message.agentId || !message.tenantId || !message.token) {\n this.sendError(ws, 'Missing authentication credentials');\n return null;\n }\n\n // Identity comes from the verified token, never from what the client claims.\n let identity;\n try {\n identity = await this.security.verifyAgentToken(message.token);\n } catch {\n this.sendError(ws, 'Authentication failed');\n return null;\n }\n if (identity.agentId !== message.agentId || identity.tenantId !== message.tenantId) {\n this.sendError(ws, 'Authentication failed');\n return null;\n }\n\n // Register agent\n this.db.prepare(`\n INSERT OR REPLACE INTO agents (agent_id, tenant_id, connected_at, last_sync_at, vector_clock)\n VALUES (?, ?, ?, ?, ?)\n `).run(\n identity.agentId,\n identity.tenantId,\n Date.now(),\n Date.now(),\n JSON.stringify(message.vectorClock || {})\n );\n\n // Send acknowledgment\n this.send(ws, {\n type: 'ack',\n timestamp: Date.now()\n });\n\n return {\n agentId: identity.agentId,\n tenantId: identity.tenantId\n };\n }\n\n /**\n * Handle pull request (agent wants updates from hub)\n */\n private async handlePull(\n ws: WebSocket,\n agentId: string,\n tenantId: string,\n message: SyncMessage\n ): Promise<void> {\n const conn = this.connections.get(agentId);\n if (!conn) {\n this.sendError(ws, 'Agent not connected');\n return;\n }\n\n // Get changes since agent's last vector clock\n const changes = await this.getChangesSince(tenantId, message.vectorClock || {});\n\n // Update last sync time\n conn.lastSyncAt = Date.now();\n\n // Send changes to agent\n this.send(ws, {\n type: 'ack',\n data: changes,\n vectorClock: this.globalVectorClock,\n timestamp: Date.now()\n });\n\n logger.info('Pull completed', {\n agentId,\n tenantId,\n changeCount: changes.length\n });\n }\n\n /**\n * Handle push request (agent sending updates to hub)\n */\n private async handlePush(\n ws: WebSocket,\n agentId: string,\n tenantId: string,\n message: SyncMessage\n ): Promise<void> {\n const conn = this.connections.get(agentId);\n if (!conn) {\n this.sendError(ws, 'Agent not connected');\n return;\n }\n\n if (!message.data || message.data.length === 0) {\n this.send(ws, { type: 'ack', timestamp: Date.now() });\n return;\n }\n\n // Store episodes in both SQLite (metadata) and AgentDB (vector memory)\n const stmt = this.db.prepare(`\n INSERT OR REPLACE INTO episodes\n (tenant_id, agent_id, session_id, task, input, output, reward, critique, success, tokens_used, latency_ms, vector_clock, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n const changeStmt = this.db.prepare(`\n INSERT INTO change_log (tenant_id, agent_id, operation, episode_id, vector_clock, created_at)\n VALUES (?, ?, 'insert', last_insert_rowid(), ?, ?)\n `);\n\n let insertCount = 0;\n\n for (const episode of message.data) {\n try {\n // Store in SQLite for metadata\n stmt.run(\n tenantId,\n agentId,\n episode.sessionId || agentId,\n episode.task,\n episode.input,\n episode.output,\n episode.reward,\n episode.critique || '',\n episode.success ? 1 : 0,\n episode.tokensUsed || 0,\n episode.latencyMs || 0,\n JSON.stringify(message.vectorClock),\n Date.now()\n );\n\n changeStmt.run(\n tenantId,\n agentId,\n JSON.stringify(message.vectorClock),\n Date.now()\n );\n\n // Store in AgentDB for vector memory (with tenant isolation)\n await this.agentDB.storePattern({\n sessionId: `${tenantId}/${episode.sessionId || agentId}`,\n task: episode.task,\n input: episode.input,\n output: episode.output,\n reward: episode.reward,\n critique: episode.critique || '',\n success: episode.success,\n tokensUsed: episode.tokensUsed || 0,\n latencyMs: episode.latencyMs || 0,\n metadata: {\n tenantId,\n agentId,\n vectorClock: message.vectorClock\n }\n });\n\n insertCount++;\n } catch (error: any) {\n logger.error('Failed to insert episode', { error: error.message });\n }\n }\n\n // Update global vector clock\n if (message.vectorClock) {\n for (const [agent, ts] of Object.entries(message.vectorClock)) {\n this.globalVectorClock[agent] = Math.max(\n this.globalVectorClock[agent] || 0,\n ts\n );\n }\n }\n\n // Update connection vector clock\n conn.vectorClock = { ...this.globalVectorClock };\n conn.lastSyncAt = Date.now();\n\n // Send acknowledgment\n this.send(ws, {\n type: 'ack',\n timestamp: Date.now()\n });\n\n logger.info('Push completed', {\n agentId,\n tenantId,\n episodeCount: insertCount\n });\n\n // Broadcast to other agents in same tenant (optional real-time sync)\n this.broadcastToTenant(tenantId, agentId, {\n type: 'push',\n agentId,\n data: message.data,\n timestamp: Date.now()\n });\n }\n\n /**\n * Get changes since a given vector clock\n * Returns memories from other agents in the same tenant\n */\n private async getChangesSince(\n tenantId: string,\n vectorClock: Record<string, number>\n ): Promise<any[]> {\n // Get all episodes for tenant from SQLite\n const episodes = this.db.prepare(`\n SELECT * FROM episodes\n WHERE tenant_id = ?\n ORDER BY created_at DESC\n LIMIT 100\n `).all(tenantId);\n\n return episodes.map((row: any) => ({\n id: row.id,\n agentId: row.agent_id,\n sessionId: row.session_id,\n task: row.task,\n input: row.input,\n output: row.output,\n reward: row.reward,\n critique: row.critique,\n success: row.success === 1,\n tokensUsed: row.tokens_used,\n latencyMs: row.latency_ms,\n vectorClock: JSON.parse(row.vector_clock),\n createdAt: row.created_at\n }));\n }\n\n /**\n * Broadcast message to all agents in a tenant (except sender)\n */\n private broadcastToTenant(\n tenantId: string,\n senderAgentId: string,\n message: SyncMessage\n ): void {\n let broadcastCount = 0;\n\n for (const [agentId, conn] of this.connections.entries()) {\n if (conn.tenantId === tenantId && agentId !== senderAgentId) {\n this.send(conn.ws, message);\n broadcastCount++;\n }\n }\n\n if (broadcastCount > 0) {\n logger.debug('Broadcasted to tenant agents', {\n tenantId,\n recipientCount: broadcastCount\n });\n }\n }\n\n /**\n * Send message to WebSocket\n */\n private send(ws: WebSocket, message: SyncMessage): void {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(message));\n }\n }\n\n /**\n * Send error message\n */\n private sendError(ws: WebSocket, error: string): void {\n this.send(ws, {\n type: 'error',\n error,\n timestamp: Date.now()\n });\n }\n\n /**\n * Get hub statistics\n */\n getStats(): {\n connectedAgents: number;\n totalEpisodes: number;\n tenants: number;\n uptime: number;\n } {\n const totalEpisodes = this.db.prepare('SELECT COUNT(*) as count FROM episodes').get() as any;\n const tenants = this.db.prepare('SELECT COUNT(DISTINCT tenant_id) as count FROM episodes').get() as any;\n\n return {\n connectedAgents: this.connections.size,\n totalEpisodes: totalEpisodes.count,\n tenants: tenants.count,\n uptime: process.uptime()\n };\n }\n\n /**\n * Stop the hub server\n */\n async stop(): Promise<void> {\n logger.info('Stopping federation hub server');\n\n // Close all connections\n for (const [agentId, conn] of this.connections.entries()) {\n conn.ws.close();\n }\n this.connections.clear();\n\n // Close WebSocket server\n if (this.wss) {\n this.wss.close();\n }\n\n // Close HTTP server\n if (this.server) {\n this.server.close();\n }\n\n // Close databases\n this.db.close();\n await this.agentDB?.close();\n\n logger.info('Federation hub server stopped');\n }\n\n /**\n * Query patterns from AgentDB with tenant isolation\n */\n async queryPatterns(tenantId: string, task: string, k: number = 5): Promise<any[]> {\n try {\n const results = await this.agentDB.searchPatterns({\n task,\n k,\n minReward: 0.0\n });\n\n // Filter by tenant (session ID contains tenant prefix)\n return results.filter((r: any) =>\n r.sessionId?.startsWith(`${tenantId}/`)\n );\n } catch (error: any) {\n logger.error('Pattern query failed', { error: error.message });\n return [];\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SecurityManager.d.ts","sourceRoot":"","sources":["../../src/federation/SecurityManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,eAAe,CAA0C;;
|
|
1
|
+
{"version":3,"file":"SecurityManager.d.ts","sourceRoot":"","sources":["../../src/federation/SecurityManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,eAAe,CAA0C;gBAErD,MAAM,CAAC,EAAE,MAAM;IAK3B;;OAEG;IACG,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAmCnE;;OAEG;IACG,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAwCjE;;;OAGG;IACG,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAqBzD;;;OAGG;IACG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAOlE;;;OAGG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAwB1G;;;OAGG;IACG,OAAO,CACX,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,EAAE,CAAC,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC;IAgClB;;OAEG;IACG,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QACvD,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,EAAE,MAAM,CAAC;QACZ,EAAE,EAAE,MAAM,CAAC;KACZ,CAAC;IAaF;;OAEG;IACH,oBAAoB,CAAC,eAAe,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO;IAW5E;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAI9B;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAI1B;;OAEG;IACH,OAAO,CAAC,eAAe;IAQvB;;OAEG;IACH,OAAO,CAAC,eAAe;IAKvB;;OAEG;IACH,UAAU,IAAI,IAAI;CAInB"}
|
|
@@ -13,9 +13,9 @@ export class SecurityManager {
|
|
|
13
13
|
algorithm = 'aes-256-gcm';
|
|
14
14
|
jwtSecret;
|
|
15
15
|
encryptionCache = new Map();
|
|
16
|
-
constructor() {
|
|
16
|
+
constructor(secret) {
|
|
17
17
|
// In production, load from secure vault (AWS Secrets Manager, HashiCorp Vault, etc.)
|
|
18
|
-
this.jwtSecret = process.env.JWT_SECRET || crypto.randomBytes(32).toString('hex');
|
|
18
|
+
this.jwtSecret = secret || process.env.JWT_SECRET || crypto.randomBytes(32).toString('hex');
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
21
|
* Create JWT token for agent authentication
|
|
@@ -62,13 +62,18 @@ export class SecurityManager {
|
|
|
62
62
|
.createHmac('sha256', this.jwtSecret)
|
|
63
63
|
.update(`${encodedHeader}.${encodedPayload}`)
|
|
64
64
|
.digest('base64url');
|
|
65
|
-
|
|
65
|
+
const given = Buffer.from(signature);
|
|
66
|
+
const wanted = Buffer.from(expectedSignature);
|
|
67
|
+
if (given.length !== wanted.length || !crypto.timingSafeEqual(given, wanted)) {
|
|
66
68
|
throw new Error('Invalid token signature');
|
|
67
69
|
}
|
|
68
70
|
// Decode payload
|
|
69
71
|
const payload = JSON.parse(this.base64UrlDecode(encodedPayload));
|
|
72
|
+
if (typeof payload?.agentId !== 'string' || typeof payload?.tenantId !== 'string' || !payload.agentId || !payload.tenantId) {
|
|
73
|
+
throw new Error('Invalid token payload');
|
|
74
|
+
}
|
|
70
75
|
// Check expiration
|
|
71
|
-
if (Date.now() >= payload.exp) {
|
|
76
|
+
if (typeof payload.exp !== 'number' || Date.now() >= payload.exp) {
|
|
72
77
|
throw new Error('Token expired');
|
|
73
78
|
}
|
|
74
79
|
logger.debug('Token verified', {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SecurityManager.js","sourceRoot":"","sources":["../../src/federation/SecurityManager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Security Manager - Authentication, encryption, and access control\n *\n * Features:\n * - JWT token generation and validation\n * - AES-256 encryption for data at rest\n * - Tenant isolation\n * - mTLS certificate management\n */\n\nimport crypto from 'crypto';\nimport { logger } from '../utils/logger.js';\n\nexport interface AgentTokenPayload {\n agentId: string;\n tenantId: string;\n expiresAt: number;\n}\n\nexport interface EncryptionKeys {\n encryptionKey: Buffer;\n iv: Buffer;\n}\n\nexport class SecurityManager {\n private readonly algorithm = 'aes-256-gcm';\n private readonly jwtSecret: string;\n private encryptionCache: Map<string, EncryptionKeys> = new Map();\n\n constructor() {\n // In production, load from secure vault (AWS Secrets Manager, HashiCorp Vault, etc.)\n this.jwtSecret = process.env.JWT_SECRET || crypto.randomBytes(32).toString('hex');\n }\n\n /**\n * Create JWT token for agent authentication\n */\n async createAgentToken(payload: AgentTokenPayload): Promise<string> {\n const header = {\n alg: 'HS256',\n typ: 'JWT'\n };\n\n const now = Date.now();\n const tokenPayload = {\n ...payload,\n iat: now,\n exp: payload.expiresAt,\n iss: 'agentic-flow-federation'\n };\n\n // Encode header and payload\n const encodedHeader = this.base64UrlEncode(JSON.stringify(header));\n const encodedPayload = this.base64UrlEncode(JSON.stringify(tokenPayload));\n\n // Create signature\n const signature = crypto\n .createHmac('sha256', this.jwtSecret)\n .update(`${encodedHeader}.${encodedPayload}`)\n .digest('base64url');\n\n const token = `${encodedHeader}.${encodedPayload}.${signature}`;\n\n logger.info('Created agent token', {\n agentId: payload.agentId,\n tenantId: payload.tenantId,\n expiresAt: new Date(payload.expiresAt).toISOString()\n });\n\n return token;\n }\n\n /**\n * Verify JWT token\n */\n async verifyAgentToken(token: string): Promise<AgentTokenPayload> {\n const parts = token.split('.');\n if (parts.length !== 3) {\n throw new Error('Invalid token format');\n }\n\n const [encodedHeader, encodedPayload, signature] = parts;\n\n // Verify signature\n const expectedSignature = crypto\n .createHmac('sha256', this.jwtSecret)\n .update(`${encodedHeader}.${encodedPayload}`)\n .digest('base64url');\n\n if (signature !== expectedSignature) {\n throw new Error('Invalid token signature');\n }\n\n // Decode payload\n const payload = JSON.parse(this.base64UrlDecode(encodedPayload));\n\n // Check expiration\n if (Date.now() >= payload.exp) {\n throw new Error('Token expired');\n }\n\n logger.debug('Token verified', {\n agentId: payload.agentId,\n tenantId: payload.tenantId\n });\n\n return payload;\n }\n\n /**\n * Get or create encryption key for a tenant (key only, IV generated per operation)\n * SECURITY FIX: IV is now generated fresh for each encryption operation\n */\n async getEncryptionKey(tenantId: string): Promise<Buffer> {\n // Check cache for encryption key only\n const cached = this.encryptionCache.get(tenantId);\n if (cached) {\n return cached.encryptionKey;\n }\n\n // Generate new key for tenant\n // In production, these would be stored in a secure key management service\n const encryptionKey = crypto.randomBytes(32); // 256-bit key\n\n // Cache only the key (IV will be generated per-operation)\n // We store a dummy IV in the cache structure for backwards compatibility\n const keys: EncryptionKeys = { encryptionKey, iv: Buffer.alloc(16) };\n this.encryptionCache.set(tenantId, keys);\n\n logger.info('Generated encryption key for tenant', { tenantId });\n\n return encryptionKey;\n }\n\n /**\n * Legacy method for backwards compatibility - prefer getEncryptionKey\n * @deprecated Use getEncryptionKey instead and generate IV per-operation\n */\n async getEncryptionKeys(tenantId: string): Promise<EncryptionKeys> {\n const encryptionKey = await this.getEncryptionKey(tenantId);\n // SECURITY: Generate fresh IV for each call (not cached)\n const iv = crypto.randomBytes(16);\n return { encryptionKey, iv };\n }\n\n /**\n * Encrypt data with AES-256-GCM\n * SECURITY FIX: Now generates a fresh IV for each encryption and returns it\n */\n async encrypt(data: string, tenantId: string): Promise<{ encrypted: string; authTag: string; iv: string }> {\n const encryptionKey = await this.getEncryptionKey(tenantId);\n\n // SECURITY: Generate fresh IV for EACH encryption operation\n // IV reuse with AES-GCM is catastrophic - this fix prevents that\n const iv = crypto.randomBytes(16);\n\n const cipher = crypto.createCipheriv(this.algorithm, encryptionKey, iv);\n\n let encrypted = cipher.update(data, 'utf8', 'base64');\n encrypted += cipher.final('base64');\n\n const authTag = cipher.getAuthTag().toString('base64');\n\n logger.debug('Data encrypted', {\n tenantId,\n originalLength: data.length,\n encryptedLength: encrypted.length\n });\n\n // SECURITY: Return IV with encrypted data so it can be used for decryption\n return { encrypted, authTag, iv: iv.toString('base64') };\n }\n\n /**\n * Decrypt data with AES-256-GCM\n * SECURITY FIX: Now accepts IV as parameter (required for proper decryption)\n */\n async decrypt(\n encrypted: string,\n authTag: string,\n tenantId: string,\n iv?: string\n ): Promise<string> {\n const encryptionKey = await this.getEncryptionKey(tenantId);\n\n // SECURITY: IV must be provided for proper decryption\n // For backwards compatibility, generate warning if not provided\n let ivBuffer: Buffer;\n if (iv) {\n ivBuffer = Buffer.from(iv, 'base64');\n } else {\n // Legacy fallback - try to use cached IV (will fail for new encryptions)\n logger.warn('Decrypt called without IV - this may fail for newly encrypted data', { tenantId });\n const cached = this.encryptionCache.get(tenantId);\n if (!cached) {\n throw new Error('No IV provided and no cached keys available');\n }\n ivBuffer = cached.iv;\n }\n\n const decipher = crypto.createDecipheriv(this.algorithm, encryptionKey, ivBuffer);\n decipher.setAuthTag(Buffer.from(authTag, 'base64'));\n\n let decrypted = decipher.update(encrypted, 'base64', 'utf8');\n decrypted += decipher.final('utf8');\n\n logger.debug('Data decrypted', {\n tenantId,\n decryptedLength: decrypted.length\n });\n\n return decrypted;\n }\n\n /**\n * Generate mTLS certificates for agent-to-hub communication\n */\n async generateMTLSCertificates(agentId: string): Promise<{\n cert: string;\n key: string;\n ca: string;\n }> {\n // Placeholder: Actual implementation would use OpenSSL or similar\n // to generate X.509 certificates with proper CA chain\n\n logger.info('Generating mTLS certificates', { agentId });\n\n return {\n cert: 'PLACEHOLDER_CERT',\n key: 'PLACEHOLDER_KEY',\n ca: 'PLACEHOLDER_CA'\n };\n }\n\n /**\n * Validate tenant access to data\n */\n validateTenantAccess(requestTenantId: string, dataTenantId: string): boolean {\n if (requestTenantId !== dataTenantId) {\n logger.warn('Tenant access violation detected', {\n requestTenantId,\n dataTenantId\n });\n return false;\n }\n return true;\n }\n\n /**\n * Hash sensitive data for storage (one-way)\n */\n hashData(data: string): string {\n return crypto.createHash('sha256').update(data).digest('hex');\n }\n\n /**\n * Generate secure random ID\n */\n generateSecureId(): string {\n return crypto.randomBytes(16).toString('hex');\n }\n\n /**\n * Base64 URL-safe encoding\n */\n private base64UrlEncode(str: string): string {\n return Buffer.from(str)\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=/g, '');\n }\n\n /**\n * Base64 URL-safe decoding\n */\n private base64UrlDecode(str: string): string {\n const base64 = str.replace(/-/g, '+').replace(/_/g, '/');\n return Buffer.from(base64, 'base64').toString('utf8');\n }\n\n /**\n * Clear cached keys (for testing or security refresh)\n */\n clearCache(): void {\n this.encryptionCache.clear();\n logger.info('Encryption cache cleared');\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SecurityManager.js","sourceRoot":"","sources":["../../src/federation/SecurityManager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Security Manager - Authentication, encryption, and access control\n *\n * Features:\n * - JWT token generation and validation\n * - AES-256 encryption for data at rest\n * - Tenant isolation\n * - mTLS certificate management\n */\n\nimport crypto from 'crypto';\nimport { logger } from '../utils/logger.js';\n\nexport interface AgentTokenPayload {\n agentId: string;\n tenantId: string;\n expiresAt: number;\n}\n\nexport interface EncryptionKeys {\n encryptionKey: Buffer;\n iv: Buffer;\n}\n\nexport class SecurityManager {\n private readonly algorithm = 'aes-256-gcm';\n private readonly jwtSecret: string;\n private encryptionCache: Map<string, EncryptionKeys> = new Map();\n\n constructor(secret?: string) {\n // In production, load from secure vault (AWS Secrets Manager, HashiCorp Vault, etc.)\n this.jwtSecret = secret || process.env.JWT_SECRET || crypto.randomBytes(32).toString('hex');\n }\n\n /**\n * Create JWT token for agent authentication\n */\n async createAgentToken(payload: AgentTokenPayload): Promise<string> {\n const header = {\n alg: 'HS256',\n typ: 'JWT'\n };\n\n const now = Date.now();\n const tokenPayload = {\n ...payload,\n iat: now,\n exp: payload.expiresAt,\n iss: 'agentic-flow-federation'\n };\n\n // Encode header and payload\n const encodedHeader = this.base64UrlEncode(JSON.stringify(header));\n const encodedPayload = this.base64UrlEncode(JSON.stringify(tokenPayload));\n\n // Create signature\n const signature = crypto\n .createHmac('sha256', this.jwtSecret)\n .update(`${encodedHeader}.${encodedPayload}`)\n .digest('base64url');\n\n const token = `${encodedHeader}.${encodedPayload}.${signature}`;\n\n logger.info('Created agent token', {\n agentId: payload.agentId,\n tenantId: payload.tenantId,\n expiresAt: new Date(payload.expiresAt).toISOString()\n });\n\n return token;\n }\n\n /**\n * Verify JWT token\n */\n async verifyAgentToken(token: string): Promise<AgentTokenPayload> {\n const parts = token.split('.');\n if (parts.length !== 3) {\n throw new Error('Invalid token format');\n }\n\n const [encodedHeader, encodedPayload, signature] = parts;\n\n // Verify signature\n const expectedSignature = crypto\n .createHmac('sha256', this.jwtSecret)\n .update(`${encodedHeader}.${encodedPayload}`)\n .digest('base64url');\n\n const given = Buffer.from(signature);\n const wanted = Buffer.from(expectedSignature);\n if (given.length !== wanted.length || !crypto.timingSafeEqual(given, wanted)) {\n throw new Error('Invalid token signature');\n }\n\n // Decode payload\n const payload = JSON.parse(this.base64UrlDecode(encodedPayload));\n\n if (typeof payload?.agentId !== 'string' || typeof payload?.tenantId !== 'string' || !payload.agentId || !payload.tenantId) {\n throw new Error('Invalid token payload');\n }\n\n // Check expiration\n if (typeof payload.exp !== 'number' || Date.now() >= payload.exp) {\n throw new Error('Token expired');\n }\n\n logger.debug('Token verified', {\n agentId: payload.agentId,\n tenantId: payload.tenantId\n });\n\n return payload;\n }\n\n /**\n * Get or create encryption key for a tenant (key only, IV generated per operation)\n * SECURITY FIX: IV is now generated fresh for each encryption operation\n */\n async getEncryptionKey(tenantId: string): Promise<Buffer> {\n // Check cache for encryption key only\n const cached = this.encryptionCache.get(tenantId);\n if (cached) {\n return cached.encryptionKey;\n }\n\n // Generate new key for tenant\n // In production, these would be stored in a secure key management service\n const encryptionKey = crypto.randomBytes(32); // 256-bit key\n\n // Cache only the key (IV will be generated per-operation)\n // We store a dummy IV in the cache structure for backwards compatibility\n const keys: EncryptionKeys = { encryptionKey, iv: Buffer.alloc(16) };\n this.encryptionCache.set(tenantId, keys);\n\n logger.info('Generated encryption key for tenant', { tenantId });\n\n return encryptionKey;\n }\n\n /**\n * Legacy method for backwards compatibility - prefer getEncryptionKey\n * @deprecated Use getEncryptionKey instead and generate IV per-operation\n */\n async getEncryptionKeys(tenantId: string): Promise<EncryptionKeys> {\n const encryptionKey = await this.getEncryptionKey(tenantId);\n // SECURITY: Generate fresh IV for each call (not cached)\n const iv = crypto.randomBytes(16);\n return { encryptionKey, iv };\n }\n\n /**\n * Encrypt data with AES-256-GCM\n * SECURITY FIX: Now generates a fresh IV for each encryption and returns it\n */\n async encrypt(data: string, tenantId: string): Promise<{ encrypted: string; authTag: string; iv: string }> {\n const encryptionKey = await this.getEncryptionKey(tenantId);\n\n // SECURITY: Generate fresh IV for EACH encryption operation\n // IV reuse with AES-GCM is catastrophic - this fix prevents that\n const iv = crypto.randomBytes(16);\n\n const cipher = crypto.createCipheriv(this.algorithm, encryptionKey, iv);\n\n let encrypted = cipher.update(data, 'utf8', 'base64');\n encrypted += cipher.final('base64');\n\n const authTag = cipher.getAuthTag().toString('base64');\n\n logger.debug('Data encrypted', {\n tenantId,\n originalLength: data.length,\n encryptedLength: encrypted.length\n });\n\n // SECURITY: Return IV with encrypted data so it can be used for decryption\n return { encrypted, authTag, iv: iv.toString('base64') };\n }\n\n /**\n * Decrypt data with AES-256-GCM\n * SECURITY FIX: Now accepts IV as parameter (required for proper decryption)\n */\n async decrypt(\n encrypted: string,\n authTag: string,\n tenantId: string,\n iv?: string\n ): Promise<string> {\n const encryptionKey = await this.getEncryptionKey(tenantId);\n\n // SECURITY: IV must be provided for proper decryption\n // For backwards compatibility, generate warning if not provided\n let ivBuffer: Buffer;\n if (iv) {\n ivBuffer = Buffer.from(iv, 'base64');\n } else {\n // Legacy fallback - try to use cached IV (will fail for new encryptions)\n logger.warn('Decrypt called without IV - this may fail for newly encrypted data', { tenantId });\n const cached = this.encryptionCache.get(tenantId);\n if (!cached) {\n throw new Error('No IV provided and no cached keys available');\n }\n ivBuffer = cached.iv;\n }\n\n const decipher = crypto.createDecipheriv(this.algorithm, encryptionKey, ivBuffer);\n decipher.setAuthTag(Buffer.from(authTag, 'base64'));\n\n let decrypted = decipher.update(encrypted, 'base64', 'utf8');\n decrypted += decipher.final('utf8');\n\n logger.debug('Data decrypted', {\n tenantId,\n decryptedLength: decrypted.length\n });\n\n return decrypted;\n }\n\n /**\n * Generate mTLS certificates for agent-to-hub communication\n */\n async generateMTLSCertificates(agentId: string): Promise<{\n cert: string;\n key: string;\n ca: string;\n }> {\n // Placeholder: Actual implementation would use OpenSSL or similar\n // to generate X.509 certificates with proper CA chain\n\n logger.info('Generating mTLS certificates', { agentId });\n\n return {\n cert: 'PLACEHOLDER_CERT',\n key: 'PLACEHOLDER_KEY',\n ca: 'PLACEHOLDER_CA'\n };\n }\n\n /**\n * Validate tenant access to data\n */\n validateTenantAccess(requestTenantId: string, dataTenantId: string): boolean {\n if (requestTenantId !== dataTenantId) {\n logger.warn('Tenant access violation detected', {\n requestTenantId,\n dataTenantId\n });\n return false;\n }\n return true;\n }\n\n /**\n * Hash sensitive data for storage (one-way)\n */\n hashData(data: string): string {\n return crypto.createHash('sha256').update(data).digest('hex');\n }\n\n /**\n * Generate secure random ID\n */\n generateSecureId(): string {\n return crypto.randomBytes(16).toString('hex');\n }\n\n /**\n * Base64 URL-safe encoding\n */\n private base64UrlEncode(str: string): string {\n return Buffer.from(str)\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=/g, '');\n }\n\n /**\n * Base64 URL-safe decoding\n */\n private base64UrlDecode(str: string): string {\n const base64 = str.replace(/-/g, '+').replace(/_/g, '/');\n return Buffer.from(base64, 'base64').toString('utf8');\n }\n\n /**\n * Clear cached keys (for testing or security refresh)\n */\n clearCache(): void {\n this.encryptionCache.clear();\n logger.info('Encryption cache cleared');\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-flow",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.5",
|
|
4
4
|
"description": "The agentic meta-harness — freeze the model, evolve the harness. An open runtime that routes each query to the cost-optimal model, evolves its own harness (planner/context/reviewer/retry/tool/memory/score policy) and autonomously repairs code, then orchestrates 66 specialized agents, 213 MCP tools, ReasoningBank memory, and multi-agent swarms on top. Built by @ruvnet on the Claude Agent SDK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -104,32 +104,32 @@ export function log(message) {
|
|
|
104
104
|
const len0 = WASM_VECTOR_LEN;
|
|
105
105
|
wasm.log(ptr0, len0);
|
|
106
106
|
}
|
|
107
|
-
export function
|
|
107
|
+
export function __wbg___wbindgen_debug_string_07cb72cfcc952e2b(arg0, arg1) {
|
|
108
108
|
const ret = debugString(getObject(arg1));
|
|
109
109
|
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
110
110
|
const len1 = WASM_VECTOR_LEN;
|
|
111
111
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
112
112
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
113
113
|
}
|
|
114
|
-
export function
|
|
114
|
+
export function __wbg___wbindgen_is_function_2f0fd7ceb86e64c5(arg0) {
|
|
115
115
|
const ret = typeof(getObject(arg0)) === 'function';
|
|
116
116
|
return ret;
|
|
117
117
|
}
|
|
118
|
-
export function
|
|
118
|
+
export function __wbg___wbindgen_is_undefined_244a92c34d3b6ec0(arg0) {
|
|
119
119
|
const ret = getObject(arg0) === undefined;
|
|
120
120
|
return ret;
|
|
121
121
|
}
|
|
122
|
-
export function
|
|
122
|
+
export function __wbg___wbindgen_throw_9c75d47bf9e7731e(arg0, arg1) {
|
|
123
123
|
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
124
124
|
}
|
|
125
|
-
export function
|
|
125
|
+
export function __wbg__wbg_cb_unref_158e43e869788cdc(arg0) {
|
|
126
126
|
getObject(arg0)._wbg_cb_unref();
|
|
127
127
|
}
|
|
128
|
-
export function
|
|
128
|
+
export function __wbg_call_a41d6421b30a32c5() { return handleError(function (arg0, arg1, arg2) {
|
|
129
129
|
const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
|
|
130
130
|
return addHeapObject(ret);
|
|
131
131
|
}, arguments); }
|
|
132
|
-
export function
|
|
132
|
+
export function __wbg_error_a6fa202b58aa1cd3(arg0, arg1) {
|
|
133
133
|
let deferred0_0;
|
|
134
134
|
let deferred0_1;
|
|
135
135
|
try {
|
|
@@ -140,18 +140,18 @@ export function __wbg_error_757e9472f8410341(arg0, arg1) {
|
|
|
140
140
|
wasm.__wbindgen_export4(deferred0_0, deferred0_1, 1);
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
|
-
export function
|
|
143
|
+
export function __wbg_getRandomValues_ef12552bf5acd2fe() { return handleError(function (arg0, arg1) {
|
|
144
144
|
globalThis.crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1));
|
|
145
145
|
}, arguments); }
|
|
146
|
-
export function
|
|
146
|
+
export function __wbg_get_41476db20fef99a8() { return handleError(function (arg0, arg1) {
|
|
147
147
|
const ret = Reflect.get(getObject(arg0), getObject(arg1));
|
|
148
148
|
return addHeapObject(ret);
|
|
149
149
|
}, arguments); }
|
|
150
|
-
export function
|
|
150
|
+
export function __wbg_indexedDB_06cbacc078ae71b2() { return handleError(function (arg0) {
|
|
151
151
|
const ret = getObject(arg0).indexedDB;
|
|
152
152
|
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
153
153
|
}, arguments); }
|
|
154
|
-
export function
|
|
154
|
+
export function __wbg_instanceof_Window_4153c1818a1c0c0b(arg0) {
|
|
155
155
|
let result;
|
|
156
156
|
try {
|
|
157
157
|
result = getObject(arg0) instanceof Window;
|
|
@@ -161,21 +161,21 @@ export function __wbg_instanceof_Window_a3b8566f0a9c5d1a(arg0) {
|
|
|
161
161
|
const ret = result;
|
|
162
162
|
return ret;
|
|
163
163
|
}
|
|
164
|
-
export function
|
|
164
|
+
export function __wbg_log_72d22df918dcc232(arg0) {
|
|
165
165
|
console.log(getObject(arg0));
|
|
166
166
|
}
|
|
167
167
|
export function __wbg_new_227d7c05414eb861() {
|
|
168
168
|
const ret = new Error();
|
|
169
169
|
return addHeapObject(ret);
|
|
170
170
|
}
|
|
171
|
-
export function
|
|
171
|
+
export function __wbg_new_typed_1137602701dc87d4(arg0, arg1) {
|
|
172
172
|
try {
|
|
173
173
|
var state0 = {a: arg0, b: arg1};
|
|
174
174
|
var cb0 = (arg0, arg1) => {
|
|
175
175
|
const a = state0.a;
|
|
176
176
|
state0.a = 0;
|
|
177
177
|
try {
|
|
178
|
-
return
|
|
178
|
+
return __wasm_bindgen_func_elem_352(a, state0.b, arg0, arg1);
|
|
179
179
|
} finally {
|
|
180
180
|
state0.a = a;
|
|
181
181
|
}
|
|
@@ -186,22 +186,22 @@ export function __wbg_new_typed_6f8b0d724fe26c07(arg0, arg1) {
|
|
|
186
186
|
state0.a = 0;
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
|
-
export function
|
|
189
|
+
export function __wbg_open_5a9e43bc5e42b3c5() { return handleError(function (arg0, arg1, arg2, arg3) {
|
|
190
190
|
const ret = getObject(arg0).open(getStringFromWasm0(arg1, arg2), arg3 >>> 0);
|
|
191
191
|
return addHeapObject(ret);
|
|
192
192
|
}, arguments); }
|
|
193
|
-
export function
|
|
193
|
+
export function __wbg_queueMicrotask_40ac6ffc2848ba77(arg0) {
|
|
194
|
+
queueMicrotask(getObject(arg0));
|
|
195
|
+
}
|
|
196
|
+
export function __wbg_queueMicrotask_74d092439f6494c1(arg0) {
|
|
194
197
|
const ret = getObject(arg0).queueMicrotask;
|
|
195
198
|
return addHeapObject(ret);
|
|
196
199
|
}
|
|
197
|
-
export function __wbg_queueMicrotask_f6a1fa10b81d1fc0(arg0) {
|
|
198
|
-
queueMicrotask(getObject(arg0));
|
|
199
|
-
}
|
|
200
200
|
export function __wbg_reasoningbankwasm_new(arg0) {
|
|
201
201
|
const ret = ReasoningBankWasm.__wrap(arg0);
|
|
202
202
|
return addHeapObject(ret);
|
|
203
203
|
}
|
|
204
|
-
export function
|
|
204
|
+
export function __wbg_resolve_9feb5d906ca62419(arg0) {
|
|
205
205
|
const ret = Promise.resolve(getObject(arg0));
|
|
206
206
|
return addHeapObject(ret);
|
|
207
207
|
}
|
|
@@ -212,32 +212,32 @@ export function __wbg_stack_3b0d974bbf31e44f(arg0, arg1) {
|
|
|
212
212
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
213
213
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
214
214
|
}
|
|
215
|
-
export function
|
|
216
|
-
const ret = typeof
|
|
215
|
+
export function __wbg_static_accessor_GLOBAL_THIS_1c7f1bd6c6941fdb() {
|
|
216
|
+
const ret = typeof globalThis === 'undefined' ? null : globalThis;
|
|
217
217
|
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
218
218
|
}
|
|
219
|
-
export function
|
|
220
|
-
const ret = typeof
|
|
219
|
+
export function __wbg_static_accessor_GLOBAL_e039bc914f83e74e() {
|
|
220
|
+
const ret = typeof global === 'undefined' ? null : global;
|
|
221
221
|
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
222
222
|
}
|
|
223
|
-
export function
|
|
223
|
+
export function __wbg_static_accessor_SELF_8bf8c48c28420ad5() {
|
|
224
224
|
const ret = typeof self === 'undefined' ? null : self;
|
|
225
225
|
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
226
226
|
}
|
|
227
|
-
export function
|
|
227
|
+
export function __wbg_static_accessor_WINDOW_6aeee9b51652ee0f() {
|
|
228
228
|
const ret = typeof window === 'undefined' ? null : window;
|
|
229
229
|
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
230
230
|
}
|
|
231
|
-
export function
|
|
231
|
+
export function __wbg_then_20a157d939b514f5(arg0, arg1) {
|
|
232
232
|
const ret = getObject(arg0).then(getObject(arg1));
|
|
233
233
|
return addHeapObject(ret);
|
|
234
234
|
}
|
|
235
|
-
export function
|
|
235
|
+
export function __wbindgen_cast_0000000000000001(arg0, arg1) {
|
|
236
236
|
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 95, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
|
237
|
-
const ret = makeMutClosure(arg0, arg1,
|
|
237
|
+
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_346);
|
|
238
238
|
return addHeapObject(ret);
|
|
239
239
|
}
|
|
240
|
-
export function
|
|
240
|
+
export function __wbindgen_cast_0000000000000002(arg0, arg1) {
|
|
241
241
|
// Cast intrinsic for `Ref(String) -> Externref`.
|
|
242
242
|
const ret = getStringFromWasm0(arg0, arg1);
|
|
243
243
|
return addHeapObject(ret);
|
|
@@ -249,14 +249,10 @@ export function __wbindgen_object_clone_ref(arg0) {
|
|
|
249
249
|
export function __wbindgen_object_drop_ref(arg0) {
|
|
250
250
|
takeObject(arg0);
|
|
251
251
|
}
|
|
252
|
-
function
|
|
253
|
-
wasm.__wasm_bindgen_func_elem_355(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
function __wasm_bindgen_func_elem_342(arg0, arg1, arg2) {
|
|
252
|
+
function __wasm_bindgen_func_elem_346(arg0, arg1, arg2) {
|
|
257
253
|
try {
|
|
258
254
|
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
259
|
-
wasm.
|
|
255
|
+
wasm.__wasm_bindgen_func_elem_346(retptr, arg0, arg1, addHeapObject(arg2));
|
|
260
256
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
261
257
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
262
258
|
if (r1) {
|
|
@@ -267,6 +263,10 @@ function __wasm_bindgen_func_elem_342(arg0, arg1, arg2) {
|
|
|
267
263
|
}
|
|
268
264
|
}
|
|
269
265
|
|
|
266
|
+
function __wasm_bindgen_func_elem_352(arg0, arg1, arg2, arg3) {
|
|
267
|
+
wasm.__wasm_bindgen_func_elem_352(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
270
|
const ReasoningBankWasmFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
271
271
|
? { register: () => {}, unregister: () => {} }
|
|
272
272
|
: new FinalizationRegistry(ptr => wasm.__wbg_reasoningbankwasm_free(ptr, 1));
|
|
Binary file
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
export const memory: WebAssembly.Memory;
|
|
4
4
|
export const __wbg_reasoningbankwasm_free: (a: number, b: number) => void;
|
|
5
|
-
export const init: () => void;
|
|
6
5
|
export const log: (a: number, b: number) => void;
|
|
7
6
|
export const reasoningbankwasm_findSimilar: (a: number, b: number, c: number, d: number, e: number, f: number) => number;
|
|
8
7
|
export const reasoningbankwasm_getPattern: (a: number, b: number, c: number) => number;
|
|
@@ -10,8 +9,9 @@ export const reasoningbankwasm_getStats: (a: number) => number;
|
|
|
10
9
|
export const reasoningbankwasm_new: (a: number, b: number) => number;
|
|
11
10
|
export const reasoningbankwasm_searchByCategory: (a: number, b: number, c: number, d: number) => number;
|
|
12
11
|
export const reasoningbankwasm_storePattern: (a: number, b: number, c: number) => number;
|
|
13
|
-
export const
|
|
14
|
-
export const
|
|
12
|
+
export const init: () => void;
|
|
13
|
+
export const __wasm_bindgen_func_elem_346: (a: number, b: number, c: number, d: number) => void;
|
|
14
|
+
export const __wasm_bindgen_func_elem_352: (a: number, b: number, c: number, d: number) => void;
|
|
15
15
|
export const __wbindgen_export: (a: number, b: number) => number;
|
|
16
16
|
export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
|
|
17
17
|
export const __wbindgen_export3: (a: number) => void;
|