@revealui/sync 0.2.1 → 0.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.
Files changed (52) hide show
  1. package/README.md +82 -112
  2. package/dist/collab/agent-client-factory.d.ts.map +1 -1
  3. package/dist/collab/agent-client.d.ts +1 -0
  4. package/dist/collab/agent-client.d.ts.map +1 -1
  5. package/dist/collab/agent-client.js +16 -7
  6. package/dist/collab/index.d.ts +1 -0
  7. package/dist/collab/index.d.ts.map +1 -1
  8. package/dist/collab/index.js +1 -0
  9. package/dist/collab/protocol-constants.d.ts +5 -0
  10. package/dist/collab/protocol-constants.d.ts.map +1 -0
  11. package/dist/collab/protocol-constants.js +4 -0
  12. package/dist/collab/server-index.d.ts +1 -0
  13. package/dist/collab/server-index.d.ts.map +1 -1
  14. package/dist/collab/server-index.js +1 -0
  15. package/dist/collab/use-collab-document.d.ts +1 -1
  16. package/dist/collab/use-collab-document.d.ts.map +1 -1
  17. package/dist/collab/use-collab-document.js +7 -4
  18. package/dist/collab/use-collaboration.d.ts.map +1 -1
  19. package/dist/collab/yjs-websocket-provider.d.ts.map +1 -1
  20. package/dist/collab/yjs-websocket-provider.js +1 -2
  21. package/dist/fetch-with-timeout.d.ts +7 -0
  22. package/dist/fetch-with-timeout.d.ts.map +1 -0
  23. package/dist/fetch-with-timeout.js +27 -0
  24. package/dist/hooks/useAgentContexts.d.ts +29 -0
  25. package/dist/hooks/useAgentContexts.d.ts.map +1 -0
  26. package/dist/hooks/useAgentContexts.js +22 -0
  27. package/dist/hooks/useAgentMemory.d.ts +34 -0
  28. package/dist/hooks/useAgentMemory.d.ts.map +1 -0
  29. package/dist/hooks/useAgentMemory.js +37 -0
  30. package/dist/hooks/useConversations.d.ts +26 -6
  31. package/dist/hooks/useConversations.d.ts.map +1 -1
  32. package/dist/hooks/useConversations.js +13 -3
  33. package/dist/hooks/useCoordinationSessions.d.ts +35 -0
  34. package/dist/hooks/useCoordinationSessions.d.ts.map +1 -0
  35. package/dist/hooks/useCoordinationSessions.js +22 -0
  36. package/dist/hooks/useCoordinationWorkItems.d.ts +41 -0
  37. package/dist/hooks/useCoordinationWorkItems.d.ts.map +1 -0
  38. package/dist/hooks/useCoordinationWorkItems.js +22 -0
  39. package/dist/index.d.ts +20 -4
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +14 -4
  42. package/dist/mutations.d.ts +14 -0
  43. package/dist/mutations.d.ts.map +1 -0
  44. package/dist/mutations.js +53 -0
  45. package/dist/provider/index.d.ts +29 -5
  46. package/dist/provider/index.d.ts.map +1 -1
  47. package/dist/provider/index.js +25 -7
  48. package/dist/shape-utils.d.ts +11 -0
  49. package/dist/shape-utils.d.ts.map +1 -0
  50. package/dist/shape-utils.js +14 -0
  51. package/dist/test-setup.d.ts.map +1 -1
  52. package/package.json +17 -15
package/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # @revealui/sync
2
2
 
3
- ElectricSQL sync utilities for RevealUI - real-time data synchronization with local-first architecture.
3
+ ElectricSQL sync utilities for RevealUI real-time data synchronization with local-first architecture.
4
4
 
5
5
  ## Features
6
6
 
7
- - **ElectricSQL Integration**: Real-time sync with ElectricSQL
8
- - **React Hooks**: Use sync data in React components
7
+ - **ElectricSQL Integration**: Real-time sync via shape subscriptions
8
+ - **React Hooks**: Subscribe to synced data in React components
9
+ - **Mutations**: Create, update, and delete records via authenticated REST endpoints
9
10
  - **Type-safe**: Full TypeScript support with database types
10
- - **Local-first**: Works offline, syncs when online
11
11
  - **React Provider**: Easy setup with `ElectricProvider`
12
- - **Optimistic Updates**: Instant UI updates with server reconciliation
12
+ - **Yjs Collaboration**: CRDT-based real-time collaborative editing
13
13
 
14
14
  ## Installation
15
15
 
