From fe6da02ad76df2772e72f525c86278dca69c6897 Mon Sep 17 00:00:00 2001 From: Charlie Gillet Date: Mon, 30 Mar 2026 17:11:15 -0700 Subject: [PATCH 1/2] feat(vscode): improve stop button feedback in Pipeline Observability screen Handle TASK_STATE.STOPPING in the control button to show "Stopping..." with a disabled state and distinct orange styling, preventing duplicate clicks and giving immediate visual feedback during pipeline shutdown. Co-Authored-By: Claude Opus 4.6 (1M context) --- apps/vscode/src/providers/views/PageStatus/PageStatus.tsx | 3 +++ apps/vscode/src/providers/views/PageStatus/styles.css | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/apps/vscode/src/providers/views/PageStatus/PageStatus.tsx b/apps/vscode/src/providers/views/PageStatus/PageStatus.tsx index c174c3406..a5262354e 100644 --- a/apps/vscode/src/providers/views/PageStatus/PageStatus.tsx +++ b/apps/vscode/src/providers/views/PageStatus/PageStatus.tsx @@ -350,6 +350,9 @@ export const PageStatus: React.FC = () => { const state = taskStatus?.state ?? TASK_STATE.NONE; const runLabel = tracingEnabled ? 'Run & Trace' : 'Run'; + if (state === TASK_STATE.STOPPING) { + return { label: 'Stopping...', action: 'stop' as const, disabled: true, className: 'action-btn stopping-btn disabled' }; + } if (state === TASK_STATE.RUNNING || state === TASK_STATE.INITIALIZING) { return { label: 'Stop', action: 'stop' as const, disabled: false, className: 'action-btn stop-btn' }; } diff --git a/apps/vscode/src/providers/views/PageStatus/styles.css b/apps/vscode/src/providers/views/PageStatus/styles.css index e45cd5358..9d678f1f0 100644 --- a/apps/vscode/src/providers/views/PageStatus/styles.css +++ b/apps/vscode/src/providers/views/PageStatus/styles.css @@ -306,6 +306,12 @@ background: var(--vscode-errorForeground); } +.action-btn.stopping-btn { + background: var(--vscode-charts-orange); + color: white; + cursor: not-allowed; +} + .action-btn.run-btn { background: var(--vscode-charts-green); color: white; From cb0f2ebc44838b5ab376b5a29e999dc9548b7e9e Mon Sep 17 00:00:00 2001 From: Charlie Gillet Date: Mon, 30 Mar 2026 17:34:04 -0700 Subject: [PATCH 2/2] docs: add example pipeline templates for common AI workflows Co-Authored-By: Claude Opus 4.6 (1M context) --- examples/README.md | 108 ++++++++++++++++++++++++++++ examples/agent-workflow.pipe | 115 ++++++++++++++++++++++++++++++ examples/document-processor.pipe | 51 ++++++++++++++ examples/llm-benchmark.pipe | 93 +++++++++++++++++++++++++ examples/rag-pipeline.pipe | 116 +++++++++++++++++++++++++++++++ 5 files changed, 483 insertions(+) create mode 100644 examples/README.md create mode 100644 examples/agent-workflow.pipe create mode 100644 examples/document-processor.pipe create mode 100644 examples/llm-benchmark.pipe create mode 100644 examples/rag-pipeline.pipe diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 000000000..cada8b1b8 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,108 @@ +# Example Pipeline Templates + +Ready-to-use `.pipe` templates for common AI workflows. Open any template in the RocketRide VS Code extension to view it in the visual canvas builder, or run it programmatically with the Python or TypeScript SDK. + +## Templates + +### rag-pipeline.pipe + +**Full RAG (Retrieval-Augmented Generation) system** with separate ingestion and query flows. + +``` +Ingestion: webhook -> parse -> preprocessor -> embedding -> Qdrant +Query: chat -> embedding -> Qdrant -> prompt -> LLM -> response +``` + +- Ingests documents via webhook, chunks text, embeds with miniLM, and stores in Qdrant +- Answers questions by embedding the query, retrieving relevant documents, and generating an answer with GPT-4o +- Uses the prompt node to merge retrieved context with the user's question + +**Required env vars:** `ROCKETRIDE_OPENAI_KEY`, `ROCKETRIDE_QDRANT_HOST`, `ROCKETRIDE_COLLECTION_NAME` + +--- + +### llm-benchmark.pipe + +**Compare three LLM providers side-by-side** using parallel agent fan-out. + +``` +chat -> agent (OpenAI) -> +chat -> agent (Anthropic) -> response (all answers) +chat -> agent (Gemini) -> +``` + +- Sends the same question to three agents, each backed by a different LLM provider +- All answers are collected into a single response for comparison +- Uses RocketRide, CrewAI, and LangChain agent frameworks + +**Required env vars:** `ROCKETRIDE_OPENAI_KEY`, `ROCKETRIDE_ANTHROPIC_KEY`, `ROCKETRIDE_GEMINI_KEY` + +--- + +### document-processor.pipe + +**Document processing pipeline** with OCR, named entity recognition, and PII anonymization. + +``` +webhook -> parse -> OCR (images) -> NER -> anonymize -> response +``` + +- Accepts documents via webhook and parses all content types +- Runs OCR on extracted images to recover text +- Identifies named entities with NER +- Anonymizes PII (names, addresses, etc.) before returning the cleaned text + +**Required env vars:** None (uses local models) + +--- + +### agent-workflow.pipe + +**Multi-agent pipeline** with hierarchical tool use and a research sub-agent. + +``` +chat -> orchestrator agent -> response + | + +------+------+------+ + | | | | + LLM Memory HTTP Python + | + research agent (sub-agent as tool) + | + +------+------+ + | | | + LLM Memory HTTP +``` + +- An orchestrator agent coordinates tools and delegates to a research sub-agent +- The research sub-agent uses HTTP requests to gather web information +- Each agent has its own LLM and memory for independent reasoning +- The orchestrator uses GPT-4o; the research agent uses Claude + +**Required env vars:** `ROCKETRIDE_OPENAI_KEY`, `ROCKETRIDE_ANTHROPIC_KEY` + +## Getting Started + +1. Copy a template to your project directory +2. Set the required environment variables in your `.env` file +3. Open the `.pipe` file in VS Code with the RocketRide extension, or run it with the SDK: + +**Python:** +```python +from rocketride import RocketRideClient + +client = RocketRideClient() +await client.connect() +result = await client.use(filepath='rag-pipeline.pipe') +``` + +**TypeScript:** +```typescript +import { RocketRideClient } from 'rocketride'; + +const client = new RocketRideClient(); +await client.connect(); +const result = await client.use({ filepath: 'rag-pipeline.pipe' }); +``` + +See the [Pipeline Rules](../docs/agents/ROCKETRIDE_PIPELINE_RULES.md) and [Component Reference](../docs/agents/ROCKETRIDE_COMPONENT_REFERENCE.md) for detailed documentation. diff --git a/examples/agent-workflow.pipe b/examples/agent-workflow.pipe new file mode 100644 index 000000000..d4bd1d420 --- /dev/null +++ b/examples/agent-workflow.pipe @@ -0,0 +1,115 @@ +{ + "components": [ + { + "id": "chat_1", + "provider": "chat", + "config": { "hideForm": true, "mode": "Source", "parameters": {}, "type": "chat" }, + "ui": { "position": { "x": 20, "y": 200 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "agent_rocketride_1", + "provider": "agent_rocketride", + "config": { + "instructions": ["You are an orchestrator agent. Use the available tools and delegate to the research sub-agent when you need to gather information from the web. Synthesize all findings into a clear response."], + "max_waves": 15, + "parameters": {} + }, + "input": [{ "lane": "questions", "from": "chat_1" }], + "ui": { "position": { "x": 240, "y": 200 }, "measured": { "width": 150, "height": 86 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "llm_openai_1", + "provider": "llm_openai", + "config": { + "profile": "openai-4o", + "openai-4o": { "apikey": "${ROCKETRIDE_OPENAI_KEY}" }, + "parameters": {} + }, + "control": [ + { "classType": "llm", "from": "agent_rocketride_1" } + ], + "ui": { "position": { "x": 130, "y": 360 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "memory_internal_1", + "provider": "memory_internal", + "config": { "type": "memory_internal" }, + "control": [ + { "classType": "memory", "from": "agent_rocketride_1" } + ], + "ui": { "position": { "x": 350, "y": 360 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "tool_http_request_1", + "provider": "tool_http_request", + "config": { "type": "tool_http_request" }, + "control": [ + { "classType": "tool", "from": "agent_rocketride_1" } + ], + "ui": { "position": { "x": 570, "y": 360 }, "measured": { "width": 150, "height": 40 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "tool_python_1", + "provider": "tool_python", + "config": { "type": "tool_python" }, + "control": [ + { "classType": "tool", "from": "agent_rocketride_1" } + ], + "ui": { "position": { "x": 790, "y": 360 }, "measured": { "width": 150, "height": 40 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "agent_rocketride_2", + "provider": "agent_rocketride", + "config": { + "instructions": ["You are a research sub-agent. Use the HTTP request tool to gather information from the web. Summarize your findings clearly and return them to the orchestrator."], + "max_waves": 10, + "parameters": {} + }, + "control": [ + { "classType": "tool", "from": "agent_rocketride_1" } + ], + "ui": { "position": { "x": 460, "y": 520 }, "measured": { "width": 150, "height": 86 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "llm_anthropic_1", + "provider": "llm_anthropic", + "config": { + "profile": "claude", + "claude": { "apikey": "${ROCKETRIDE_ANTHROPIC_KEY}" }, + "parameters": {} + }, + "control": [ + { "classType": "llm", "from": "agent_rocketride_2" } + ], + "ui": { "position": { "x": 350, "y": 680 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "memory_internal_2", + "provider": "memory_internal", + "config": { "type": "memory_internal" }, + "control": [ + { "classType": "memory", "from": "agent_rocketride_2" } + ], + "ui": { "position": { "x": 570, "y": 680 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "tool_http_request_2", + "provider": "tool_http_request", + "config": { "type": "tool_http_request" }, + "control": [ + { "classType": "tool", "from": "agent_rocketride_2" } + ], + "ui": { "position": { "x": 790, "y": 680 }, "measured": { "width": 150, "height": 40 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "response_answers_1", + "provider": "response_answers", + "config": { "laneName": "answers" }, + "input": [{ "lane": "answers", "from": "agent_rocketride_1" }], + "ui": { "position": { "x": 460, "y": 200 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + } + ], + "project_id": "93a804e7-846b-4a7f-bcb1-5c3ade5157e3", + "viewport": { "x": 0, "y": 0, "zoom": 1 }, + "version": 1 +} diff --git a/examples/document-processor.pipe b/examples/document-processor.pipe new file mode 100644 index 000000000..2bec70b7d --- /dev/null +++ b/examples/document-processor.pipe @@ -0,0 +1,51 @@ +{ + "components": [ + { + "id": "webhook_1", + "provider": "webhook", + "config": { "hideForm": true, "mode": "Source", "parameters": {}, "type": "webhook" }, + "ui": { "position": { "x": 20, "y": 200 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "parse_1", + "provider": "parse", + "config": {}, + "input": [{ "lane": "tags", "from": "webhook_1" }], + "ui": { "position": { "x": 240, "y": 200 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "ocr_1", + "provider": "ocr", + "config": {}, + "input": [{ "lane": "image", "from": "parse_1" }], + "ui": { "position": { "x": 460, "y": 120 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "ner_1", + "provider": "ner", + "config": {}, + "input": [ + { "lane": "text", "from": "parse_1" }, + { "lane": "text", "from": "ocr_1" } + ], + "ui": { "position": { "x": 680, "y": 200 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "anonymize_1", + "provider": "anonymize", + "config": {}, + "input": [{ "lane": "text", "from": "ner_1" }], + "ui": { "position": { "x": 900, "y": 200 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "response_text_1", + "provider": "response_text", + "config": { "laneName": "text" }, + "input": [{ "lane": "text", "from": "anonymize_1" }], + "ui": { "position": { "x": 1120, "y": 200 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + } + ], + "project_id": "6744c740-0cdb-4667-b471-6c31d17d92d2", + "viewport": { "x": 0, "y": 0, "zoom": 1 }, + "version": 1 +} diff --git a/examples/llm-benchmark.pipe b/examples/llm-benchmark.pipe new file mode 100644 index 000000000..32db63415 --- /dev/null +++ b/examples/llm-benchmark.pipe @@ -0,0 +1,93 @@ +{ + "components": [ + { + "id": "chat_1", + "provider": "chat", + "config": { "hideForm": true, "mode": "Source", "parameters": {}, "type": "chat" }, + "ui": { "position": { "x": 20, "y": 300 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "agent_rocketride_1", + "provider": "agent_rocketride", + "config": { "instructions": ["You are a helpful assistant. Answer the user's question clearly and concisely."], "max_waves": 5, "parameters": {} }, + "input": [{ "lane": "questions", "from": "chat_1" }], + "ui": { "position": { "x": 240, "y": 140 }, "measured": { "width": 150, "height": 86 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "agent_crewai_1", + "provider": "agent_crewai", + "config": { "instructions": ["You are a helpful assistant. Answer the user's question clearly and concisely."], "parameters": {} }, + "input": [{ "lane": "questions", "from": "chat_1" }], + "ui": { "position": { "x": 240, "y": 300 }, "measured": { "width": 150, "height": 86 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "agent_langchain_1", + "provider": "agent_langchain", + "config": { "instructions": ["You are a helpful assistant. Answer the user's question clearly and concisely."], "parameters": {} }, + "input": [{ "lane": "questions", "from": "chat_1" }], + "ui": { "position": { "x": 240, "y": 460 }, "measured": { "width": 150, "height": 86 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "llm_openai_1", + "provider": "llm_openai", + "config": { + "profile": "openai-4o", + "openai-4o": { "apikey": "${ROCKETRIDE_OPENAI_KEY}" }, + "parameters": {} + }, + "control": [ + { "classType": "llm", "from": "agent_rocketride_1" } + ], + "ui": { "position": { "x": 170, "y": 620 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "llm_anthropic_1", + "provider": "llm_anthropic", + "config": { + "profile": "claude", + "claude": { "apikey": "${ROCKETRIDE_ANTHROPIC_KEY}" }, + "parameters": {} + }, + "control": [ + { "classType": "llm", "from": "agent_crewai_1" } + ], + "ui": { "position": { "x": 240, "y": 620 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "llm_gemini_1", + "provider": "llm_gemini", + "config": { + "profile": "gemini", + "gemini": { "apikey": "${ROCKETRIDE_GEMINI_KEY}" }, + "parameters": {} + }, + "control": [ + { "classType": "llm", "from": "agent_langchain_1" } + ], + "ui": { "position": { "x": 310, "y": 620 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "memory_internal_1", + "provider": "memory_internal", + "config": { "type": "memory_internal" }, + "control": [ + { "classType": "memory", "from": "agent_rocketride_1" } + ], + "ui": { "position": { "x": 100, "y": 620 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "response_answers_1", + "provider": "response_answers", + "config": { "laneName": "answers" }, + "input": [ + { "lane": "answers", "from": "agent_rocketride_1" }, + { "lane": "answers", "from": "agent_crewai_1" }, + { "lane": "answers", "from": "agent_langchain_1" } + ], + "ui": { "position": { "x": 460, "y": 300 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + } + ], + "project_id": "daa7c4fe-7604-47a8-bdf3-6f592cc619d4", + "viewport": { "x": 0, "y": 0, "zoom": 1 }, + "version": 1 +} diff --git a/examples/rag-pipeline.pipe b/examples/rag-pipeline.pipe new file mode 100644 index 000000000..167f2ea78 --- /dev/null +++ b/examples/rag-pipeline.pipe @@ -0,0 +1,116 @@ +{ + "components": [ + { + "id": "webhook_1", + "provider": "webhook", + "config": { "hideForm": true, "mode": "Source", "parameters": {}, "type": "webhook" }, + "ui": { "position": { "x": 20, "y": 200 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "parse_1", + "provider": "parse", + "config": {}, + "input": [{ "lane": "tags", "from": "webhook_1" }], + "ui": { "position": { "x": 240, "y": 200 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "preprocessor_langchain_1", + "provider": "preprocessor_langchain", + "config": { + "profile": "default", + "default": { + "mode": "strlen", + "splitter": "RecursiveCharacterTextSplitter", + "strlen": 512 + }, + "parameters": {} + }, + "input": [{ "lane": "text", "from": "parse_1" }], + "ui": { "position": { "x": 460, "y": 200 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "embedding_transformer_1", + "provider": "embedding_transformer", + "config": { "profile": "miniLM", "parameters": {} }, + "input": [{ "lane": "documents", "from": "preprocessor_langchain_1" }], + "ui": { "position": { "x": 680, "y": 200 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "qdrant_1", + "provider": "qdrant", + "config": { + "profile": "local", + "local": { + "host": "${ROCKETRIDE_QDRANT_HOST}", + "port": 6333, + "collection": "${ROCKETRIDE_COLLECTION_NAME}" + }, + "parameters": {} + }, + "input": [{ "lane": "documents", "from": "embedding_transformer_1" }], + "ui": { "position": { "x": 900, "y": 200 }, "measured": { "width": 150, "height": 135 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "chat_1", + "provider": "chat", + "config": { "hideForm": true, "mode": "Source", "parameters": {}, "type": "chat" }, + "ui": { "position": { "x": 20, "y": 500 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "embedding_transformer_2", + "provider": "embedding_transformer", + "config": { "profile": "miniLM", "parameters": {} }, + "input": [{ "lane": "questions", "from": "chat_1" }], + "ui": { "position": { "x": 240, "y": 500 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "qdrant_2", + "provider": "qdrant", + "config": { + "profile": "local", + "local": { + "host": "${ROCKETRIDE_QDRANT_HOST}", + "port": 6333, + "collection": "${ROCKETRIDE_COLLECTION_NAME}" + }, + "parameters": {} + }, + "input": [{ "lane": "questions", "from": "embedding_transformer_2" }], + "ui": { "position": { "x": 460, "y": 500 }, "measured": { "width": 150, "height": 135 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "prompt_1", + "provider": "prompt", + "config": { + "instructions": ["Use the provided context to answer the question accurately. If the context does not contain relevant information, say so."], + "parameters": {} + }, + "input": [ + { "lane": "documents", "from": "qdrant_2" }, + { "lane": "questions", "from": "qdrant_2" } + ], + "ui": { "position": { "x": 680, "y": 500 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "llm_openai_1", + "provider": "llm_openai", + "config": { + "profile": "openai-4o", + "openai-4o": { "apikey": "${ROCKETRIDE_OPENAI_KEY}" }, + "parameters": {} + }, + "input": [{ "lane": "questions", "from": "prompt_1" }], + "ui": { "position": { "x": 900, "y": 500 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + }, + { + "id": "response_answers_1", + "provider": "response_answers", + "config": { "laneName": "answers" }, + "input": [{ "lane": "answers", "from": "llm_openai_1" }], + "ui": { "position": { "x": 1120, "y": 500 }, "measured": { "width": 150, "height": 66 }, "nodeType": "default", "formDataValid": true } + } + ], + "project_id": "1327e7c0-8479-4ab7-a319-c4dc944daeb5", + "viewport": { "x": 0, "y": 0, "zoom": 1 }, + "version": 1 +}