theprogrammablemind 7.12.8 → 8.0.0

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/client.js CHANGED
@@ -81,104 +81,6 @@ const pickObjects = (config, testConfig, getObjects) => {
81
81
  return projection
82
82
  }
83
83
 
84
- // move ask to the KM's since verbatim is called probably in dialogues?
85
- const getAsk = (config) => (uuid) => {
86
- // if (!uuid) {
87
- // debugger
88
- //}
89
- return (asks) => {
90
- const ask = (ask) => {
91
- let oneShot = true // default
92
- if (ask.oneShot === false) {
93
- oneShot = false
94
- }
95
-
96
- const id_q = stableId('semantic')
97
- const id_rs = []
98
- let wasAsked = false
99
- let wasApplied = false
100
- const getWasAsked = () => {
101
- return wasAsked
102
- }
103
- const setWasAsked = (value) => {
104
- wasAsked = value
105
- }
106
- const getWasApplied = () => {
107
- return wasApplied
108
- }
109
- const setWasApplied = (value) => {
110
- wasApplied = value
111
- }
112
-
113
- const semanticsr = ask.semanticsr || []
114
- if (semanticsr.length == 0) {
115
- semanticsr.push({ match: ask.matchr, apply: ask.applyr })
116
- }
117
- for (const semantic of semanticsr) {
118
- const id_r = stableId('semantic')
119
- id_rs.push(id_r)
120
- config.addSemantic({
121
- uuid,
122
- id: id_r,
123
- tied_ids: [id_q],
124
- oneShot,
125
- where: semantic.where || ask.where || where(2),
126
- source: 'response',
127
- match: (args) => semantic.match(args),
128
- apply: (args) => {
129
- setWasApplied(true)
130
- semantic.apply(args)
131
- },
132
- })
133
- }
134
-
135
- config.addSemantic({
136
- uuid,
137
- oneShot,
138
- id: id_q,
139
- tied_ids: id_rs,
140
- where: ask.where,
141
- isQuestion: true, // do one question at a time
142
- getWasAsked,
143
- getWasApplied,
144
- onNevermind: ask.onNevermind,
145
- source: 'question',
146
- match: ({ context }) => context.marker == 'controlEnd' || context.marker == 'controlBetween',
147
- apply: (args) => {
148
- let matchq = ask.matchq
149
- let applyq = ask.applyq
150
- if (!matchq) {
151
- let wasAsked = false
152
- matchq = () => !wasAsked,
153
- applyq = (args) => {
154
- wasAsked = true
155
- return ask.applyq(args)
156
- }
157
- }
158
- if (matchq(args)) {
159
- setWasAsked(true)
160
- setWasApplied(false)
161
- // args.context.motivationKeep = true
162
- args.verbatim(applyq(args))
163
- /*
164
- args.context.verbatim = applyq(args)
165
- args.context.isResponse = true;
166
- delete args.context.controlRemove;
167
- */
168
- args.context.controlKeepMotivation = true
169
- }
170
- args.context.cascade = true
171
- }
172
- })
173
- }
174
- if (!Array.isArray(asks)) {
175
- asks = [asks]
176
- }
177
-
178
- [...asks].reverse().forEach( (a) => ask(a) )
179
- }
180
- }
181
-
182
84
  const sameJSON = (json1, json2) => {
183
85
  const sjson1 = sortJson(json1, { depth: 25 })
184
86
  const sjson2 = sortJson(json2, { depth: 25 })
@@ -300,7 +202,6 @@ const setupArgs = (args, config, logs, hierarchy, uuidForScoping) => {
300
202
  }
301
203
  // for semantics
302
204
  args.addAssumedScoped(args, {})
303
- config.getAddedArgs(args)
304
205
 
305
206
  const getAPI = (uuid) => {
306
207
  if (config && config.getAPI) {
@@ -312,14 +213,14 @@ const setupArgs = (args, config, logs, hierarchy, uuidForScoping) => {
312
213
  return config.getAPIs(uuid)
313
214
  }
314
215
  }
315
- const scopedAsk = getAsk(config)
316
216
  args.getUUIDScoped = (uuid) => {
317
217
  return {
318
- ask: scopedAsk(uuid),
319
218
  api: getAPI(uuid),
320
219
  apis: getAPIs(uuid)
321
220
  }
322
221
  }
222
+ config.getAddedArgs(args)
223
+
323
224
  Object.assign(args, args.getUUIDScoped(uuidForScoping || config.uuid))
324
225
  /*
325
226
  if (uuidForScoping) {
@@ -745,17 +646,15 @@ const loadInstance = (config, instance) => {
745
646
  const results = instance.resultss[i]
746
647
  if (results.extraConfig) {
747
648
  // config.addInternal(results, useOldVersion = true, skipObjects = false, includeNamespaces = true, allowNameToBeNull = false)
748
- // config.addInternal(config.template.queries[i], { handleCalculatedProps: true } )
749
649
  const uuid = config.nameToUUID(instance.name)
750
650
  // used to do a CLONE
751
- // config.addInternal(_.cloneDeep(instance.template.queries[i]), { uuid, addFirst: true, handleCalculatedProps: true })
752
- config.addInternal(instance.template.queries[i], { uuid, addFirst: true, handleCalculatedProps: true })
651
+ config.addInternal(instance.template.configs[i], { uuid, addFirst: true, handleCalculatedProps: true })
753
652
  } else if (results.apply) {
754
653
  const objects = config.get('objects')
755
654
  const args = { objects, getObjects: getObjects(objects) }
756
- if (instance.queries) {
655
+ if (instance.configs) {
757
656
  args.isInstance = `instance${i}`
758
- args.instance = instance.queries[i]
657
+ args.instance = instance.configs[i]
759
658
  }
760
659
 
761
660
  const uuid = config.nameToUUID(instance.name)
@@ -923,15 +822,27 @@ const getConfigForTest = (config, testConfig) => {
923
822
  // configForTest[key] = config.config[key]
924
823
  if (key === 'words') {
925
824
  const words = config.config.words
926
- configForTest.words = {}
927
- for (const key of Object.keys(words)) {
825
+ configForTest.words = {
826
+ literals: {},
827
+ patterns: [],
828
+ hierarchy: [],
829
+ }
830
+
831
+ const literals = config.config.words.literals
832
+ for (const key in literals) {
928
833
  const defs = []
929
- for (const def of words[key]) {
834
+ for (const def of literals[key]) {
930
835
  // TODO handle thie uuids the right way
931
836
  defs.push(Object.assign({}, def, { uuid: undefined }))
932
837
  }
933
- configForTest.words[key] = defs
838
+ configForTest.words.literals[key] = defs
934
839
  }
840
+
841
+ const patterns = config.config.words.patterns
842
+ configForTest.words.patterns = patterns.map((pattern) => Object.assign({}, pattern, { uuid: undefined }))
843
+
844
+ const hierarchy = config.config.words.hierarchy
845
+ configForTest.words.hierarchy = hierarchy.map((hierarchy) => Object.assign({}, hierarchy, { uuid: undefined }))
935
846
  } else if (key === 'operators') {
936
847
  configForTest.operators = config.config.operators.map((operator) => Object.assign({}, operator, { uuid: undefined }))
937
848
  } else if (key === 'bridges') {
@@ -1281,7 +1192,7 @@ const defaultInnerProcess = (config, errorHandler, responses) => {
1281
1192
  console.log('Errors')
1282
1193
  responses.errors.forEach((error) => console.log(` ${error}`))
1283
1194
  }
1284
- console.log("KM's loaded", config.configs.map((c) => c.name))
1195
+ console.log("KM's loaded (ordered)", config.configs.map((c) => c.name))
1285
1196
  console.log('This is the global objects from running semantics:\n', config.objects)
1286
1197
  if (!_.isEmpty(responses.learned_contextual_priorities)) {
1287
1198
  console.log('\nThe learned contextual priorties are :\n')
@@ -1404,12 +1315,12 @@ const rebuildTemplate = async ({ config, target, previousResultss, startOfChange
1404
1315
  associations: [],
1405
1316
  learned_contextual_priorities: []
1406
1317
  }
1407
- const looper = async (queries) => {
1408
- if (queries.length === 0) {
1318
+ const looper = async (configs) => {
1319
+ if (configs.length === 0) {
1409
1320
  finish()
1410
1321
  return
1411
1322
  }
1412
- const { property, hierarchy, query: queryOrExtraConfig, previousResults, initializer, skipSemantics } = queries.shift()
1323
+ const { property, hierarchy, query: queryOrExtraConfig, previousResults, initializer, skipSemantics } = configs.shift()
1413
1324
  // queries are strings or { query: "blah", development: true/false }
1414
1325
  if (typeof queryOrExtraConfig === 'string' || queryOrExtraConfig.query) {
1415
1326
  let query = queryOrExtraConfig
@@ -1461,7 +1372,7 @@ const rebuildTemplate = async ({ config, target, previousResultss, startOfChange
1461
1372
  accumulators[property].push(results)
1462
1373
  accumulators.associations = accumulators.associations.concat(results.associations)
1463
1374
  accumulators.learned_contextual_priorities = accumulators.learned_contextual_priorities.concat(results.learned_contextual_priorities)
1464
- await looper(queries)
1375
+ await looper(configs)
1465
1376
  } catch (e) {
1466
1377
  const error = { errors: [e], query: query.query }
1467
1378
  config.config.skipSemantics = null
@@ -1475,7 +1386,7 @@ const rebuildTemplate = async ({ config, target, previousResultss, startOfChange
1475
1386
  setupArgs(args, config, config.logs, hierarchy)
1476
1387
  initFunction(args)
1477
1388
  accumulators[property].push({ apply: queryOrExtraConfig })
1478
- await looper(queries)
1389
+ await looper(configs)
1479
1390
  } else {
1480
1391
  // extra config is def from a time like operators or bridges or words etc
1481
1392
  // it will just get added to the config
@@ -1491,7 +1402,7 @@ const rebuildTemplate = async ({ config, target, previousResultss, startOfChange
1491
1402
  throw new Error(`Error processing extra config${where}: ${e.stack}}`)
1492
1403
  }
1493
1404
  accumulators[property].push({ extraConfig: true, ...extraConfig })
1494
- await looper(queries)
1405
+ await looper(configs)
1495
1406
  }
1496
1407
  }
1497
1408
  }
@@ -1531,7 +1442,7 @@ const rebuildTemplate = async ({ config, target, previousResultss, startOfChange
1531
1442
  return template
1532
1443
  }
1533
1444
  stabilizeOutput(accumulators)
1534
- runtime.fs.writeFileSync(instanceName, JSON.stringify(Object.assign({ queries: template.queries.map(updateQueries) }, accumulators), 0, 2))
1445
+ runtime.fs.writeFileSync(instanceName, JSON.stringify(Object.assign({ configs: template.configs.map(updateQueries) }, accumulators), 0, 2))
1535
1446
 
1536
1447
  // km tests file
1537
1448
  const testsName = `./${target}.test.json`
@@ -1550,7 +1461,7 @@ const rebuildTemplate = async ({ config, target, previousResultss, startOfChange
1550
1461
  }
1551
1462
  let todo = []
1552
1463
  todo = todo.concat((template.initializers || []).map((query) => { return { initializer: true, property: 'resultss', query, skipSemantics: false || query.skipSemantics } }))
1553
- todo = todo.concat((template.queries || []).map((query, index) => {
1464
+ todo = todo.concat((template.configs || []).map((query, index) => {
1554
1465
  let pr
1555
1466
  if (index < startOfChanges) {
1556
1467
  pr = previousResultss[index]
@@ -1600,19 +1511,6 @@ const knowledgeModuleImpl = async ({
1600
1511
  acceptsAdditionalConfig = false,
1601
1512
  ...rest
1602
1513
  } = {}) => {
1603
- /*
1604
- if (description == 'fastfood related concepts') {
1605
- debugger
1606
- global.old = template.template.queries[91].bridges[0]
1607
- }
1608
- let old
1609
- if (template && template.template && template.template.queries) {
1610
- old = template.template.queries
1611
- template.template.queries = _.cloneDeep(template.template.queries)
1612
- template.wasCopied = true
1613
- }
1614
- */
1615
-
1616
1514
  const unknownArgs = Object.keys(rest)
1617
1515
  if (unknownArgs.length > 0) {
1618
1516
  throw new Error(`Unknown arguments to knowledgeModule: ${unknownArgs.join()}`)
@@ -2270,6 +2168,7 @@ const knowledgeModule = async (...args) => {
2270
2168
 
2271
2169
  module.exports = {
2272
2170
  process: _process,
2171
+ stableId,
2273
2172
  where,
2274
2173
  w,
2275
2174
  // submitBug,
package/index.js CHANGED
@@ -15,6 +15,7 @@ module.exports = {
15
15
  knowledgeModule: client.knowledgeModule,
16
16
  ensureTestFile: client.ensureTestFile,
17
17
  where: client.where,
18
+ stableId: client.stableId,
18
19
  w: client.w,
19
20
  Config,
20
21
  Semantics,
package/package.json CHANGED
@@ -65,6 +65,6 @@
65
65
  "json-stable-stringify": "^1.0.1",
66
66
  "node-fetch": "^2.6.1"
67
67
  },
68
- "version": "7.12.8",
68
+ "version": "8.0.0",
69
69
  "license": "UNLICENSED"
70
70
  }
package/src/config.js CHANGED
@@ -26,6 +26,19 @@ const config_toServer = (config) => {
26
26
  // cant change things because copy breaks something
27
27
  }
28
28
 
29
+ const initWords = (words) => {
30
+ if (!words.literals) {
31
+ words.literals = {}
32
+ }
33
+ if (!words.patterns) {
34
+ words.patterns = []
35
+ }
36
+ if (!words.hierarchy) {
37
+ words.hierarchy = []
38
+ }
39
+ return words
40
+ }
41
+
29
42
  const debugPriority = (priority) => {
30
43
  if (global.entodictonDebugPriority) {
31
44
  if (helpers.subPriority(entodictonDebugPriority, priority)) {
@@ -123,6 +136,7 @@ const validConfigProps = (config) => {
123
136
 
124
137
  const setupInitializerFNArgs = (config, args) => {
125
138
  const aw = (word, def) => config.addWord(word, def, args.uuid)
139
+ const ap = (pattern, def) => config.addPattern(pattern, def, args.uuid)
126
140
  const ag = (generator) => config.addGenerator(generator, args.uuid, config.name)
127
141
  const km = (name) => config.getConfig(name)
128
142
  const apis = (name) => config.getConfig(name).api
@@ -130,6 +144,7 @@ const setupInitializerFNArgs = (config, args) => {
130
144
  return {
131
145
  ...args,
132
146
  addWord: aw,
147
+ addPattern: ap,
133
148
  addGenerator: ag,
134
149
  config: config.getPseudoConfig(args.uuid, args.currentConfig),
135
150
  km,
@@ -213,6 +228,9 @@ const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
213
228
  config.addHierarchy(child, bridge.id)
214
229
  }
215
230
  }
231
+ if (bridge.operator) {
232
+ config.addOperator(bridge.operator, uuid || config.uuid)
233
+ }
216
234
  if (bridge.parents) {
217
235
  for (const parent of bridge.parents) {
218
236
  config.addHierarchy(bridge.id, parent)
@@ -329,7 +347,7 @@ const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
329
347
  if (bridge.semantic) {
330
348
  const semantic = {
331
349
  where: bridge.semantic.where || bridge.where || client.where(3),
332
- match: ({ context }) => bridge.id == context.marker,
350
+ match: ({ context }) => bridge.id == context.marker && !context.evaluate,
333
351
  apply: (args) => bridge.semantic(args),
334
352
  applyWrapped: bridge.semantic,
335
353
  property: 'semantic'
@@ -348,7 +366,7 @@ const handleCalculatedProps = (baseConfig, moreConfig, { addFirst, uuid } = {})
348
366
  if (moreConfig.bridges) {
349
367
  moreConfig.bridges = moreConfig.bridges.map((bridge) => {
350
368
  bridge = { ...bridge }
351
- const valid = ['after', 'before', 'bridge', 'development', 'evaluator', 'generatorp', 'generatorr', 'generatorpr', 'generators', 'id', 'convolution', 'inverted', 'isA', 'children', 'parents',
369
+ const valid = ['after', 'before', 'bridge', 'development', 'evaluator', 'generatorp', 'generatorr', 'generatorpr', 'generators', 'operator', 'id', 'convolution', 'inverted', 'isA', 'children', 'parents',
352
370
  'level', 'optional', 'selector', 'semantic', 'words', /Bridge$/, 'localHierarchy', 'levelSpecificHierarchy', 'where', 'uuid']
353
371
  helpers.validProps(valid, bridge, 'bridge')
354
372
  handleBridgeProps(baseConfig, bridge, { addFirst, uuid })
@@ -409,10 +427,13 @@ const hierarchyCanonical = (element) => {
409
427
  }
410
428
  }
411
429
 
412
- const isValidDef = (word, def, config) => {
430
+ const isValidWordDef = (word, def, config) => {
431
+ // TODO trie
432
+ /*
413
433
  if (!def.id) {
414
434
  throw new Error(`In the KM "${config.name}", for the word ${word} the following definition is missing the "id" property: ${JSON.stringify(def)}`)
415
435
  }
436
+ */
416
437
  /*
417
438
  if (!def.initial) {
418
439
  throw `In the KM "${config.name}", for the word ${word} the following definition is missing the "initial" property: ${JSON.stringify(def)}`
@@ -429,16 +450,20 @@ const hierarchyToCanonical = (edge) => {
429
450
 
430
451
  const addWord = (config, uuid) => ({ word, id, initial }) => {
431
452
  if (!config.words) {
432
- config.words = {}
453
+ config.words = {
454
+ literals: {},
455
+ patterns: [],
456
+ hierarchy: [],
457
+ }
433
458
  }
434
- const words = config.words
459
+ const literals = config.words.literals
435
460
  const def = { id, initial, uuid }
436
- if (words[word]) {
437
- if (!words[word].some((e) => helpers.safeEquals(e, def))) {
438
- words[word].unshift(def)
461
+ if (literals[word]) {
462
+ if (!literals[word].some((e) => helpers.safeEquals(e, def))) {
463
+ literals[word].unshift(def)
439
464
  }
440
465
  } else {
441
- words[word] = [def]
466
+ literals[word] = [def]
442
467
  }
443
468
  }
444
469
 
@@ -453,6 +478,7 @@ const normalizeConfig = (config) => {
453
478
  }
454
479
  }
455
480
  }
481
+
456
482
  if (config.bridges) {
457
483
  for (const bridge of config.bridges) {
458
484
  if (!bridge.level) {
@@ -471,6 +497,14 @@ const normalizeConfig = (config) => {
471
497
  }
472
498
  }
473
499
  }
500
+
501
+ if (config.operators) {
502
+ for (let i = 0; i < config.operators.length; ++i) {
503
+ if (typeof config.operators[i] === 'string') {
504
+ config.operators[i] = { pattern: config.operators[i] }
505
+ }
506
+ }
507
+ }
474
508
  }
475
509
  }
476
510
 
@@ -488,8 +522,17 @@ function configDup (config, options) {
488
522
  }
489
523
 
490
524
  function setWordsUUIDs (words, uuid) {
491
- for (const key in words) {
492
- words[key] = words[key].map((o) => Object.assign(o, { uuid }))
525
+ const literals = words.literals
526
+ for (const key in literals) {
527
+ literals[key] = literals[key].map((o) => Object.assign(o, { uuid }))
528
+ }
529
+ const patterns = words.patterns
530
+ for (const pattern of patterns) {
531
+ pattern.defs.map((def) => Object.assign(def, { uuid }))
532
+ }
533
+ const hierarchy = words.hierarchy
534
+ for (const pair of hierarchy) {
535
+ pair.uuid = uuid
493
536
  }
494
537
  }
495
538
 
@@ -740,7 +783,7 @@ class Config {
740
783
  }
741
784
  const templateQueries = []
742
785
  if (this.instances && this.instances.length > 0) {
743
- for (const query of this.instances.slice(-1)[0].queries) {
786
+ for (const query of this.instances.slice(-1)[0].configs) {
744
787
  if (typeof query === 'string') {
745
788
  templateQueries.push(query)
746
789
  }
@@ -764,6 +807,7 @@ class Config {
764
807
  addSemantic: (...args) => this.addSemantic(...args, uuid, config.name),
765
808
  removeSemantic: (...args) => this.removeSemantic(...args, uuid, config.name),
766
809
  addWord: (...args) => this.addWord(...args, uuid),
810
+ addPattern: (...args) => this.addPattern(...args, uuid),
767
811
 
768
812
  getHierarchy: (...args) => this.config.hierarchy,
769
813
  getBridges: (...args) => this.config.bridges,
@@ -785,28 +829,6 @@ class Config {
785
829
  }
786
830
  }
787
831
 
788
- // return the config with just the elements from the included KM's
789
- baseConfig () {
790
- const operators = this.config.operators.filter((operator) => {
791
- return operator.uuid !== this.uuid
792
- })
793
- const bridges = this.config.bridges.filter((bridge) => {
794
- return bridge.uuid !== this.uuid
795
- })
796
- const words = {}
797
- for (const word in this.config.words) {
798
- const defs = this.config.words[word].filter((def) => def.uuid !== this.uuid)
799
- if (defs.length > 0) {
800
- words[word] = defs
801
- }
802
- }
803
- return {
804
- operators,
805
- bridges,
806
- words
807
- }
808
- }
809
-
810
832
  getCounter (maybeName = '') {
811
833
  const counter = this.configCounter
812
834
  this.configCounter += 1
@@ -843,7 +865,11 @@ class Config {
843
865
  namespaced: {}
844
866
  },
845
867
  description: '',
846
- words: {}, // Done
868
+ words: {
869
+ literals: {},
870
+ patterns: [],
871
+ hierarchy: [],
872
+ }, // Done
847
873
  floaters: [],
848
874
  implicits: [],
849
875
  flatten: [],
@@ -1102,8 +1128,8 @@ class Config {
1102
1128
  return elements.map(toCanonicalQuery)
1103
1129
  }
1104
1130
 
1105
- const templateQueries = toCanonicalQueries(template.queries || []).map(helpers.updateQueries)
1106
- const instanceQueries = toCanonicalQueries(instance.queries || [])
1131
+ const templateQueries = toCanonicalQueries(template.configs || []).map(helpers.updateQueries)
1132
+ const instanceQueries = toCanonicalQueries(instance.configs || [])
1107
1133
  let sameQueries = true
1108
1134
  let startOfChanges
1109
1135
  for (let iq = 0; iq < templateQueries.length; ++iq) {
@@ -1124,7 +1150,6 @@ class Config {
1124
1150
  if (templateQueries.length < instanceQueries.length) {
1125
1151
  startOfChanges = instanceQueries.length
1126
1152
  }
1127
- // const sameQueries = helpers.safeEquals(toCanonicalQueries(template.queries || []).map(helpers.updateQueries), toCanonicalQueries(instance.queries || []))
1128
1153
 
1129
1154
  if (debug) {
1130
1155
  if (!(instance && sameQueries && sameFragments)) {
@@ -1133,8 +1158,6 @@ class Config {
1133
1158
  console.log('sameFragments', sameFragments)
1134
1159
  // console.log("templateFragments", templateFragments)
1135
1160
  // console.log("instanceFragments", instanceFragments)
1136
- // console.log('template.queries', JSON.stringify(toCanonicalQueries(template.queries || []).map(helpers.updateQueries), null, 2))
1137
- // console.log("instance.queries", JSON.stringify(toCanonicalQueries(instance.queries || []), null, 2))
1138
1161
  }
1139
1162
  }
1140
1163
  if (startOfChanges || instance.resultss) {
@@ -1145,13 +1168,13 @@ class Config {
1145
1168
  }
1146
1169
 
1147
1170
  validifyTemplate (template) {
1148
- if (!template.queries && !template.fragments) {
1149
- throw new Error(`Expected the template for ${this.name} to be an object that can have the properties: queries and fragments`)
1171
+ if (!template.configs && !template.fragments) {
1172
+ throw new Error(`Expected the template for ${this.name} to be an object that can have the properties: configs and fragments`)
1150
1173
  }
1151
- for (const query of template.queries || []) {
1174
+ for (const query of template.configs || []) {
1152
1175
  if (typeof query === 'string') {
1153
1176
  } else if (query instanceof Config) {
1154
- throw new Error(`For the template for ${this.name}, each element in queries should be either a string or a structure with a config (not a Config object).`)
1177
+ throw new Error(`For the template for ${this.name}, each element in configs should be either a string or a structure with a config (not a Config object).`)
1155
1178
  }
1156
1179
  }
1157
1180
  }
@@ -1168,7 +1191,7 @@ class Config {
1168
1191
  this.logs.push(`loading template for ${this.name}`)
1169
1192
  if (options.rebuild) {
1170
1193
  // TODO fix beforeQuery
1171
- template = { fragments: [], queries: [], ...template }
1194
+ template = { fragments: [], configs: [], ...template }
1172
1195
  template.fragments = template.fragments.concat(this.dynamicFragments)
1173
1196
  client.rebuildTemplate({ config: this, target: this.name, previousResultss: options.previousResultss, startOfChanges: options.startOfChanges, beforeQuery: () => {}, template, ...options })
1174
1197
  } else {
@@ -1176,7 +1199,7 @@ class Config {
1176
1199
  // this.initInstances.push({ ...instance, name: config.name })
1177
1200
  const isEmpty = (instance) => {
1178
1201
  const properties = [
1179
- 'queries',
1202
+ 'configs',
1180
1203
  'resultss',
1181
1204
  'fragments',
1182
1205
  'semantics',
@@ -1189,7 +1212,7 @@ class Config {
1189
1212
  for (let i = 0; i < instance.resultss.length; ++i) {
1190
1213
  const result = instance.resultss[i]
1191
1214
  if (result.apply) {
1192
- result.apply = template.queries[i]
1215
+ result.apply = template.configs[i]
1193
1216
  }
1194
1217
  }
1195
1218
  instance.name = this.name
@@ -1429,21 +1452,41 @@ class Config {
1429
1452
 
1430
1453
  addWordInternal (word, def, uuid) {
1431
1454
  if (!this.config.words) {
1432
- this.config.words = {}
1455
+ this.config.words = {
1456
+ literals: {},
1457
+ patterns: [],
1458
+ hierarchy: [],
1459
+ }
1433
1460
  }
1434
- const words = this.config.words
1461
+
1462
+ const literals = this.config.words.literals
1435
1463
  def = Object.assign({}, def, { uuid: uuid || this._uuid })
1436
- if (words[word]) {
1437
- if (!words[word].some((e) => helpers.safeEquals(e, def))) {
1438
- words[word].unshift(def)
1464
+ if (literals[word]) {
1465
+ if (!literals[word].some((e) => helpers.safeEquals(e, def))) {
1466
+ literals[word].unshift(def)
1439
1467
  }
1440
1468
  } else {
1441
- words[word] = [def]
1469
+ literals[word] = [def]
1442
1470
  }
1443
1471
 
1444
1472
  this._delta.json.words.push({ action: 'add', word, def })
1445
1473
  }
1446
1474
 
1475
+ addPattern (pattern, def, uuid) {
1476
+ if (!this.config.words) {
1477
+ this.config.words = {
1478
+ literals: {},
1479
+ patterns: [],
1480
+ hierarchy: [],
1481
+ }
1482
+ }
1483
+
1484
+ const patterns = this.config.words.patterns
1485
+ def = Object.assign({}, def, { uuid: uuid || this._uuid })
1486
+ patterns.unshift({ pattern, defs: [def] })
1487
+ this._delta.json.words.push({ action: 'add', pattern, defs: [def] })
1488
+ }
1489
+
1447
1490
  getAPI (uuid) {
1448
1491
  if (this._uuid === uuid) {
1449
1492
  return this.api
@@ -1637,13 +1680,35 @@ class Config {
1637
1680
  config.generators = config.generators.filter((element) => !element.development)
1638
1681
  config.semantics = config.semantics.filter((element) => !element.development)
1639
1682
  config.hierarchy = (config.hierarchy).filter((element) => !element.development)
1640
- for (const word in config.words) {
1641
- const defs = config.words[word] || []
1642
- config.words[word] = defs.filter((def) => !def.development)
1643
- if (config.words[word].length == 0) {
1644
- delete config.words[word]
1683
+
1684
+ const literals = config.words.literals
1685
+ for (const word in literals) {
1686
+ const defs = literals[word] || []
1687
+ literals[word] = defs.filter((def) => !def.development)
1688
+ if (literals[word].length == 0) {
1689
+ delete literals[word]
1690
+ }
1691
+ }
1692
+
1693
+ const patterns = config.words.patterns || []
1694
+ const patternsPrime = []
1695
+ for (const pattern of patterns) {
1696
+ let defs = pattern.defs || []
1697
+ defs = defs.filter((def) => !def.development)
1698
+ if (defs.length !== 0) {
1699
+ patternsPrime.push({...pattern, defs})
1645
1700
  }
1646
1701
  }
1702
+ config.words.patterns = patternsPrime
1703
+
1704
+ const hierarchy = config.words.hierarchy || []
1705
+ const hierarchyPrime = []
1706
+ for (const pair of hierarchy) {
1707
+ if (!pair.development) {
1708
+ hierarchyPrime.push(pair)
1709
+ }
1710
+ }
1711
+ config.words.hierarchy = hierarchyPrime
1647
1712
  }
1648
1713
 
1649
1714
  // configs = [ { config, namespace } ... ]
@@ -1657,7 +1722,7 @@ class Config {
1657
1722
 
1658
1723
  config.operators = config.operators || []
1659
1724
  config.bridges = config.bridges || []
1660
- config.words = config.words || {}
1725
+ config.words = config.words || { literals: {}, patterns: [], hierarchy: [] }
1661
1726
  config.generators = config.generators || []
1662
1727
  config.semantics = config.semantics || []
1663
1728
  config.hierarchy = config.hierarchy || []
@@ -1687,7 +1752,7 @@ class Config {
1687
1752
  this.instances = []
1688
1753
  this.logs = []
1689
1754
  this.dynamicFragments = []
1690
- // when running queries any bridges added are marked as transitory so that the associated will ignore those op's
1755
+ // when running configs any bridges added are marked as transitory so that the associated will ignore those op's
1691
1756
  this.transitoryMode = false
1692
1757
 
1693
1758
  // check for duplicate bridges
@@ -1709,11 +1774,8 @@ class Config {
1709
1774
  }
1710
1775
 
1711
1776
  if (config && config.words) {
1712
- for (const word of Object.keys(config.words)) {
1713
- for (const def of config.words[word]) {
1714
- isValidDef(word, def, config)
1715
- }
1716
- }
1777
+ initWords(config.words)
1778
+ isValidWordDef(config.words)
1717
1779
  }
1718
1780
 
1719
1781
  if (config && config.priorities) {
@@ -1778,7 +1840,16 @@ class Config {
1778
1840
  getAddedArgs (args) {
1779
1841
  for (let addedArgs of this.addedArgss) {
1780
1842
  addedArgs = addedArgs(args)
1843
+ const getUUIDScoped = addedArgs.getUUIDScoped
1844
+ delete addedArgs.getUUIDScoped
1781
1845
  Object.assign(args, addedArgs)
1846
+ if (getUUIDScoped) {
1847
+ const currentGetUUIDScoped = args.getUUIDScoped
1848
+ if (!currentGetUUIDScoped) {
1849
+ debugger
1850
+ }
1851
+ args.getUUIDScoped = (uuid) => Object.assign(currentGetUUIDScoped(uuid), getUUIDScoped(uuid))
1852
+ }
1782
1853
  }
1783
1854
  }
1784
1855
 
@@ -2020,10 +2091,28 @@ class Config {
2020
2091
  this.config.namespaces = ns
2021
2092
  }
2022
2093
 
2023
- if (this.config.words) {
2024
- const words = this.config.words
2025
- for (const key in words) {
2026
- words[key].forEach((o) => {
2094
+ if (!this.config.words) {
2095
+ this.config.words = {}
2096
+ }
2097
+
2098
+ if (this.config.words.literals) {
2099
+ const literals = this.config.words.literals
2100
+ for (const key in literals) {
2101
+ literals[key].forEach((o) => {
2102
+ if (o.uuid) {
2103
+ if (map[o.uuid]) {
2104
+ o.uuid = map[o.uuid]
2105
+ }
2106
+ } else {
2107
+ o.uuid = this._uuid
2108
+ }
2109
+ })
2110
+ }
2111
+ }
2112
+
2113
+ const mapDefList = (list) => {
2114
+ for (const element of list) {
2115
+ element.defs.forEach((o) => {
2027
2116
  if (o.uuid) {
2028
2117
  if (map[o.uuid]) {
2029
2118
  o.uuid = map[o.uuid]
@@ -2035,6 +2124,22 @@ class Config {
2035
2124
  }
2036
2125
  }
2037
2126
 
2127
+ if (this.config.words.patterns) {
2128
+ mapDefList(this.config.words.patterns)
2129
+ }
2130
+
2131
+ if (this.config.words.hierarchy) {
2132
+ for (const o of this.config.words.hierarchy) {
2133
+ if (o.uuid) {
2134
+ if (map[o.uuid]) {
2135
+ o.uuid = map[o.uuid]
2136
+ }
2137
+ } else {
2138
+ o.uuid = this._uuid
2139
+ }
2140
+ }
2141
+ }
2142
+
2038
2143
  if (this.config.bridges) {
2039
2144
  this.config.bridges.forEach((bridge) => {
2040
2145
  if (bridge.uuid) {
@@ -2207,11 +2312,14 @@ class Config {
2207
2312
  }
2208
2313
  */
2209
2314
 
2210
- for (const key in this.config.words) {
2211
- const values = this.config.words[key]
2212
- if (values.some((word) => (Object.keys(word).includes('uuid') && !word.uuid))) {
2213
- debugBreak()
2214
- return false
2315
+ const literals = this.config.words.literals
2316
+ if (literals) {
2317
+ for (const key in literals) {
2318
+ const values = literals[key]
2319
+ if (values.some((word) => (Object.keys(word).includes('uuid') && !word.uuid))) {
2320
+ debugBreak()
2321
+ return false
2322
+ }
2215
2323
  }
2216
2324
  }
2217
2325
 
@@ -2425,7 +2533,7 @@ class Config {
2425
2533
  this.config.hierarchy = []
2426
2534
  this.config.priorities = []
2427
2535
  this.config.associations = { positive: [], negative: [] }
2428
- this.config.words = {}
2536
+ this.config.words = initWords({})
2429
2537
 
2430
2538
  for (let i = 0; i < addInternals.length; ++i) {
2431
2539
  let name
@@ -2612,13 +2720,25 @@ class Config {
2612
2720
  }
2613
2721
 
2614
2722
  if (config.words) {
2615
- const words = {}
2616
- for (const word in config.words) {
2617
- words[word] = config.words[word].map((word) => {
2723
+ const literals = {}
2724
+ for (const word in config.words.literals) {
2725
+ literals[word] = config.words.literals[word].map((word) => {
2618
2726
  return Object.assign({}, word, { id: toNS(word.id), uuid })
2619
2727
  })
2620
2728
  }
2621
- config.words = words
2729
+ config.words.literals = literals
2730
+
2731
+ for (const pattern of config.words.patterns) {
2732
+ pattern.defs.forEach((def) => {
2733
+ def.id = toNS(def.id)
2734
+ def.uuid = uuid
2735
+ })
2736
+ }
2737
+
2738
+ for (const pair of config.words.hierarchy) {
2739
+ pair.child = toNS(pair.child)
2740
+ pair.parent = toNS(pair.parent)
2741
+ }
2622
2742
  }
2623
2743
 
2624
2744
  if (config.hierarchy) {
@@ -2739,6 +2859,7 @@ class Config {
2739
2859
  throw new Error(`Setting invalid property ${property}`)
2740
2860
  }
2741
2861
 
2862
+ // TODO trie
2742
2863
  if (property == 'words') {
2743
2864
  for (const word in value) {
2744
2865
  for (const def of value[word]) {
@@ -2803,7 +2924,8 @@ class Config {
2803
2924
  more = more.copy()
2804
2925
  more.server(this._server, this._key, this._queryParams)
2805
2926
 
2806
- this.loadOrder.addList(more.configs.map((km) => km.name || km.uuid))
2927
+ const moreConfigs = more.configs.map((km) => km.name || km.uuid)
2928
+ this.loadOrder.addList(moreConfigs)
2807
2929
 
2808
2930
  // get the new ones
2809
2931
  // remove the dups
@@ -2885,16 +3007,36 @@ class Config {
2885
3007
  continue
2886
3008
  }
2887
3009
  if (key === 'words') {
2888
- const configWords = this.config.words
2889
- const moreWords = more.words
2890
- for (const word of Object.keys(moreWords)) {
2891
- if (!configWords[word]) {
2892
- configWords[word] = []
3010
+ if (more.words.literals) {
3011
+ const literals = this.config.words.literals
3012
+ const moreLiterals = more.words.literals
3013
+ for (const word of Object.keys(moreLiterals)) {
3014
+ if (!literals[word]) {
3015
+ literals[word] = []
3016
+ }
3017
+ if (addFirst) {
3018
+ literals[word] = moreLiterals[word].concat(literals[word])
3019
+ } else {
3020
+ literals[word] = literals[word].concat(moreLiterals[word])
3021
+ }
2893
3022
  }
3023
+ }
3024
+ if (more.words.patterns) {
3025
+ const patterns = this.config.words.patterns
3026
+ const morePatterns = more.words.patterns
2894
3027
  if (addFirst) {
2895
- configWords[word] = moreWords[word].concat(configWords[word])
3028
+ this.config.words.patterns = morePatterns.concat(patterns)
2896
3029
  } else {
2897
- configWords[word] = configWords[word].concat(moreWords[word])
3030
+ this.config.words.patterns = patterns.concat(morePatterns)
3031
+ }
3032
+ }
3033
+ if (more.words.hierarchy) {
3034
+ const hierarchy = this.config.words.hierarchy
3035
+ const moreHierarchy = more.words.hierarchy
3036
+ if (addFirst) {
3037
+ this.config.words.hierarchy = moreHierarchy.concat(hierarchy)
3038
+ } else {
3039
+ this.config.words.hierarchy = hierarchy.concat(moreHierarchy)
2898
3040
  }
2899
3041
  }
2900
3042
  } else if (key === 'name') {
@@ -3006,14 +3148,25 @@ class Config {
3006
3148
  continue
3007
3149
  }
3008
3150
  if (key === 'words') {
3009
- const configWords = this.config.words
3010
- const moreWords = more.words
3011
- for (const word of Object.keys(moreWords)) {
3012
- if (!configWords[word]) {
3013
- configWords[word] = []
3151
+ if (this.config.words.literals) {
3152
+ const literals = this.config.words.literals
3153
+ const moreLiterals = more.words.literals
3154
+ for (const word of Object.keys(moreLiterals)) {
3155
+ if (!literals[word]) {
3156
+ literals[word] = []
3157
+ }
3158
+ literals[word] = moreLiterals[word].concat(literals[word])
3014
3159
  }
3015
- // configWords[word] = configWords[word].concat(moreWords[word])
3016
- configWords[word] = moreWords[word].concat(configWords[word])
3160
+ }
3161
+ if (this.config.words.patterns) {
3162
+ const patterns = this.config.words.patterns
3163
+ const morePatterns = more.words.patterns
3164
+ this.config.words.patterns = morePatterns.concat(patterns)
3165
+ }
3166
+ if (this.config.words.hierarchy) {
3167
+ const hierarchy = this.config.words.hierarchy
3168
+ const moreHierarchy = more.words.hierarchy
3169
+ this.config.words.hierarchy = moreHierarchy.concat(hierarchy)
3017
3170
  }
3018
3171
  } else if (key === 'name') {
3019
3172
  /*
package/src/digraph.js CHANGED
@@ -113,19 +113,31 @@ class Digraph {
113
113
  }
114
114
 
115
115
  minima (nodes) {
116
- let minima = new Set(nodes)
117
- const ancestors = new Set([])
118
- nodes.forEach((node) => {
119
- this.ancestors(node).forEach((n) => ancestors.add(n))
120
- })
121
- ancestors.forEach((n) => minima.delete(n))
122
- if (minima.size === 0) {
123
- // all unrelated
124
- minima = new Set(nodes)
116
+ nodes = new Set(nodes)
117
+ const nodeToDescendants = {}
118
+ for (const node of nodes) {
119
+ nodeToDescendants[node] = this.descendants(node)
120
+ }
121
+ let minima = new Set()
122
+ for (const node of nodes) {
123
+ let okay = true
124
+ for (const key of nodeToDescendants[node]) {
125
+ if (nodes.has(key)) {
126
+ if (key in nodeToDescendants && nodeToDescendants[key].has(node)) {
127
+ continue
128
+ }
129
+ okay = false
130
+ break
131
+ }
132
+ }
133
+ if (okay) {
134
+ minima.add(node)
135
+ }
125
136
  }
126
137
  return minima
127
138
  }
128
139
 
140
+ /*
129
141
  maxima (nodes) {
130
142
  const maxima = new Set(nodes)
131
143
  const descendants = new Set([])
@@ -135,14 +147,21 @@ class Digraph {
135
147
  descendants.forEach((n) => maxima.delete(n))
136
148
  return maxima
137
149
  }
150
+ */
138
151
 
139
152
  add (child, parent) {
140
153
  this._edges.push([child, parent])
141
154
  }
142
155
 
156
+ exists(child, parent) {
157
+ return this._edges.find((edge) => edge[0] == child && edge[1] == parent)
158
+ }
159
+
143
160
  addList (l) {
144
161
  for (let i = 1; i < l.length; ++i) {
145
- this._edges.push([l[i - 1], l[i]])
162
+ if (!this.exists(l[i-1], l[i])) {
163
+ this._edges.push([l[i - 1], l[i]])
164
+ }
146
165
  }
147
166
  }
148
167
 
@@ -81,19 +81,31 @@ class DigraphInternal {
81
81
  }
82
82
 
83
83
  minima (nodes) {
84
- let minima = new Set(nodes)
85
- const ancestors = new Set([])
86
- nodes.forEach((node) => {
87
- this.ancestors(node).forEach((n) => ancestors.add(n))
88
- })
89
- ancestors.forEach((n) => minima.delete(n))
90
- if (minima.size === 0) {
91
- // all unrelated
92
- minima = new Set(nodes)
84
+ nodes = new Set(nodes)
85
+ const nodeToDescendants = {}
86
+ for (const node of nodes) {
87
+ nodeToDescendants[node] = this.descendants(node)
88
+ }
89
+ let minima = new Set()
90
+ for (const node of nodes) {
91
+ let okay = true
92
+ for (const key of nodeToDescendants[node]) {
93
+ if (nodes.has(key)) {
94
+ if (key in nodeToDescendants && nodeToDescendants[key].has(node)) {
95
+ continue
96
+ }
97
+ okay = false
98
+ break
99
+ }
100
+ }
101
+ if (okay) {
102
+ minima.add(node)
103
+ }
93
104
  }
94
105
  return minima
95
106
  }
96
107
 
108
+ /*
97
109
  maxima (nodes) {
98
110
  const maxima = new Set(nodes)
99
111
  const descendants = new Set([])
@@ -103,14 +115,21 @@ class DigraphInternal {
103
115
  descendants.forEach((n) => maxima.delete(n))
104
116
  return maxima
105
117
  }
118
+ */
106
119
 
107
120
  add (child, parent) {
108
121
  this._edges.push([child, parent])
109
122
  }
110
123
 
124
+ exists(child, parent) {
125
+ return this._edges.findIndex((edge) => edge[0] == child && edge[1] == parent) != -1
126
+ }
127
+
111
128
  addList (l) {
112
129
  for (let i = 1; i < l.length; ++i) {
113
- this._edges.push([l[i - 1], l[i]])
130
+ if (!this.exists(l[i-1], l[i])) {
131
+ this._edges.push([l[i - 1], l[i]])
132
+ }
114
133
  }
115
134
  }
116
135