theprogrammablemind 7.12.4-beta.2 → 7.12.4-beta.4

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
@@ -10,10 +10,36 @@ const _ = require('lodash')
10
10
  const stringify = require('json-stable-stringify')
11
11
  const Lines = require('./lines')
12
12
  const flattens = require('./src/flatten')
13
- const { appendNoDups, InitCalls, updateQueries, safeNoDups } = require('./src/helpers')
13
+ const { appendNoDups, InitCalls, updateQueries, safeNoDups, stableId } = require('./src/helpers')
14
14
  const runtime = require('./runtime')
15
15
  const sortJson = runtime.sortJson
16
16
 
17
+ function where (goUp = 2) {
18
+ const e = new Error()
19
+ const regexForm1 = /\((.*):(\d+):(\d+)\)$/
20
+ const regexForm2 = /at (.*):(\d+):(\d+)$/
21
+ const lines = e.stack.split('\n')
22
+ let line
23
+ let match
24
+ for (line of lines.slice(1)) {
25
+ // if (!(line.includes('config.js:') || line.includes('client.js:') || line.includes('<anonymous>'))) {
26
+ if (!(line.includes('config.js:') || line.includes('client.js:'))) {
27
+ match = regexForm1.exec(line) || regexForm2.exec(line)
28
+ if (!match) {
29
+ continue
30
+ }
31
+ break
32
+ }
33
+ }
34
+ // const line = e.stack.split("\n")[goUp];
35
+ // const match = regexForm1.exec(line) || regexForm2.exec(line)
36
+ if (match) {
37
+ return `${match[1]}:${match[2]}`
38
+ } else {
39
+ return 'running in browser'
40
+ }
41
+ }
42
+
17
43
  const getConfig_getObjectsCheck = (config, testConfig) => {
18
44
  let testConfigName = config.name
19
45
  if (testConfig.testModuleName) {
@@ -55,57 +81,102 @@ const pickObjects = (config, testConfig, getObjects) => {
55
81
  return projection
56
82
  }
57
83
 
58
- // move ask to the KM's since verbatim is called
59
- const getAsk = (config) => (uuid) => (asks) => {
60
- for (const ask of asks) {
61
- let oneShot = true // default
62
- if (ask.oneShot === false) {
63
- oneShot = false
64
- }
65
- config.addSemantic({
66
- uuid,
67
- oneShot,
68
- match: (args) => ask.matchr(args),
69
- apply: (args) => ask.applyr(args)
70
- })
71
- }
72
- let oneShot = true
73
- for (const ask of asks) {
74
- if (ask.oneShot === false) {
75
- oneShot = false
76
- }
77
- }
78
- config.addSemantic({
79
- uuid,
80
- oneShot,
81
- match: ({ context }) => context.marker == 'controlEnd' || context.marker == 'controlBetween',
82
- apply: (args) => {
83
- for (const ask of asks) {
84
- let matchq = ask.matchq
85
- let applyq = ask.applyq
86
- if (!matchq) {
87
- let wasAsked = false
88
- matchq = () => !wasAsked,
89
- applyq = (args) => {
90
- wasAsked = true
91
- applyq(args)
84
+ // move ask to the KM's since verbatim is called probably in dialogues?
85
+ const getAsk = (config) => (uuid) => {
86
+ // if (!uuid) {
87
+ // debugger
88
+ //}
89
+ return (asks) => {
90
+ const ask = (ask) => {
91
+ let oneShot = true // default
92
+ if (ask.oneShot === false) {
93
+ oneShot = false
94
+ }
95
+
96
+ const id_q = stableId('semantic')
97
+ const id_rs = []
98
+ let wasAsked = false
99
+ let wasApplied = false
100
+ const getWasAsked = () => {
101
+ return wasAsked
102
+ }
103
+ const setWasAsked = (value) => {
104
+ wasAsked = value
105
+ }
106
+ const getWasApplied = () => {
107
+ return wasApplied
108
+ }
109
+ const setWasApplied = (value) => {
110
+ wasApplied = value
111
+ }
112
+
113
+ const semanticsr = ask.semanticsr || []
114
+ if (semanticsr.length == 0) {
115
+ semanticsr.push({ match: ask.matchr, apply: ask.applyr })
116
+ }
117
+ for (const semantic of semanticsr) {
118
+ const id_r = stableId('semantic')
119
+ id_rs.push(id_r)
120
+ config.addSemantic({
121
+ uuid,
122
+ id: id_r,
123
+ tied_ids: [id_q],
124
+ oneShot,
125
+ where: semantic.where || ask.where || where(2),
126
+ source: 'response',
127
+ match: (args) => semantic.match(args),
128
+ apply: (args) => {
129
+ setWasApplied(true)
130
+ semantic.apply(args)
131
+ },
132
+ })
133
+ }
134
+
135
+ config.addSemantic({
136
+ uuid,
137
+ oneShot,
138
+ id: id_q,
139
+ tied_ids: id_rs,
140
+ where: ask.where,
141
+ isQuestion: true, // do one question at a time
142
+ getWasAsked,
143
+ getWasApplied,
144
+ onNevermind: ask.onNevermind,
145
+ source: 'question',
146
+ match: ({ context }) => context.marker == 'controlEnd' || context.marker == 'controlBetween',
147
+ apply: (args) => {
148
+ let matchq = ask.matchq
149
+ let applyq = ask.applyq
150
+ if (!matchq) {
151
+ let wasAsked = false
152
+ matchq = () => !wasAsked,
153
+ applyq = (args) => {
154
+ wasAsked = true
155
+ return ask.applyq(args)
156
+ }
92
157
  }
158
+ if (matchq(args)) {
159
+ setWasAsked(true)
160
+ setWasApplied(false)
161
+ // args.context.motivationKeep = true
162
+ args.verbatim(applyq(args))
163
+ /*
164
+ args.context.verbatim = applyq(args)
165
+ args.context.isResponse = true;
166
+ delete args.context.controlRemove;
167
+ */
168
+ args.context.controlKeepMotivation = true
169
+ }
170
+ args.context.cascade = true
93
171
  }
94
- if (matchq(args)) {
95
- // args.context.motivationKeep = true
96
- args.verbatim(applyq(args))
97
- /*
98
- args.context.verbatim = applyq(args)
99
- args.context.isResponse = true;
100
- delete args.context.controlRemove;
101
- */
102
- args.context.controlKeepMotivation = true
103
- break
104
- }
105
- }
106
- args.context.cascade = true
172
+ })
107
173
  }
108
- })
174
+ if (!Array.isArray(asks)) {
175
+ asks = [asks]
176
+ }
177
+
178
+ [...asks].reverse().forEach( (a) => ask(a) )
179
+ }
109
180
  }
110
181
 
111
182
  const sameJSON = (json1, json2) => {
@@ -178,7 +249,7 @@ class ErrorReason extends Error {
178
249
  }
179
250
 
180
251
  const setupArgs = (args, config, logs, hierarchy, uuidForScoping) => {
181
- config.setArgs(args)
252
+
182
253
  // callId
183
254
  args.calls = new InitCalls(args.isInstance ? `${args.isInstance}#${config.name}` : config.name)
184
255
  if (global.theprogrammablemind && global.theprogrammablemind.loadForTesting) {
@@ -197,32 +268,11 @@ const setupArgs = (args, config, logs, hierarchy, uuidForScoping) => {
197
268
  args.asList = asList
198
269
  args.retry = () => { throw new RetryError() }
199
270
  args.fragments = (query) => config.fragment(query)
200
- const scopedAsk = getAsk(config)
201
-
202
- const getAPI = (uuid) => {
203
- if (config && config.getAPI) {
204
- return config.getAPI(uuid)
205
- }
206
- }
207
- const getAPIs = (uuid) => {
208
- if (config && config.getAPIs) {
209
- return config.getAPIs(uuid)
210
- }
211
- }
212
- args.getUUIDScoped = (uuid) => {
213
- return {
214
- ask: scopedAsk(uuid),
215
- api: getAPI(uuid),
216
- apis: getAPIs(uuid)
217
- }
218
- }
219
- Object.assign(args, args.getUUIDScoped(uuidForScoping))
220
271
  args.breakOnSemantics = false
221
272
  args.theDebugger = {
222
273
  breakOnSemantics: (value) => args.breakOnSemantics = value
223
274
  }
224
275
  if (!logs) {
225
- debugger
226
276
  }
227
277
  args.log = (message) => logs.push(message)
228
278
 
@@ -251,6 +301,33 @@ const setupArgs = (args, config, logs, hierarchy, uuidForScoping) => {
251
301
  // for semantics
252
302
  args.addAssumedScoped(args, {})
253
303
  config.getAddedArgs(args)
304
+
305
+ const getAPI = (uuid) => {
306
+ if (config && config.getAPI) {
307
+ return config.getAPI(uuid)
308
+ }
309
+ }
310
+ const getAPIs = (uuid) => {
311
+ if (config && config.getAPIs) {
312
+ return config.getAPIs(uuid)
313
+ }
314
+ }
315
+ const scopedAsk = getAsk(config)
316
+ args.getUUIDScoped = (uuid) => {
317
+ return {
318
+ ask: scopedAsk(uuid),
319
+ api: getAPI(uuid),
320
+ apis: getAPIs(uuid)
321
+ }
322
+ }
323
+ Object.assign(args, args.getUUIDScoped(uuidForScoping || config.uuid))
324
+ /*
325
+ if (uuidForScoping) {
326
+ Object.assign(args, args.getUUIDScoped(uuidForScoping))
327
+ }
328
+ */
329
+ // sets args for all the API. that make a copy so the args must be fully setup by here except for scoped
330
+ config.setArgs(args)
254
331
  }
255
332
 
256
333
  const gs = (g) => (contexts, separator, lastSeparator) => {
@@ -2179,26 +2256,6 @@ const ensureTestFile = (module, name, type) => {
2179
2256
  }
2180
2257
  }
2181
2258
 
2182
- function where (goUp = 2) {
2183
- const e = new Error()
2184
- const regexForm1 = /\((.*):(\d+):(\d+)\)$/
2185
- const regexForm2 = /at (.*):(\d+):(\d+)$/
2186
- const lines = e.stack.split('\n')
2187
- let line
2188
- for (line of lines.slice(1)) {
2189
- if (!(line.includes('config.js:') || line.includes('client.js:'))) {
2190
- break
2191
- }
2192
- }
2193
- // const line = e.stack.split("\n")[goUp];
2194
- const match = regexForm1.exec(line) || regexForm2.exec(line)
2195
- if (match) {
2196
- return `${match[1]}:${match[2]}`
2197
- } else {
2198
- return 'running in browser'
2199
- }
2200
- }
2201
-
2202
2259
  function w (func) {
2203
2260
  func.where = where(3)
2204
2261
  return func
package/package.json CHANGED
@@ -65,6 +65,6 @@
65
65
  "json-stable-stringify": "^1.0.1",
66
66
  "node-fetch": "^2.6.1"
67
67
  },
68
- "version": "7.12.4-beta.2",
68
+ "version": "7.12.4-beta.4",
69
69
  "license": "UNLICENSED"
70
70
  }
package/src/config.js CHANGED
@@ -467,7 +467,7 @@ const normalizeConfig = (config) => {
467
467
  if (config.semantics) {
468
468
  for (const semantic of config.semantics) {
469
469
  if (semantic.oneShot) {
470
- semantic.id = uuid()
470
+ semantic.id = semantic.id || helpers.stableId('semantic')
471
471
  }
472
472
  }
473
473
  }
@@ -902,6 +902,10 @@ class Config {
902
902
  }
903
903
  }
904
904
 
905
+ get semantics() {
906
+ return [...this.config.semantics]
907
+ }
908
+
905
909
  getSemantics (logs = []) {
906
910
  return new Semantics(this.config.semantics, logs, { km: this.name })
907
911
  }
@@ -1366,9 +1370,28 @@ class Config {
1366
1370
  }
1367
1371
 
1368
1372
  removeSemantic (deleteSemantic) {
1369
- const index = this.config.semantics.findIndex((semantic) => semantic.id === deleteSemantic.id)
1370
- if (index >= 0) {
1371
- this.config.semantics.splice(index, 1)
1373
+ const id = deleteSemantic.id || deleteSemantic
1374
+ const todo = [id]
1375
+ const seen = new Set()
1376
+
1377
+ while (todo.length > 0) {
1378
+ const id = todo.pop()
1379
+ if (seen.has(id)) {
1380
+ continue
1381
+ }
1382
+ seen.add(id)
1383
+ const index = this.config.semantics.findIndex((semantic) => semantic.id === id)
1384
+ if (index == -1) {
1385
+ continue
1386
+ }
1387
+ for (const tied_id of this.config.semantics[index].tied_ids || []) {
1388
+ if (!seen.has(tied_id)) {
1389
+ todo.push(tied_id)
1390
+ }
1391
+ }
1392
+ if (index >= 0) {
1393
+ this.config.semantics.splice(index, 1)
1394
+ }
1372
1395
  }
1373
1396
  }
1374
1397
 
@@ -1556,7 +1579,7 @@ class Config {
1556
1579
  config._api.multiApi[api].args = args
1557
1580
  }
1558
1581
  } else {
1559
- config._api.args = args
1582
+ config._api.args = { ...args, ...args.getUUIDScoped(config.uuid) }
1560
1583
  }
1561
1584
  }
1562
1585
 
@@ -3079,5 +3102,5 @@ module.exports = {
3079
3102
  Config,
3080
3103
  config_toServer,
3081
3104
  operatorKey_valid,
3082
- handleBridgeProps
3105
+ handleBridgeProps,
3083
3106
  }
package/src/helpers.js CHANGED
@@ -374,7 +374,15 @@ const subPriority = (sub, sup) => {
374
374
  return true
375
375
  }
376
376
 
377
+ const stableIds = {}
378
+ const stableId = (tag) => {
379
+ const id = stableIds[tag] || 1
380
+ stableIds[tag] = id + 1
381
+ return id
382
+ }
383
+
377
384
  module.exports = {
385
+ stableId,
378
386
  ecatch,
379
387
  functionsToStrings,
380
388
  updateQueries,
package/src/semantics.js CHANGED
@@ -6,7 +6,7 @@ class Semantic {
6
6
  // constructor ({match, apply, uuid, index, km, notes}) {
7
7
  constructor (semantic) {
8
8
  semantic = normalizeSemantic(semantic)
9
- const { match, apply, uuid, index, km, notes, priority, debug, where, applyWrapped, property, oneShot, id } = semantic
9
+ const { match, apply, uuid, index, km, notes, priority, debug, where, source, applyWrapped, property, oneShot, id, tied_ids, isQuestion } = semantic
10
10
  this.matcher = match
11
11
  this._apply = apply
12
12
  this._applyWrapped = applyWrapped
@@ -18,8 +18,11 @@ class Semantic {
18
18
  this.notes = notes
19
19
  this.callId = debug
20
20
  this.where = where
21
+ this.source = source
21
22
  this.oneShot = oneShot
23
+ this.isQuestion = isQuestion
22
24
  this.id = id
25
+ this.tied_ids = tied_ids || []
23
26
  }
24
27
 
25
28
  toLabel () {
@@ -184,11 +187,16 @@ class Semantics {
184
187
  let applied = false
185
188
  const stack = args.calls.push()
186
189
  let counter = 0
190
+ let seenQuestion = false
187
191
  for (const isemantic in this.semantics) {
188
192
  const semantic = this.semantics[isemantic]
189
193
  if (!semantic) {
190
194
  debugger
191
195
  }
196
+ // only one question at a time
197
+ if (semantic.isQuestion && seenQuestion) {
198
+ continue
199
+ }
192
200
  if (semantic.matches(args, context, options)) {
193
201
  if (!this.calls[counter]) {
194
202
  this.calls[counter] = 0
@@ -198,6 +206,7 @@ class Semantics {
198
206
  try {
199
207
  contextPrime = semantic.apply(args, context, s, log, options)
200
208
  if (!contextPrime.controlKeepMotivation && semantic.oneShot) {
209
+ // semantic.tied_ids.forEach((tied_id) => args.config.removeSemantic(tied_id))
201
210
  args.config.removeSemantic(semantic)
202
211
  }
203
212
  } catch (e) {
@@ -274,6 +283,7 @@ class Semantics {
274
283
  this.logs.push(lines.toString())
275
284
  }
276
285
  applied = true
286
+ seenQuestion = seenQuestion || semantic.isQuestion
277
287
  if (contextPrime.cascade) {
278
288
  contextPrime.cascade = false
279
289
  } else {