@knowlearning/agents 0.3.18 → 0.4.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/agents/browser/embed.js +20 -21
- package/agents/generic.js +25 -26
- package/package.json +1 -1
- package/vue/3/content.vue +2 -6
package/agents/browser/embed.js
CHANGED
|
@@ -95,28 +95,27 @@ export default function embed(environment, iframe) {
|
|
|
95
95
|
|
|
96
96
|
// TODO: make sure content security policy headers for embedded domain always restrict iframe
|
|
97
97
|
// src to only self for embedded domain
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
frameLoaded = true
|
|
103
|
-
processPostMessageQueue()
|
|
104
|
-
}
|
|
105
|
-
const { protocol, pathname } = window.location
|
|
106
|
-
if (validateUUID(environment.content)) {
|
|
107
|
-
// TODO: fix development port workararounds for embed
|
|
108
|
-
if (protocol === 'http:') embed = embed.replace(':32002', ':32020')
|
|
109
|
-
iframe.src = `${protocol}//${embed}${pathname}?s=${session}`
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
iframe.src = environment.content
|
|
113
|
-
}
|
|
98
|
+
iframe.onload = () => {
|
|
99
|
+
frameLoaded = true
|
|
100
|
+
processPostMessageQueue()
|
|
101
|
+
}
|
|
114
102
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
103
|
+
setUpEmbeddedFrame()
|
|
104
|
+
|
|
105
|
+
async function setUpEmbeddedFrame() {
|
|
106
|
+
const { protocol } = window.location
|
|
107
|
+
const { id } = environment
|
|
108
|
+
if (validateUUID(id)) {
|
|
109
|
+
const { domain } = await Agent.metadata(id)
|
|
110
|
+
iframe.src = `${protocol}//${domain}/${id}`
|
|
111
|
+
}
|
|
112
|
+
else iframe.src = id // TODO: ensure is url
|
|
113
|
+
|
|
114
|
+
while(!embeddedAgentInitialized) {
|
|
115
|
+
postMessage({ type: 'setup', session })
|
|
116
|
+
await new Promise(r => setTimeout(r, 100))
|
|
117
|
+
}
|
|
118
|
+
}
|
|
120
119
|
|
|
121
120
|
function remove () {
|
|
122
121
|
if (iframe.parentNode) iframe.parentNode.removeChild(iframe)
|
package/agents/generic.js
CHANGED
|
@@ -39,14 +39,11 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
39
39
|
let lastSentSI = -1
|
|
40
40
|
let lastHeartbeat
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
downloads: {},
|
|
48
|
-
patches: {}
|
|
49
|
-
}
|
|
42
|
+
// TODO: probably an use "mutate" function from below
|
|
43
|
+
const subscriptions = new MutableProxy({}, patch => queueMessage({scope: 'subscriptions', patch}))
|
|
44
|
+
const uploads = new MutableProxy({}, patch => queueMessage({scope: 'uploads', patch}))
|
|
45
|
+
const downloads = new MutableProxy({}, patch => queueMessage({scope: 'downloads', patch}))
|
|
46
|
+
const patches = new MutableProxy({}, patch => queueMessage({scope: 'patches', patch}))
|
|
50
47
|
|
|
51
48
|
log('INITIALIZING AGENT CONNECTION')
|
|
52
49
|
initWS()
|
|
@@ -91,23 +88,25 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
91
88
|
)
|
|
92
89
|
}
|
|
93
90
|
|
|
91
|
+
let restarting = false
|
|
94
92
|
async function restartConnection() {
|
|
95
|
-
if (
|
|
93
|
+
if (restarting) return
|
|
94
|
+
|
|
95
|
+
restarting = true
|
|
96
96
|
authed = false
|
|
97
97
|
ws.onmessage = () => {} // needs to be a no-op since a closing ws can still get messages
|
|
98
98
|
if (!disconnected) {
|
|
99
99
|
await new Promise(r => setTimeout(r, Math.min(1000, failedConnections * 100)))
|
|
100
100
|
failedConnections += 1
|
|
101
101
|
initWS() // TODO: don't do this if we are purposefully unloading...
|
|
102
|
+
restarting = false
|
|
102
103
|
}
|
|
103
104
|
}
|
|
104
105
|
|
|
105
106
|
function initWS() {
|
|
106
107
|
ws = new WebSocket(`${protocol}://${host}`)
|
|
107
108
|
|
|
108
|
-
let opened = false
|
|
109
109
|
ws.onopen = async () => {
|
|
110
|
-
opened = true
|
|
111
110
|
log('AUTHORIZING NEWLY OPENED WS FOR SESSION:', session)
|
|
112
111
|
failedConnections = 0
|
|
113
112
|
ws.send(JSON.stringify({ token: await token(), session }))
|
|
@@ -157,10 +156,10 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
157
156
|
else {
|
|
158
157
|
const key = `${message.domain}/${message.user}/${message.scope}`
|
|
159
158
|
if (watchers[key]) {
|
|
160
|
-
if (
|
|
159
|
+
if (subscriptions[key] + 1 !== message.ii) {
|
|
161
160
|
// TODO: this seems to be an error that happens with decent regularity (an answer with a given si was skipped/failed)
|
|
162
161
|
// we should be wary of out-of-order ii being passed down (maybe need to wait for older ones???)
|
|
163
|
-
console.warn('UNEXPECTED UPDATE INTERACTION INDEX!!!!!!!!!!! last index in session',
|
|
162
|
+
console.warn('UNEXPECTED UPDATE INTERACTION INDEX!!!!!!!!!!! last index in session', subscriptions[key], ' passed index ', message.ii)
|
|
164
163
|
}
|
|
165
164
|
states[key] = await states[key] || {}
|
|
166
165
|
|
|
@@ -169,7 +168,7 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
169
168
|
|
|
170
169
|
applyPatch(states[key], standardJSONPatch(message.patch.slice(lastResetPatchIndex + 1)))
|
|
171
170
|
watchers[key].forEach(fn => fn({ ...message, state: states[key] }))
|
|
172
|
-
|
|
171
|
+
subscriptions[key] = message.ii
|
|
173
172
|
}
|
|
174
173
|
}
|
|
175
174
|
}
|
|
@@ -180,12 +179,11 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
180
179
|
}
|
|
181
180
|
|
|
182
181
|
ws.onerror = async error => {
|
|
183
|
-
log('WS CONNECTION ERROR', error.message
|
|
184
|
-
if (!opened) restartConnection() // onclose won't trigger if never opened
|
|
182
|
+
log('WS CONNECTION ERROR', error.message)
|
|
185
183
|
}
|
|
186
184
|
|
|
187
185
|
ws.onclose = async error => {
|
|
188
|
-
log('WS CLOSURE', error.message
|
|
186
|
+
log('WS CLOSURE', error.message)
|
|
189
187
|
restartConnection()
|
|
190
188
|
}
|
|
191
189
|
|
|
@@ -211,15 +209,15 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
211
209
|
if (states[k] === undefined) {
|
|
212
210
|
watchers[k] = []
|
|
213
211
|
states[k] = new Promise(async resolve => {
|
|
214
|
-
|
|
212
|
+
subscriptions[k] = null
|
|
215
213
|
const { ii, state } = await lastMessageResponse()
|
|
216
|
-
|
|
214
|
+
subscriptions[k] = ii
|
|
217
215
|
resolve(state)
|
|
218
216
|
if (ii === -1) {
|
|
219
217
|
// -1 indicates the result is a computed scope, so
|
|
220
218
|
// ii does not apply (we clear out the subscription to not cache value)
|
|
221
219
|
delete states[k]
|
|
222
|
-
delete
|
|
220
|
+
delete subscriptions[k]
|
|
223
221
|
}
|
|
224
222
|
})
|
|
225
223
|
}
|
|
@@ -249,7 +247,7 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
249
247
|
const k = await key
|
|
250
248
|
removeWatcher(k, watchFn)
|
|
251
249
|
if (watchers[k].length === 0) {
|
|
252
|
-
delete
|
|
250
|
+
delete subscriptions[k]
|
|
253
251
|
delete watchers[k]
|
|
254
252
|
}
|
|
255
253
|
}
|
|
@@ -260,9 +258,9 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
260
258
|
// TODO: if no data, set up streaming upload
|
|
261
259
|
async function upload(name, type, data, id=uuid()) {
|
|
262
260
|
// TODO: include data size info...
|
|
263
|
-
|
|
261
|
+
uploads[id] = { url: null, sent: 0, name, type }
|
|
264
262
|
const { url } = await lastMessageResponse()
|
|
265
|
-
|
|
263
|
+
uploads[id].url = url
|
|
266
264
|
|
|
267
265
|
if (data === undefined) return url
|
|
268
266
|
else {
|
|
@@ -276,9 +274,9 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
276
274
|
}
|
|
277
275
|
|
|
278
276
|
async function download(id, passthrough=false) {
|
|
279
|
-
|
|
277
|
+
downloads[id] = { url: null, size: null, sent: 0 }
|
|
280
278
|
const { url } = await lastMessageResponse()
|
|
281
|
-
|
|
279
|
+
downloads[id].url = url
|
|
282
280
|
|
|
283
281
|
if (passthrough) return url
|
|
284
282
|
else {
|
|
@@ -291,7 +289,7 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
291
289
|
}
|
|
292
290
|
|
|
293
291
|
async function patch(root, scopes) {
|
|
294
|
-
|
|
292
|
+
patches[uuid()] = { root, scopes }
|
|
295
293
|
const { swaps } = await lastMessageResponse()
|
|
296
294
|
return { swaps }
|
|
297
295
|
}
|
|
@@ -333,6 +331,7 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
333
331
|
}
|
|
334
332
|
|
|
335
333
|
async function mutate(scope, initialize=true) {
|
|
334
|
+
// TODO: probably can remove redundant copy
|
|
336
335
|
const initial = initialize ? copy(await state(scope) || {}) : {}
|
|
337
336
|
return new MutableProxy(initial, patch => interact(scope, patch))
|
|
338
337
|
}
|
package/package.json
CHANGED
package/vue/3/content.vue
CHANGED
|
@@ -12,10 +12,6 @@ export default {
|
|
|
12
12
|
id: {
|
|
13
13
|
type: String,
|
|
14
14
|
required: true
|
|
15
|
-
},
|
|
16
|
-
scope: {
|
|
17
|
-
type: String,
|
|
18
|
-
required: false
|
|
19
15
|
}
|
|
20
16
|
},
|
|
21
17
|
unmounted() {
|
|
@@ -25,9 +21,9 @@ export default {
|
|
|
25
21
|
setup(iframe) {
|
|
26
22
|
if (!iframe || this.iframe === iframe) return
|
|
27
23
|
|
|
28
|
-
const { id
|
|
24
|
+
const { id } = this
|
|
29
25
|
this.iframe = iframe
|
|
30
|
-
this.embedding = Agent.embed({
|
|
26
|
+
this.embedding = Agent.embed({ id }, iframe)
|
|
31
27
|
|
|
32
28
|
/*
|
|
33
29
|
const { handle } = this.embedding
|