Skip to content

Comments

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

Open
sfo2001 wants to merge 4 commits intoopenclaw:mainfrom
sfo2001:feat/pipeline-each
Open

feat(stdlib): add each command for per-item sub-pipeline iteration#13
sfo2001 wants to merge 4 commits intoopenclaw:mainfrom
sfo2001:feat/pipeline-each

Conversation

@sfo2001
Copy link

@sfo2001 sfo2001 commented Feb 15, 2026

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

sfo2001 and others added 4 commits February 15, 2026 11:29
Dead code left over from the clawd-only refactor in 5679042.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract getByPath and renderTemplate into template_utils.ts. Fix ReDoS
vulnerability in template regex and add Object.hasOwn guard to block
prototype chain traversal in getByPath.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add { } body parsing with backward-compatible bare brace handling,
recursion depth limit (50), and truncated error messages. Bare } at
depth 0 is treated as literal to avoid breaking existing pipelines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add each { ... } pipeline operator that runs a sub-pipeline per input
item with {{.field}} interpolation. Includes _bodyRaw pass-through,
sideEffects metadata, and tests for runtime errors, prototype denylist,
and recursion depth.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

1 participant