@knowlearning/agents 0.9.7 → 0.9.9

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 CHANGED
@@ -2,6 +2,7 @@ import MutableProxy from '../persistence/json.js'
2
2
  import download from './download.js'
3
3
 
4
4
  const HEARTBEAT_TIMEOUT = 10000
5
+ const SESSION_TYPE = 'application/json;type=session'
5
6
  const UPLOAD_TYPE = 'application/json;type=upload'
6
7
  const SUBSCRIPTION_TYPE = 'application/json;type=subscription'
7
8
  const POSTGRES_QUERY_TYPE = 'application/json;type=postgres-query'
@@ -23,6 +24,12 @@ function sanitizeJSONPatchPathSegment(s) {
23
24
  else return s
24
25
  }
25
26
 
27
+ const sessionMetrics = {
28
+ loaded: Date.now(),
29
+ connected: null,
30
+ authenticated: null
31
+ }
32
+
26
33
  export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fetch, applyPatch, login, logout, reboot }) {
27
34
  let ws
28
35
  let user
@@ -119,6 +126,7 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
119
126
  ws = new WebSocket(`${protocol}://${host}`)
120
127
 
121
128
  ws.onopen = async () => {
129
+ if (!sessionMetrics.connected) sessionMetrics.connected = Date.now()
122
130
  log('AUTHORIZING NEWLY OPENED WS FOR SESSION:', session)
123
131
  failedConnections = 0
124
132
  ws.send(JSON.stringify({ token: await token(), session }))
@@ -141,10 +149,18 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
141
149
 
142
150
  authed = true
143
151
  if (!user) { // this is the first authed websocket connection
152
+ sessionMetrics.authenticated = Date.now()
144
153
  user = message.auth.user
145
154
  session = message.session
146
155
  domain = message.domain
147
156
  server = message.server
157
+
158
+ // save session metrics
159
+ interact(session, [
160
+ {op: 'add', path: ['active', 'loaded'], value: sessionMetrics.loaded },
161
+ {op: 'add', path: ['active', 'connected'], value: sessionMetrics.connected },
162
+ {op: 'add', path: ['active', 'authenticated'], value: sessionMetrics.authenticated },
163
+ ])
148
164
  resolveEnvironment(message)
149
165
  }
150
166
  else if (server !== message.server) {
@@ -248,30 +264,19 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
248
264
  create({
249
265
  id,
250
266
  active_type: SUBSCRIPTION_TYPE,
251
- active: { session, scope, ii: null }
267
+ active: { session, scope, ii: null, initialized: Date.now() },
252
268
  })
253
269
 
254
270
  try {
255
271
  const state = await lastMessageResponse()
256
- // TODO: replace with editing scope of type
257
- interact(id, [{
258
- op: 'add',
259
- path: ['active', 'ii'],
260
- value: 1 // TODO: use state.ii when is coming down properly...
261
- }])
272
+ interact(id, [
273
+ { op: 'add', path: ['active', 'ii'], value: 1 }, // TODO: use state.ii when is coming down properly...
274
+ { op: 'add', path: ['active', 'synced'], value: Date.now() }
275
+ ])
262
276
 
263
277
  resolve(state)
264
-
265
- if (state.ii === -1) {
266
- // -1 indicates the result is a computed scope, so
267
- // ii does not apply (we clear out the subscription to not cache value)
268
- delete states[scope]
269
- delete keyToSubscriptionId[scope]
270
- }
271
- }
272
- catch (error) {
273
- reject(error)
274
278
  }
279
+ catch (error) { reject(error) }
275
280
  })
276
281
  }
277
282
 
