theprogrammablemind_4wp 9.7.1-beta.18 → 9.7.1-beta.20

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
@@ -267,7 +267,7 @@ const throwErrorHandler = (error) => {
267
267
  throw error
268
268
  }
269
269
 
270
- const _process = async (config, query, { initializer, commandLineArgs, credentials, writeTests, logs, isProcess, isModule, isTest, saveDeveloper, rebuildingTemplate, testConfig, testsFN, errorHandler = throwErrorHandler } = {}) => {
270
+ const _process = async (config, query, { queryNumber, initializer, commandLineArgs, credentials, writeTests, logs, isProcess, isModule, isTest, saveDeveloper, rebuildingTemplate, testConfig, testsFN, errorHandler = throwErrorHandler } = {}) => {
271
271
  if (credentials) {
272
272
  config.server(credentials.server, credentials.key)
273
273
  }
@@ -418,6 +418,7 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
418
418
  return response
419
419
  } catch (error) {
420
420
  error.summaries = summaries
421
+ error.queryNumber = queryNumber
421
422
  error.query = query
422
423
  errorHandler(error)
423
424
  }
@@ -510,7 +511,7 @@ const runTest = async (config, expected, { args, verbose, testConfig, debug, tim
510
511
  setupArgs(args, config)
511
512
  await testConfig.initializer(args)
512
513
  }
513
- const result = await _process(config, test, { errorHandler, isTest: true, isProcess: true, isModule: false })
514
+ const result = await _process(config, test, { queryNumber: args.queryNumber, errorHandler, isTest: true, isProcess: true, isModule: false })
514
515
  result.query = test
515
516
  if (debug) {
516
517
  defaultInnerProcess(config, errorHandler, result)
@@ -630,6 +631,7 @@ const runTestsHelper = async (config, tests, failed, juicyBits) => {
630
631
  }
631
632
  const test = tests.shift()
632
633
  juicyBits.index = index
634
+ juicyBits.args.queryNumber = index
633
635
  const result = await runTest(config, test, juicyBits)
634
636
  if (result != null) {
635
637
  result.index = index
@@ -800,7 +802,7 @@ const defaultErrorHandler = async (error) => {
800
802
  }
801
803
 
802
804
  if (error.query) {
803
- console.log('query: ', error.query)
805
+ console.log(`query: #${error.queryNumber} ${error.query}`)
804
806
  doErrorExit = true
805
807
  }
806
808
 
@@ -1654,12 +1656,7 @@ const knowledgeModuleImpl = async ({
1654
1656
  }
1655
1657
 
1656
1658
  if (hasArg('s')) {
1657
- const easyToRead = _.cloneDeep(config.config.semantics)
1658
- for (const semantic of easyToRead) {
1659
- semantic.match = semantic.match.toString()
1660
- semantic.apply = semantic.apply.toString()
1661
- }
1662
- console.dir(easyToRead)
1659
+ config.printSemantics()
1663
1660
  }
1664
1661
  }
1665
1662
  }
package/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  const { Semantics, Semantic } = require('./src/semantics')
2
2
  const { Generators, Generator } = require('./src/generators')
3
3
  const { Config } = require('./src/config')
4
- const { w, where, OverrideCheck } = require('./src/helpers')
4
+ const { w, where, OverrideCheck, setByPath, getByPath } = require('./src/helpers')
5
5
  const Digraph = require('./src/digraph')
6
6
  const client = require('./client')
7
7
  const flattens = require('./src/flatten')
@@ -16,6 +16,8 @@ module.exports = {
16
16
  runTests: client.runTests,
17
17
  knowledgeModule: client.knowledgeModule,
18
18
  ensureTestFile: client.ensureTestFile,
19
+ setByPath,
20
+ getByPath,
19
21
  where,
20
22
  stableId: client.stableId,
21
23
  w,
package/package.json CHANGED
@@ -73,6 +73,6 @@
73
73
  "scriptjs": "^2.5.9",
74
74
  "uuid": "^8.3.2"
75
75
  },
76
- "version": "9.7.1-beta.18",
76
+ "version": "9.7.1-beta.20",
77
77
  "license": "UNLICENSED"
78
78
  }
package/src/config.js CHANGED
@@ -981,6 +981,15 @@ class Config {
981
981
  return config_toServer(config)
982
982
  }
983
983
 
984
+ printSemantics() {
985
+ const easyToRead = _.cloneDeep(this.config.semantics)
986
+ for (const semantic of easyToRead) {
987
+ semantic.match = semantic.match.toString()
988
+ semantic.apply = semantic.apply.toString()
989
+ }
990
+ console.dir(easyToRead)
991
+ }
992
+
984
993
  async run(handler) {
985
994
  return configHelpers.run(this, handler)
986
995
  }
@@ -1683,6 +1692,7 @@ class Config {
1683
1692
  return
1684
1693
  }
1685
1694
  }
1695
+
1686
1696
  if (global.transitoryMode) {
1687
1697
  def.transitoryMode = true
1688
1698
  }
@@ -3384,6 +3394,10 @@ class Config {
3384
3394
  let duplicated = new Set()
3385
3395
  const seen = new Set()
3386
3396
  for (const bridge of this.config.bridges) {
3397
+ if (typeof bridge.id !== 'string') {
3398
+ throw new Error('Config.addBridge: expected the bridge id to be a non-empty string.')
3399
+ }
3400
+
3387
3401
  const id = `${bridge.id}/${bridge.level} (namespace: ${bridge.uuid || this.uuid})`
3388
3402
  if (seen.has(id)) {
3389
3403
  duplicated.add(id)
@@ -165,10 +165,14 @@ const setupArgs = (args, config, logs, hierarchy, uuidForScoping) => {
165
165
  }
166
166
  args.contextHierarchy = new ContextHierarchy()
167
167
  args.namespaced = {
168
- get: (km, context, property) => {
168
+ get: (km, context, property, _default) => {
169
169
  context.namespaced ??= {}
170
170
  context.namespaced[km] ??= {}
171
- return context.namespaced[km][property]
171
+ const value = context.namespaced[km][property]
172
+ if (value == undefined) {
173
+ return _default
174
+ }
175
+ return value
172
176
  },
173
177
  set: (km, context, property, value) => {
174
178
  context.namespaced ??= {}
package/src/digraph.js CHANGED
@@ -73,11 +73,25 @@ class Digraph {
73
73
  this._edges = edges
74
74
  }
75
75
 
76
- /*
77
- set edges(edges) {
78
- this._edges = edges.map( toA )
76
+ tos(from) {
77
+ const tos = []
78
+ for (const edge of this._edges) {
79
+ if (edge[0] == from) {
80
+ tos.push(edge[1])
81
+ }
82
+ }
83
+ return tos
84
+ }
85
+
86
+ froms(to) {
87
+ const froms = []
88
+ for (const edge of this._edges) {
89
+ if (edge[1] == to) {
90
+ froms.push(edge[0])
91
+ }
92
+ }
93
+ return froms
79
94
  }
80
- */
81
95
 
82
96
  acdcs (s, from, to) {
83
97
  if (!s) {
@@ -170,18 +184,6 @@ class Digraph {
170
184
  return this.minima(common)
171
185
  }
172
186
 
173
- /*
174
- maxima (nodes) {
175
- const maxima = new Set(nodes)
176
- const descendants = new Set([])
177
- nodes.forEach((node) => {
178
- this.descendants(node).forEach((n) => descendants.add(n))
179
- })
180
- descendants.forEach((n) => maxima.delete(n))
181
- return maxima
182
- }
183
- */
184
-
185
187
  add (child, parent) {
186
188
  this._edges.push([child, parent])
187
189
  }
@@ -39,6 +39,26 @@ class DigraphInternal {
39
39
  this._edges = edges
40
40
  }
41
41
 
42
+ tos(from) {
43
+ const tos = []
44
+ for (const edge of this._edges) {
45
+ if (edge[0] == from) {
46
+ tos.push(edge[1])
47
+ }
48
+ }
49
+ return tos
50
+ }
51
+
52
+ froms(to) {
53
+ const froms = []
54
+ for (const edge of this._edges) {
55
+ if (edge[1] == to) {
56
+ froms.push(edge[0])
57
+ }
58
+ }
59
+ return froms
60
+ }
61
+
42
62
  get length () {
43
63
  return this._edges.length
44
64
  }
@@ -137,18 +157,6 @@ class DigraphInternal {
137
157
  return this.minima(common)
138
158
  }
139
159
 
140
- /*
141
- maxima (nodes) {
142
- const maxima = new Set(nodes)
143
- const descendants = new Set([])
144
- nodes.forEach((node) => {
145
- this.descendants(node).forEach((n) => descendants.add(n))
146
- })
147
- descendants.forEach((n) => maxima.delete(n))
148
- return maxima
149
- }
150
- */
151
-
152
160
  add (child, parent) {
153
161
  this._edges.push([child, parent])
154
162
  }
package/src/generators.js CHANGED
@@ -125,11 +125,10 @@ class Generator {
125
125
  args.g = args.gp
126
126
  }
127
127
  return await debug.hitScoped(args.callId, async () => {
128
- if ((options.debug || {}).apply ||
129
- callId === this.callId) {
128
+ if ((options.debug || {}).apply || process.env.DEBUG_CALLID == args.callId || callId === this.callId) {
130
129
  debugger // eslint-disable-line no-debugger
131
130
  }
132
- return await this._apply(args)
131
+ return await this._apply(args) // DEBUG: This is the line you want to step into
133
132
  })
134
133
  }
135
134
  }
@@ -195,7 +194,7 @@ class Generators {
195
194
  console.error("TPMKMS_TRACE", debug.counter("TPMKMS_TRACE"))
196
195
  console.error(generator.toLabel())
197
196
  console.error(generator.toString())
198
- console.log(`To debug this use debug.breakAt('${args.calls.current()}. Check the 'callId' arg to see this value.')`)
197
+ console.log(`To debug this use debug.breakAt('${args.calls.current()}') or DEBUG_CALLID="${args.calls.current()}"`)
199
198
  }
200
199
 
201
200
  try {
@@ -232,7 +231,7 @@ class Generators {
232
231
  lines.setElement(0, 2, stack)
233
232
  lines.newRow()
234
233
  lines.setElement(0, 1, 'DEBUG')
235
- lines.setElement(0, 2, `To debug this use debug.breakAt('${args.calls.current()}. Check the 'callId' arg to see this value.')`)
234
+ lines.setElement(0, 2, `To debug this use debug.breakAt('${args.calls.current()}') or DEBUG_CALLID="${args.calls.current()}"`)
236
235
  lines.newRow()
237
236
  lines.setElement(0, 1, 'ERROR')
238
237
  lines.setElement(0, 2, errorMessage)
@@ -264,7 +263,7 @@ class Generators {
264
263
  lines.setElement(0, 2, stack)
265
264
  lines.newRow()
266
265
  lines.setElement(0, 1, 'DEBUG')
267
- lines.setElement(0, 2, `To debug this use debug.breakAt('${args.calls.current()}. Check the 'callId' arg to see this value.')`)
266
+ lines.setElement(0, 2, `To debug this use debug.breakAt('${args.calls.current()}')`)
268
267
  lines.newRow()
269
268
  lines.setElement(0, 1, 'TO')
270
269
  lines.setElement(0, 2, `context_id: ${context.context_id}`)
package/src/helpers.js CHANGED
@@ -544,52 +544,77 @@ const stableId = (tag) => {
544
544
  }
545
545
 
546
546
  function getByPath(obj, path, defaultValue) {
547
+ const segments = Array.isArray(path) ? path : [path];
548
+ const keys = segments.flatMap((segment) => {
549
+ if (typeof segment !== "string") return [segment];
550
+ return segment
551
+ .replace(/\[(\d+)\]/g, ".$1")
552
+ .split(".")
553
+ .filter((key) => key !== "");
554
+ });
555
+
547
556
  let current = obj;
548
- for (const key of path) {
557
+ for (const key of keys) {
549
558
  if (current === null || current === undefined) return defaultValue;
550
- if (typeof current !== 'object') return defaultValue;
559
+ if (typeof current !== "object") return defaultValue;
551
560
  current = current[key];
552
561
  }
553
562
  return current === undefined ? defaultValue : current;
554
563
  }
555
564
 
565
+ function normalizePath(path) {
566
+ const segments = Array.isArray(path) ? path : [path];
567
+ return segments.flatMap((segment) => {
568
+ if (typeof segment !== "string") return [segment];
569
+ return segment
570
+ .replace(/\[(\d+)\]/g, ".$1")
571
+ .split(".")
572
+ .filter((key) => key !== "");
573
+ });
574
+ }
575
+
576
+ function isArrayIndex(key) {
577
+ if (typeof key === "number") return Number.isInteger(key) && key >= 0;
578
+ return key !== "" && String(key >>> 0) === String(key);
579
+ }
580
+
556
581
  /**
557
- * Set a value in an object by path array.
582
+ * Set a value in an object by path (string or array).
558
583
  * Automatically creates missing objects {} or arrays [] as needed.
559
584
  *
560
585
  * @param {Object} obj - The root object to modify
561
- * @param {Array<string|number>} path - Array of keys/indices
586
+ * @param {string|Array<string|number>} path - Path keys/indices
562
587
  * @param {*} value - Value to set
563
588
  * @returns {*} The set value (for chaining)
564
589
  */
565
590
  function setByPath(obj, path, value) {
566
- if (!Array.isArray(path) || path.length === 0) {
567
- throw new Error('Path must be a non-empty array');
591
+ const keys = normalizePath(path);
592
+
593
+ if (keys.length === 0) {
594
+ throw new Error("Path must be a non-empty string or array");
595
+ }
596
+
597
+ if (obj == null || typeof obj !== "object") {
598
+ throw new Error("Target must be an object or array");
568
599
  }
569
600
 
570
601
  let current = obj;
571
602
 
572
- for (let i = 0; i < path.length; i++) {
573
- const key = path[i];
574
- const isLast = i === path.length - 1;
603
+ for (let i = 0; i < keys.length; i++) {
604
+ const key = keys[i];
605
+ const isLast = i === keys.length - 1;
575
606
 
576
607
  if (isLast) {
577
- // Final step — just assign
578
608
  current[key] = value;
579
609
  } else {
580
- // Not last — ensure next level exists
581
- const nextKey = path[i + 1];
582
-
583
- if (current[key] == null) {
584
- // Auto-create: array if next key is number, otherwise object
585
- current[key] = typeof nextKey === 'number' || String(nextKey >>> 0) === nextKey
586
- ? []
587
- : {};
588
- } else if (Array.isArray(current[key]) && typeof nextKey !== 'number') {
589
- // Safety: if current is array but next key isn't a valid index → convert to object
610
+ const nextKey = keys[i + 1];
611
+ const nextIsIndex = isArrayIndex(nextKey);
612
+
613
+ if (current[key] == null || typeof current[key] !== "object") {
614
+ current[key] = nextIsIndex ? [] : {};
615
+ } else if (Array.isArray(current[key]) && !nextIsIndex) {
590
616
  current[key] = { ...current[key] };
591
- } else if (!Array.isArray(current[key]) && typeof nextKey === 'number') {
592
- // If next expects array but current is object → convert
617
+ } else if (!Array.isArray(current[key]) && nextIsIndex) {
593
618
  current[key] = Object.values(current[key]);
594
619
  }
595
620
 
package/src/semantics.js CHANGED
@@ -77,10 +77,11 @@ class Semantic {
77
77
  this.fixUpArgs(args, context)
78
78
  return await debug.hitScoped(args.callId, async () => {
79
79
  const matches = await this.matcher(args)
80
- if (matches && (options.debug || {}).match || args.callId === this.callId) {
81
- // next line is the matcher
82
- debugger // eslint-disable-line no-debugger
83
- await this.matcher(args)
80
+ if (matches) {
81
+ if ((options.debug || {}).match || args.callId === this.callId || process.env.DEBUG_CALLID == args.callId) {
82
+ debugger // eslint-disable-line no-debugger
83
+ await this.matcher(args) // DEBUG: This is the line you step into
84
+ }
84
85
  }
85
86
  return matches
86
87
  })
@@ -100,8 +101,8 @@ class Semantic {
100
101
  this.fixUpArgs(args, contextPrime)
101
102
 
102
103
  return await debug.hitScoped(args.callId, async () => {
103
- if ((options.debug || {}).apply || args.callId === this.callId) {
104
- debugger // eslint-disable-line no-debugger
104
+ if ((options.debug || {}).apply || args.callId === this.callId || process.env.DEBUG_CALLID == args.callId) {
105
+ debugger // eslint-disable-line no-debugger // STEP ABOUT THREE TIMES TO THE DEBUG LINE
105
106
  }
106
107
  if (args.breakOnSemantics) {
107
108
  debugger // eslint-disable-line no-debugger
@@ -109,7 +110,7 @@ class Semantic {
109
110
 
110
111
  try {
111
112
  args.stack.push(this)
112
- await this._apply(args)
113
+ await this._apply(args) // DEBUG: This is the line you want to step into
113
114
  args.stack.pop()
114
115
  } catch( e ) {
115
116
  args.stack.pop()
@@ -260,7 +261,7 @@ class Semantics {
260
261
  lines.setElement(0, 2, semantic.toString())
261
262
  lines.newRow()
262
263
  lines.setElement(0, 1, 'DEBUG')
263
- lines.setElement(0, 2, `To debug this use debug.breakAt('${args.calls.current()}. Check the 'callId' arg to see this value.')`)
264
+ lines.setElement(0, 2, `To debug this use debug.breakAt('${args.calls.current()}') in the code or DEBUG_CALLID="${args.calls.current()}"`)
264
265
  lines.newRow()
265
266
  lines.setElement(0, 1, 'TO')
266
267
  lines.setElement(0, 2, `context_id: ${context.context_id}`)
@@ -295,7 +296,7 @@ class Semantics {
295
296
  lines.setElement(0, 2, semantic.toString())
296
297
  lines.newRow()
297
298
  lines.setElement(0, 1, 'DEBUG')
298
- lines.setElement(0, 2, `To debug this use debug.breakAt('${args.calls.current()}. Check the 'callId' arg to see this value.')`)
299
+ lines.setElement(0, 2, `To debug this use debug.breakAt('${args.calls.current()}') in the code or DEBUG_CALLID="${args.calls.current()}"`)
299
300
  lines.newRow()
300
301
  lines.setElement(0, 1, 'TO')
301
302
  lines.setElement(0, 2, `context_id: ${context.context_id}`)