@patcherly/nodejs-connector 2.2.3 → 2.2.5

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/README.md CHANGED
@@ -21,6 +21,20 @@ npx patcherly login
21
21
  patcherly login
22
22
  ```
23
23
 
24
+ ## Test ingest
25
+
26
+ After pairing, verify the pipeline without waiting for a real exception. In your [Patcherly dashboard](https://app.patcherly.com/targets), open **Targets → your target → Test Mode** (30-minute window per target), then run:
27
+
28
+ ```bash
29
+ npx patcherly send-test
30
+ ```
31
+
32
+ The sample is tagged `is_test_sample` — it does not affect metrics or notifications. See [Verify ingest with send-test](https://help.patcherly.com/connectors/nodejs/#verify-ingest-end-to-end-with-patcherly-send-test) in the help center.
33
+
34
+ ## Security
35
+
36
+ OAuth pairing and per-token **HMAC signing**; fix payloads verified before apply. See [Connectors overview](https://help.patcherly.com/connectors/overview/), [Prompt injection protection](https://help.patcherly.com/security/prompt-injection-protection.md), and [Custom sanitiser patterns](https://help.patcherly.com/security/custom-sanitizer-patterns.md). Node.js-specific detail: [Node.js connector — security](https://help.patcherly.com/connectors/nodejs/#hmac-signing).
37
+
24
38
  ## Documentation
25
39
 
26
40
  - [Node.js connector guide](https://help.patcherly.com/connectors/nodejs/)
@@ -1,6 +1,6 @@
1
1
  /**
2
- * AUTO-GENERATED from config/settings_schema.yaml error_type_configurations — do not edit by hand.
3
- * Shared log-line → error_type → severity inference for connector ingest payloads.
2
+ * AUTO-GENERATED from config/settings_schema.yaml + log_ingest_skip_patterns.yaml — do not edit by hand.
3
+ * Shared log-line → error_type → severity inference and pre-ingest noise filtering.
4
4
  */
5
5
  'use strict';
6
6
 
@@ -22,6 +22,58 @@ const DEFAULT_ERROR_TYPE_SEVERITIES = {
22
22
  "warning": "Low",
23
23
  };
24
24
 
25
+ const LOG_INGEST_KEEP_PATTERNS = [
26
+ "PHP\\s+Fatal",
27
+ "PHP\\s+Parse\\s+error",
28
+ "PHP\\s+Recoverable\\s+fatal",
29
+ "^Fatal error:",
30
+ "Maximum execution time|Allowed memory size",
31
+ "Uncaught\\s+\\S*(Error|Exception)",
32
+ "^Traceback\\s",
33
+ "^\\w+(Error|Exception):",
34
+ "^Exception:",
35
+ "^Error:\\s",
36
+ "Unhandled\\s+(Promise\\s+)?Rejection",
37
+ "uncaughtException|uncaught exception",
38
+ "Assertion failed",
39
+ "File\\s+[\"']",
40
+ "^\\s*#\\d+\\s+",
41
+ "^\\s+at\\s+",
42
+ "\"level\"\\s*:\\s*\"(error|fatal|critical)\"",
43
+ "\"level\"\\s*:\\s*50\\b",
44
+ "\"severity\"\\s*:\\s*\"(ERROR|CRITICAL|FATAL)\"",
45
+ ].map((p) => new RegExp(p, 'i'));
46
+ const LOG_INGEST_SKIP_PHP_PREFIX = new RegExp("^PHP\\s+(Notice|Deprecated|Warning|Strict\\s+standards|Info)\\s*:", 'i');
47
+ const LOG_INGEST_SKIP_PATTERNS = [
48
+ "^\\(node:\\d+\\)\\s+\\[DEP\\d+\\]",
49
+ "DeprecationWarning:",
50
+ "^UserWarning:",
51
+ "^\\[info\\]",
52
+ "^INFO:",
53
+ "^DEBUG:",
54
+ ].map((p) => new RegExp(p, 'i'));
55
+ const LOG_INGEST_SKIP_SUBSTRINGS = ["auditor:scan", "\"kind\":\"installed-plugin\""];
56
+ const LOG_INGEST_FAILURE_SIGNAL = new RegExp("\\b(error|exception|traceback|fatal|critical|panic|failed|failure|rejection|errno|segfault)\\b|^\\w+(Error|Exception):", 'i');
57
+
58
+ function shouldSkipLogLineForIngest(logLine) {
59
+ const line = String(logLine || '').trim();
60
+ if (!line) return true;
61
+ for (const re of LOG_INGEST_KEEP_PATTERNS) {
62
+ if (re.test(line)) return false;
63
+ }
64
+ if (LOG_INGEST_SKIP_PHP_PREFIX && LOG_INGEST_SKIP_PHP_PREFIX.test(line)) return true;
65
+ for (const re of LOG_INGEST_SKIP_PATTERNS) {
66
+ if (re.test(line)) return true;
67
+ }
68
+ const lower = line.toLowerCase();
69
+ for (const sub of LOG_INGEST_SKIP_SUBSTRINGS) {
70
+ if (sub && lower.includes(String(sub).toLowerCase())) return true;
71
+ }
72
+ if (!LOG_INGEST_FAILURE_SIGNAL.test(line)) return true;
73
+ return false;
74
+ }
75
+
76
+
25
77
  function inferErrorTypeFromLogLine(logLine) {
26
78
  const line = String(logLine || '').toLowerCase();
27
79
  if (line.includes('parse error')) return 'parse';
@@ -48,6 +100,7 @@ function buildIngestSeverityFields(logLine) {
48
100
 
49
101
  module.exports = {
50
102
  DEFAULT_ERROR_TYPE_SEVERITIES,
103
+ shouldSkipLogLineForIngest,
51
104
  inferErrorTypeFromLogLine,
52
105
  severityForErrorType,
53
106
  buildIngestSeverityFields,
package/node_agent.js CHANGED
@@ -20,7 +20,7 @@ const path = require('path');
20
20
  const { execFile } = require('child_process');
21
21
  const util = require('util');
22
22
  const execFileAsync = util.promisify(execFile);
23
- const { buildIngestSeverityFields } = require('./lib/ingest_severity.js');
23
+ const { buildIngestSeverityFields, shouldSkipLogLineForIngest } = require('./lib/ingest_severity.js');
24
24
  const apiPaths = require('./lib/api_paths.js');
25
25
  const { namedPaths, appPath } = apiPaths;
26
26
 
@@ -193,7 +193,7 @@ const { DEFAULT_API_URL, getConfiguredServerUrl, isExplicitApiBaseConfigured } =
193
193
  * update-release-latest.yml workflow so the value baked into every released tarball matches
194
194
  * the GitHub release tag. Reported to the API on every context upload.
195
195
  */
196
- const PATCHERLY_CONNECTOR_VERSION = '2.2.3';
196
+ const PATCHERLY_CONNECTOR_VERSION = '2.2.5';
197
197
  let CENTRAL_SERVER_URL = getConfiguredServerUrl();
198
198
  const IDS_PATH = process.env.PATCHERLY_IDS_PATH || path.join(__dirname, 'patcherly_ids.json');
199
199
  const QUEUE_PATH = process.env.PATCHERLY_QUEUE_PATH || path.join(__dirname, 'patcherly_queue.jsonl');
@@ -1004,7 +1004,7 @@ function extractErrorContext(logData) {
1004
1004
  const lines = logData.split('\n');
1005
1005
  const events = [];
1006
1006
  let current = [];
1007
- const startOrCont = /^(Traceback\s|File\s+["']|Exception:|Error:\s|PHP\s+Fatal|PHP\s+Warning|^\s+at\s+|\s*#\d+\s+)/i;
1007
+ const startOrCont = /^(Traceback\s|File\s+["']|Exception:|Error:\s|PHP\s+Fatal|^\s+at\s+|\s*#\d+\s+)/i;
1008
1008
  const errorWord = /\b(error|exception|traceback|fatal)\b/i;
1009
1009
  // Python exception type line (e.g. "ValueError: bad") — treat as continuation when in a block
1010
1010
  const pythonExceptionLine = /^\w+(?:Error|Exception):\s/i;
@@ -1033,7 +1033,10 @@ function extractErrorContext(logData) {
1033
1033
  }
1034
1034
  flush();
1035
1035
  if (events.length === 0) {
1036
- const errorLines = lines.filter(l => /error/i.test(l));
1036
+ const errorLines = lines.filter(l =>
1037
+ /\b(error|exception|traceback|fatal|critical|failed|failure|rejection)\b/i.test(l)
1038
+ || /^\s*\w+(Error|Exception):/i.test(l)
1039
+ );
1037
1040
  if (errorLines.length) events.push(errorLines.join('\n'));
1038
1041
  }
1039
1042
  return events;
@@ -1261,6 +1264,10 @@ async function processError(errorContext) {
1261
1264
  // ingest (errorContext is string or object; server expects log_line string)
1262
1265
  const logLine = typeof errorContext === 'string' ? errorContext : JSON.stringify(errorContext);
1263
1266
  const logLineSanitized = sanitizeLogLineForIngest(logLine);
1267
+ if (shouldSkipLogLineForIngest(logLineSanitized)) {
1268
+ console.log('Non-error log noise skipped.');
1269
+ return;
1270
+ }
1264
1271
  const payload = { log_line: logLineSanitized, source: 'log_monitor' };
1265
1272
  Object.assign(payload, buildIngestSeverityFields(logLineSanitized));
1266
1273
  if (TENANT_ID && TARGET_ID){ payload.tenant_id = TENANT_ID; payload.target_id = TARGET_ID; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patcherly/nodejs-connector",
3
- "version": "2.2.3",
3
+ "version": "2.2.5",
4
4
  "description": "Patcherly detects bugs in real time in your app. It creates a customized AI patch, and once you approve it, backs up your code, fixes it & tests the patch for you. If anything is off, it rolls back the changes automatically, or you can always roll it back in a click. Website: https://patcherly.com · Docs: https://help.patcherly.com/connectors/nodejs/",
5
5
  "license": "MIT",
6
6
  "homepage": "https://patcherly.com",