theprogrammablemind 7.7.0 → 7.8.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
@@ -30,18 +30,29 @@ const pickObjects = (testConfig, objects) => {
30
30
  return project(objects, getConfig_getObjectsCheck(testConfig))
31
31
  }
32
32
 
33
+ // move ask to the KM's since verbatim is called
33
34
  const getAsk = (config) => (uuid) => (asks) => {
34
35
  for (let ask of asks) {
36
+ let oneShot = true // default
37
+ if (ask.oneShot === false) {
38
+ oneShot = false
39
+ }
35
40
  config.addSemantic({
36
41
  uuid,
37
- oneShot: true,
42
+ oneShot,
38
43
  match: (args) => ask.matchr(args),
39
44
  apply: (args) => ask.applyr(args)
40
45
  })
41
46
  }
47
+ let oneShot = true
48
+ for (let ask of asks) {
49
+ if (ask.oneShot === false) {
50
+ oneShot = false
51
+ }
52
+ }
42
53
  config.addSemantic({
43
54
  uuid,
44
- oneShot: true,
55
+ oneShot,
45
56
  match: ({context}) => context.marker == 'controlEnd' || context.marker == 'controlBetween',
46
57
  apply: (args) => {
47
58
  for (let ask of asks) {
@@ -57,14 +68,18 @@ const getAsk = (config) => (uuid) => (asks) => {
57
68
  }
58
69
  if (matchq(args)) {
59
70
  // args.context.motivationKeep = true
71
+ args.verbatim(applyq(args))
72
+ /*
60
73
  args.context.verbatim = applyq(args)
61
74
  args.context.isResponse = true;
62
75
  delete args.context.controlRemove;
76
+ */
63
77
  args.context.controlKeepMotivation = true;
64
78
  break
65
79
  }
66
80
  }
67
- }
81
+ args.context.cascade = true
82
+ }
68
83
  })
69
84
  }
70
85
 
@@ -169,6 +184,7 @@ const setupArgs = (args, config, logs, hierarchy) => {
169
184
  apis: getAPIs(uuid)
170
185
  }
171
186
  }
187
+ Object.assign(args, args.getUUIDScoped(this.uuid))
172
188
  args.breakOnSemantics = false
