theprogrammablemind 8.0.0 → 8.1.0-beta.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.
@@ -0,0 +1,455 @@
1
+ const { InitCalls } = require('./helpers')
2
+ const DigraphInternal = require('./digraph_internal')
3
+
4
+ const gs = (g) => async (contexts, separator, lastSeparator) => {
5
+ if (!Array.isArray(contexts)) {
6
+ throw new Error('Expected a list')
7
+ }
8
+
9
+ let s = ''
10
+ if (!separator) {
11
+ separator = ' '
12
+ }
13
+ if (!lastSeparator) {
14
+ lastSeparator = separator
15
+ }
16
+ let nextSeparator = ''
17
+ for (let i = 0; i < contexts.length; ++i) {
18
+ const context = contexts[i]
19
+ const value = await g(context)
20
+ if (i > 0) {
21
+ if (i === contexts.length - 1) {
22
+ nextSeparator = lastSeparator
23
+ } else {
24
+ nextSeparator = separator
25
+ }
26
+ }
27
+ s += nextSeparator + value
28
+ }
29
+ return s
30
+ }
31
+
32
+ const asList = (context) => {
33
+ if (context.marker === 'list') {
34
+ return context
35
+ }
36
+ return {
37
+ marker: 'list',
38
+ types: [context.marker],
39
+ value: [context]
40
+ }
41
+ }
42
+
43
+ const isA = (hierarchy) => (child, parent) => {
44
+ if (!child || !parent) {
45
+ return false
46
+ }
47
+ if (child.marker) {
48
+ child = child.marker
49
+ }
50
+ if (parent.marker) {
51
+ parent = parent.marker
52
+ }
53
+ return hierarchy.isA(child, parent)
54
+ }
55
+
56
+ class ErrorReason extends Error {
57
+ constructor (context) {
58
+ super(JSON.stringify(context))
59
+ this.reason = context
60
+ }
61
+ }
62
+
63
+ const listable = (hierarchy) => (c, type) => {
64
+ if (!c) {
65
+ return false
66
+ }
67
+ if (hierarchy.isA(c.marker, type)) {
68
+ return true
69
+ }
70
+ if (c.marker === 'list') {
71
+ for (const t of c.types) {
72
+ if (hierarchy.isA(t, type)) {
73
+ return true
74
+ }
75
+ }
76
+ }
77
+ return false
78
+ }
79
+
80
+ const cleanAssign = (dest, ...srcs) => {
81
+ for (const key in dest) {
82
+ let found = false
83
+ for (const src of srcs) {
84
+ if (src[key]) {
85
+ found = true
86
+ break
87
+ }
88
+ }
89
+ if (!found) {
90
+ delete dest[key]
91
+ }
92
+ }
93
+ Object.assign(dest, ...srcs)
94
+ }
95
+
96
+ const setupArgs = (args, config, logs, hierarchy, uuidForScoping) => {
97
+
98
+ // callId
99
+ args.calls = new InitCalls(args.isInstance ? `${args.isInstance}#${config.name}` : config.name)
100
+ if (global.theprogrammablemind && global.theprogrammablemind.loadForTesting) {
101
+ args.calls = new InitCalls(Object.keys(global.theprogrammablemind.loadForTesting)[0])
102
+ }
103
+ args.cleanAssign = cleanAssign
104
+ args.km = (name) => config.getConfig(name)
105
+ args.api = (name) => config.getConfig(name).api
106
+ args.error = (context) => {
107
+ throw new ErrorReason(context)
108
+ }
109
+ args.kms = config.getConfigs()
110
+ args.config = config
111
+ args.hierarchy = hierarchy
112
+ args.isA = isA(hierarchy)
113
+ args.listable = listable(hierarchy)
114
+ args.asList = asList
115
+ args.retry = () => { throw new RetryError() }
116
+ args.fragments = (query) => {
117
+ return config.fragment(args, query)
118
+ }
119
+ args.breakOnSemantics = false
120
+ args.theDebugger = {
121
+ breakOnSemantics: (value) => args.breakOnSemantics = value
122
+ }
123
+ if (!logs) {
124
+ }
125
+ args.log = (message) => logs.push(message)
126
+
127
+ args.addAssumedScoped = (args, assumed) => {
128
+ const addAssumed = (args, ...moreAssumed) => {
129
+ return { ...args, assumed: Object.assign({}, assumed, (args.assumed || {}), ...moreAssumed) }
130
+ }
131
+
132
+ args.s = (c) => config.getSemantics(logs).apply(args, c)
133
+ args.g = (c, a = {}) => {
134
+ return config.getGenerators(logs).apply(addAssumed(args, a), c, a)
135
+ }
136
+ args.gp = (c, a = {}) => {
137
+ return config.getGenerators(logs).apply(addAssumed(args, a, { paraphrase: true, isResponse: false, response: false }), c, { paraphrase: true, isResponse: false, response: false })
138
+ }
139
+ args.gr = (c, a = {}) => {
140
+ return config.getGenerators(logs).apply(addAssumed(args, a, { paraphrase: false, isResponse: true }), { ...c, paraphrase: false, isResponse: true })
141
+ }
142
+ args.e = (c) => {
143
+ return config.getEvaluator(args.s, args.calls, logs, c)
144
+ }
145
+ args.gs = gs(args.g)
146
+ args.gsp = gs(args.gp)
147
+ args.gsr = gs(args.gr)
148
+ }
149
+ // for semantics
150
+ args.addAssumedScoped(args, {})
151
+
152
+ const getAPI = (uuid) => {
153
+ if (config && config.getAPI) {
154
+ return config.getAPI(uuid)
155
+ }
156
+ }
157
+ const getAPIs = (uuid) => {
158
+ if (config && config.getAPIs) {
159
+ return config.getAPIs(uuid)
160
+ }
161
+ }
162
+ args.getUUIDScoped = (uuid) => {
163
+ return {
164
+ api: getAPI(uuid),
165
+ apis: getAPIs(uuid)
166
+ }
167
+ }
168
+ config.getAddedArgs(args)
169
+
170
+ Object.assign(args, args.getUUIDScoped(uuidForScoping || config.uuid))
171
+ /*
172
+ if (uuidForScoping) {
173
+ Object.assign(args, args.getUUIDScoped(uuidForScoping))
174
+ }
175
+ */
176
+ // sets args for all the API. that make a copy so the args must be fully setup by here except for scoped
177
+ config.setArgs(args)
178
+ }
179
+
180
+ const getObjects = (objects) => {
181
+ return (uuid) => {
182
+ if (objects && objects.namespaced) {
183
+ return objects.namespaced[uuid]
184
+ }
185
+ return objects
186
+ }
187
+ }
188
+
189
+ const processContext = async (context, { objects = {}, config, logs = [] }) => {
190
+ const generators = config.getGenerators(logs)
191
+ const semantics = config.getSemantics(logs)
192
+
193
+ // map to hash
194
+ config = config || {}
195
+ if (config.config) {
196
+ config = config
197
+ }
198
+
199
+ const response = {} // NA but passed in
200
+ // generators = new Generators(generators.map((g) => new Generator(normalizeGenerator(g))))
201
+ // semantics = new Semantics(semantics.map((g) => new Semantic(normalizeSemantic(g))))
202
+ const hierarchy = new DigraphInternal((config.config || {}).hierarchy || [])
203
+
204
+ const args = { objects, response, getObjects: getObjects(objects) }
205
+ setupArgs(args, config, logs, hierarchy)
206
+
207
+ context = await semantics.apply(args, context)
208
+ const generated = await generators.apply(args, context)
209
+ const assumed = { paraphrase: true, response: false, isResponse: false }
210
+ const paraphrases = await generators.apply({ ...args, assumed }, context, { paraphrase: true, response: false, isResponse: false })
211
+ let responses = []
212
+ if (context.isResponse) {
213
+ responses = generated
214
+ }
215
+ return { context, generated, paraphrases, responses }
216
+ }
217
+
218
+ const setupProcessB = ({ config, initializer, allowDelta = false } = {}) => {
219
+ const key = config._key
220
+
221
+ const data = Object.assign({ key, version: '3' }, { uuid: config._uuid })
222
+ if (allowDelta && config.allowDelta && config.hasDelta()) {
223
+ // console.log('config', config)
224
+ data.delta = config.delta()
225
+ } else {
226
+ config.toData(data)
227
+ // Object.assign(data, config.config)
228
+ }
229
+
230
+ // config.toServer(data)
231
+
232
+ if (data.namespaces) {
233
+ for (const uuid of Object.keys(data.namespaces)) {
234
+ const km = config.configs.find((km) => km.uuid === uuid)
235
+ data.namespaces[uuid].name = km.name
236
+ }
237
+ }
238
+
239
+ // const generators = new Generators((data.generators || []).map((g) => new Generator(normalizeGenerator(g))))
240
+ delete data.generators
241
+ // const semantics = new Semantics((data.semantics || []).map((g) => new Semantic(normalizeSemantic(g))))
242
+ delete data.semantics
243
+ const hierarchy = new DigraphInternal((config.config || {}).hierarchy || [])
244
+
245
+ return {
246
+ data,
247
+ // generators,
248
+ // semantics,
249
+ hierarchy
250
+ }
251
+ }
252
+
253
+ const setupContexts = (rawContexts) => {
254
+ let first = true
255
+ const contexts = []
256
+ contexts.push({ marker: 'controlStart', controlRemove: true })
257
+ for (const context of rawContexts) {
258
+ if (first) {
259
+ first = false
260
+ } else {
261
+ contexts.push({ marker: 'controlBetween', controlRemove: true })
262
+ }
263
+ contexts.push(context)
264
+ }
265
+ contexts.push({ marker: 'controlEnd', controlRemove: true })
266
+ return contexts
267
+ }
268
+
269
+ const processContextsB = async ({ config, hierarchy, semantics, generators, json, isTest, rebuildingTemplate, isInstance, instance, query, data, retries, url, commandLineArgs }) => {
270
+ // TODO fix this name to contextsPrime
271
+ const contextsPrime = []
272
+ const generatedPrime = []
273
+ const paraphrasesPrime = []
274
+ const paraphrasesParenthesizedPrime = []
275
+ const generatedParenthesizedPrime = []
276
+ const responsesPrime = []
277
+ const contexts = setupContexts(json.contexts)
278
+
279
+ const objects = config.get('objects')
280
+ const args = { objects, isResponse: true, response: json, isTest, isInstance, getObjects: getObjects(objects), instance }
281
+ if (!json.logs) {
282
+ json.logs = []
283
+ }
284
+ setupArgs(args, config, json.logs, hierarchy)
285
+ const toDo = [...contexts]
286
+ args.insert = (context) => toDo.unshift(context)
287
+ let overlap, lastRange
288
+ config.debugLoops = commandLineArgs && commandLineArgs.debugLoops
289
+ while (toDo.length > 0) {
290
+ const context = toDo.shift()
291
+ args.calls.next()
292
+ let contextPrime = context
293
+ context.topLevel = true
294
+ try {
295
+ if (json.has_errors) {
296
+ throw new Error('There are errors in the logs. Run with the -d flag and grep for Error')
297
+ }
298
+ const generateParenthesized = isTest || (commandLineArgs && commandLineArgs.save)
299
+ if (!config.get('skipSemantics')) {
300
+ const semantics = config.getSemantics(json.logs)
301
+ try {
302
+ contextPrime = await semantics.apply(args, context)
303
+ } catch (e) {
304
+ if (e.message == 'Maximum call stack size exceeded') {
305
+ const mostCalled = semantics.getMostCalled()
306
+ e.message += `\nThe most called semantic was:\nnotes: ${mostCalled.notes}\nmatch: ${mostCalled.matcher.toString()}\napply: ${mostCalled._apply.toString()}\n`
307
+ }
308
+ // contextPrime = semantics.apply(args, { marker: 'error', context, error: e })
309
+ if (isInstance) {
310
+ console.log('error', e.error)
311
+ }
312
+ let reason = e.reason
313
+ if (!reason) {
314
+ if (e.error) {
315
+ reason = e.error[0]
316
+ }
317
+ }
318
+ contextPrime = await semantics.apply(args, {
319
+ marker: 'error',
320
+ context,
321
+ text: e ? e.toString() : 'not available',
322
+ // reason: e.reason,
323
+ reason,
324
+ error: e.stack || e.error
325
+ })
326
+ if (rebuildingTemplate) {
327
+ throw e
328
+ }
329
+ }
330
+ }
331
+ if (contextPrime.controlRemove) {
332
+ continue
333
+ }
334
+ let assumed = { isResponse: true }
335
+ const generated = contextPrime.isResponse ? await config.getGenerators(json.logs).apply({ ...args, assumed }, contextPrime, assumed) : ''
336
+ let generatedParenthesized = []
337
+ if (generateParenthesized) {
338
+ config.parenthesized = true
339
+ generatedParenthesized = contextPrime.isResponse ? await config.getGenerators(json.logs).apply({ ...args, assumed }, contextPrime, assumed) : ''
340
+ config.parenthesized = false
341
+ }
342
+ // assumed = { paraphrase: true, response: false };
343
+ assumed = { paraphrase: true, isResponse: false, response: false }
344
+ if (generateParenthesized) {
345
+ config.parenthesized = false
346
+ }
347
+ const paraphrases = await config.getGenerators(json.logs).apply({ ...args, assumed }, contextPrime, assumed)
348
+ let paraphrasesParenthesized = []
349
+ if (generateParenthesized) {
350
+ config.parenthesized = true
351
+ paraphrasesParenthesized = await config.getGenerators(json.logs).apply({ ...args, assumed }, contextPrime, assumed)
352
+ config.parenthesized = false
353
+ }
354
+ contextsPrime.push(contextPrime)
355
+ generatedPrime.push(generated)
356
+ paraphrasesPrime.push(paraphrases)
357
+ if (generateParenthesized) {
358
+ paraphrasesParenthesizedPrime.push(paraphrasesParenthesized)
359
+ generatedParenthesizedPrime.push(generatedParenthesized)
360
+ }
361
+ if (contextPrime.isResponse) {
362
+ responsesPrime.push(generated)
363
+ } else {
364
+ responsesPrime.push('')
365
+ }
366
+
367
+ // add results to processed list
368
+ config.config.objects.processed = config.config.objects.processed || []
369
+ config.config.objects.processed = config.config.objects.processed.slice(0, 5)
370
+ config.config.objects.processed.unshift({ context: contextPrime, paraphrases: paraphrases, paraphrasesParenthesized, generatedParenthesized, responses: responsesPrime })
371
+ } catch (e) {
372
+ if (Array.isArray(e)) {
373
+ e = {
374
+ errors: e
375
+ }
376
+ }
377
+ e.context = contextPrime
378
+ if (e.logs) {
379
+ e.logs = e.logs.concat(json.logs)
380
+ } else {
381
+ e.logs = json.logs
382
+ }
383
+ e.metadata = json.metadata
384
+ if (json.trace) {
385
+ e.trace = json.trace
386
+ }
387
+ throw e
388
+ }
389
+ }
390
+ return { contextsPrime, generatedPrime, paraphrasesPrime, paraphrasesParenthesizedPrime, generatedParenthesizedPrime, responsesPrime }
391
+ }
392
+
393
+ // instance template loadTemplate
394
+ const loadInstance = async (config, instance) => {
395
+ const transitoryMode = global.transitoryMode
396
+ global.transitoryMode = false
397
+
398
+ if (instance && (instance.associations || instance.learned_contextual_priorities)) {
399
+ if (!config.config.retrain) {
400
+ if (instance.associations) {
401
+ config.addAssociations(instance.associations)
402
+ }
403
+ if (instance.learned_contextual_priorities && instance.learned_contextual_priorities.length > 0) {
404
+ config.addPriorities(instance.learned_contextual_priorities)
405
+ }
406
+ }
407
+ }
408
+
409
+ const { /* data, generators, semantics, */ hierarchy } = setupProcessB({ config })
410
+ for (const i in (instance.resultss || [])) {
411
+ const results = instance.resultss[i]
412
+ if (results.extraConfig) {
413
+ // config.addInternal(results, useOldVersion = true, skipObjects = false, includeNamespaces = true, allowNameToBeNull = false)
414
+ const uuid = config.nameToUUID(instance.name)
415
+ // used to do a CLONE
416
+ config.addInternal(instance.template.configs[i], { uuid, addFirst: true, handleCalculatedProps: true })
417
+ } else if (results.apply) {
418
+ const objects = getObjects(config.get('objects'))(config.uuid)
419
+ const args = { objects, getObjects: getObjects(objects) }
420
+ if (instance.configs) {
421
+ args.isInstance = `instance${i}`
422
+ args.instance = instance.configs[i]
423
+ }
424
+
425
+ const uuid = config.nameToUUID(instance.name)
426
+ setupArgs(args, config, config.logs, hierarchy, uuid)
427
+ await results.apply(args)
428
+ } else if (results.isFragment) {
429
+ } else {
430
+ if (results.skipSemantics) {
431
+ config.config.skipSemantics = results.skipSemantics
432
+ }
433
+ const args = { config, hierarchy, json: results, commandLineArgs: {} }
434
+ args.isInstance = `instance${i}`
435
+ args.instance = ''
436
+ await processContextsB(args)
437
+ if (results.skipSemantics) {
438
+ config.config.skipSemantics = null
439
+ }
440
+ }
441
+ }
442
+ global.transitoryMode = transitoryMode
443
+ }
444
+
445
+ module.exports = {
446
+ setupProcessB,
447
+ ErrorReason,
448
+ listable,
449
+ setupArgs,
450
+ processContext,
451
+ getObjects,
452
+ gs,
453
+ processContextsB,
454
+ loadInstance,
455
+ }
package/src/generators.js CHANGED
@@ -44,7 +44,7 @@ class Generator {
44
44
  return `Generator(${this.match}, ${this._applyWrapped || this._apply})${this.property ? `\nsee the ${this.property} property` : ''}`
45
45
  }
