@almadar/server 2.1.0 → 2.1.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"multi-user.d.ts","sourceRoot":"","sources":["../../src/middleware/multi-user.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG/D,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,IAAI,CAAC,EAAE;gBACL,GAAG,EAAE,MAAM,CAAC;gBACZ,KAAK,CAAC,EAAE,MAAM,CAAC;gBACf,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;gBACjB,KAAK,CAAC,EAAE,MAAM,CAAC;aAChB,CAAC;YACF,WAAW,CAAC,EAAE;gBACZ,MAAM,EAAE,MAAM,CAAC;gBACf,KAAK,CAAC,EAAE,MAAM,CAAC;gBACf,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;aAClB,CAAC;SACH;KACF;CACF;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,IAAI,CAAC,CA4Bf;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,IAAI,CAAC,CA4Bf"}
1
+ {"version":3,"file":"multi-user.d.ts","sourceRoot":"","sources":["../../src/middleware/multi-user.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG/D,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,IAAI,CAAC,EAAE;gBACL,GAAG,EAAE,MAAM,CAAC;gBACZ,KAAK,CAAC,EAAE,MAAM,CAAC;gBACf,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;gBACjB,KAAK,CAAC,EAAE,MAAM,CAAC;aAChB,CAAC;YACF,WAAW,CAAC,EAAE;gBACZ,MAAM,EAAE,MAAM,CAAC;gBACf,KAAK,CAAC,EAAE,MAAM,CAAC;gBACf,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;aAClB,CAAC;SACH;KACF;CACF;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,IAAI,CAAC,CA4Bf"}
@@ -1 +1 @@
1
- {"version":3,"file":"observability.d.ts","sourceRoot":"","sources":["../../src/routes/observability.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,QAAA,MAAM,MAAM,EAAE,UAAU,CAAC,OAAO,MAAM,CAAY,CAAC;AAyEnD,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"observability.d.ts","sourceRoot":"","sources":["../../src/routes/observability.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAOjC,QAAA,MAAM,MAAM,EAAE,UAAU,CAAC,OAAO,MAAM,CAAY,CAAC;AAyEnD,eAAe,MAAM,CAAC"}
@@ -34,6 +34,6 @@ interface SocketServer {
34
34
  /**
35
35
  * Set up state sync WebSocket with Firebase Auth
36
36
  */
37
- export declare function setupStateSyncWebSocket(io: SocketServer): void;
37
+ export declare function setupStateSyncWebSocket(io: SocketServer): Promise<void>;
38
38
  export {};
39
39
  //# sourceMappingURL=state-sync.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"state-sync.d.ts","sourceRoot":"","sources":["../../src/websocket/state-sync.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,UAAU,MAAM;IACd,IAAI,EAAE;QAAE,IAAI,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,EAAE,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACjE,SAAS,EAAE;QAAE,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACzD,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK,IAAI,CAAC;IACnE,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClD,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;KAAE,CAAC;CAC7E;AAED,UAAU,YAAY;IACpB,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,CAAC;IACjF,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,KAAK,IAAI,CAAC;CAChE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAmE9D"}
1
+ {"version":3,"file":"state-sync.d.ts","sourceRoot":"","sources":["../../src/websocket/state-sync.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,UAAU,MAAM;IACd,IAAI,EAAE;QAAE,IAAI,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,EAAE,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACjE,SAAS,EAAE;QAAE,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACzD,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK,IAAI,CAAC;IACnE,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClD,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;KAAE,CAAC;CAC7E;AAED,UAAU,YAAY;IACpB,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,CAAC;IACjF,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,KAAK,IAAI,CAAC;CAChE;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAqE7E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/server",
3
- "version": "2.1.0",
3
+ "version": "2.1.2",
4
4
  "description": "Shared server infrastructure for Almadar applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,48 +0,0 @@
1
- import { MemoryManager } from '@almadar-io/agent';
2
- import admin from 'firebase-admin';
3
-
4
- // src/deepagent/memory.ts
5
- function getApp() {
6
- if (admin.apps.length === 0) {
7
- throw new Error(
8
- "@almadar/server: Firebase Admin SDK is not initialized. Call initializeFirebase() or admin.initializeApp() before using @almadar/server."
9
- );
10
- }
11
- return admin.app();
12
- }
13
- function getFirestore() {
14
- return getApp().firestore();
15
- }
16
- var db = new Proxy({}, {
17
- get(_target, prop, receiver) {
18
- const firestore = getFirestore();
19
- const value = Reflect.get(firestore, prop, receiver);
20
- return typeof value === "function" ? value.bind(firestore) : value;
21
- }
22
- });
23
-
24
- // src/deepagent/memory.ts
25
- var memoryManager = null;
26
- function getMemoryManager() {
27
- if (!memoryManager) {
28
- memoryManager = new MemoryManager({
29
- db,
30
- usersCollection: "agent_memory_users",
31
- projectsCollection: "agent_memory_projects",
32
- generationsCollection: "agent_memory_generations",
33
- patternsCollection: "agent_memory_patterns",
34
- interruptsCollection: "agent_memory_interrupts",
35
- feedbackCollection: "agent_memory_feedback",
36
- checkpointsCollection: "agent_memory_checkpoints",
37
- toolPreferencesCollection: "agent_memory_tool_preferences"
38
- });
39
- }
40
- return memoryManager;
41
- }
42
- function resetMemoryManager() {
43
- memoryManager = null;
44
- }
45
-
46
- export { getMemoryManager, resetMemoryManager };
47
- //# sourceMappingURL=memory.js.map
48
- //# sourceMappingURL=memory.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/lib/db.ts","../../src/deepagent/memory.ts"],"names":[],"mappings":";;;;AAoFA,SAAS,MAAA,GAAwB;AAC/B,EAAA,IAAI,KAAA,CAAM,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAC3B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF;AACA,EAAA,OAAO,MAAM,GAAA,EAAI;AACnB;AAKO,SAAS,YAAA,GAA0C;AACxD,EAAA,OAAO,MAAA,GAAS,SAAA,EAAU;AAC5B;AAgBO,IAAM,EAAA,GAAK,IAAI,KAAA,CAAM,EAAC,EAAgC;AAAA,EAC3D,GAAA,CAAI,OAAA,EAAS,IAAA,EAAM,QAAA,EAAU;AAC3B,IAAA,MAAM,YAAY,YAAA,EAAa;AAC/B,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,SAAA,EAAW,MAAM,QAAQ,CAAA;AACnD,IAAA,OAAO,OAAO,KAAA,KAAU,UAAA,GAAa,KAAA,CAAM,IAAA,CAAK,SAAS,CAAA,GAAI,KAAA;AAAA,EAC/D;AACF,CAAC,CAAA;;;AC9GD,IAAI,aAAA,GAAsC,IAAA;AAKnC,SAAS,gBAAA,GAAkC;AAChD,EAAA,IAAI,CAAC,aAAA,EAAe;AAClB,IAAA,aAAA,GAAgB,IAAI,aAAA,CAAc;AAAA,MAChC,EAAA;AAAA,MACA,eAAA,EAAiB,oBAAA;AAAA,MACjB,kBAAA,EAAoB,uBAAA;AAAA,MACpB,qBAAA,EAAuB,0BAAA;AAAA,MACvB,kBAAA,EAAoB,uBAAA;AAAA,MACpB,oBAAA,EAAsB,yBAAA;AAAA,MACtB,kBAAA,EAAoB,uBAAA;AAAA,MACpB,qBAAA,EAAuB,0BAAA;AAAA,MACvB,yBAAA,EAA2B;AAAA,KAC5B,CAAA;AAAA,EACH;AACA,EAAA,OAAO,aAAA;AACT;AAKO,SAAS,kBAAA,GAA2B;AACzC,EAAA,aAAA,GAAgB,IAAA;AAClB","file":"memory.js","sourcesContent":["/**\n * Database Accessors & Initialization\n *\n * This module provides:\n * - `initializeFirebase()` — convenience function to init Firebase from env vars\n * - `getFirestore()`, `getAuth()` — accessors for Firebase services\n * - `db` — lazy Firestore proxy (no eager initialization)\n *\n * The consuming application MUST call `initializeFirebase()` or\n * `admin.initializeApp()` before using any Firebase-dependent features.\n */\n\nimport admin from 'firebase-admin';\n\n/**\n * Initialize Firebase Admin SDK from environment variables.\n *\n * Reads: FIREBASE_PROJECT_ID, FIREBASE_CLIENT_EMAIL, FIREBASE_PRIVATE_KEY,\n * FIREBASE_SERVICE_ACCOUNT_PATH, FIRESTORE_EMULATOR_HOST\n *\n * Safe to call multiple times — returns existing app if already initialized.\n */\nexport function initializeFirebase(): admin.app.App {\n // Already initialized — return existing app\n if (admin.apps.length > 0) {\n return admin.app();\n }\n\n const projectId = process.env.FIREBASE_PROJECT_ID;\n const emulatorHost = process.env.FIRESTORE_EMULATOR_HOST;\n\n // Emulator mode — no credentials needed\n if (emulatorHost) {\n const app = admin.initializeApp({\n projectId: projectId || 'demo-project',\n });\n console.log(`Firebase Admin initialized for emulator: ${emulatorHost}`);\n return app;\n }\n\n // Service account file\n const serviceAccountPath = process.env.FIREBASE_SERVICE_ACCOUNT_PATH;\n if (serviceAccountPath) {\n // Dynamic require for JSON service account file at runtime\n const serviceAccount = require(serviceAccountPath) as Record<string, unknown>;\n return admin.initializeApp({\n credential: admin.credential.cert(serviceAccount),\n projectId,\n });\n }\n\n // Inline credentials\n const clientEmail = process.env.FIREBASE_CLIENT_EMAIL;\n const privateKey = process.env.FIREBASE_PRIVATE_KEY;\n if (projectId && clientEmail && privateKey) {\n return admin.initializeApp({\n credential: admin.credential.cert({\n projectId,\n clientEmail,\n privateKey: privateKey.replace(/\\\\n/g, '\\n'),\n }),\n projectId,\n });\n }\n\n // Application default credentials (Cloud Run, etc.)\n if (projectId) {\n return admin.initializeApp({\n credential: admin.credential.applicationDefault(),\n projectId,\n });\n }\n\n throw new Error(\n '@almadar/server: Cannot initialize Firebase — no credentials found. ' +\n 'Set FIREBASE_PROJECT_ID + FIREBASE_CLIENT_EMAIL + FIREBASE_PRIVATE_KEY, ' +\n 'or FIREBASE_SERVICE_ACCOUNT_PATH, or FIRESTORE_EMULATOR_HOST.'\n );\n}\n\n/**\n * Get the initialized Firebase app.\n * Throws if Firebase Admin SDK has not been initialized.\n */\nfunction getApp(): admin.app.App {\n if (admin.apps.length === 0) {\n throw new Error(\n '@almadar/server: Firebase Admin SDK is not initialized. ' +\n 'Call initializeFirebase() or admin.initializeApp() before using @almadar/server.'\n );\n }\n return admin.app();\n}\n\n/**\n * Get Firestore instance from the pre-initialized Firebase app.\n */\nexport function getFirestore(): admin.firestore.Firestore {\n return getApp().firestore();\n}\n\n/**\n * Get Firebase Auth instance from the pre-initialized Firebase app.\n */\nexport function getAuth(): admin.auth.Auth {\n return getApp().auth();\n}\n\n// Re-export admin for convenience\nexport { admin };\n\n/**\n * Lazy Firestore proxy — resolves on first property access, not at import time.\n * This prevents the \"Firebase not initialized\" error during module loading.\n */\nexport const db = new Proxy({} as admin.firestore.Firestore, {\n get(_target, prop, receiver) {\n const firestore = getFirestore();\n const value = Reflect.get(firestore, prop, receiver);\n return typeof value === 'function' ? value.bind(firestore) : value;\n },\n});\n","/**\n * Memory Manager Singleton\n *\n * Provides Firestore-backed memory management for DeepAgent.\n *\n * @packageDocumentation\n */\n\nimport { MemoryManager } from '@almadar-io/agent';\nimport { db } from '../lib/db.js';\n\nlet memoryManager: MemoryManager | null = null;\n\n/**\n * Get or create the MemoryManager singleton\n */\nexport function getMemoryManager(): MemoryManager {\n if (!memoryManager) {\n memoryManager = new MemoryManager({\n db,\n usersCollection: 'agent_memory_users',\n projectsCollection: 'agent_memory_projects',\n generationsCollection: 'agent_memory_generations',\n patternsCollection: 'agent_memory_patterns',\n interruptsCollection: 'agent_memory_interrupts',\n feedbackCollection: 'agent_memory_feedback',\n checkpointsCollection: 'agent_memory_checkpoints',\n toolPreferencesCollection: 'agent_memory_tool_preferences',\n });\n }\n return memoryManager;\n}\n\n/**\n * Reset the MemoryManager (useful for testing)\n */\nexport function resetMemoryManager(): void {\n memoryManager = null;\n}\n"]}
@@ -1,68 +0,0 @@
1
- import { SessionManager, MemoryManager } from '@almadar-io/agent';
2
- import admin from 'firebase-admin';
3
-
4
- // src/deepagent/session.ts
5
- function getApp() {
6
- if (admin.apps.length === 0) {
7
- throw new Error(
8
- "@almadar/server: Firebase Admin SDK is not initialized. Call initializeFirebase() or admin.initializeApp() before using @almadar/server."
9
- );
10
- }
11
- return admin.app();
12
- }
13
- function getFirestore() {
14
- return getApp().firestore();
15
- }
16
- var db = new Proxy({}, {
17
- get(_target, prop, receiver) {
18
- const firestore = getFirestore();
19
- const value = Reflect.get(firestore, prop, receiver);
20
- return typeof value === "function" ? value.bind(firestore) : value;
21
- }
22
- });
23
- var memoryManager = null;
24
- function getMemoryManager() {
25
- if (!memoryManager) {
26
- memoryManager = new MemoryManager({
27
- db,
28
- usersCollection: "agent_memory_users",
29
- projectsCollection: "agent_memory_projects",
30
- generationsCollection: "agent_memory_generations",
31
- patternsCollection: "agent_memory_patterns",
32
- interruptsCollection: "agent_memory_interrupts",
33
- feedbackCollection: "agent_memory_feedback",
34
- checkpointsCollection: "agent_memory_checkpoints",
35
- toolPreferencesCollection: "agent_memory_tool_preferences"
36
- });
37
- }
38
- return memoryManager;
39
- }
40
-
41
- // src/deepagent/session.ts
42
- var sessionManager = null;
43
- function createFirestoreAdapter(firestore) {
44
- return firestore;
45
- }
46
- function getSessionManager() {
47
- if (!sessionManager) {
48
- sessionManager = new SessionManager({
49
- mode: "firestore",
50
- firestoreDb: createFirestoreAdapter(db),
51
- memoryManager: getMemoryManager(),
52
- // Enable GAP-002D
53
- compactionConfig: {
54
- maxTokens: 15e4,
55
- keepRecentMessages: 10,
56
- strategy: "last"
57
- }
58
- });
59
- }
60
- return sessionManager;
61
- }
62
- function resetSessionManager() {
63
- sessionManager = null;
64
- }
65
-
66
- export { getSessionManager, resetSessionManager };
67
- //# sourceMappingURL=session.js.map
68
- //# sourceMappingURL=session.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/lib/db.ts","../../src/deepagent/memory.ts","../../src/deepagent/session.ts"],"names":[],"mappings":";;;;AAoFA,SAAS,MAAA,GAAwB;AAC/B,EAAA,IAAI,KAAA,CAAM,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAC3B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF;AACA,EAAA,OAAO,MAAM,GAAA,EAAI;AACnB;AAKO,SAAS,YAAA,GAA0C;AACxD,EAAA,OAAO,MAAA,GAAS,SAAA,EAAU;AAC5B;AAgBO,IAAM,EAAA,GAAK,IAAI,KAAA,CAAM,EAAC,EAAgC;AAAA,EAC3D,GAAA,CAAI,OAAA,EAAS,IAAA,EAAM,QAAA,EAAU;AAC3B,IAAA,MAAM,YAAY,YAAA,EAAa;AAC/B,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,SAAA,EAAW,MAAM,QAAQ,CAAA;AACnD,IAAA,OAAO,OAAO,KAAA,KAAU,UAAA,GAAa,KAAA,CAAM,IAAA,CAAK,SAAS,CAAA,GAAI,KAAA;AAAA,EAC/D;AACF,CAAC,CAAA;AC9GD,IAAI,aAAA,GAAsC,IAAA;AAKnC,SAAS,gBAAA,GAAkC;AAChD,EAAA,IAAI,CAAC,aAAA,EAAe;AAClB,IAAA,aAAA,GAAgB,IAAI,aAAA,CAAc;AAAA,MAChC,EAAA;AAAA,MACA,eAAA,EAAiB,oBAAA;AAAA,MACjB,kBAAA,EAAoB,uBAAA;AAAA,MACpB,qBAAA,EAAuB,0BAAA;AAAA,MACvB,kBAAA,EAAoB,uBAAA;AAAA,MACpB,oBAAA,EAAsB,yBAAA;AAAA,MACtB,kBAAA,EAAoB,uBAAA;AAAA,MACpB,qBAAA,EAAuB,0BAAA;AAAA,MACvB,yBAAA,EAA2B;AAAA,KAC5B,CAAA;AAAA,EACH;AACA,EAAA,OAAO,aAAA;AACT;;;AClBA,IAAI,cAAA,GAAwC,IAAA;AAK5C,SAAS,uBAAuB,SAAA,EAAmC;AACjE,EAAA,OAAO,SAAA;AACT;AAKO,SAAS,iBAAA,GAAoC;AAClD,EAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,IAAA,cAAA,GAAiB,IAAI,cAAA,CAAe;AAAA,MAClC,IAAA,EAAM,WAAA;AAAA,MACN,WAAA,EAAa,uBAAuB,EAAE,CAAA;AAAA,MACtC,eAAe,gBAAA,EAAiB;AAAA;AAAA,MAChC,gBAAA,EAAkB;AAAA,QAChB,SAAA,EAAW,IAAA;AAAA,QACX,kBAAA,EAAoB,EAAA;AAAA,QACpB,QAAA,EAAU;AAAA;AACZ,KACD,CAAA;AAAA,EACH;AACA,EAAA,OAAO,cAAA;AACT;AAKO,SAAS,mBAAA,GAA4B;AAC1C,EAAA,cAAA,GAAiB,IAAA;AACnB","file":"session.js","sourcesContent":["/**\n * Database Accessors & Initialization\n *\n * This module provides:\n * - `initializeFirebase()` — convenience function to init Firebase from env vars\n * - `getFirestore()`, `getAuth()` — accessors for Firebase services\n * - `db` — lazy Firestore proxy (no eager initialization)\n *\n * The consuming application MUST call `initializeFirebase()` or\n * `admin.initializeApp()` before using any Firebase-dependent features.\n */\n\nimport admin from 'firebase-admin';\n\n/**\n * Initialize Firebase Admin SDK from environment variables.\n *\n * Reads: FIREBASE_PROJECT_ID, FIREBASE_CLIENT_EMAIL, FIREBASE_PRIVATE_KEY,\n * FIREBASE_SERVICE_ACCOUNT_PATH, FIRESTORE_EMULATOR_HOST\n *\n * Safe to call multiple times — returns existing app if already initialized.\n */\nexport function initializeFirebase(): admin.app.App {\n // Already initialized — return existing app\n if (admin.apps.length > 0) {\n return admin.app();\n }\n\n const projectId = process.env.FIREBASE_PROJECT_ID;\n const emulatorHost = process.env.FIRESTORE_EMULATOR_HOST;\n\n // Emulator mode — no credentials needed\n if (emulatorHost) {\n const app = admin.initializeApp({\n projectId: projectId || 'demo-project',\n });\n console.log(`Firebase Admin initialized for emulator: ${emulatorHost}`);\n return app;\n }\n\n // Service account file\n const serviceAccountPath = process.env.FIREBASE_SERVICE_ACCOUNT_PATH;\n if (serviceAccountPath) {\n // Dynamic require for JSON service account file at runtime\n const serviceAccount = require(serviceAccountPath) as Record<string, unknown>;\n return admin.initializeApp({\n credential: admin.credential.cert(serviceAccount),\n projectId,\n });\n }\n\n // Inline credentials\n const clientEmail = process.env.FIREBASE_CLIENT_EMAIL;\n const privateKey = process.env.FIREBASE_PRIVATE_KEY;\n if (projectId && clientEmail && privateKey) {\n return admin.initializeApp({\n credential: admin.credential.cert({\n projectId,\n clientEmail,\n privateKey: privateKey.replace(/\\\\n/g, '\\n'),\n }),\n projectId,\n });\n }\n\n // Application default credentials (Cloud Run, etc.)\n if (projectId) {\n return admin.initializeApp({\n credential: admin.credential.applicationDefault(),\n projectId,\n });\n }\n\n throw new Error(\n '@almadar/server: Cannot initialize Firebase — no credentials found. ' +\n 'Set FIREBASE_PROJECT_ID + FIREBASE_CLIENT_EMAIL + FIREBASE_PRIVATE_KEY, ' +\n 'or FIREBASE_SERVICE_ACCOUNT_PATH, or FIRESTORE_EMULATOR_HOST.'\n );\n}\n\n/**\n * Get the initialized Firebase app.\n * Throws if Firebase Admin SDK has not been initialized.\n */\nfunction getApp(): admin.app.App {\n if (admin.apps.length === 0) {\n throw new Error(\n '@almadar/server: Firebase Admin SDK is not initialized. ' +\n 'Call initializeFirebase() or admin.initializeApp() before using @almadar/server.'\n );\n }\n return admin.app();\n}\n\n/**\n * Get Firestore instance from the pre-initialized Firebase app.\n */\nexport function getFirestore(): admin.firestore.Firestore {\n return getApp().firestore();\n}\n\n/**\n * Get Firebase Auth instance from the pre-initialized Firebase app.\n */\nexport function getAuth(): admin.auth.Auth {\n return getApp().auth();\n}\n\n// Re-export admin for convenience\nexport { admin };\n\n/**\n * Lazy Firestore proxy — resolves on first property access, not at import time.\n * This prevents the \"Firebase not initialized\" error during module loading.\n */\nexport const db = new Proxy({} as admin.firestore.Firestore, {\n get(_target, prop, receiver) {\n const firestore = getFirestore();\n const value = Reflect.get(firestore, prop, receiver);\n return typeof value === 'function' ? value.bind(firestore) : value;\n },\n});\n","/**\n * Memory Manager Singleton\n *\n * Provides Firestore-backed memory management for DeepAgent.\n *\n * @packageDocumentation\n */\n\nimport { MemoryManager } from '@almadar-io/agent';\nimport { db } from '../lib/db.js';\n\nlet memoryManager: MemoryManager | null = null;\n\n/**\n * Get or create the MemoryManager singleton\n */\nexport function getMemoryManager(): MemoryManager {\n if (!memoryManager) {\n memoryManager = new MemoryManager({\n db,\n usersCollection: 'agent_memory_users',\n projectsCollection: 'agent_memory_projects',\n generationsCollection: 'agent_memory_generations',\n patternsCollection: 'agent_memory_patterns',\n interruptsCollection: 'agent_memory_interrupts',\n feedbackCollection: 'agent_memory_feedback',\n checkpointsCollection: 'agent_memory_checkpoints',\n toolPreferencesCollection: 'agent_memory_tool_preferences',\n });\n }\n return memoryManager;\n}\n\n/**\n * Reset the MemoryManager (useful for testing)\n */\nexport function resetMemoryManager(): void {\n memoryManager = null;\n}\n","/**\n * Session Manager Singleton\n *\n * Provides Firestore-backed session management with full GAP features.\n *\n * @packageDocumentation\n */\n\nimport { SessionManager } from '@almadar-io/agent';\nimport { db } from '../lib/db.js';\nimport { getMemoryManager } from './memory.js';\nimport type { FirestoreDb } from '@almadar-io/agent';\n\nlet sessionManager: SessionManager | null = null;\n\n/**\n * Adapter to make Firebase Firestore compatible with @almadar/agent FirestoreDb interface\n */\nfunction createFirestoreAdapter(firestore: typeof db): FirestoreDb {\n return firestore as unknown as FirestoreDb;\n}\n\n/**\n * Get or create the SessionManager singleton\n */\nexport function getSessionManager(): SessionManager {\n if (!sessionManager) {\n sessionManager = new SessionManager({\n mode: 'firestore',\n firestoreDb: createFirestoreAdapter(db),\n memoryManager: getMemoryManager(), // Enable GAP-002D\n compactionConfig: {\n maxTokens: 150000,\n keepRecentMessages: 10,\n strategy: 'last',\n },\n });\n }\n return sessionManager;\n}\n\n/**\n * Reset the SessionManager (useful for testing)\n */\nexport function resetSessionManager(): void {\n sessionManager = null;\n}\n"]}
@@ -1,114 +0,0 @@
1
- import { MemoryManager, SessionManager, getObservabilityCollector, getMultiUserManager, createWorkflowToolWrapper, createSkillAgent } from '@almadar-io/agent';
2
- import admin from 'firebase-admin';
3
-
4
- // src/deepagent/skill-agent.ts
5
- function getApp() {
6
- if (admin.apps.length === 0) {
7
- throw new Error(
8
- "@almadar/server: Firebase Admin SDK is not initialized. Call initializeFirebase() or admin.initializeApp() before using @almadar/server."
9
- );
10
- }
11
- return admin.app();
12
- }
13
- function getFirestore() {
14
- return getApp().firestore();
15
- }
16
- var db = new Proxy({}, {
17
- get(_target, prop, receiver) {
18
- const firestore = getFirestore();
19
- const value = Reflect.get(firestore, prop, receiver);
20
- return typeof value === "function" ? value.bind(firestore) : value;
21
- }
22
- });
23
-
24
- // src/deepagent/memory.ts
25
- var memoryManager = null;
26
- function getMemoryManager() {
27
- if (!memoryManager) {
28
- memoryManager = new MemoryManager({
29
- db,
30
- usersCollection: "agent_memory_users",
31
- projectsCollection: "agent_memory_projects",
32
- generationsCollection: "agent_memory_generations",
33
- patternsCollection: "agent_memory_patterns",
34
- interruptsCollection: "agent_memory_interrupts",
35
- feedbackCollection: "agent_memory_feedback",
36
- checkpointsCollection: "agent_memory_checkpoints",
37
- toolPreferencesCollection: "agent_memory_tool_preferences"
38
- });
39
- }
40
- return memoryManager;
41
- }
42
- var sessionManager = null;
43
- function createFirestoreAdapter(firestore) {
44
- return firestore;
45
- }
46
- function getSessionManager() {
47
- if (!sessionManager) {
48
- sessionManager = new SessionManager({
49
- mode: "firestore",
50
- firestoreDb: createFirestoreAdapter(db),
51
- memoryManager: getMemoryManager(),
52
- // Enable GAP-002D
53
- compactionConfig: {
54
- maxTokens: 15e4,
55
- keepRecentMessages: 10,
56
- strategy: "last"
57
- }
58
- });
59
- }
60
- return sessionManager;
61
- }
62
-
63
- // src/deepagent/skill-agent.ts
64
- async function createServerSkillAgent(options) {
65
- const memoryManager2 = getMemoryManager();
66
- getSessionManager();
67
- const observability = getObservabilityCollector();
68
- const multiUser = getMultiUserManager();
69
- if (options.threadId) {
70
- const access = multiUser.canAccessSession(options.threadId, {
71
- userId: options.userId,
72
- roles: ["user"]
73
- });
74
- if (!access.allowed) {
75
- throw new Error(`Access denied: ${access.reason}`);
76
- }
77
- }
78
- observability.startSession(options.threadId ?? "new", options.userId);
79
- const workflowToolWrapper = createWorkflowToolWrapper({
80
- maxRetries: 2,
81
- enableTelemetry: true,
82
- timeoutMs: 3e5
83
- // 5 minutes
84
- });
85
- try {
86
- const result = await createSkillAgent({
87
- ...options,
88
- memoryManager: memoryManager2,
89
- // GAP-001: Enable memory
90
- userId: options.userId,
91
- // GAP-002D: Session → Memory sync
92
- appId: options.appId,
93
- toolWrapper: workflowToolWrapper.wrap
94
- // Always use workflow wrapper for reliability
95
- });
96
- if (result.threadId) {
97
- multiUser.assignSessionOwnership(result.threadId, options.userId);
98
- }
99
- observability.recordEvent({
100
- type: "session_start",
101
- sessionId: result.threadId,
102
- userId: options.userId,
103
- payload: { skill: options.skill }
104
- });
105
- return result;
106
- } catch (error) {
107
- observability.recordError(options.threadId ?? "new", error);
108
- throw error;
109
- }
110
- }
111
-
112
- export { createServerSkillAgent, getMemoryManager, getSessionManager };
113
- //# sourceMappingURL=skill-agent.js.map
114
- //# sourceMappingURL=skill-agent.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/lib/db.ts","../../src/deepagent/memory.ts","../../src/deepagent/session.ts","../../src/deepagent/skill-agent.ts"],"names":["memoryManager"],"mappings":"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","file":"skill-agent.js","sourcesContent":["/**\n * Database Accessors & Initialization\n *\n * This module provides:\n * - `initializeFirebase()` — convenience function to init Firebase from env vars\n * - `getFirestore()`, `getAuth()` — accessors for Firebase services\n * - `db` — lazy Firestore proxy (no eager initialization)\n *\n * The consuming application MUST call `initializeFirebase()` or\n * `admin.initializeApp()` before using any Firebase-dependent features.\n */\n\nimport admin from 'firebase-admin';\n\n/**\n * Initialize Firebase Admin SDK from environment variables.\n *\n * Reads: FIREBASE_PROJECT_ID, FIREBASE_CLIENT_EMAIL, FIREBASE_PRIVATE_KEY,\n * FIREBASE_SERVICE_ACCOUNT_PATH, FIRESTORE_EMULATOR_HOST\n *\n * Safe to call multiple times — returns existing app if already initialized.\n */\nexport function initializeFirebase(): admin.app.App {\n // Already initialized — return existing app\n if (admin.apps.length > 0) {\n return admin.app();\n }\n\n const projectId = process.env.FIREBASE_PROJECT_ID;\n const emulatorHost = process.env.FIRESTORE_EMULATOR_HOST;\n\n // Emulator mode — no credentials needed\n if (emulatorHost) {\n const app = admin.initializeApp({\n projectId: projectId || 'demo-project',\n });\n console.log(`Firebase Admin initialized for emulator: ${emulatorHost}`);\n return app;\n }\n\n // Service account file\n const serviceAccountPath = process.env.FIREBASE_SERVICE_ACCOUNT_PATH;\n if (serviceAccountPath) {\n // Dynamic require for JSON service account file at runtime\n const serviceAccount = require(serviceAccountPath) as Record<string, unknown>;\n return admin.initializeApp({\n credential: admin.credential.cert(serviceAccount),\n projectId,\n });\n }\n\n // Inline credentials\n const clientEmail = process.env.FIREBASE_CLIENT_EMAIL;\n const privateKey = process.env.FIREBASE_PRIVATE_KEY;\n if (projectId && clientEmail && privateKey) {\n return admin.initializeApp({\n credential: admin.credential.cert({\n projectId,\n clientEmail,\n privateKey: privateKey.replace(/\\\\n/g, '\\n'),\n }),\n projectId,\n });\n }\n\n // Application default credentials (Cloud Run, etc.)\n if (projectId) {\n return admin.initializeApp({\n credential: admin.credential.applicationDefault(),\n projectId,\n });\n }\n\n throw new Error(\n '@almadar/server: Cannot initialize Firebase — no credentials found. ' +\n 'Set FIREBASE_PROJECT_ID + FIREBASE_CLIENT_EMAIL + FIREBASE_PRIVATE_KEY, ' +\n 'or FIREBASE_SERVICE_ACCOUNT_PATH, or FIRESTORE_EMULATOR_HOST.'\n );\n}\n\n/**\n * Get the initialized Firebase app.\n * Throws if Firebase Admin SDK has not been initialized.\n */\nfunction getApp(): admin.app.App {\n if (admin.apps.length === 0) {\n throw new Error(\n '@almadar/server: Firebase Admin SDK is not initialized. ' +\n 'Call initializeFirebase() or admin.initializeApp() before using @almadar/server.'\n );\n }\n return admin.app();\n}\n\n/**\n * Get Firestore instance from the pre-initialized Firebase app.\n */\nexport function getFirestore(): admin.firestore.Firestore {\n return getApp().firestore();\n}\n\n/**\n * Get Firebase Auth instance from the pre-initialized Firebase app.\n */\nexport function getAuth(): admin.auth.Auth {\n return getApp().auth();\n}\n\n// Re-export admin for convenience\nexport { admin };\n\n/**\n * Lazy Firestore proxy — resolves on first property access, not at import time.\n * This prevents the \"Firebase not initialized\" error during module loading.\n */\nexport const db = new Proxy({} as admin.firestore.Firestore, {\n get(_target, prop, receiver) {\n const firestore = getFirestore();\n const value = Reflect.get(firestore, prop, receiver);\n return typeof value === 'function' ? value.bind(firestore) : value;\n },\n});\n","/**\n * Memory Manager Singleton\n *\n * Provides Firestore-backed memory management for DeepAgent.\n *\n * @packageDocumentation\n */\n\nimport { MemoryManager } from '@almadar-io/agent';\nimport { db } from '../lib/db.js';\n\nlet memoryManager: MemoryManager | null = null;\n\n/**\n * Get or create the MemoryManager singleton\n */\nexport function getMemoryManager(): MemoryManager {\n if (!memoryManager) {\n memoryManager = new MemoryManager({\n db,\n usersCollection: 'agent_memory_users',\n projectsCollection: 'agent_memory_projects',\n generationsCollection: 'agent_memory_generations',\n patternsCollection: 'agent_memory_patterns',\n interruptsCollection: 'agent_memory_interrupts',\n feedbackCollection: 'agent_memory_feedback',\n checkpointsCollection: 'agent_memory_checkpoints',\n toolPreferencesCollection: 'agent_memory_tool_preferences',\n });\n }\n return memoryManager;\n}\n\n/**\n * Reset the MemoryManager (useful for testing)\n */\nexport function resetMemoryManager(): void {\n memoryManager = null;\n}\n","/**\n * Session Manager Singleton\n *\n * Provides Firestore-backed session management with full GAP features.\n *\n * @packageDocumentation\n */\n\nimport { SessionManager } from '@almadar-io/agent';\nimport { db } from '../lib/db.js';\nimport { getMemoryManager } from './memory.js';\nimport type { FirestoreDb } from '@almadar-io/agent';\n\nlet sessionManager: SessionManager | null = null;\n\n/**\n * Adapter to make Firebase Firestore compatible with @almadar/agent FirestoreDb interface\n */\nfunction createFirestoreAdapter(firestore: typeof db): FirestoreDb {\n return firestore as unknown as FirestoreDb;\n}\n\n/**\n * Get or create the SessionManager singleton\n */\nexport function getSessionManager(): SessionManager {\n if (!sessionManager) {\n sessionManager = new SessionManager({\n mode: 'firestore',\n firestoreDb: createFirestoreAdapter(db),\n memoryManager: getMemoryManager(), // Enable GAP-002D\n compactionConfig: {\n maxTokens: 150000,\n keepRecentMessages: 10,\n strategy: 'last',\n },\n });\n }\n return sessionManager;\n}\n\n/**\n * Reset the SessionManager (useful for testing)\n */\nexport function resetSessionManager(): void {\n sessionManager = null;\n}\n","/**\n * Skill Agent Factory\n *\n * Creates DeepAgent instances with full GAP feature integration.\n *\n * @packageDocumentation\n */\n\nimport {\n createSkillAgent,\n getObservabilityCollector,\n getMultiUserManager,\n createWorkflowToolWrapper,\n type SkillAgentOptions,\n type SkillAgentResult,\n} from '@almadar-io/agent';\nimport { getMemoryManager } from './memory.js';\nimport { getSessionManager } from './session.js';\n\ninterface ServerSkillAgentOptions extends SkillAgentOptions {\n /** User ID from Firebase Auth */\n userId: string;\n /** App/Project ID for context */\n appId?: string;\n}\n\n/**\n * Create a skill agent with full server-side GAP integration\n */\nexport async function createServerSkillAgent(\n options: ServerSkillAgentOptions,\n): Promise<SkillAgentResult> {\n const memoryManager = getMemoryManager();\n const sessionManager = getSessionManager();\n const observability = getObservabilityCollector();\n const multiUser = getMultiUserManager();\n\n // Check access if resuming existing session\n if (options.threadId) {\n const access = multiUser.canAccessSession(options.threadId, {\n userId: options.userId,\n roles: ['user'],\n });\n if (!access.allowed) {\n throw new Error(`Access denied: ${access.reason}`);\n }\n }\n\n // Start observability\n observability.startSession(options.threadId ?? 'new', options.userId);\n\n // Create workflow tool wrapper for retry/telemetry (always enabled)\n const workflowToolWrapper = createWorkflowToolWrapper({\n maxRetries: 2,\n enableTelemetry: true,\n timeoutMs: 300000, // 5 minutes\n });\n\n try {\n const result = await createSkillAgent({\n ...options,\n memoryManager, // GAP-001: Enable memory\n userId: options.userId, // GAP-002D: Session → Memory sync\n appId: options.appId,\n toolWrapper: workflowToolWrapper.wrap, // Always use workflow wrapper for reliability\n });\n\n // Assign ownership for new sessions\n if (result.threadId) {\n multiUser.assignSessionOwnership(result.threadId, options.userId);\n }\n\n // Record successful creation\n observability.recordEvent({\n type: 'session_start',\n sessionId: result.threadId,\n userId: options.userId,\n payload: { skill: options.skill },\n });\n\n return result;\n } catch (error) {\n observability.recordError(options.threadId ?? 'new', error as Error);\n throw error;\n }\n}\n\n// Re-export for convenience\nexport { getMemoryManager, getSessionManager };\n"]}
@@ -1,76 +0,0 @@
1
- import { createUserContext, getMultiUserManager } from '@almadar-io/agent';
2
- import admin from 'firebase-admin';
3
-
4
- // src/middleware/multi-user.ts
5
- function getApp() {
6
- if (admin.apps.length === 0) {
7
- throw new Error(
8
- "@almadar/server: Firebase Admin SDK is not initialized. Call initializeFirebase() or admin.initializeApp() before using @almadar/server."
9
- );
10
- }
11
- return admin.app();
12
- }
13
- function getFirestore() {
14
- return getApp().firestore();
15
- }
16
- function getAuth() {
17
- return getApp().auth();
18
- }
19
- new Proxy({}, {
20
- get(_target, prop, receiver) {
21
- const firestore = getFirestore();
22
- const value = Reflect.get(firestore, prop, receiver);
23
- return typeof value === "function" ? value.bind(firestore) : value;
24
- }
25
- });
26
-
27
- // src/middleware/multi-user.ts
28
- async function multiUserMiddleware(req, res, next) {
29
- const userId = req.user?.uid;
30
- if (!userId) {
31
- res.status(401).json({ error: "Authentication required" });
32
- return;
33
- }
34
- req.userContext = createUserContext(userId, {
35
- orgId: req.user?.orgId,
36
- roles: req.user?.roles ?? ["user"]
37
- });
38
- const originalJson = res.json.bind(res);
39
- res.json = (body) => {
40
- if (body && typeof body === "object" && "threadId" in body) {
41
- const multiUser = getMultiUserManager();
42
- multiUser.assignSessionOwnership(
43
- body.threadId,
44
- userId
45
- );
46
- }
47
- return originalJson(body);
48
- };
49
- next();
50
- }
51
- async function verifyFirebaseAuth(req, res, next) {
52
- const authHeader = req.headers.authorization;
53
- if (!authHeader?.startsWith("Bearer ")) {
54
- res.status(401).json({ error: "No token provided" });
55
- return;
56
- }
57
- const token = authHeader.split("Bearer ")[1];
58
- try {
59
- const decodedToken = await getAuth().verifyIdToken(token);
60
- const user = await getAuth().getUser(decodedToken.uid);
61
- req.user = {
62
- uid: decodedToken.uid,
63
- email: decodedToken.email,
64
- roles: user.customClaims?.roles ?? ["user"],
65
- orgId: user.customClaims?.orgId
66
- };
67
- next();
68
- } catch (error) {
69
- console.error("Token verification failed:", error);
70
- res.status(401).json({ error: "Invalid token" });
71
- }
72
- }
73
-
74
- export { multiUserMiddleware, verifyFirebaseAuth };
75
- //# sourceMappingURL=multi-user.js.map
76
- //# sourceMappingURL=multi-user.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/lib/db.ts","../../src/middleware/multi-user.ts"],"names":[],"mappings":";;;;AAoFA,SAAS,MAAA,GAAwB;AAC/B,EAAA,IAAI,KAAA,CAAM,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAC3B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF;AACA,EAAA,OAAO,MAAM,GAAA,EAAI;AACnB;AAKO,SAAS,YAAA,GAA0C;AACxD,EAAA,OAAO,MAAA,GAAS,SAAA,EAAU;AAC5B;AAKO,SAAS,OAAA,GAA2B;AACzC,EAAA,OAAO,MAAA,GAAS,IAAA,EAAK;AACvB;AASkB,IAAI,KAAA,CAAM,EAAC,EAAgC;AAAA,EAC3D,GAAA,CAAI,OAAA,EAAS,IAAA,EAAM,QAAA,EAAU;AAC3B,IAAA,MAAM,YAAY,YAAA,EAAa;AAC/B,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,SAAA,EAAW,MAAM,QAAQ,CAAA;AACnD,IAAA,OAAO,OAAO,KAAA,KAAU,UAAA,GAAa,KAAA,CAAM,IAAA,CAAK,SAAS,CAAA,GAAI,KAAA;AAAA,EAC/D;AACF,CAAC;;;ACvFD,eAAsB,mBAAA,CACpB,GAAA,EACA,GAAA,EACA,IAAA,EACe;AACf,EAAA,MAAM,MAAA,GAAS,IAAI,IAAA,EAAM,GAAA;AAEzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,GAAA,CAAI,OAAO,GAAG,CAAA,CAAE,KAAK,EAAE,KAAA,EAAO,2BAA2B,CAAA;AACzD,IAAA;AAAA,EACF;AAGA,EAAA,GAAA,CAAI,WAAA,GAAc,kBAAkB,MAAA,EAAQ;AAAA,IAC1C,KAAA,EAAO,IAAI,IAAA,EAAM,KAAA;AAAA,IACjB,KAAA,EAAO,GAAA,CAAI,IAAA,EAAM,KAAA,IAAS,CAAC,MAAM;AAAA,GAClC,CAAA;AAGD,EAAA,MAAM,YAAA,GAAe,GAAA,CAAI,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA;AACtC,EAAA,GAAA,CAAI,IAAA,GAAO,CAAC,IAAA,KAAkB;AAC5B,IAAA,IAAI,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,IAAY,cAAc,IAAA,EAAM;AAC1D,MAAA,MAAM,YAAY,mBAAA,EAAoB;AACtC,MAAA,SAAA,CAAU,sBAAA;AAAA,QACP,IAAA,CAA8B,QAAA;AAAA,QAC/B;AAAA,OACF;AAAA,IACF;AACA,IAAA,OAAO,aAAa,IAAI,CAAA;AAAA,EAC1B,CAAA;AAEA,EAAA,IAAA,EAAK;AACP;AAKA,eAAsB,kBAAA,CACpB,GAAA,EACA,GAAA,EACA,IAAA,EACe;AACf,EAAA,MAAM,UAAA,GAAa,IAAI,OAAA,CAAQ,aAAA;AAE/B,EAAA,IAAI,CAAC,UAAA,EAAY,UAAA,CAAW,SAAS,CAAA,EAAG;AACtC,IAAA,GAAA,CAAI,OAAO,GAAG,CAAA,CAAE,KAAK,EAAE,KAAA,EAAO,qBAAqB,CAAA;AACnD,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,KAAA,CAAM,SAAS,EAAE,CAAC,CAAA;AAE3C,EAAA,IAAI;AACF,IAAA,MAAM,YAAA,GAAe,MAAM,OAAA,EAAQ,CAAE,cAAc,KAAK,CAAA;AAGxD,IAAA,MAAM,OAAO,MAAM,OAAA,EAAQ,CAAE,OAAA,CAAQ,aAAa,GAAG,CAAA;AAErD,IAAA,GAAA,CAAI,IAAA,GAAO;AAAA,MACT,KAAK,YAAA,CAAa,GAAA;AAAA,MAClB,OAAO,YAAA,CAAa,KAAA;AAAA,MACpB,KAAA,EAAQ,IAAA,CAAK,YAAA,EAAc,KAAA,IAAsB,CAAC,MAAM,CAAA;AAAA,MACxD,KAAA,EAAO,KAAK,YAAA,EAAc;AAAA,KAC5B;AAEA,IAAA,IAAA,EAAK;AAAA,EACP,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,8BAA8B,KAAK,CAAA;AACjD,IAAA,GAAA,CAAI,OAAO,GAAG,CAAA,CAAE,KAAK,EAAE,KAAA,EAAO,iBAAiB,CAAA;AAAA,EACjD;AACF","file":"multi-user.js","sourcesContent":["/**\n * Database Accessors & Initialization\n *\n * This module provides:\n * - `initializeFirebase()` — convenience function to init Firebase from env vars\n * - `getFirestore()`, `getAuth()` — accessors for Firebase services\n * - `db` — lazy Firestore proxy (no eager initialization)\n *\n * The consuming application MUST call `initializeFirebase()` or\n * `admin.initializeApp()` before using any Firebase-dependent features.\n */\n\nimport admin from 'firebase-admin';\n\n/**\n * Initialize Firebase Admin SDK from environment variables.\n *\n * Reads: FIREBASE_PROJECT_ID, FIREBASE_CLIENT_EMAIL, FIREBASE_PRIVATE_KEY,\n * FIREBASE_SERVICE_ACCOUNT_PATH, FIRESTORE_EMULATOR_HOST\n *\n * Safe to call multiple times — returns existing app if already initialized.\n */\nexport function initializeFirebase(): admin.app.App {\n // Already initialized — return existing app\n if (admin.apps.length > 0) {\n return admin.app();\n }\n\n const projectId = process.env.FIREBASE_PROJECT_ID;\n const emulatorHost = process.env.FIRESTORE_EMULATOR_HOST;\n\n // Emulator mode — no credentials needed\n if (emulatorHost) {\n const app = admin.initializeApp({\n projectId: projectId || 'demo-project',\n });\n console.log(`Firebase Admin initialized for emulator: ${emulatorHost}`);\n return app;\n }\n\n // Service account file\n const serviceAccountPath = process.env.FIREBASE_SERVICE_ACCOUNT_PATH;\n if (serviceAccountPath) {\n // Dynamic require for JSON service account file at runtime\n const serviceAccount = require(serviceAccountPath) as Record<string, unknown>;\n return admin.initializeApp({\n credential: admin.credential.cert(serviceAccount),\n projectId,\n });\n }\n\n // Inline credentials\n const clientEmail = process.env.FIREBASE_CLIENT_EMAIL;\n const privateKey = process.env.FIREBASE_PRIVATE_KEY;\n if (projectId && clientEmail && privateKey) {\n return admin.initializeApp({\n credential: admin.credential.cert({\n projectId,\n clientEmail,\n privateKey: privateKey.replace(/\\\\n/g, '\\n'),\n }),\n projectId,\n });\n }\n\n // Application default credentials (Cloud Run, etc.)\n if (projectId) {\n return admin.initializeApp({\n credential: admin.credential.applicationDefault(),\n projectId,\n });\n }\n\n throw new Error(\n '@almadar/server: Cannot initialize Firebase — no credentials found. ' +\n 'Set FIREBASE_PROJECT_ID + FIREBASE_CLIENT_EMAIL + FIREBASE_PRIVATE_KEY, ' +\n 'or FIREBASE_SERVICE_ACCOUNT_PATH, or FIRESTORE_EMULATOR_HOST.'\n );\n}\n\n/**\n * Get the initialized Firebase app.\n * Throws if Firebase Admin SDK has not been initialized.\n */\nfunction getApp(): admin.app.App {\n if (admin.apps.length === 0) {\n throw new Error(\n '@almadar/server: Firebase Admin SDK is not initialized. ' +\n 'Call initializeFirebase() or admin.initializeApp() before using @almadar/server.'\n );\n }\n return admin.app();\n}\n\n/**\n * Get Firestore instance from the pre-initialized Firebase app.\n */\nexport function getFirestore(): admin.firestore.Firestore {\n return getApp().firestore();\n}\n\n/**\n * Get Firebase Auth instance from the pre-initialized Firebase app.\n */\nexport function getAuth(): admin.auth.Auth {\n return getApp().auth();\n}\n\n// Re-export admin for convenience\nexport { admin };\n\n/**\n * Lazy Firestore proxy — resolves on first property access, not at import time.\n * This prevents the \"Firebase not initialized\" error during module loading.\n */\nexport const db = new Proxy({} as admin.firestore.Firestore, {\n get(_target, prop, receiver) {\n const firestore = getFirestore();\n const value = Reflect.get(firestore, prop, receiver);\n return typeof value === 'function' ? value.bind(firestore) : value;\n },\n});\n","/**\n * Multi-User Middleware\n *\n * Provides user isolation and session ownership using Firebase Auth.\n *\n * @packageDocumentation\n */\n\nimport { getMultiUserManager, createUserContext } from '@almadar-io/agent';\nimport { getAuth } from '../lib/db.js';\nimport type { Request, Response, NextFunction } from 'express';\n\n// Extend Express Request to include Firebase user\ndeclare global {\n namespace Express {\n interface Request {\n user?: {\n uid: string;\n email?: string;\n roles?: string[];\n orgId?: string;\n };\n userContext?: {\n userId: string;\n orgId?: string;\n roles?: string[];\n };\n }\n }\n}\n\n/**\n * Middleware to set up user context from Firebase Auth\n */\nexport async function multiUserMiddleware(\n req: Request,\n res: Response,\n next: NextFunction,\n): Promise<void> {\n const userId = req.user?.uid;\n\n if (!userId) {\n res.status(401).json({ error: 'Authentication required' });\n return;\n }\n\n // Create user context\n req.userContext = createUserContext(userId, {\n orgId: req.user?.orgId,\n roles: req.user?.roles ?? ['user'],\n });\n\n // Assign session ownership when creating new sessions\n const originalJson = res.json.bind(res);\n res.json = (body: unknown) => {\n if (body && typeof body === 'object' && 'threadId' in body) {\n const multiUser = getMultiUserManager();\n multiUser.assignSessionOwnership(\n (body as { threadId: string }).threadId,\n userId,\n );\n }\n return originalJson(body);\n };\n\n next();\n}\n\n/**\n * Verify Firebase Auth token from Authorization header\n */\nexport async function verifyFirebaseAuth(\n req: Request,\n res: Response,\n next: NextFunction,\n): Promise<void> {\n const authHeader = req.headers.authorization;\n\n if (!authHeader?.startsWith('Bearer ')) {\n res.status(401).json({ error: 'No token provided' });\n return;\n }\n\n const token = authHeader.split('Bearer ')[1];\n\n try {\n const decodedToken = await getAuth().verifyIdToken(token);\n\n // Get custom claims for roles/org\n const user = await getAuth().getUser(decodedToken.uid);\n\n req.user = {\n uid: decodedToken.uid,\n email: decodedToken.email,\n roles: (user.customClaims?.roles as string[]) ?? ['user'],\n orgId: user.customClaims?.orgId as string,\n };\n\n next();\n } catch (error) {\n console.error('Token verification failed:', error);\n res.status(401).json({ error: 'Invalid token' });\n }\n}\n"]}
@@ -1,62 +0,0 @@
1
- import { Router } from 'express';
2
- import { getObservabilityCollector } from '@almadar-io/agent';
3
-
4
- // src/routes/observability.ts
5
- var router = Router();
6
- router.get("/metrics", async (req, res) => {
7
- try {
8
- const collector = getObservabilityCollector();
9
- const snapshot = collector.getPerformanceSnapshot();
10
- res.json(snapshot);
11
- } catch (error) {
12
- console.error("Metrics error:", error);
13
- res.status(500).json({ error: "Failed to get metrics" });
14
- }
15
- });
16
- router.get("/health", async (req, res) => {
17
- try {
18
- const collector = getObservabilityCollector();
19
- const health = await collector.healthCheck();
20
- const allHealthy = health.every((h) => h.status === "healthy");
21
- res.status(allHealthy ? 200 : 503).json({
22
- status: allHealthy ? "healthy" : "degraded",
23
- timestamp: Date.now(),
24
- checks: health
25
- });
26
- } catch (error) {
27
- console.error("Health check error:", error);
28
- res.status(500).json({
29
- status: "unhealthy",
30
- error: "Health check failed"
31
- });
32
- }
33
- });
34
- router.get("/sessions/:threadId/telemetry", async (req, res) => {
35
- try {
36
- const collector = getObservabilityCollector();
37
- const telemetry = collector.getSessionTelemetry(req.params.threadId);
38
- if (!telemetry) {
39
- res.status(404).json({ error: "Session not found" });
40
- return;
41
- }
42
- res.json(telemetry);
43
- } catch (error) {
44
- console.error("Telemetry error:", error);
45
- res.status(500).json({ error: "Failed to get telemetry" });
46
- }
47
- });
48
- router.get("/active-sessions", async (req, res) => {
49
- try {
50
- const collector = getObservabilityCollector();
51
- const sessions = collector.getActiveSessions();
52
- res.json(sessions);
53
- } catch (error) {
54
- console.error("Active sessions error:", error);
55
- res.status(500).json({ error: "Failed to get active sessions" });
56
- }
57
- });
58
- var observability_default = router;
59
-
60
- export { observability_default as default };
61
- //# sourceMappingURL=observability.js.map
62
- //# sourceMappingURL=observability.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/routes/observability.ts"],"names":[],"mappings":";;;;AAWA,IAAM,SAAoC,MAAA,EAAO;AAKjD,MAAA,CAAO,GAAA,CAAI,UAAA,EAAY,OAAO,GAAA,EAAK,GAAA,KAAQ;AACzC,EAAA,IAAI;AACF,IAAA,MAAM,YAAY,yBAAA,EAA0B;AAC5C,IAAA,MAAM,QAAA,GAAW,UAAU,sBAAA,EAAuB;AAClD,IAAA,GAAA,CAAI,KAAK,QAAQ,CAAA;AAAA,EACnB,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,kBAAkB,KAAK,CAAA;AACrC,IAAA,GAAA,CAAI,OAAO,GAAG,CAAA,CAAE,KAAK,EAAE,KAAA,EAAO,yBAAyB,CAAA;AAAA,EACzD;AACF,CAAC,CAAA;AAKD,MAAA,CAAO,GAAA,CAAI,SAAA,EAAW,OAAO,GAAA,EAAK,GAAA,KAAQ;AACxC,EAAA,IAAI;AACF,IAAA,MAAM,YAAY,yBAAA,EAA0B;AAC5C,IAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,WAAA,EAAY;AAC3C,IAAA,MAAM,aAAa,MAAA,CAAO,KAAA,CAAM,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,SAAS,CAAA;AAE7D,IAAA,GAAA,CAAI,MAAA,CAAO,UAAA,GAAa,GAAA,GAAM,GAAG,EAAE,IAAA,CAAK;AAAA,MACtC,MAAA,EAAQ,aAAa,SAAA,GAAY,UAAA;AAAA,MACjC,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,MACpB,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,uBAAuB,KAAK,CAAA;AAC1C,IAAA,GAAA,CAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK;AAAA,MACnB,MAAA,EAAQ,WAAA;AAAA,MACR,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,EACH;AACF,CAAC,CAAA;AAKD,MAAA,CAAO,GAAA,CAAI,+BAAA,EAAiC,OAAO,GAAA,EAAK,GAAA,KAAQ;AAC9D,EAAA,IAAI;AACF,IAAA,MAAM,YAAY,yBAAA,EAA0B;AAC5C,IAAA,MAAM,SAAA,GAAY,SAAA,CAAU,mBAAA,CAAoB,GAAA,CAAI,OAAO,QAAQ,CAAA;AAEnE,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,GAAA,CAAI,OAAO,GAAG,CAAA,CAAE,KAAK,EAAE,KAAA,EAAO,qBAAqB,CAAA;AACnD,MAAA;AAAA,IACF;AAEA,IAAA,GAAA,CAAI,KAAK,SAAS,CAAA;AAAA,EACpB,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,oBAAoB,KAAK,CAAA;AACvC,IAAA,GAAA,CAAI,OAAO,GAAG,CAAA,CAAE,KAAK,EAAE,KAAA,EAAO,2BAA2B,CAAA;AAAA,EAC3D;AACF,CAAC,CAAA;AAKD,MAAA,CAAO,GAAA,CAAI,kBAAA,EAAoB,OAAO,GAAA,EAAK,GAAA,KAAQ;AACjD,EAAA,IAAI;AACF,IAAA,MAAM,YAAY,yBAAA,EAA0B;AAC5C,IAAA,MAAM,QAAA,GAAW,UAAU,iBAAA,EAAkB;AAC7C,IAAA,GAAA,CAAI,KAAK,QAAQ,CAAA;AAAA,EACnB,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,0BAA0B,KAAK,CAAA;AAC7C,IAAA,GAAA,CAAI,OAAO,GAAG,CAAA,CAAE,KAAK,EAAE,KAAA,EAAO,iCAAiC,CAAA;AAAA,EACjE;AACF,CAAC,CAAA;AAED,IAAO,qBAAA,GAAQ","file":"observability.js","sourcesContent":["/**\n * Observability Routes\n *\n * Provides endpoints for metrics, health checks, and telemetry.\n *\n * @packageDocumentation\n */\n\nimport { Router } from 'express';\nimport { getObservabilityCollector } from '@almadar-io/agent';\n\nconst router: ReturnType<typeof Router> = Router();\n\n/**\n * GET /metrics - Get performance snapshot\n */\nrouter.get('/metrics', async (req, res) => {\n try {\n const collector = getObservabilityCollector();\n const snapshot = collector.getPerformanceSnapshot();\n res.json(snapshot);\n } catch (error) {\n console.error('Metrics error:', error);\n res.status(500).json({ error: 'Failed to get metrics' });\n }\n});\n\n/**\n * GET /health - Get health check\n */\nrouter.get('/health', async (req, res) => {\n try {\n const collector = getObservabilityCollector();\n const health = await collector.healthCheck();\n const allHealthy = health.every((h) => h.status === 'healthy');\n\n res.status(allHealthy ? 200 : 503).json({\n status: allHealthy ? 'healthy' : 'degraded',\n timestamp: Date.now(),\n checks: health,\n });\n } catch (error) {\n console.error('Health check error:', error);\n res.status(500).json({\n status: 'unhealthy',\n error: 'Health check failed',\n });\n }\n});\n\n/**\n * GET /sessions/:threadId/telemetry - Get session telemetry\n */\nrouter.get('/sessions/:threadId/telemetry', async (req, res) => {\n try {\n const collector = getObservabilityCollector();\n const telemetry = collector.getSessionTelemetry(req.params.threadId);\n\n if (!telemetry) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n\n res.json(telemetry);\n } catch (error) {\n console.error('Telemetry error:', error);\n res.status(500).json({ error: 'Failed to get telemetry' });\n }\n});\n\n/**\n * GET /active-sessions - Get active sessions\n */\nrouter.get('/active-sessions', async (req, res) => {\n try {\n const collector = getObservabilityCollector();\n const sessions = collector.getActiveSessions();\n res.json(sessions);\n } catch (error) {\n console.error('Active sessions error:', error);\n res.status(500).json({ error: 'Failed to get active sessions' });\n }\n});\n\nexport default router;\n"]}
@@ -1,77 +0,0 @@
1
- import { getStateSyncManager, getMultiUserManager } from '@almadar-io/agent';
2
- import admin from 'firebase-admin';
3
-
4
- // src/websocket/state-sync.ts
5
- function getApp() {
6
- if (admin.apps.length === 0) {
7
- throw new Error(
8
- "@almadar/server: Firebase Admin SDK is not initialized. Call initializeFirebase() or admin.initializeApp() before using @almadar/server."
9
- );
10
- }
11
- return admin.app();
12
- }
13
- function getFirestore() {
14
- return getApp().firestore();
15
- }
16
- function getAuth() {
17
- return getApp().auth();
18
- }
19
- new Proxy({}, {
20
- get(_target, prop, receiver) {
21
- const firestore = getFirestore();
22
- const value = Reflect.get(firestore, prop, receiver);
23
- return typeof value === "function" ? value.bind(firestore) : value;
24
- }
25
- });
26
-
27
- // src/websocket/state-sync.ts
28
- function setupStateSyncWebSocket(io) {
29
- const stateSync = getStateSyncManager();
30
- io.use(async (socket, next) => {
31
- try {
32
- const token = socket.handshake.auth.token;
33
- if (!token) {
34
- return next(new Error("Authentication required"));
35
- }
36
- const decodedToken = await getAuth().verifyIdToken(token);
37
- const user = await getAuth().getUser(decodedToken.uid);
38
- socket.data.user = {
39
- uid: decodedToken.uid,
40
- roles: user.customClaims?.roles ?? ["user"],
41
- orgId: user.customClaims?.orgId
42
- };
43
- next();
44
- } catch (error) {
45
- console.error("Socket auth failed:", error);
46
- next(new Error("Invalid token"));
47
- }
48
- });
49
- io.on("connection", (socket) => {
50
- const userId = socket.data.user.uid;
51
- const clientId = socket.handshake.auth.clientId;
52
- console.log(`[StateSync] Client ${clientId} connected for user ${userId}`);
53
- stateSync.updateConfig({ clientId });
54
- socket.join(`user:${userId}`);
55
- socket.on("stateChange", (...args) => {
56
- const event = args[0];
57
- const multiUser = getMultiUserManager();
58
- if (!multiUser.isSessionOwner(event.threadId, userId)) {
59
- socket.emit("error", { message: "Not session owner" });
60
- return;
61
- }
62
- stateSync.receiveRemoteChange(event);
63
- socket.to(`user:${userId}`).emit("remoteChange", event);
64
- });
65
- stateSync.on("syncRequired", (changes) => {
66
- socket.emit("syncBatch", changes);
67
- });
68
- socket.on("disconnect", () => {
69
- console.log(`[StateSync] Client ${clientId} disconnected`);
70
- socket.leave(`user:${userId}`);
71
- });
72
- });
73
- }
74
-
75
- export { setupStateSyncWebSocket };
76
- //# sourceMappingURL=state-sync.js.map
77
- //# sourceMappingURL=state-sync.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/lib/db.ts","../../src/websocket/state-sync.ts"],"names":[],"mappings":"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","file":"state-sync.js","sourcesContent":["/**\n * Database Accessors & Initialization\n *\n * This module provides:\n * - `initializeFirebase()` — convenience function to init Firebase from env vars\n * - `getFirestore()`, `getAuth()` — accessors for Firebase services\n * - `db` — lazy Firestore proxy (no eager initialization)\n *\n * The consuming application MUST call `initializeFirebase()` or\n * `admin.initializeApp()` before using any Firebase-dependent features.\n */\n\nimport admin from 'firebase-admin';\n\n/**\n * Initialize Firebase Admin SDK from environment variables.\n *\n * Reads: FIREBASE_PROJECT_ID, FIREBASE_CLIENT_EMAIL, FIREBASE_PRIVATE_KEY,\n * FIREBASE_SERVICE_ACCOUNT_PATH, FIRESTORE_EMULATOR_HOST\n *\n * Safe to call multiple times — returns existing app if already initialized.\n */\nexport function initializeFirebase(): admin.app.App {\n // Already initialized — return existing app\n if (admin.apps.length > 0) {\n return admin.app();\n }\n\n const projectId = process.env.FIREBASE_PROJECT_ID;\n const emulatorHost = process.env.FIRESTORE_EMULATOR_HOST;\n\n // Emulator mode — no credentials needed\n if (emulatorHost) {\n const app = admin.initializeApp({\n projectId: projectId || 'demo-project',\n });\n console.log(`Firebase Admin initialized for emulator: ${emulatorHost}`);\n return app;\n }\n\n // Service account file\n const serviceAccountPath = process.env.FIREBASE_SERVICE_ACCOUNT_PATH;\n if (serviceAccountPath) {\n // Dynamic require for JSON service account file at runtime\n const serviceAccount = require(serviceAccountPath) as Record<string, unknown>;\n return admin.initializeApp({\n credential: admin.credential.cert(serviceAccount),\n projectId,\n });\n }\n\n // Inline credentials\n const clientEmail = process.env.FIREBASE_CLIENT_EMAIL;\n const privateKey = process.env.FIREBASE_PRIVATE_KEY;\n if (projectId && clientEmail && privateKey) {\n return admin.initializeApp({\n credential: admin.credential.cert({\n projectId,\n clientEmail,\n privateKey: privateKey.replace(/\\\\n/g, '\\n'),\n }),\n projectId,\n });\n }\n\n // Application default credentials (Cloud Run, etc.)\n if (projectId) {\n return admin.initializeApp({\n credential: admin.credential.applicationDefault(),\n projectId,\n });\n }\n\n throw new Error(\n '@almadar/server: Cannot initialize Firebase — no credentials found. ' +\n 'Set FIREBASE_PROJECT_ID + FIREBASE_CLIENT_EMAIL + FIREBASE_PRIVATE_KEY, ' +\n 'or FIREBASE_SERVICE_ACCOUNT_PATH, or FIRESTORE_EMULATOR_HOST.'\n );\n}\n\n/**\n * Get the initialized Firebase app.\n * Throws if Firebase Admin SDK has not been initialized.\n */\nfunction getApp(): admin.app.App {\n if (admin.apps.length === 0) {\n throw new Error(\n '@almadar/server: Firebase Admin SDK is not initialized. ' +\n 'Call initializeFirebase() or admin.initializeApp() before using @almadar/server.'\n );\n }\n return admin.app();\n}\n\n/**\n * Get Firestore instance from the pre-initialized Firebase app.\n */\nexport function getFirestore(): admin.firestore.Firestore {\n return getApp().firestore();\n}\n\n/**\n * Get Firebase Auth instance from the pre-initialized Firebase app.\n */\nexport function getAuth(): admin.auth.Auth {\n return getApp().auth();\n}\n\n// Re-export admin for convenience\nexport { admin };\n\n/**\n * Lazy Firestore proxy — resolves on first property access, not at import time.\n * This prevents the \"Firebase not initialized\" error during module loading.\n */\nexport const db = new Proxy({} as admin.firestore.Firestore, {\n get(_target, prop, receiver) {\n const firestore = getFirestore();\n const value = Reflect.get(firestore, prop, receiver);\n return typeof value === 'function' ? value.bind(firestore) : value;\n },\n});\n","/**\n * State Sync WebSocket Handler\n *\n * Provides real-time state synchronization using Socket.IO.\n *\n * @packageDocumentation\n */\n\nimport { getStateSyncManager } from '@almadar-io/agent';\nimport { getMultiUserManager } from '@almadar-io/agent';\nimport { getAuth } from '../lib/db.js';\n\n// Type definitions for Socket.IO (to avoid dependency)\ninterface Socket {\n data: { user: { uid: string; roles: string[]; orgId?: string } };\n handshake: { auth: { token: string; clientId: string } };\n join: (room: string) => void;\n leave: (room: string) => void;\n on: (event: string, handler: (...args: unknown[]) => void) => void;\n emit: (event: string, ...args: unknown[]) => void;\n to: (room: string) => { emit: (event: string, ...args: unknown[]) => void };\n}\n\ninterface SocketServer {\n use: (middleware: (socket: Socket, next: (err?: Error) => void) => void) => void;\n on: (event: string, handler: (socket: Socket) => void) => void;\n}\n\n/**\n * Set up state sync WebSocket with Firebase Auth\n */\nexport function setupStateSyncWebSocket(io: SocketServer): void {\n const stateSync = getStateSyncManager();\n\n // Firebase Auth middleware for Socket.IO\n io.use(async (socket, next) => {\n try {\n const token = socket.handshake.auth.token as string;\n if (!token) {\n return next(new Error('Authentication required'));\n }\n\n const decodedToken = await getAuth().verifyIdToken(token);\n const user = await getAuth().getUser(decodedToken.uid);\n\n socket.data.user = {\n uid: decodedToken.uid,\n roles: (user.customClaims?.roles as string[]) ?? ['user'],\n orgId: user.customClaims?.orgId as string,\n };\n\n next();\n } catch (error) {\n console.error('Socket auth failed:', error);\n next(new Error('Invalid token'));\n }\n });\n\n io.on('connection', (socket: Socket) => {\n const userId = socket.data.user.uid;\n const clientId = socket.handshake.auth.clientId;\n\n console.log(`[StateSync] Client ${clientId} connected for user ${userId}`);\n\n // Update client ID in sync manager\n stateSync.updateConfig({ clientId });\n\n // Join user's room for targeted updates\n socket.join(`user:${userId}`);\n\n // Listen for state changes from client\n socket.on('stateChange', (...args: unknown[]) => {\n const event = args[0] as { threadId: string };\n \n // Verify ownership\n const multiUser = getMultiUserManager();\n if (!multiUser.isSessionOwner(event.threadId, userId)) {\n socket.emit('error', { message: 'Not session owner' });\n return;\n }\n\n // Process through sync manager\n stateSync.receiveRemoteChange(event as unknown as import('@almadar-io/agent').StateChangeEvent);\n\n // Broadcast to other clients of same user\n socket.to(`user:${userId}`).emit('remoteChange', event);\n });\n\n // Handle sync required events from agent\n stateSync.on('syncRequired', (changes: unknown[]) => {\n socket.emit('syncBatch', changes);\n });\n\n socket.on('disconnect', () => {\n console.log(`[StateSync] Client ${clientId} disconnected`);\n socket.leave(`user:${userId}`);\n });\n });\n}\n"]}