@knowlearning/agents 0.9.188 → 0.9.189
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 +56 -0
- package/agents/embedded.js +22 -12
- package/agents/generic/state.js +9 -5
- package/package.json +1 -1
- package/types.d.ts +6 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { applyPatch } from 'fast-json-patch'
|
|
2
|
+
import { standardJSONPatch } from '@knowlearning/patch-proxy'
|
|
3
|
+
|
|
4
|
+
// Wraps a state promise with a .synced(callback?) method that applies external
|
|
5
|
+
// patches to the live proxy in-place.
|
|
6
|
+
//
|
|
7
|
+
// Usage:
|
|
8
|
+
// const promise = attachSynced(watchers, (ctx, resolve) => {
|
|
9
|
+
// const p = new Promise(async (...) => {
|
|
10
|
+
// const proxy = new PatchProxy(data, patch => {
|
|
11
|
+
// if (ctx.applyingExternalUpdate) return
|
|
12
|
+
// // ... interact
|
|
13
|
+
// })
|
|
14
|
+
// resolve(proxy, qualifiedKey)
|
|
15
|
+
// resolvePromise(proxy)
|
|
16
|
+
// })
|
|
17
|
+
// return p
|
|
18
|
+
// })
|
|
19
|
+
export default function attachSynced(watchers, init) {
|
|
20
|
+
const ctx = { applyingExternalUpdate: false }
|
|
21
|
+
let shouldSync = false
|
|
22
|
+
let syncCallbacks = []
|
|
23
|
+
let syncRegistered = false
|
|
24
|
+
let resolvedProxy = null
|
|
25
|
+
let resolvedKey = null
|
|
26
|
+
|
|
27
|
+
function registerSyncWatcher() {
|
|
28
|
+
if (syncRegistered) return
|
|
29
|
+
syncRegistered = true
|
|
30
|
+
if (!watchers[resolvedKey]) watchers[resolvedKey] = []
|
|
31
|
+
watchers[resolvedKey].push(({ patch }) => {
|
|
32
|
+
if (!patch) return
|
|
33
|
+
ctx.applyingExternalUpdate = true
|
|
34
|
+
applyPatch(resolvedProxy, standardJSONPatch(patch))
|
|
35
|
+
ctx.applyingExternalUpdate = false
|
|
36
|
+
syncCallbacks.forEach(cb => cb(resolvedProxy, patch))
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function resolve(proxy, key) {
|
|
41
|
+
resolvedProxy = proxy
|
|
42
|
+
resolvedKey = key
|
|
43
|
+
if (shouldSync) registerSyncWatcher()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const promise = init(ctx, resolve)
|
|
47
|
+
|
|
48
|
+
promise.synced = function(callback) {
|
|
49
|
+
shouldSync = true
|
|
50
|
+
if (callback) syncCallbacks.push(callback)
|
|
51
|
+
if (resolvedProxy) registerSyncWatcher()
|
|
52
|
+
return promise
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return promise
|
|
56
|
+
}
|
package/agents/embedded.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { validate as isUUID, v1 as uuid } from 'uuid'
|
|
2
2
|
import PatchProxy from '@knowlearning/patch-proxy'
|
|
3
|
+
import attachSynced from './attach-synced.js'
|
|
3
4
|
import watchImplementation from './watch.js'
|
|
4
5
|
import sync from './sync.js'
|
|
5
6
|
|
|
@@ -96,18 +97,27 @@ export default function EmbeddedAgent(postMessage) {
|
|
|
96
97
|
return send({ type: 'patch', root, scopes })
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
100
|
+
function state(scope, user, domain) {
|
|
101
|
+
return attachSynced(watchers, (ctx, resolveSync) => (async () => {
|
|
102
|
+
if (scope === undefined) {
|
|
103
|
+
const { context } = await environment()
|
|
104
|
+
scope = JSON.stringify(context)
|
|
105
|
+
}
|
|
106
|
+
const startState = await send({ type: 'state', scope, user, domain })
|
|
107
|
+
const { auth, domain: rootDomain } = await environment()
|
|
108
|
+
const d = !domain || domain === rootDomain ? '' : domain
|
|
109
|
+
const u = !user || auth.user === user ? '' : user
|
|
110
|
+
const key = isUUID(scope) ? scope : `${d}/${u}/${scope}`
|
|
111
|
+
const proxy = new PatchProxy(startState, patch => {
|
|
112
|
+
// TODO: reject updates if user is not owner
|
|
113
|
+
if (ctx.applyingExternalUpdate) return
|
|
114
|
+
const activePatch = structuredClone(patch)
|
|
115
|
+
activePatch.forEach(entry => entry.path.unshift('active'))
|
|
116
|
+
interact(scope, activePatch)
|
|
117
|
+
})
|
|
118
|
+
resolveSync(proxy, key)
|
|
119
|
+
return proxy
|
|
120
|
+
})())
|
|
111
121
|
}
|
|
112
122
|
|
|
113
123
|
function reset(scope) {
|
package/agents/generic/state.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { v4 as uuid, validate as isUUID } from 'uuid'
|
|
2
2
|
import PatchProxy from '@knowlearning/patch-proxy'
|
|
3
|
+
import attachSynced from '../attach-synced.js'
|
|
3
4
|
|
|
4
5
|
export default function(scope='[]', user, domain, { keyToSubscriptionId, watchers, states, create, environment, lastMessageResponse, lastInteractionResponse, interact, log }) {
|
|
5
6
|
let resolveMetadataPromise
|
|
6
7
|
let metadataPromise = new Promise(resolve => resolveMetadataPromise = resolve)
|
|
7
8
|
|
|
8
|
-
const statePromise = new Promise(async (resolveState, rejectState) => {
|
|
9
|
+
const statePromise = attachSynced(watchers, (ctx, resolveSync) => new Promise(async (resolveState, rejectState) => {
|
|
9
10
|
const { auth: { user: u }, domain: d, session } = await environment()
|
|
10
11
|
|
|
11
12
|
const qualifiedScope = isUUID(scope) ? scope : `${!domain || domain === d ? '' : domain}/${!user || user === u ? '' : user}/${scope}`
|
|
@@ -35,17 +36,20 @@ export default function(scope='[]', user, domain, { keyToSubscriptionId, watcher
|
|
|
35
36
|
const active = data.active
|
|
36
37
|
delete data.active
|
|
37
38
|
resolveMetadataPromise(data)
|
|
38
|
-
|
|
39
|
+
const proxy = new PatchProxy(active || {}, patch => {
|
|
40
|
+
if (ctx.applyingExternalUpdate) return
|
|
39
41
|
const activePatch = structuredClone(patch)
|
|
40
42
|
activePatch.forEach(entry => entry.path.unshift('active'))
|
|
41
43
|
interact(scope, activePatch)
|
|
42
|
-
})
|
|
44
|
+
})
|
|
45
|
+
resolveSync(proxy, qualifiedScope)
|
|
46
|
+
resolveState(proxy)
|
|
43
47
|
}
|
|
44
48
|
catch (error) {
|
|
45
49
|
rejectState(error)
|
|
46
50
|
}
|
|
47
|
-
})
|
|
51
|
+
}))
|
|
48
52
|
|
|
49
53
|
statePromise.metadata = metadataPromise
|
|
50
54
|
return statePromise
|
|
51
|
-
}
|
|
55
|
+
}
|
package/package.json
CHANGED
package/types.d.ts
CHANGED
|
@@ -27,11 +27,16 @@ export interface AgentUploadInfo {
|
|
|
27
27
|
accept?: string;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
export interface SyncedStatePromise extends Promise<object> {
|
|
31
|
+
synced(callback?: (state: object, patch: object[]) => void): SyncedStatePromise;
|
|
32
|
+
metadata: Promise<object>;
|
|
33
|
+
}
|
|
34
|
+
|
|
30
35
|
export interface Agent {
|
|
31
36
|
login(provider: string): void;
|
|
32
37
|
logout(): void;
|
|
33
38
|
uuid(): string;
|
|
34
|
-
state(id: string, user?: string, domain?: string):
|
|
39
|
+
state(id: string, user?: string, domain?: string): SyncedStatePromise;
|
|
35
40
|
metadata(id: string, user?: string, domain?: string): Promise<object>;
|
|
36
41
|
watch(id: string, callback: (update: { state: object }) => void, user?: string, domain?: string): void;
|
|
37
42
|
upload(info?: AgentUploadInfo): Promise<string>;
|