@affectively/dash 5.3.0 → 5.3.1
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/dist/index.d.ts +62 -0
- package/dist/index.js +31 -0
- package/dist/sync/index.d.ts +6 -0
- package/dist/sync/index.js +4 -0
- package/package.json +45 -66
- package/README.md +0 -193
- package/dist/src/api/firebase/auth/index.d.ts +0 -137
- package/dist/src/api/firebase/auth/index.js +0 -352
- package/dist/src/api/firebase/auth/providers.d.ts +0 -254
- package/dist/src/api/firebase/auth/providers.js +0 -518
- package/dist/src/api/firebase/database/index.d.ts +0 -108
- package/dist/src/api/firebase/database/index.js +0 -368
- package/dist/src/api/firebase/errors.d.ts +0 -15
- package/dist/src/api/firebase/errors.js +0 -215
- package/dist/src/api/firebase/firestore/data-types.d.ts +0 -116
- package/dist/src/api/firebase/firestore/data-types.js +0 -280
- package/dist/src/api/firebase/firestore/index.d.ts +0 -7
- package/dist/src/api/firebase/firestore/index.js +0 -13
- package/dist/src/api/firebase/firestore/listeners.d.ts +0 -20
- package/dist/src/api/firebase/firestore/listeners.js +0 -50
- package/dist/src/api/firebase/firestore/operations.d.ts +0 -123
- package/dist/src/api/firebase/firestore/operations.js +0 -490
- package/dist/src/api/firebase/firestore/query.d.ts +0 -118
- package/dist/src/api/firebase/firestore/query.js +0 -418
- package/dist/src/api/firebase/index.d.ts +0 -11
- package/dist/src/api/firebase/index.js +0 -17
- package/dist/src/api/firebase/storage/index.d.ts +0 -100
- package/dist/src/api/firebase/storage/index.js +0 -286
- package/dist/src/api/firebase/types.d.ts +0 -341
- package/dist/src/api/firebase/types.js +0 -4
- package/dist/src/auth/manager.d.ts +0 -182
- package/dist/src/auth/manager.js +0 -598
- package/dist/src/engine/ai.d.ts +0 -10
- package/dist/src/engine/ai.js +0 -76
- package/dist/src/engine/sqlite.d.ts +0 -346
- package/dist/src/engine/sqlite.js +0 -1325
- package/dist/src/engine/vec_extension.d.ts +0 -5
- package/dist/src/engine/vec_extension.js +0 -10
- package/dist/src/index.d.ts +0 -15
- package/dist/src/index.js +0 -24
- package/dist/src/mcp/server.d.ts +0 -8
- package/dist/src/mcp/server.js +0 -87
- package/dist/src/reactivity/signal.d.ts +0 -3
- package/dist/src/reactivity/signal.js +0 -31
- package/dist/src/schema/lens.d.ts +0 -29
- package/dist/src/schema/lens.js +0 -122
- package/dist/src/sync/aeon/config.d.ts +0 -21
- package/dist/src/sync/aeon/config.js +0 -14
- package/dist/src/sync/aeon/delta-adapter.d.ts +0 -62
- package/dist/src/sync/aeon/delta-adapter.js +0 -98
- package/dist/src/sync/aeon/index.d.ts +0 -18
- package/dist/src/sync/aeon/index.js +0 -19
- package/dist/src/sync/aeon/offline-adapter.d.ts +0 -110
- package/dist/src/sync/aeon/offline-adapter.js +0 -227
- package/dist/src/sync/aeon/presence-adapter.d.ts +0 -114
- package/dist/src/sync/aeon/presence-adapter.js +0 -157
- package/dist/src/sync/aeon/schema-adapter.d.ts +0 -95
- package/dist/src/sync/aeon/schema-adapter.js +0 -163
- package/dist/src/sync/backup.d.ts +0 -12
- package/dist/src/sync/backup.js +0 -44
- package/dist/src/sync/connection.d.ts +0 -20
- package/dist/src/sync/connection.js +0 -50
- package/dist/src/sync/d1-provider.d.ts +0 -97
- package/dist/src/sync/d1-provider.js +0 -345
- package/dist/src/sync/hybrid-provider.d.ts +0 -172
- package/dist/src/sync/hybrid-provider.js +0 -477
- package/dist/src/sync/provider.d.ts +0 -11
- package/dist/src/sync/provider.js +0 -67
- package/dist/src/sync/verify.d.ts +0 -1
- package/dist/src/sync/verify.js +0 -23
- package/dist/tsconfig.tsbuildinfo +0 -1
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Offline Adapter for Dash
|
|
3
|
-
*
|
|
4
|
-
* Wraps Aeon's OfflineOperationQueue to provide offline-first
|
|
5
|
-
* operation queuing for Yjs documents.
|
|
6
|
-
*/
|
|
7
|
-
import { type OfflineOperation, type OfflineQueueStats, type OperationPriority } from '@affectively/aeon';
|
|
8
|
-
import * as Y from 'yjs';
|
|
9
|
-
/**
|
|
10
|
-
* Adapter that queues Yjs updates when offline
|
|
11
|
-
*/
|
|
12
|
-
export declare class DashOfflineAdapter {
|
|
13
|
-
private queue;
|
|
14
|
-
private doc;
|
|
15
|
-
private roomId;
|
|
16
|
-
private storageKey;
|
|
17
|
-
private isOnline;
|
|
18
|
-
private processingQueue;
|
|
19
|
-
constructor(doc: Y.Doc, roomId: string, maxQueueSize?: number, maxRetries?: number);
|
|
20
|
-
/**
|
|
21
|
-
* Setup network status listeners
|
|
22
|
-
*/
|
|
23
|
-
private setupNetworkListeners;
|
|
24
|
-
/**
|
|
25
|
-
* Setup queue event handlers
|
|
26
|
-
*/
|
|
27
|
-
private setupQueueEvents;
|
|
28
|
-
/**
|
|
29
|
-
* Queue a Yjs update for later sync
|
|
30
|
-
*/
|
|
31
|
-
queueUpdate(update: Uint8Array, priority?: OperationPriority): OfflineOperation;
|
|
32
|
-
/**
|
|
33
|
-
* Check if we should queue (offline) or send directly
|
|
34
|
-
*/
|
|
35
|
-
shouldQueue(): boolean;
|
|
36
|
-
/**
|
|
37
|
-
* Process queued operations
|
|
38
|
-
* @param sendFn Function to send updates (typically HybridProvider.send)
|
|
39
|
-
*/
|
|
40
|
-
processQueue(sendFn?: (update: Uint8Array) => Promise<void>): Promise<ProcessQueueResult>;
|
|
41
|
-
/**
|
|
42
|
-
* Get queue statistics
|
|
43
|
-
*/
|
|
44
|
-
getStats(): OfflineQueueStats;
|
|
45
|
-
/**
|
|
46
|
-
* Get pending operation count
|
|
47
|
-
*/
|
|
48
|
-
getPendingCount(): number;
|
|
49
|
-
/**
|
|
50
|
-
* Check if online
|
|
51
|
-
*/
|
|
52
|
-
getOnlineStatus(): boolean;
|
|
53
|
-
/**
|
|
54
|
-
* Retry failed operations
|
|
55
|
-
*/
|
|
56
|
-
retryFailed(): void;
|
|
57
|
-
/**
|
|
58
|
-
* Clear failed operations
|
|
59
|
-
*/
|
|
60
|
-
clearFailed(): void;
|
|
61
|
-
/**
|
|
62
|
-
* Clear all queued operations
|
|
63
|
-
*/
|
|
64
|
-
clear(): void;
|
|
65
|
-
/**
|
|
66
|
-
* Subscribe to queue events
|
|
67
|
-
*/
|
|
68
|
-
on<E extends keyof OfflineQueueEvents>(event: E, handler: OfflineQueueEvents[E]): void;
|
|
69
|
-
/**
|
|
70
|
-
* Unsubscribe from queue events
|
|
71
|
-
*/
|
|
72
|
-
off<E extends keyof OfflineQueueEvents>(event: E, handler: OfflineQueueEvents[E]): void;
|
|
73
|
-
/**
|
|
74
|
-
* Persist queue to localStorage
|
|
75
|
-
*/
|
|
76
|
-
private persistQueue;
|
|
77
|
-
/**
|
|
78
|
-
* Load queue from localStorage
|
|
79
|
-
*/
|
|
80
|
-
private loadPersistedQueue;
|
|
81
|
-
/**
|
|
82
|
-
* Clear persisted queue
|
|
83
|
-
*/
|
|
84
|
-
private clearPersistedQueue;
|
|
85
|
-
/**
|
|
86
|
-
* Cleanup
|
|
87
|
-
*/
|
|
88
|
-
destroy(): void;
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Result of processing the queue
|
|
92
|
-
*/
|
|
93
|
-
export interface ProcessQueueResult {
|
|
94
|
-
synced: number;
|
|
95
|
-
failed: number;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Offline queue event types
|
|
99
|
-
*/
|
|
100
|
-
export interface OfflineQueueEvents {
|
|
101
|
-
'operation-added': (operation: OfflineOperation) => void;
|
|
102
|
-
'operation-synced': (operation: OfflineOperation) => void;
|
|
103
|
-
'operation-failed': (operation: OfflineOperation, error: Error) => void;
|
|
104
|
-
'queue-empty': () => void;
|
|
105
|
-
'sync-started': () => void;
|
|
106
|
-
'sync-completed': (stats: {
|
|
107
|
-
synced: number;
|
|
108
|
-
failed: number;
|
|
109
|
-
}) => void;
|
|
110
|
-
}
|
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Offline Adapter for Dash
|
|
3
|
-
*
|
|
4
|
-
* Wraps Aeon's OfflineOperationQueue to provide offline-first
|
|
5
|
-
* operation queuing for Yjs documents.
|
|
6
|
-
*/
|
|
7
|
-
import { OfflineOperationQueue, } from '@affectively/aeon';
|
|
8
|
-
import * as Y from 'yjs';
|
|
9
|
-
const STORAGE_KEY_PREFIX = 'dash-offline-queue-';
|
|
10
|
-
/**
|
|
11
|
-
* Adapter that queues Yjs updates when offline
|
|
12
|
-
*/
|
|
13
|
-
export class DashOfflineAdapter {
|
|
14
|
-
queue;
|
|
15
|
-
doc;
|
|
16
|
-
roomId;
|
|
17
|
-
storageKey;
|
|
18
|
-
isOnline = true;
|
|
19
|
-
processingQueue = false;
|
|
20
|
-
constructor(doc, roomId, maxQueueSize = 1000, maxRetries = 3) {
|
|
21
|
-
this.queue = new OfflineOperationQueue(maxQueueSize, maxRetries);
|
|
22
|
-
this.doc = doc;
|
|
23
|
-
this.roomId = roomId;
|
|
24
|
-
this.storageKey = `${STORAGE_KEY_PREFIX}${roomId}`;
|
|
25
|
-
// Load persisted queue on startup
|
|
26
|
-
this.loadPersistedQueue();
|
|
27
|
-
// Setup network status listeners
|
|
28
|
-
this.setupNetworkListeners();
|
|
29
|
-
// Setup queue event handlers
|
|
30
|
-
this.setupQueueEvents();
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Setup network status listeners
|
|
34
|
-
*/
|
|
35
|
-
setupNetworkListeners() {
|
|
36
|
-
if (typeof window !== 'undefined') {
|
|
37
|
-
if (typeof navigator !== 'undefined' && typeof navigator.onLine === 'boolean') {
|
|
38
|
-
this.isOnline = navigator.onLine;
|
|
39
|
-
}
|
|
40
|
-
if (typeof window.addEventListener === 'function') {
|
|
41
|
-
window.addEventListener('online', () => {
|
|
42
|
-
this.isOnline = true;
|
|
43
|
-
this.processQueue();
|
|
44
|
-
});
|
|
45
|
-
window.addEventListener('offline', () => {
|
|
46
|
-
this.isOnline = false;
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Setup queue event handlers
|
|
53
|
-
*/
|
|
54
|
-
setupQueueEvents() {
|
|
55
|
-
this.queue.on('operation-synced', (operation) => {
|
|
56
|
-
this.persistQueue();
|
|
57
|
-
});
|
|
58
|
-
this.queue.on('operation-failed', (operation, error) => {
|
|
59
|
-
console.warn(`[DashOfflineAdapter] Operation ${operation.id} failed: ${error.message}`);
|
|
60
|
-
this.persistQueue();
|
|
61
|
-
});
|
|
62
|
-
this.queue.on('queue-empty', () => {
|
|
63
|
-
this.clearPersistedQueue();
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Queue a Yjs update for later sync
|
|
68
|
-
*/
|
|
69
|
-
queueUpdate(update, priority = 'normal') {
|
|
70
|
-
const operation = this.queue.enqueue('update', { update: Array.from(update) }, this.roomId, priority);
|
|
71
|
-
this.persistQueue();
|
|
72
|
-
return operation;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Check if we should queue (offline) or send directly
|
|
76
|
-
*/
|
|
77
|
-
shouldQueue() {
|
|
78
|
-
return !this.isOnline;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Process queued operations
|
|
82
|
-
* @param sendFn Function to send updates (typically HybridProvider.send)
|
|
83
|
-
*/
|
|
84
|
-
async processQueue(sendFn) {
|
|
85
|
-
if (!this.isOnline || this.processingQueue) {
|
|
86
|
-
return { synced: 0, failed: 0 };
|
|
87
|
-
}
|
|
88
|
-
this.processingQueue = true;
|
|
89
|
-
let synced = 0;
|
|
90
|
-
let failed = 0;
|
|
91
|
-
try {
|
|
92
|
-
while (true) {
|
|
93
|
-
const batch = this.queue.getNextBatch(10);
|
|
94
|
-
if (batch.length === 0)
|
|
95
|
-
break;
|
|
96
|
-
const ids = batch.map((op) => op.id);
|
|
97
|
-
this.queue.markSyncing(ids);
|
|
98
|
-
for (const operation of batch) {
|
|
99
|
-
try {
|
|
100
|
-
const update = new Uint8Array(operation.data.update);
|
|
101
|
-
if (sendFn) {
|
|
102
|
-
// Send via provided function
|
|
103
|
-
await sendFn(update);
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
106
|
-
// Apply locally if no send function
|
|
107
|
-
Y.applyUpdate(this.doc, update);
|
|
108
|
-
}
|
|
109
|
-
this.queue.markSynced(operation.id);
|
|
110
|
-
synced++;
|
|
111
|
-
}
|
|
112
|
-
catch (error) {
|
|
113
|
-
this.queue.markFailed(operation.id, error);
|
|
114
|
-
failed++;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
finally {
|
|
120
|
-
this.processingQueue = false;
|
|
121
|
-
this.persistQueue();
|
|
122
|
-
}
|
|
123
|
-
return { synced, failed };
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Get queue statistics
|
|
127
|
-
*/
|
|
128
|
-
getStats() {
|
|
129
|
-
return this.queue.getStats();
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Get pending operation count
|
|
133
|
-
*/
|
|
134
|
-
getPendingCount() {
|
|
135
|
-
return this.queue.getPendingCount();
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Check if online
|
|
139
|
-
*/
|
|
140
|
-
getOnlineStatus() {
|
|
141
|
-
return this.isOnline;
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Retry failed operations
|
|
145
|
-
*/
|
|
146
|
-
retryFailed() {
|
|
147
|
-
this.queue.retryFailed();
|
|
148
|
-
this.persistQueue();
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Clear failed operations
|
|
152
|
-
*/
|
|
153
|
-
clearFailed() {
|
|
154
|
-
this.queue.clearFailed();
|
|
155
|
-
this.persistQueue();
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Clear all queued operations
|
|
159
|
-
*/
|
|
160
|
-
clear() {
|
|
161
|
-
this.queue.clear();
|
|
162
|
-
this.clearPersistedQueue();
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Subscribe to queue events
|
|
166
|
-
*/
|
|
167
|
-
on(event, handler) {
|
|
168
|
-
this.queue.on(event, handler);
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Unsubscribe from queue events
|
|
172
|
-
*/
|
|
173
|
-
off(event, handler) {
|
|
174
|
-
this.queue.off(event, handler);
|
|
175
|
-
}
|
|
176
|
-
// ============================================
|
|
177
|
-
// Persistence
|
|
178
|
-
// ============================================
|
|
179
|
-
/**
|
|
180
|
-
* Persist queue to localStorage
|
|
181
|
-
*/
|
|
182
|
-
persistQueue() {
|
|
183
|
-
if (typeof localStorage !== 'undefined') {
|
|
184
|
-
try {
|
|
185
|
-
const operations = this.queue.export();
|
|
186
|
-
localStorage.setItem(this.storageKey, JSON.stringify(operations));
|
|
187
|
-
}
|
|
188
|
-
catch (error) {
|
|
189
|
-
console.warn('[DashOfflineAdapter] Failed to persist queue:', error);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
/**
|
|
194
|
-
* Load queue from localStorage
|
|
195
|
-
*/
|
|
196
|
-
loadPersistedQueue() {
|
|
197
|
-
if (typeof localStorage !== 'undefined') {
|
|
198
|
-
try {
|
|
199
|
-
const stored = localStorage.getItem(this.storageKey);
|
|
200
|
-
if (stored) {
|
|
201
|
-
const operations = JSON.parse(stored);
|
|
202
|
-
this.queue.import(operations);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
catch (error) {
|
|
206
|
-
console.warn('[DashOfflineAdapter] Failed to load persisted queue:', error);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Clear persisted queue
|
|
212
|
-
*/
|
|
213
|
-
clearPersistedQueue() {
|
|
214
|
-
if (typeof localStorage !== 'undefined') {
|
|
215
|
-
localStorage.removeItem(this.storageKey);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* Cleanup
|
|
220
|
-
*/
|
|
221
|
-
destroy() {
|
|
222
|
-
this.queue.clear();
|
|
223
|
-
if (typeof window !== 'undefined') {
|
|
224
|
-
// Note: Can't easily remove anonymous listeners, but they'll be GC'd
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Presence Adapter for Dash
|
|
3
|
-
*
|
|
4
|
-
* Bridges Yjs awareness protocol with Aeon's AgentPresenceManager.
|
|
5
|
-
* Provides rich presence features: cursor tracking, active sections, roles.
|
|
6
|
-
*/
|
|
7
|
-
import { type AgentPresence } from '@affectively/aeon';
|
|
8
|
-
import type { Awareness } from 'y-protocols/awareness';
|
|
9
|
-
/**
|
|
10
|
-
* Adapter that syncs Yjs awareness with Aeon presence
|
|
11
|
-
*/
|
|
12
|
-
export declare class DashPresenceAdapter {
|
|
13
|
-
private aeonPresence;
|
|
14
|
-
private yjsAwareness;
|
|
15
|
-
private localAgentId;
|
|
16
|
-
private roomId;
|
|
17
|
-
constructor(roomId: string, awareness: Awareness);
|
|
18
|
-
/**
|
|
19
|
-
* Sync Yjs awareness updates to Aeon presence
|
|
20
|
-
*/
|
|
21
|
-
private setupYjsToAeonSync;
|
|
22
|
-
/**
|
|
23
|
-
* Sync Aeon presence updates back to Yjs awareness
|
|
24
|
-
*/
|
|
25
|
-
private setupAeonToYjsSync;
|
|
26
|
-
/**
|
|
27
|
-
* Update local cursor position
|
|
28
|
-
*/
|
|
29
|
-
updateCursor(x: number, y: number, path: string): void;
|
|
30
|
-
/**
|
|
31
|
-
* Update local active section
|
|
32
|
-
*/
|
|
33
|
-
updateActiveSection(section: string): void;
|
|
34
|
-
/**
|
|
35
|
-
* Update local user info
|
|
36
|
-
*/
|
|
37
|
-
updateUserInfo(name: string, role?: AgentPresence['role']): void;
|
|
38
|
-
/**
|
|
39
|
-
* Get all online agents
|
|
40
|
-
*/
|
|
41
|
-
getOnlineAgents(): AgentPresence[];
|
|
42
|
-
/**
|
|
43
|
-
* Get all agents (including offline)
|
|
44
|
-
*/
|
|
45
|
-
getAllAgents(): AgentPresence[];
|
|
46
|
-
/**
|
|
47
|
-
* Get presence for specific agent
|
|
48
|
-
*/
|
|
49
|
-
getPresence(agentId: string): AgentPresence | undefined;
|
|
50
|
-
/**
|
|
51
|
-
* Get agents in a specific section
|
|
52
|
-
*/
|
|
53
|
-
getAgentsInSection(section: string): AgentPresence[];
|
|
54
|
-
/**
|
|
55
|
-
* Get presence statistics
|
|
56
|
-
*/
|
|
57
|
-
getStats(): {
|
|
58
|
-
total: number;
|
|
59
|
-
online: number;
|
|
60
|
-
away: number;
|
|
61
|
-
offline: number;
|
|
62
|
-
reconnecting: number;
|
|
63
|
-
byRole: Record<string, number>;
|
|
64
|
-
};
|
|
65
|
-
/**
|
|
66
|
-
* Get local agent ID
|
|
67
|
-
*/
|
|
68
|
-
getLocalAgentId(): string;
|
|
69
|
-
/**
|
|
70
|
-
* Subscribe to presence events
|
|
71
|
-
*/
|
|
72
|
-
on<E extends keyof PresenceEvents>(event: E, handler: PresenceEvents[E]): void;
|
|
73
|
-
/**
|
|
74
|
-
* Unsubscribe from presence events
|
|
75
|
-
*/
|
|
76
|
-
off<E extends keyof PresenceEvents>(event: E, handler: PresenceEvents[E]): void;
|
|
77
|
-
/**
|
|
78
|
-
* Cleanup
|
|
79
|
-
*/
|
|
80
|
-
destroy(): void;
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Presence event types
|
|
84
|
-
*/
|
|
85
|
-
export interface PresenceEvents {
|
|
86
|
-
presence_updated: (data: {
|
|
87
|
-
agentId: string;
|
|
88
|
-
presence: AgentPresence;
|
|
89
|
-
}) => void;
|
|
90
|
-
agent_joined: (data: {
|
|
91
|
-
agentId: string;
|
|
92
|
-
presence: AgentPresence;
|
|
93
|
-
}) => void;
|
|
94
|
-
agent_left: (data: {
|
|
95
|
-
agentId: string;
|
|
96
|
-
presence: AgentPresence;
|
|
97
|
-
}) => void;
|
|
98
|
-
cursor_updated: (data: {
|
|
99
|
-
agentId: string;
|
|
100
|
-
cursorPosition: {
|
|
101
|
-
x: number;
|
|
102
|
-
y: number;
|
|
103
|
-
path: string;
|
|
104
|
-
};
|
|
105
|
-
}) => void;
|
|
106
|
-
section_updated: (data: {
|
|
107
|
-
agentId: string;
|
|
108
|
-
activeSection: string;
|
|
109
|
-
}) => void;
|
|
110
|
-
status_updated: (data: {
|
|
111
|
-
agentId: string;
|
|
112
|
-
status: AgentPresence['status'];
|
|
113
|
-
}) => void;
|
|
114
|
-
}
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Presence Adapter for Dash
|
|
3
|
-
*
|
|
4
|
-
* Bridges Yjs awareness protocol with Aeon's AgentPresenceManager.
|
|
5
|
-
* Provides rich presence features: cursor tracking, active sections, roles.
|
|
6
|
-
*/
|
|
7
|
-
import { AgentPresenceManager, } from '@affectively/aeon';
|
|
8
|
-
/**
|
|
9
|
-
* Adapter that syncs Yjs awareness with Aeon presence
|
|
10
|
-
*/
|
|
11
|
-
export class DashPresenceAdapter {
|
|
12
|
-
aeonPresence;
|
|
13
|
-
yjsAwareness;
|
|
14
|
-
localAgentId;
|
|
15
|
-
roomId;
|
|
16
|
-
constructor(roomId, awareness) {
|
|
17
|
-
this.roomId = roomId;
|
|
18
|
-
this.yjsAwareness = awareness;
|
|
19
|
-
this.localAgentId = `agent-${awareness.clientID}`;
|
|
20
|
-
this.aeonPresence = new AgentPresenceManager(roomId);
|
|
21
|
-
// Register local agent
|
|
22
|
-
this.aeonPresence.agentJoined(this.localAgentId, `User ${awareness.clientID}`, 'user');
|
|
23
|
-
// Bidirectional sync setup
|
|
24
|
-
this.setupYjsToAeonSync();
|
|
25
|
-
this.setupAeonToYjsSync();
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Sync Yjs awareness updates to Aeon presence
|
|
29
|
-
*/
|
|
30
|
-
setupYjsToAeonSync() {
|
|
31
|
-
this.yjsAwareness.on('update', ({ added, updated, removed }) => {
|
|
32
|
-
const states = this.yjsAwareness.getStates();
|
|
33
|
-
// Handle added/updated
|
|
34
|
-
for (const clientId of [...added, ...updated]) {
|
|
35
|
-
const state = states.get(clientId);
|
|
36
|
-
if (state) {
|
|
37
|
-
const agentId = `agent-${clientId}`;
|
|
38
|
-
if (added.includes(clientId)) {
|
|
39
|
-
this.aeonPresence.agentJoined(agentId, state.user?.name || `User ${clientId}`, state.user?.role || 'user', state.metadata);
|
|
40
|
-
}
|
|
41
|
-
// Sync cursor and section if present
|
|
42
|
-
if (state.cursor) {
|
|
43
|
-
this.aeonPresence.updateCursor(agentId, state.cursor.x ?? 0, state.cursor.y ?? 0, state.cursor.path ?? '');
|
|
44
|
-
}
|
|
45
|
-
if (state.activeSection) {
|
|
46
|
-
this.aeonPresence.updateActiveSection(agentId, state.activeSection);
|
|
47
|
-
}
|
|
48
|
-
// Heartbeat to keep presence alive
|
|
49
|
-
this.aeonPresence.heartbeat(agentId);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
// Handle removed
|
|
53
|
-
for (const clientId of removed) {
|
|
54
|
-
this.aeonPresence.agentLeft(`agent-${clientId}`);
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Sync Aeon presence updates back to Yjs awareness
|
|
60
|
-
*/
|
|
61
|
-
setupAeonToYjsSync() {
|
|
62
|
-
// When local presence updates via Aeon API, reflect to Yjs
|
|
63
|
-
this.aeonPresence.on('cursor_updated', ({ agentId, cursorPosition }) => {
|
|
64
|
-
if (agentId === this.localAgentId) {
|
|
65
|
-
this.yjsAwareness.setLocalStateField('cursor', cursorPosition);
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
this.aeonPresence.on('section_updated', ({ agentId, activeSection }) => {
|
|
69
|
-
if (agentId === this.localAgentId) {
|
|
70
|
-
this.yjsAwareness.setLocalStateField('activeSection', activeSection);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
// ============================================
|
|
75
|
-
// Rich Presence API
|
|
76
|
-
// ============================================
|
|
77
|
-
/**
|
|
78
|
-
* Update local cursor position
|
|
79
|
-
*/
|
|
80
|
-
updateCursor(x, y, path) {
|
|
81
|
-
this.aeonPresence.updateCursor(this.localAgentId, x, y, path);
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Update local active section
|
|
85
|
-
*/
|
|
86
|
-
updateActiveSection(section) {
|
|
87
|
-
this.aeonPresence.updateActiveSection(this.localAgentId, section);
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Update local user info
|
|
91
|
-
*/
|
|
92
|
-
updateUserInfo(name, role = 'user') {
|
|
93
|
-
this.aeonPresence.updatePresence(this.localAgentId, {
|
|
94
|
-
agentId: this.localAgentId,
|
|
95
|
-
name,
|
|
96
|
-
role,
|
|
97
|
-
status: 'online',
|
|
98
|
-
});
|
|
99
|
-
// Also sync to Yjs awareness
|
|
100
|
-
this.yjsAwareness.setLocalStateField('user', { name, role });
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Get all online agents
|
|
104
|
-
*/
|
|
105
|
-
getOnlineAgents() {
|
|
106
|
-
return this.aeonPresence.getOnlineAgents();
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Get all agents (including offline)
|
|
110
|
-
*/
|
|
111
|
-
getAllAgents() {
|
|
112
|
-
return this.aeonPresence.getAllAgents();
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Get presence for specific agent
|
|
116
|
-
*/
|
|
117
|
-
getPresence(agentId) {
|
|
118
|
-
return this.aeonPresence.getPresence(agentId);
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Get agents in a specific section
|
|
122
|
-
*/
|
|
123
|
-
getAgentsInSection(section) {
|
|
124
|
-
return this.aeonPresence.getInSection(section);
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Get presence statistics
|
|
128
|
-
*/
|
|
129
|
-
getStats() {
|
|
130
|
-
return this.aeonPresence.getPresenceStats();
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Get local agent ID
|
|
134
|
-
*/
|
|
135
|
-
getLocalAgentId() {
|
|
136
|
-
return this.localAgentId;
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Subscribe to presence events
|
|
140
|
-
*/
|
|
141
|
-
on(event, handler) {
|
|
142
|
-
this.aeonPresence.on(event, handler);
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Unsubscribe from presence events
|
|
146
|
-
*/
|
|
147
|
-
off(event, handler) {
|
|
148
|
-
this.aeonPresence.off(event, handler);
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Cleanup
|
|
152
|
-
*/
|
|
153
|
-
destroy() {
|
|
154
|
-
this.aeonPresence.agentLeft(this.localAgentId);
|
|
155
|
-
this.aeonPresence.destroy();
|
|
156
|
-
}
|
|
157
|
-
}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Schema Adapter for Dash
|
|
3
|
-
*
|
|
4
|
-
* Bridges Aeon's SchemaVersionManager with Dash's LensEngine.
|
|
5
|
-
* Provides migration tracking, version compatibility checks, and audit trails.
|
|
6
|
-
*/
|
|
7
|
-
import { type SchemaVersion, type Migration, type MigrationResult } from '@affectively/aeon';
|
|
8
|
-
import { LensEngine, type LensOp } from '../../schema/lens.js';
|
|
9
|
-
/**
|
|
10
|
-
* Adapter that bridges Aeon versioning with Dash's Lens system
|
|
11
|
-
*/
|
|
12
|
-
export declare class DashSchemaAdapter {
|
|
13
|
-
private versionManager;
|
|
14
|
-
private migrationEngine;
|
|
15
|
-
private migrationTracker;
|
|
16
|
-
private lensEngine;
|
|
17
|
-
constructor(lensEngine: LensEngine);
|
|
18
|
-
/**
|
|
19
|
-
* Register a schema version with associated Lens operations
|
|
20
|
-
*/
|
|
21
|
-
registerVersion(version: string, description: string, lensOps?: LensOp[], breaking?: boolean): void;
|
|
22
|
-
/**
|
|
23
|
-
* Register a migration for a version upgrade
|
|
24
|
-
*/
|
|
25
|
-
registerMigration(id: string, fromVersion: string, toVersion: string, migrate: (data: unknown) => unknown, rollback?: (data: unknown) => unknown): void;
|
|
26
|
-
/**
|
|
27
|
-
* Execute a migration on data
|
|
28
|
-
*/
|
|
29
|
-
executeMigration(migrationId: string, data: unknown): Promise<MigrationResult>;
|
|
30
|
-
/**
|
|
31
|
-
* Rollback a migration
|
|
32
|
-
*/
|
|
33
|
-
rollbackMigration(migrationId: string, data: unknown): Promise<MigrationResult>;
|
|
34
|
-
/**
|
|
35
|
-
* Migrate data using Lens transformations
|
|
36
|
-
*/
|
|
37
|
-
migrateWithLens(data: Record<string, unknown>, fromVersion: number, toVersion: number): Record<string, unknown>;
|
|
38
|
-
/**
|
|
39
|
-
* Get current version
|
|
40
|
-
*/
|
|
41
|
-
getCurrentVersion(): SchemaVersion;
|
|
42
|
-
/**
|
|
43
|
-
* Get a specific version by string
|
|
44
|
-
*/
|
|
45
|
-
getVersion(version: string): SchemaVersion | undefined;
|
|
46
|
-
/**
|
|
47
|
-
* Get migration by ID
|
|
48
|
-
*/
|
|
49
|
-
getMigration(id: string): Migration | undefined;
|
|
50
|
-
/**
|
|
51
|
-
* Check if migration is needed
|
|
52
|
-
*/
|
|
53
|
-
needsMigration(fromVersion: string, toVersion: string): boolean;
|
|
54
|
-
/**
|
|
55
|
-
* Get migration path between versions
|
|
56
|
-
*/
|
|
57
|
-
getMigrationPath(fromVersion: string, toVersion: string): SchemaVersion[];
|
|
58
|
-
/**
|
|
59
|
-
* Get pending migrations
|
|
60
|
-
*/
|
|
61
|
-
getPendingMigrations(): Migration[];
|
|
62
|
-
/**
|
|
63
|
-
* Get migration statistics
|
|
64
|
-
*/
|
|
65
|
-
getStatistics(): {
|
|
66
|
-
engine: {
|
|
67
|
-
totalExecuted: number;
|
|
68
|
-
successful: number;
|
|
69
|
-
failed: number;
|
|
70
|
-
successRate: number;
|
|
71
|
-
totalDurationMs: number;
|
|
72
|
-
averageDurationMs: number;
|
|
73
|
-
totalAffected: number;
|
|
74
|
-
};
|
|
75
|
-
tracker: {
|
|
76
|
-
total: number;
|
|
77
|
-
applied: number;
|
|
78
|
-
failed: number;
|
|
79
|
-
pending: number;
|
|
80
|
-
rolledBack: number;
|
|
81
|
-
successRate: number;
|
|
82
|
-
totalDurationMs: number;
|
|
83
|
-
averageDurationMs: number;
|
|
84
|
-
totalItemsAffected: number;
|
|
85
|
-
};
|
|
86
|
-
};
|
|
87
|
-
/**
|
|
88
|
-
* Format version for display
|
|
89
|
-
*/
|
|
90
|
-
formatVersion(version: SchemaVersion): string;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Create a schema adapter from an existing LensEngine
|
|
94
|
-
*/
|
|
95
|
-
export declare function createSchemaAdapter(lensEngine: LensEngine): DashSchemaAdapter;
|