neuralos 3.9.5 → 3.10.0

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.
Files changed (69) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +103 -337
  3. package/cli.js +103 -0
  4. package/engine.js +124 -0
  5. package/index.js +230 -0
  6. package/package.json +38 -43
  7. package/test.js +20 -0
  8. package/tools.js +89 -0
  9. package/validate.js +263 -0
  10. package/bin/gybackend.cjs +0 -411663
  11. package/plugins/agentspan-bridge/agentspan-bridge.extreme.spec.ts +0 -328
  12. package/plugins/agentspan-bridge/agentspan-bridge.phase2.extreme.spec.ts +0 -282
  13. package/plugins/agentspan-bridge/conductorClient.mjs +0 -182
  14. package/plugins/agentspan-bridge/index.mjs +0 -389
  15. package/plugins/agentspan-bridge/playbookToWorkflowDef.mjs +0 -209
  16. package/plugins/agentspan-bridge/plugin.json +0 -27
  17. package/plugins/fraudops/index.d.mts +0 -9
  18. package/plugins/fraudops/index.mjs +0 -185
  19. package/plugins/fraudops/plugin.json +0 -10
  20. package/plugins/iam-connector/index.d.mts +0 -10
  21. package/plugins/iam-connector/index.mjs +0 -229
  22. package/plugins/iam-connector/plugin.json +0 -10
  23. package/plugins/mitmproxy-bridge/index.d.mts +0 -20
  24. package/plugins/mitmproxy-bridge/index.mjs +0 -256
  25. package/plugins/mitmproxy-bridge/plugin.json +0 -17
  26. package/plugins/monid-bridge/index.mjs +0 -228
  27. package/plugins/monid-bridge/monid-bridge.extreme.spec.mjs +0 -75
  28. package/plugins/monid-bridge/plugin.json +0 -15
  29. package/plugins/netdata-rterm/index.mjs +0 -229
  30. package/plugins/netdata-rterm/netdata-rterm.extreme.spec.ts +0 -252
  31. package/plugins/netdata-rterm/plugin.json +0 -22
  32. package/plugins/netexec-bridge/index.d.mts +0 -28
  33. package/plugins/netexec-bridge/index.mjs +0 -325
  34. package/plugins/netexec-bridge/plugin.json +0 -20
  35. package/plugins/neuralos/index.mjs +0 -137
  36. package/plugins/neuralos/neuralos.extreme.spec.mts +0 -386
  37. package/plugins/neuralos/neuralosEngine.mjs +0 -369
  38. package/plugins/neuralos/plugin.json +0 -15
  39. package/plugins/numbat-bridge/index.mjs +0 -229
  40. package/plugins/numbat-bridge/numbat-bridge.extreme.spec.mjs +0 -148
  41. package/plugins/numbat-bridge/plugin.json +0 -21
  42. package/plugins/patch-manager/index.d.mts +0 -10
  43. package/plugins/patch-manager/index.mjs +0 -288
  44. package/plugins/patch-manager/plugin.json +0 -10
  45. package/plugins/promptfoo-redteam/index.d.mts +0 -15
  46. package/plugins/promptfoo-redteam/index.mjs +0 -277
  47. package/plugins/promptfoo-redteam/plugin.json +0 -16
  48. package/plugins/reactorpro-bridge/index.mjs +0 -499
  49. package/plugins/reactorpro-bridge/plugin.json +0 -26
  50. package/plugins/reactorpro-bridge/reactorpro-bridge.extreme.spec.mts +0 -409
  51. package/plugins/reactorpro-bridge/reactorproAgent.mjs +0 -399
  52. package/plugins/request-router/index.d.mts +0 -9
  53. package/plugins/request-router/index.mjs +0 -239
  54. package/plugins/request-router/plugin.json +0 -10
  55. package/plugins/sample-k8s-slo/index.ts +0 -58
  56. package/plugins/sample-k8s-slo/plugin.json +0 -11
  57. package/plugins/sop-assistant/index.d.mts +0 -9
  58. package/plugins/sop-assistant/index.mjs +0 -325
  59. package/plugins/sop-assistant/plugin.json +0 -10
  60. package/plugins/synapse-bridge/index.mjs +0 -484
  61. package/plugins/synapse-bridge/plugin.json +0 -29
  62. package/plugins/synapse-bridge/synapse-bridge.extreme.spec.mjs +0 -204
  63. package/plugins/synapse-bridge/synapseAgent.extreme.spec.mjs +0 -236
  64. package/plugins/synapse-bridge/synapseAgent.mjs +0 -254
  65. package/plugins/web-intel/index.mjs +0 -381
  66. package/plugins/web-intel/plugin.json +0 -28
  67. package/plugins/web-intel/sidecar.mjs +0 -134
  68. package/plugins/web-intel/web-intel.extreme.spec.ts +0 -263
  69. package/plugins/web-intel/wigoloClient.mjs +0 -145