@@ -28,27 +28,29 @@ import { ElectricProvider } from '@revealui/sync/provider'
28
28
 
29
29
  export default function App() {
30
30
  return (
31
- <ElectricProvider>
31
+ <ElectricProvider proxyBaseUrl="https://cms.revealui.com">
32
32
  <YourComponents />
33
33
  </ElectricProvider>
34
34
  )
35
35
  }
36
36
  ```
37
37
 
38
- ### Use Synced Data
38
+ ### Read Synced Data
39
+
40
+ Hooks subscribe to ElectricSQL shapes via authenticated proxy routes. Data updates in real-time as the database changes.
39
41
 
40
42
  ```typescript
41
43
  import { useAgentContexts } from '@revealui/sync'
42
44
 
43
45
  function MyComponent() {
44
- const { data: contexts, isLoading } = useAgentContexts()
46
+ const { contexts, isLoading } = useAgentContexts()
45
47
 
46
48
  if (isLoading) return <div>Loading...</div>
47
49
 
48
50
  return (
49
51
  <ul>
50
52
  {contexts.map(context => (
51
- <li key={context.id}>{context.name}</li>
53
+ <li key={context.id}>{JSON.stringify(context.context)}</li>
52
54
  ))}
53
55
  </ul>
54
56
  )
@@ -57,18 +59,29 @@ function MyComponent() {
57
59
 
58
60
  ### Mutations
59
61
 
62
+ Each hook returns `create`, `update`, and `remove` functions. Mutations go through authenticated REST endpoints at `/api/sync/*`. ElectricSQL picks up the database changes and pushes updates to all subscribers automatically.
63
+
60
64
  ```typescript
61
65
  import { useAgentContexts } from '@revealui/sync'
62
66
 
63
67
  function CreateContext() {
64
- const { create } = useAgentContexts()
68
+ const { contexts, create, update, remove } = useAgentContexts()
65
69
 
66
70
  const handleCreate = async () => {
67
- await create({
68
- name: 'New Context',
69
- agent_id: 'agent-123',
70
- // ... other fields
71
+ const result = await create({
72
+ agent_id: 'assistant',
73
+ context: { theme: 'dark', language: 'en' },
74
+ priority: 0.8,
71
75
  })
76
+ if (!result.success) console.error(result.error)
77
+ }
78
+
79
+ const handleUpdate = async (id: string) => {
80
+ await update(id, { context: { theme: 'light' } })
81
+ }
82
+
83
+ const handleDelete = async (id: string) => {
84
+ await remove(id)
72
85
  }
73
86
 
74
87
  return <button onClick={handleCreate}>Create</button>
@@ -79,139 +92,96 @@ function CreateContext() {
79
92
 
80
93
  ### `useAgentContexts()`
81
94
 
82
- Sync agent contexts (task context, working memory, etc.)
95
+ Subscribe to agent contexts (task context, working memory).
83
96
 
84
97
  ```typescript
85
98
  const {
86
- data, // Agent contexts array
87
- isLoading, // Loading state
88
- error, // Error state
89
- create, // Create function
90
- update, // Update function
91
- remove // Delete function
99
+ contexts, // AgentContextRecord[]
100
+ isLoading, // boolean
101
+ error, // Error | null
102
+ create, // (data: CreateAgentContextInput) => Promise<MutationResult>
103
+ update, // (id: string, data: UpdateAgentContextInput) => Promise<MutationResult>
104
+ remove, // (id: string) => Promise<MutationResult>
92
105
  } = useAgentContexts()
93
106
  ```
94
107
 
95
- ### `useAgentMemory()`
108
+ ### `useAgentMemory(agentId)`
96
109
 
97
- Sync agent memory (episodic, semantic, working)
110
+ Subscribe to agent memory (episodic, semantic, working) filtered by agent ID.
98
111
 
99
112
  ```typescript
100
113
  const {
101
- data, // Memory entries array
102
- isLoading,
103
- error,
104
- create,
105
- update,
106
- remove
107
- } = useAgentMemory()
114
+ memories, // AgentMemoryRecord[]
115
+ isLoading, // boolean
116
+ error, // Error | null
117
+ create, // (data: CreateAgentMemoryInput) => Promise<MutationResult>
118
+ update, // (id: string, data: UpdateAgentMemoryInput) => Promise<MutationResult>
119
+ remove, // (id: string) => Promise<MutationResult>
120
+ } = useAgentMemory('assistant')
108
121
  ```
109
122
 
110
- ### `useConversations()`
123
+ ### `useConversations(userId)`
111
124
 
112
- Sync conversation history
125
+ Subscribe to conversation history. Server-side proxy enforces row-level filtering by session — the `userId` parameter is for API compatibility but filtering is handled server-side.
113
126
 
114
127
  ```typescript
115
128
  const {
116
- data, // Conversations array
117
- isLoading,
118
- error,
119
- create,
120
- update,
121
- remove
122
- } = useConversations()
129
+ conversations, // ConversationRecord[]
130
+ isLoading, // boolean
131
+ error, // Error | null
132
+ create, // (data: CreateConversationInput) => Promise<MutationResult>
133
+ update, // (id: string, data: UpdateConversationInput) => Promise<MutationResult>
134
+ remove, // (id: string) => Promise<MutationResult>
135
+ } = useConversations(userId)
123
136
  ```
124
137
 
125
138
  ## How It Works
126
139
 
127
- 1. **ElectricSQL Service**: Runs as a sync service between Postgres and clients
128
- 2. **Shape Subscriptions**: Subscribe to "shapes" of data (queries)
129
- 3. **Local Cache**: Data cached locally in browser
130
- 4. **Real-time Updates**: Changes propagate instantly to all connected clients
131
- 5. **Conflict Resolution**: CRDT-based conflict resolution for offline edits
140
+ 1. **Reads**: ElectricSQL shape subscriptions via authenticated CMS proxy (`/api/shapes/*`)
141
+ 2. **Writes**: REST mutations via CMS API (`/api/sync/*`) → Postgres → ElectricSQL replication
142
+ 3. **Real-time**: Database changes propagate to all shape subscribers automatically
143
+ 4. **Auth**: All endpoints require a valid session cookie
132
144
 
133
- ## Environment Variables
145
+ ## Collaboration (Yjs)
134
146
 
135
- ```env
136
- # ElectricSQL service URL
137
- NEXT_PUBLIC_ELECTRIC_SERVICE_URL=http://localhost:5133
147
+ The collab layer provides CRDT-based collaborative editing:
138
148
 
139
- # Optional: Server-side Electric URL (if different)
140
- ELECTRIC_SERVICE_URL=http://localhost:5133
149
+ ```typescript
150
+ import { useCollaboration } from '@revealui/sync'
151
+
152
+ function Editor() {
153
+ const { doc, synced, connectedUsers } = useCollaboration({
154
+ documentId: 'doc-uuid',
155
+ serverUrl: 'ws://localhost:4000',
156
+ })
157
+ // ...
158
+ }
141
159
  ```
142
160
 
143
- ## Development
161
+ Server-side agents can use `AgentCollabClient` from `@revealui/sync/collab/server`.
144
162
 
145
- ```bash
146
- # Build package
147
- pnpm --filter @revealui/sync build
163
+ ## Environment Variables
148
164
 
149
- # Watch mode
150
- pnpm --filter @revealui/sync dev
165
+ ```env
166
+ # ElectricSQL service URL (used by CMS proxy)
167
+ ELECTRIC_SERVICE_URL=http://localhost:5133
151
168
 
152
- # Run tests
153
- pnpm --filter @revealui/sync test
169
+ # Optional: Electric auth secret
170
+ ELECTRIC_SECRET=your-secret
154
171
 
155
- # Type check
156
- pnpm --filter @revealui/sync typecheck
172
+ # Client-side (stored in provider context)
173
+ NEXT_PUBLIC_ELECTRIC_SERVICE_URL=http://localhost:5133
157
174
  ```
158
175
 
159
- ## Testing
176
+ ## Development
160
177
 
161
178
  ```bash
162
- # Run all tests
163
- pnpm --filter @revealui/sync test
164
-
165
- # Watch mode
166
- pnpm --filter @revealui/sync test:watch
167
-
168
- # Coverage
169
- pnpm --filter @revealui/sync test:coverage
179
+ pnpm --filter @revealui/sync build # Build
180
+ pnpm --filter @revealui/sync dev # Watch mode
181
+ pnpm --filter @revealui/sync test # Run tests
182
+ pnpm --filter @revealui/sync typecheck # Type check
170
183
  ```
171
184
 
172
- ## Architecture
173
-
174
- ```
175
- ┌─────────────────┐
176
- │ React Component │
177
- │ (useAgentContexts) │
178
- └────────┬────────┘
179
-
180
-
181
- ┌─────────────────┐
182
- │ ElectricSQL │
183
- │ Shape Hook │
184
- └────────┬────────┘
185
-
186
-
187
- ┌─────────────────┐
188
- │ Electric Sync │
189
- │ Service │
190
- └────────┬────────┘
191
-
192
-
193
- ┌─────────────────┐
194
- │ PostgreSQL │
195
- │ Database │
196
- └─────────────────┘
197
- ```
198
-
199
- ## Limitations
200
-
201
- ⚠️ **CRITICAL**: ElectricSQL API endpoints need independent verification before production use.
202
-
203
- **Status:** ⚠️ NEEDS VERIFICATION
204
- - ElectricSQL integration exists but requires testing
205
- - API endpoints based on assumptions
206
- - No integration tests performed yet
207
- - Verify against your deployment before relying on sync in production
208
-
209
- ## Related Documentation
210
-
211
- - [ElectricSQL Documentation](https://electric-sql.com/docs) - Official ElectricSQL docs
212
- - [Architecture](../../docs/ARCHITECTURE.md) - System architecture overview
213
- - [Database Guide](../../docs/DATABASE.md) - Database setup
214
-
215
185
  ## License
216
186
 
217
187
  MIT
@@ -1 +1 @@
1
- {"version":3,"file":"agent-client-factory.d.ts","sourceRoot":"","sources":["../../src/collab/agent-client-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAsB,MAAM,mBAAmB,CAAA;AAIzE,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB,CAgBtF;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,wBAAwB,GAAG;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7D,OAAO,CAAC,iBAAiB,CAAC,CAK5B"}
1
+ {"version":3,"file":"agent-client-factory.d.ts","sourceRoot":"","sources":["../../src/collab/agent-client-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAsB,MAAM,mBAAmB,CAAC;AAI1E,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB,CAgBtF;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,wBAAwB,GAAG;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7D,OAAO,CAAC,iBAAiB,CAAC,CAK5B"}
@@ -31,6 +31,7 @@ export declare class AgentCollabClient extends Observable<string> {
31
31
  private updateHandler;
32
32
  private awarenessUpdateHandler;
33
33
  private destroyed;
34
+ private pendingSyncAbort;
34
35
  constructor(options: AgentCollabClientOptions);
35
36
  connect(): void;
36
37
  disconnect(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-client.d.ts","sourceRoot":"","sources":["../../src/collab/agent-client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,OAAO,KAAK,iBAAiB,MAAM,uBAAuB,CAAA;AAE1D,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAQxB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,aAAa,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,qBAAa,iBAAkB,SAAQ,UAAU,CAAC,MAAM,CAAC;IACvD,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAA;IACnB,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC,SAAS,CAAA;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAQ;IACnC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAQ;IAExC,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,iBAAiB,CAAI;IAC7B,OAAO,CAAC,cAAc,CAA6C;IACnE,OAAO,CAAC,aAAa,CAA+D;IACpF,OAAO,CAAC,sBAAsB,CAGrB;IACT,OAAO,CAAC,SAAS,CAAQ;gBAEb,OAAO,EAAE,wBAAwB;IA0B7C,OAAO,IAAI,IAAI;IAcf,UAAU,IAAI,IAAI;IAkBlB,WAAW,IAAI,CAAC,CAAC,GAAG;IAIpB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI;IAI9B,cAAc,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM;IAMrC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAI/D,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAI9D,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAQhD,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI;IAU5D,iBAAiB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAUzD,WAAW,CAAC,SAAS,SAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB5C,OAAO,IAAI,IAAI;IASf,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,UAAU;IAoClB,OAAO,CAAC,aAAa;IA+BrB,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,eAAe;CAOxB"}
1
+ {"version":3,"file":"agent-client.d.ts","sourceRoot":"","sources":["../../src/collab/agent-client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,KAAK,iBAAiB,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAOzB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,aAAa,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,iBAAkB,SAAQ,UAAU,CAAC,MAAM,CAAC;IACvD,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC,SAAS,CAAC;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IAEzC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,aAAa,CAAgE;IACrF,OAAO,CAAC,sBAAsB,CAGpB;IACV,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,gBAAgB,CAA6B;gBAEzC,OAAO,EAAE,wBAAwB;IA0B7C,OAAO,IAAI,IAAI;IAcf,UAAU,IAAI,IAAI;IAkBlB,WAAW,IAAI,CAAC,CAAC,GAAG;IAIpB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI;IAI9B,cAAc,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM;IAIrC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAI/D,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAI9D,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAQhD,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI;IAU5D,iBAAiB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAUzD,WAAW,CAAC,SAAS,SAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA+B5C,OAAO,IAAI,IAAI;IAUf,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,UAAU;IAoClB,OAAO,CAAC,aAAa;IAoCrB,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,eAAe;CAOxB"}
@@ -5,8 +5,7 @@ import WebSocket from 'ws';
5
5
  import * as awarenessProtocol from 'y-protocols/awareness';
6
6
  import * as syncProtocol from 'y-protocols/sync';
7
7
  import * as Y from 'yjs';
8
- const MESSAGE_SYNC = 0;
9
- const MESSAGE_AWARENESS = 1;
8
+ import { MESSAGE_AWARENESS, MESSAGE_SYNC } from './protocol-constants.js';
10
9
  const MAX_RECONNECT_ATTEMPTS = 5;
11
10
  const BASE_RECONNECT_DELAY = 1000;
12
11
  const RECONNECT_MULTIPLIER = 2;
@@ -26,6 +25,7 @@ export class AgentCollabClient extends Observable {
26
25
  updateHandler = null;
27
26
  awarenessUpdateHandler;
28
27
  destroyed = false;
28
+ pendingSyncAbort = null;
29
29
  constructor(options) {
30
30
  super();
31
31
  this.serverUrl = options.serverUrl;
@@ -83,8 +83,6 @@ export class AgentCollabClient extends Observable {
83
83
  return this.doc.getText(name ?? this.defaultTextName);
84
84
  }
85
85
  getTextContent(name) {
86
- // Y.Text.toString() returns the text content — ESLint doesn't recognize this
87
- // eslint-disable-next-line @typescript-eslint/no-base-to-string
88
86
  return this.getText(name).toString();
89
87
  }
90
88
  insertText(index, content, name) {
@@ -122,22 +120,33 @@ export class AgentCollabClient extends Observable {
122
120
  if (this.synced)
123
121
  return Promise.resolve();
124
122
  return new Promise((resolve, reject) => {
125
- const timeout = setTimeout(() => {
123
+ const cleanup = () => {
124
+ clearTimeout(timeout);
126
125
  this.off('sync', handler);
126
+ if (this.pendingSyncAbort === abort)
127
+ this.pendingSyncAbort = null;
128
+ };
129
+ const timeout = setTimeout(() => {
130
+ cleanup();
127
131
  reject(new Error(`Sync timeout after ${timeoutMs}ms`));
128
132
  }, timeoutMs);
129
133
  const handler = (isSynced) => {
130
134
  if (isSynced) {
131
- clearTimeout(timeout);
132
- this.off('sync', handler);
135
+ cleanup();
133
136
  resolve();
134
137
  }
135
138
  };
139
+ const abort = () => {
140
+ cleanup();
141
+ reject(new Error('Client destroyed while waiting for sync'));
142
+ };
143
+ this.pendingSyncAbort = abort;
136
144
  this.on('sync', handler);
137
145
  });
138
146
  }
139
147
  destroy() {
140
148
  this.destroyed = true;
149
+ this.pendingSyncAbort?.();
141
150
  this.awareness.off('update', this.awarenessUpdateHandler);
142
151
  this.disconnect();
143
152
  this.awareness.destroy();
@@ -1,3 +1,4 @@
1
+ export { MESSAGE_AWARENESS, MESSAGE_SYNC } from './protocol-constants.js';
1
2
  export type { CollabDocumentState } from './use-collab-document.js';
2
3
  export { useCollabDocument } from './use-collab-document.js';
3
4
  export type { CollaborationIdentity, UseCollaborationOptions, UseCollaborationResult, } from './use-collaboration.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/collab/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,YAAY,EACV,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/collab/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC1E,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,YAAY,EACV,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,YAAY,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC"}
@@ -1,3 +1,4 @@
1
+ export { MESSAGE_AWARENESS, MESSAGE_SYNC } from './protocol-constants.js';
1
2
  export { useCollabDocument } from './use-collab-document.js';
2
3
  export { useCollaboration } from './use-collaboration.js';
3
4
  export { CollabProvider } from './yjs-websocket-provider.js';
@@ -0,0 +1,5 @@
1
+ /** Yjs sync protocol message type */
2
+ export declare const MESSAGE_SYNC = 0;
3
+ /** Yjs awareness protocol message type */
4
+ export declare const MESSAGE_AWARENESS = 1;
5
+ //# sourceMappingURL=protocol-constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol-constants.d.ts","sourceRoot":"","sources":["../../src/collab/protocol-constants.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,0CAA0C;AAC1C,eAAO,MAAM,iBAAiB,IAAI,CAAC"}
@@ -0,0 +1,4 @@
1
+ /** Yjs sync protocol message type */
2
+ export const MESSAGE_SYNC = 0;
3
+ /** Yjs awareness protocol message type */
4
+ export const MESSAGE_AWARENESS = 1;
@@ -2,4 +2,5 @@ export type { AgentCollabClientOptions, AgentIdentity } from './agent-client.js'
2
2
  export { AgentCollabClient } from './agent-client.js';