@@ -424,11 +429,14 @@ export default function Agent({ host, token, WebSocket, protocol='ws', uuid, fet
424
429
  }
425
430
 
426
431
  async function query(query, params, domain) {
432
+ const id = uuid()
427
433
  create({
434
+ id,
428
435
  active_type: POSTGRES_QUERY_TYPE,
429
- active: { query, params, domain }
436
+ active: { query, params, domain, requested: Date.now() },
430
437
  })
431
438
  const { rows } = await lastMessageResponse()
439
+ interact(id, [{ op: 'add', path: ['active', 'responded'], value: Date.now() }])
432
440
  return rows
433
441
  }
434
442
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knowlearning/agents",
3
- "version": "0.9.7",
3
+ "version": "0.9.9",
4
4
  "description": "API for embedding applications in KnowLearning systems.",
5
5
  "main": "node.js",
6
6
  "browser": "browser.js",
@@ -0,0 +1,51 @@
1
+ <template>
2
+ <pre v-if="state">{{value}}</pre>
3
+ <span v-else>loading...</span>
4
+ </template>
5
+
6
+ <script>
7
+
8
+ export default {
9
+ props: {
10
+ id: String,
11
+ path: {
12
+ type: Array,
13
+ default: []
14
+ }
15
+ },
16
+ data() {
17
+ return {
18
+ state: null
19
+ }
20
+ },
21
+ watch: {
22
+ id() {
23
+ this.stopWatching()
24
+ this.startWatching()
25
+ }
26
+ },
27
+ mounted() {
28
+ this.startWatching()
29
+ },
30
+ unmounted() {
31
+ this.stopWatching()
32
+ },
33
+ computed: {
34
+ value() {
35
+ if (this.path.length === 0) return this.state
36
+
37
+ return (
38
+ this
39
+ .path
40
+ .reduce((acc, field) => acc?.[field], this.state)
41
+ )
42
+ }
43
+ },
44
+ methods: {
45
+ startWatching() {
46
+ this.stopWatching = Agent.watch(this.id, ({ state }) => this.state = state)
47
+ }
48
+ }
49
+ }
50
+
51
+ </script>
@@ -1,5 +1,5 @@
1
1
  import { watchEffect, defineAsyncComponent } from 'vue'
2
- import { browserAgent } from '../../browser.js'
2
+ import { browserAgent } from '../../../browser.js'
3
3
 
4
4
  const Agent = browserAgent()
5
5
 
@@ -1,4 +1,4 @@
1
- import MutableProxy from './json.js'
1
+ import MutableProxy from '../../../persistence/json.js'
2
2
 
3
3
  // TODO: consider path serialization approach. Also consider just using a mutable proxy from agent.state...
4
4
 
@@ -9,12 +9,12 @@ async function scopeIsUninitialized(scope) {
9
9
  return Object.keys(await Agent.state(scope)).length === 0
10
10
  }
11
11
 
12
- export default async function (storeDefinition, scope=window.location.host) {
12
+ export default async function (storeDefinition, scope) {
13
13
  let state = copy(await Agent.state(scope))
14
14
  const scopedPaths = getScopedPaths(storeDefinition)
15
15
  const stateAttachedStore = await attachModuleState(state, storeDefinition, scopedPaths)
16
16
  const s = stateAttachedStore.state
17
- const originalState = s instanceof Function ? s() : s
17
+ const originalState = s instanceof Function ? s() : s
18
18
 
19
19
  const handlePatch = patch => {
20
20
  patch.forEach(({ path }) => path.unshift('active'))
@@ -72,11 +72,12 @@ async function attachModuleState(state, module, scopedPaths, path='') {
72
72
  const ephemeralPaths = descendantPaths(path, scopedPaths)
73
73
  state = MutableProxy(copy(initState), handlePatch, ephemeralPaths)
74
74
  if (await scopeIsUninitialized(scope)) {
75
- Object.assign(state, module.state())
75
+ Object.assign(state, module.state instanceof Function ? module.state() : module.state)
76
76
  }
77
77
  return { ...module, state: () => state }
78
78
  }
79
- else return state ? { ...module, state: () => state } : module
79
+ // TODO: better check for initialized state
80
+ else return Object.keys(state).length ? { ...module, state: () => state } : module
80
81
  }
81
82
 
82
83
  function getScopedPaths(module, path="", paths={}) {
package/vue.js CHANGED
@@ -1,4 +1,5 @@
1
- export { default as vuePersistentStore } from './persistence/vuex.js'
2
- export { default as vueEmbedComponent } from './vue/3/content.vue'
3
- export { default as vueNameComponent } from './vue/3/name.vue'
4
- export { default as vuePersistentComponent } from './vue/3/component.js'
1
+ export { default as vuePersistentStore } from './vue/3/persist/vuex.js'
2
+ export { default as vuePersistentComponent } from './vue/3/persist/component.js'
3
+ export { default as vueEmbedComponent } from './vue/3/components/content.vue'
4
+ export { default as vueNameComponent } from './vue/3/components/name.vue'
5
+ export { default as vueScopeComponent } from './vue/3/components/scope.vue'
File without changes
File without changes