theprogrammablemind 7.5.8-beta.4 → 7.5.8-beta.40

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/src/config.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // lookup = (name) => returns <config>
2
2
  const { Semantics, normalizeGenerator } = require('./semantics')
3
3
  const { Generators } = require('./generators')
4
- // const { uuid: uuidv4 } = require('uuidv4')
4
+ const { v4 : uuidv4 } = require('uuid');
5
5
  const client = require('../client')
6
6
  const DigraphInternal = require('./digraph_internal')
7
7
  const helpers = require('./helpers')
@@ -22,7 +22,144 @@ const indent = (string, indent) => {
22
22
  return string.replace(/^/gm, ' '.repeat(indent));
23
23
  }
24
24
 
25
- const handleBridgeProps = (config, bridge) => {
25
+ const config_toServer = (config) => {
26
+ if (config.contextual_priorities) {
27
+ config.contextual_priorities = config.contextual_priorities.map((cp) => {
28
+ return [cp.context, cp.choose]
29
+ })
30
+ }
31
+ }
32
+
33
+ const validConfigProps = (config) => {
34
+ const valid = [
35
+ 'hierarchy',
36
+ 'objects',
37
+ 'bridges',
38
+ 'operators',
39
+ 'words',
40
+ 'priorities',
41
+ 'contextual_priorities',
42
+ 'associations',
43
+ 'name',
44
+ 'version',
45
+ 'generatorp',
46
+ 'generators',
47
+ 'semantics',
48
+ 'where',
49
+ 'floaters',
50
+ 'debug',
51
+
52
+ // TODO Fix these from the test app
53
+ 'implicits',
54
+ 'convolution',
55
+ 'expected_generated',
56
+ 'expected_results',
57
+ 'skipSemantics',
58
+ 'description',
59
+ 'contexts',
60
+ 'utterances',
61
+ 'flatten',
62
+
63
+ 'namespaces',
64
+ 'eqClasses',
65
+ ]
66
+ helpers.validProps(valid, config, 'config')
67
+ }
68
+
69
+ const setupInitializerFNArgs = (config, args) => {
70
+ const aw = (word, def) => config.addWord(word, def, args.uuid)
71
+ const ag = (generator) => config.addGenerator(generator, args.uuid, config.name)
72
+ const km = (name) => config.getConfig(name)
73
+ const apis = (name) => config.getConfig(name).api
74
+
75
+ return {
76
+ ...args,
77
+ addWord: aw,
78
+ addGenerator: ag,
79
+ config: config.getPseudoConfig(args.uuid, args.currentConfig),
80
+ km,
81
+ baseConfig: config,
82
+ apis,
83
+ }
84
+ }
85
+
86
+ const contextual_priorities_toServer = (cp) => {
87
+ if (cp.context && cp.choose) {
88
+ return [cp.context, cp.choose]
89
+ }
90
+ return cp
91
+ }
92
+
93
+ const contextual_priorities_toClient = (cp) => {
94
+ if (cp.context && cp.choose) {
95
+ return cp
96
+ }
97
+ return { context: cp[0], choose: cp[1] }
98
+ }
99
+
100
+ const operatorKey_valid = (key) => {
101
+ if (
102
+ !_.isArray(key) ||
103
+ key.length != 2 ||
104
+ !_.isString(key[0]) ||
105
+ !_.isInteger(key[1]) ||
106
+ key[1] < 0
107
+ ) {
108
+
109
+ let details = ''
110
+ if (!_.isArray(key)) {
111
+ details = "Expected an array."
112
+ } else if (key.length != 2) {
113
+ details = "Expected an array of length two."
114
+ } else if (!_.isString(key[0])) {
115
+ details = "Expected element zero to be a string that is an operator id."
116
+ } else if (!_.isInteger(key[1])) {
117
+ details = "Expected element one to be a number that is an operator level."
118
+ } else if (key[1] < 0) {
119
+ details = "Expected element one to be a number that is an operator level which is greater than zero."
120
+ }
121
+ throw new Error(`${JSON.stringify(key)} is not a valid operator key. Values are of the form [<operatorId>, <operatorLevel>]. ${details}`)
122
+ }
123
+ }
124
+
125
+ const elist = (list, check, prefix) => {
126
+ for ([index, element] of list.entries()) {
127
+ try {
128
+ check(element)
129
+ } catch( e ) {
130
+ throw new Error(prefix(index, e))
131
+ }
132
+ }
133
+ }
134
+ const contextual_priorities_valid = (cps) => {
135
+ elist(cps, (cp) => contextual_priority_valid(cp), (index, e) => `contextual_priorities has an invalid contextual priority at position ${index}. ${e}`)
136
+ }
137
+
138
+ const contextual_priority_valid = (cp) => {
139
+ if (!cp.context) {
140
+ throw new Error(`The contextual priority ${JSON.stringify(cp)} is missing the "context" property. That is a list of the operator keys that are to be prioritized differently.`)
141
+ }
142
+ if (!_.isArray(cp.context)) {
143
+ throw new Error(`The contextual priority ${JSON.stringify(cp)} has an invalid "context" value. That is a list of the operator keys that are to be prioritized differently.`)
144
+ }
145
+ elist(cp.context, (element) => operatorKey_valid(element), (index, e) => `The contextual priority ${JSON.stringify(cp)} has an invalid operator key at position ${index}. ${e}`)
146
+ if (!_.isArray(cp.choose)) {
147
+ throw new Error(`The contextual priority ${JSON.stringify(cp)} has an invalid "choose" value. The value should be a list of the operators in the context to consider for prioritization.`)
148
+ }
149
+ elist(cp.choose,
150
+ (element) => {
151
+ if (!element && element !== 0) {
152
+ throw new Error(`The value should be an index into the "context" property of the operator that is to be considered for prioritization.`)
153
+ }
154
+ if (!_.isInteger(element) || element < 0 || element >= cp.context.length) {
155
+ throw new Error(`The value should be an index into the "context" property of the operator that is to be considered for prioritization. Valid values are between 0 and ${cp.context.length-1}.`)
156
+ }
157
+ },
158
+ (index, e) => `The choose property in the contextual priority ${JSON.stringify(cp)} has an invalid index at position ${index}. ${e}`
159
+ )
160
+ }
161
+
162
+ const handleBridgeProps = (config, bridge, addFirst) => {
26
163
  ecatch(`While processing the bridge for ${bridge.id}#${bridge.level}`,
27
164
  () => {
28
165
  if (!bridge.bridge) {
@@ -68,19 +205,29 @@ const handleBridgeProps = (config, bridge) => {
68
205
  config.addWordInternal(def, {"id": bridge.id, "initial": `{ value: "${def}"}` })
69
206
  } else {
70
207
  const word = def.word
71
- def = { initial: JSON.stringify(def), id: bridge.id, word: undefined }
208
+ def = { initial: JSON.stringify(def), id: bridge.id, word }
72
209
  config.addWordInternal(word, def)
73
210
  }
74
211
  }
75
212
  }
213
+ /*
76
214
  if (bridge.generator) {
77
- config.config.generators.unshift(bridge.generator)
215
+ if (addFirst) {
216
+ config.config.generators.unshift(bridge.generator)
217
+ } else {
218
+ config.config.generators.push(bridge.generator)
219
+ }
78
220
  }
221
+ */
79
222
  if (bridge.generators) {
80
223
  const generators = [...bridge.generators]
81
224
  generators.reverse()
82
225
  for (let generator of generators) {
83
- config.config.generators.unshift(generator)
226
+ if (addFirst) {
227
+ config.config.generators.unshift(generator)
228
+ } else {
229
+ config.config.generators.push(generator)
230
+ }
84
231
  }
85
232
  }
86
233
  if (bridge.generatorpr) {
@@ -91,66 +238,76 @@ const handleBridgeProps = (config, bridge) => {
91
238
  const match = bridge.generatorp.match || (() => true)
92
239
  const apply = typeof bridge.generatorp == 'function' ? bridge.generatorp : bridge.generatorp.apply || bridge.generatorp
93
240
  const level = bridge.generatorp.level >= 0 ? bridge.generatorp.level : bridge.level + 1
94
- config.config.generators.unshift({
241
+
242
+ const generator = {
95
243
  where: bridge.generatorp.where || bridge.where || client.where(4),
96
244
  match: (args) => bridge.id == args.context.marker && args.context.level == level && args.context.paraphrase && match(args),
97
245
  apply: (args) => apply(args),
98
246
  applyWrapped: apply,
99
247
  property: 'generatorp',
100
- })
248
+ }
249
+ if (addFirst) {
250
+ config.config.generators.unshift(generator)
251
+ } else {
252
+ config.config.generators.push(generator)
253
+ }
254
+
101
255
  }
102
256
  if (bridge.generatorr) {
103
257
  const match = bridge.generatorr.match || (() => true)
104
258
  const apply = typeof bridge.generatorr == 'function' ? bridge.generatorr : bridge.generatorr.apply || bridge.generatorr
105
259
  const level = bridge.generatorr.level >= 0 ? bridge.generatorr.level : bridge.level + 1
106
- config.config.generators.unshift({
260
+ const generator = {
107
261
  where: bridge.generatorr.where || bridge.where || client.where(4),
108
262
  match: (args) => bridge.id == args.context.marker && args.context.level == level && !args.context.paraphrase && (args.context.response || args.context.isResponse) && match(args),
109
263
  apply: (args) => apply(args),
110
264
  applyWrapped: apply,
111
265
  property: 'generatorr',
112
- })
113
- }
114
- /*
115
- if (bridge.generatorr) {
116
- config.config.generators.unshift({
117
- // TODO merge response and isResponse
118
- where: bridge.generatorr.where || bridge.where || client.where(3),
119
- match: ({context}) => bridge.id == context.marker && !context.paraphrase && (context.response || context.isResponse),
120
- apply: (args) => bridge.generatorr(args),
121
- applyWrapped: bridge.generatorr,
122
- property: 'generatorr',
123
- })
266
+ }
267
+ if (addFirst) {
268
+ config.config.generators.unshift(generator)
269
+ } else {
270
+ config.config.generators.push(generator)
271
+ }
124
272
  }
125
- */
126
273
  if (bridge.evaluator) {
127
- config.config.semantics.unshift({
274
+ const semantic = {
128
275
  where: bridge.evaluator.where || bridge.where || client.where(3),
129
276
  match: ({context}) => bridge.id == context.marker && context.evaluate,
130
277
  apply: (args) => bridge.evaluator(args),
131
278
  applyWrapped: bridge.evaluator,
132
279
  property: 'evaluator',
133
- })
280
+ }
281
+ if (addFirst) {
282
+ config.config.semantics.unshift(semantic)
283
+ } else {
284
+ config.config.semantics.push(semantic)
285
+ }
134
286
  }
135
287
  if (bridge.semantic) {
136
- config.config.semantics.unshift({
288
+ const semantic = {
137
289
  where: bridge.semantic.where || bridge.where || client.where(3),
138
290
  match: ({context}) => bridge.id == context.marker,
139
291
  apply: (args) => bridge.semantic(args),
140
292
  applyWrapped: bridge.semantic,
141
293
  property: 'semantic',
142
- })
294
+ }
295
+ if (addFirst) {
296
+ config.config.semantics.unshift(semantic)
297
+ } else {
298
+ config.config.semantics.push(semantic)
299
+ }
143
300
  }
144
301
  }
145
302
  )
146
303
  }
147
304
 
148
- const handleCalculatedProps = (baseConfig, moreConfig) => {
149
- for (let bridge of moreConfig.bridges) {
305
+ const handleCalculatedProps = (baseConfig, moreConfig, addFirst) => {
306
+ for (let bridge of (moreConfig.bridges || [])) {
150
307
  const valid = [ 'after', 'before', 'bridge', 'development', 'evaluator', 'generatorp', 'generatorr', 'generatorpr', 'generators', 'id', 'convolution', 'inverted', 'isA', 'children', 'parents',
151
- 'level', 'optional', 'selector', 'semantic', 'words', /Bridge$/, 'localHierarchy', 'levelSpecificHierarchy', 'where' ]
308
+ 'level', 'optional', 'selector', 'semantic', 'words', /Bridge$/, 'localHierarchy', 'levelSpecificHierarchy', 'where', 'uuid' ]
152
309
  helpers.validProps(valid, bridge, 'bridge')
153
- handleBridgeProps(baseConfig, bridge)
310
+ handleBridgeProps(baseConfig, bridge, addFirst)
154
311
  }
155
312
  if (moreConfig.operators) {
156
313
  moreConfig.operators = moreConfig.operators.map((operator) => {
@@ -171,6 +328,10 @@ if (runtime.process.env.DEBUG_PRIORITY) {
171
328
  global.entodictonDebugPriority = JSON.parse(runtime.process.env.DEBUG_PRIORITY)
172
329
  }
173
330
 
331
+ if (runtime.process.env.DEBUG_CONTEXTUAL_PRIORITY) {
332
+ global.entodictonDebugContextualPriority = JSON.parse(runtime.process.env.DEBUG_CONTEXTUAL_PRIORITY)
333
+ }
334
+
174
335
  if (runtime.process.env.DEBUG_ASSOCIATION) {
175
336
  global.entodictonDebugAssociation = JSON.parse(runtime.process.env.DEBUG_ASSOCIATION)
176
337
  }
@@ -252,6 +413,14 @@ const normalizeConfig = (config) => {
252
413
  }
253
414
  }
254
415
  }
416
+
417
+ if (config.semantics) {
418
+ for (let semantic of config.semantics) {
419
+ if (semantic.oneShot) {
420
+ semantic.id = uuid()
421
+ }
422
+ }
423
+ }
255
424
  }
256
425
  }
257
426
 
@@ -459,8 +628,8 @@ const multiApiImpl = (initializer) => {
459
628
  initializer(config, api)
460
629
  const name = api.getName()
461
630
  multiApi.apis[name] = api
462
- api.objects = config.get('objects')
463
- api.config = () => config
631
+ // api.objects = config.get('objects')
632
+ // api.config = () => config
464
633
  multiApi.current = name
465
634
  },
466
635
 
@@ -471,11 +640,13 @@ const multiApiImpl = (initializer) => {
471
640
  }
472
641
  },
473
642
 
643
+ /*
474
644
  set objects (value) {
475
645
  for (const key in Object.keys(this.apis)) {
476
646
  this.apis[key].objects = value
477
647
  }
478
648
  },
649
+ */
479
650
 
480
651
  // "product1": apiInstance(testData1),
481
652
  apis: {
@@ -489,6 +660,46 @@ const multiApiImpl = (initializer) => {
489
660
 
490
661
  class Config {
491
662
 
663
+ toServer (config) {
664
+ return config_toServer(config)
665
+ }
666
+
667
+ base () {
668
+ const base = new Config()
669
+ for (let km of this.configs.reverse()) {
670
+ if (km.isSelf) {
671
+ continue
672
+ }
673
+ base.add(km.config)
674
+ }
675
+ return base
676
+ }
677
+
678
+ getPseudoConfig (uuid, config) {
679
+ return {
680
+ description: "this is a pseudo config that has limited functionality due to being available in the initializer function context",
681
+ addAssociation: (...args) => this.addAssociation(...args),
682
+ addAssociations: (...args) => this.addAssociations(...args),
683
+ addBridge: (...args) => this.addBridge(...args, uuid),
684
+ addContextualPriority: (...args) => this.addContextualPriority(...args),
685
+ addGenerator: (...args) => this.addGenerator(...args, uuid, config.name),
686
+ addHierarchy: (...args) => this.addHierarchy(...args),
687
+ addOperator: (...args) => this.addOperator(...args, uuid),
688
+ addPriorities: (...args) => this.addPriorities(...args),
689
+ addSemantic: (...args) => this.addSemantic(...args, uuid, config.name),
690
+ removeSemantic: (...args) => this.removeSemantic(...args, uuid, config.name),
691
+ addWord: (...args) => this.addWord(...args, uuid),
692
+
693
+ getHierarchy: (...args) => this.config.hierarchy,
694
+ getBridges: (...args) => this.config.bridges,
695
+
696
+ addArgs: (...args) => this.addArgs(...args),
697
+ getBridge: (...args) => this.getBridge(...args),
698
+ fragment: (...args) => this.fragment(...args),
699
+ addAPI: (...args) => this.addAPI(...args),
700
+ }
701
+ }
702
+
492
703
  inDevelopmentMode (call) {
493
704
  config.developmentModeOn += 1
494
705
  try {
@@ -527,9 +738,6 @@ class Config {
527
738
  }
528
739
 
529
740
  setTestConfig(testConfig) {
530
- if (this.name == 'ui') {
531
- console.log('ui setting testConfig')
532
- }
533
741
  this.testConfig = testConfig
534
742
  }
535
743
 
@@ -548,6 +756,7 @@ class Config {
548
756
  },
549
757
  eqClasses: [],
550
758
  priorities: [], // Done
759
+ contextual_priorities: [],
551
760
  version: '3',
552
761
  debug: false,
553
762
  associations: { // Done
@@ -586,6 +795,7 @@ class Config {
586
795
  'namespaces',
587
796
  'eqClasses',
588
797
  'priorities',
798
+ 'contextual_priorities',
589
799
  'associations',
590
800
  'words',
591
801
  'floaters',
@@ -739,6 +949,12 @@ class Config {
739
949
  }
740
950
  }
741
951
 
952
+ toData (data) {
953
+ Object.assign(data, this.config)
954
+ config_toServer(data)
955
+ }
956
+
957
+ // loadTemplate
742
958
  load (template, instance, options = { rebuild: false } ) {
743
959
  this.validifyTemplate(template)
744
960
  instance.template = template
@@ -750,7 +966,7 @@ class Config {
750
966
  // TODO fix beforeQuery
751
967
  template = { fragments: [], queries: [], ...template }
752
968
  template.fragments = template.fragments.concat(this.dynamicFragments)
753
- client.build({ config: this, target: this.name, beforeQuery: () => {}, template, ...options })
969
+ client.rebuildTemplate({ config: this, target: this.name, beforeQuery: () => {}, template, ...options })
754
970
  } else {
755
971
  // no change
756
972
  // this.initInstances.push({ ...instance, name: config.name })
@@ -768,7 +984,7 @@ class Config {
768
984
  instance.name = this.name
769
985
  this.initInstances.push(instance)
770
986
  this.instances.push(instance)
771
- client.processInstance(this, instance)
987
+ client.loadInstance(this, instance)
772
988
  }
773
989
  }
774
990
  }
@@ -825,6 +1041,22 @@ class Config {
825
1041
  this._delta.json.priorities.push({ action: 'add', priorities })
826
1042
  }
827
1043
 
1044
+ // [ operators: <list of [id, level]>, select: <index of prioritized operator> ]
1045
+ addContextualPriority(contextual_priority) {
1046
+ if (!this.config.contextual_priorities) {
1047
+ this.config.contextual_priorities = []
1048
+ }
1049
+ if (global.entodictonDebugContextualPriority) {
1050
+ if (helpers.safeEquals(entodictonDebugContextualPriority, contextual_priorities)) {
1051
+ debugger; // debug hierarchy hit
1052
+ }
1053
+ }
1054
+ contextual_priority_valid(contextual_priority)
1055
+ this.config.contextual_priorities.push(contextual_priority)
1056
+ const cpServer = contextual_priorities_toServer(contextual_priority)
1057
+ this._delta.json.contextual_priorities.push({ action: 'add', contextual_priority: cpServer })
1058
+ }
1059
+
828
1060
  addHierarchy (child, parent) {
829
1061
  if (child && parent || !child || Array.isArray(child) || (typeof child == 'string' && !parent)) {
830
1062
  this.addHierarchyChildParent(child, parent)
@@ -881,15 +1113,19 @@ class Config {
881
1113
  }
882
1114
 
883
1115
  getBridge (id, level) {
884
- return this.config.bridges.find( (bridge) => bridge.id == id && bridge.level == level )
1116
+ if (level) {
1117
+ return this.config.bridges.find( (bridge) => bridge.id == id && bridge.level == level )
1118
+ } else {
1119
+ return this.config.bridges.find( (bridge) => bridge.id == id)
1120
+ }
885
1121
  }
886
1122
 
887
- addBridge (bridge) {
1123
+ addBridge (bridge, uuid) {
888
1124
  if (!this.config.bridges) {
889
1125
  this.config.bridges = []
890
1126
  }
891
1127
  const bridges = this.config.bridges
892
- const def = Object.assign({}, bridge, { uuid: this._uuid })
1128
+ const def = Object.assign({}, bridge, { uuid: uuid || this._uuid })
893
1129
 
894
1130
  if (global.entodictonDebugBridge) {
895
1131
  if (global.entodictonDebugBridge[0] == bridge.id && global.entodictonDebugBridge[1] == bridge.level) {
@@ -911,12 +1147,7 @@ class Config {
911
1147
  this._delta.json.bridges.push({ action: 'add', bridge: def })
912
1148
  }
913
1149
 
914
- addGenerator (match, apply) {
915
- let generator = match
916
- if ((typeof match === 'function') && (typeof apply === 'function')) {
917
- generator = { match, apply }
918
- }
919
-
1150
+ addGenerator (generator, uuid, name) {
920
1151
  if (!(typeof generator.match === 'function')) {
921
1152
  throw new Error('addGenerator: Expected matcher to be a function')
922
1153
  }
@@ -933,20 +1164,16 @@ class Config {
933
1164
  }
934
1165
 
935
1166
  const generators = this.config.generators
936
- Object.assign(generator, { uuid: this._uuid, km: this.name, index: generators.length })
1167
+ Object.assign(generator, { uuid: uuid || this._uuid, km: name || this.name, index: generators.length })
937
1168
  // used to be unshift
938
1169
  generators.unshift(generator)
939
1170
  }
940
1171
 
941
- addSemantic (match, apply) {
942
- let semantic = match
943
- if ((typeof match === 'function') && (typeof apply === 'function')) {
944
- semantic = { match, apply }
945
- }
946
-
1172
+ addSemantic (semantic, uuid, name) {
947
1173
  if (!(typeof semantic.match === 'function')) {
948
1174
  throw new Error('addSemantic: Expected match to be a function')
949
1175
  }
1176
+
950
1177
  if (!(typeof semantic.apply === 'function')) {
951
1178
  throw new Error('addSemantic: Expected apply to be a function')
952
1179
  }
@@ -960,11 +1187,18 @@ class Config {
960
1187
  }
961
1188
 
962
1189
  const semantics = this.config.semantics
963
- Object.assign(semantic, { uuid: this._uuid, km: this.name, index: semantics.length })
1190
+ Object.assign(semantic, { uuid: uuid || semantic.uuid || this._uuid, km: name || this.name, index: semantics.length, id: semantic.id || uuidv4() })
964
1191
  semantics.unshift(semantic)
965
1192
  }
966
1193
 
967
- addOperator (objectOrPattern) {
1194
+ removeSemantic(deleteSemantic) {
1195
+ const index = this.config.semantics.findIndex( (semantic) => semantic.id === deleteSemantic.id )
1196
+ if (index >= 0) {
1197
+ this.config.semantics.splice(index, 1)
1198
+ }
1199
+ }
1200
+
1201
+ addOperator (objectOrPattern, uuid) {
968
1202
  if (!this.config.operators) {
969
1203
  this.config.operators = []
970
1204
  }
@@ -973,9 +1207,9 @@ class Config {
973
1207
 
974
1208
  let operator;
975
1209
  if (typeof objectOrPattern === 'string') {
976
- operator = { pattern: objectOrPattern, uuid: this._uuid }
1210
+ operator = { pattern: objectOrPattern, uuid: uuid || this._uuid }
977
1211
  } else {
978
- operator = Object.assign({}, objectOrPattern, { uuid: this._uuid })
1212
+ operator = Object.assign({}, objectOrPattern, { uuid: uuid || this._uuid })
979
1213
  }
980
1214
 
981
1215
  if (global.entodictonDebugOperator) {
@@ -996,16 +1230,16 @@ class Config {
996
1230
  this._delta.json.operators.push({ action: 'add', operator })
997
1231
  }
998
1232
 
999
- addWord (word, def) {
1000
- this.addWordInternal(word, def)
1233
+ addWord (word, def, uuid) {
1234
+ this.addWordInternal(word, def, uuid)
1001
1235
  }
1002
1236
 
1003
- addWordInternal (word, def) {
1237
+ addWordInternal (word, def, uuid) {
1004
1238
  if (!this.config.words) {
1005
1239
  this.config.words = {}
1006
1240
  }
1007
1241
  const words = this.config.words
1008
- def = Object.assign({}, def, { uuid: this._uuid })
1242
+ def = Object.assign({}, def, { uuid: uuid || this._uuid })
1009
1243
  if (words[word]) {
1010
1244
  if (!words[word].some((e) => helpers.safeEquals(e, def))) {
1011
1245
  words[word].unshift(def)
@@ -1226,33 +1460,7 @@ class Config {
1226
1460
  }
1227
1461
 
1228
1462
  if (config) {
1229
- const valid = [
1230
- 'hierarchy',
1231
- 'objects',
1232
- 'bridges',
1233
- 'operators',
1234
- 'words',
1235
- 'priorities',
1236
- 'associations',
1237
- 'name',
1238
- 'version',
1239
- 'generators',
1240
- 'semantics',
1241
- 'floaters',
1242
- 'debug',
1243
-
1244
- // TODO Fix these from the test app
1245
- 'implicits',
1246
- 'convolution',
1247
- 'expected_generated',
1248
- 'expected_results',
1249
- 'skipSemantics',
1250
- 'description',
1251
- 'contexts',
1252
- 'utterances',
1253
- 'flatten',
1254
- ]
1255
- helpers.validProps(valid, config, 'config')
1463
+ validConfigProps(config)
1256
1464
 
1257
1465
  config.operators = config.operators || []
1258
1466
  config.bridges = config.bridges || []
@@ -1262,6 +1470,7 @@ class Config {
1262
1470
  config.hierarchy = config.hierarchy || []
1263
1471
  config.associations = config.associations || { negative: [], positive: [] }
1264
1472
  config.priorities = config.priorities || []
1473
+ config.contextual_priorities = config.contextual_priorities || []
1265
1474
  }
1266
1475
 
1267
1476
  this.maxDepth = 20 // for generators and semantics
@@ -1315,6 +1524,10 @@ class Config {
1315
1524
  }
1316
1525
  }
1317
1526
 
1527
+ if (config && config.contextual_priorities) {
1528
+ contextual_priorities_valid(config.contextual_priorities)
1529
+ }
1530
+
1318
1531
  normalizeConfig(config)
1319
1532
 
1320
1533
  // set the default server so stuff just works
@@ -1330,7 +1543,6 @@ class Config {
1330
1543
  if (config) {
1331
1544
  this.name = config.name
1332
1545
  }
1333
- this.motivations = []
1334
1546
  this.loadOrder = new DigraphInternal()
1335
1547
  this.wasInitialized = false
1336
1548
  this.configs = []
@@ -1385,7 +1597,10 @@ class Config {
1385
1597
  }
1386
1598
 
1387
1599
  delta () {
1388
- return { cacheKey: this._delta.cacheKey, json: this._delta.json }
1600
+ return {
1601
+ cacheKey: this._delta.cacheKey,
1602
+ json: this._delta.json
1603
+ }
1389
1604
  }
1390
1605
 
1391
1606
  resetDelta (cacheKey) {
@@ -1397,6 +1612,7 @@ class Config {
1397
1612
  bridges: [],
1398
1613
  associations: [],
1399
1614
  priorities: [],
1615
+ contextual_priorities: [],
1400
1616
  hierarchy: [],
1401
1617
  }
1402
1618
  }
@@ -1431,11 +1647,13 @@ class Config {
1431
1647
  this._api.add(this, this._api, value)
1432
1648
  } else {
1433
1649
  this._api = _.cloneDeep(value)
1650
+ /*
1434
1651
  if (this._api) {
1435
- this._api.objects = this.config.objects
1436
- this._api.config = () => this
1437
- this._api.uuid = this._uuid
1652
+ // this._api.objects = this.config.objects
1653
+ // this._api.config = () => this
1654
+ // this._api.uuid = this._uuid
1438
1655
  }
1656
+ */
1439
1657
  this.rebuild()
1440
1658
  }
1441
1659
  }
@@ -1478,40 +1696,6 @@ class Config {
1478
1696
  // this.valid() init was not run because the kms are not all setup yet
1479
1697
  }
1480
1698
 
1481
- // motivation === { match, apply, uuid }
1482
- addMotivation (motivation) {
1483
- if (!motivation.uuid) {
1484
- motivation.uuid = this.uuid
1485
- }
1486
- this.motivations.push(motivation)
1487
- }
1488
-
1489
- resetMotivations () {
1490
- this.motivations = []
1491
- }
1492
-
1493
- doMotivations (args, context) {
1494
- args = Object.assign({}, args, { context, api: this.api })
1495
- // console.log('src/config doMotivations this.uuid', this.uuid)
1496
- // args.objects = args.getObjects(this.uuid)
1497
- const motivations = this.motivations
1498
- this.motivations = []
1499
- let done = false
1500
- for (const motivation of motivations) {
1501
- args.objects = args.getObjects(motivation.uuid)
1502
- if (!done && motivation.match(args)) {
1503
- motivation.apply(args)
1504
- if (args.context.controlKeepMotivation || motivation.repeat) {
1505
- this.motivations.push(motivation)
1506
- }
1507
- done = true
1508
- } else {
1509
- this.motivations.push(motivation)
1510
- }
1511
- }
1512
- return done
1513
- }
1514
-
1515
1699
  // TODO add more details
1516
1700
  equal(config) {
1517
1701
  if (JSON.stringify(this.config) != JSON.stringify(config.config)) {
@@ -1525,6 +1709,9 @@ class Config {
1525
1709
  runtime.fs.writeFileSync(fn, JSON.stringify(this.config, 0, 2))
1526
1710
  }
1527
1711
 
1712
+ copy (options = { callInitializers: true }) {
1713
+ }
1714
+
1528
1715
  copy (options = { callInitializers: true }) {
1529
1716
  this.valid()
1530
1717
  const cp = new Config()
@@ -1534,15 +1721,14 @@ class Config {
1534
1721
  cp.transitoryMode = this.transitoryMode
1535
1722
  cp.configs = this.configs.map((km) => km.copy2(Object.assign({}, options, { getCounter: (name) => cp.getCounter(name), callInitializers: false })))
1536
1723
  cp._uuid = cp.configs[0]._uuid
1724
+ // update uuid here set the uuid in the objects and add error checking
1537
1725
  cp.initializerFn = this.initializerFn
1538
- cp.initAfterApi = this.initAfterApi
1539
1726
  cp._api = _.cloneDeep(this._api)
1540
1727
  cp._namespace = this._namespace
1541
1728
  cp._eqClasses = this._eqClasses
1542
1729
  cp.name = this.name
1543
1730
  cp.description = this.description
1544
1731
  cp.tests = this.tests
1545
- cp.motivations = [...this.motivations]
1546
1732
  cp.isModule = this.isModule
1547
1733
  cp.loadedForTesting = this.loadedForTesting
1548
1734
  cp.initInstances = this.initInstances.slice()
@@ -1567,25 +1753,38 @@ class Config {
1567
1753
  }
1568
1754
  cp.mapUUIDs(map)
1569
1755
 
1756
+ if (cp._uuid == 'concept2') {
1757
+ // debugger
1758
+ }
1570
1759
  if (options.callInitializers) {
1571
1760
  cp.rebuild(options)
1572
- }
1573
- if (cp._api) {
1574
- cp._api.objects = cp.config.objects
1575
- cp._api.config = () => (cp instanceof Config) ? cp : cp.config
1576
- cp._api.uuid = cp._uuid
1577
- }
1761
+ } else {
1762
+ // this mess is for duplicate into a KM after resetToOne was called
1763
+ /*
1764
+ if (cp._api) {
1765
+ // cp._api.objects = cp.config.objects
1766
+ // cp._api.config = () => (cp instanceof Config) ? cp : cp.config
1767
+ // cp._api.uuid = cp._uuid
1768
+ }
1769
+ */
1578
1770
 
1579
- if (!cp.config.objects) {
1580
- cp.config.objects = { namespaced: {} }
1581
- } else if (!cp.config.objects.namespaced) {
1582
- cp.config.objects.namespaced = {}
1771
+ if (!cp.config.objects) {
1772
+ cp.config.objects = { namespaced: {} }
1773
+ } else if (!cp.config.objects.namespaced) {
1774
+ cp.config.objects.namespaced = {}
1775
+ }
1776
+ cp.configs.forEach((km) => {
1777
+ // const namespace = km.namespace
1778
+ cp.config.objects.namespaced[km._uuid] = {}
1779
+ })
1780
+ /*
1781
+ if (cp._uuid == 'concept2') {
1782
+ if (!cp.api.objects.defaultTypesForHierarchy) {
1783
+ debugger
1784
+ }
1785
+ }
1786
+ */
1583
1787
  }
1584
- cp.configs.forEach((km) => {
1585
- // const namespace = km.namespace
1586
- cp.config.objects.namespaced[km._uuid] = {}
1587
- })
1588
-
1589
1788
  cp.valid()
1590
1789
  return cp
1591
1790
  }
@@ -1685,38 +1884,33 @@ class Config {
1685
1884
  }
1686
1885
  */
1687
1886
  const objects = {}
1688
- const km = (name) => this.getConfig(name)
1689
1887
  if (config instanceof Config) {
1690
- // const aw = addWord(this.config, config.uuid)
1691
- const aw = (word, def) => this.addWord(word, def)
1692
1888
  this.get('objects').namespaced[config._uuid] = objects
1889
+ /*
1693
1890
  if (config._api) {
1694
- config._api.objects = objects
1695
- config._api.config = () => this
1891
+ // config._api.objects = objects
1892
+ // config._api.config = () => this
1696
1893
  }
1697
- config.initializerFn({ addWord: aw, km, config, baseConfig: this, currentConfig: config, objects, namespace, uuid, api: config.api })
1894
+ */
1895
+ config.initializerFn(setupInitializerFNArgs(this, { testConfig: config, currentConfig: config, objects, namespace, uuid }))
1698
1896
  } else {
1699
- // const aw = addWord(this.config, this.uuid)
1700
- const aw = (word, def) => this.addWord(word, def)
1701
1897
  this.get('objects').namespaced[this._uuid] = objects
1898
+ /*
1702
1899
  if (config._api) {
1703
- config._api.objects = objects
1704
- config._api.config = () => this
1900
+ // config._api.objects = objects
1901
+ // config._api.config = () => this
1705
1902
  }
1706
- this.initializerFn({ addWord: aw, km, config: this, baseConfig: this, currentConfig: this, objects, namespace, uuid, api: this.api })
1903
+ */
1904
+ this.initializerFn(setupInitializerFNArgs(this, { testConfig: this, currentConfig: this, objects, namespace, uuid }))
1707
1905
  }
1708
1906
  })
1709
- this.instances.forEach((instance) => client.processInstance(this, instance))
1907
+ this.instances.forEach((instance) => client.loadInstance(this, instance))
1710
1908
  }
1711
1909
 
1712
1910
  initialize ({ force = true } = {}) {
1713
1911
  if (force || !this.wasInitialized) {
1714
- // const aw = addWord(this.config, this.uuid)
1715
- const aw = (word, def) => this.addWord(word, def)
1716
- const km = (name) => this.getConfig(name)
1717
- // this.initializerFn({ addWord: aw, km, config: this, baseConfig: this, currentConfig: this, objects: this.get('objects'), uuid: this._uuid, namespace: '', api: this.api })
1718
1912
  const objects = this.config.objects.namespaced[this._uuid]
1719
- this.initializerFn({ addWord: aw, km, config: this, baseConfig: this, currentConfig: this, objects, uuid: this._uuid, namespace: '', api: this.api })
1913
+ this.initializerFn(setupInitializerFNArgs(this, { testConfig: this, currentConfig: this, objects, uuid: this._uuid, namespace: '' }))
1720
1914
  this.wasInitialized = true
1721
1915
  }
1722
1916
  }
@@ -1724,29 +1918,22 @@ class Config {
1724
1918
  initializer (fn, options = {}) {
1725
1919
  if (options) {
1726
1920
  for (let option of Object.keys(options)) {
1727
- const validOptions = ['initAfterApi']
1728
- if (!['initAfterApi'].includes(option)) {
1921
+ const validOptions = []
1922
+ if (!validOptions.includes(option)) {
1729
1923
  throw new Error(`For Config.initializer, unrecognized option ${option}. The valid options are ${validOptions}`)
1730
1924
  }
1731
1925
  }
1732
1926
  }
1733
- const { initAfterApi = false } = options;
1734
1927
  this.wasInitialized = false
1735
- this.initAfterApi = initAfterApi
1736
- this.initializerFn = (args) => {
1928
+ this.initializerFn = (args, { dontCallFn } = {}) => {
1737
1929
  const transitoryMode = global.transitoryMode
1738
1930
  global.transitoryMode = false
1739
1931
  // const baseConfig = args.baseConfig
1740
1932
  const currentConfig = args.currentConfig
1741
1933
 
1742
- if (currentConfig.api) {
1743
- currentConfig.api.objects = args.objects
1744
- // GREG42 currentConfig.api.config = () => this
1745
- currentConfig.api.config = () => args.baseConfig
1746
- currentConfig.api.uuid = currentConfig._uuid
1934
+ if (args.isAfterApi) {
1935
+ fn(args)
1747
1936
  }
1748
- // this.instances.forEach( (instance) => client.processInstance(this, instance) )
1749
- fn(args)
1750
1937
  currentConfig.wasInitialized = true
1751
1938
  global.transitoryMode = transitoryMode
1752
1939
  }
@@ -1913,7 +2100,6 @@ class Config {
1913
2100
  }
1914
2101
  this.config.objects.namespaced = {}
1915
2102
  this.resetWasInitialized()
1916
- this.resetMotivations()
1917
2103
 
1918
2104
  // reorder configs base on load ordering
1919
2105
  {
@@ -1939,8 +2125,8 @@ class Config {
1939
2125
  this.config.objects.namespaced[km._uuid] = {}
1940
2126
  const namespacedObjects = this.config.objects.namespaced[km._uuid]
1941
2127
  this.setupNamespace(km)
1942
- // const aw = addWord(km.config.config ? km.config.config : km.config, km.config.uuid)
1943
- const aw = (word, def) => this.addWord(word, def)
2128
+ // const aw = (word, def) => this.addWord(word, def)
2129
+ // const ag = (matchOrGenerator, applyOrNothing) => this.addGenerator(matchOrGenerator, applyOrNothing)
1944
2130
  let config = km.config
1945
2131
 
1946
2132
  if (config.addedArgss) {
@@ -1961,45 +2147,51 @@ class Config {
1961
2147
  }
1962
2148
  config.wasInitialized = false
1963
2149
  // TODO change name of config: to baseConfig:
1964
- const kmFn = (name) => this.getConfig(name)
2150
+ const kmFn = (name) => {
2151
+ const config = this.getConfig(name)
2152
+ return config
2153
+ }
1965
2154
  // const hierarchy = new DigraphInternal((config.config || {}).hierarchy)
1966
- const args = {
2155
+ const args = new Object(setupInitializerFNArgs(this, {
1967
2156
  isModule,
1968
- addWord: aw,
1969
- km: kmFn,
1970
2157
  hierarchy: this.hierarchy,
1971
- config,
1972
- baseConfig: this,
2158
+ testConfig: config,
1973
2159
  currentConfig: config,
1974
2160
  uuid: config._uuid,
1975
2161
  objects: namespacedObjects,
1976
2162
  namespace,
1977
- motivation: (m) => config.addMotivation(m),
1978
- api: config.api
2163
+ api: config.api,
2164
+ }))
2165
+
2166
+ const currentConfig = args.currentConfig
2167
+
2168
+ /*
2169
+ if (args.currentConfig.api) {
2170
+ // args.currentConfig.api.objects = args.objects
2171
+ // TODO assign pseudo config?
2172
+ // args.currentConfig.api.config = () => args.baseConfig
2173
+ // args.currentConfig.api.uuid = args.currentConfig._uuid
2174
+ args.currentConfig.wasInitialized = true
1979
2175
  }
1980
- config.initializerFn(args)
1981
- if (config.initAfterApi) {
1982
- // reverse the list
2176
+ */
2177
+ // debugger
2178
+ // greg55
2179
+ config.initializerFn(args, { dontCallFn: true })
1983
2180
  initAfterApis.unshift({ config, args })
1984
- } else {
1985
- if (interleaved) {
1986
- initAfterApis.unshift(null)
1987
- }
1988
- }
1989
- // greg
1990
2181
  if (config._api) {
1991
2182
  if (config._api.initialize) {
1992
2183
  // reverse the list
1993
- inits.unshift( () => config._api.initialize({ config: this, km: kmFn, api: config._api }) )
2184
+ // TODO sync up the args with initialize of config
2185
+ inits.unshift( () => config._api.initialize({ config: this, km: kmFn, ...args, api: config._api }) )
1994
2186
  // config._api.initialize({ config, api: config._api })
1995
2187
  } else {
1996
2188
  if (interleaved) {
1997
2189
  inits.unshift(null)
1998
2190
  }
1999
2191
  }
2000
- config._api.objects = namespacedObjects
2001
- config._api.config = () => this
2002
- config._api.uuid = config._uuid
2192
+ // config._api.objects = namespacedObjects
2193
+ // config._api.config = () => this
2194
+ // config._api.uuid = config._uuid
2003
2195
  } else {
2004
2196
  if (interleaved) {
2005
2197
  inits.unshift(null)
@@ -2041,16 +2233,16 @@ class Config {
2041
2233
  init()
2042
2234
  }
2043
2235
  for (let init of initAfterApis) {
2044
- // init.args.isAfterApi = true
2045
2236
  init.config.initializerFn({ ...init.args, kms: this.getConfigs(), isAfterApi: true })
2046
2237
  }
2047
- this.instances.forEach((instance) => client.processInstance(this, instance))
2238
+ this.instances.forEach((instance) => client.loadInstance(this, instance))
2048
2239
  } else {
2049
2240
  const base = {
2050
2241
  operators: this.config.operators,
2051
2242
  bridges: this.config.bridges,
2052
2243
  hierarchy: this.config.hierarchy,
2053
2244
  priorities: this.config.priorities,
2245
+ contextual_priorities: this.config.contextual_priorities,
2054
2246
  associations: this.config.associations,
2055
2247
  words: this.config.words
2056
2248
  }
@@ -2059,6 +2251,7 @@ class Config {
2059
2251
  this.config.bridges = []
2060
2252
  this.config.hierarchy = []
2061
2253
  this.config.priorities = []
2254
+ this.config.contextual_priorities = []
2062
2255
  this.config.associations = { positive: [], negative: [] }
2063
2256
  this.config.words = {}
2064
2257
 
@@ -2073,19 +2266,19 @@ class Config {
2073
2266
  }
2074
2267
  // console.log('name -------------', name)
2075
2268
  if (inits[i]) {
2269
+ // greg55
2076
2270
  inits[i]()
2077
2271
  }
2078
2272
  if (initAfterApis[i]) {
2079
2273
  const init = initAfterApis[i]
2080
- init.config.initializerFn({ ...init.args, kms: this.getConfigs(), isAfterApi: true })
2274
+ init.config.initializerFn({ ...init.args, kms: this.getConfigs(), isAfterApi: true})
2081
2275
  }
2082
2276
  const instance = this.instances.find((instance) => instance.name == name)
2083
2277
  if (instance) {
2084
- client.processInstance(this, instance)
2278
+ client.loadInstance(this, instance)
2085
2279
  }
2086
2280
  this.hierarchy.edges = this.config.hierarchy
2087
2281
  }
2088
- // this.instances.forEach((instance) => client.processInstance(this, instance))
2089
2282
  }
2090
2283
 
2091
2284
  if (reverseIt) {
@@ -2208,13 +2401,9 @@ class Config {
2208
2401
  }
2209
2402
  const km = (name) => this.getConfig(name)
2210
2403
  if (config instanceof Config) {
2211
- // const aw = addWord(this.config, config.uuid)
2212
- const aw = (word, def) => this.addWord(word, def)
2213
- config.initializerFn({ isModule: this.isModule, addWord: aw, baseConfig: this, km, currentConfig: config, config, objects: nsobjects, namespace, uuid, api: config.api })
2404
+ config.initializerFn(setupInitializerFNArgs(this, { isModule: this.isModule, currentConfig: config, testConfig: config, objects: nsobjects, namespace, uuid }))
2214
2405
  } else {
2215
- // const aw = addWord(this.config, this.uuid)
2216
- const aw = (word, def) => this.addWord(word, def)
2217
- this.initializerFn({ isModule: this.isModule, addWord: aw, baseConfig: this, km, currentConfig: this, config: this, objects: nsobjects, namespace, uuid, api: this.api })
2406
+ this.initializerFn(setupInitializerFNArgs(this, { isModule: this.isModule, currentConfig: this, testConfig: this, objects: nsobjects, namespace, uuid }))
2218
2407
  }
2219
2408
  })
2220
2409
  }
@@ -2279,6 +2468,20 @@ class Config {
2279
2468
  config.priorities = priorities
2280
2469
  }
2281
2470
 
2471
+ if (config.contextual_priorities) {
2472
+ let contextual_priorities = config.contextual_priorities
2473
+ contextual_priorities = contextual_priorities.map((cp) => {
2474
+ const { context, choose } = cp
2475
+ return {
2476
+ context: context.map((id) => {
2477
+ return [toNS(id[0]), id[1]]
2478
+ }),
2479
+ choose
2480
+ }
2481
+ })
2482
+ config.contextual_priorities = contextual_priorities
2483
+ }
2484
+
2282
2485
  for (const bag of bags) {
2283
2486
  if (config[bag]) {
2284
2487
  config[bag] = config[bag].map((b) => {
@@ -2473,7 +2676,8 @@ class Config {
2473
2676
  }
2474
2677
 
2475
2678
  // TODO get rid of useOldVersion arg
2476
- addInternal (more, { useOldVersion = true, skipObjects = false, includeNamespaces = true, allowNameToBeNull = false, handleCalculatedProps : hcps = false } = {}) {
2679
+ addInternal (more, { addFirst = false, useOldVersion = true, skipObjects = false, includeNamespaces = true, allowNameToBeNull = false, handleCalculatedProps : hcps = false } = {}) {
2680
+ validConfigProps(more)
2477
2681
  if (more instanceof Config) {
2478
2682
  more.initialize({ force: false })
2479
2683
  if (useOldVersion) {
@@ -2484,7 +2688,7 @@ class Config {
2484
2688
  }
2485
2689
  }
2486
2690
  if (hcps) {
2487
- handleCalculatedProps(this, more)
2691
+ handleCalculatedProps(this, more, addFirst)
2488
2692
  applyUUID(more, this._uuid)
2489
2693
  }
2490
2694
  for (const key of Object.keys(more)) {
@@ -2509,7 +2713,11 @@ class Config {
2509
2713
  if (!configWords[word]) {
2510
2714
  configWords[word] = []
2511
2715
  }
2512
- configWords[word] = configWords[word].concat(moreWords[word])
2716
+ if (addFirst) {
2717
+ configWords[word] = moreWords[word].concat(configWords[word])
2718
+ } else {
2719
+ configWords[word] = configWords[word].concat(moreWords[word])
2720
+ }
2513
2721
  }
2514
2722
  } else if (key === 'name') {
2515
2723
  /*
@@ -2571,13 +2779,17 @@ class Config {
2571
2779
  this.config[key].splice(iOldOne, 1)
2572
2780
  break;
2573
2781
  }
2574
- }
2782
+ }
2575
2783
  }
2576
2784
  }
2577
2785
  }
2578
2786
  // console.log('key', key, 'XXX')
2579
2787
  // console.log('more', JSON.stringify(more, null, 2))
2580
- this.config[key] = this.config[key].concat(more[key])
2788
+ if (addFirst) {
2789
+ this.config[key] = more[key].concat(this.config[key])
2790
+ } else {
2791
+ this.config[key] = this.config[key].concat(more[key])
2792
+ }
2581
2793
  } else {
2582
2794
  if (!(key in this.config)) {
2583
2795
  throw new Error(`Unexpected property in config ${key}`)
@@ -2708,5 +2920,8 @@ class Config {
2708
2920
  }
2709
2921
 
2710
2922
  module.exports = {
2711
- Config
2923
+ Config,
2924
+ config_toServer,
2925
+ operatorKey_valid,
2926
+ handleBridgeProps,
2712
2927
  }