[PR #13] feat(stdlib): add each command for per-item sub-pipeline iteration #13

Open
opened 2026-02-15 18:15:41 -05:00 by yindo · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/openclaw/lobster/pull/13
Author: @sfo2001
Created: 2/15/2026
Status: 🔄 Open

Base: mainHead: feat/pipeline-each


📝 Commits (4)

  • 671dcd6 fix(stdlib): remove unused Transport type and transport variable
  • 5d78f6c refactor(stdlib): extract shared template_utils from map and template
  • ee6b629 feat(parser): add brace-delimited body syntax for sub-pipelines
  • 542e2f6 feat(stdlib): add each command for per-item sub-pipeline iteration

📊 Changes

9 files changed (+399 additions, -52 deletions)

View changed files

📝 src/cli.ts (+1 -1)
📝 src/commands/registry.ts (+2 -0)
src/commands/stdlib/each.ts (+85 -0)
📝 src/commands/stdlib/llm_task_invoke.ts (+0 -3)
📝 src/commands/stdlib/map.ts (+1 -20)
📝 src/commands/stdlib/template.ts (+1 -21)
src/commands/stdlib/template_utils.ts (+21 -0)
📝 src/parser.ts (+107 -7)
test/each.test.ts (+181 -0)

📄 Description

Motivation

Pipelines currently have no native way to read from or write to local files. Loading data requires shelling out (exec cat + manual parsing), and there is no structured JSON transformation primitive beyond map. file.read, file.write, and jq-filter fill these gaps: pipelines can ingest local datasets, persist intermediate results, and apply arbitrary jq expressions
without leaving the pipeline or spawning ad-hoc shell commands.

Summary

  • Add each command: runs a sub-pipeline for each input item, collecting results
  • Add brace-delimited body syntax to the parser (each { map --unwrap url | exec curl "{{.}}" })
  • Extract shared template_utils.ts from map and template to eliminate duplication
  • {{.field}} interpolation in sub-pipeline args per item; nested each supported
  • Fail-fast error propagation; recursion depth limit (16) on nested braces

Changes

Category Files
New command src/commands/stdlib/each.ts
New shared util src/commands/stdlib/template_utils.ts
Parser src/parser.ts (brace body parsing)
Refactored src/commands/stdlib/map.ts, template.ts (use shared util)
Registry src/commands/registry.ts (+1)
Tests test/each.test.ts (12 tests + 8 parser tests)

+389 / -48 lines across 7 files.

Test plan

  • pnpm build passes
  • pnpm lint passes
  • node --test dist/test/each.test.js -- 20 tests (12 each + 8 parser brace tests)
  • Existing map and template tests still pass (template_utils refactor)

Use of AI


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/openclaw/lobster/pull/13 **Author:** [@sfo2001](https://github.com/sfo2001) **Created:** 2/15/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `feat/pipeline-each` --- ### 📝 Commits (4) - [`671dcd6`](https://github.com/openclaw/lobster/commit/671dcd66b39ddfb8ba690e0d8571ca140efbcc75) fix(stdlib): remove unused Transport type and transport variable - [`5d78f6c`](https://github.com/openclaw/lobster/commit/5d78f6c3165af4a152e5f388461642fa022fd248) refactor(stdlib): extract shared template_utils from map and template - [`ee6b629`](https://github.com/openclaw/lobster/commit/ee6b629861b69c60b46587a32d46ddf6b20ddf52) feat(parser): add brace-delimited body syntax for sub-pipelines - [`542e2f6`](https://github.com/openclaw/lobster/commit/542e2f694b3471212d68fe506c70a641084986e0) feat(stdlib): add each command for per-item sub-pipeline iteration ### 📊 Changes **9 files changed** (+399 additions, -52 deletions) <details> <summary>View changed files</summary> 📝 `src/cli.ts` (+1 -1) 📝 `src/commands/registry.ts` (+2 -0) ➕ `src/commands/stdlib/each.ts` (+85 -0) 📝 `src/commands/stdlib/llm_task_invoke.ts` (+0 -3) 📝 `src/commands/stdlib/map.ts` (+1 -20) 📝 `src/commands/stdlib/template.ts` (+1 -21) ➕ `src/commands/stdlib/template_utils.ts` (+21 -0) 📝 `src/parser.ts` (+107 -7) ➕ `test/each.test.ts` (+181 -0) </details> ### 📄 Description ## Motivation Pipelines currently have no native way to read from or write to local files. Loading data requires shelling out (`exec cat` + manual parsing), and there is no structured JSON transformation primitive beyond `map`. `file.read`, `file.write`, and `jq-filter` fill these gaps: pipelines can ingest local datasets, persist intermediate results, and apply arbitrary jq expressions without leaving the pipeline or spawning ad-hoc shell commands. ## Summary - Add `each` command: runs a sub-pipeline for each input item, collecting results - Add brace-delimited body syntax to the parser (`each { map --unwrap url | exec curl "{{.}}" }`) - Extract shared `template_utils.ts` from `map` and `template` to eliminate duplication - `{{.field}}` interpolation in sub-pipeline args per item; nested `each` supported - Fail-fast error propagation; recursion depth limit (16) on nested braces ## Changes | Category | Files | |---|---| | New command | `src/commands/stdlib/each.ts` | | New shared util | `src/commands/stdlib/template_utils.ts` | | Parser | `src/parser.ts` (brace body parsing) | | Refactored | `src/commands/stdlib/map.ts`, `template.ts` (use shared util) | | Registry | `src/commands/registry.ts` (+1) | | Tests | `test/each.test.ts` (12 tests + 8 parser tests) | +389 / -48 lines across 7 files. ## Test plan - [x] `pnpm build` passes - [x] `pnpm lint` passes - [x] `node --test dist/test/each.test.js` -- 20 tests (12 each + 8 parser brace tests) - [x] Existing `map` and `template` tests still pass (template_utils refactor) ## Use of AI - my idea, code and test generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
yindo added the pull-request label 2026-02-15 18:15:41 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: openclaw/lobster#13