theprogrammablemind_4wp 7.5.8-beta.2 → 7.5.8-beta.20

Sign up to get free protection for your applications and to get access to all the features.
package/client.js CHANGED
@@ -109,7 +109,7 @@ class ErrorReason extends Error {
109
109
 
110
110
  const setupArgs = (args, config, logs, hierarchy) => {
111
111
  config.setArgs(args)
112
- args.calls = new InitCalls(config.name)
112
+ args.calls = new InitCalls(args.isInstance ? `${args.isInstance}#${config.name}` : config.name)
113
113
  if (global.theprogrammablemind && global.theprogrammablemind.loadForTesting) {
114
114
  args.calls = new InitCalls(Object.keys(global.theprogrammablemind.loadForTesting)[0])
115
115
  }
@@ -288,7 +288,7 @@ const writeTestFile = (fn, tests) => {
288
288
  runtime.fs.writeFileSync(fn, stringify(tests, { space: 2 }), { encoding: 'utf8', flag: 'w+' })
289
289
  }
290
290
 
291
- const writeTest = (fn, query, objects, generated, paraphrases, responses, contexts, associations, metadata, config, saveDeveloper) => {
291
+ const writeTest = (fn, query, objects, generated, paraphrases, responses, contexts, associations, metadata, config, saveDeveloper, paraphrasesParenthesized, generatedParenthesized) => {
292
292
  let tests = []
293
293
  if (runtime.fs.existsSync(fn)) {
294
294
  tests = JSON.parse(runtime.fs.readFileSync(fn))
@@ -298,7 +298,18 @@ const writeTest = (fn, query, objects, generated, paraphrases, responses, contex
298
298
  }
299
299
  associations.sort()
300
300
  // tests[query] = sortJson({ paraphrases, responses, contexts, objects: convertToStable(objects), associations, metadata, config, developerTest: saveDeveloper }, { depth: 25 })
301
- results = sortJson({ query, paraphrases, responses, contexts, objects: convertToStable(objects), associations, metadata, config, developerTest: saveDeveloper }, { depth: 25 })
301
+ results = sortJson({
302
+ query,
303
+ paraphrases,
304
+ responses,
305
+ contexts,
306
+ objects: convertToStable(objects),
307
+ associations,
308
+ metadata,
309
+ config,
310
+ developerTest: saveDeveloper,
311
+ paraphrasesParenthesized,
312
+ generatedParenthesized }, { depth: 25 })
302
313
  let wasSet = false;
303
314
  tests.forEach( (test, index) => {
304
315
  if (test.query == query) {
@@ -355,16 +366,18 @@ const setupContexts = (rawContexts) => {
355
366
  return contexts
356
367
  }
357
368
 
358
- const processContextsB = ({ config, hierarchy, semantics, generators, json, isTest, query, data, retries, url, commandLineArgs }) => {
369
+ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTest, isInstance, query, data, retries, url, commandLineArgs }) => {
359
370
  // TODO fix this name to contextsPrime
360
371
  const contextsPrime = []
361
372
  const generatedPrime = []
362
373
  const paraphrasesPrime = []
374
+ const paraphrasesParenthesizedPrime = []
375
+ const generatedParenthesizedPrime = []
363
376
  const responsesPrime = []
364
377
  const contexts = setupContexts(json.contexts)
365
378
 
366
379
  const objects = config.get('objects')
367
- const args = { objects, isResponse: true, response: json, isTest, getObjects: getObjects(objects) }
380
+ const args = { objects, isResponse: true, response: json, isTest, isInstance, getObjects: getObjects(objects), isInstance }
368
381
  if (!json.logs) {
369
382
  json.logs = []
370
383
  }
@@ -404,6 +417,7 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
404
417
  if (json.has_errors) {
405
418
  throw new Error('There are errors in the logs. Run with the -d flag and grep for Error')
406
419
  }
420
+ const generateParenthesized = isTest || (commandLineArgs && commandLineArgs.save)
407
421
  if (!config.get('skipSemantics')) {
408
422
  if (!config.doMotivations(args, context)) {
409
423
  const semantics = config.getSemantics(json.logs)
@@ -423,7 +437,13 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
423
437
  continue
424
438
  }
425
439
  let assumed = { isResponse: true };
426
- const generated = config.getGenerators(json.logs).apply(args, contextPrime, assumed)[0]
440
+ const generated = contextPrime.isResponse ? config.getGenerators(json.logs).apply(args, contextPrime, assumed)[0] : ''
441
+ let generatedParenthesized = []
442
+ if (generateParenthesized) {
443
+ config.parenthesized = true
444
+ generatedParenthesized = contextPrime.isResponse ? config.getGenerators(json.logs).apply(args, contextPrime, assumed)[0] : ''
445
+ config.parenthesized = false
446
+ }
427
447
  // assumed = { paraphrase: true, response: false };
428
448
  assumed = { paraphrase: true };
429
449
  args.g = (c) => config.getGenerators(json.logs).apply(args, c, assumed)
@@ -432,7 +452,16 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
432
452
  args.gs = gs(args.g)
433
453
  args.gsp = gs(args.gsp)
434
454
  args.gsr = gs(args.gr)
455
+ if (generateParenthesized) {
456
+ config.parenthesized = false
457
+ }
435
458
  const paraphrases = config.getGenerators(json.logs).apply(args, contextPrime, assumed)[0]
459
+ let paraphrasesParenthesized = []
460
+ if (generateParenthesized) {
461
+ config.parenthesized = true
462
+ paraphrasesParenthesized = config.getGenerators(json.logs).apply(args, contextPrime, assumed)[0]
463
+ config.parenthesized = false
464
+ }
436
465
  args.g = (c) => config.getGenerators(json.logs).apply(args, c)
437
466
  args.gp = (c) => config.getGenerators(json.logs).apply(args, {...c, paraphrase: true, isResponse: false, response: false })
438
467
  args.gr = (c) => config.getGenerators(json.logs).apply(args, {...c, paraphrase: false })
@@ -442,6 +471,10 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
442
471
  contextsPrime.push(contextPrime)
443
472
  generatedPrime.push(generated)
444
473
  paraphrasesPrime.push(paraphrases)
474
+ if (generateParenthesized) {
475
+ paraphrasesParenthesizedPrime.push(paraphrasesParenthesized)
476
+ generatedParenthesizedPrime.push(generatedParenthesized)
477
+ }
445
478
  if (contextPrime.isResponse) {
446
479
  responsesPrime.push(generated)
447
480
  } else {
@@ -451,7 +484,7 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
451
484
  // add results to processed list
452
485
  config.config.objects.processed = config.config.objects.processed || []
453
486
  config.config.objects.processed = config.config.objects.processed.slice(0, 5)
454
- config.config.objects.processed.unshift({ context: contextPrime, paraphrases: paraphrases, responses: responsesPrime })
487
+ config.config.objects.processed.unshift({ context: contextPrime, paraphrases: paraphrases, paraphrasesParenthesized, generatedParenthesized, responses: responsesPrime })
455
488
  } catch (e) {
456
489
  if (Array.isArray(e)) {
457
490
  e = {
@@ -471,7 +504,7 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
471
504
  throw e
472
505
  }
473
506
  }
474
- return { contextsPrime, generatedPrime, paraphrasesPrime, responsesPrime }
507
+ return { contextsPrime, generatedPrime, paraphrasesPrime, paraphrasesParenthesizedPrime, generatedParenthesizedPrime, responsesPrime }
475
508
  }
476
509
 
477
510
  const doWithRetries = async (n, url, queryParams, data) => {
@@ -493,17 +526,17 @@ const doWithRetries = async (n, url, queryParams, data) => {
493
526
  }
494
527
  if (result.status === 504) {
495
528
  if (n === 0) {
496
- throw `Error ${result.status} - ${result.statusText}`
529
+ throw new Error(`Error ${result.status} - ${result.statusText}`)
497
530
  } else {
498
531
  continue
499
532
  }
500
533
  }
501
534
  if (result.status >= 500 && result.status < 600) {
502
- throw `Error ${result.status} - ${result.statusText}.`
535
+ throw new Error(`Error ${result.status} - ${result.statusText}.`)
503
536
  } if (result.status >= 404) {
504
- throw `Error ${result.status} - ${result.statusText} - Trying it connect to ${url}`
537
+ throw new Error(`Error ${result.status} - ${result.statusText} - Trying it connect to ${url}`)
505
538
  } else {
506
- throw `Error ${result.status} - ${result.statusText}`
539
+ throw new Error(`Error ${result.status} - ${result.statusText}`)
507
540
  }
508
541
  }
509
542
  }
@@ -516,8 +549,11 @@ const setupProcessB = ({ config, initializer, allowDelta=false } = {}) => {
516
549
  // console.log('config', config)
517
550
  data.delta = config.delta()
518
551
  } else {
519
- Object.assign(data, config.config)
552
+ config.toData(data)
553
+ // Object.assign(data, config.config)
520
554
  }
555
+
556
+ // config.toServer(data)
521
557
 
522
558
  if (data.namespaces) {
523
559
  for (const uuid of Object.keys(data.namespaces)) {
@@ -553,13 +589,13 @@ const processInstance = (config, instance) => {
553
589
  // config.addInternal(config.template.queries[i], { handleCalculatedProps: true } )
554
590
  config.addInternal(instance.template.queries[i], { handleCalculatedProps: true } )
555
591
  } else {
556
- processContextsB({ config, hierarchy, json: results/*, generators, semantics */, commandLineArgs: {} })
592
+ processContextsB({ config, hierarchy, json: results/*, generators, semantics */, commandLineArgs: {}, isInstance: `instance${i}` })
557
593
  }
558
594
  }
559
595
  global.transitoryMode = transitoryMode
560
596
  }
561
597
 
562
- const _process = async (config, query, { initializer, commandLineArgs, credentials, writeTests, isTest, saveDeveloper, testConfig, testsFN, errorHandler = defaultErrorHandler } = {}) => {
598
+ const _process = async (config, query, { initializer, commandLineArgs, credentials, writeTests, isTest, saveDeveloper, rebuildingTemplate, testConfig, testsFN, errorHandler = defaultErrorHandler } = {}) => {
563
599
  if (credentials) {
564
600
  config.server(credentials.server, credentials.key)
565
601
  }
@@ -583,6 +619,9 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
583
619
  if (commandLineArgs && commandLineArgs.checkForLoop) {
584
620
  data.checkForLoop = true
585
621
  }
622
+ if (rebuildingTemplate) {
623
+ data.errors_ignore_contextual_priorities_non_existant_ops = true
624
+ }
586
625
  let queries = query.split('\\n')
587
626
 
588
627
  try {
@@ -598,6 +637,8 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
598
637
  contexts: [],
599
638
  generated: [],
600
639
  paraphrases: [],
640
+ paraphrasesParenthesized: [],
641
+ generatedParenthesized: [],
601
642
  responses: [],
602
643
  associations: [],
603
644
  }
@@ -633,7 +674,7 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
633
674
  if (json.status !== 200) {
634
675
  throw json
635
676
  } else {
636
- const { contextsPrime, generatedPrime, paraphrasesPrime, responsesPrime } =
677
+ const { contextsPrime, generatedPrime, paraphrasesPrime, paraphrasesParenthesizedPrime, generatedParenthesizedPrime, responsesPrime } =
637
678
  processContextsB({ isTest, config, hierarchy, json, commandLineArgs /*, generators, semantics */ })
638
679
  response.associations = json.associations
639
680
  response.hierarchy = json.hierarchy
@@ -650,6 +691,8 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
650
691
  response.contexts = response.contexts.concat(contextsPrime)
651
692
  response.generated = response.generated.concat(generatedPrime)
652
693
  response.paraphrases = response.paraphrases.concat(paraphrasesPrime)
694
+ response.paraphrasesParenthesized = response.paraphrasesParenthesized.concat(paraphrasesParenthesizedPrime)
695
+ response.generatedParenthesized = response.generatedParenthesized.concat(generatedParenthesizedPrime)
653
696
  response.responses = response.responses.concat(responsesPrime)
654
697
  queries = queries.slice(1)
655
698
  }
@@ -657,7 +700,7 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
657
700
 
658
701
  if (writeTests) {
659
702
  const actual_config = getConfigForTest(config, testConfig)
660
- writeTest(testsFN, query, config.config.objects, response.generated, response.paraphrases, response.responses, response.contexts, response.associations, response.metadata, actual_config, saveDeveloper)
703
+ 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)
661
704
  }
662
705
 
663
706
  return response
@@ -738,8 +781,11 @@ const runTest = async (config, expected, { args, verbose, afterTest, testConfig,
738
781
  lines.log()
739
782
  }
740
783
  const expected_objects = sortJson(convertToStable(expected.objects), { depth: 25 })
784
+ delete expected_objects.nameToUUID
741
785
  const actual_objects = sortJson(convertToStable(config.config.objects), { depth: 25 })
742
786
  const failed_paraphrases = !matching(result.paraphrases, expected.paraphrases)
787
+ const failed_paraphrasesParenthesized = !matching(result.paraphrasesParenthesized, expected.paraphrasesParenthesized)
788
+ const failed_generatedParenthesized = !matching(result.generatedParenthesized, expected.generatedParenthesized)
743
789
  const failed_responses = !matching(result.responses, expected.responses)
744
790
  const failed_contexts = !matching(result.contexts, expected.contexts)
745
791
  const failed_objects = !matching(actual_objects, expected_objects)
@@ -784,7 +830,7 @@ const runTest = async (config, expected, { args, verbose, afterTest, testConfig,
784
830
  const actual_config = sortJson(convertToStable(getConfigForTest(config, testConfig)), { depth: 25 })
785
831
  const expected_config = sortJson(convertToStable(expected.config), { depth: 25 })
786
832
  const failed_config = !matching(actual_config, expected_config)
787
- let failed = failed_paraphrases || failed_responses || failed_contexts || failed_objects || failed_config || failed_checked
833
+ let failed = failed_paraphrases || failed_paraphrasesParenthesized || failed_generatedParenthesized || failed_responses || failed_contexts || failed_objects || failed_config || failed_checked
788
834
  if (!failed) {
789
835
  if (config.afterTest) {
790
836
  failed = config.afterTest({ query: test, expected, actual: result, config })
@@ -792,8 +838,26 @@ const runTest = async (config, expected, { args, verbose, afterTest, testConfig,
792
838
  return {
793
839
  utterance: test,
794
840
  errorFromAfterTest: failed,
795
- expected: { responses: expected.responses, paraphrases: expected.paraphrases, results: expected.contexts, checked: expected_checked, objects: expected_objects, config: expected.config },
796
- actual: { responses: result.responses, paraphrases: result.paraphrases, results: result.contexts, checked: actual_checked, objects: actual_objects, config: actual_config }
841
+ expected: {
842
+ responses: expected.responses,
843
+ paraphrases: expected.paraphrases,
844
+ paraphrasesParenthesized: expected.paraphrasesParenthesized,
845
+ generatedParenthesized: expected.generatedParenthesized,
846
+ results: expected.contexts,
847
+ checked: expected_checked,
848
+ objects: expected_objects,
849
+ config: expected.config
850
+ },
851
+ actual: {
852
+ responses: result.responses,
853
+ paraphrases: result.paraphrases,
854
+ paraphrasesParenthesized: result.paraphrasesParenthesized,
855
+ generatedParenthesized: result.generatedParenthesized,
856
+ results: result.contexts,
857
+ checked: actual_checked,
858
+ objects: actual_objects,
859
+ config: actual_config
860
+ }
797
861
  }
798
862
  }
799
863
  }
@@ -809,8 +873,26 @@ const runTest = async (config, expected, { args, verbose, afterTest, testConfig,
809
873
  if (failed) {
810
874
  return {
811
875
  utterance: test,
812
- expected: { responses: expected.responses, paraphrases: expected.paraphrases, results: expected.contexts, checked: expected_checked, objects: expected_objects, config: expected.config },
813
- actual: { responses: result.responses, paraphrases: result.paraphrases, results: result.contexts, checked: actual_checked, objects: actual_objects, config: actual_config }
876
+ expected: {
877
+ responses: expected.responses,
878
+ paraphrases: expected.paraphrases,
879
+ paraphrasesParenthesized: expected.paraphrasesParenthesized,
880
+ generatedParenthesized: expected.generatedParenthesized,
881
+ results: expected.contexts,
882
+ checked: expected_checked,
883
+ objects: expected_objects,
884
+ config: expected.config
885
+ },
886
+ actual: {
887
+ responses: result.responses,
888
+ paraphrases: result.paraphrases,
889
+ paraphrasesParenthesized: result.paraphrasesParenthesized,
890
+ generatedParenthesized: result.generatedParenthesized,
891
+ results: result.contexts,
892
+ checked: actual_checked,
893
+ objects: actual_objects,
894
+ config: actual_config
895
+ }
814
896
  }
815
897
  }
816
898
  } catch(error) {
@@ -872,7 +954,7 @@ const saveTest = async (testFile, config, test, expected, testConfig, saveDevelo
872
954
  for (let km of config.configs) {
873
955
  saveObjects.nameToUUID[km.name] = km.uuid
874
956
  }
875
- writeTest(testFile, test, saveObjects, result.generated, result.paraphrases, result.responses, result.contexts, result.associations, result.metadata, actualConfig, saveDeveloper)
957
+ writeTest(testFile, test, saveObjects, result.generated, result.paraphrases, result.responses, result.contexts, result.associations, result.metadata, actualConfig, saveDeveloper, result.paraphrasesParenthesized, result.generatedParenthesized)
876
958
  }
877
959
 
878
960
  const saveTestsHelper = async (testFile, config, tests, todo, testConfig, saveDeveloper) => {
@@ -1042,10 +1124,11 @@ const defaultErrorHandler = async (error) => {
1042
1124
  doErrorExit = true
1043
1125
  }
1044
1126
 
1045
- if (doErrorExit) {
1127
+ if (typeof runtime.process.exit == 'function' && doErrorExit) {
1046
1128
  runtime.process.exit(-1)
1047
1129
  }
1048
- // throw error
1130
+
1131
+ throw error
1049
1132
  }
1050
1133
 
1051
1134
  const defaultInnerProcess = (config, errorHandler, responses) => {
@@ -1168,13 +1251,15 @@ const build = async ({ config, target, template, errorHandler = defaultErrorHand
1168
1251
  }
1169
1252
 
1170
1253
  try {
1171
- const results = await _process(config, query.query, {initializer})
1254
+ const results = await _process(config, query.query, {initializer, rebuildingTemplate: true})
1172
1255
  if (config.config.debug) {
1173
1256
  // TODO pass in the error handler like the other ones
1174
1257
  defaultInnerProcess(config, defaultErrorHandler, results)
1175
1258
  }
1176
1259
  if (results.contexts.length > 1) {
1177
- console.log(`query ${query.query}. There is ${results.contexts.length} contexts in the results. Make sure its producing the results that you expect.`)
1260
+ console.log(`query "${query.query}". There is ${results.contexts.length} contexts in the results. Make sure its producing the results that you expect.`)
1261
+ } else if (results.paraphrases[0] != query.query) {
1262
+ console.log(`query "${query.query}". The paraphrase is different from the query "${results.paraphrases[0]}".`)
1178
1263
  } else {
1179
1264
  console.log(`query ${query.query}`)
1180
1265
  }
@@ -1271,9 +1356,15 @@ const knowledgeModule = async ({
1271
1356
  beforeTests = () => {},
1272
1357
  afterTests = () => {},
1273
1358
  beforeTest = () => {},
1274
- afterTest = () => {}
1359
+ afterTest = () => {},
1360
+ ...rest
1275
1361
  } = {}) => {
1276
1362
 
1363
+ const unknownArgs = Object.keys(rest)
1364
+ if (unknownArgs.length > 0) {
1365
+ throw new Error(`Unknown arguments to knowledgeModule: ${unknownArgs.join()}`)
1366
+ }
1367
+
1277
1368
  config.beforeQuery = beforeQuery
1278
1369
  config.beforeTests = beforeTests
1279
1370
  config.afterTests = afterTests
@@ -1283,19 +1374,19 @@ const knowledgeModule = async ({
1283
1374
  const testConfig = test
1284
1375
 
1285
1376
  if (!moduleFromJSFile) {
1286
- throw "'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."
1377
+ 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.")
1287
1378
  }
1288
1379
  if (!config) {
1289
- throw "'config' is a required parameter. The value should the config that defines the knowledge module."
1380
+ throw new Error("'config' is a required parameter. The value should the config that defines the knowledge module.")
1290
1381
  }
1291
1382
  if (!config.name) {
1292
- throw "config must have 'name' set to the knowledge module name."
1383
+ throw new Error("config must have 'name' set to the knowledge module name.")
1293
1384
  }
1294
1385
  if (!description) {
1295
- throw "'description' is a required parameter. The value should the description of the knowledge module."
1386
+ throw new Error("'description' is a required parameter. The value should the description of the knowledge module.")
1296
1387
  }
1297
1388
  if (!test) {
1298
- throw "'test' is a required parameter. The value should the path to the file used to store the tests of the knowledge module and the contents of the file in the form { name: <filePath>, contexts: <json> }."
1389
+ throw new Error("'test' is a required parameter. The value should the path to the file used to store the tests of the knowledge module and the contents of the file in the form { name: <filePath>, contexts: <json> }.")
1299
1390
  }
1300
1391
 
1301
1392
  const isProcess = require.main === moduleFromJSFile
@@ -1353,7 +1444,7 @@ const knowledgeModule = async ({
1353
1444
  if (!isProcess) {
1354
1445
  if (template) {
1355
1446
  if (config.needsRebuild(template.template, template.instance)) {
1356
- throw `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.`
1447
+ 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.`)
1357
1448
  }
1358
1449
  try {
1359
1450
  config.load(template.template, template.instance)
@@ -1368,9 +1459,10 @@ const knowledgeModule = async ({
1368
1459
  description: 'Entodicton knowledge module'
1369
1460
  })
1370
1461
 
1371
- 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"]\' })'
1372
- 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"]\' })'
1373
- 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"]\' })'
1462
+ 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]]\' })'
1463
+ 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]]\' })'
1464
+ 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]]\' })'
1465
+ 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}\' })'
1374
1466
  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\' })'
1375
1467
  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]))\' })'
1376
1468
 
@@ -1392,6 +1484,7 @@ const knowledgeModule = async ({
1392
1484
  parser.add_argument('-ip ', '--server', { help: 'Server to run against' })
1393
1485
  parser.add_argument('-qp ', '--queryParams', { help: 'Query params for the server call' })
1394
1486
  parser.add_argument('-dt', '--deleteTest', { help: 'Delete the specified query from the tests file.' })
1487
+ parser.add_argument('--parenthesized', { action: 'store_true', help: 'Show the generated phrases with parenthesis.' })
1395
1488
  parser.add_argument('-c', '--clean', { help: 'Remove data from the test files. a === association' })
1396
1489
  parser.add_argument('-od', '--objectDiff', { action: 'store_true', help: 'When showing the objects use a colour diff' })
1397
1490
  parser.add_argument('-daa', '--dontAddAssociations', { action: 'store_true', help: 'Do not add associations from the tests.' })
@@ -1404,12 +1497,17 @@ const knowledgeModule = async ({
1404
1497
  parser.add_argument('-da', '--debugAssociation', { help: helpDebugAssociation })
1405
1498
  parser.add_argument('-dh', '--debugHierarchy', { help: helpDebugHierarchy })
1406
1499
  parser.add_argument('-dp', '--debugPriority', { help: helpDebugPriority })
1500
+ parser.add_argument('-dcp', '--debugContextualPriority', { help: helpDebugContextualPriority })
1407
1501
  parser.add_argument('-db', '--debugBridge', { help: helpDebugBridge })
1408
1502
  parser.add_argument('-do', '--debugOperator', { help: helpDebugOperator })
1409
1503
 
1410
1504
  const args = parser.parse_args()
1411
1505
  args.count = args.count || 1
1412
1506
 
1507
+ if (args.parenthesized) {
1508
+ config.parenthesized = true
1509
+ }
1510
+
1413
1511
  if (args.debugAssociation) {
1414
1512
  console.log(helpDebugAssociation)
1415
1513
  runtime.process.exit(-1)
@@ -1629,6 +1727,12 @@ const knowledgeModule = async ({
1629
1727
  if (JSON.stringify(result.expected.paraphrases) !== JSON.stringify(result.actual.paraphrases)) {
1630
1728
  hasError = true
1631
1729
  }
1730
+ if (JSON.stringify(result.expected.paraphrasesParenthesized) !== JSON.stringify(result.actual.paraphrasesParenthesized)) {
1731
+ hasError = true
1732
+ }
1733
+ if (JSON.stringify(result.expected.generatedParenthesized) !== JSON.stringify(result.actual.generatedParenthesized)) {
1734
+ hasError = true
1735
+ }
1632
1736
  if (JSON.stringify(result.expected.responses) !== JSON.stringify(result.actual.responses)) {
1633
1737
  hasError = true
1634
1738
  }
@@ -1641,6 +1745,22 @@ const knowledgeModule = async ({
1641
1745
  console.log('**************************** ERRORS ************************')
1642
1746
  for (const result of results) {
1643
1747
  console.log('Utterance: ', result.utterance)
1748
+ const show = (label, expected, actual) => {
1749
+ if (JSON.stringify(expected) !== JSON.stringify(actual)) {
1750
+ if (!headerShown) {
1751
+ console.log(' Failure')
1752
+ }
1753
+ console.log(` expected ${label}`, expected)
1754
+ console.log(` actual ${label} `, actual)
1755
+ newError = true
1756
+ headerShown = true
1757
+ }
1758
+ }
1759
+ show('paraphrases', result.expected.paraphrases, result.actual.paraphrases)
1760
+ show('paraphrases parenthesized', result.expected.paraphrasesParenthesized, result.actual.paraphrasesParenthesized)
1761
+ show('responses', result.expected.responses, result.actual.responses)
1762
+ show('responses parenthesized', result.expected.generatedParenthesized, result.actual.generatedParenthesized)
1763
+ /*
1644
1764
  if (JSON.stringify(result.expected.paraphrases) !== JSON.stringify(result.actual.paraphrases)) {
1645
1765
  if (!headerShown) {
1646
1766
  console.log(' Failure')
@@ -1659,6 +1779,7 @@ const knowledgeModule = async ({
1659
1779
  newError = true
1660
1780
  headerShown = true
1661
1781
  }
1782
+ */
1662
1783
  if (JSON.stringify(result.expected.checked) !== JSON.stringify(result.actual.checked)) {
1663
1784
  if (!headerShown) {
1664
1785
  console.log(' Failure')
@@ -1720,7 +1841,7 @@ const knowledgeModule = async ({
1720
1841
  console.log(results.responses.join(' '))
1721
1842
  })
1722
1843
  if (!('then' in promise)) {
1723
- throw 'Return a promise from process in the definition of knowledgeModule'
1844
+ throw new Error('Return a promise from process in the definition of knowledgeModule')
1724
1845
  }
1725
1846
  promise
1726
1847
  .then(() => {
@@ -1829,3 +1950,4 @@ module.exports = {
1829
1950
  flattens,
1830
1951
  writeTest
1831
1952
  }
1953
+
package/lines.js CHANGED
@@ -13,7 +13,7 @@ class Lines {
13
13
  setElement (row, column, value) {
14
14
  const values = value.toString().split('\n')
15
15
  if (column >= this.widths.length) {
16
- throw "Column out of range."
16
+ throw new Error("Column out of range.")
17
17
  }
18
18
  const width = this.widths[column]
19
19
  let index = 0
package/package.json CHANGED
@@ -63,6 +63,6 @@
63
63
  "json-stable-stringify": "^1.0.1",
64
64
  "node-fetch": "^2.6.1"
65
65
  },
66
- "version": "7.5.8-beta.2",
66
+ "version": "7.5.8-beta.20",
67
67
  "license": "ISC"
68
68
  }
package/src/config.js CHANGED
@@ -22,6 +22,90 @@ const indent = (string, indent) => {
22
22
  return string.replace(/^/gm, ' '.repeat(indent));
23
23
  }
24
24
 
25
+ const config_toServer = (config) => {
26
+ if (config.contextual_priorities) {
27
+ config.contextual_priorities = config.contextual_priorities.map((cp) => {
28
+ return [cp.context, cp.choose]
29
+ })
30
+ }
31
+ }
32
+
33
+ const contextual_priorities_toServer = (cp) => {
34
+ if (cp.context && cp.choose) {
35
+ return [cp.context, cp.choose]
36
+ }
37
+ return cp
38
+ }
39
+
40
+ const contextual_priorities_toClient = (cp) => {
41
+ if (cp.context && cp.choose) {
42
+ return cp
43
+ }
44
+ return { context: cp[0], choose: cp[1] }
45
+ }
46
+
47
+ const operatorKey_valid = (key) => {
48
+ if (
49
+ !_.isArray(key) ||
50
+ key.length != 2 ||
51
+ !_.isString(key[0]) ||
52
+ !_.isInteger(key[1]) ||
53
+ key[1] < 0
54
+ ) {
55
+
56
+ let details = ''
57
+ if (!_.isArray(key)) {
58
+ details = "Expected an array."
59
+ } else if (key.length != 2) {
60
+ details = "Expected an array of length two."
61
+ } else if (!_.isString(key[0])) {
62
+ details = "Expected element zero to be a string that is an operator id."
63
+ } else if (!_.isInteger(key[1])) {
64
+ details = "Expected element one to be a number that is an operator level."
65
+ } else if (key[1] < 0) {
66
+ details = "Expected element one to be a number that is an operator level which is greater than zero."
67
+ }
68
+ throw new Error(`${JSON.stringify(key)} is not a valid operator key. Values are of the form [<operatorId>, <operatorLevel>]. ${details}`)
69
+ }
70
+ }
71
+
72
+ const elist = (list, check, prefix) => {
73
+ for ([index, element] of list.entries()) {
74
+ try {
75
+ check(element)
76
+ } catch( e ) {
77
+ throw new Error(prefix(index, e))
78
+ }
79
+ }
80
+ }
81
+ const contextual_priorities_valid = (cps) => {
82
+ elist(cps, (cp) => contextual_priority_valid(cp), (index, e) => `contextual_priorities has an invalid contextual priority at position ${index}. ${e}`)
83
+ }
84
+
85
+ const contextual_priority_valid = (cp) => {
86
+ if (!cp.context) {
87
+ throw new Error(`The contextual priority ${JSON.stringify(cp)} is missing the "context" property. That is a list of the operator keys that are to be prioritized differently.`)
88
+ }
89
+ if (!_.isArray(cp.context)) {
90
+ throw new Error(`The contextual priority ${JSON.stringify(cp)} has an invalid "context" value. That is a list of the operator keys that are to be prioritized differently.`)
91
+ }
92
+ elist(cp.context, (element) => operatorKey_valid(element), (index, e) => `The contextual priority ${JSON.stringify(cp)} has an invalid operator key at position ${index}. ${e}`)
93
+ if (!_.isArray(cp.choose)) {
94
+ throw new Error(`The contextual priority ${JSON.stringify(cp)} has an invalid "choose" value. The value should be a list of the operators in the context to consider for prioritization.`)
95
+ }
96
+ elist(cp.choose,
97
+ (element) => {
98
+ if (!element && element !== 0) {
99
+ throw new Error(`The value should be an index into the "context" property of the operator that is to be considered for prioritization.`)
100
+ }
101
+ if (!_.isInteger(element) || element < 0 || element >= cp.context.length) {
102
+ throw new Error(`The value should be an index into the "context" property of the operator that is to be considered for prioritization. Valid values are between 0 and ${cp.context.length-1}.`)
103
+ }
104
+ },
105
+ (index, e) => `The choose property in the contextual priority ${JSON.stringify(cp)} has an invalid index at position ${index}. ${e}`
106
+ )
107
+ }
108
+
25
109
  const handleBridgeProps = (config, bridge) => {
26
110
  ecatch(`While processing the bridge for ${bridge.id}#${bridge.level}`,
27
111
  () => {
@@ -54,6 +138,14 @@ const handleBridgeProps = (config, bridge) => {
54
138
  config.addPriorities([after, [bridge.id, bridge.level]])
55
139
  }
56
140
  }
141
+ if (bridge.after) {
142
+ for (let before of bridge.after) {
143
+ if (typeof before == 'string') {
144
+ before = [before, 0]
145
+ }
146
+ config.addPriorities([[bridge.id, bridge.level], before])
147
+ }
148
+ }
57
149
  if (bridge.words) {
58
150
  for (let def of bridge.words) {
59
151
  if (typeof def == 'string') {
@@ -80,15 +172,30 @@ const handleBridgeProps = (config, bridge) => {
80
172
  bridge.generatorr = bridge.generatorpr
81
173
  }
82
174
  if (bridge.generatorp) {
175
+ const match = bridge.generatorp.match || (() => true)
176
+ const apply = typeof bridge.generatorp == 'function' ? bridge.generatorp : bridge.generatorp.apply || bridge.generatorp
177
+ const level = bridge.generatorp.level >= 0 ? bridge.generatorp.level : bridge.level + 1
83
178
  config.config.generators.unshift({
84
179
  where: bridge.generatorp.where || bridge.where || client.where(4),
85
- // match: ({context}) => bridge.id == context.marker && context.paraphrase,
86
- match: ({context}) => bridge.id == context.marker && context.level == bridge.level + 1 && context.paraphrase,
87
- apply: (args) => bridge.generatorp(args),
88
- applyWrapped: bridge.generatorp,
180
+ match: (args) => bridge.id == args.context.marker && args.context.level == level && args.context.paraphrase && match(args),
181
+ apply: (args) => apply(args),
182
+ applyWrapped: apply,
89
183
  property: 'generatorp',
90
184
  })
91
185
  }
186
+ if (bridge.generatorr) {
187
+ const match = bridge.generatorr.match || (() => true)
188
+ const apply = typeof bridge.generatorr == 'function' ? bridge.generatorr : bridge.generatorr.apply || bridge.generatorr
189
+ const level = bridge.generatorr.level >= 0 ? bridge.generatorr.level : bridge.level + 1
190
+ config.config.generators.unshift({
191
+ where: bridge.generatorr.where || bridge.where || client.where(4),
192
+ match: (args) => bridge.id == args.context.marker && args.context.level == level && !args.context.paraphrase && (args.context.response || args.context.isResponse) && match(args),
193
+ apply: (args) => apply(args),
194
+ applyWrapped: apply,
195
+ property: 'generatorr',
196
+ })
197
+ }
198
+ /*
92
199
  if (bridge.generatorr) {
93
200
  config.config.generators.unshift({
94
201
  // TODO merge response and isResponse
@@ -99,6 +206,7 @@ const handleBridgeProps = (config, bridge) => {
99
206
  property: 'generatorr',
100
207
  })
101
208
  }
209
+ */
102
210
  if (bridge.evaluator) {
103
211
  config.config.semantics.unshift({
104
212
  where: bridge.evaluator.where || bridge.where || client.where(3),
@@ -123,7 +231,7 @@ const handleBridgeProps = (config, bridge) => {
123
231
 
124
232
  const handleCalculatedProps = (baseConfig, moreConfig) => {
125
233
  for (let bridge of moreConfig.bridges) {
126
- const valid = [ 'before', 'bridge', 'development', 'evaluator', 'generatorp', 'generatorr', 'generatorpr', 'generators', 'id', 'convolution', 'inverted', 'isA', 'children', 'parents',
234
+ const valid = [ 'after', 'before', 'bridge', 'development', 'evaluator', 'generatorp', 'generatorr', 'generatorpr', 'generators', 'id', 'convolution', 'inverted', 'isA', 'children', 'parents',
127
235
  'level', 'optional', 'selector', 'semantic', 'words', /Bridge$/, 'localHierarchy', 'levelSpecificHierarchy', 'where' ]
128
236
  helpers.validProps(valid, bridge, 'bridge')
129
237
  handleBridgeProps(baseConfig, bridge)
@@ -147,6 +255,10 @@ if (runtime.process.env.DEBUG_PRIORITY) {
147
255
  global.entodictonDebugPriority = JSON.parse(runtime.process.env.DEBUG_PRIORITY)
148
256
  }
149
257
 
258
+ if (runtime.process.env.DEBUG_CONTEXTUAL_PRIORITY) {
259
+ global.entodictonDebugContextualPriority = JSON.parse(runtime.process.env.DEBUG_CONTEXTUAL_PRIORITY)
260
+ }
261
+
150
262
  if (runtime.process.env.DEBUG_ASSOCIATION) {
151
263
  global.entodictonDebugAssociation = JSON.parse(runtime.process.env.DEBUG_ASSOCIATION)
152
264
  }
@@ -157,7 +269,7 @@ if (runtime.process.env.DEBUG_BRIDGE) {
157
269
  if (global.entodictonDebugBridge.length !== 2) {
158
270
  console.log('Expected DEBUG_BRIDGE to be of the form "id/level"');
159
271
  }
160
- global.entodictonDebugBridge[1] = int(global.entodictonDebugBridge[1])
272
+ global.entodictonDebugBridge[1] = parseInt(global.entodictonDebugBridge[1])
161
273
  }
162
274
 
163
275
  if (runtime.process.env.DEBUG_OPERATOR) {
@@ -175,7 +287,7 @@ const hierarchyCanonical = (element) => {
175
287
 
176
288
  const isValidDef = (word, def, config) => {
177
289
  if (!def.id) {
178
- throw `In the KM "${config.name}", for the word ${word} the following definition is missing the "id" property: ${JSON.stringify(def)}`
290
+ throw new Error(`In the KM "${config.name}", for the word ${word} the following definition is missing the "id" property: ${JSON.stringify(def)}`)
179
291
  }
180
292
  /*
181
293
  if (!def.initial) {
@@ -465,6 +577,10 @@ const multiApiImpl = (initializer) => {
465
577
 
466
578
  class Config {
467
579
 
580
+ toServer (config) {
581
+ return config_toServer(config)
582
+ }
583
+
468
584
  inDevelopmentMode (call) {
469
585
  config.developmentModeOn += 1
470
586
  try {
@@ -524,6 +640,7 @@ class Config {
524
640
  },
525
641
  eqClasses: [],
526
642
  priorities: [], // Done
643
+ contextual_priorities: [],
527
644
  version: '3',
528
645
  debug: false,
529
646
  associations: { // Done
@@ -562,6 +679,7 @@ class Config {
562
679
  'namespaces',
563
680
  'eqClasses',
564
681
  'priorities',
682
+ 'contextual_priorities',
565
683
  'associations',
566
684
  'words',
567
685
  'floaters',
@@ -715,6 +833,11 @@ class Config {
715
833
  }
716
834
  }
717
835
 
836
+ toData (data) {
837
+ Object.assign(data, this.config)
838
+ config_toServer(data)
839
+ }
840
+
718
841
  load (template, instance, options = { rebuild: false } ) {
719
842
  this.validifyTemplate(template)
720
843
  instance.template = template
@@ -738,7 +861,7 @@ class Config {
738
861
  "semantics",
739
862
  "associations",
740
863
  ]
741
- return !properties.find( (property) => instance[property].length > 0 )
864
+ return !properties.find( (property) => instance[property] && instance[property].length > 0 )
742
865
  }
743
866
  if (!isEmpty(instance)) {
744
867
  instance.name = this.name
@@ -801,6 +924,22 @@ class Config {
801
924
  this._delta.json.priorities.push({ action: 'add', priorities })
802
925
  }
803
926
 
927
+ // [ operators: <list of [id, level]>, select: <index of prioritized operator> ]
928
+ addContextualPriority(contextual_priority) {
929
+ if (!this.config.contextual_priorities) {
930
+ this.config.contextual_priorities = []
931
+ }
932
+ if (global.entodictonDebugContextualPriority) {
933
+ if (helpers.safeEquals(entodictonDebugContextualPriority, contextual_priorities)) {
934
+ debugger; // debug hierarchy hit
935
+ }
936
+ }
937
+ contextual_priority_valid(contextual_priority)
938
+ this.config.contextual_priorities.push(contextual_priority)
939
+ const cpServer = contextual_priorities_toServer(contextual_priority)
940
+ this._delta.json.contextual_priorities.push({ action: 'add', contextual_priority: cpServer })
941
+ }
942
+
804
943
  addHierarchy (child, parent) {
805
944
  if (child && parent || !child || Array.isArray(child) || (typeof child == 'string' && !parent)) {
806
945
  this.addHierarchyChildParent(child, parent)
@@ -813,10 +952,10 @@ class Config {
813
952
  addHierarchyProperties (edge) {
814
953
  const { child, parent } = edge
815
954
  if (typeof child !== 'string') {
816
- throw `addHierarchy expected child property to be a string. got ${JSON.stringify(child)}`
955
+ throw new Error(`addHierarchy expected child property to be a string. got ${JSON.stringify(child)}`)
817
956
  }
818
957
  if (typeof parent !== 'string') {
819
- throw `addHierarchy expected parent property to be a string. got ${JSON.stringify(parent)}`
958
+ throw new Error(`addHierarchy expected parent property to be a string. got ${JSON.stringify(parent)}`)
820
959
  }
821
960
  if (global.entodictonDebugHierarchy) {
822
961
  if (helpers.safeEquals(entodictonDebugHierarchy, [child, parent])) {
@@ -830,10 +969,10 @@ class Config {
830
969
 
831
970
  addHierarchyChildParent (child, parent) {
832
971
  if (typeof child !== 'string') {
833
- throw `addHierarchy expected child to be a string. got ${JSON.stringify(child)}`
972
+ throw new Error(`addHierarchy expected child to be a string. got ${JSON.stringify(child)}`)
834
973
  }
835
974
  if (typeof parent !== 'string') {
836
- throw `addHierarchy expected parent to be a string. got ${JSON.stringify(parent)}`
975
+ throw new Error(`addHierarchy expected parent to be a string. got ${JSON.stringify(parent)}`)
837
976
  }
838
977
 
839
978
  if (global.entodictonDebugHierarchy) {
@@ -894,10 +1033,10 @@ class Config {
894
1033
  }
895
1034
 
896
1035
  if (!(typeof generator.match === 'function')) {
897
- throw 'addGenerator: Expected matcher to be a function'
1036
+ throw new Error('addGenerator: Expected matcher to be a function')
898
1037
  }
899
1038
  if (!(typeof generator.apply === 'function')) {
900
- throw 'addGenerator: Expected action to be a function'
1039
+ throw new Error('addGenerator: Expected action to be a function')
901
1040
  }
902
1041
 
903
1042
  if (!this.config.generators) {
@@ -921,10 +1060,10 @@ class Config {
921
1060
  }
922
1061
 
923
1062
  if (!(typeof semantic.match === 'function')) {
924
- throw 'addSemantic: Expected match to be a function'
1063
+ throw new Error('addSemantic: Expected match to be a function')
925
1064
  }
926
1065
  if (!(typeof semantic.apply === 'function')) {
927
- throw 'addSemantic: Expected apply to be a function'
1066
+ throw new Error('addSemantic: Expected apply to be a function')
928
1067
  }
929
1068
 
930
1069
  if (!this.config.semantics) {
@@ -1198,7 +1337,7 @@ class Config {
1198
1337
  // configs = [ { config, namespace } ... ]
1199
1338
  constructor (config, module) {
1200
1339
  if (config instanceof Config) {
1201
- throw 'Excepted the config argument to be a hash not a Config object'
1340
+ throw new Error('Excepted the config argument to be a hash not a Config object')
1202
1341
  }
1203
1342
 
1204
1343
  if (config) {
@@ -1209,6 +1348,7 @@ class Config {
1209
1348
  'operators',
1210
1349
  'words',
1211
1350
  'priorities',
1351
+ 'contextual_priorities',
1212
1352
  'associations',
1213
1353
  'name',
1214
1354
  'version',
@@ -1238,6 +1378,7 @@ class Config {
1238
1378
  config.hierarchy = config.hierarchy || []
1239
1379
  config.associations = config.associations || { negative: [], positive: [] }
1240
1380
  config.priorities = config.priorities || []
1381
+ config.contextual_priorities = config.contextual_priorities || []
1241
1382
  }
1242
1383
 
1243
1384
  this.maxDepth = 20 // for generators and semantics
@@ -1279,7 +1420,7 @@ class Config {
1279
1420
  }
1280
1421
  duplicated = Array.from(duplicated)
1281
1422
  if (duplicated.length > 0) {
1282
- throw `In the KM ${config.name}, the following operators are duplicated in the bridges: ${duplicated}`
1423
+ throw new Error(`In the KM ${config.name}, the following operators are duplicated in the bridges: ${duplicated}`)
1283
1424
  }
1284
1425
  }
1285
1426
 
@@ -1291,6 +1432,10 @@ class Config {
1291
1432
  }
1292
1433
  }
1293
1434
 
1435
+ if (config && config.contextual_priorities) {
1436
+ contextual_priorities_valid(config.contextual_priorities)
1437
+ }
1438
+
1294
1439
  normalizeConfig(config)
1295
1440
 
1296
1441
  // set the default server so stuff just works
@@ -1361,7 +1506,10 @@ class Config {
1361
1506
  }
1362
1507
 
1363
1508
  delta () {
1364
- return { cacheKey: this._delta.cacheKey, json: this._delta.json }
1509
+ return {
1510
+ cacheKey: this._delta.cacheKey,
1511
+ json: this._delta.json
1512
+ }
1365
1513
  }
1366
1514
 
1367
1515
  resetDelta (cacheKey) {
@@ -1373,6 +1521,7 @@ class Config {
1373
1521
  bridges: [],
1374
1522
  associations: [],
1375
1523
  priorities: [],
1524
+ contextual_priorities: [],
1376
1525
  hierarchy: [],
1377
1526
  }
1378
1527
  }
@@ -1394,13 +1543,13 @@ class Config {
1394
1543
  if (this._api && this._api.multiApi) {
1395
1544
  this._api.add(this, this._api, api)
1396
1545
  } else {
1397
- throw "Can only add apis to a multi-api";
1546
+ throw new Error("Can only add apis to a multi-api")
1398
1547
  }
1399
1548
  }
1400
1549
 
1401
1550
  set api (value) {
1402
1551
  if (!value.initialize) {
1403
- throw `Expected the API to have an initialize function for ${this.name}.`
1552
+ throw new Error(`Expected the API to have an initialize function for ${this.name}.`)
1404
1553
  }
1405
1554
 
1406
1555
  if (this._api && this._api.multiApi) {
@@ -1467,7 +1616,7 @@ class Config {
1467
1616
  }
1468
1617
 
1469
1618
  doMotivations (args, context) {
1470
- args = Object.assign({}, args, { context })
1619
+ args = Object.assign({}, args, { context, api: this.api })
1471
1620
  // console.log('src/config doMotivations this.uuid', this.uuid)
1472
1621
  // args.objects = args.getObjects(this.uuid)
1473
1622
  const motivations = this.motivations
@@ -1510,6 +1659,7 @@ class Config {
1510
1659
  cp.transitoryMode = this.transitoryMode
1511
1660
  cp.configs = this.configs.map((km) => km.copy2(Object.assign({}, options, { getCounter: (name) => cp.getCounter(name), callInitializers: false })))
1512
1661
  cp._uuid = cp.configs[0]._uuid
1662
+ // update uuid here set the uuid in the objects and add error checking
1513
1663
  cp.initializerFn = this.initializerFn
1514
1664
  cp.initAfterApi = this.initAfterApi
1515
1665
  cp._api = _.cloneDeep(this._api)
@@ -1665,21 +1815,23 @@ class Config {
1665
1815
  if (config instanceof Config) {
1666
1816
  // const aw = addWord(this.config, config.uuid)
1667
1817
  const aw = (word, def) => this.addWord(word, def)
1818
+ const ag = (matchOrGenerator, applyOrNothing) => this.addGenerator(matchOrGenerator, applyOrNothing)
1668
1819
  this.get('objects').namespaced[config._uuid] = objects
1669
1820
  if (config._api) {
1670
1821
  config._api.objects = objects
1671
1822
  config._api.config = () => this
1672
1823
  }
1673
- config.initializerFn({ addWord: aw, km, config, baseConfig: this, currentConfig: config, objects, namespace, uuid, api: config.api })
1824
+ config.initializerFn({ addWord: aw, addGenerator: ag, km, config, baseConfig: this, currentConfig: config, objects, namespace, uuid, api: config.api })
1674
1825
  } else {
1675
1826
  // const aw = addWord(this.config, this.uuid)
1676
1827
  const aw = (word, def) => this.addWord(word, def)
1828
+ const ag = (matchOrGenerator, applyOrNothing) => this.addGenerator(matchOrGenerator, applyOrNothing)
1677
1829
  this.get('objects').namespaced[this._uuid] = objects
1678
1830
  if (config._api) {
1679
1831
  config._api.objects = objects
1680
1832
  config._api.config = () => this
1681
1833
  }
1682
- this.initializerFn({ addWord: aw, km, config: this, baseConfig: this, currentConfig: this, objects, namespace, uuid, api: this.api })
1834
+ this.initializerFn({ addWord: aw, addGenerator: ag, km, config: this, baseConfig: this, currentConfig: this, objects, namespace, uuid, api: this.api })
1683
1835
  }
1684
1836
  })
1685
1837
  this.instances.forEach((instance) => client.processInstance(this, instance))
@@ -1689,10 +1841,11 @@ class Config {
1689
1841
  if (force || !this.wasInitialized) {
1690
1842
  // const aw = addWord(this.config, this.uuid)
1691
1843
  const aw = (word, def) => this.addWord(word, def)
1844
+ const ag = (matchOrGenerator, applyOrNothing) => this.addGenerator(matchOrGenerator, applyOrNothing)
1692
1845
  const km = (name) => this.getConfig(name)
1693
1846
  // this.initializerFn({ addWord: aw, km, config: this, baseConfig: this, currentConfig: this, objects: this.get('objects'), uuid: this._uuid, namespace: '', api: this.api })
1694
1847
  const objects = this.config.objects.namespaced[this._uuid]
1695
- this.initializerFn({ addWord: aw, km, config: this, baseConfig: this, currentConfig: this, objects, uuid: this._uuid, namespace: '', api: this.api })
1848
+ this.initializerFn({ addWord: aw, addGenerator: ag, km, config: this, baseConfig: this, currentConfig: this, objects, uuid: this._uuid, namespace: '', api: this.api })
1696
1849
  this.wasInitialized = true
1697
1850
  }
1698
1851
  }
@@ -1702,7 +1855,7 @@ class Config {
1702
1855
  for (let option of Object.keys(options)) {
1703
1856
  const validOptions = ['initAfterApi']
1704
1857
  if (!['initAfterApi'].includes(option)) {
1705
- throw `For Config.initializer, unrecognized option ${option}. The valid options are ${validOptions}`
1858
+ throw new Error(`For Config.initializer, unrecognized option ${option}. The valid options are ${validOptions}`)
1706
1859
  }
1707
1860
  }
1708
1861
  }
@@ -1910,6 +2063,7 @@ class Config {
1910
2063
  const initAfterApis = []
1911
2064
  const reverseIt = true
1912
2065
  const interleaved = true
2066
+ let isAfterApi = false
1913
2067
  this.configs.forEach((km) => {
1914
2068
  const namespace = km.namespace
1915
2069
  this.config.objects.namespaced[km._uuid] = {}
@@ -1917,6 +2071,7 @@ class Config {
1917
2071
  this.setupNamespace(km)
1918
2072
  // const aw = addWord(km.config.config ? km.config.config : km.config, km.config.uuid)
1919
2073
  const aw = (word, def) => this.addWord(word, def)
2074
+ const ag = (matchOrGenerator, applyOrNothing) => this.addGenerator(matchOrGenerator, applyOrNothing)
1920
2075
  let config = km.config
1921
2076
 
1922
2077
  if (config.addedArgss) {
@@ -1937,9 +2092,31 @@ class Config {
1937
2092
  }
1938
2093
  config.wasInitialized = false
1939
2094
  // TODO change name of config: to baseConfig:
1940
- const kmFn = (name) => this.getConfig(name)
2095
+ const kmFn = (name) => {
2096
+ const config = this.getConfig(name)
2097
+ return config
2098
+ }
1941
2099
  // const hierarchy = new DigraphInternal((config.config || {}).hierarchy)
1942
- const args = { isModule, addWord: aw, km: kmFn, hierarchy: this.hierarchy, config, baseConfig: this, currentConfig: config, uuid: config._uuid, objects: namespacedObjects, namespace, api: config.api }
2100
+ const args = new Object({
2101
+ isModule,
2102
+ addWord: aw,
2103
+ addGenerator: ag,
2104
+ km: kmFn,
2105
+ hierarchy: this.hierarchy,
2106
+ config,
2107
+ baseConfig: this,
2108
+ currentConfig: config,
2109
+ uuid: config._uuid,
2110
+ objects: namespacedObjects,
2111
+ namespace,
2112
+ motivation: (m) => config.addMotivation(m),
2113
+ get api() {
2114
+ if (!isAfterApi) {
2115
+ throw new Error("APIs should not be accessed in the initializer until after they are all initialized. Call initializer like config.initializer(fn, { initAfterApi: true }). Then the args to the initalizer will include isAfterApi which can be used to determine if the initialize is being run before or after the API's are initialized. The default is before.")
2116
+ }
2117
+ return config.api
2118
+ }
2119
+ })
1943
2120
  config.initializerFn(args)
1944
2121
  if (config.initAfterApi) {
1945
2122
  // reverse the list
@@ -1991,6 +2168,7 @@ class Config {
1991
2168
  this.config.semantics = []
1992
2169
  }
1993
2170
 
2171
+ isAfterApi = true
1994
2172
  if (!interleaved) {
1995
2173
  for (const config of addInternals) {
1996
2174
  if (!reverseIt) {
@@ -2005,7 +2183,7 @@ class Config {
2005
2183
  }
2006
2184
  for (let init of initAfterApis) {
2007
2185
  // init.args.isAfterApi = true
2008
- init.config.initializerFn({ ...init.args, kms: this.getConfigs(), isAfterApi: true })
2186
+ init.config.initializerFn({ ...init.args, kms: this.getConfigs(), isAfterApi })
2009
2187
  }
2010
2188
  this.instances.forEach((instance) => client.processInstance(this, instance))
2011
2189
  } else {
@@ -2014,6 +2192,7 @@ class Config {
2014
2192
  bridges: this.config.bridges,
2015
2193
  hierarchy: this.config.hierarchy,
2016
2194
  priorities: this.config.priorities,
2195
+ contextual_priorities: this.config.contextual_priorities,
2017
2196
  associations: this.config.associations,
2018
2197
  words: this.config.words
2019
2198
  }
@@ -2022,6 +2201,7 @@ class Config {
2022
2201
  this.config.bridges = []
2023
2202
  this.config.hierarchy = []
2024
2203
  this.config.priorities = []
2204
+ this.config.contextual_priorities = []
2025
2205
  this.config.associations = { positive: [], negative: [] }
2026
2206
  this.config.words = {}
2027
2207
 
@@ -2040,7 +2220,7 @@ class Config {
2040
2220
  }
2041
2221
  if (initAfterApis[i]) {
2042
2222
  const init = initAfterApis[i]
2043
- init.config.initializerFn({ ...init.args, kms: this.getConfigs(), isAfterApi: true })
2223
+ init.config.initializerFn({ ...init.args, kms: this.getConfigs(), isAfterApi})
2044
2224
  }
2045
2225
  const instance = this.instances.find((instance) => instance.name == name)
2046
2226
  if (instance) {
@@ -2173,11 +2353,13 @@ class Config {
2173
2353
  if (config instanceof Config) {
2174
2354
  // const aw = addWord(this.config, config.uuid)
2175
2355
  const aw = (word, def) => this.addWord(word, def)
2176
- config.initializerFn({ isModule: this.isModule, addWord: aw, baseConfig: this, km, currentConfig: config, config, objects: nsobjects, namespace, uuid, api: config.api })
2356
+ const ag = (matchOrGenerator, applyOrNothing) => this.addGenerator(matchOrGenerator, applyOrNothing)
2357
+ config.initializerFn({ isModule: this.isModule, addWord: aw, addGenerator: ag, baseConfig: this, km, currentConfig: config, config, objects: nsobjects, namespace, uuid, api: config.api })
2177
2358
  } else {
2178
2359
  // const aw = addWord(this.config, this.uuid)
2179
2360
  const aw = (word, def) => this.addWord(word, def)
2180
- this.initializerFn({ isModule: this.isModule, addWord: aw, baseConfig: this, km, currentConfig: this, config: this, objects: nsobjects, namespace, uuid, api: this.api })
2361
+ const ag = (matchOrGenerator, applyOrNothing) => this.addGenerator(matchOrGenerator, applyOrNothing)
2362
+ this.initializerFn({ isModule: this.isModule, addWord: aw, addGenerator: ag, baseConfig: this, km, currentConfig: this, config: this, objects: nsobjects, namespace, uuid, api: this.api })
2181
2363
  }
2182
2364
  })
2183
2365
  }
@@ -2242,6 +2424,20 @@ class Config {
2242
2424
  config.priorities = priorities
2243
2425
  }
2244
2426
 
2427
+ if (config.contextual_priorities) {
2428
+ let contextual_priorities = config.contextual_priorities
2429
+ contextual_priorities = contextual_priorities.map((cp) => {
2430
+ const { context, choose } = cp
2431
+ return {
2432
+ context: context.map((id) => {
2433
+ return [toNS(id[0]), id[1]]
2434
+ }),
2435
+ choose
2436
+ }
2437
+ })
2438
+ config.contextual_priorities = contextual_priorities
2439
+ }
2440
+
2245
2441
  for (const bag of bags) {
2246
2442
  if (config[bag]) {
2247
2443
  config[bag] = config[bag].map((b) => {
@@ -2327,14 +2523,14 @@ class Config {
2327
2523
 
2328
2524
  set (property, value) {
2329
2525
  if (!this.config.hasOwnProperty(property)) {
2330
- throw `Setting invalid property ${property}`
2526
+ throw new Error(`Setting invalid property ${property}`)
2331
2527
  }
2332
2528
 
2333
2529
  if ('words' == property) {
2334
2530
  for (let word in value) {
2335
2531
  for (let def of value[word]) {
2336
2532
  if (!def['uuid']) {
2337
- throw `All definitions for '${property}' must have the uuid property set (config.uuid). uuid is missing from ${JSON.stringify(def)} for the word '${word}'`
2533
+ throw new Error(`All definitions for '${property}' must have the uuid property set (config.uuid). uuid is missing from ${JSON.stringify(def)} for the word '${word}'`)
2338
2534
  }
2339
2535
  }
2340
2536
  }
@@ -2343,7 +2539,7 @@ class Config {
2343
2539
  if (['operators', 'bridges'].includes(property)) {
2344
2540
  for (let def of value) {
2345
2541
  if (!def['uuid']) {
2346
- throw `All definitions for '${property}' must have the uuid property set (config.uuid). uuid is missing from ${JSON.stringify(def)}`
2542
+ throw new Error(`All definitions for '${property}' must have the uuid property set (config.uuid). uuid is missing from ${JSON.stringify(def)}`)
2347
2543
  }
2348
2544
  }
2349
2545
  }
@@ -2375,7 +2571,7 @@ class Config {
2375
2571
 
2376
2572
  add (more) {
2377
2573
  if (more === this) {
2378
- throw 'Cannot add an object to itself.'
2574
+ throw new Error('Cannot add an object to itself.')
2379
2575
  }
2380
2576
  if (!(more instanceof Config)) {
2381
2577
  more = new Config(more)
@@ -2543,7 +2739,7 @@ class Config {
2543
2739
  this.config[key] = this.config[key].concat(more[key])
2544
2740
  } else {
2545
2741
  if (!(key in this.config)) {
2546
- throw `Unexpected property in config ${key}`
2742
+ throw new Error(`Unexpected property in config ${key}`)
2547
2743
  }
2548
2744
  this.config[key] = more[key]
2549
2745
  }
@@ -2661,7 +2857,7 @@ class Config {
2661
2857
  this.config[key] = more[key].concat(this.config[key])
2662
2858
  } else {
2663
2859
  if (!(key in this.config)) {
2664
- throw `Unexpected property in config ${key}`
2860
+ throw new Error(`Unexpected property in config ${key}`)
2665
2861
  }
2666
2862
  this.config[key] = more[key]
2667
2863
  }
@@ -2671,5 +2867,7 @@ class Config {
2671
2867
  }
2672
2868
 
2673
2869
  module.exports = {
2674
- Config
2870
+ Config,
2871
+ config_toServer,
2872
+ operatorKey_valid,
2675
2873
  }
package/src/generators.js CHANGED
@@ -75,7 +75,7 @@ class Generator {
75
75
 
76
76
  apply (baseArgs, objects, g, gs, context, hierarchy, config, response, log, options = {}) {
77
77
  if (!log) {
78
- throw 'generators.apply argument log is required'
78
+ throw new Error('generators.apply argument log is required')
79
79
  }
80
80
  if (baseArgs.call && config && sbaseArgs.calls.stack.length > config.maxDepth) {
81
81
  throw new Error(`Max depth of ${config.maxDepth} for calls has been exceeded. maxDepth can be set on the config object. To see the calls run with the --dl or set the debugLoops property on the config`)
@@ -292,7 +292,7 @@ class Generators {
292
292
  lines.setElement(0, 2, JSON.stringify(context, null, 2))
293
293
  this.logs.push(lines.toString())
294
294
  }
295
- contextsPrime.push(generated)
295
+ contextsPrime.push((config || {}).parenthesized ? "(" + generated + ")" : generated)
296
296
  }
297
297
  return contextsPrime
298
298
  }
package/src/helpers.js CHANGED
@@ -54,6 +54,9 @@ const safeEquals = (v1, v2) => {
54
54
  } else if (type == 'function') {
55
55
  return v1.toString() == v2.toString()
56
56
  } else {
57
+ if (v1.length != v2.length) {
58
+ return false
59
+ }
57
60
  for (let key in v1) {
58
61
  if (!safeEquals(v1[key], v2[key])) {
59
62
  return false
@@ -235,13 +238,17 @@ const validProps = (valids, object, type) => {
235
238
  for (let prop of Object.keys(object)) {
236
239
  let okay = false
237
240
  for (valid of valids) {
238
- if (prop.match(valid)) {
239
- okay = true
241
+ if (typeof valid == 'string') {
242
+ okay = prop == valid
243
+ } else {
244
+ okay = prop.match(valid)
245
+ }
246
+ if (okay) {
240
247
  break
241
248
  }
242
249
  }
243
250
  if (!okay) {
244
- throw `Unknown property "${prop}" in the ${type}. Valid properties are ${valids}. The ${type} is ${JSON.stringify(object)}`
251
+ throw new Error(`Unknown property "${prop}" in the ${type}. Valid properties are ${valids}. The ${type} is ${JSON.stringify(object)}`)
245
252
  }
246
253
  }
247
254
  }
package/src/semantics.js CHANGED
@@ -89,7 +89,7 @@ class Semantic {
89
89
  // const ask = baseArgs.getAsk(this.uuid)
90
90
  if (!log) {
91
91
  console.trace()
92
- throw 'log is a required argument'
92
+ throw new Error('log is a required argument')
93
93
  }
94
94
  const contextPrime = Object.assign({}, context)
95
95
  let n = (id) => id