package/validate.js ADDED
@@ -0,0 +1,263 @@
1
+ /**
2
+ * Grounding + extraction validation — the Node port of the Python
3
+ * `needle` validation core (needle/__init__.py), kept behaviour-compatible:
4
+ *
5
+ * * sourceYears() — years literally written in the input
6
+ * * licensedYears() — those years, plus the system date's year when the
7
+ * input reasons relatively ("tomorrow", "next week")
8
+ * * walkGrounding() — date arguments must carry a licensed year
9
+ * * groundedNumberPaths() — numbers a value may carry without being invented
10
+ * * annotateUngrounded() — the engine's own fabrication report, re-checked
11
+ * * validateExtraction() — strict mode: raise instead of returning
12
+ * ungrounded values silently
13
+ *
14
+ * Python raises ExtractionValidationError; so do we.
15
+ */
16
+ 'use strict';
17
+
18
+ class ExtractionValidationError extends Error {
19
+ constructor(message) {
20
+ super(message);
21
+ this.name = 'ExtractionValidationError';
22
+ }
23
+ }
24
+
25
+ const MONTHS =
26
+ '(?:jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|' +
27
+ 'jun(?:e)?|jul(?:y)?|aug(?:ust)?|sep(?:t(?:ember)?)?|' +
28
+ 'oct(?:ober)?|nov(?:ember)?|dec(?:ember)?)';
29
+
30
+ // The number after a day+month is its year, unless it is the hour of a time
31
+ // ("5 June 19:30", "June 5 7 pm"): no ISO argument can carry that as a year,
32
+ // so licensing it would reject every date. Year-first numeric dates only
33
+ // (2024-03-15) — a day/month-first date must not mint its leading component.
34
+ const SOURCE_YEAR_PATTERNS = [
35
+ new RegExp(`\\b\\d{1,2}(?:st|nd|rd|th)?\\s+${MONTHS}[\\s,]+(\\d{1,4})(?![0-9A-Za-z]|:\\d|\\s*[ap]\\.?m\\b)`, 'g'),
36
+ new RegExp(`\\b${MONTHS}\\s+\\d{1,2}(?:st|nd|rd|th)?\\s*,?\\s+(\\d{1,4})(?![0-9A-Za-z]|:\\d|\\s*[ap]\\.?m\\b)`, 'g'),
37
+ new RegExp(`\\b${MONTHS}[\\s,]+(\\d{3,4})(?![0-9A-Za-z])`, 'g'),
38
+ /\byear\s+(\d{1,4})(?![0-9A-Za-z])/g,
39
+ /(?<![0-9])(\d{4})(?=[-/]\d{1,2}[-/]\d{1,2}(?![0-9]))/g,
40
+ ];
41
+
42
+ const RELATIVE_CUE = new RegExp(
43
+ '\\b(today|tonight|tomorrow|yesterday|next|this|coming|now|in \\d+ (?:days?|weeks?|months?|years?)|' +
44
+ 'monday|tuesday|wednesday|thursday|friday|saturday|sunday)\\b', 'i');
45
+
46
+ const NUMBER_TOKEN =
47
+ /(?<![\w.,])(?:[-+]?\d{1,3}(?:,\d{3})+(?:\.\d+)?|[-+]?\d+(?:\.\d+)?)(?!\d)/g;
48
+
49
+ const DATE_FACT =
50
+ /date:\s*\d{4}-\d{2}-\d{2}(?:\s+[A-Za-z]{3})?(?:\s+\d{2}:\d{2})?|\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2})?/g;
51
+
52
+ /** Years literally written in the text. */
53
+ function sourceYears(text) {
54
+ const lowered = String(text || '').toLowerCase();
55
+ const years = new Set();
56
+ for (const pattern of SOURCE_YEAR_PATTERNS) {
57
+ pattern.lastIndex = 0;
58
+ let match;
59
+ while ((match = pattern.exec(lowered)) !== null) {
60
+ years.add(parseInt(match[1], 10));
61
+ }
62
+ }
63
+ return years;
64
+ }
65
+
66
+ function relativeCue(text) {
67
+ return !!text && RELATIVE_CUE.test(String(text));
68
+ }
69
+
70
+ /** Years a date argument may carry without being fabricated. */
71
+ function licensedYears(seenYears, system, relative = true) {
72
+ const years = new Set(seenYears || []);
73
+ if (years.size && system && relative) {
74
+ for (const year of sourceYears(system)) years.add(year);
75
+ }
76
+ return years;
77
+ }
78
+
79
+ function schemaParameters(schema) {
80
+ if (schema && typeof schema === 'object' && schema.parameters) return schema.parameters;
81
+ return schema || {};
82
+ }
83
+
84
+ function resolveRef(node, root) {
85
+ const seen = new Set();
86
+ let current = node;
87
+ while (current && typeof current === 'object' && current.$ref) {
88
+ if (seen.has(current.$ref)) break;
89
+ seen.add(current.$ref);
90
+ const parts = String(current.$ref).replace(/^#\//, '').split('/');
91
+ let target = root;
92
+ for (const part of parts) {
93
+ target = (target || {})[part.replace(/~1/g, '/').replace(/~0/g, '~')] || {};
94
+ }
95
+ if (target === current) break;
96
+ current = target;
97
+ }
98
+ return current;
99
+ }
100
+
101
+ /** Date arguments must carry a year that is licensed by the input. */
102
+ function walkGrounding(schema, arguments_, years) {
103
+ const root = schemaParameters(schema);
104
+ const checked = new Set();
105
+ const failures = new Set();
106
+
107
+ const walk = (value, node, path) => {
108
+ node = resolveRef(node, root) || {};
109
+ const variants = node.anyOf || node.oneOf || [];
110
+ const concrete = variants.filter((v) => (resolveRef(v, root) || {}).type !== 'null');
111
+ if (concrete.length === 1) node = resolveRef(concrete[0], root) || {};
112
+
113
+ if ((node.format === 'date' || node.format === 'date-time') && typeof value === 'string') {
114
+ const match = /^(\d{4})-/.exec(value);
115
+ if (match && years.size) {
116
+ checked.add(path);
117
+ if (!years.has(parseInt(match[1], 10))) failures.add(path);
118
+ }
119
+ return;
120
+ }
121
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
122
+ const properties = node.properties || {};
123
+ for (const [key, item] of Object.entries(value)) {
124
+ if (key in properties) walk(item, properties[key], path ? `${path}.${key}` : key);
125
+ }
126
+ } else if (Array.isArray(value) && node.items) {
127
+ value.forEach((item, index) => walk(item, node.items, `${path}[${index}]`));
128
+ }
129
+ };
130
+
131
+ walk(arguments_, root, '');
132
+ return { checked, failures };
133
+ }
134
+
135
+ function temporalGrounding(text, schema, arguments_, system) {
136
+ const years = licensedYears(sourceYears(text), system, relativeCue(text));
137
+ return walkGrounding(schema, arguments_, years);
138
+ }
139
+
140
+ function withoutDateFacts(text) {
141
+ return String(text || '').replace(DATE_FACT, ' ');
142
+ }
143
+
144
+ /** (path, value) for every numeric leaf, arguments-relative. */
145
+ function numericPaths(arguments_, path = '') {
146
+ const out = [];
147
+ const walk = (value, currentPath) => {
148
+ if (typeof value === 'boolean') return;
149
+ if (typeof value === 'number' && Number.isFinite(value)) {
150
+ out.push([currentPath, value]);
151
+ return;
152
+ }
153
+ if (Array.isArray(value)) {
154
+ value.forEach((item, index) => walk(item, `${currentPath}[${index}]`));
155
+ } else if (value && typeof value === 'object') {
156
+ for (const [key, item] of Object.entries(value)) {
157
+ walk(item, currentPath ? `${currentPath}.${key}` : String(key));
158
+ }
159
+ }
160
+ };
161
+ walk(arguments_, path);
162
+ return out;
163
+ }
164
+
165
+ /** Numeric values written in the source texts (separators normalized). */
166
+ function sourceNumbers(...sources) {
167
+ const text = sources
168
+ .map((source) => withoutDateFacts(source))
169
+ .filter((source) => source)
170
+ .join('\n');
171
+ const numbers = new Set();
172
+ NUMBER_TOKEN.lastIndex = 0;
173
+ let match;
174
+ while ((match = NUMBER_TOKEN.exec(text)) !== null) {
175
+ const normalized = match[0].replace(/,/g, '');
176
+ const asNumber = Number(normalized);
177
+ if (Number.isFinite(asNumber)) numbers.add(asNumber);
178
+ }
179
+ return numbers;
180
+ }
181
+
182
+ function groundedNumberPaths(arguments_, ...sources) {
183
+ const numbers = sourceNumbers(...sources);
184
+ const grounded = new Set();
185
+ if (!numbers.size) return grounded;
186
+ for (const [path, value] of numericPaths(arguments_)) {
187
+ if (numbers.has(value)) grounded.add(path);
188
+ }
189
+ return grounded;
190
+ }
191
+
192
+ /** The engine's fabrication report, grouped by tool. */
193
+ function ungroundedPaths(response) {
194
+ const validation = (response && response.validation) || {};
195
+ const grouped = new Map();
196
+ for (const name of validation.ungrounded || []) {
197
+ const text = String(name);
198
+ const dot = text.indexOf('.');
199
+ const tool = dot === -1 ? text : text.slice(0, dot);
200
+ const path = dot === -1 ? text : text.slice(dot + 1);
201
+ if (!grouped.has(tool)) grouped.set(tool, new Set());
202
+ grouped.get(tool).add(path || tool);
203
+ }
204
+ return grouped;
205
+ }
206
+
207
+ /** Add engine-reported ungrounded values to response.validation.ungrounded. */
208
+ function annotateUngrounded(response, toolSchemas, seenYears, system, text) {
209
+ const calls = response.function_calls || [];
210
+ const years = licensedYears(seenYears, system, text !== undefined && text !== null ? relativeCue(text) : true);
211
+ if (!calls.length || !years.size) return;
212
+ const schemas = new Map();
213
+ for (const entry of toolSchemas || []) {
214
+ if (entry && entry.name) schemas.set(entry.name, entry);
215
+ }
216
+ const found = [];
217
+ for (const call of calls) {
218
+ const schema = schemas.get(call.name);
219
+ if (!schema) continue;
220
+ const { failures } = walkGrounding(schema, call.arguments || {}, years);
221
+ for (const path of [...failures].sort()) found.push(`${call.name}.${path}`);
222
+ }
223
+ if (!found.length) return;
224
+ const validation = response.validation || {};
225
+ const existing = [...(validation.ungrounded || [])];
226
+ validation.ungrounded = existing.concat(found.filter((name) => !existing.includes(name)));
227
+ response.validation = validation;
228
+ }
229
+
230
+ /** Strict mode: raise instead of returning values the input does not license. */
231
+ function validateExtraction(text, schema, arguments_, response, system) {
232
+ const { checked, failures } = temporalGrounding(text, schema, arguments_, system);
233
+ const validation = (response && response.validation) || {};
234
+ const flagged = validation.ungrounded || [];
235
+ const grounded = flagged.length ? groundedNumberPaths(arguments_, text, system) : new Set();
236
+ for (const name of flagged) {
237
+ const path = String(name).includes('.') ? String(name).split('.').slice(1).join('.') : String(name);
238
+ if (grounded.has(path)) continue;
239
+ if (!checked.has(path) || failures.has(path)) failures.add(path);
240
+ }
241
+ if (validation.negation) failures.add('negated request');
242
+ if (failures.size) {
243
+ const detail = [...failures].sort().join(', ');
244
+ throw new ExtractionValidationError(
245
+ `extraction returned values not grounded in the input: ${detail}`);
246
+ }
247
+ return arguments_;
248
+ }
249
+
250
+ module.exports = {
251
+ ExtractionValidationError,
252
+ sourceYears,
253
+ relativeCue,
254
+ licensedYears,
255
+ walkGrounding,
256
+ temporalGrounding,
257
+ groundedNumberPaths,
258
+ sourceNumbers,
259
+ numericPaths,
260
+ ungroundedPaths,
261
+ annotateUngrounded,
262
+ validateExtraction,
263
+ };