@knowlearning/agents 0.9.189 → 0.9.190
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/agents/attach-synced.js +32 -5
- package/agents/embedded.js +43 -2
- package/agents/generic/index.js +9 -1
- package/agents/generic/state.js +34 -2
- package/package.json +1 -1
package/agents/attach-synced.js
CHANGED
|
@@ -28,12 +28,37 @@ export default function attachSynced(watchers, init) {
|
|
|
28
28
|
if (syncRegistered) return
|
|
29
29
|
syncRegistered = true
|
|
30
30
|
if (!watchers[resolvedKey]) watchers[resolvedKey] = []
|
|
31
|
-
watchers[resolvedKey].push(({ patch }) => {
|
|
31
|
+
watchers[resolvedKey].push(({ patch, state, ii }) => {
|
|
32
32
|
if (!patch) return
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
const pending = ctx.pendingInteractions?.size
|
|
34
|
+
? Promise.all(ctx.pendingInteractions)
|
|
35
|
+
: Promise.resolve()
|
|
36
|
+
pending.then(() => {
|
|
37
|
+
const isOwn = ctx.ownInteractions?.has(ii)
|
|
38
|
+
const echoBatch = isOwn ? ctx.ownInteractionBatches?.get(ii) : null
|
|
39
|
+
if (isOwn) {
|
|
40
|
+
ctx.ownInteractions.delete(ii)
|
|
41
|
+
if (echoBatch) ctx.ownInteractionBatches.delete(ii)
|
|
42
|
+
} else {
|
|
43
|
+
ctx.applyingExternalUpdate = true
|
|
44
|
+
applyPatch(resolvedProxy, standardJSONPatch(patch))
|
|
45
|
+
ctx.applyingExternalUpdate = false
|
|
46
|
+
}
|
|
47
|
+
if (echoBatch) {
|
|
48
|
+
echoBatch.state = state
|
|
49
|
+
if (echoBatch.remaining !== undefined) echoBatch.remaining -= 1
|
|
50
|
+
if ((echoBatch.remaining === undefined || echoBatch.remaining === 0) && !echoBatch.resolved) {
|
|
51
|
+
echoBatch.resolved = true
|
|
52
|
+
syncCallbacks.forEach(cb => cb(echoBatch.state, patch))
|
|
53
|
+
echoBatch.resolve()
|
|
54
|
+
}
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
syncCallbacks.forEach(cb => cb(state, patch))
|
|
58
|
+
if (isOwn && ctx.echoResolvers?.length) {
|
|
59
|
+
ctx.echoResolvers.shift()()
|
|
60
|
+
}
|
|
61
|
+
})
|
|
37
62
|
})
|
|
38
63
|
}
|
|
39
64
|
|
|
@@ -47,6 +72,8 @@ export default function attachSynced(watchers, init) {
|
|
|
47
72
|
|
|
48
73
|
promise.synced = function(callback) {
|
|
49
74
|
shouldSync = true
|
|
75
|
+
ctx.syncActive = true
|
|
76
|
+
if (!ctx.echoResolvers) ctx.echoResolvers = []
|
|
50
77
|
if (callback) syncCallbacks.push(callback)
|
|
51
78
|
if (resolvedProxy) registerSyncWatcher()
|
|
52
79
|
return promise
|
package/agents/embedded.js
CHANGED
|
@@ -11,6 +11,7 @@ export default function EmbeddedAgent(postMessage) {
|
|
|
11
11
|
const responses = {}
|
|
12
12
|
const watchers = {}
|
|
13
13
|
const sentUpdates = {}
|
|
14
|
+
const pendingEchoCallbacks = new Set()
|
|
14
15
|
|
|
15
16
|
const [ watch, removeWatcher ] = watchImplementation({ metadata, state, watchers, synced, sentUpdates, environment })
|
|
16
17
|
|
|
@@ -108,12 +109,48 @@ export default function EmbeddedAgent(postMessage) {
|
|
|
108
109
|
const d = !domain || domain === rootDomain ? '' : domain
|
|
109
110
|
const u = !user || auth.user === user ? '' : user
|
|
110
111
|
const key = isUUID(scope) ? scope : `${d}/${u}/${scope}`
|
|
112
|
+
if (!ctx.ownInteractions) ctx.ownInteractions = new Set()
|
|
113
|
+
if (!ctx.ownInteractionBatches) ctx.ownInteractionBatches = new Map()
|
|
114
|
+
if (!ctx.pendingInteractions) ctx.pendingInteractions = new Set()
|
|
115
|
+
if (!ctx.echoResolvers) ctx.echoResolvers = []
|
|
116
|
+
let currentEchoBatch = null
|
|
111
117
|
const proxy = new PatchProxy(startState, patch => {
|
|
112
118
|
// TODO: reject updates if user is not owner
|
|
113
119
|
if (ctx.applyingExternalUpdate) return
|
|
114
120
|
const activePatch = structuredClone(patch)
|
|
115
121
|
activePatch.forEach(entry => entry.path.unshift('active'))
|
|
116
|
-
|
|
122
|
+
let echoBatch
|
|
123
|
+
if (ctx.syncActive) {
|
|
124
|
+
if (!currentEchoBatch) {
|
|
125
|
+
let resolveEcho
|
|
126
|
+
const echoPromise = new Promise(r => resolveEcho = r)
|
|
127
|
+
echoBatch = currentEchoBatch = { remaining: 0, resolve: resolveEcho, resolved: false }
|
|
128
|
+
pendingEchoCallbacks.add(echoPromise)
|
|
129
|
+
echoPromise.then(() => pendingEchoCallbacks.delete(echoPromise))
|
|
130
|
+
Promise.resolve().then(() => { currentEchoBatch = null })
|
|
131
|
+
}
|
|
132
|
+
else echoBatch = currentEchoBatch
|
|
133
|
+
echoBatch.remaining += 1
|
|
134
|
+
}
|
|
135
|
+
const interactPromise = interact(scope, activePatch)
|
|
136
|
+
const p = interactPromise.then(
|
|
137
|
+
r => {
|
|
138
|
+
ctx.ownInteractions.add(r.ii)
|
|
139
|
+
if (echoBatch) ctx.ownInteractionBatches.set(r.ii, echoBatch)
|
|
140
|
+
ctx.pendingInteractions.delete(p)
|
|
141
|
+
},
|
|
142
|
+
() => {
|
|
143
|
+
if (echoBatch) {
|
|
144
|
+
echoBatch.remaining -= 1
|
|
145
|
+
if (echoBatch.remaining === 0 && !echoBatch.resolved) {
|
|
146
|
+
echoBatch.resolved = true
|
|
147
|
+
echoBatch.resolve()
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
ctx.pendingInteractions.delete(p)
|
|
151
|
+
}
|
|
152
|
+
)
|
|
153
|
+
ctx.pendingInteractions.add(p)
|
|
117
154
|
})
|
|
118
155
|
resolveSync(proxy, key)
|
|
119
156
|
return proxy
|
|
@@ -213,7 +250,11 @@ export default function EmbeddedAgent(postMessage) {
|
|
|
213
250
|
function logout() { return send({ type: 'logout' }) }
|
|
214
251
|
function disconnect() { return send({ type: 'disconnect' }) }
|
|
215
252
|
function reconnect() { return send({ type: 'reconnect' }) }
|
|
216
|
-
function synced() {
|
|
253
|
+
async function synced() {
|
|
254
|
+
const echoSnapshot = [...pendingEchoCallbacks]
|
|
255
|
+
await send({ type: 'synced' })
|
|
256
|
+
if (echoSnapshot.length) await Promise.all(echoSnapshot)
|
|
257
|
+
}
|
|
217
258
|
function close(info) { return send({ type: 'close', info }) }
|
|
218
259
|
function guarantee(script, namespaces, context) { return send({ type: 'guarantee', script, namespaces, context }) }
|
|
219
260
|
function response(id=lastRequestId) { return send({ type: 'response', id }) }
|
package/agents/generic/index.js
CHANGED
|
@@ -17,6 +17,7 @@ export default function Agent({ Connection, domain, token, sid, uuid, fetch, app
|
|
|
17
17
|
const watchers = {}
|
|
18
18
|
const keyToSubscriptionId = {}
|
|
19
19
|
const lastInteractionResponse = {}
|
|
20
|
+
const pendingEchoCallbacks = new Set()
|
|
20
21
|
|
|
21
22
|
log('INITIALIZING AGENT CONNECTION')
|
|
22
23
|
const [
|
|
@@ -47,6 +48,7 @@ export default function Agent({ Connection, domain, token, sid, uuid, fetch, app
|
|
|
47
48
|
interact,
|
|
48
49
|
fetch,
|
|
49
50
|
synced,
|
|
51
|
+
pendingEchoCallbacks,
|
|
50
52
|
metadata,
|
|
51
53
|
log
|
|
52
54
|
}
|
|
@@ -204,6 +206,12 @@ export default function Agent({ Connection, domain, token, sid, uuid, fetch, app
|
|
|
204
206
|
}
|
|
205
207
|
}
|
|
206
208
|
|
|
209
|
+
async function syncedWithEchoCallbacks() {
|
|
210
|
+
const echoSnapshot = [...pendingEchoCallbacks]
|
|
211
|
+
await synced()
|
|
212
|
+
if (echoSnapshot.length) await Promise.all(echoSnapshot)
|
|
213
|
+
}
|
|
214
|
+
|
|
207
215
|
function response() {
|
|
208
216
|
return lastMessageResponse()
|
|
209
217
|
}
|
|
@@ -224,7 +232,7 @@ export default function Agent({ Connection, domain, token, sid, uuid, fetch, app
|
|
|
224
232
|
reset,
|
|
225
233
|
metadata,
|
|
226
234
|
query,
|
|
227
|
-
synced,
|
|
235
|
+
synced: syncedWithEchoCallbacks,
|
|
228
236
|
disconnect,
|
|
229
237
|
reconnect,
|
|
230
238
|
debug,
|
package/agents/generic/state.js
CHANGED
|
@@ -2,7 +2,7 @@ import { v4 as uuid, validate as isUUID } from 'uuid'
|
|
|
2
2
|
import PatchProxy from '@knowlearning/patch-proxy'
|
|
3
3
|
import attachSynced from '../attach-synced.js'
|
|
4
4
|
|
|
5
|
-
export default function(scope='[]', user, domain, { keyToSubscriptionId, watchers, states, create, environment, lastMessageResponse, lastInteractionResponse, interact, log }) {
|
|
5
|
+
export default function(scope='[]', user, domain, { keyToSubscriptionId, watchers, states, create, environment, lastMessageResponse, lastInteractionResponse, interact, pendingEchoCallbacks, log }) {
|
|
6
6
|
let resolveMetadataPromise
|
|
7
7
|
let metadataPromise = new Promise(resolve => resolveMetadataPromise = resolve)
|
|
8
8
|
|
|
@@ -36,11 +36,43 @@ export default function(scope='[]', user, domain, { keyToSubscriptionId, watcher
|
|
|
36
36
|
const active = data.active
|
|
37
37
|
delete data.active
|
|
38
38
|
resolveMetadataPromise(data)
|
|
39
|
+
if (!ctx.ownInteractions) ctx.ownInteractions = new Set()
|
|
40
|
+
if (!ctx.ownInteractionBatches) ctx.ownInteractionBatches = new Map()
|
|
41
|
+
if (!ctx.pendingInteractions) ctx.pendingInteractions = new Set()
|
|
42
|
+
if (!ctx.echoResolvers) ctx.echoResolvers = []
|
|
43
|
+
let currentEchoBatch = null
|
|
39
44
|
const proxy = new PatchProxy(active || {}, patch => {
|
|
40
45
|
if (ctx.applyingExternalUpdate) return
|
|
41
46
|
const activePatch = structuredClone(patch)
|
|
42
47
|
activePatch.forEach(entry => entry.path.unshift('active'))
|
|
43
|
-
|
|
48
|
+
let echoBatch
|
|
49
|
+
if (ctx.syncActive && pendingEchoCallbacks) {
|
|
50
|
+
if (!currentEchoBatch) {
|
|
51
|
+
let resolveEcho
|
|
52
|
+
const echoPromise = new Promise(r => resolveEcho = r)
|
|
53
|
+
echoBatch = currentEchoBatch = { resolve: resolveEcho, resolved: false }
|
|
54
|
+
pendingEchoCallbacks.add(echoPromise)
|
|
55
|
+
echoPromise.then(() => pendingEchoCallbacks.delete(echoPromise))
|
|
56
|
+
Promise.resolve().then(() => { currentEchoBatch = null })
|
|
57
|
+
}
|
|
58
|
+
else echoBatch = currentEchoBatch
|
|
59
|
+
}
|
|
60
|
+
const interactPromise = interact(scope, activePatch)
|
|
61
|
+
const p = interactPromise.then(
|
|
62
|
+
r => {
|
|
63
|
+
ctx.ownInteractions.add(r.ii)
|
|
64
|
+
if (echoBatch) ctx.ownInteractionBatches.set(r.ii, echoBatch)
|
|
65
|
+
ctx.pendingInteractions.delete(p)
|
|
66
|
+
},
|
|
67
|
+
() => {
|
|
68
|
+
if (echoBatch && !echoBatch.resolved) {
|
|
69
|
+
echoBatch.resolved = true
|
|
70
|
+
echoBatch.resolve()
|
|
71
|
+
}
|
|
72
|
+
ctx.pendingInteractions.delete(p)
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
ctx.pendingInteractions.add(p)
|
|
44
76
|
})
|
|
45
77
|
resolveSync(proxy, qualifiedScope)
|
|
46
78
|
resolveState(proxy)
|