@knowlearning/agents 0.9.16 → 0.9.18
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/generic.js +73 -13
- package/package.json +1 -1
- package/vue/3/components/scope.vue +12 -29
package/agents/generic.js
CHANGED
|
@@ -56,6 +56,8 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
56
56
|
const environmentPromise = new Promise(r => resolveEnvironment = r)
|
|
57
57
|
let lastSentSI = -1
|
|
58
58
|
let lastHeartbeat
|
|
59
|
+
let lastSynchronousScopePatched = null
|
|
60
|
+
let lastSynchronousScopePatchPromise = null
|
|
59
61
|
const syncedPromiseResolutions = []
|
|
60
62
|
|
|
61
63
|
const patches = state('patches')
|
|
@@ -77,12 +79,20 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
77
79
|
if (watcherIndex > -1) watchers[key].splice(watcherIndex, 1)
|
|
78
80
|
else console.warn('TRIED TO REMOVE WATCHER THAT DOES NOT EXIST')
|
|
79
81
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
|
|
83
|
+
// TODO: clear acknowledged messages
|
|
84
|
+
async function flushMessageQueue() {
|
|
85
|
+
// this makes flushing async, giving time for queue message to combine synchronous updates
|
|
86
|
+
await new Promise(resolve => resolve())
|
|
87
|
+
lastSynchronousScopePatched = null
|
|
88
|
+
|
|
83
89
|
while (authed && ws.readyState === WebSocket.OPEN && lastSentSI+1 < messageQueue.length) {
|
|
90
|
+
lastSynchronousScopePatched = null
|
|
84
91
|
lastSentSI += 1
|
|
85
92
|
ws.send(JSON.stringify(messageQueue[lastSentSI]))
|
|
93
|
+
|
|
94
|
+
// async so we don't try and push more to a closed connection
|
|
95
|
+
await new Promise(resolve => resolve())
|
|
86
96
|
}
|
|
87
97
|
}
|
|
88
98
|
|
|
@@ -90,13 +100,21 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
90
100
|
return new Promise((resolve, reject) => responses[si].push([resolve, reject]))
|
|
91
101
|
}
|
|
92
102
|
|
|
93
|
-
function queueMessage(
|
|
103
|
+
function queueMessage({ scope, patch }) {
|
|
94
104
|
isSynced = false
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
105
|
+
if (lastSynchronousScopePatched === scope) {
|
|
106
|
+
const i = messageQueue.length - 1
|
|
107
|
+
messageQueue[i].patch = [...messageQueue[i].patch, ...patch]
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
si += 1
|
|
111
|
+
lastSynchronousScopePatchPromise = new Promise((resolve, reject) => responses[si] = [[resolve, reject]])
|
|
112
|
+
messageQueue.push({ scope, patch, si, ts: Date.now()})
|
|
113
|
+
lastSynchronousScopePatched = scope
|
|
114
|
+
flushMessageQueue()
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return lastSynchronousScopePatchPromise
|
|
100
118
|
}
|
|
101
119
|
|
|
102
120
|
function checkHeartbeat() {
|
|
@@ -114,11 +132,11 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
114
132
|
async function restartConnection() {
|
|
115
133
|
if (restarting) return
|
|
116
134
|
|
|
117
|
-
restarting = true
|
|
118
135
|
authed = false
|
|
119
|
-
ws.onmessage = () => {} // needs to be a no-op since a closing ws can still get messages
|
|
120
136
|
if (!disconnected) {
|
|
121
137
|
await new Promise(r => setTimeout(r, Math.min(1000, failedConnections * 100)))
|
|
138
|
+
ws.onmessage = () => {} // needs to be a no-op since a closing ws can still get messages
|
|
139
|
+
restarting = true
|
|
122
140
|
failedConnections += 1
|
|
123
141
|
initWS() // TODO: don't do this if we are purposefully unloading...
|
|
124
142
|
restarting = false
|
|
@@ -231,8 +249,12 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
231
249
|
|
|
232
250
|
function create({ id=uuid(), active_type, active, name }) {
|
|
233
251
|
// TODO: collapse into 1 patch and 1 interact call
|
|
234
|
-
|
|
235
|
-
|
|
252
|
+
// (requires updating side effects)
|
|
253
|
+
const patch = [
|
|
254
|
+
{ op: 'add', path: ['active_type'], value: active_type },
|
|
255
|
+
{ op: 'add', path: ['active'], value: active }
|
|
256
|
+
]
|
|
257
|
+
interact(id, patch, false)
|
|
236
258
|
return id
|
|
237
259
|
}
|
|
238
260
|
|
|
@@ -300,7 +322,45 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
|
|
|
300
322
|
})
|
|
301
323
|
}
|
|
302
324
|
|
|
325
|
+
function watchResolution(path, callback) {
|
|
326
|
+
const id = path[0]
|
|
327
|
+
const references = path.slice(1)
|
|
328
|
+
let unwatchDeeper = () => {}
|
|
329
|
+
|
|
330
|
+
const unwatch = watch(id, ({ state }) => {
|
|
331
|
+
if (references.length === 0) {
|
|
332
|
+
callback(value)
|
|
333
|
+
return
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// TODO: check if value we care about actually changed
|
|
337
|
+
// and ignore this update if it has not.
|
|
338
|
+
unwatchDeeper()
|
|
339
|
+
|
|
340
|
+
let value = state
|
|
341
|
+
for (let index = 0; index < references.length; index += 1) {
|
|
342
|
+
value = value[references[index]]
|
|
343
|
+
if (
|
|
344
|
+
value === null ||
|
|
345
|
+
value === undefined ||
|
|
346
|
+
index === references.length - 1
|
|
347
|
+
) callback(value)
|
|
348
|
+
else if (isUUID(value)) {
|
|
349
|
+
unwatchDeeper = watchResolution([value, ...references.slice(index + 1)], callback)
|
|
350
|
+
return
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
return () => {
|
|
356
|
+
unwatch()
|
|
357
|
+
unwatchDeeper()
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
303
361
|
function watch(scope=DEFAULT_SCOPE_NAME, fn) {
|
|
362
|
+
if (Array.isArray(scope)) return watchResolution(scope, fn)
|
|
363
|
+
|
|
304
364
|
let initialSent = false
|
|
305
365
|
const queue = []
|
|
306
366
|
function cb(update) {
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<span v-if="
|
|
2
|
+
<span v-if="value">{{ value === null && placeholder ? placeholder : value }}</span>
|
|
3
3
|
<span v-else>loading...</span>
|
|
4
4
|
</template>
|
|
5
5
|
|
|
@@ -8,46 +8,29 @@
|
|
|
8
8
|
export default {
|
|
9
9
|
props: {
|
|
10
10
|
id: String,
|
|
11
|
-
path: {
|
|
12
|
-
|
|
13
|
-
default: []
|
|
14
|
-
},
|
|
15
|
-
placeholder: {
|
|
16
|
-
type: String,
|
|
17
|
-
default: ''
|
|
18
|
-
}
|
|
11
|
+
path: { type: Array, default: [] },
|
|
12
|
+
placeholder: { type: String, default: '' }
|
|
19
13
|
},
|
|
20
14
|
data() {
|
|
21
15
|
return {
|
|
22
|
-
|
|
16
|
+
value: undefined
|
|
23
17
|
}
|
|
24
18
|
},
|
|
25
19
|
watch: {
|
|
26
|
-
id() {
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
id() { this.startWatching() },
|
|
21
|
+
path: {
|
|
22
|
+
deep: true,
|
|
23
|
+
handler() { this.startWatching() }
|
|
29
24
|
}
|
|
30
25
|
},
|
|
31
|
-
|
|
32
|
-
this.startWatching()
|
|
33
|
-
},
|
|
26
|
+
created() { this.startWatching() },
|
|
34
27
|
unmounted() {
|
|
35
|
-
this.stopWatching()
|
|
36
|
-
},
|
|
37
|
-
computed: {
|
|
38
|
-
value() {
|
|
39
|
-
if (this.path.length === 0) return this.state
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
this
|
|
43
|
-
.path
|
|
44
|
-
.reduce((acc, field) => acc?.[field], this.state)
|
|
45
|
-
)
|
|
46
|
-
}
|
|
28
|
+
if (this.startWatching) this.stopWatching()
|
|
47
29
|
},
|
|
48
30
|
methods: {
|
|
49
31
|
startWatching() {
|
|
50
|
-
|
|
32
|
+
if (this.startWatching) this.stopWatching()
|
|
33
|
+
this.stopWatching = Agent.watch([this.id, ...path], value => this.value = value)
|
|
51
34
|
}
|
|
52
35
|
}
|
|
53
36
|
}
|