theprogrammablemind_4wp 7.5.8-beta.8 → 7.5.8-beta.80

Sign up to get free protection for your applications and to get access to all the features.
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,21 @@ 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, { marker: 'error', context, reason: e.reason, error: e.stack })
434
438
  }
435
439
  }
436
440
  if (contextPrime.controlRemove) {
@@ -439,7 +443,7 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
439
443
  let assumed = { isResponse: true };
440
444
  const generated = contextPrime.isResponse ? config.getGenerators(json.logs).apply(args, contextPrime, assumed)[0] : ''
441
445
  let generatedParenthesized = []
442
- if (isTest) {
446
+ if (generateParenthesized) {
443
447
  config.parenthesized = true
444
448
  generatedParenthesized = contextPrime.isResponse ? config.getGenerators(json.logs).apply(args, contextPrime, assumed)[0] : ''
445
449
  config.parenthesized = false
@@ -452,12 +456,12 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
452
456
  args.gs = gs(args.g)
453
457
  args.gsp = gs(args.gsp)
454
458
  args.gsr = gs(args.gr)
455
- if (isTest) {
459
+ if (generateParenthesized) {
456
460
  config.parenthesized = false
457
461
  }
458
462
  const paraphrases = config.getGenerators(json.logs).apply(args, contextPrime, assumed)[0]
459
463
  let paraphrasesParenthesized = []
460
- if (isTest) {
464
+ if (generateParenthesized) {
461
465
  config.parenthesized = true
462
466
  paraphrasesParenthesized = config.getGenerators(json.logs).apply(args, contextPrime, assumed)[0]
463
467
  config.parenthesized = false
@@ -471,7 +475,7 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
471
475
  contextsPrime.push(contextPrime)
472
476
  generatedPrime.push(generated)
473
477
  paraphrasesPrime.push(paraphrases)
474
- if (isTest) {
478
+ if (generateParenthesized) {
475
479
  paraphrasesParenthesizedPrime.push(paraphrasesParenthesized)
476
480
  generatedParenthesizedPrime.push(generatedParenthesized)
477
481
  }
@@ -549,8 +553,11 @@ const setupProcessB = ({ config, initializer, allowDelta=false } = {}) => {
549
553
  // console.log('config', config)
550
554
  data.delta = config.delta()
551
555
  } else {
552
- Object.assign(data, config.config)
556
+ config.toData(data)
557
+ // Object.assign(data, config.config)
553
558
  }
559
+
560
+ // config.toServer(data)
554
561
 
555
562
  if (data.namespaces) {
556
563
  for (const uuid of Object.keys(data.namespaces)) {
@@ -573,10 +580,22 @@ const setupProcessB = ({ config, initializer, allowDelta=false } = {}) => {
573
580
  }
574
581
  }
575
582
 
576
- // instance template
577
- const processInstance = (config, instance) => {
583
+ // instance template loadTemplate
584
+ const loadInstance = (config, instance) => {
578
585
  const transitoryMode = global.transitoryMode
579
586
  global.transitoryMode = false
587
+
588
+ if (instance && (instance.associations || instance.learned_contextual_priorities)) {
589
+ if (!config.config.retrain) {
590
+ if (instance.associations) {
591
+ config.addAssociations(instance.associations)
592
+ }
593
+ if (instance.learned_contextual_priorities && instance.learned_contextual_priorities.length > 0) {
594
+ config.addPriorities(instance.learned_contextual_priorities)
595
+ }
596
+ }
597
+ }
598
+
580
599
  const { /* data, generators, semantics, */ hierarchy } = setupProcessB({ config })
581
600
  // for (const results of (instance.resultss || [])) {
582
601
  for (const i in (instance.resultss || [])) {
@@ -584,15 +603,21 @@ const processInstance = (config, instance) => {
584
603
  if (results.extraConfig) {
585
604
  // config.addInternal(results, useOldVersion = true, skipObjects = false, includeNamespaces = true, allowNameToBeNull = false)
586
605
  // config.addInternal(config.template.queries[i], { handleCalculatedProps: true } )
587
- config.addInternal(instance.template.queries[i], { handleCalculatedProps: true } )
606
+ config.addInternal(instance.template.queries[i], { addFirst: true, handleCalculatedProps: true } )
588
607
  } else {
589
- processContextsB({ config, hierarchy, json: results/*, generators, semantics */, commandLineArgs: {} })
608
+ if (results.skipSemantics) {
609
+ config.config.skipSemantics = results.skipSemantics
610
+ }
611
+ processContextsB({ config, hierarchy, json: results/*, generators, semantics */, commandLineArgs: {}, isInstance: `instance${i}`, instance: instance.queries[i] })
612
+ if (results.skipSemantics) {
613
+ config.config.skipSemantics = null
614
+ }
590
615
  }
591
616
  }
592
617
  global.transitoryMode = transitoryMode
593
618
  }
594
619
 
595
- const _process = async (config, query, { initializer, commandLineArgs, credentials, writeTests, isTest, saveDeveloper, testConfig, testsFN, errorHandler = defaultErrorHandler } = {}) => {
620
+ const _process = async (config, query, { initializer, commandLineArgs, credentials, writeTests, isTest, saveDeveloper, rebuildingTemplate, testConfig, testsFN, errorHandler = defaultErrorHandler } = {}) => {
596
621
  if (credentials) {
597
622
  config.server(credentials.server, credentials.key)
598
623
  }
@@ -606,7 +631,6 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
606
631
  if (writeTests) {
607
632
  config.rebuild()
608
633
  const objects = getObjects(config.config.objects)(config.uuid)
609
- config.beforeQuery({ query, isModule: false, objects })
610
634
  }
611
635
  } catch(error) {
612
636
  throw error
@@ -614,7 +638,10 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
614
638
 
615
639
  let { data, /* generators, semantics, */ hierarchy } = setupProcessB({ config, initializer, allowDelta: true })
616
640
  if (commandLineArgs && commandLineArgs.checkForLoop) {
617
- data.checkForLoop = true
641
+ data.checkForLoop = commandLineArgs.checkForLoop
642
+ }
643
+ if (rebuildingTemplate) {
644
+ data.errors_ignore_contextual_priorities_non_existant_ops = true
618
645
  }
619
646
  let queries = query.split('\\n')
620
647
 
@@ -671,6 +698,7 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
671
698
  const { contextsPrime, generatedPrime, paraphrasesPrime, paraphrasesParenthesizedPrime, generatedParenthesizedPrime, responsesPrime } =
672
699
  processContextsB({ isTest, config, hierarchy, json, commandLineArgs /*, generators, semantics */ })
673
700
  response.associations = json.associations
701
+ response.learned_contextual_priorities = json.learned_contextual_priorities
674
702
  response.hierarchy = json.hierarchy
675
703
  response.load_cache_time += json.load_cache_time
676
704
  appendNoDups(response.logs, json.logs)
@@ -681,6 +709,7 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
681
709
  response.times += json.times
682
710
  response.trace = response.trace.concat(json.trace)
683
711
  response.version = json.version
712
+ response.explain_priorities = json.explain_priorities
684
713
 
685
714
  response.contexts = response.contexts.concat(contextsPrime)
686
715
  response.generated = response.generated.concat(generatedPrime)
@@ -694,7 +723,12 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
694
723
 
695
724
  if (writeTests) {
696
725
  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)
726
+ const saveObjects = {...config.config.objects}
727
+ saveObjects.nameToUUID = {}
728
+ for (let km of config.configs) {
729
+ saveObjects.nameToUUID[km.name] = km.uuid
730
+ }
731
+ writeTest(testsFN, query, saveObjects, response.generated, response.paraphrases, response.responses, response.contexts, response.associations, response.metadata, actual_config, saveDeveloper, response.paraphrasesParenthesized, response.generatedParenthesized)
698
732
  }
699
733
 
700
734
  return response
@@ -734,7 +768,7 @@ const getConfigForTest = (config, testConfig) => {
734
768
  return configForTest
735
769
  }
736
770
 
737
- const runTest = async (config, expected, { args, verbose, afterTest, testConfig, debug }) => {
771
+ const runTest = async (config, expected, { args, verbose, testConfig, debug }) => {
738
772
  const test = expected.query
739
773
  // initialize in between test so state is not preserved since the test was adding without state
740
774
  config.rebuild()
@@ -759,8 +793,6 @@ const runTest = async (config, expected, { args, verbose, afterTest, testConfig,
759
793
  objects = getObjects(config.config.objects)(config.getConfigs()[testConfig.testModuleName].uuid)
760
794
  testConfigName = testConfig.testModuleName
761
795
  }
762
- config.beforeQuery({ query: test, isModule: false, objects })
763
- // config.resetMotivations()
764
796
  try {
765
797
  const result = await _process(config, test, { errorHandler, isTest: true })
766
798
  result.query = test
@@ -778,38 +810,29 @@ const runTest = async (config, expected, { args, verbose, afterTest, testConfig,
778
810
  delete expected_objects.nameToUUID
779
811
  const actual_objects = sortJson(convertToStable(config.config.objects), { depth: 25 })
780
812
  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)
813
+ let failed_paraphrasesParenthesized = !matching(result.paraphrasesParenthesized, expected.paraphrasesParenthesized)
814
+ let failed_generatedParenthesized = !matching(result.generatedParenthesized, expected.generatedParenthesized)
815
+ // TODO fix the naming conventions: camelcase + use actual instead of result
783
816
  const failed_responses = !matching(result.responses, expected.responses)
784
817
  const failed_contexts = !matching(result.contexts, expected.contexts)
785
818
  const failed_objects = !matching(actual_objects, expected_objects)
786
819
 
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
820
+ if (args.testNoParenthesized) {
821
+ failed_paraphrasesParenthesized = false
822
+ failed_generatedParenthesized = false
805
823
  }
824
+
825
+ const pickedResultContexts = result.contexts.map(pickContext(testConfig))
826
+ const pickedExpectedContexts = expected.contexts.map(pickContext(testConfig))
827
+ const failedCheckedContexts = !matching(pickedResultContexts, pickedExpectedContexts)
828
+
806
829
  const expectedGetObjects = (name) => {
807
830
  if (!name) {
808
831
  name = config.name
809
832
  }
810
833
  return expected.objects.namespaced[expected.objects.nameToUUID[name]]
811
834
  }
812
- const expected_checked = sortJson(pickEm(expectedGetObjects), { depth: 25 })
835
+ const expected_checked = sortJson(pickObjects(testConfig, objects), { depth: 25 })
813
836
  const actualGetObjects = (name) => {
814
837
  if (!name) {
815
838
  name = config.name
@@ -817,45 +840,14 @@ const runTest = async (config, expected, { args, verbose, afterTest, testConfig,
817
840
  const km = config.configs.find( (km) => km.name == name )
818
841
  return config.config.objects.namespaced[km.uuid]
819
842
  }
820
- const actual_checked = sortJson(pickEm(actualGetObjects), { depth: 25 })
843
+ const actual_checked = sortJson(pickObjects(testConfig, actualGetObjects(testConfigName)), { depth: 25 })
821
844
  const failed_checked = !matching(actual_objects, expected_objects)
822
845
 
823
846
  const failed_checks = !matching(actual_objects, expected_objects)
824
847
  const actual_config = sortJson(convertToStable(getConfigForTest(config, testConfig)), { depth: 25 })
825
848
  const expected_config = sortJson(convertToStable(expected.config), { depth: 25 })
826
849
  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
- }
850
+ let failed = failed_paraphrases || failed_paraphrasesParenthesized || failed_generatedParenthesized || failed_responses || failed_contexts || failed_objects || failed_config || failed_checked || failedCheckedContexts
859
851
 
860
852
  if (expected.metadata && result.metadata && failed) {
861
853
  const priorities = analyzeMetaData(expected.metadata, result.metadata)
@@ -874,6 +866,7 @@ const runTest = async (config, expected, { args, verbose, afterTest, testConfig,
874
866
  generatedParenthesized: expected.generatedParenthesized,
875
867
  results: expected.contexts,
876
868
  checked: expected_checked,
869
+ checkedContexts: pickedExpectedContexts,
877
870
  objects: expected_objects,
878
871
  config: expected.config
879
872
  },
@@ -884,6 +877,7 @@ const runTest = async (config, expected, { args, verbose, afterTest, testConfig,
884
877
  generatedParenthesized: result.generatedParenthesized,
885
878
  results: result.contexts,
886
879
  checked: actual_checked,
880
+ checkedContexts: pickedResultContexts,
887
881
  objects: actual_objects,
888
882
  config: actual_config
889
883
  }
@@ -923,20 +917,16 @@ const runTestsHelper = async (config, tests, failed, juicyBits) => {
923
917
 
924
918
  const runTests = async (config, testFile, juicyBits) => {
925
919
  const tests = JSON.parse(runtime.fs.readFileSync(testFile))
926
- config.beforeTests()
927
920
  if (juicyBits.verbose) {
928
921
  console.log('\n', testFile, '-----------------------------------------------', '\n')
929
922
  }
930
923
  const v = await runTestsHelper(config, [...tests], [], juicyBits)
931
- config.afterTests()
932
924
  return v
933
925
  }
934
926
 
935
927
  const saveTest = async (testFile, config, test, expected, testConfig, saveDeveloper) => {
936
928
  config.rebuild()
937
929
  const objects = getObjects(config.config.objects)(config.uuid)
938
- //config.resetMotivations()
939
- config.beforeQuery({ query: test, isModule: false, objects })
940
930
  console.log(test)
941
931
  const result = await _process(config, test, { isTest: true })
942
932
  // const actualObjects = config.config.objects
@@ -1118,10 +1108,11 @@ const defaultErrorHandler = async (error) => {
1118
1108
  doErrorExit = true
1119
1109
  }
1120
1110
 
1121
- if (doErrorExit) {
1111
+ if (typeof runtime.process.exit == 'function' && doErrorExit) {
1122
1112
  runtime.process.exit(-1)
1123
1113
  }
1124
- // throw error
1114
+
1115
+ throw error
1125
1116
  }
1126
1117
 
1127
1118
  const defaultInnerProcess = (config, errorHandler, responses) => {
@@ -1131,6 +1122,13 @@ const defaultInnerProcess = (config, errorHandler, responses) => {
1131
1122
  }
1132
1123
  console.log("KM's loaded", config.configs.map((c) => c.name))
1133
1124
  console.log('This is the global objects from running semantics:\n', config.objects)
1125
+ if (!_.isEmpty(responses.learned_contextual_priorities)) {
1126
+ console.log('\nThe learned contextual priorties are :\n')
1127
+ for (const lcp of responses.learned_contextual_priorities) {
1128
+ console.log(` ${JSON.stringify(lcp)},\n`)
1129
+ }
1130
+ console.log("\n")
1131
+ }
1134
1132
  if (responses.logs) {
1135
1133
  console.log('Logs')
1136
1134
  responses.logs.forEach((log) => console.log(` ${log}`))
@@ -1142,6 +1140,50 @@ const defaultInnerProcess = (config, errorHandler, responses) => {
1142
1140
  } else {
1143
1141
  console.log('objects', runtime.util.inspect(config.get('objects'), { depth: Infinity, sorted: true }))
1144
1142
  }
1143
+
1144
+ const pickEm = () => {
1145
+ const picked = {}
1146
+ const namespaced = config.get('objects')['namespaced']
1147
+ for (let prop of getConfig_getObjectCheck(config.testConfig)) {
1148
+ if (prop.km) {
1149
+ /*
1150
+ const objects = namespaced[prop.km]]
1151
+ picked[prop.km] = {}
1152
+ for (let p of c.testConfig.check) {
1153
+ if (p.km) {
1154
+ continue
1155
+ }
1156
+ picked[p] = objects[p]
1157
+ }
1158
+ */
1159
+ console.log('TODO implement this if needed')
1160
+ } else {
1161
+ const objects = namespaced[config.uuid]
1162
+ picked[prop] = objects[prop]
1163
+ }
1164
+ }
1165
+ return picked
1166
+ }
1167
+
1168
+ if (responses.explain_priorities) {
1169
+ console.log("Explain Priorities")
1170
+ for ([inputss, outpus, reason] of responses.explain_priorities) {
1171
+ console.log(` ${JSON.stringify(inputss)} reason: ${reason}`)
1172
+ }
1173
+ }
1174
+ const objects = config.get('objects').namespaced[config.uuid]
1175
+ const picked = sortJson(pickObjects(config.testConfig, objects), { depth: 25 })
1176
+ if (!_.isEmpty(picked)) {
1177
+ console.log('--- Object showing only the checked values ---')
1178
+ console.log(JSON.stringify(picked, null, 2))
1179
+ }
1180
+
1181
+ const pickedResultContexts = responses.contexts.map(pickContext(config.testConfig))
1182
+ if (pickedResultContexts.some( (context) => Object.keys(context).length > 0 )) {
1183
+ console.log('--- Contexts showing only the checked values ---')
1184
+ console.log(JSON.stringify(pickedResultContexts, null, 2))
1185
+ }
1186
+
1145
1187
  console.log('--- The contexts are ----------')
1146
1188
  console.log(JSON.stringify(sortJson(responses.contexts, { depth: 25 }), null, 2))
1147
1189
  console.log('')
@@ -1182,37 +1224,14 @@ const defaultProcess = ({ config, errorHandler }) => async (promise) => {
1182
1224
  }
1183
1225
  }
1184
1226
 
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 }) => {
1227
+ // builtTemplate saveInstance
1228
+ const rebuildTemplate = async ({ config, target, template, errorHandler = defaultErrorHandler }) => {
1211
1229
  const accumulators = {
1212
1230
  resultss: [],
1213
1231
  fragments: [],
1214
1232
  semantics: [],
1215
1233
  associations: [],
1234
+ learned_contextual_priorities: [],
1216
1235
  }
1217
1236
  const looper = async (queries) => {
1218
1237
  if (queries.length === 0) {
@@ -1231,8 +1250,6 @@ const build = async ({ config, target, template, errorHandler = defaultErrorHand
1231
1250
  if (property == 'fragments') {
1232
1251
  global.transitoryMode = true
1233
1252
  }
1234
- // greg32
1235
- // config.addInternal( query )
1236
1253
  if (hierarchy) {
1237
1254
  for (let edge of hierarchy) {
1238
1255
  if (Array.isArray(edge)) {
@@ -1242,9 +1259,8 @@ const build = async ({ config, target, template, errorHandler = defaultErrorHand
1242
1259
  }
1243
1260
  }
1244
1261
  }
1245
-
1246
1262
  try {
1247
- const results = await _process(config, query.query, {initializer})
1263
+ const results = await _process(config, query.query, {initializer, rebuildingTemplate: true})
1248
1264
  if (config.config.debug) {
1249
1265
  // TODO pass in the error handler like the other ones
1250
1266
  defaultInnerProcess(config, defaultErrorHandler, results)
@@ -1259,10 +1275,12 @@ const build = async ({ config, target, template, errorHandler = defaultErrorHand
1259
1275
  global.transitoryMode = transitoryMode
1260
1276
  config.config.skipSemantics = null
1261
1277
  results.query = query.query
1278
+ results.skipSemantics = skipSemantics
1262
1279
  results.development = query.development
1263
1280
  results.key = { query: query.query, hierarchy }
1264
1281
  accumulators[property].push(results)
1265
1282
  accumulators.associations = accumulators.associations.concat(results.associations)
1283
+ accumulators.learned_contextual_priorities = accumulators.learned_contextual_priorities.concat(results.learned_contextual_priorities)
1266
1284
  await looper(queries)
1267
1285
  } catch(e) {
1268
1286
  const error = { errors: [e], query: query.query };
@@ -1274,6 +1292,12 @@ const build = async ({ config, target, template, errorHandler = defaultErrorHand
1274
1292
  // it will just get added to the config
1275
1293
  const extraConfig = queryOrExtraConfig
1276
1294
  console.log('config', extraConfig)
1295
+ try {
1296
+ config.addInternal(_.cloneDeep(extraConfig), { handleCalculatedProps: true } )
1297
+ } catch ( e ) {
1298
+ const where = extraConfig.where ? ` ${extraConfig.where}` : ''
1299
+ throw new Error(`Error processing extra config${where}: ${e.stack}}`)
1300
+ }
1277
1301
  accumulators[property].push({ extraConfig: true, ...extraConfig })
1278
1302
  await looper(queries)
1279
1303
  }
@@ -1301,6 +1325,7 @@ const build = async ({ config, target, template, errorHandler = defaultErrorHand
1301
1325
  delete result.version
1302
1326
  result.hierarchy.sort()
1303
1327
  stabilizeAssociations(result.associations)
1328
+ result.learned_contextual_priorities = safeNoDups(result.learned_contextual_priorities)
1304
1329
  }
1305
1330
  }
1306
1331
  }
@@ -1321,14 +1346,14 @@ const build = async ({ config, target, template, errorHandler = defaultErrorHand
1321
1346
 
1322
1347
  const toProperties = (queryStringOrProperties) => {
1323
1348
  if (typeof queryStringOrProperties == 'string') {
1324
- return { query: queryStringOrProperties}
1349
+ return { query: queryStringOrProperties }
1325
1350
  } else {
1326
1351
  return queryStringOrProperties
1327
1352
  }
1328
1353
  }
1329
1354
  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 } }))
1355
+ todo = todo.concat((template.initializers || []).map((query) => { return { initializer: true, property: 'resultss', query, skipSemantics: false || query.skipSemantics } }))
1356
+ todo = todo.concat((template.queries || []).map((query) => { return { property: 'resultss', query, skipSemantics: false || query.skipSemantics} }))
1332
1357
  todo = todo.concat((template.fragments || []).map((query) => { return Object.assign({}, toProperties(query), { property: 'fragments', skipSemantics: false }) }))
1333
1358
  todo = todo.concat((template.semantics || []).map((definition) => { return { property: 'semantics', query: `${definition.from}\n${definition.to}`, skipSemantics: true } }))
1334
1359
  await looper(Object.assign([], todo))
@@ -1338,36 +1363,31 @@ const knowledgeModule = async ({
1338
1363
  module: moduleFromJSFile,
1339
1364
  description,
1340
1365
  section,
1341
- config,
1366
+ // config, createConfig,
1367
+ createConfig,
1368
+ newWay,
1342
1369
  demo,
1343
1370
  test,
1344
1371
  template,
1345
1372
  errorHandler = defaultErrorHandler,
1346
1373
  process: processResults = defaultProcess,
1347
1374
  stopAtFirstFailure = true,
1348
- beforeQuery = () => {},
1349
- beforeTests = () => {},
1350
- afterTests = () => {},
1351
- beforeTest = () => {},
1352
- afterTest = () => {}
1375
+ ...rest
1353
1376
  } = {}) => {
1354
1377
 
1355
- config.beforeQuery = beforeQuery
1356
- config.beforeTests = beforeTests
1357
- config.afterTests = afterTests
1358
- config.beforeTest = beforeTest
1359
- config.afterTest = afterTest
1378
+ const unknownArgs = Object.keys(rest)
1379
+ if (unknownArgs.length > 0) {
1380
+ throw new Error(`Unknown arguments to knowledgeModule: ${unknownArgs.join()}`)
1381
+ }
1360
1382
 
1361
1383
  const testConfig = test
1362
1384
 
1363
1385
  if (!moduleFromJSFile) {
1364
1386
  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
1387
  }
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.")
1388
+ // if (!config && !createConfig) {
1389
+ if (!createConfig) {
1390
+ throw new Error("'config' or 'createConfig' is a required parameter. The value should the config that defines the knowledge module.")
1371
1391
  }
1372
1392
  if (!description) {
1373
1393
  throw new Error("'description' is a required parameter. The value should the description of the knowledge module.")
@@ -1377,86 +1397,52 @@ const knowledgeModule = async ({
1377
1397
  }
1378
1398
 
1379
1399
  const isProcess = require.main === moduleFromJSFile
1380
- let loadForTesting = false
1381
- if (global.theprogrammablemind) {
1382
- if (global.theprogrammablemind.loadForTesting[config.name]) {
1383
- loadForTesting = true
1400
+
1401
+ const setupConfig = (config) => {
1402
+ if (!config.name) {
1403
+ throw new Error("config must have 'name' set to the knowledge module name.")
1384
1404
  }
1385
- }
1386
1405
 
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
1406
+ config.description = description
1407
+ if (typeof test === 'object') {
1408
+ if (test.contents) {
1409
+ config.tests = test.contents
1410
+ test = test.name
1401
1411
  }
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
1412
  } 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)
1413
+ if (runtime.fs && runtime.fs.existsSync(test)) {
1414
+ config.tests = JSON.parse(runtime.fs.readFileSync(test))
1415
+ } else {
1416
+ config.tests = []
1440
1417
  }
1441
1418
  }
1419
+ config.setTestConfig(testConfig)
1442
1420
  }
1421
+
1422
+
1443
1423
  if (isProcess) {
1424
+ const config = createConfig()
1425
+ setupConfig(config)
1426
+ processResults = processResults({ config, errorHandler })
1444
1427
  // setup();
1445
1428
  const parser = new runtime.ArgumentParser({
1446
1429
  description: 'Entodicton knowledge module'
1447
1430
  })
1448
1431
 
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]))\' })'
1432
+ 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]]\''
1433
+ 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]]\''
1434
+ 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]]\''
1435
+ 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}\''
1436
+ 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\''
1437
+ 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
1438
 
1455
1439
 
1456
1440
  parser.add_argument('-tmn', '--testModuleName', { help: 'When running tests instead of using the current modules tests use the specified modules tests' })
1457
1441
  parser.add_argument('-t', '--test', { action: 'store_true', help: 'Run the tests. Create tests by running with the --query + --save flag' })
1458
1442
  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' })
1443
+ // parser.add_argument('-ttr', '--testToRun', { help: 'Only the specified test will be run' })
1459
1444
  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' })
1445
+ parser.add_argument('-tnp', '--testNoParenthesized', { action: 'store_true', help: 'Don\' check parenthesized differences for the tests' })
1460
1446
  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
1447
  // 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
1448
  parser.add_argument('-rt', '--rebuildTemplate', { action: 'store_true', help: 'Force a template rebuild' })
@@ -1464,7 +1450,7 @@ const knowledgeModule = async ({
1464
1450
  parser.add_argument('-i', '--info', { action: 'store_true', help: 'Print meta-data for the module' })
1465
1451
  parser.add_argument('-v', '--vimdiff', { action: 'store_true', help: 'For failures run vimdiff' })
1466
1452
  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' })
1453
+ 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
1454
  parser.add_argument('-r', '--retrain', { action: 'store_true', help: 'Get the server to retrain the neural nets' })
1469
1455
  parser.add_argument('-q', '--query', { help: 'Run the specified query' })
1470
1456
  parser.add_argument('-ip ', '--server', { help: 'Server to run against' })
@@ -1477,14 +1463,16 @@ const knowledgeModule = async ({
1477
1463
  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
1464
  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
1465
  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
1466
  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
1467
  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 })
1468
+ parser.add_argument('-da', '--debugAssociation', { action: 'store_true', help: helpDebugAssociation })
1469
+ parser.add_argument('-dh', '--debugHierarchy', { action: 'store_true', help: helpDebugHierarchy })
1470
+ parser.add_argument('-dp', '--debugPriority', { action: 'store_true', help: helpDebugPriority })
1471
+ parser.add_argument('-dcp', '--debugContextualPriority', { action: 'store_true', help: helpDebugContextualPriority })
1472
+ parser.add_argument('-db', '--debugBridge', { action: 'store_true', help: helpDebugBridge })
1473
+ parser.add_argument('-do', '--debugOperator', { action: 'store_true', help: helpDebugOperator })
1474
+ 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"})
1475
+ 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
1476
 
1489
1477
  const args = parser.parse_args()
1490
1478
  args.count = args.count || 1
@@ -1492,7 +1480,35 @@ const knowledgeModule = async ({
1492
1480
  if (args.parenthesized) {
1493
1481
  config.parenthesized = true
1494
1482
  }
1495
-
1483
+ if (args.checkForLoop) {
1484
+ try {
1485
+ args.checkForLoop = JSON.parse(args.checkForLoop)
1486
+ const isKey = (what) => {
1487
+ if (!Array.isArray(what)) {
1488
+ return false
1489
+ }
1490
+ if (what.length !== 2) {
1491
+ return false
1492
+ }
1493
+ if (!typeof what[0] == 'string') {
1494
+ return false
1495
+ }
1496
+ if (!typeof what[1] == 'number') {
1497
+ return false
1498
+ }
1499
+ return true
1500
+ }
1501
+ if (!Array.isArray(args.checkForLoop) || args.checkForLoop.some((value) => !isKey(value))) {
1502
+ throw new Error(`Error for the checkForLoop argument. Expected a JSON array of operator keys of the form "[<id>, <level>]"`)
1503
+ }
1504
+ } catch( e ) {
1505
+ throw new Error(`Error parsing JSON of the checkForLoop argument. ${e}`)
1506
+ }
1507
+ } else {
1508
+ if (process.argv.includes('--checkForLoop') || process.argv.includes('-cl')) {
1509
+ args.checkForLoop = true
1510
+ }
1511
+ }
1496
1512
  if (args.debugAssociation) {
1497
1513
  console.log(helpDebugAssociation)
1498
1514
  runtime.process.exit(-1)
@@ -1550,35 +1566,12 @@ const knowledgeModule = async ({
1550
1566
  if (args.debug) {
1551
1567
  config.config.debug = true
1552
1568
  }
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
1569
 
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
- //}
1570
+ if (args.explainPriorities) {
1571
+ config.config.explain_priorities = true
1572
1572
  }
1573
1573
 
1574
- /*
1575
- if (args.buildTemplate) {
1576
- if (template) {
1577
- config.rebuild()
1578
- config.load(template.template, template.instance, { rebuild: true })
1579
- }
1580
- }
1581
- */
1574
+ config.config.debugIncludeConvolutions = args.debugIncludeConvolutions || process.argv.includes('--debugIncludeConvolutions') || process.argv.includes('-dic')
1582
1575
 
1583
1576
  let configPrinted = false
1584
1577
  const printConfig = () => {
@@ -1671,6 +1664,24 @@ const knowledgeModule = async ({
1671
1664
  }
1672
1665
  }
1673
1666
 
1667
+ if (template) {
1668
+ const needsRebuild = config.needsRebuild(template.template, template.instance, options)
1669
+ if (needsRebuild) {
1670
+ console.log(`This module "${config.name}" needs rebuilding all other arguments will be ignored. Try again after the template is rebuilt.`)
1671
+ options.rebuild = true
1672
+ config.config.rebuild = true
1673
+ }
1674
+ config.load(template.template, template.instance, { rebuild: needsRebuild })
1675
+ printConfig()
1676
+ if (needsRebuild) {
1677
+ return
1678
+ }
1679
+ }
1680
+
1681
+ if (!args.save && !args.rebuildTemplate && !args.dontAddAssociations) {
1682
+ config.addAssociationsFromTests(config.tests);
1683
+ }
1684
+
1674
1685
  if (args.retrain) {
1675
1686
  config.config.retrain = true
1676
1687
  }
@@ -1712,11 +1723,13 @@ const knowledgeModule = async ({
1712
1723
  if (JSON.stringify(result.expected.paraphrases) !== JSON.stringify(result.actual.paraphrases)) {
1713
1724
  hasError = true
1714
1725
  }
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
1726
+ if (!args.testNoParenthesized) {
1727
+ if (JSON.stringify(result.expected.paraphrasesParenthesized) !== JSON.stringify(result.actual.paraphrasesParenthesized)) {
1728
+ hasError = true
1729
+ }
1730
+ if (JSON.stringify(result.expected.generatedParenthesized) !== JSON.stringify(result.actual.generatedParenthesized)) {
1731
+ hasError = true
1732
+ }
1720
1733
  }
1721
1734
  if (JSON.stringify(result.expected.responses) !== JSON.stringify(result.actual.responses)) {
1722
1735
  hasError = true
@@ -1724,6 +1737,9 @@ const knowledgeModule = async ({
1724
1737
  if (JSON.stringify(result.expected.checked) !== JSON.stringify(result.actual.checked)) {
1725
1738
  hasError = true
1726
1739
  }
1740
+ if (!sameJSON(result.expected.checkedContexts, result.actual.checkedContexts)) {
1741
+ hasError = true
1742
+ }
1727
1743
  }
1728
1744
 
1729
1745
  if (hasError) {
@@ -1742,9 +1758,13 @@ const knowledgeModule = async ({
1742
1758
  }
1743
1759
  }
1744
1760
  show('paraphrases', result.expected.paraphrases, result.actual.paraphrases)
1745
- show('paraphrases parenthesized', result.expected.paraphrasesParenthesized, result.actual.paraphrasesParenthesized)
1761
+ if (!args.testNoParenthesized) {
1762
+ show('paraphrases parenthesized', result.expected.paraphrasesParenthesized, result.actual.paraphrasesParenthesized)
1763
+ }
1746
1764
  show('responses', result.expected.responses, result.actual.responses)
1747
- show('responses parenthesized', result.expected.generatedParenthesized, result.actual.generatedParenthesized)
1765
+ if (!args.testNoParenthesized) {
1766
+ show('responses parenthesized', result.expected.generatedParenthesized, result.actual.generatedParenthesized)
1767
+ }
1748
1768
  /*
1749
1769
  if (JSON.stringify(result.expected.paraphrases) !== JSON.stringify(result.actual.paraphrases)) {
1750
1770
  if (!headerShown) {
@@ -1783,6 +1803,24 @@ const knowledgeModule = async ({
1783
1803
  newError = true
1784
1804
  headerShown = true
1785
1805
  }
1806
+ if (!sameJSON(result.expected.checkedContexts, result.actual.checkedContexts)) {
1807
+ if (!headerShown) {
1808
+ console.log(' Failure')
1809
+ }
1810
+ const widths = [4, 18, 72]
1811
+ const lines = new Lines(widths)
1812
+ lines.setElement(1, 1, 'expected checkedContexts', true)
1813
+ lines.setElement(2, 2, JSON.stringify(result.expected.checkedContexts, null, 2))
1814
+ lines.log()
1815
+ lines.setElement(1, 1, 'actual checkedContexts', true)
1816
+ lines.setElement(2, 2, JSON.stringify(result.actual.checkedContexts, null, 2))
1817
+ lines.log()
1818
+ if (args.vimdiff) {
1819
+ vimdiff(result.actual.checkedContexts, result.expected.checkedContexts)
1820
+ }
1821
+ newError = true
1822
+ headerShown = true
1823
+ }
1786
1824
  }
1787
1825
  } else {
1788
1826
  if (results.length > 0 && args.vimdiff) {
@@ -1821,7 +1859,6 @@ const knowledgeModule = async ({
1821
1859
  if (query.length === 0) {
1822
1860
  return readline.close()
1823
1861
  }
1824
- // const promise = processResults(_process(config, query, { testsFN: test }))
1825
1862
  const promise = _process(config, query, { testsFN: test }).then((results) => {
1826
1863
  console.log(results.responses.join(' '))
1827
1864
  })
@@ -1849,7 +1886,6 @@ const knowledgeModule = async ({
1849
1886
  if (args.objectDiff) {
1850
1887
  global.beforeObjects = _.cloneDeep(objects)
1851
1888
  }
1852
- config.beforeQuery({ query: args.query, isModule: false, objects })
1853
1889
  try {
1854
1890
  await processResults(_process(config, args.query, { commandLineArgs: args, dontAddAssociations: args.dontAddAssociations, writeTests: args.save || args.saveDeveloper, saveDeveloper: args.saveDeveloper, testConfig, testsFN: test }))
1855
1891
  } catch( error ) {
@@ -1858,11 +1894,55 @@ const knowledgeModule = async ({
1858
1894
  }
1859
1895
  printConfig()
1860
1896
  } else {
1861
- config.addAssociationsFromTests(config.tests);
1862
- //for (let query in config.tests) {
1863
- // config.addAssociations(config.tests[query].associations || []);
1864
- //}
1865
- module()
1897
+ const initConfig = (config) => {
1898
+ setupConfig(config)
1899
+
1900
+ let loadForTesting = false
1901
+ if (global.theprogrammablemind) {
1902
+ if (global.theprogrammablemind.loadForTesting[config.name]) {
1903
+ loadForTesting = true
1904
+ }
1905
+ }
1906
+ // remove test only stuff
1907
+ if (!isProcess && !loadForTesting) {
1908
+ config.config.operators = config.config.operators.filter( (operator) => {
1909
+ if (operator.development) {
1910
+ return false
1911
+ } else {
1912
+ return true
1913
+ }
1914
+ })
1915
+ config.config.bridges = config.config.bridges.filter( (bridge) => {
1916
+ if (bridge.development) {
1917
+ return false
1918
+ } else {
1919
+ return true
1920
+ }
1921
+ })
1922
+ }
1923
+
1924
+ if (template) {
1925
+ if (config.needsRebuild(template.template, template.instance, { isModule: !isProcess })) {
1926
+ 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.`
1927
+ throw new Error(error)
1928
+ }
1929
+ try {
1930
+ config.load(template.template, template.instance)
1931
+ } catch( e ) {
1932
+ errorHandler(e)
1933
+ }
1934
+ }
1935
+
1936
+ config.addAssociationsFromTests(config.tests);
1937
+ }
1938
+
1939
+ createConfigExport = () => {
1940
+ const config = createConfig()
1941
+ initConfig(config)
1942
+ config.rebuild({ isModule: true })
1943
+ return config
1944
+ }
1945
+ moduleFromJSFile.exports = createConfigExport
1866
1946
  }
1867
1947
 
1868
1948
  }
@@ -1918,7 +1998,7 @@ module.exports = {
1918
1998
  w,
1919
1999
  // submitBug,
1920
2000
  ensureTestFile,
1921
- build,
2001
+ rebuildTemplate,
1922
2002
  processContext,
1923
2003
  processContexts,
1924
2004
  runTests,
@@ -1930,8 +2010,9 @@ module.exports = {
1930
2010
  Digraph,
1931
2011
  analyzeMetaData,
1932
2012
  processContextsB,
1933
- processInstance,
2013
+ loadInstance,
1934
2014
  gs,
1935
2015
  flattens,
1936
2016
  writeTest
1937
2017
  }
2018
+