3
3
  export type { CreateAgentClientOptions } from './agent-client-factory.js';
4
4
  export { createAgentClient, createAndConnectAgentClient } from './agent-client-factory.js';
5
+ export { MESSAGE_AWARENESS, MESSAGE_SYNC } from './protocol-constants.js';
5
6
  //# sourceMappingURL=server-index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server-index.d.ts","sourceRoot":"","sources":["../../src/collab/server-index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,wBAAwB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAChF,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,YAAY,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAA;AACzE,OAAO,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAA"}
1
+ {"version":3,"file":"server-index.d.ts","sourceRoot":"","sources":["../../src/collab/server-index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,wBAAwB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,YAAY,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAC3F,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export { AgentCollabClient } from './agent-client.js';
2
2
  export { createAgentClient, createAndConnectAgentClient } from './agent-client-factory.js';
3
+ export { MESSAGE_AWARENESS, MESSAGE_SYNC } from './protocol-constants.js';
@@ -4,5 +4,5 @@ export interface CollabDocumentState {
4
4
  isLoading: boolean;
5
5
  error: Error | null;
6
6
  }
7
- export declare function useCollabDocument(documentId: string, electricUrl: string): CollabDocumentState;
7
+ export declare function useCollabDocument(documentId: string): CollabDocumentState;
8
8
  //# sourceMappingURL=use-collab-document.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-collab-document.d.ts","sourceRoot":"","sources":["../../src/collab/use-collab-document.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,UAAU,GAAG,IAAI,CAAA;IAC/B,gBAAgB,EAAE,MAAM,CAAA;IACxB,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;CACpB;AAKD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,mBAAmB,CA+C9F"}
1
+ {"version":3,"file":"use-collab-document.d.ts","sourceRoot":"","sources":["../../src/collab/use-collab-document.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,UAAU,GAAG,IAAI,CAAC;IAChC,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAKD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,mBAAmB,CAiDzE"}
@@ -1,18 +1,21 @@
1
1
  import { useShape } from '@electric-sql/react';
2
+ import { fetchWithTimeout } from '../fetch-with-timeout.js';
3
+ import { useElectricConfig } from '../provider/index.js';
2
4
  // UUID v4 pattern — only format accepted as a yjs_documents PK
3
5
  const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
4
- export function useCollabDocument(documentId, electricUrl) {
6
+ export function useCollabDocument(documentId) {
7
+ const { proxyBaseUrl } = useElectricConfig();
5
8
  // Validate before interpolating into the WHERE clause. yjs_documents PKs are
6
9
  // always UUIDs — reject anything else so no untrusted string enters the query.
7
10
  const isValidId = UUID_RE.test(documentId);
8
11
  // Hook must always be called (Rules of Hooks). Pass an impossible WHERE when
9
12
  // the ID is invalid so the shape returns no rows but the hook still runs.
10
13
  const { data, isLoading, error } = useShape({
11
- url: `${electricUrl}/v1/shape`,
14
+ url: `${proxyBaseUrl}/api/shapes/yjs-documents`,
12
15
  params: {
13
- table: 'yjs_documents',
14
- where: isValidId ? `id = '${documentId}'` : `id = 'invalid'`,
16
+ document_id: isValidId ? documentId : '__invalid__',
15
17
  },
18
+ fetchClient: fetchWithTimeout,
16
19
  });
17
20
  if (!isValidId) {
18
21
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"use-collaboration.d.ts","sourceRoot":"","sources":["../../src/collab/use-collaboration.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAE5D,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,YAAY,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;IAChC,QAAQ,CAAC,EAAE,qBAAqB,CAAA;CACjC;AAED,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,CAAC,CAAC,GAAG,GAAG,IAAI,CAAA;IACjB,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAA;IAC/B,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;IACnB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;CAC1C;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,UAAU,EACV,SAAS,EACT,OAAc,EACd,YAAmB,EACnB,QAAQ,GACT,EAAE,uBAAuB,GAAG,sBAAsB,CAqElD"}
1
+ {"version":3,"file":"use-collaboration.d.ts","sourceRoot":"","sources":["../../src/collab/use-collaboration.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAClC;AAED,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC;IAClB,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAC3C;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,UAAU,EACV,SAAS,EACT,OAAc,EACd,YAAmB,EACnB,QAAQ,GACT,EAAE,uBAAuB,GAAG,sBAAsB,CAqElD"}
@@ -1 +1 @@
1
- {"version":3,"file":"yjs-websocket-provider.d.ts","sourceRoot":"","sources":["../../src/collab/yjs-websocket-provider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,KAAK,iBAAiB,MAAM,uBAAuB,CAAA;AAE1D,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAQxB,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,OAAO,GAAG,OAAO,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAC3C;AAED,qBAAa,cAAe,SAAQ,UAAU,CAAC,MAAM,CAAC;IACpD,GAAG,EAAE,CAAC,CAAC,GAAG,CAAA;IACV,SAAS,EAAE,iBAAiB,CAAC,SAAS,CAAA;IACtC,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,iBAAiB,CAAI;IAC7B,OAAO,CAAC,cAAc,CAA6C;IACnE,OAAO,CAAC,aAAa,CAA+D;IACpF,OAAO,CAAC,sBAAsB,CAGrB;gBAGP,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,CAAC,CAAC,GAAG,EACV,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE;IA2BhD,gBAAgB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;IAI9C,iBAAiB,IAAI,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC;IAU9C,OAAO,IAAI,IAAI;IAuFf,UAAU,IAAI,IAAI;IAmBlB,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,eAAe;IAQvB,OAAO,IAAI,IAAI;CAMhB"}
1
+ {"version":3,"file":"yjs-websocket-provider.d.ts","sourceRoot":"","sources":["../../src/collab/yjs-websocket-provider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,iBAAiB,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAOzB,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5C;AAED,qBAAa,cAAe,SAAQ,UAAU,CAAC,MAAM,CAAC;IACpD,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC;IACX,SAAS,EAAE,iBAAiB,CAAC,SAAS,CAAC;IACvC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,aAAa,CAAgE;IACrF,OAAO,CAAC,sBAAsB,CAGpB;gBAGR,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,CAAC,CAAC,GAAG,EACV,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE;IA2BhD,gBAAgB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;IAI9C,iBAAiB,IAAI,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC;IAU9C,OAAO,IAAI,IAAI;IAuFf,UAAU,IAAI,IAAI;IAmBlB,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,eAAe;IAQvB,OAAO,IAAI,IAAI;CAMhB"}
@@ -4,8 +4,7 @@ import { Observable } from 'lib0/observable';
4
4
  import * as awarenessProtocol from 'y-protocols/awareness';
5
5
  import * as syncProtocol from 'y-protocols/sync';
6
6
  import * as Y from 'yjs';
7
- const MESSAGE_SYNC = 0;
8
- const MESSAGE_AWARENESS = 1;
7
+ import { MESSAGE_AWARENESS, MESSAGE_SYNC } from './protocol-constants.js';
9
8
  const MAX_RECONNECT_ATTEMPTS = 10;
10
9
  const BASE_RECONNECT_DELAY = 1000;
11
10
  const RECONNECT_MULTIPLIER = 1.5;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * A fetch wrapper that aborts requests after {@link SHAPE_FETCH_TIMEOUT_MS} (10 s).
3
+ * Passed as `fetchClient` to ElectricSQL `useShape` so that shape subscription
4
+ * requests to the CMS proxy do not hang indefinitely.
5
+ */
6
+ export declare function fetchWithTimeout(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
7
+ //# sourceMappingURL=fetch-with-timeout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-with-timeout.d.ts","sourceRoot":"","sources":["../src/fetch-with-timeout.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAoBhG"}
@@ -0,0 +1,27 @@
1
+ /** Default timeout for Electric shape proxy fetch requests (milliseconds). */
2
+ const SHAPE_FETCH_TIMEOUT_MS = 10_000;
3
+ /**
4
+ * A fetch wrapper that aborts requests after {@link SHAPE_FETCH_TIMEOUT_MS} (10 s).
5
+ * Passed as `fetchClient` to ElectricSQL `useShape` so that shape subscription
6
+ * requests to the CMS proxy do not hang indefinitely.
7
+ */
8
+ export function fetchWithTimeout(input, init) {
9
+ // If the caller already provides a signal, respect it and compose with our timeout.
10
+ const externalSignal = init?.signal;
11
+ const controller = new AbortController();
12
+ const timeout = setTimeout(() => controller.abort(), SHAPE_FETCH_TIMEOUT_MS);
13
+ // If the external signal aborts, forward to our controller.
14
+ if (externalSignal) {
15
+ if (externalSignal.aborted) {
16
+ controller.abort(externalSignal.reason);
17
+ }
18
+ else {
19
+ externalSignal.addEventListener('abort', () => controller.abort(externalSignal.reason), {
20
+ once: true,
21
+ });
22
+ }
23
+ }
24
+ return fetch(input, { ...init, signal: controller.signal }).finally(() => {
25
+ clearTimeout(timeout);
26
+ });
27
+ }
@@ -0,0 +1,29 @@
1
+ import type { MutationResult } from '../mutations.js';
2
+ export interface AgentContextRecord {
3
+ id: string;
4
+ session_id: string;
5
+ agent_id: string;
6
+ context: Record<string, unknown>;
7
+ priority: number;
8
+ created_at: string;
9
+ updated_at: string;
10
+ }
11
+ export interface CreateAgentContextInput {
12
+ agent_id: string;
13
+ context?: Record<string, unknown>;
14
+ priority?: number;
15
+ }
16
+ export interface UpdateAgentContextInput {
17
+ context?: Record<string, unknown>;
18
+ priority?: number;
19
+ }
20
+ export interface UseAgentContextsResult {
21
+ contexts: AgentContextRecord[];
22
+ isLoading: boolean;
23
+ error: Error | null;
24
+ create: (data: CreateAgentContextInput) => Promise<MutationResult<AgentContextRecord>>;
25
+ update: (id: string, data: UpdateAgentContextInput) => Promise<MutationResult<AgentContextRecord>>;
26
+ remove: (id: string) => Promise<MutationResult<void>>;
27
+ }
28
+ export declare function useAgentContexts(): UseAgentContextsResult;
29
+ //# sourceMappingURL=useAgentContexts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAgentContexts.d.ts","sourceRoot":"","sources":["../../src/hooks/useAgentContexts.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAKtD,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,IAAI,EAAE,uBAAuB,KAAK,OAAO,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACvF,MAAM,EAAE,CACN,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,uBAAuB,KAC1B,OAAO,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACjD,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;CACvD;AAED,wBAAgB,gBAAgB,IAAI,sBAAsB,CAqBzD"}
@@ -0,0 +1,22 @@
1
+ 'use client';
2
+ import { useShape } from '@electric-sql/react';
3
+ import { fetchWithTimeout } from '../fetch-with-timeout.js';
4
+ import { useSyncMutations } from '../mutations.js';
5
+ import { useElectricConfig } from '../provider/index.js';
6
+ import { toRecords } from '../shape-utils.js';
7
+ export function useAgentContexts() {
8
+ const { proxyBaseUrl } = useElectricConfig();
9
+ const { data, isLoading, error } = useShape({
10
+ url: `${proxyBaseUrl}/api/shapes/agent-contexts`,
11
+ fetchClient: fetchWithTimeout,
12
+ });
13
+ const { create, update, remove } = useSyncMutations('agent-contexts');
14
+ return {
15
+ contexts: toRecords(data),
16
+ isLoading,
17
+ error: error || null,
18
+ create,
19
+ update,
20
+ remove,
21
+ };
22
+ }
@@ -0,0 +1,34 @@
1
+ import type { MutationResult } from '../mutations.js';
2
+ export interface AgentMemoryRecord {
3
+ id: string;
4
+ agent_id: string;
5
+ content: string;
6
+ type: string;
7
+ metadata: Record<string, unknown>;
8
+ created_at: string;
9
+ expires_at: string | null;
10
+ }
11
+ export interface CreateAgentMemoryInput {
12
+ agent_id: string;
13
+ content: string;
14
+ type: string;
15
+ source: Record<string, unknown>;
16
+ metadata?: Record<string, unknown>;
17
+ expires_at?: string | null;
18
+ }
19
+ export interface UpdateAgentMemoryInput {
20
+ content?: string;
21
+ type?: string;
22
+ metadata?: Record<string, unknown>;
23
+ expires_at?: string | null;
24
+ }
25
+ export interface UseAgentMemoryResult {
26
+ memories: AgentMemoryRecord[];
27
+ isLoading: boolean;
28
+ error: Error | null;
29
+ create: (data: CreateAgentMemoryInput) => Promise<MutationResult<AgentMemoryRecord>>;
30
+ update: (id: string, data: UpdateAgentMemoryInput) => Promise<MutationResult<AgentMemoryRecord>>;
31
+ remove: (id: string) => Promise<MutationResult<void>>;
32
+ }
33
+ export declare function useAgentMemory(agentId: string): UseAgentMemoryResult;
34
+ //# sourceMappingURL=useAgentMemory.d.ts.map