-
Notifications
You must be signed in to change notification settings - Fork 35
Description
Hi ,
I’m writing to share a set of advanced features I’ve implemented in my local fork of Cannoli. I have heavily modified the core logic to transform Cannoli into a powerful logic engine capable of executing JavaScript and handling complex JSON data flows.
Reason for not submitting a PR: These changes involve invasive modifications to factory.ts, node type mappings, and the execution loop (e.g., handling Mock vs. Real runs). Because this might introduce instability or conflict with your core roadmap, I am not submitting a Pull Request. However, I hope these concepts might inspire future official features.
Here is the technical summary of what I implemented:
- JsCodeNode (Mapped to Red Color "1")
I repurposed the Red node to act as a JavaScript sandbox with full access to the Obsidian environment.
Capabilities: Supports async/await, app (Obsidian API), plugins, and Cannoli context variables.
Execution Safety: I solved the issue where code ran twice (during validation and execution) by checking if (this.run.isMock) return; inside the execution logic.
Context Handling: Solved JS reserved keyword conflicts by exposing the node context as _this instead of this.
- Advanced Logic Branching
The JsCodeNode acts as a decision engine. It supports two return types to control "Choice Arrows" (Yellow/3):
Simple String Return:
Returns "success" → Triggers the arrow labeled success.
Object Return (Logic + Payload):
Returns { choice: "next", data: [1,2,3], user: "me" }.
The choice property dictates the path.
The rest of the object is passed as a payload to the next node.
- Enhanced Data Access in Content/Formatter Nodes
I implemented a parser that allows downstream nodes to access the JSON objects returned by the JsCodeNode using both Dot Notation and JSONPath.
Example Scenario:
JsCodeNode Returns: { "choice": "next", "times": [1, 2, 3], "name": "test", "store": {...} }
Downstream Node Syntax Support:
Handlebars
{{option}} // Returns the full JSON object string
{{option.times}} // Returns "[1, 2, 3]" (Dot Notation)
{{option.name}} // Returns "test"
{{option.$.times}} // Returns "[1, 2, 3]" (JSONPath support)
{{option.$.store.book[*].author}} // Complex JSONPath queries
4. Smart Context Variables (Text-Generator style)
I also included {{TG_SELECTION}}, {{PREV_LINE}}, and {{NEXT_LINE}} to give the LLM/Code nodes better awareness of the user's cursor position in the active note.Similar to obsidian-textgenerator-plugin
These changes make Cannoli significantly more powerful for automation tasks that require real logic programming alongside LLM generation. I’m happy to share specific snippets (like the JSONPath implementation or the Mock run fix) if you are interested.
Thanks for building such an extensible tool!
Best regards,