@tbrandenburg/node-red-agents 0.4.0 → 0.4.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.
@@ -715,7 +715,21 @@ module.exports = function (RED) {
715
715
  "",
716
716
  );
717
717
  });
718
- return substituteInputs(raw, inputsMap);
718
+ // issue #29: warn once per distinct unmatched $INPUTS.<name>
719
+ // token found in this run (de-duplicated so a typo'd token
720
+ // repeated in `arguments` doesn't spam the log) -- purely
721
+ // additive observability, the substituted text itself (and
722
+ // thus the eventual invocation) is unchanged.
723
+ const unmatchedNames = new Set();
724
+ const substituted = substituteInputs(raw, inputsMap, (name) =>
725
+ unmatchedNames.add(name),
726
+ );
727
+ unmatchedNames.forEach((name) => {
728
+ node.warn(
729
+ `$INPUTS.${name} has no matching 'inputs' entry and was left unsubstituted`,
730
+ );
731
+ });
732
+ return substituted;
719
733
  })()
720
734
  : undefined,
721
735
  cwd: (() => {
@@ -7,15 +7,26 @@
7
7
  // tokens are left as literal text rather than throwing, so a typo in a
8
8
  // flow's arguments string degrades to visible-but-harmless output instead
9
9
  // of a hard failure.
10
+ //
11
+ // issue #29: this module has no access to the Node-RED `node` object (and
12
+ // unit tests call it directly without a fake node), so it never warns
13
+ // itself -- callers that do have a `node` may pass an optional
14
+ // onUnmatched(name) callback, invoked for every token left as literal text
15
+ // (missing from inputsMap, or present but mapped to null/undefined -- both
16
+ // produce the same visible symptom of a literal token reaching the LLM).
10
17
  const TOKEN_RE = /\$INPUTS\.([A-Za-z0-9_]+)/g;
11
18
 
12
- function substituteInputs(text, inputsMap) {
19
+ function substituteInputs(text, inputsMap, onUnmatched) {
13
20
  if (typeof text !== "string" || !text) return text;
14
21
  const map = inputsMap || {};
15
22
  return text.replace(TOKEN_RE, (match, name) => {
16
- if (!Object.prototype.hasOwnProperty.call(map, name)) return match;
17
- const value = map[name];
18
- return value === undefined || value === null ? match : String(value);
23
+ const hasName = Object.prototype.hasOwnProperty.call(map, name);
24
+ const value = hasName ? map[name] : undefined;
25
+ if (!hasName || value === undefined || value === null) {
26
+ if (typeof onUnmatched === "function") onUnmatched(name);
27
+ return match;
28
+ }
29
+ return String(value);
19
30
  });
20
31
  }
21
32
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tbrandenburg/node-red-agents",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Node-RED nodes for running coding agents (opencode, pi) and GitHub CLI operations from flows.",
5
5
  "keywords": [
6
6
  "node-red",