theprogrammablemind 7.4.0 → 7.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/client.js CHANGED
@@ -12,14 +12,16 @@ const { appendNoDups, InitCalls } = require('./src/helpers')
12
12
  const runtime = require('./runtime')
13
13
  const sortJson = runtime.sortJson
14
14
 
15
- const ask = (config) => (asks) => {
15
+ const getAsk = (config) => (uuid) => (asks) => {
16
16
  for (let ask of asks) {
17
17
  config.addMotivation({
18
+ uuid,
18
19
  match: (args) => ask.matchr(args),
19
20
  apply: (args) => ask.applyr(args)
20
21
  })
21
22
  }
22
23
  config.addMotivation({
24
+ uuid,
23
25
  match: ({context}) => context.marker == 'controlEnd' || context.marker == 'controlBetween',
24
26
  apply: (args) => {
25
27
  for (let ask of asks) {
@@ -100,7 +102,25 @@ const setupArgs = (args, config, logs, hierarchy) => {
100
102
  args.listable = listable(hierarchy)
101
103
  args.asList = asList
102
104
  args.retry = () => { throw new RetryError() }
103
- args.ask = ask(config)
105
+ const scopedAsk = getAsk(config)
106
+
107
+ const getAPI = (uuid) => {
108
+ if (config && config.getAPI) {
109
+ return config.getAPI(uuid)
110
+ }
111
+ }
112
+ const getAPIs = (uuid) => {
113
+ if (config && config.getAPIs) {
114
+ return config.getAPIs(uuid)
115
+ }
116
+ }
117
+ args.getUUIDScoped = (uuid) => {
118
+ return {
119
+ ask: scopedAsk(uuid),
120
+ api: getAPI(uuid),
121
+ apis: getAPIs(uuid)
122
+ }
123
+ }
104
124
  args.motivation = (m) => config.addMotivation(m)
105
125
  args.s = (c) => config.getSemantics(logs).apply(args, c)
106
126
  args.g = (c) => config.getGenerators(logs).apply(args, c)
@@ -174,11 +194,13 @@ const processContexts = (contexts, params) => {
174
194
  return { contexts: contextsPrime, generated, logs }
175
195
  }
176
196
 
177
- const getObjects = (objects) => (uuid) => {
178
- if (objects && objects.namespaced) {
179
- objects = objects.namespaced[uuid]
197
+ const getObjects = (objects) => {
198
+ return (uuid) => {
199
+ if (objects && objects.namespaced) {
200
+ return objects.namespaced[uuid]
201
+ }
202
+ return objects
180
203
  }
181
- return objects
182
204
  }
183
205
 
184
206
  const processContext = (context, { objects = {}, config, logs = [] }) => {
@@ -484,7 +506,7 @@ const processInstance = (config, instance) => {
484
506
  global.transitoryMode = transitoryMode
485
507
  }
486
508
 
487
- const _process = async (config, query, { credentials, writeTests, isTest, saveDeveloper, testConfig, testsFN, errorHandler = defaultErrorHandler, beforeQuery } = {}) => {
509
+ const _process = async (config, query, { credentials, writeTests, isTest, saveDeveloper, testConfig, testsFN, errorHandler = defaultErrorHandler } = {}) => {
488
510
  if (credentials) {
489
511
  config.server(credentials.server, credentials.key)
490
512
  }
@@ -497,7 +519,7 @@ const _process = async (config, query, { credentials, writeTests, isTest, saveDe
497
519
  if (writeTests) {
498
520
  config.rebuild()
499
521
  const objects = getObjects(config.config.objects)(config.uuid)
500
- beforeQuery({ query, isModule: false, objects })
522
+ config.beforeQuery({ query, isModule: false, objects })
501
523
  }
502
524
  } catch(error) {
503
525
  throw error
@@ -598,7 +620,7 @@ const getConfigForTest = (config, testConfig) => {
598
620
  return configForTest
599
621
  }
600
622
 
601
- const runTest = async (config, expected, { verbose, beforeQuery, afterTest, testConfig, debug }) => {
623
+ const runTest = async (config, expected, { verbose, afterTest, testConfig, debug }) => {
602
624
  const test = expected.query
603
625
  // initialize in between test so state is not preserved since the test was adding without state
604
626
  config.rebuild()
@@ -616,7 +638,7 @@ const runTest = async (config, expected, { verbose, beforeQuery, afterTest, test
616
638
  }
617
639
 
618
640
  const objects = getObjects(config.config.objects)(config.uuid)
619
- beforeQuery({ query: test, isModule: false, objects })
641
+ config.beforeQuery({ query: test, isModule: false, objects })
620
642
  config.resetMotivations()
621
643
  try {
622
644
  const result = await _process(config, test, { errorHandler, isTest: true })
@@ -642,8 +664,8 @@ const runTest = async (config, expected, { verbose, beforeQuery, afterTest, test
642
664
  const failed_config = !matching(actual_config, expected_config)
643
665
  let failed = failed_paraphrases || failed_responses || failed_contexts || failed_objects || failed_config
644
666
  if (!failed) {
645
- if (afterTest) {
646
- failed = afterTest({ query: test, expected, actual: result, config })
667
+ if (config.afterTest) {
668
+ failed = config.afterTest({ query: test, expected, actual: result, config })
647
669
  if (failed) {
648
670
  return {
649
671
  utterance: test,
@@ -703,21 +725,20 @@ const runTestsHelper = async (config, tests, failed, juicyBits) => {
703
725
 
704
726
  const runTests = async (config, testFile, juicyBits) => {
705
727
  const tests = JSON.parse(runtime.fs.readFileSync(testFile))
706
- const { beforeTests, afterTests } = juicyBits
707
- beforeTests()
728
+ config.beforeTests()
708
729
  if (juicyBits.verbose) {
709
730
  console.log('\n', testFile, '-----------------------------------------------', '\n')
710
731
  }
711
732
  const v = await runTestsHelper(config, [...tests], [], juicyBits)
712
- afterTests()
733
+ config.afterTests()
713
734
  return v
714
735
  }
715
736
 
716
- const saveTest = async (testFile, config, test, expected, beforeQuery, testConfig, saveDeveloper) => {
737
+ const saveTest = async (testFile, config, test, expected, testConfig, saveDeveloper) => {
717
738
  config.rebuild()
718
739
  const objects = getObjects(config.config.objects)(config.uuid)
719
740
  config.resetMotivations()
720
- beforeQuery({ query: test, isModule: false, objects })
741
+ config.beforeQuery({ query: test, isModule: false, objects })
721
742
  console.log(test)
722
743
  const result = await _process(config, test, { isTest: true })
723
744
  // const actualObjects = config.config.objects
@@ -725,23 +746,23 @@ const saveTest = async (testFile, config, test, expected, beforeQuery, testConfi
725
746
  writeTest(testFile, test, config.config.objects, result.generated, result.paraphrases, result.responses, result.contexts, result.associations, result.metadata, actualConfig, saveDeveloper)
726
747
  }
727
748
 
728
- const saveTestsHelper = async (testFile, config, tests, todo, beforeQuery, testConfig, saveDeveloper) => {
749
+ const saveTestsHelper = async (testFile, config, tests, todo, testConfig, saveDeveloper) => {
729
750
  if (todo.length === 0) {
730
751
  return
731
752
  }
732
753
  const test = todo.pop()
733
754
  config.rebuild()
734
- const result = await saveTest(testFile, config, test, tests[test], beforeQuery, testConfig, saveDeveloper)
755
+ const result = await saveTest(testFile, config, test, tests[test], testConfig, saveDeveloper)
735
756
  // initialize in between test so state is not preserved since the test was adding without state
736
757
  // config.initialize({force: true})
737
758
  config.rebuild()
738
- return saveTestsHelper(testFile, config, tests, todo, beforeQuery, testConfig, saveDeveloper)
759
+ return saveTestsHelper(testFile, config, tests, todo, testConfig, saveDeveloper)
739
760
  }
740
761
 
741
- const saveTests = (config, testFile, beforeQuery, testConfig) => {
762
+ const saveTests = (config, testFile, testConfig) => {
742
763
  const tests = JSON.parse(runtime.fs.readFileSync(testFile))
743
764
  console.log(testFile)
744
- return saveTestsHelper(testFile, config, tests, tests.map( (test) => test.query ), beforeQuery, testConfig)
765
+ return saveTestsHelper(testFile, config, tests, tests.map( (test) => test.query ), testConfig)
745
766
  }
746
767
 
747
768
  /*
@@ -962,7 +983,7 @@ entodicton.knowledgeModule( {
962
983
  `
963
984
  */
964
985
 
965
- const build = async ({ config, target, beforeQuery, template, errorHandler = defaultErrorHandler }) => {
986
+ const build = async ({ config, target, template, errorHandler = defaultErrorHandler }) => {
966
987
  const accumulators = {
967
988
  resultss: [],
968
989
  fragments: [],
@@ -1000,7 +1021,7 @@ const build = async ({ config, target, beforeQuery, template, errorHandler = def
1000
1021
  }
1001
1022
 
1002
1023
  try {
1003
- const results = await _process(config, query.query, { beforeQuery })
1024
+ const results = await _process(config, query.query, {})
1004
1025
  if (config.config.debug) {
1005
1026
  // TODO pass in the error handler like the other ones
1006
1027
  defaultInnerProcess(config, defaultErrorHandler, results)
@@ -1097,11 +1118,40 @@ const knowledgeModule = async ({
1097
1118
  afterTest = () => {}
1098
1119
  } = {}) => {
1099
1120
 
1100
- const isProcess = require.main === moduleFromJSFile
1121
+ config.beforeQuery = beforeQuery
1122
+ config.beforeTests = beforeTests
1123
+ config.afterTests = afterTests
1124
+ config.beforeTest = beforeTest
1125
+ config.afterTest = afterTest
1126
+
1101
1127
  const testConfig = test
1102
1128
 
1129
+ if (!moduleFromJSFile) {
1130
+ 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."
1131
+ }
1132
+ if (!config) {
1133
+ throw "'config' is a required parameter. The value should the config that defines the knowledge module."
1134
+ }
1135
+ if (!config.name) {
1136
+ throw "config must have 'name' set to the knowledge module name."
1137
+ }
1138
+ if (!description) {
1139
+ throw "'description' is a required parameter. The value should the description of the knowledge module."
1140
+ }
1141
+ if (!test) {
1142
+ 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> }."
1143
+ }
1144
+
1145
+ const isProcess = require.main === moduleFromJSFile
1146
+ let loadForTesting = false
1147
+ if (global.theprogrammablemind) {
1148
+ if (global.theprogrammablemind.loadForTesting[config.name]) {
1149
+ loadForTesting = true
1150
+ }
1151
+ }
1152
+
1103
1153
  // remove test only stuff
1104
- if (!isProcess) {
1154
+ if (!isProcess && !loadForTesting) {
1105
1155
  config.config.operators = config.config.operators.filter( (operator) => {
1106
1156
  if (operator.development) {
1107
1157
  return false
@@ -1118,22 +1168,6 @@ const knowledgeModule = async ({
1118
1168
  })
1119
1169
  }
1120
1170
 
1121
- if (!moduleFromJSFile) {
1122
- 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."
1123
- }
1124
- if (!config) {
1125
- throw "'config' is a required parameter. The value should the config that defines the knowledge module."
1126
- }
1127
- if (!config.name) {
1128
- throw "config must have 'name' set to the knowledge module name."
1129
- }
1130
- if (!description) {
1131
- throw "'description' is a required parameter. The value should the description of the knowledge module."
1132
- }
1133
- if (!test) {
1134
- 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> }."
1135
- }
1136
-
1137
1171
  let module
1138
1172
  if (_.isFunction(moduleFromJSFile)) {
1139
1173
  module = moduleFromJSFile
@@ -1172,6 +1206,7 @@ const knowledgeModule = async ({
1172
1206
  description: 'Entodicton knowledge module'
1173
1207
  })
1174
1208
 
1209
+ parser.add_argument('-tfn', '--testFileName', { help: 'Override the test file for the module when the tests are being run' })
1175
1210
  parser.add_argument('-t', '--test', { action: 'store_true', help: 'Run the tests. Create tests by running with the --query + --save flag' })
1176
1211
  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' })
1177
1212
  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' })
@@ -1366,9 +1401,8 @@ const knowledgeModule = async ({
1366
1401
 
1367
1402
  if (!args.query && !args.test && !args.info && (args.save || args.saveDeveloper)) {
1368
1403
  global.transitoryMode = true
1369
- saveTests(config, test, beforeQuery, testConfig, args.saveDeveloper)
1404
+ saveTests(config, test, testConfig, args.saveDeveloper)
1370
1405
  // } else if (args.build) {
1371
- // build({ config, target: args.build, beforeQuery, errorHandler })
1372
1406
  } else if (args.info) {
1373
1407
  showInfo(description, section, config)
1374
1408
  } else if (args.test || args.testVerbose || args.testAllVerbose) {
@@ -1381,7 +1415,7 @@ const knowledgeModule = async ({
1381
1415
  }
1382
1416
  return
1383
1417
  }
1384
- runTests(config, test, { debug: args.debug, testConfig: testConfig, verbose: args.testVerbose || args.testAllVerbose, stopAtFirstError: !args.testAllVerbose, beforeQuery, beforeTests, afterTests, beforeTest, afterTest }).then((results) => {
1418
+ runTests(config, args.testFileName ? `${args.testFileName}.test.json` : test, { debug: args.debug, testConfig: testConfig, verbose: args.testVerbose || args.testAllVerbose, stopAtFirstError: !args.testAllVerbose }).then((results) => {
1385
1419
  if (results.length > 0 && args.vimdiff) {
1386
1420
  for (const result of results) {
1387
1421
  vimdiff(result.expected, result.actual)
@@ -1454,9 +1488,9 @@ const knowledgeModule = async ({
1454
1488
  if (args.objectDiff) {
1455
1489
  global.beforeObjects = _.cloneDeep(objects)
1456
1490
  }
1457
- beforeQuery({ query: args.query, isModule: false, objects })
1491
+ config.beforeQuery({ query: args.query, isModule: false, objects })
1458
1492
  try {
1459
- processResults(_process(config, args.query, { dontAddAssociations: args.dontAddAssociations, writeTests: args.save || args.saveDeveloper, saveDeveloper: args.saveDeveloper, testConfig, testsFN: test, beforeQuery }))
1493
+ processResults(_process(config, args.query, { dontAddAssociations: args.dontAddAssociations, writeTests: args.save || args.saveDeveloper, saveDeveloper: args.saveDeveloper, testConfig, testsFN: test }))
1460
1494
  } catch( error ) {
1461
1495
  console.log('Error', error);
1462
1496
  }
package/package.json CHANGED
@@ -61,6 +61,6 @@
61
61
  "json-stable-stringify": "^1.0.1",
62
62
  "node-fetch": "^2.6.1"
63
63
  },
64
- "version": "7.4.0",
64
+ "version": "7.4.1",
65
65
  "license": "ISC"
66
66
  }
package/src/config.js CHANGED
@@ -767,6 +767,23 @@ class Config {
767
767
  }
768
768
  }
769
769
 
770
+ getAPIs (uuid) {
771
+ let config
772
+ if (this._uuid === uuid) {
773
+ config = this
774
+ } else {
775
+ for (const km of this.configs) {
776
+ if (km._uuid === uuid) {
777
+ config = km.config
778
+ break
779
+ }
780
+ }
781
+ }
782
+ if (config && config._api && config._api.multiApi) {
783
+ return config._api.apis
784
+ }
785
+ }
786
+
770
787
  getServer() {
771
788
  return this._server
772
789
  }
@@ -888,6 +905,19 @@ class Config {
888
905
  return configs;
889
906
  }
890
907
 
908
+ getConfigByUUID (uuid) {
909
+ if (this.uuid === uuid) {
910
+ return this
911
+ }
912
+ for (const config of this.configs) {
913
+ if (config.config instanceof Config) {
914
+ if (config.uuid === uuid) {
915
+ return config.config
916
+ }
917
+ }
918
+ }
919
+ }
920
+
891
921
  getConfig (name) {
892
922
  if (this.name === name) {
893
923
  return this
@@ -932,7 +962,13 @@ class Config {
932
962
  }
933
963
 
934
964
  this.addedArgss = []
935
- const isProcess = require.main === module
965
+ let isProcess = require.main === module
966
+ if (global.theprogrammablemind && config) {
967
+ if (global.theprogrammablemind.loadForTesting[config.name]) {
968
+ isProcess = true
969
+ this.loadedForTesting = true
970
+ }
971
+ }
936
972
  this.isModule = !isProcess
937
973
  if (this.isModule) {
938
974
  this.removeDevelopmentElements(config)
@@ -1198,6 +1234,9 @@ class Config {
1198
1234
 
1199
1235
  // motivation === { match, apply, uuid }
1200
1236
  addMotivation (motivation) {
1237
+ if (!motivation.uuid) {
1238
+ motivation.uuid = this.uuid
1239
+ }
1201
1240
  this.motivations.push(motivation)
1202
1241
  }
1203
1242
 
@@ -1207,11 +1246,13 @@ class Config {
1207
1246
 
1208
1247
  doMotivations (args, context) {
1209
1248
  args = Object.assign({}, args, { context })
1210
- args.objects = args.getObjects(this.uuid)
1249
+ // console.log('src/config doMotivations this.uuid', this.uuid)
1250
+ // args.objects = args.getObjects(this.uuid)
1211
1251
  const motivations = this.motivations
1212
1252
  this.motivations = []
1213
1253
  let done = false
1214
1254
  for (const motivation of motivations) {
1255
+ args.objects = args.getObjects(motivation.uuid)
1215
1256
  if (!done && motivation.match(args)) {
1216
1257
  motivation.apply(args)
1217
1258
  if (args.context.controlKeepMotivation || motivation.repeat) {
@@ -1255,6 +1296,7 @@ class Config {
1255
1296
  cp.tests = this.tests
1256
1297
  cp.motivations = this.motivations
1257
1298
  cp.isModule = this.isModule
1299
+ cp.loadedForTesting = this.loadedForTesting
1258
1300
  cp.initInstances = this.initInstances.slice()
1259
1301
  cp.instances = this.instances.slice()
1260
1302
  cp.configCounter = this.configCounter
@@ -1603,6 +1645,12 @@ class Config {
1603
1645
  // already set
1604
1646
  // this.isModule = this.isModule || mainIsModule
1605
1647
  mainIsModule = (mainIsModule === undefined) ? this.isModule : mainIsModule
1648
+ if (mainIsModule !== undefined) {
1649
+ this.isModule = mainIsModule
1650
+ }
1651
+ if (this.loadedForTesting) {
1652
+ this.isModule = false
1653
+ }
1606
1654
  this.config.objects.namespaced = {}
1607
1655
  this.resetWasInitialized()
1608
1656
 
@@ -1640,7 +1688,9 @@ class Config {
1640
1688
  if (!(config instanceof Config)) {
1641
1689
  config = this
1642
1690
  isSelf = true
1643
- isModule = mainIsModule
1691
+ isModule = config.isModule || mainIsModule
1692
+ } else {
1693
+ isModule = config.isModule
1644
1694
  }
1645
1695
  if (!isSelf) {
1646
1696
  config.config = _.cloneDeep(config.initConfig)
package/src/generators.js CHANGED
@@ -59,7 +59,7 @@ class Generator {
59
59
  api: this.getAPI(config),
60
60
  apis: this.getAPIs(config)
61
61
  }
62
- const args = Object.assign({}, baseArgs, moreArgs)
62
+ const args = Object.assign({}, baseArgs, moreArgs, (baseArgs.getUUIDScoped || (() => { return {} }))(this.uuid))
63
63
  // return this.match(args)
64
64
  const matches = this.match(args)
65
65
  if ((matches && (options.debug || {}).match)
@@ -106,7 +106,7 @@ class Generator {
106
106
  api: this.getAPI(config),
107
107
  apis: this.getAPIs(config)
108
108
  }
109
- const args = Object.assign({}, baseArgs, moreArgs)
109
+ const args = Object.assign({}, baseArgs, moreArgs, (baseArgs.getUUIDScoped || (() => { return {} }))(this.uuid))
110
110
  // if (this.callId) {
111
111
  // greg
112
112
  /*
package/src/semantics.js CHANGED
@@ -45,13 +45,16 @@ class Semantic {
45
45
  matches (baseArgs, context, options = {}) {
46
46
  const hierarchy = baseArgs.hierarchy
47
47
  const config = baseArgs.config
48
+
48
49
  const objects = baseArgs.getObjects(this.uuid)
50
+ // const ask = baseArgs.getAsk(this.uuid)
51
+
49
52
  // return this.matcher(Object.assign({}, argsBase, {args: contextArgs(context, hierarchy), objects: objects, global: objects, context: context, hierarchy: hierarchy, api: this.getAPI(config)})
50
53
  const callId = baseArgs.calls.current()
51
54
  const moreArgs = {
52
55
  uuid: this.uuid,
53
56
  args: contextArgs(context, hierarchy),
54
- objects: objects,
57
+ objects,
55
58
  global: objects,
56
59
  context: context,
57
60
  // hierarchy: hierarchy,
@@ -59,7 +62,7 @@ class Semantic {
59
62
  api: this.getAPI(config),
60
63
  apis: this.getAPIs(config)
61
64
  }
62
- const args = Object.assign({}, baseArgs, moreArgs)
65
+ const args = Object.assign({}, baseArgs, moreArgs, (baseArgs.getUUIDScoped || (() => { return {} }))(this.uuid))
63
66
 
64
67
  const matches = this.matcher(args)
65
68
  if (matches && (options.debug || {}).match
@@ -74,6 +77,7 @@ class Semantic {
74
77
  apply (baseArgs, context, s, log, options = {}) {
75
78
  const { hierarchy, config, response } = baseArgs
76
79
  const objects = baseArgs.getObjects(this.uuid)
80
+ // const ask = baseArgs.getAsk(this.uuid)
77
81
  if (!log) {
78
82
  console.trace()
79
83
  throw 'log is a required argument'
@@ -99,7 +103,7 @@ class Semantic {
99
103
  api: this.getAPI(config),
100
104
  apis: this.getAPIs(config)
101
105
  }
102
- const args = Object.assign({}, baseArgs, moreArgs)
106
+ const args = Object.assign({}, baseArgs, moreArgs, (baseArgs.getUUIDScoped || (() => { return {} }))(this.uuid))
103
107
  if ((options.debug || {}).apply
104
108
  ||
105
109
  callId == this.callId) {