46
46
 
47
- matches (baseArgs, objects, context, hierarchy, config, options = {}) {
47
+ async matches (baseArgs, objects, context, hierarchy, config, options = {}) {
48
48
  if (objects && objects.namespaced) {
49
49
  objects = objects.namespaced[this.uuid]
50
50
  }
@@ -63,17 +63,17 @@ class Generator {
63
63
  }
64
64
  const args = Object.assign({}, baseArgs, moreArgs, (baseArgs.getUUIDScoped || (() => { return {} }))(this.uuid))
65
65
  // return this.match(args)
66
- const matches = this.match(args)
66
+ const matches = await this.match(args)
67
67
  if ((matches && (options.debug || {}).match) ||
68
68
  callId == this.callId) {
69
69
  debugger // next line is the matcher
70
- this.match(args)
70
+ await this.match(args)
71
71
  }
72
72
  return matches
73
73
  }
74
74
 
75
75
  // apply (baseArgs, objects, g, gs, context, hierarchy, config, response, log, options = {}) {
76
- apply (baseArgs, objects, context, hierarchy, config, response, log, options = {}) {
76
+ async apply (baseArgs, objects, context, hierarchy, config, response, log, options = {}) {
77
77
  if (!log) {
78
78
  throw new Error('generators.apply argument log is required')
79
79
  }
@@ -129,7 +129,7 @@ class Generator {
129
129
  callId == this.callId) {
130
130
  debugger
131
131
  }
132
- return this._apply(args)
132
+ return await this._apply(args)
133
133
  }
134
134
  }
135
135
 
@@ -165,7 +165,7 @@ class Generators {
165
165
  };
166
166
 
167
167
  // assumed - properties added to context before the generators are called. For setting paraphrase property
168
- apply (args, context, assumed = {}, options = {}) {
168
+ async apply (args, context, assumed = {}, options = {}) {
169
169
  if (Array.isArray(context)) {
170
170
  throw new Error('Expected a context not an array')
171
171
  }
@@ -186,12 +186,12 @@ class Generators {
186
186
  const stack = args.calls.push()
187
187
  for (let igenerator = 0; igenerator < this.generators.length; ++igenerator) {
188
188
  const generator = this.generators[igenerator]
189
- if (generator.matches(args, objects, context, hierarchy, config, options)) {
189
+ if (await generator.matches(args, objects, context, hierarchy, config, options)) {
190
190
  const log = (message) => { this.logs.push(message) }
191
191
  // this.logs.push(`Generators: applied ${generator.toString()}\n to\n ${JSON.stringify(context)}`)
192
192
  let errorMessage = 'The apply function did not return a value'
193
193
  try {
194
- generated = generator.apply(args, objects, context, hierarchy, config, response, log)
194
+ generated = await generator.apply(args, objects, context, hierarchy, config, response, log)
195
195
  } catch (e) {
196
196
  // the next if handle this
197
197
  generated = null
package/src/helpers.js CHANGED
@@ -1,6 +1,37 @@
1
1
  const deepEqual = require('deep-equal')
2
2
  const stringify = require('json-stable-stringify')
3
3
 
4
+ function where (goUp = 2) {
5
+ const e = new Error()
6
+ const regexForm1 = /\((.*):(\d+):(\d+)\)$/
7
+ const regexForm2 = /at (.*):(\d+):(\d+)$/
8
+ const lines = e.stack.split('\n')
9
+ let line
10
+ let match
11
+ for (line of lines.slice(1)) {
12
+ // if (!(line.includes('config.js:') || line.includes('client.js:') || line.includes('<anonymous>'))) {
13
+ if (!(line.includes('config.js:') || line.includes('client.js:') || line.includes('helpers.js:'))) {
14
+ match = regexForm1.exec(line) || regexForm2.exec(line)
15
+ if (!match) {
16
+ continue
17
+ }
18
+ break
19
+ }
20
+ }
21
+ // const line = e.stack.split("\n")[goUp];
22
+ // const match = regexForm1.exec(line) || regexForm2.exec(line)
23
+ if (match) {
24
+ return `${match[1]}:${match[2]}`
25
+ } else {
26
+ return 'running in browser or in an async call so the stack is broken.'
27
+ }
28
+ }
29
+
30
+ function w (func) {
31
+ func.where = where(3)
32
+ return func
33
+ }
34
+
4
35
  // properties - the properties that correspond to types
5
36
  // types - the expected types of the properties
6
37
  // returns list of properties found matching order of types
@@ -403,5 +434,7 @@ module.exports = {
403
434
  InitCalls,
404
435
  hashCode,
405
436
  sortJson,
406
- subPriority
437
+ subPriority,
438
+ where,
439
+ w,
407
440
  }
package/src/project.js CHANGED
@@ -49,7 +49,7 @@ const project = (object, filter) => {
49
49
  const property = properties.property
50
50
  if (properties.isPropertyList) {
51
51
  if (!Array.isArray(object[property])) {
52
- return projection
52
+ continue
53
53
  }
54
54
  for (const propertyRef of object[property]) {
55
55
  const old = object[propertyRef]