173
189
  args.theDebugger = {
174
190
  breakOnSemantics: (value) => args.breakOnSemantics = value
@@ -179,11 +195,23 @@ const setupArgs = (args, config, logs, hierarchy) => {
179
195
  args.log = (message) => logs.push(message)
180
196
 
181
197
  args.addAssumedScoped = (args, assumed) => {
198
+ const addAssumed = (args, ...moreAssumed) => {
199
+ return { ...args, assumed: Object.assign({}, (args.assumed || {}), ...moreAssumed) }
200
+ }
201
+
182
202
  args.s = (c) => config.getSemantics(logs).apply(args, c)
183
- args.g = (c) => config.getGenerators(logs).apply(args, c)
184
- args.gp = (c) => config.getGenerators(logs).apply({...args, assumed: {paraphrase: true, isResponse: false, response: false}}, c, {paraphrase: true, isResponse: false, response: false})
185
- args.gr = (c) => config.getGenerators(logs).apply({...args, assumed: {paraphrase: false, isResponse: true}}, { ...c, paraphrase: false, isResponse: true })
186
- args.e = (c) => config.getEvaluator(args.s, args.calls, logs, c)
203
+ args.g = (c, a = {}) => {
204
+ return config.getGenerators(logs).apply(addAssumed(args, a), c, a)
205
+ }
206
+ args.gp = (c, a = {}) => {
207
+ return config.getGenerators(logs).apply(addAssumed(args, a, {paraphrase: true, isResponse: false, response: false}), c, {paraphrase: true, isResponse: false, response: false})
208
+ }
209
+ args.gr = (c, a = {}) => {
210
+ return config.getGenerators(logs).apply(addAssumed(args, a, {paraphrase: false, isResponse: true}), { ...c, paraphrase: false, isResponse: true })
211
+ }
212
+ args.e = (c) => {
213
+ return config.getEvaluator(args.s, args.calls, logs, c)
214
+ }
187
215
  args.gs = gs(args.g)
188
216
  args.gsp = gs(args.gp)
189
217
  args.gsr = gs(args.gr)
@@ -467,8 +495,6 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
467
495
  }
468
496
  // assumed = { paraphrase: true, response: false };
469
497
  assumed = { paraphrase: true, isResponse: false, response: false };
470
- // args.g = (c) => config.getGenerators(json.logs).apply({...args, assumed}, c, assumed)
471
- // args.gs = gs(args.g)
472
498
  if (generateParenthesized) {
473
499
  config.parenthesized = false
474
500
  }
@@ -479,8 +505,6 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
479
505
  paraphrasesParenthesized = config.getGenerators(json.logs).apply({...args, assumed}, contextPrime, assumed)
480
506
  config.parenthesized = false
481
507
  }
482
- // args.g = (c) => config.getGenerators(json.logs).apply(args, c)
483
- // args.gs = gs(args.g)
484
508
  contextsPrime.push(contextPrime)
485
509
  generatedPrime.push(generated)
486
510
  paraphrasesPrime.push(paraphrases)
@@ -613,11 +637,25 @@ const loadInstance = (config, instance) => {
613
637
  // config.addInternal(results, useOldVersion = true, skipObjects = false, includeNamespaces = true, allowNameToBeNull = false)
614
638
  // config.addInternal(config.template.queries[i], { handleCalculatedProps: true } )
615
639
  config.addInternal(instance.template.queries[i], { addFirst: true, handleCalculatedProps: true } )
640
+ } else if (results.apply) {
641
+ const objects = config.get('objects')
642
+ const args = { objects, getObjects: getObjects(objects) }
643
+ if (instance.queries) {
644
+ args.isInstance = `instance${i}`
645
+ args.instance = instance.queries[i]
646
+ }
647
+ setupArgs(args, config, config.logs, hierarchy)
648
+ results.apply(args)
616
649
  } else {
617
650
  if (results.skipSemantics) {
618
651
  config.config.skipSemantics = results.skipSemantics
619
652
  }
620
- processContextsB({ config, hierarchy, json: results/*, generators, semantics */, commandLineArgs: {}, isInstance: `instance${i}`, instance: instance.queries[i] })
653
+ const args = { config, hierarchy, json: results, commandLineArgs: {} }
654
+ if (instance.queries) {
655
+ args.isInstance = `instance${i}`
656
+ args.instance = instance.queries[i]
657
+ }
658
+ processContextsB(args)
621
659
  if (results.skipSemantics) {
622
660
  config.config.skipSemantics = null
623
661
  }
@@ -1183,8 +1221,8 @@ const defaultInnerProcess = (config, errorHandler, responses) => {
1183
1221
 
1184
1222
  if (responses.explain_priorities) {
1185
1223
  console.log("Explain Priorities")
1186
- for ([inputss, outpus, reason] of responses.explain_priorities) {
1187
- console.log(` ${JSON.stringify(inputss)} reason: ${reason}`)
1224
+ for ([inputs, output, reason] of responses.explain_priorities) {
1225
+ console.log(` inputs: ${JSON.stringify(inputs)} output: ${JSON.stringify(output)} reason: ${reason}`)
1188
1226
  }
1189
1227
  }
1190
1228
  const objects = config.get('objects').namespaced[config.uuid]
@@ -1241,7 +1279,7 @@ const defaultProcess = ({ config, errorHandler }) => async (promise) => {
1241
1279
  }
1242
1280
 
1243
1281
  // builtTemplate saveInstance
1244
- const rebuildTemplate = async ({ config, target, template, errorHandler = defaultErrorHandler }) => {
1282
+ const rebuildTemplate = async ({ config, target, previousResultss, startOfChanges, template, errorHandler = defaultErrorHandler }) => {
1245
1283
  const accumulators = {
1246
1284
  resultss: [],
1247
1285
  fragments: [],
@@ -1254,7 +1292,7 @@ const rebuildTemplate = async ({ config, target, template, errorHandler = defaul
1254
1292
  finish()
1255
1293
  return
1256
1294
  }
1257
- const { property, hierarchy, query: queryOrExtraConfig, initializer, skipSemantics } = queries.shift()
1295
+ const { property, hierarchy, query: queryOrExtraConfig, previousResults, initializer, skipSemantics } = queries.shift()
1258
1296
  // queries are strings or { query: "blah", development: true/false }
1259
1297
  if (typeof queryOrExtraConfig === 'string' || queryOrExtraConfig.query) {
1260
1298
  let query = queryOrExtraConfig;
@@ -1276,17 +1314,26 @@ const rebuildTemplate = async ({ config, target, template, errorHandler = defaul
1276
1314
  }
1277
1315
  }
1278
1316
  try {
1279
- const results = await _process(config, query.query, {initializer, rebuildingTemplate: true})
1317
+ let results
1318
+ let prMessage = ''
1319
+ if (previousResults && previousResults.query == query.query) {
1320
+ results = previousResults
1321
+ prMessage = ' Using previous results. use -rtf for a hard rebuild of everything on the server side.'
1322
+ loadInstance(config, { resultss: [results] })
1323
+ } else {
1324
+ results = await _process(config, query.query, {initializer, rebuildingTemplate: true})
1325
+ }
1280
1326
  if (config.config.debug) {
1281
1327
  // TODO pass in the error handler like the other ones
1282
1328
  defaultInnerProcess(config, defaultErrorHandler, results)
1283
1329
  }
1284
1330
  if (results.contexts.length > 1) {
1285
1331
  console.log(`query "${query.query}". There is ${results.contexts.length} contexts in the results. Make sure its producing the results that you expect.`)
1332
+ throw new Error(`query "${query.query}". There is ${results.contexts.length} contexts in the results. Make sure its producing the results that you expect.`)
1286
1333
  } else if (results.paraphrases[0] != query.query) {
1287
- console.log(`query "${query.query}". The paraphrase is different from the query "${results.paraphrases[0]}".`)
1334
+ console.log(`query "${query.query}". The paraphrase is different from the query "${results.paraphrases[0]}".${prMessage}`)
1288
1335
  } else {
1289
- console.log(`query ${query.query}`)
1336
+ console.log(`query "${query.query}".${prMessage}`)
1290
1337
  }
1291
1338
  global.transitoryMode = transitoryMode
1292
1339
  config.config.skipSemantics = null
@@ -1303,19 +1350,32 @@ const rebuildTemplate = async ({ config, target, template, errorHandler = defaul
1303
1350
  config.config.skipSemantics = null
1304
1351
  errorHandler(error)
1305
1352
  }
1353
+ } else if (typeof queryOrExtraConfig == 'function') {
1354
+ console.log('calling initialize function')
1355
+ const initFunction = queryOrExtraConfig
1356
+ const objects = config.get('objects')
1357
+ const args = { objects, getObjects: getObjects(objects) }
1358
+ setupArgs(args, config, config.logs, hierarchy)
1359
+ initFunction(args)
1360
+ accumulators[property].push({ apply: queryOrExtraConfig })
1361
+ await looper(queries)
1306
1362
  } else {
1307
1363
  // extra config is def from a time like operators or bridges or words etc
1308
1364
  // it will just get added to the config
1309
1365
  const extraConfig = queryOrExtraConfig
1310
1366
  console.log('config', extraConfig)
1311
- try {
1312
- config.addInternal(_.cloneDeep(extraConfig), { handleCalculatedProps: true } )
1313
- } catch ( e ) {
1314
- const where = extraConfig.where ? ` ${extraConfig.where}` : ''
1315
- throw new Error(`Error processing extra config${where}: ${e.stack}}`)
1367
+ if (extraConfig.stop) {
1368
+ await looper([])
1369
+ } else {
1370
+ try {
1371
+ config.addInternal(_.cloneDeep(extraConfig), { handleCalculatedProps: true } )
1372
+ } catch ( e ) {
1373
+ const where = extraConfig.where ? ` ${extraConfig.where}` : ''
1374
+ throw new Error(`Error processing extra config${where}: ${e.stack}}`)
1375
+ }
1376
+ accumulators[property].push({ extraConfig: true, ...extraConfig })
1377
+ await looper(queries)
1316
1378
  }
1317
- accumulators[property].push({ extraConfig: true, ...extraConfig })
1318
- await looper(queries)
1319
1379
  }
1320
1380
  }
1321
1381
 
@@ -1331,8 +1391,11 @@ const rebuildTemplate = async ({ config, target, template, errorHandler = defaul
1331
1391
  const stabilizeOutput = (template) => {
1332
1392
  stabilizeAssociations(template.associations)
1333
1393
  const stabilize = (results) => {
1334
- for (let result of results) {
1335
- if (result.extraConfig) {
1394
+ for (let i = 0; i < results.length; ++i) {
1395
+ const result = results[i]
1396
+ if (result.apply) {
1397
+ result.apply = result.apply.toString()
1398
+ } else if (result.extraConfig) {
1336
1399
  } else {
1337
1400
  delete result.load_cache_time
1338
1401
  delete result.times
@@ -1370,7 +1433,13 @@ const rebuildTemplate = async ({ config, target, template, errorHandler = defaul
1370
1433
  }
1371
1434
  let todo = []
1372
1435
  todo = todo.concat((template.initializers || []).map((query) => { return { initializer: true, property: 'resultss', query, skipSemantics: false || query.skipSemantics } }))
1373
- todo = todo.concat((template.queries || []).map((query) => { return { property: 'resultss', query, skipSemantics: false || query.skipSemantics} }))
1436
+ todo = todo.concat((template.queries || []).map((query, index) => {
1437
+ let pr
1438
+ if (index < startOfChanges) {
1439
+ pr = previousResultss[index]
1440
+ }
1441
+ return { property: 'resultss', query, previousResults: pr, skipSemantics: false || query.skipSemantics}
1442
+ }))
1374
1443
  todo = todo.concat((template.fragments || []).map((query) => { return Object.assign({}, toProperties(query), { property: 'fragments', skipSemantics: false }) }))
1375
1444
  todo = todo.concat((template.semantics || []).map((definition) => { return { property: 'semantics', query: `${definition.from}\n${definition.to}`, skipSemantics: true } }))
1376
1445
  await looper(Object.assign([], todo))
@@ -1398,7 +1467,7 @@ const checkTest = (testConfig) => {
1398
1467
  }
1399
1468
  }
1400
1469
 
1401
- const knowledgeModule = async ({
1470
+ const knowledgeModuleImpl = async ({
1402
1471
  module: moduleFromJSFile,
1403
1472
  description,
1404
1473
  section,
@@ -1485,13 +1554,14 @@ const knowledgeModule = async ({
1485
1554
  parser.add_argument('-tnp', '--testNoParenthesized', { action: 'store_true', help: 'Don\' check parenthesized differences for the tests' })
1486
1555
  parser.add_argument('-n', '--count', { help: 'Number of times to run the tests. Default is one. Use this to check for flakey test. If possible the system will print out a message with the word "hint" suggesting how to fix the problem' })
1487
1556
  // parser.add_argument('-b', '--build', { help: 'Specify the template file name of the form <kmName>. There should be a file called <baseKmName>.<kmName>.template.json with the queries to run. For example { queries: [...] }. The template file will be run and generate an instantiation called <baseKmName>.<kmName>.instance.json and a file called <kmName>.js that will load the template file (this is file generated only if not already existing) and a test file called <KmName>.tests.json. This can then be loaded into an instance of the current knowledge module to setup initial conditions.' })
1488
- parser.add_argument('-rt', '--rebuildTemplate', { action: 'store_true', help: 'Force a template rebuild' })
1557
+ parser.add_argument('-rt', '--rebuildTemplate', { action: 'store_true', help: 'Force a template rebuild. Using optimization where if the query/config has not changed it will use the previous value. One there is a change all subsequence query/configs will be run.' })
1558
+ parser.add_argument('-rtf', '--rebuildTemplateFull', { action: 'store_true', help: 'Force a template rebuild. Skip the optimization' })
1489
1559
  parser.add_argument('-l', '--loop', { action: 'store_true', help: 'Run a loop so that multiply queries may be run' })
1490
1560
  parser.add_argument('-i', '--info', { action: 'store_true', help: 'Print meta-data for the module' })
1491
1561
  parser.add_argument('-v', '--vimdiff', { action: 'store_true', help: 'For failures run vimdiff' })
1492
1562
  parser.add_argument('-g', '--greg', { action: 'store_true', help: 'Set the server to be localhost so I can debug stuff' })
1493
1563
  parser.add_argument('-cl', '--checkForLoop', { nargs: "?", help: 'Check for loops in the priorities, Optional argument is list of operator keys to consider. For example [["banana", 0], ["food", 1]]' })
1494
- parser.add_argument('-r', '--retrain', { action: 'store_true', help: 'Get the server to retrain the neural nets' })
1564
+ parser.add_argument('-r', '--reset', { action: 'store_true', help: 'Get the server to bypass the cache and rebuild everything' })
1495
1565
  parser.add_argument('-q', '--query', { help: 'Run the specified query' })
1496
1566
  parser.add_argument('-ip ', '--server', { help: 'Server to run against' })
1497
1567
  parser.add_argument('-qp ', '--queryParams', { help: 'Query params for the server call' })
@@ -1516,6 +1586,10 @@ const knowledgeModule = async ({
1516
1586
  const args = parser.parse_args()
1517
1587
  args.count = args.count || 1
1518
1588
 
1589
+ if (args.rebuildTemplateFull) {
1590
+ args.rebuildTemplate = true
1591
+ }
1592
+
1519
1593
  if (args.parenthesized) {
1520
1594
  config.parenthesized = true
1521
1595
  }
@@ -1606,6 +1680,10 @@ const knowledgeModule = async ({
1606
1680
  config.config.debug = true
1607
1681
  }
1608
1682
 
1683
+ if (args.reset) {
1684
+ config.config.skip_cache = true
1685
+ }
1686
+
1609
1687
  if (args.explainPriorities) {
1610
1688
  config.config.explain_priorities = true
1611
1689
  }
@@ -1706,17 +1784,33 @@ const knowledgeModule = async ({
1706
1784
  checkTemplate(template)
1707
1785
 
1708
1786
  if (template) {
1709
- const needsRebuild = config.needsRebuild(template.template, template.instance, options)
1710
- if (needsRebuild) {
1787
+ let needsRebuild
1788
+ if (args.rebuildTemplate && !args.rebuildTemplateFull) {
1789
+ // get the startOfChanges for the partial rebuild
1790
+ needsRebuild = config.needsRebuild(template.template, template.instance, { ...options, rebuild: false })
1791
+ } else {
1792
+ // do a check or full rebuild
1793
+ needsRebuild = config.needsRebuild(template.template, template.instance, options)
1794
+ }
1795
+
1796
+ if (needsRebuild.needsRebuild) {
1797
+ if (needsRebuild.previousResultss) {
1798
+ console.log("Rebuild using the optimization to use previous results until a change is hit. For a full rebuild use -rtf")
1799
+ }
1711
1800
  console.log(`This module "${config.name}" needs rebuilding all other arguments will be ignored. Try again after the template is rebuilt.`)
1712
1801
  options.rebuild = true
1713
1802
  config.config.rebuild = true
1714
1803
  }
1715
- config.load(template.template, template.instance, { rebuild: needsRebuild })
1804
+ try {
1805
+ config.load(template.template, template.instance, { rebuild: needsRebuild.needsRebuild || options.rebuild, previousResultss: needsRebuild.previousResultss, startOfChanges: needsRebuild.startOfChanges })
1806
+ } catch( e ) {
1807
+ console.error(`Error loading template for ${config.name}. ${e.error ? e.error : e}${e.stack ? e.stack : ''}`)
1808
+ runtime.process.exit(-1)
1809
+ }
1716
1810
  if (!args.query) {
1717
1811
  printConfig()
1718
1812
  }
1719
- if (needsRebuild) {
1813
+ if (needsRebuild.needsRebuild) {
1720
1814
  return
1721
1815
  }
1722
1816
  }
@@ -1792,14 +1886,14 @@ const knowledgeModule = async ({
1792
1886
  console.log(` actual ${label} `, actual)
1793
1887
  newError = true
1794
1888
  headerShown = true
1889
+ if (args.vimdiff) {
1890
+ vimdiff(result.actual.paraphrasesParenthesized, result.expected.paraphrasesParenthesized)
1891
+ }
1795
1892
  }
1796
1893
  }
1797
1894
  show('paraphrases', result.expected.paraphrases, result.actual.paraphrases)
1798
1895
  if (!args.testNoParenthesized) {
1799
1896
  show('paraphrases parenthesized', result.expected.paraphrasesParenthesized, result.actual.paraphrasesParenthesized)
1800
- if (args.vimdiff) {
1801
- vimdiff(result.actual.paraphrasesParenthesized, result.expected.paraphrasesParenthesized)
1802
- }
1803
1897
  }
1804
1898
  /*
1805
1899
  }
@@ -1832,10 +1926,10 @@ const knowledgeModule = async ({
1832
1926
  }
1833
1927
  const widths = [4, 18, 72]
1834
1928
  const lines = new Lines(widths)
1835
- lines.setElement(1, 1, 'expected checked')
1929
+ lines.setElement(1, 1, 'expected checked objects')
1836
1930
  lines.setElement(2, 2, JSON.stringify(result.expected.checked, null, 2))
1837
1931
  lines.log()
1838
- lines.setElement(1, 1, 'actual checked')
1932
+ lines.setElement(1, 1, 'actual checked objects')
1839
1933
  lines.setElement(2, 2, JSON.stringify(result.actual.checked, null, 2))
1840
1934
  lines.log()
1841
1935
  if (args.vimdiff) {
@@ -1850,10 +1944,10 @@ const knowledgeModule = async ({
1850
1944
  }
1851
1945
  const widths = [4, 18, 72]
1852
1946
  const lines = new Lines(widths)
1853
- lines.setElement(1, 1, 'expected checkedContexts', true)
1947
+ lines.setElement(1, 1, 'expected checked contexts', true)
1854
1948
  lines.setElement(2, 2, JSON.stringify(result.expected.checkedContexts, null, 2))
1855
1949
  lines.log()
1856
- lines.setElement(1, 1, 'actual checkedContexts', true)
1950
+ lines.setElement(1, 1, 'actual checked contexts', true)
1857
1951
  lines.setElement(2, 2, JSON.stringify(result.actual.checkedContexts, null, 2))
1858
1952
  lines.log()
1859
1953
  if (args.vimdiff) {
@@ -1879,7 +1973,7 @@ const knowledgeModule = async ({
1879
1973
  if (!(useTestConfig.check && useTestConfig.check.length > 0)) {
1880
1974
  console.log('use -v arg to write files expected.json and actual.json in the current directory for detailed comparison. Or do -s and then git diff the changes.')
1881
1975
  // console.log(JSON.stringify(contexts))
1882
- console.log('**************************** ERRORS ************************')
1976
+ console.log('**************************** THERE WERE ERRORS ************************')
1883
1977
  }
1884
1978
  }
1885
1979
  }
@@ -1965,7 +2059,7 @@ const knowledgeModule = async ({
1965
2059
  }
1966
2060
 
1967
2061
  if (template) {
1968
- if (config.needsRebuild(template.template, template.instance, { isModule: !isProcess })) {
2062
+ if (config.needsRebuild(template.template, template.instance, { isModule: !isProcess }).needsRebuild) {
1969
2063
  const error = `This module "${config.name}" cannot be used because the instance file needs rebuilding. Run on the command line with no arguments or the -rt argument to rebuild.`
1970
2064
  throw new Error(error)
1971
2065
  }
@@ -1985,7 +2079,6 @@ const knowledgeModule = async ({
1985
2079
  }
1986
2080
  moduleFromJSFile.exports = createConfigExport
1987
2081
  }
1988
-
1989
2082
  }
1990
2083
 
1991
2084
  /*
@@ -2033,6 +2126,10 @@ function w(func) {
2033
2126
  return func
2034
2127
  }
2035
2128
 
2129
+ const knowledgeModule = async (...args) => {
2130
+ await knowledgeModuleImpl(...args).catch((e) => console.error(e))
2131
+ }
2132
+
2036
2133
  module.exports = {
2037
2134
  process: _process,
2038
2135
  where,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "devDependencies": {
3
3
  "eslint-plugin-import": "^2.23.4",
4
- "jest": "^26.6.3",
4
+ "jest": "^29.7.0",
5
5
  "@typescript-eslint/parser": "^4.28.4",
6
6
  "@typescript-eslint/eslint-plugin": "^4.28.4",
7
7
  "eslint-plugin-node": "^11.1.0",
@@ -12,6 +12,7 @@
12
12
  "scripts": {
13
13
  "to:debug": "node inspect node_modules/.bin/jest --runInBand -t NEO23",
14
14
  "test:debug": "node inspect node_modules/.bin/jest --runInBand --config ./jest.config.json",
15
+ "td": "node inspect node_modules/.bin/jest --runInBand --config ./jest.config.json",
15
16
  "tod": "node inspect node_modules/.bin/jest --runInBand -t NEO23",
16
17
  "lint:fix": "eslint \"**/*.js\" --fix",
17
18
  "lint": "eslint \"**/*.js\"",
@@ -64,6 +65,6 @@
64
65
  "json-stable-stringify": "^1.0.1",
65
66
  "node-fetch": "^2.6.1"
66
67
  },
67
- "version": "7.7.0",
68
+ "version": "7.8.0",
68
69
  "license": "ISC"
69
70
  }
package/src/config.js CHANGED
@@ -27,7 +27,7 @@ const config_toServer = (config) => {
27
27
 
28
28
  const debugPriority = (priority) => {
29
29
  if (global.entodictonDebugPriority) {
30
- if (helpers.safeEquals(entodictonDebugPriority, priority)) {
30
+ if (helpers.subPriority(entodictonDebugPriority, priority)) {
31
31
  debugger; // debug hierarchy hit
32
32
  }
33
33
  }
@@ -965,7 +965,7 @@ class Config {
965
965
  }
966
966
 
967
967
  // { rebuild: false, isModule: false }
968
- needsRebuild(template, instance, options) {
968
+ needsRebuild (template, instance, options) {
969
969
  if (options.rebuild) {
970
970
  return true
971
971
  }
@@ -983,6 +983,18 @@ class Config {
983
983
  if (typeof queryOrConfig == 'string') {
984
984
  const query = queryOrConfig
985
985
  return query
986
+ } else if (typeof queryOrConfig == 'function') {
987
+ if (options.isModule) {
988
+ return { apply: 'function in the browser has webpack rewrites so can not be compared' }
989
+ } else {
990
+ return { apply: queryOrConfig.toString() }
991
+ }
992
+ } else if (queryOrConfig.apply) {
993
+ if (options.isModule) {
994
+ return { apply: 'function in the browser has webpack rewrites so can not be compared' }
995
+ } else {
996
+ return { apply: queryOrConfig.apply }
997
+ }
986
998
  } else {
987
999
  const config = { ...queryOrConfig }
988
1000
  delete config.where
@@ -1058,7 +1070,27 @@ class Config {
1058
1070
  return elements.map( toCanonicalQuery )
1059
1071
  }
1060
1072
 
1061
- const sameQueries = helpers.safeEquals(toCanonicalQueries(template.queries || []).map(helpers.updateQueries), toCanonicalQueries(instance.queries || []))
1073
+ const templateQueries = toCanonicalQueries(template.queries || []).map(helpers.updateQueries)
1074
+ const instanceQueries = toCanonicalQueries(instance.queries || [])
1075
+ let sameQueries = true
1076
+ let startOfChanges;
1077
+ for (let iq = 0; iq < templateQueries.length; ++iq) {
1078
+ if (!helpers.safeEquals(templateQueries[iq], instanceQueries[iq])) {
1079
+ sameQueries = false
1080
+ startOfChanges = iq
1081
+ }
1082
+ }
1083
+
1084
+ if (startOfChanges) {
1085
+ console.log('templateQueries[startOfChanges]', templateQueries[startOfChanges]);
1086
+ console.log('instanceQueries[startOfChanges]', instanceQueries[startOfChanges]);
1087
+ }
1088
+
1089
+ // things were deleted case
1090
+ if (templateQueries.length < instanceQueries.length) {
1091
+ startOfChanges = instanceQueries.length
1092
+ }
1093
+ // const sameQueries = helpers.safeEquals(toCanonicalQueries(template.queries || []).map(helpers.updateQueries), toCanonicalQueries(instance.queries || []))
1062
1094
 
1063
1095
  const debug = false
1064
1096
  if (debug) {
@@ -1067,16 +1099,20 @@ class Config {
1067
1099
  debugger
1068
1100
  debugger
1069
1101
  }
1070
- console.log("instance", instance)
1102
+ // console.log("instance", instance)
1071
1103
  console.log("sameQueries", sameQueries)
1072
1104
  console.log("sameFragments", sameFragments)
1073
- console.log("templateFragments", templateFragments)
1074
- console.log("instanceFragments", instanceFragments)
1075
- console.log('template.queries', JSON.stringify(toCanonicalQueries(template.queries || []).map(helpers.updateQueries), null, 2))
1076
- console.log("instance.queries", JSON.stringify(toCanonicalQueries(instance.queries || []), null, 2))
1105
+ // console.log("templateFragments", templateFragments)
1106
+ // console.log("instanceFragments", instanceFragments)
1107
+ // console.log('template.queries', JSON.stringify(toCanonicalQueries(template.queries || []).map(helpers.updateQueries), null, 2))
1108
+ // console.log("instance.queries", JSON.stringify(toCanonicalQueries(instance.queries || []), null, 2))
1077
1109
  }
1078
1110
  }
1079
- return !(instance && sameQueries && sameFragments)
1111
+ if (startOfChanges || instance.resultss) {
1112
+ return { needsRebuild: !(instance && sameQueries && sameFragments), startOfChanges, previousResultss: instance.resultss }
1113
+ } else {
1114
+ return { needsRebuild: !(instance && sameQueries && sameFragments) }
1115
+ }
1080
1116
  }
1081
1117
 
1082
1118
  validifyTemplate (template) {
@@ -1097,7 +1133,7 @@ class Config {
1097
1133
  }
1098
1134
 
1099
1135
  // loadTemplate
1100
- load (template, instance, options = { rebuild: false } ) {
1136
+ load (template, instance, options = { rebuild: false, previousResultss: undefined, startOfChanges: undefined } ) {
1101
1137
  this.validifyTemplate(template)
1102
1138
  instance.template = template
1103
1139
  this.logs.push(`loading template for ${this.name}`)
@@ -1105,7 +1141,7 @@ class Config {
1105
1141
  // TODO fix beforeQuery
1106
1142
  template = { fragments: [], queries: [], ...template }
1107
1143
  template.fragments = template.fragments.concat(this.dynamicFragments)
1108
- client.rebuildTemplate({ config: this, target: this.name, beforeQuery: () => {}, template, ...options })
1144
+ client.rebuildTemplate({ config: this, target: this.name, previousResultss: options.previousResultss, startOfChanges: options.startOfChanges, beforeQuery: () => {}, template, ...options })
1109
1145
  } else {
1110
1146
  // no change
1111
1147
  // this.initInstances.push({ ...instance, name: config.name })
@@ -1120,6 +1156,13 @@ class Config {
1120
1156
  return !properties.find( (property) => instance[property] && instance[property].length > 0 )
1121
1157
  }
1122
1158
  if (!isEmpty(instance)) {
1159
+ // fix up apply functions
1160
+ for (let i = 0; i < instance.resultss.length; ++i) {
1161
+ const result = instance.resultss[i]
1162
+ if (result.apply) {
1163
+ result.apply = template.queries[i]
1164
+ }
1165
+ }
1123
1166
  instance.name = this.name
1124
1167
  this.initInstances.push(instance)
1125
1168
  this.instances.push(instance)
@@ -2219,8 +2262,6 @@ class Config {
2219
2262
  const addInternals = []
2220
2263
  const inits = []
2221
2264
  const initAfterApis = []
2222
- const reverseIt = true
2223
- const interleaved = true
2224
2265
  this.configs.forEach((km) => {
2225
2266
  const namespace = km.namespace
2226
2267
  this.config.objects.namespaced[km._uuid] = {}
@@ -2286,58 +2327,30 @@ class Config {
2286
2327
  inits.unshift( () => config._api.initialize({ config: this, km: kmFn, ...args, api: config._api }) )
2287
2328
  // config._api.initialize({ config, api: config._api })
2288
2329
  } else {
2289
- if (interleaved) {
2290
- inits.unshift(null)
2291
- }
2330
+ inits.unshift(null)
2292
2331
  }
2293
2332
  // config._api.objects = namespacedObjects
2294
2333
  // config._api.config = () => this
2295
2334
  // config._api.uuid = config._uuid
2296
2335
  } else {
2297
- if (interleaved) {
2298
- inits.unshift(null)
2299
- }
2336
+ inits.unshift(null)
2300
2337
  }
2301
2338
  config.setUUIDs()
2302
2339
  config.applyNamespace(config.config, namespace, config.uuid)
2303
2340
  if (!isSelf) {
2304
- if (!reverseIt) {
2305
- addInternals.push(config)
2306
- } else {
2307
- addInternals.unshift(config)
2308
- }
2341
+ addInternals.unshift(config)
2309
2342
  } else {
2310
- if (interleaved) {
2311
- addInternals.unshift(null)
2312
- }
2343
+ addInternals.unshift(null)
2313
2344
  }
2314
2345
  km.valid()
2315
2346
  })
2316
2347
 
2317
2348
  const generators = this.config.generators
2318
2349
  const semantics = this.config.semantics
2319
- if (reverseIt) {
2320
- this.config.generators = []
2321
- this.config.semantics = []
2322
- }
2350
+ this.config.generators = []
2351
+ this.config.semantics = []
2323
2352
 
2324
- if (!interleaved) {
2325
- for (const config of addInternals) {
2326
- if (!reverseIt) {
2327
- this.addInternal(config, { includeNamespace: false, allowNameToBeNull: true })
2328
- } else {
2329
- this.addInternalR(config, true, false, false, true)
2330
- }
2331
- }
2332
- // console.log('inits from config', inits)
2333
- for (const init of inits) {
2334
- init()
2335
- }
2336
- for (let init of initAfterApis) {
2337
- init.config.initializerFn({ ...init.args, kms: this.getConfigs(), isAfterApi: true })
2338
- }
2339
- this.instances.forEach((instance) => client.loadInstance(this, instance))
2340
- } else {
2353
+ {
2341
2354
  const base = {
2342
2355
  operators: this.config.operators,
2343
2356
  bridges: this.config.bridges,
@@ -2353,13 +2366,16 @@ class Config {
2353
2366
  this.config.priorities = []
2354
2367
  this.config.associations = { positive: [], negative: [] }
2355
2368
  this.config.words = {}
2356
-
2369
+
2357
2370
  for (let i = 0; i < addInternals.length; ++i) {
2358
2371
  let name;
2359
2372
  if (addInternals[i]) {
2360
2373
  this.addInternalR(addInternals[i], true, false, false, true)
2361
2374
  name = addInternals[i].name
2362
2375
  } else{
2376
+ // the ones defined in config must come after the ones in the templates
2377
+ this.config.generators = generators.concat(this.config.generators)
2378
+ this.config.semantics = semantics.concat(this.config.semantics)
2363
2379
  this.addInternalR(base, true, false, false, true)
2364
2380
  name = this.name
2365
2381
  }
@@ -2380,10 +2396,6 @@ class Config {
2380
2396
  }
2381
2397
  }
2382
2398
 
2383
- if (reverseIt) {
2384
- this.config.generators = generators.concat(this.config.generators)
2385
- this.config.semantics = semantics.concat(this.config.semantics)
2386
- }
2387
2399
  this.hierarchy.edges = this.config.hierarchy
2388
2400
  this.valid()
2389
2401
  this.checkBridges()
package/src/generators.js CHANGED
@@ -169,7 +169,7 @@ class Generators {
169
169
  // assumed - properties added to context before the generators are called. For setting paraphrase property
170
170
  apply (args, context, assumed = {}, options = {}) {
171
171
  if (Array.isArray(context)) {
172
- return new Error("Expected a context not an array")
172
+ throw new Error("Expected a context not an array")
173
173
  }
174
174
  if (typeof context !== 'object') {
175
175
  return String(context)
@@ -179,7 +179,6 @@ class Generators {
179
179
  const objects = args.objects
180
180
  const hierarchy = args.hierarchy
181
181
  const response = args.response
182
-
183
182
 
184
183
  // args = { ...args, ...args.getAssumedScoped(assumed) }
185
184
  args.addAssumedScoped(args, assumed)
package/src/helpers.js CHANGED
@@ -272,6 +272,8 @@ const mapInPlace = (list, fn) => {
272
272
  const updateQueries = (queryOrConfig) => {
273
273
  if (typeof queryOrConfig == 'string' || queryOrConfig.query) {
274
274
  return queryOrConfig
275
+ } else if (typeof queryOrConfig == 'function') {
276
+ return { apply: queryOrConfig.toString() }
275
277
  } else {
276
278
  const config = queryOrConfig
277
279
  return functionsToStrings(config)
@@ -334,6 +336,45 @@ const ecatch = (where, call) => {
334
336
  }
335
337
  }
336
338
 
339
+ const equalKey = (key1, key2) => {
340
+ return key1[0] == key2[0] && key1[1] == key2[1]
341
+ }
342
+
343
+ // matches for { context: ..., [ordered], choose: ... } exactely OR
344
+ // [ <id1>, <id2> ] - where id1 is chosen
345
+ const subPriority = (sub, sup) => {
346
+ if (Array.isArray(sub)) {
347
+ const subChoosen = sub[0]
348
+ const subOther = sub[1]
349
+ const hasChoosen = sup.choose.find( (index) => equalKey(sup.context[index], subChoosen)) != undefined
350
+ const hasOtherChosen = sup.choose.find( (index) => equalKey(sup.context[index], subOther)) != undefined
351
+ const hasOther = sup.context.find( (other) => equalKey(other, subOther) ) !== undefined
352
+ return !!(hasChoosen && hasOther) && !hasOtherChosen
353
+ }
354
+
355
+ if (!safeEquals([...sub.choose].sort(), [...sup.choose].sort())) {
356
+ return false
357
+ }
358
+
359
+ const choose = (priority) => {
360
+ const chosen = []
361
+ for (const i of priority.choose) {
362
+ chosen.push(priority.context[i])
363
+ }
364
+ return chosen
365
+ }
366
+ const chosen1 = choose(sub)
367
+ const chosen2 = choose(sup)
368
+ const sameId = (id1, id2) => id1[0] == id2[0] && id1[1] == id2[1]
369
+ // same length so only need one way
370
+ const missing1 = chosen1.find( (id1) => !chosen2.find( (id2) => sameId(id1, id2)) )
371
+ if (missing1) {
372
+ return false
373
+ }
374
+
375
+ return true
376
+ }
377
+
337
378
  module.exports = {
338
379
  ecatch,
339
380
  functionsToStrings,
@@ -354,5 +395,6 @@ module.exports = {
354
395
  isCompound,
355
396
  InitCalls,
356
397
  hashCode,
357
- sortJson
398
+ sortJson,
399
+ subPriority,
358
400
  }
package/src/project.js CHANGED
@@ -16,6 +16,9 @@ const project = (object, filter) => {
16
16
  return object.map( element => project(element, filter) )
17
17
  } else {
18
18
  for (let properties of filter) {
19
+ if (typeof properties == 'function') {
20
+ properties = properties(object)
21
+ }
19
22
  if (typeof properties == 'object') {
20
23
  if (properties.propertyLists) {
21
24
  for (const propertyList in properties.propertyLists) {