flownav 0.2.0 → 0.2.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.
package/README.md CHANGED
@@ -185,12 +185,15 @@ Tool replies are written for an agent to act on. If a name matches several nodes
185
185
  $ flownav explain order
186
186
  error: "order" matches 5 nodes. Do not guess: ask the user which one they mean. Then use the workflow:node form.
187
187
  1. Order intake › Order Webhook [webhook] use: wf-orders:Order Webhook
188
+ Webhook POST /orders (responseNode) · group "Intake" · starts the workflow
188
189
  2. Order intake › Is Large Order [if] use: wf-orders:Is Large Order
190
+ IF 1 condition(s) · group "Intake" · after: Normalize
189
191
  3. Order intake › Save Order [googleSheets] use: wf-orders:Save Order
192
+ googleSheets: append · group "Intake" · after: Is Large Order
190
193
  ...
191
194
  ```
192
195
 
193
- If a partial name matches exactly one node, it resolves but the reply starts with a `NOTE:` asking the agent to confirm with the user before changing anything. To search a family of workflows, use `flownav find --match "<part of workflow name>" --name "<part of node name>"` (`--name` searches node names only; `--text` also searches parameters and code). The installed skill tells the agent to stop and ask in these cases. How reliably an agent follows that depends on the agent.
196
+ Each candidate carries one line of context (what the node does, its sticky-note group, and what feeds it or what it plugs into), so the agent can ask a specific question instead of "which one?". Workflow candidates show their trigger types and whether they are active. If a partial name matches exactly one node, it resolves but the reply starts with a `NOTE:` asking the agent to confirm with the user before changing anything. To search a family of workflows, use `flownav find --match "<part of workflow name>" --name "<part of node name>"` (`--name` searches node names only; `--text` also searches parameters and code). The installed skill tells the agent to stop and ask in these cases. How reliably an agent follows that depends on the agent.
194
197
 
195
198
  ## Reading code in small pieces
196
199
 
package/dist/graph.js CHANGED
@@ -66,7 +66,14 @@ export class G {
66
66
  const hits = exact.length ? exact : part;
67
67
  if (!hits.length)
68
68
  throw new Error(`No workflow matches "${q}". Run flownav_scan to list workflows.`);
69
- const rows = hits.slice(0, 10).map((w, i) => ` ${i + 1}. ${w.name} [id ${w.id}, ${w.nodeCount} nodes]`);
69
+ const rows = hits.slice(0, 10).flatMap((w, i) => {
70
+ const trig = [...new Set(this.nodesOf(w.id).filter((n) => n.trigger).map((n) => shortType(n.type)))];
71
+ const state = w.active === undefined ? '' : w.active ? ', active' : ', inactive';
72
+ return [
73
+ ` ${i + 1}. ${w.name} [id ${w.id}, ${w.nodeCount} nodes${state}]`,
74
+ ` ${trig.length ? `started by: ${trig.slice(0, 4).join(', ')}` : 'no trigger of its own'}${w.errorWorkflow ? ' · has an error workflow' : ''}`,
75
+ ];
76
+ });
70
77
  if (hits.length > 10)
71
78
  rows.push(` ... and ${hits.length - 10} more`);
72
79
  throw new Error([`"${q}" matches ${hits.length} workflows. ${ASK} Then use its id.`, ...rows,
@@ -76,8 +83,32 @@ export class G {
76
83
  resolveNode(q) {
77
84
  return this.resolveNodeEx(q).node;
78
85
  }
86
+ /** One line of context so the agent can tell candidates apart and ask a sharper question. */
87
+ contextLine(n) {
88
+ const bits = [n.summary];
89
+ if (n.group)
90
+ bits.push(`group "${n.group}"`);
91
+ if (n.disabled)
92
+ bits.push('disabled');
93
+ const names = (ids) => [...new Set(ids.map((id) => this.nodeById.get(id)?.name ?? id))];
94
+ const from = names(this.inE(n.id, ['main', 'capability']).map((e) => e.from));
95
+ const into = names(this.outE(n.id, ['capability']).map((e) => e.to));
96
+ if (n.trigger)
97
+ bits.push('starts the workflow');
98
+ else if (from.length)
99
+ bits.push(`after: ${from.slice(0, 2).join(', ')}${from.length > 2 ? ` (+${from.length - 2})` : ''}`);
100
+ else if (into.length)
101
+ bits.push(`plugs into: ${into.slice(0, 2).join(', ')}`);
102
+ else
103
+ bits.push('not connected to anything');
104
+ const line = bits.join(' · ');
105
+ return line.length > 150 ? `${line.slice(0, 149)}…` : line;
106
+ }
79
107
  ambiguousNodes(q, hits) {
80
- const rows = hits.slice(0, 10).map((n, i) => ` ${i + 1}. ${this.g.workflows[n.wf]?.name ?? n.wf} › ${n.name} [${shortType(n.type)}] use: ${n.wf}:${n.name}`);
108
+ const rows = hits.slice(0, 10).flatMap((n, i) => [
109
+ ` ${i + 1}. ${this.g.workflows[n.wf]?.name ?? n.wf} › ${n.name} [${shortType(n.type)}] use: ${n.wf}:${n.name}`,
110
+ ` ${this.contextLine(n)}`,
111
+ ]);
81
112
  if (hits.length > 10)
82
113
  rows.push(` ... and ${hits.length - 10} more`);
83
114
  return [`"${q}" matches ${hits.length} nodes. ${ASK} Then use the workflow:node form.`, ...rows].join('\n');
package/dist/viewer.js CHANGED
@@ -126,10 +126,11 @@ aside li button{width:100%;text-align:left;margin:2px 0;border-radius:6px;overfl
126
126
  <script>
127
127
  (function () {
128
128
  var D = JSON.parse(document.getElementById('data').textContent);
129
- var NS = 'http://www.w3.org/2000/svg';
129
+ var svg = document.getElementById('svg'), vp = document.getElementById('vp'), panel = document.getElementById('panel');
130
+ // The page's own <svg> element already carries the SVG namespace; reuse it for new elements.
131
+ var NS = svg.namespaceURI;
130
132
  var NW = 176, NH = 38, COLW = 250, ROWH = 62, PAD = 36, HEAD = 34, GAP = 50;
131
133
  var LAYER = { main: 1, capability: 1, calls: 1, on_error: 1, webhook_calls: 1 };
132
- var svg = document.getElementById('svg'), vp = document.getElementById('vp'), panel = document.getElementById('panel');
133
134
 
134
135
  function el(tag, attrs, parent, text) {
135
136
  var e = document.createElementNS(NS, tag);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flownav",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "See what references an n8n node before you rename it. A typed graph of your workflows with a CLI and an MCP server, so AI agents read a few lines instead of the whole workflow JSON.",
5
5
  "author": "Omer Turkenits",
6
6
  "license": "MIT",