theprogrammablemind 7.5.8-beta.9 → 7.5.8-beta.90

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
@@ -2,6 +2,7 @@ const { Semantics, Semantic } = require('./src/semantics')
2
2
  const { Generators, Generator } = require('./src/generators')
3
3
  const DigraphInternal = require('./src/digraph_internal')
4
4
  const Digraph = require('./src/digraph')
5
+ const { project } = require('./src/project')
5
6
  const fetch = require('node-fetch')
6
7
  const base64 = require('base-64')
7
8
  const deepEqual = require('deep-equal')
@@ -9,20 +10,38 @@ const _ = require('lodash')
9
10
  const stringify = require('json-stable-stringify')
10
11
  const Lines = require('./lines')
11
12
  const flattens = require('./src/flatten')
12
- const { appendNoDups, InitCalls, updateQueries } = require('./src/helpers')
13
+ const { appendNoDups, InitCalls, updateQueries, safeNoDups } = require('./src/helpers')
13
14
  const runtime = require('./runtime')
14
15
  const sortJson = runtime.sortJson
15
16
 
17
+ const getConfig_getObjectsCheck = (testConfig) => {
18
+ return (testConfig.checks && testConfig.checks.objects) || []
19
+ }
20
+
21
+ const getConfig_getContextCheck = (testConfig) => {
22
+ return (testConfig.checks && testConfig.checks.context) || []
23
+ }
24
+
25
+ const pickContext = (testConfig) => (context) => {
26
+ return project(context, getConfig_getContextCheck(testConfig))
27
+ }
28
+
29
+ const pickObjects = (testConfig, objects) => {
30
+ return project(objects, getConfig_getObjectsCheck(testConfig))
31
+ }
32
+
16
33
  const getAsk = (config) => (uuid) => (asks) => {
17
34
  for (let ask of asks) {
18
- config.addMotivation({
35
+ config.addSemantic({
19
36
  uuid,
37
+ oneShot: true,
20
38
  match: (args) => ask.matchr(args),
21
39
  apply: (args) => ask.applyr(args)
22
40
  })
23
41
  }
24
- config.addMotivation({
42
+ config.addSemantic({
25
43
  uuid,
44
+ oneShot: true,
26
45
  match: ({context}) => context.marker == 'controlEnd' || context.marker == 'controlBetween',
27
46
  apply: (args) => {
28
47
  for (let ask of asks) {
@@ -37,7 +56,7 @@ const getAsk = (config) => (uuid) => (asks) => {
37
56
  }
38
57
  }
39
58
  if (matchq(args)) {
40
- args.context.motivationKeep = true
59
+ // args.context.motivationKeep = true
41
60
  args.context.verbatim = applyq(args)
42
61
  args.context.isResponse = true;
43
62
  delete args.context.controlRemove;
@@ -49,6 +68,12 @@ const getAsk = (config) => (uuid) => (asks) => {
49
68
  })
50
69
  }
51
70
 
71
+ const sameJSON = (json1, json2) => {
72
+ const sjson1 = sortJson(json1, { depth: 25 })
73
+ const sjson2 = sortJson(json2, { depth: 25 })
74
+ return JSON.stringify(sjson1) == JSON.stringify(sjson2)
75
+ }
76
+
52
77
  const vimdiff = (actualJSON, expectedJSON) => {
53
78
  const path = '.'
54
79
  const actual = sortJson(actualJSON, { depth: 25 })
@@ -58,7 +83,6 @@ const vimdiff = (actualJSON, expectedJSON) => {
58
83
  // console.log(`vimdiff ${path}/actual.json ${path}/expected.json`)
59
84
  {
60
85
  const editor = runtime.process.env.EDITOR || 'vimdiff'
61
- debugger
62
86
  // const child = runtime.child_process.spawn(editor, [`${path}/expected.json`, `${path}/actual.json`], { stdio: 'inherit' })
63
87
  console.log(`${editor} ${path}/expected.json ${path}/actual.json`)
64
88
  runtime.child_process.execSync(`${editor} ${path}/expected.json ${path}/actual.json`, {stdio: 'inherit'})
@@ -109,11 +133,12 @@ class ErrorReason extends Error {
109
133
 
110
134
  const setupArgs = (args, config, logs, hierarchy) => {
111
135
  config.setArgs(args)
112
- args.calls = new InitCalls(config.name)
136
+ args.calls = new InitCalls(args.isInstance ? `${args.isInstance}#${config.name}` : config.name)
113
137
  if (global.theprogrammablemind && global.theprogrammablemind.loadForTesting) {
114
138
  args.calls = new InitCalls(Object.keys(global.theprogrammablemind.loadForTesting)[0])
115
139
  }
116
140
  args.km = (name) => config.getConfig(name)
141
+ args.api = (name) => config.getConfig(name).api
117
142
  args.error = (context) => {
118
143
  throw new ErrorReason(context)
119
144
  }
@@ -124,6 +149,7 @@ const setupArgs = (args, config, logs, hierarchy) => {
124
149
  args.listable = listable(hierarchy)
125
150
  args.asList = asList
126
151
  args.retry = () => { throw new RetryError() }
152
+ args.fragments = (query) => config.fragment(query)
127
153
  const scopedAsk = getAsk(config)
128
154
 
129
155
  const getAPI = (uuid) => {
@@ -143,7 +169,6 @@ const setupArgs = (args, config, logs, hierarchy) => {
143
169
  apis: getAPIs(uuid)
144
170
  }
145
171
  }
146
- args.motivation = (m) => config.addMotivation(m)
147
172
  args.breakOnSemantics = false
148
173
  args.theDebugger = {
149
174
  breakOnSemantics: (value) => args.breakOnSemantics = value
@@ -157,10 +182,10 @@ const setupArgs = (args, config, logs, hierarchy) => {
157
182
  }
158
183
  args.e = (c) => config.getEvaluator(args.s, args.calls, logs, c)
159
184
  args.log = (message) => logs.push(message)
160
- // config.getAddedArgs(args)
161
185
  args.gs = gs(args.g)
162
186
  args.gsp = gs(args.gp)
163
187
  args.gsr = gs(args.gr)
188
+ config.getAddedArgs(args)
164
189
  }
165
190
 
166
191
  const gs = (g) => (contexts, separator, lastSeparator) => {
@@ -298,7 +323,6 @@ const writeTest = (fn, query, objects, generated, paraphrases, responses, contex
298
323
  }
299
324
  associations.sort()
300
325
  // tests[query] = sortJson({ paraphrases, responses, contexts, objects: convertToStable(objects), associations, metadata, config, developerTest: saveDeveloper }, { depth: 25 })
301
- debugger
302
326
  results = sortJson({
303
327
  query,
304
328
  paraphrases,
@@ -367,7 +391,7 @@ const setupContexts = (rawContexts) => {
367
391
  return contexts
368
392
  }
369
393
 
370
- const processContextsB = ({ config, hierarchy, semantics, generators, json, isTest, query, data, retries, url, commandLineArgs }) => {
394
+ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTest, isInstance, instance, query, data, retries, url, commandLineArgs }) => {
371
395
  // TODO fix this name to contextsPrime
372
396
  const contextsPrime = []
373
397
  const generatedPrime = []
@@ -378,7 +402,7 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
378
402
  const contexts = setupContexts(json.contexts)
379
403
 
380
404
  const objects = config.get('objects')
381
- const args = { objects, isResponse: true, response: json, isTest, getObjects: getObjects(objects) }
405
+ const args = { objects, isResponse: true, response: json, isTest, isInstance, getObjects: getObjects(objects), instance }
382
406
  if (!json.logs) {
383
407
  json.logs = []
384
408
  }
@@ -389,28 +413,6 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
389
413
  config.debugLoops = commandLineArgs && commandLineArgs.debugLoops
390
414
  while (toDo.length > 0) {
391
415
  const context = toDo.shift()
392
- /*
393
- if (false && query) {
394
- if (config.wasChanged()) {
395
- // process contexts that overlap
396
- overlap = lastRange
397
- } else {
398
- config.watch()
399
- }
400
- if (overlap) {
401
- if (overlaps(overlap, context)) {
402
- // okay
403
- query = query.slice(overlap.end+1)
404
- data.utterance = query
405
- const json = await doWithRetries(retries, url, data)
406
- toDo = setupContexts(json.contexts).slice(1) // take off the start context
407
- }
408
- overlap = undefined
409
- }
410
- lastRange = context.range
411
- }
412
- */
413
-
414
416
  args.calls.next()
415
417
  let contextPrime = context
416
418
  context.topLevel = true
@@ -418,19 +420,27 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
418
420
  if (json.has_errors) {
419
421
  throw new Error('There are errors in the logs. Run with the -d flag and grep for Error')
420
422
  }
423
+ const generateParenthesized = isTest || (commandLineArgs && commandLineArgs.save)
421
424
  if (!config.get('skipSemantics')) {
422
- if (!config.doMotivations(args, context)) {
423
- const semantics = config.getSemantics(json.logs)
424
- try {
425
- contextPrime = semantics.apply(args, context)
426
- } catch( e ) {
427
- if (e.message == 'Maximum call stack size exceeded') {
428
- const mostCalled = semantics.getMostCalled()
429
- e.message += `\nThe most called semantic was:\nnotes: ${mostCalled.notes}\nmatch: ${mostCalled.matcher.toString()}\napply: ${mostCalled._apply.toString()}\n`
430
- }
431
- // contextPrime = semantics.apply(args, { marker: 'error', context, error: e })
432
- contextPrime = semantics.apply(args, { marker: 'error', context, reason: e.reason })
425
+ const semantics = config.getSemantics(json.logs)
426
+ try {
427
+ contextPrime = semantics.apply(args, context)
428
+ } catch( e ) {
429
+ if (e.message == 'Maximum call stack size exceeded') {
430
+ const mostCalled = semantics.getMostCalled()
431
+ e.message += `\nThe most called semantic was:\nnotes: ${mostCalled.notes}\nmatch: ${mostCalled.matcher.toString()}\napply: ${mostCalled._apply.toString()}\n`
432
+ }
433
+ // contextPrime = semantics.apply(args, { marker: 'error', context, error: e })
434
+ if (isInstance) {
435
+ console.log('error', e.error)
433
436
  }
437
+ contextPrime = semantics.apply(args, {
438
+ marker: 'error',
439
+ context,
440
+ text: e ? e.toString() : 'not available',
441
+ reason: e.reason,
442
+ error: e.stack || e.error
443
+ })
434
444
  }
435
445
  }
436
446
  if (contextPrime.controlRemove) {
@@ -439,7 +449,7 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
439
449
  let assumed = { isResponse: true };
440
450
  const generated = contextPrime.isResponse ? config.getGenerators(json.logs).apply(args, contextPrime, assumed)[0] : ''
441
451
  let generatedParenthesized = []
442
- if (isTest) {
452
+ if (generateParenthesized) {
443
453
  config.parenthesized = true
444
454
  generatedParenthesized = contextPrime.isResponse ? config.getGenerators(json.logs).apply(args, contextPrime, assumed)[0] : ''
445
455
  config.parenthesized = false
@@ -452,12 +462,12 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
452
462
  args.gs = gs(args.g)
453
463
  args.gsp = gs(args.gsp)
454
464
  args.gsr = gs(args.gr)
455
- if (isTest) {
465
+ if (generateParenthesized) {
456
466
  config.parenthesized = false
457
467
  }
458
468
  const paraphrases = config.getGenerators(json.logs).apply(args, contextPrime, assumed)[0]
459
469
  let paraphrasesParenthesized = []
460
- if (isTest) {
470
+ if (generateParenthesized) {
461
471
  config.parenthesized = true
462
472
  paraphrasesParenthesized = config.getGenerators(json.logs).apply(args, contextPrime, assumed)[0]
463
473
  config.parenthesized = false
@@ -471,7 +481,7 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
471
481
  contextsPrime.push(contextPrime)
472
482
  generatedPrime.push(generated)
473
483
  paraphrasesPrime.push(paraphrases)
474
- if (isTest) {
484
+ if (generateParenthesized) {
475
485
  paraphrasesParenthesizedPrime.push(paraphrasesParenthesized)
476
486
  generatedParenthesizedPrime.push(generatedParenthesized)
477
487
  }
@@ -549,8 +559,11 @@ const setupProcessB = ({ config, initializer, allowDelta=false } = {}) => {
549
559
  // console.log('config', config)
550
560
  data.delta = config.delta()
551
561
  } else {
552
- Object.assign(data, config.config)
562
+ config.toData(data)
563
+ // Object.assign(data, config.config)
553
564
  }
565
+
566
+ // config.toServer(data)
554
567
 
555
568
  if (data.namespaces) {
556
569
  for (const uuid of Object.keys(data.namespaces)) {
@@ -573,10 +586,22 @@ const setupProcessB = ({ config, initializer, allowDelta=false } = {}) => {
573
586
  }
574
587
  }
575
588
 
576
- // instance template
577
- const processInstance = (config, instance) => {
589
+ // instance template loadTemplate
590
+ const loadInstance = (config, instance) => {
578
591
  const transitoryMode = global.transitoryMode
579
592
  global.transitoryMode = false
593
+
594
+ if (instance && (instance.associations || instance.learned_contextual_priorities)) {
595
+ if (!config.config.retrain) {
596
+ if (instance.associations) {
597
+ config.addAssociations(instance.associations)
598
+ }
599
+ if (instance.learned_contextual_priorities && instance.learned_contextual_priorities.length > 0) {
600
+ config.addPriorities(instance.learned_contextual_priorities)
601
+ }
602
+ }
603
+ }
604
+
580
605
  const { /* data, generators, semantics, */ hierarchy } = setupProcessB({ config })
581
606
  // for (const results of (instance.resultss || [])) {
582
607
  for (const i in (instance.resultss || [])) {
@@ -584,15 +609,21 @@ const processInstance = (config, instance) => {
584
609
  if (results.extraConfig) {
585
610
  // config.addInternal(results, useOldVersion = true, skipObjects = false, includeNamespaces = true, allowNameToBeNull = false)
586
611
  // config.addInternal(config.template.queries[i], { handleCalculatedProps: true } )
587
- config.addInternal(instance.template.queries[i], { handleCalculatedProps: true } )
612
+ config.addInternal(instance.template.queries[i], { addFirst: true, handleCalculatedProps: true } )
588
613
  } else {
589
- processContextsB({ config, hierarchy, json: results/*, generators, semantics */, commandLineArgs: {} })
614
+ if (results.skipSemantics) {
615
+ config.config.skipSemantics = results.skipSemantics
616
+ }
617
+ processContextsB({ config, hierarchy, json: results/*, generators, semantics */, commandLineArgs: {}, isInstance: `instance${i}`, instance: instance.queries[i] })
618
+ if (results.skipSemantics) {
619
+ config.config.skipSemantics = null
620
+ }
590
621
  }
591
622
  }
592
623
  global.transitoryMode = transitoryMode
593
624
  }
594
625
 
595
- const _process = async (config, query, { initializer, commandLineArgs, credentials, writeTests, isTest, saveDeveloper, testConfig, testsFN, errorHandler = defaultErrorHandler } = {}) => {
626
+ const _process = async (config, query, { initializer, commandLineArgs, credentials, writeTests, isTest, saveDeveloper, rebuildingTemplate, testConfig, testsFN, errorHandler = defaultErrorHandler } = {}) => {
596
627
  if (credentials) {
597
628
  config.server(credentials.server, credentials.key)
598
629
  }
@@ -606,7 +637,6 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
606
637
  if (writeTests) {
607
638
  config.rebuild()
608
639
  const objects = getObjects(config.config.objects)(config.uuid)
609
- config.beforeQuery({ query, isModule: false, objects })
610
640
  }
611
641
  } catch(error) {
612
642
  throw error
@@ -614,7 +644,10 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
614
644
 
615
645
  let { data, /* generators, semantics, */ hierarchy } = setupProcessB({ config, initializer, allowDelta: true })
616
646
  if (commandLineArgs && commandLineArgs.checkForLoop) {
617
- data.checkForLoop = true
647
+ data.checkForLoop = commandLineArgs.checkForLoop
648
+ }
649
+ if (rebuildingTemplate) {
650
+ data.errors_ignore_contextual_priorities_non_existant_ops = true
618
651
  }
619
652
  let queries = query.split('\\n')
620
653
 
@@ -671,6 +704,7 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
671
704
  const { contextsPrime, generatedPrime, paraphrasesPrime, paraphrasesParenthesizedPrime, generatedParenthesizedPrime, responsesPrime } =
672
705
  processContextsB({ isTest, config, hierarchy, json, commandLineArgs /*, generators, semantics */ })
673
706
  response.associations = json.associations
707
+ response.learned_contextual_priorities = json.learned_contextual_priorities
674
708
  response.hierarchy = json.hierarchy
675
709
  response.load_cache_time += json.load_cache_time
676
710
  appendNoDups(response.logs, json.logs)
@@ -681,6 +715,7 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
681
715
  response.times += json.times
682
716
  response.trace = response.trace.concat(json.trace)
683
717
  response.version = json.version
718
+ response.explain_priorities = json.explain_priorities
684
719
 
685
720
  response.contexts = response.contexts.concat(contextsPrime)
686
721
  response.generated = response.generated.concat(generatedPrime)
@@ -694,7 +729,12 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
694
729
 
695
730
  if (writeTests) {
696
731
  const actual_config = getConfigForTest(config, testConfig)
697
- writeTest(testsFN, query, config.config.objects, response.generated, response.paraphrases, response.responses, response.contexts, response.associations, response.metadata, actual_config, saveDeveloper, response.paraphrasesParenthesized, response.generatedParenthesized)
732
+ const saveObjects = {...config.config.objects}
733
+ saveObjects.nameToUUID = {}
734
+ for (let km of config.configs) {
735
+ saveObjects.nameToUUID[km.name] = km.uuid
736
+ }
737
+ writeTest(testsFN, query, saveObjects, response.generated, response.paraphrases, response.responses, response.contexts, response.associations, response.metadata, actual_config, saveDeveloper, response.paraphrasesParenthesized, response.generatedParenthesized)
698
738
  }
699
739
 
700
740
  return response
@@ -734,7 +774,7 @@ const getConfigForTest = (config, testConfig) => {
734
774
  return configForTest
735
775
  }
736
776
 
737
- const runTest = async (config, expected, { args, verbose, afterTest, testConfig, debug }) => {
777
+ const runTest = async (config, expected, { args, verbose, testConfig, debug }) => {
738
778
  const test = expected.query
739
779
  // initialize in between test so state is not preserved since the test was adding without state
740
780
  config.rebuild()
@@ -759,8 +799,6 @@ const runTest = async (config, expected, { args, verbose, afterTest, testConfig,
759
799
  objects = getObjects(config.config.objects)(config.getConfigs()[testConfig.testModuleName].uuid)
760
800
  testConfigName = testConfig.testModuleName
761
801
  }
762
- config.beforeQuery({ query: test, isModule: false, objects })
763
- // config.resetMotivations()
764
802
  try {
765
803
  const result = await _process(config, test, { errorHandler, isTest: true })
766
804
  result.query = test
@@ -778,38 +816,29 @@ const runTest = async (config, expected, { args, verbose, afterTest, testConfig,
778
816
  delete expected_objects.nameToUUID
779
817
  const actual_objects = sortJson(convertToStable(config.config.objects), { depth: 25 })
780
818
  const failed_paraphrases = !matching(result.paraphrases, expected.paraphrases)
781
- const failed_paraphrasesParenthesized = !matching(result.paraphrasesParenthesized, expected.paraphrasesParenthesized)
782
- const failed_generatedParenthesized = !matching(result.generatedParenthesized, expected.generatedParenthesized)
819
+ let failed_paraphrasesParenthesized = !matching(result.paraphrasesParenthesized, expected.paraphrasesParenthesized)
820
+ let failed_generatedParenthesized = !matching(result.generatedParenthesized, expected.generatedParenthesized)
821
+ // TODO fix the naming conventions: camelcase + use actual instead of result
783
822
  const failed_responses = !matching(result.responses, expected.responses)
784
823
  const failed_contexts = !matching(result.contexts, expected.contexts)
785
824
  const failed_objects = !matching(actual_objects, expected_objects)
786
825
 
787
- const pickEm = (getObjects) => {
788
- const picked = {}
789
- for (let prop of (testConfig.check || [])) {
790
- if (prop.km) {
791
- c = config.getConfig(prop.km)
792
- o = getObjects(prop.km)
793
- picked[prop.km] = {}
794
- for (let p of c.testConfig.check) {
795
- if (p.km) {
796
- continue
797
- }
798
- picked[p] = o[p]
799
- }
800
- } else {
801
- picked[prop] = getObjects(testConfigName)[prop]
802
- }
803
- }
804
- return picked
826
+ if (args.testNoParenthesized) {
827
+ failed_paraphrasesParenthesized = false
828
+ failed_generatedParenthesized = false
805
829
  }
830
+
831
+ const pickedResultContexts = result.contexts.map(pickContext(testConfig))
832
+ const pickedExpectedContexts = expected.contexts.map(pickContext(testConfig))
833
+ const failedCheckedContexts = !matching(pickedResultContexts, pickedExpectedContexts)
834
+
806
835
  const expectedGetObjects = (name) => {
807
836
  if (!name) {
808
837
  name = config.name
809
838
  }
810
839
  return expected.objects.namespaced[expected.objects.nameToUUID[name]]
811
840
  }
812
- const expected_checked = sortJson(pickEm(expectedGetObjects), { depth: 25 })
841
+ const expected_checked = sortJson(pickObjects(testConfig, objects), { depth: 25 })
813
842
  const actualGetObjects = (name) => {
814
843
  if (!name) {
815
844
  name = config.name
@@ -817,45 +846,14 @@ const runTest = async (config, expected, { args, verbose, afterTest, testConfig,
817
846
  const km = config.configs.find( (km) => km.name == name )
818
847
  return config.config.objects.namespaced[km.uuid]
819
848
  }
820
- const actual_checked = sortJson(pickEm(actualGetObjects), { depth: 25 })
849
+ const actual_checked = sortJson(pickObjects(testConfig, actualGetObjects(testConfigName)), { depth: 25 })
821
850
  const failed_checked = !matching(actual_objects, expected_objects)
822
851
 
823
852
  const failed_checks = !matching(actual_objects, expected_objects)
824
853
  const actual_config = sortJson(convertToStable(getConfigForTest(config, testConfig)), { depth: 25 })
825
854
  const expected_config = sortJson(convertToStable(expected.config), { depth: 25 })
826
855
  const failed_config = !matching(actual_config, expected_config)
827
- let failed = failed_paraphrases || failed_paraphrasesParenthesized || failed_generatedParenthesized || failed_responses || failed_contexts || failed_objects || failed_config || failed_checked
828
- if (!failed) {
829
- if (config.afterTest) {
830
- failed = config.afterTest({ query: test, expected, actual: result, config })
831
- if (failed) {
832
- return {
833
- utterance: test,
834
- errorFromAfterTest: failed,
835
- expected: {
836
- responses: expected.responses,
837
- paraphrases: expected.paraphrases,
838
- paraphrasesParenthesized: expected.paraphrasesParenthesized,
839
- generatedParenthesized: expected.generatedParenthesized,
840
- results: expected.contexts,
841
- checked: expected_checked,
842
- objects: expected_objects,
843
- config: expected.config
844
- },
845
- actual: {
846
- responses: result.responses,
847
- paraphrases: result.paraphrases,
848
- paraphrasesParenthesized: result.paraphrasesParenthesized,
849
- generatedParenthesized: result.generatedParenthesized,
850
- results: result.contexts,
851
- checked: actual_checked,
852
- objects: actual_objects,
853
- config: actual_config
854
- }
855
- }
856
- }
857
- }
858
- }
856
+ let failed = failed_paraphrases || failed_paraphrasesParenthesized || failed_generatedParenthesized || failed_responses || failed_contexts || failed_objects || failed_config || failed_checked || failedCheckedContexts
859
857
 
860
858
  if (expected.metadata && result.metadata && failed) {
861
859
  const priorities = analyzeMetaData(expected.metadata, result.metadata)
@@ -874,6 +872,7 @@ const runTest = async (config, expected, { args, verbose, afterTest, testConfig,
874
872
  generatedParenthesized: expected.generatedParenthesized,
875
873
  results: expected.contexts,
876
874
  checked: expected_checked,
875
+ checkedContexts: pickedExpectedContexts,
877
876
  objects: expected_objects,
878
877
  config: expected.config
879
878
  },
@@ -884,6 +883,7 @@ const runTest = async (config, expected, { args, verbose, afterTest, testConfig,
884
883
  generatedParenthesized: result.generatedParenthesized,
885
884
  results: result.contexts,
886
885
  checked: actual_checked,
886
+ checkedContexts: pickedResultContexts,
887
887
  objects: actual_objects,
888
888
  config: actual_config
889
889
  }
@@ -923,20 +923,16 @@ const runTestsHelper = async (config, tests, failed, juicyBits) => {
923
923
 
924
924
  const runTests = async (config, testFile, juicyBits) => {
925
925
  const tests = JSON.parse(runtime.fs.readFileSync(testFile))
926
- config.beforeTests()
927
926
  if (juicyBits.verbose) {
928
927
  console.log('\n', testFile, '-----------------------------------------------', '\n')
929
928
  }
930
929
  const v = await runTestsHelper(config, [...tests], [], juicyBits)
931
- config.afterTests()
932
930
  return v
933
931
  }
934
932
 
935
933
  const saveTest = async (testFile, config, test, expected, testConfig, saveDeveloper) => {
936
934
  config.rebuild()
937
935
  const objects = getObjects(config.config.objects)(config.uuid)
938
- //config.resetMotivations()
939
- config.beforeQuery({ query: test, isModule: false, objects })
940
936
  console.log(test)
941
937
  const result = await _process(config, test, { isTest: true })
942
938
  // const actualObjects = config.config.objects
@@ -1118,10 +1114,11 @@ const defaultErrorHandler = async (error) => {
1118
1114
  doErrorExit = true
1119
1115
  }
1120
1116
 
1121
- if (doErrorExit) {
1117
+ if (typeof runtime.process.exit == 'function' && doErrorExit) {
1122
1118
  runtime.process.exit(-1)
1123
1119
  }
1124
- // throw error
1120
+
1121
+ throw error
1125
1122
  }
1126
1123
 
1127
1124
  const defaultInnerProcess = (config, errorHandler, responses) => {
@@ -1131,6 +1128,13 @@ const defaultInnerProcess = (config, errorHandler, responses) => {
1131
1128
  }
1132
1129
  console.log("KM's loaded", config.configs.map((c) => c.name))
1133
1130
  console.log('This is the global objects from running semantics:\n', config.objects)
1131
+ if (!_.isEmpty(responses.learned_contextual_priorities)) {
1132
+ console.log('\nThe learned contextual priorties are :\n')
1133
+ for (const lcp of responses.learned_contextual_priorities) {
1134
+ console.log(` ${JSON.stringify(lcp)},\n`)
1135
+ }
1136
+ console.log("\n")
1137
+ }
1134
1138
  if (responses.logs) {
1135
1139
  console.log('Logs')
1136
1140
  responses.logs.forEach((log) => console.log(` ${log}`))
@@ -1142,6 +1146,50 @@ const defaultInnerProcess = (config, errorHandler, responses) => {
1142
1146
  } else {
1143
1147
  console.log('objects', runtime.util.inspect(config.get('objects'), { depth: Infinity, sorted: true }))
1144
1148
  }
1149
+
1150
+ const pickEm = () => {
1151
+ const picked = {}
1152
+ const namespaced = config.get('objects')['namespaced']
1153
+ for (let prop of getConfig_getObjectCheck(config.testConfig)) {
1154
+ if (prop.km) {
1155
+ /*
1156
+ const objects = namespaced[prop.km]]
1157
+ picked[prop.km] = {}
1158
+ for (let p of c.testConfig.check) {
1159
+ if (p.km) {
1160
+ continue
1161
+ }
1162
+ picked[p] = objects[p]
1163
+ }
1164
+ */
1165
+ console.log('TODO implement this if needed')
1166
+ } else {
1167
+ const objects = namespaced[config.uuid]
1168
+ picked[prop] = objects[prop]
1169
+ }
1170
+ }
1171
+ return picked
1172
+ }
1173
+
1174
+ if (responses.explain_priorities) {
1175
+ console.log("Explain Priorities")
1176
+ for ([inputss, outpus, reason] of responses.explain_priorities) {
1177
+ console.log(` ${JSON.stringify(inputss)} reason: ${reason}`)
1178
+ }
1179
+ }
1180
+ const objects = config.get('objects').namespaced[config.uuid]
1181
+ const picked = sortJson(pickObjects(config.testConfig, objects), { depth: 25 })
1182
+ if (!_.isEmpty(picked)) {
1183
+ console.log('--- Object showing only the checked values ---')
1184
+ console.log(JSON.stringify(picked, null, 2))
1185
+ }
1186
+
1187
+ const pickedResultContexts = responses.contexts.map(pickContext(config.testConfig))
1188
+ if (pickedResultContexts.some( (context) => Object.keys(context).length > 0 )) {
1189
+ console.log('--- Contexts showing only the checked values ---')
1190
+ console.log(JSON.stringify(pickedResultContexts, null, 2))
1191
+ }
1192
+
1145
1193
  console.log('--- The contexts are ----------')
1146
1194
  console.log(JSON.stringify(sortJson(responses.contexts, { depth: 25 }), null, 2))
1147
1195
  console.log('')
@@ -1182,37 +1230,14 @@ const defaultProcess = ({ config, errorHandler }) => async (promise) => {
1182
1230
  }
1183
1231
  }
1184
1232
 
1185
- /*
1186
- const kmFileTemplate = (kmBaseName, kmName) =>
1187
- `const entodicton = require('entodicton')
1188
- const base = require('./${kmBaseName}').copy()
1189
- const ${kmName}_tests = require('./${kmName}.test.json')
1190
- const ${kmName}_instance = require('./${kmBaseName}.${kmName}.instance.json')
1191
-
1192
- const config = new entodicton.Config({ name: '${kmName}' })
1193
- config.add(base)
1194
- kirk_instance.base = '${kmBaseName}'
1195
- config.load(${kmName}_instance)
1196
-
1197
- entodicton.knowledgeModule( {
1198
- module,
1199
- description: '${kmName} related concepts',
1200
- section,
1201
- config,
1202
- test: {
1203
- name: './${kmName}.test.json',
1204
- contents: ${kmName}_tests
1205
- },
1206
- })
1207
- `
1208
- */
1209
-
1210
- const build = async ({ config, target, template, errorHandler = defaultErrorHandler }) => {
1233
+ // builtTemplate saveInstance
1234
+ const rebuildTemplate = async ({ config, target, template, errorHandler = defaultErrorHandler }) => {
1211
1235
  const accumulators = {
1212
1236
  resultss: [],
1213
1237
  fragments: [],
1214
1238
  semantics: [],
1215
1239
  associations: [],
1240
+ learned_contextual_priorities: [],
1216
1241
  }
1217
1242
  const looper = async (queries) => {
1218
1243
  if (queries.length === 0) {
@@ -1231,8 +1256,6 @@ const build = async ({ config, target, template, errorHandler = defaultErrorHand
1231
1256
  if (property == 'fragments') {
1232
1257
  global.transitoryMode = true
1233
1258
  }
1234
- // greg32
1235
- // config.addInternal( query )
1236
1259
  if (hierarchy) {
1237
1260
  for (let edge of hierarchy) {
1238
1261
  if (Array.isArray(edge)) {
@@ -1242,9 +1265,8 @@ const build = async ({ config, target, template, errorHandler = defaultErrorHand
1242
1265
  }
1243
1266
  }
1244
1267
  }
1245
-
1246
1268
  try {
1247
- const results = await _process(config, query.query, {initializer})
1269
+ const results = await _process(config, query.query, {initializer, rebuildingTemplate: true})
1248
1270
  if (config.config.debug) {
1249
1271
  // TODO pass in the error handler like the other ones
1250
1272
  defaultInnerProcess(config, defaultErrorHandler, results)
@@ -1259,10 +1281,12 @@ const build = async ({ config, target, template, errorHandler = defaultErrorHand
1259
1281
  global.transitoryMode = transitoryMode
1260
1282
  config.config.skipSemantics = null
1261
1283
  results.query = query.query
1284
+ results.skipSemantics = skipSemantics
1262
1285
  results.development = query.development
1263
1286
  results.key = { query: query.query, hierarchy }
1264
1287
  accumulators[property].push(results)
1265
1288
  accumulators.associations = accumulators.associations.concat(results.associations)
1289
+ accumulators.learned_contextual_priorities = accumulators.learned_contextual_priorities.concat(results.learned_contextual_priorities)
1266
1290
  await looper(queries)
1267
1291
  } catch(e) {
1268
1292
  const error = { errors: [e], query: query.query };
@@ -1274,6 +1298,12 @@ const build = async ({ config, target, template, errorHandler = defaultErrorHand
1274
1298
  // it will just get added to the config
1275
1299
  const extraConfig = queryOrExtraConfig
1276
1300
  console.log('config', extraConfig)
1301
+ try {
1302
+ config.addInternal(_.cloneDeep(extraConfig), { handleCalculatedProps: true } )
1303
+ } catch ( e ) {
1304
+ const where = extraConfig.where ? ` ${extraConfig.where}` : ''
1305
+ throw new Error(`Error processing extra config${where}: ${e.stack}}`)
1306
+ }
1277
1307
  accumulators[property].push({ extraConfig: true, ...extraConfig })
1278
1308
  await looper(queries)
1279
1309
  }
@@ -1301,6 +1331,7 @@ const build = async ({ config, target, template, errorHandler = defaultErrorHand
1301
1331
  delete result.version
1302
1332
  result.hierarchy.sort()
1303
1333
  stabilizeAssociations(result.associations)
1334
+ result.learned_contextual_priorities = safeNoDups(result.learned_contextual_priorities)
1304
1335
  }
1305
1336
  }
1306
1337
  }
@@ -1321,14 +1352,14 @@ const build = async ({ config, target, template, errorHandler = defaultErrorHand
1321
1352
 
1322
1353
  const toProperties = (queryStringOrProperties) => {
1323
1354
  if (typeof queryStringOrProperties == 'string') {
1324
- return { query: queryStringOrProperties}
1355
+ return { query: queryStringOrProperties }
1325
1356
  } else {
1326
1357
  return queryStringOrProperties
1327
1358
  }
1328
1359
  }
1329
1360
  let todo = []
1330
- todo = todo.concat((template.initializers || []).map((query) => { return { initializer: true, property: 'resultss', query, skipSemantics: false } }))
1331
- todo = todo.concat((template.queries || []).map((query) => { return { property: 'resultss', query, skipSemantics: false } }))
1361
+ todo = todo.concat((template.initializers || []).map((query) => { return { initializer: true, property: 'resultss', query, skipSemantics: false || query.skipSemantics } }))
1362
+ todo = todo.concat((template.queries || []).map((query) => { return { property: 'resultss', query, skipSemantics: false || query.skipSemantics} }))
1332
1363
  todo = todo.concat((template.fragments || []).map((query) => { return Object.assign({}, toProperties(query), { property: 'fragments', skipSemantics: false }) }))
1333
1364
  todo = todo.concat((template.semantics || []).map((definition) => { return { property: 'semantics', query: `${definition.from}\n${definition.to}`, skipSemantics: true } }))
1334
1365
  await looper(Object.assign([], todo))
@@ -1338,36 +1369,31 @@ const knowledgeModule = async ({
1338
1369
  module: moduleFromJSFile,
1339
1370
  description,
1340
1371
  section,
1341
- config,
1372
+ // config, createConfig,
1373
+ createConfig,
1374
+ newWay,
1342
1375
  demo,
1343
1376
  test,
1344
1377
  template,
1345
1378
  errorHandler = defaultErrorHandler,
1346
1379
  process: processResults = defaultProcess,
1347
1380
  stopAtFirstFailure = true,
1348
- beforeQuery = () => {},
1349
- beforeTests = () => {},
1350
- afterTests = () => {},
1351
- beforeTest = () => {},
1352
- afterTest = () => {}
1381
+ ...rest
1353
1382
  } = {}) => {
1354
1383
 
1355
- config.beforeQuery = beforeQuery
1356
- config.beforeTests = beforeTests
1357
- config.afterTests = afterTests
1358
- config.beforeTest = beforeTest
1359
- config.afterTest = afterTest
1384
+ const unknownArgs = Object.keys(rest)
1385
+ if (unknownArgs.length > 0) {
1386
+ throw new Error(`Unknown arguments to knowledgeModule: ${unknownArgs.join()}`)
1387
+ }
1360
1388
 
1361
1389
  const testConfig = test
1362
1390
 
1363
1391
  if (!moduleFromJSFile) {
1364
1392
  throw new Error("'module' is a required parameter. The value should be either 'module' or a lambda that will be called when the file is acting as a module.")
1365
1393
  }
1366
- if (!config) {
1367
- throw new Error("'config' is a required parameter. The value should the config that defines the knowledge module.")
1368
- }
1369
- if (!config.name) {
1370
- throw new Error("config must have 'name' set to the knowledge module name.")
1394
+ // if (!config && !createConfig) {
1395
+ if (!createConfig) {
1396
+ throw new Error("'config' or 'createConfig' is a required parameter. The value should the config that defines the knowledge module.")
1371
1397
  }
1372
1398
  if (!description) {
1373
1399
  throw new Error("'description' is a required parameter. The value should the description of the knowledge module.")
@@ -1377,86 +1403,52 @@ const knowledgeModule = async ({
1377
1403
  }
1378
1404
 
1379
1405
  const isProcess = require.main === moduleFromJSFile
1380
- let loadForTesting = false
1381
- if (global.theprogrammablemind) {
1382
- if (global.theprogrammablemind.loadForTesting[config.name]) {
1383
- loadForTesting = true
1406
+
1407
+ const setupConfig = (config) => {
1408
+ if (!config.name) {
1409
+ throw new Error("config must have 'name' set to the knowledge module name.")
1384
1410
  }
1385
- }
1386
1411
 
1387
- // remove test only stuff
1388
- if (!isProcess && !loadForTesting) {
1389
- config.config.operators = config.config.operators.filter( (operator) => {
1390
- if (operator.development) {
1391
- return false
1392
- } else {
1393
- return true
1394
- }
1395
- })
1396
- config.config.bridges = config.config.bridges.filter( (bridge) => {
1397
- if (bridge.development) {
1398
- return false
1399
- } else {
1400
- return true
1412
+ config.description = description
1413
+ if (typeof test === 'object') {
1414
+ if (test.contents) {
1415
+ config.tests = test.contents
1416
+ test = test.name
1401
1417
  }
1402
- })
1403
- }
1404
-
1405
- let module
1406
- if (_.isFunction(moduleFromJSFile)) {
1407
- module = moduleFromJSFile
1408
- } else {
1409
- module = () => {
1410
- config.rebuild({ isModule: true })
1411
- moduleFromJSFile.exports = config
1412
- }
1413
- }
1414
- processResults = processResults({ config, errorHandler })
1415
- config.description = description
1416
- config.demo = demo
1417
- if (typeof test === 'object') {
1418
- if (test.contents) {
1419
- config.tests = test.contents
1420
- test = test.name
1421
- }
1422
- } else {
1423
- if (runtime.fs && runtime.fs.existsSync(test)) {
1424
- config.tests = JSON.parse(runtime.fs.readFileSync(test))
1425
1418
  } else {
1426
- config.tests = {}
1427
- }
1428
- }
1429
- config.setTestConfig(testConfig)
1430
-
1431
- if (!isProcess) {
1432
- if (template) {
1433
- if (config.needsRebuild(template.template, template.instance)) {
1434
- throw new Error(`This module "${config.name}" cannot be used because the instance file needs rebuilding. Run on the command line with no arguements or the -rt argument to rebuild.`)
1435
- }
1436
- try {
1437
- config.load(template.template, template.instance)
1438
- } catch( e ) {
1439
- errorHandler(e)
1419
+ if (runtime.fs && runtime.fs.existsSync(test)) {
1420
+ config.tests = JSON.parse(runtime.fs.readFileSync(test))
1421
+ } else {
1422
+ config.tests = []
1440
1423
  }
1441
1424
  }
1425
+ config.setTestConfig(testConfig)
1442
1426
  }
1427
+
1428
+
1443
1429
  if (isProcess) {
1430
+ const config = createConfig()
1431
+ setupConfig(config)
1432
+ processResults = processResults({ config, errorHandler })
1444
1433
  // setup();
1445
1434
  const parser = new runtime.ArgumentParser({
1446
1435
  description: 'Entodicton knowledge module'
1447
1436
  })
1448
1437
 
1449
- const helpDebugAssociation = 'In order to get a debug break when a specific association is created set the DEBUG_ASSOCIATION environment variable to the JSON of the association to break on. For example DEBUG_ASSOCIATION=\'["the#0", "mammel#0"]\' })'
1450
- const helpDebugHierarchy = 'In order to get a debug break when a specific hierarchy is created set the DEBUG_HIERARCHY environment variable to the JSON of the child-parent pair to break on. For example DEBUG_HIERARCHY=\'["cat#1", "mammel#1"]\' })'
1451
- const helpDebugPriority = 'In order to get a debug break when a specific set of priorities is created set set DEBUG_PRIORITY environment variable to the JSON of the priorities that you want to break on. For example DEBUG_PRIORITY=\'["verb#0", "article#0"]\' })'
1452
- const helpDebugBridge = 'In order to get a debug break when a specific bridge is created set the DEBUG_BRIDGE environment variable to id/level to break on. For example DEBUG_BRIDGE=\'id#level\' })'
1453
- const helpDebugOperator = 'In order to get a debug break when a specific hierarcy is created set the DEBUG_OPERATOR environment variable to debug any config loaded. For example DEBUG_OPERATOR=\'([operator] ([arg]))\' })'
1438
+ const helpDebugAssociation = 'In order to get a debug break when a specific association is created set the DEBUG_ASSOCIATION environment variable to the JSON of the association to break on. For example DEBUG_ASSOCIATION=\'[["the", 0], ["mammal", 1]]\''
1439
+ const helpDebugHierarchy = 'In order to get a debug break when a specific hierarchy is created set the DEBUG_HIERARCHY environment variable to the JSON of the child-parent pair to break on. For example DEBUG_HIERARCHY=\'[["cat", 1], ["mammel", 1]]\''
1440
+ const helpDebugPriority = 'In order to get a debug break when a specific set of priorities is created set set DEBUG_PRIORITY environment variable to the JSON of the priorities that you want to break on. For example DEBUG_PRIORITY=\'[["verb", 0], ["article", 0]]\''
1441
+ const helpDebugContextualPriority = 'In order to get a debug break when a specific set of contextual priorities is created set set DEBUG_CONTEXTUAL_PRIORITY environment variable to the JSON of the priorities that you want to break on. For example DEBUG_CONTEXTUAL_PRIORITY=\'{ context: [["verb", 0], ["article", 0], select: 1}\''
1442
+ const helpDebugBridge = 'In order to get a debug break when a specific bridge is created set the DEBUG_BRIDGE environment variable to id/level to break on. For example DEBUG_BRIDGE=\'id#level\''
1443
+ const helpDebugOperator = 'In order to get a debug break when a specific hierarcy is created set the DEBUG_OPERATOR environment variable to debug any config loaded. For example DEBUG_OPERATOR=\'([operator] ([arg]))\''
1454
1444
 
1455
1445
 
1456
1446
  parser.add_argument('-tmn', '--testModuleName', { help: 'When running tests instead of using the current modules tests use the specified modules tests' })
1457
1447
  parser.add_argument('-t', '--test', { action: 'store_true', help: 'Run the tests. Create tests by running with the --query + --save flag' })
1458
1448
  parser.add_argument('-tv', '--testVerbose', { action: 'store_true', help: 'Run the tests in verbose mode. Create tests by running with the --query or --loop with the --save flag' })
1449
+ // parser.add_argument('-ttr', '--testToRun', { help: 'Only the specified test will be run' })
1459
1450
  parser.add_argument('-tva', '--testAllVerbose', { action: 'store_true', help: 'Run the tests in verbose mode. All the tests will be run instead of stopping at first failure. Create tests by running with the --query or --loop with the --save flag' })
1451
+ parser.add_argument('-tnp', '--testNoParenthesized', { action: 'store_true', help: 'Don\' check parenthesized differences for the tests' })
1460
1452
  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' })
1461
1453
  // 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.' })
1462
1454
  parser.add_argument('-rt', '--rebuildTemplate', { action: 'store_true', help: 'Force a template rebuild' })
@@ -1464,7 +1456,7 @@ const knowledgeModule = async ({
1464
1456
  parser.add_argument('-i', '--info', { action: 'store_true', help: 'Print meta-data for the module' })
1465
1457
  parser.add_argument('-v', '--vimdiff', { action: 'store_true', help: 'For failures run vimdiff' })
1466
1458
  parser.add_argument('-g', '--greg', { action: 'store_true', help: 'Set the server to be localhost so I can debug stuff' })
1467
- parser.add_argument('-cl', '--checkForLoop', { action: 'store_true', help: 'Check for loops in the priorities' })
1459
+ 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]]' })
1468
1460
  parser.add_argument('-r', '--retrain', { action: 'store_true', help: 'Get the server to retrain the neural nets' })
1469
1461
  parser.add_argument('-q', '--query', { help: 'Run the specified query' })
1470
1462
  parser.add_argument('-ip ', '--server', { help: 'Server to run against' })
@@ -1477,14 +1469,16 @@ const knowledgeModule = async ({
1477
1469
  parser.add_argument('-p', '--print', { help: 'Print the specified elements c === config, w === words, b === bridges, o === operators d === objects (d for data), h === hierarchy, g === generators, s === semantics, l === load t=tests ordering p === priorities a == associations j == JSON sent to server. for example --print wb' })
1478
1470
  parser.add_argument('-s', '--save', { action: 'store_true', help: 'When running with the --query flag this will save the current run to the test file. When running without the --query flag all tests will be run and resaved.' })
1479
1471
  parser.add_argument('-sd', '--saveDeveloper', { action: 'store_true', help: 'Same as -s but the query will not show up in the info command.' })
1480
- parser.add_argument('-dic', '--debugIncludeConvolutions', { action: 'store_true', help: 'When running with the --debugIncludeConvolutions flag the logs will include convolutions which are somewhat annoying verbose. Default is false' })
1481
1472
  parser.add_argument('-dl', '--debugLoops', { action: 'store_true', help: 'When running with the --debugLoops flag the logs calls to semantics and generators will be immediately written to the console '})
1482
1473
  parser.add_argument('-d', '--debug', { action: 'store_true', help: 'When running with the --debug flag this set the debug flag in the config' })
1483
- parser.add_argument('-da', '--debugAssociation', { help: helpDebugAssociation })
1484
- parser.add_argument('-dh', '--debugHierarchy', { help: helpDebugHierarchy })
1485
- parser.add_argument('-dp', '--debugPriority', { help: helpDebugPriority })
1486
- parser.add_argument('-db', '--debugBridge', { help: helpDebugBridge })
1487
- parser.add_argument('-do', '--debugOperator', { help: helpDebugOperator })
1474
+ parser.add_argument('-da', '--debugAssociation', { action: 'store_true', help: helpDebugAssociation })
1475
+ parser.add_argument('-dh', '--debugHierarchy', { action: 'store_true', help: helpDebugHierarchy })
1476
+ parser.add_argument('-dp', '--debugPriority', { action: 'store_true', help: helpDebugPriority })
1477
+ parser.add_argument('-dcp', '--debugContextualPriority', { action: 'store_true', help: helpDebugContextualPriority })
1478
+ parser.add_argument('-db', '--debugBridge', { action: 'store_true', help: helpDebugBridge })
1479
+ parser.add_argument('-do', '--debugOperator', { action: 'store_true', help: helpDebugOperator })
1480
+ parser.add_argument('-ep', '--explainPriorities', { action: 'store_true', help: "The server will return all priorities including the generated one along with an explanation of there they came from"})
1481
+ parser.add_argument('-dic', '--debugIncludeConvolutions', { nargs: "?", help: 'When running with the --debugIncludeConvolutions flag the logs will include convolutions which are somewhat annoyingly verbose. Default is false' })
1488
1482
 
1489
1483
  const args = parser.parse_args()
1490
1484
  args.count = args.count || 1
@@ -1492,7 +1486,35 @@ const knowledgeModule = async ({
1492
1486
  if (args.parenthesized) {
1493
1487
  config.parenthesized = true
1494
1488
  }
1495
-
1489
+ if (args.checkForLoop) {
1490
+ try {
1491
+ args.checkForLoop = JSON.parse(args.checkForLoop)
1492
+ const isKey = (what) => {
1493
+ if (!Array.isArray(what)) {
1494
+ return false
1495
+ }
1496
+ if (what.length !== 2) {
1497
+ return false
1498
+ }
1499
+ if (!typeof what[0] == 'string') {
1500
+ return false
1501
+ }
1502
+ if (!typeof what[1] == 'number') {
1503
+ return false
1504
+ }
1505
+ return true
1506
+ }
1507
+ if (!Array.isArray(args.checkForLoop) || args.checkForLoop.some((value) => !isKey(value))) {
1508
+ throw new Error(`Error for the checkForLoop argument. Expected a JSON array of operator keys of the form "[<id>, <level>]"`)
1509
+ }
1510
+ } catch( e ) {
1511
+ throw new Error(`Error parsing JSON of the checkForLoop argument. ${e}`)
1512
+ }
1513
+ } else {
1514
+ if (process.argv.includes('--checkForLoop') || process.argv.includes('-cl')) {
1515
+ args.checkForLoop = true
1516
+ }
1517
+ }
1496
1518
  if (args.debugAssociation) {
1497
1519
  console.log(helpDebugAssociation)
1498
1520
  runtime.process.exit(-1)
@@ -1550,35 +1572,12 @@ const knowledgeModule = async ({
1550
1572
  if (args.debug) {
1551
1573
  config.config.debug = true
1552
1574
  }
1553
- config.config.debugIncludeConvolutions = args.debugIncludeConvolutions
1554
-
1555
- if (template) {
1556
- const needsRebuild = config.needsRebuild(template.template, template.instance, options)
1557
- if (needsRebuild) {
1558
- console.log(`This module "${config.name}" needs rebuilding all other arguments will be ignored. Try again after the template is rebuilt.`)
1559
-
1560
- }
1561
- config.load(template.template, template.instance, { rebuild: needsRebuild })
1562
- if (needsRebuild) {
1563
- return
1564
- }
1565
- }
1566
1575
 
1567
- if (!args.save && !args.rebuildTemplate && !args.dontAddAssociations) {
1568
- config.addAssociationsFromTests(config.tests);
1569
- //for (let query in config.tests) {
1570
- // config.addAssociations(config.tests[query].associations || []);
1571
- //}
1576
+ if (args.explainPriorities) {
1577
+ config.config.explain_priorities = true
1572
1578
  }
1573
1579
 
1574
- /*
1575
- if (args.buildTemplate) {
1576
- if (template) {
1577
- config.rebuild()
1578
- config.load(template.template, template.instance, { rebuild: true })
1579
- }
1580
- }
1581
- */
1580
+ config.config.debugIncludeConvolutions = args.debugIncludeConvolutions || process.argv.includes('--debugIncludeConvolutions') || process.argv.includes('-dic')
1582
1581
 
1583
1582
  let configPrinted = false
1584
1583
  const printConfig = () => {
@@ -1671,6 +1670,24 @@ const knowledgeModule = async ({
1671
1670
  }
1672
1671
  }
1673
1672
 
1673
+ if (template) {
1674
+ const needsRebuild = config.needsRebuild(template.template, template.instance, options)
1675
+ if (needsRebuild) {
1676
+ console.log(`This module "${config.name}" needs rebuilding all other arguments will be ignored. Try again after the template is rebuilt.`)
1677
+ options.rebuild = true
1678
+ config.config.rebuild = true
1679
+ }
1680
+ config.load(template.template, template.instance, { rebuild: needsRebuild })
1681
+ printConfig()
1682
+ if (needsRebuild) {
1683
+ return
1684
+ }
1685
+ }
1686
+
1687
+ if (!args.save && !args.rebuildTemplate && !args.dontAddAssociations) {
1688
+ config.addAssociationsFromTests(config.tests);
1689
+ }
1690
+
1674
1691
  if (args.retrain) {
1675
1692
  config.config.retrain = true
1676
1693
  }
@@ -1712,11 +1729,13 @@ const knowledgeModule = async ({
1712
1729
  if (JSON.stringify(result.expected.paraphrases) !== JSON.stringify(result.actual.paraphrases)) {
1713
1730
  hasError = true
1714
1731
  }
1715
- if (JSON.stringify(result.expected.paraphrasesParenthesized) !== JSON.stringify(result.actual.paraphrasesParenthesized)) {
1716
- hasError = true
1717
- }
1718
- if (JSON.stringify(result.expected.generatedParenthesized) !== JSON.stringify(result.actual.generatedParenthesized)) {
1719
- hasError = true
1732
+ if (!args.testNoParenthesized) {
1733
+ if (JSON.stringify(result.expected.paraphrasesParenthesized) !== JSON.stringify(result.actual.paraphrasesParenthesized)) {
1734
+ hasError = true
1735
+ }
1736
+ if (JSON.stringify(result.expected.generatedParenthesized) !== JSON.stringify(result.actual.generatedParenthesized)) {
1737
+ hasError = true
1738
+ }
1720
1739
  }
1721
1740
  if (JSON.stringify(result.expected.responses) !== JSON.stringify(result.actual.responses)) {
1722
1741
  hasError = true
@@ -1724,6 +1743,9 @@ const knowledgeModule = async ({
1724
1743
  if (JSON.stringify(result.expected.checked) !== JSON.stringify(result.actual.checked)) {
1725
1744
  hasError = true
1726
1745
  }
1746
+ if (!sameJSON(result.expected.checkedContexts, result.actual.checkedContexts)) {
1747
+ hasError = true
1748
+ }
1727
1749
  }
1728
1750
 
1729
1751
  if (hasError) {
@@ -1742,9 +1764,13 @@ const knowledgeModule = async ({
1742
1764
  }
1743
1765
  }
1744
1766
  show('paraphrases', result.expected.paraphrases, result.actual.paraphrases)
1745
- show('paraphrases parenthesized', result.expected.paraphrasesParenthesized, result.actual.paraphrasesParenthesized)
1767
+ if (!args.testNoParenthesized) {
1768
+ show('paraphrases parenthesized', result.expected.paraphrasesParenthesized, result.actual.paraphrasesParenthesized)
1769
+ }
1746
1770
  show('responses', result.expected.responses, result.actual.responses)
1747
- show('responses parenthesized', result.expected.generatedParenthesized, result.actual.generatedParenthesized)
1771
+ if (!args.testNoParenthesized) {
1772
+ show('responses parenthesized', result.expected.generatedParenthesized, result.actual.generatedParenthesized)
1773
+ }
1748
1774
  /*
1749
1775
  if (JSON.stringify(result.expected.paraphrases) !== JSON.stringify(result.actual.paraphrases)) {
1750
1776
  if (!headerShown) {
@@ -1783,6 +1809,24 @@ const knowledgeModule = async ({
1783
1809
  newError = true
1784
1810
  headerShown = true
1785
1811
  }
1812
+ if (!sameJSON(result.expected.checkedContexts, result.actual.checkedContexts)) {
1813
+ if (!headerShown) {
1814
+ console.log(' Failure')
1815
+ }
1816
+ const widths = [4, 18, 72]
1817
+ const lines = new Lines(widths)
1818
+ lines.setElement(1, 1, 'expected checkedContexts', true)
1819
+ lines.setElement(2, 2, JSON.stringify(result.expected.checkedContexts, null, 2))
1820
+ lines.log()
1821
+ lines.setElement(1, 1, 'actual checkedContexts', true)
1822
+ lines.setElement(2, 2, JSON.stringify(result.actual.checkedContexts, null, 2))
1823
+ lines.log()
1824
+ if (args.vimdiff) {
1825
+ vimdiff(result.actual.checkedContexts, result.expected.checkedContexts)
1826
+ }
1827
+ newError = true
1828
+ headerShown = true
1829
+ }
1786
1830
  }
1787
1831
  } else {
1788
1832
  if (results.length > 0 && args.vimdiff) {
@@ -1821,7 +1865,6 @@ const knowledgeModule = async ({
1821
1865
  if (query.length === 0) {
1822
1866
  return readline.close()
1823
1867
  }
1824
- // const promise = processResults(_process(config, query, { testsFN: test }))
1825
1868
  const promise = _process(config, query, { testsFN: test }).then((results) => {
1826
1869
  console.log(results.responses.join(' '))
1827
1870
  })
@@ -1849,7 +1892,6 @@ const knowledgeModule = async ({
1849
1892
  if (args.objectDiff) {
1850
1893
  global.beforeObjects = _.cloneDeep(objects)
1851
1894
  }
1852
- config.beforeQuery({ query: args.query, isModule: false, objects })
1853
1895
  try {
1854
1896
  await processResults(_process(config, args.query, { commandLineArgs: args, dontAddAssociations: args.dontAddAssociations, writeTests: args.save || args.saveDeveloper, saveDeveloper: args.saveDeveloper, testConfig, testsFN: test }))
1855
1897
  } catch( error ) {
@@ -1858,11 +1900,55 @@ const knowledgeModule = async ({
1858
1900
  }
1859
1901
  printConfig()
1860
1902
  } else {
1861
- config.addAssociationsFromTests(config.tests);
1862
- //for (let query in config.tests) {
1863
- // config.addAssociations(config.tests[query].associations || []);
1864
- //}
1865
- module()
1903
+ const initConfig = (config) => {
1904
+ setupConfig(config)
1905
+
1906
+ let loadForTesting = false
1907
+ if (global.theprogrammablemind) {
1908
+ if (global.theprogrammablemind.loadForTesting[config.name]) {
1909
+ loadForTesting = true
1910
+ }
1911
+ }
1912
+ // remove test only stuff
1913
+ if (!isProcess && !loadForTesting) {
1914
+ config.config.operators = config.config.operators.filter( (operator) => {
1915
+ if (operator.development) {
1916
+ return false
1917
+ } else {
1918
+ return true
1919
+ }
1920
+ })
1921
+ config.config.bridges = config.config.bridges.filter( (bridge) => {
1922
+ if (bridge.development) {
1923
+ return false
1924
+ } else {
1925
+ return true
1926
+ }
1927
+ })
1928
+ }
1929
+
1930
+ if (template) {
1931
+ if (config.needsRebuild(template.template, template.instance, { isModule: !isProcess })) {
1932
+ 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.`
1933
+ throw new Error(error)
1934
+ }
1935
+ try {
1936
+ config.load(template.template, template.instance)
1937
+ } catch( e ) {
1938
+ errorHandler(e)
1939
+ }
1940
+ }
1941
+
1942
+ config.addAssociationsFromTests(config.tests);
1943
+ }
1944
+
1945
+ createConfigExport = () => {
1946
+ const config = createConfig()
1947
+ initConfig(config)
1948
+ config.rebuild({ isModule: true })
1949
+ return config
1950
+ }
1951
+ moduleFromJSFile.exports = createConfigExport
1866
1952
  }
1867
1953
 
1868
1954
  }
@@ -1918,7 +2004,7 @@ module.exports = {
1918
2004
  w,
1919
2005
  // submitBug,
1920
2006
  ensureTestFile,
1921
- build,
2007
+ rebuildTemplate,
1922
2008
  processContext,
1923
2009
  processContexts,
1924
2010
  runTests,
@@ -1930,8 +2016,9 @@ module.exports = {
1930
2016
  Digraph,
1931
2017
  analyzeMetaData,
1932
2018
  processContextsB,
1933
- processInstance,
2019
+ loadInstance,
1934
2020
  gs,
1935
2021
  flattens,
1936
2022
  writeTest
1937
2023
  }
2024
+