Skip to content

feat(frontend): show node output reference hint in config modal#23

Open
LukasHirt wants to merge 2 commits into
mainfrom
feat/node-output-reference-hint
Open

feat(frontend): show node output reference hint in config modal#23
LukasHirt wants to merge 2 commits into
mainfrom
feat/node-output-reference-hint

Conversation

@LukasHirt

Copy link
Copy Markdown
Collaborator

Summary

Users configuring any node in the workflow canvas had no reliable way to learn the exact {{...}} template syntax needed to reference that node's output from a downstream node. The only hints were scattered placeholder strings on a couple of specific fields (LLM prompt/comment/message), not a consistent, always-visible piece of UI, and their accuracy had never been verified against the executor.

Investigation (executor.go ground truth)

Read backend/pkg/executor/executor.go in full. Findings:

  • LLM node: runLLM() writes vars["llm.output"] = output (line 172) and sets result.Output on the NodeResult. So {{llm.output}} genuinely works today. Confirmed by the pre-existing TestRunTriggerLLMAction test, which already asserts a downstream action node receives the rendered {{llm.output}}.
  • Action nodes (tag/comment/move/copy/rename/notify): every case in runAction() set result.Output on the execution-result record, but none of them wrote anything into the shared vars map. I proved this with a new failing test (TestActionOutputIsReferenceableDownstream, added first per TDD) that chains a tag action into a comment action referencing {{tag.output}} — before the fix, the comment literally contained the unexpanded string {{tag.output}}. So action outputs were not referenceable at all prior to this PR, despite result.Output existing — a real trap for anyone assuming otherwise.
  • WorkflowNodeData.outputVariable (frontend/src/types/workflow.ts): grepped the whole repo — it's declared on the type but never read anywhere, frontend or backend. runLLM() unconditionally uses the literal key "llm.output" regardless of this field. It currently has zero effect on runtime behavior, so the new hint intentionally does not offer a "customized variable name" variant — that would have been fictional.
  • Trigger node: file.name / file.content are populated into vars once per run whenever a resourcePath is supplied (line 66-76), independent of trigger type. This is meaningfully "the trigger's output" and is surfaced the same way.

Changes

Backend (backend/pkg/executor/executor.go) — small, scoped fix so the new UI hint is true rather than aspirational: each action case now also writes its result into vars under "<actionType>.output" (tag.output, comment.output, move.output, copy.output, rename.output, notify.output), mirroring the existing llm.output convention (a single global key per node-kind, not per node-id — same characteristic the existing llm.output key already has). Added TestActionOutputIsReferenceableDownstream covering this end-to-end through a chained tag → comment workflow.

Frontend (frontend/src/components/NodeDetailsPanel.vue) — added a persistent "Output" section, shown for every node type, stating only verified-correct tokens:

  • LLM: {{llm.output}}
  • tag: {{tag.output}}, comment: {{comment.output}}, move: {{move.output}}, copy: {{copy.output}}, rename: {{rename.output}}, notify: {{notify.output}}
  • trigger: {{file.name}}, {{file.content}}

Added frontend/tests/unit/NodeDetailsPanel.spec.ts — the first component-mount test in this package, using @vue/test-utils + createGettext() (real gettext plugin, since useGettext() throws without it) with oc-icon/oc-button/oc-text-input stubbed (host-shell design-system components unavailable in unit tests). Covers LLM, tag/move/notify action nodes, and a trigger node.

Both new tests were written first, confirmed to fail for the right reason (fictional/missing wiring), then made to pass.

Test plan

  • cd backend && go test ./... — all packages pass, including new TestActionOutputIsReferenceableDownstream
  • cd backend && go vet ./... — clean
  • cd frontend && npm run test:unit — 3 files / 9 tests pass
  • cd frontend && npm run check:types — clean
  • cd frontend && npm run lint — clean

Scope note: did not touch node categorization, the "+" button, node positioning, the OK button, or auto-open-on-add behavior — kept strictly to the output-hint concern.

@LukasHirt
LukasHirt requested a review from a team as a code owner July 24, 2026 16:05
@LukasHirt LukasHirt self-assigned this Jul 24, 2026
mzner
mzner previously approved these changes Jul 24, 2026
Action nodes (tag/comment/move/copy/rename/notify) already recorded their
result on the NodeResult execution record, but never wrote it into the
shared vars map that {{...}} template rendering reads from — unlike LLM
nodes, whose output is wired in via vars["llm.output"]. That meant an
action's result was, in practice, never referenceable from a downstream
node's template, even though nothing in the code or UI signaled that.

Mirror the llm.output pattern by writing each action's result into vars
under "<actionType>.output" (tag.output, comment.output, move.output,
copy.output, rename.output, notify.output) right where result.Output is
already set. This makes the upcoming frontend output hint truthful
instead of aspirational.

Signed-off-by: Lukas Hirt <info@hirt.cz>
Users configuring a node had no reliable way to learn the exact {{...}}
syntax needed to reference its output from a downstream node — only a
couple of fields carried it as scattered placeholder text.

Add a persistent "Output" section to NodeDetailsPanel.vue, shown for
every node type, that states the verified-correct template token(s):
- llm node: {{llm.output}}
- action nodes: {{tag.output}}, {{comment.output}}, {{move.output}},
  {{copy.output}}, {{rename.output}}, {{notify.output}} — matching the
  vars keys the executor now writes (see the paired backend commit)
- trigger node: {{file.name}} / {{file.content}}, available whenever
  the run targets a specific file

The WorkflowNodeData.outputVariable field was checked and confirmed to
have no effect on runtime behavior (backend/pkg/executor/executor.go
hardcodes the "llm.output" key regardless of it), so the LLM hint
intentionally does not offer a "customized" variant of the token.

Adds a Vitest component-mount test for NodeDetailsPanel.vue (the first
of its kind in this package) covering LLM, action, and trigger nodes.

Signed-off-by: Lukas Hirt <info@hirt.cz>
@LukasHirt
LukasHirt force-pushed the feat/node-output-reference-hint branch from de4c87c to bcc04fc Compare July 24, 2026 20:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants