Skip to content

feat(sdk): add WorkflowBuilder.paths() for multi-repo cloud workflows#814

Merged
khaliqgant merged 1 commit intomainfrom
sdk-add-paths-builder
May 5, 2026
Merged

feat(sdk): add WorkflowBuilder.paths() for multi-repo cloud workflows#814
khaliqgant merged 1 commit intomainfrom
sdk-add-paths-builder

Conversation

@khaliqgant
Copy link
Copy Markdown
Member

Summary

  • Phase B of the multi-repo cloud workflow rollout (relay#774, cloud#302) shipped the CLI-side regex parser for paths and the cloud bootstrap that mounts each declared path, but never added a fluent .paths(...) method on the SDK WorkflowBuilder. Workflows that wrote the natural form
    workflow('multi-repo').paths([{name:'alpha', path:'alpha'}, ...]).run()
    tarballed correctly at submit time (CLI parsed the literal via regex) but threw TypeError: ... .paths is not a function the moment the sandbox runtime evaluated the file, because the builder the sandbox imports from @agent-relay/sdk/workflows had no such method.
  • This PR adds the missing builder method.

What changes

  • packages/sdk/src/workflows/builder.ts: import the existing PathDefinition type, add a _paths private field on WorkflowBuilder, add a paths(paths: PathDefinition[]): this method with up-front validation (non-array, missing name/path, duplicate names all throw at builder time), and thread _paths into toConfig() so the field lands on the built RelayYamlConfig.
  • packages/sdk/src/workflows/__tests__/builder-paths.test.ts: 7 focused tests — recording, omission when unset, defensive copy-on-input, three validation paths, and the chain-return contract.

What does NOT change

  • The runner still does not consume paths to execute steps — that's a CLI/cloud concern. Adding the method is purely about being a no-op-at-runtime, single-source-of-truth setter for tools that walk the built config (dashboards, dry-run reports, cloud bootstrap).
  • PathDefinition type already existed in types.ts; this PR only wires the fluent setter that callers expect to exist.

Once published + snapshot rebuilt

Workflow authors can swap the current Phase-B workaround

export const config = { paths: [...] };  // CLI-only, regex-parsed

back to the natural fluent form

workflow('multi-repo').paths([...]).step(...).run();

without the runtime TypeError.

Test plan

  • vitest run packages/sdk/src/workflows/__tests__/builder-paths.test.ts — 7/7 passing
  • Full SDK suite re-run: 956 passing, 1 pre-existing failure on main (workflow-runner.test.ts "record review completion in trajectory" — unrelated to this change, also fails on origin/main HEAD)
  • tsc --noEmit against packages/sdk — clean
  • After release: cloud sandbox snapshot needs to be rebuilt against the bumped @agent-relay/sdk so existing relax + bootstrap PRs (cloud#423/fix: add fallback logic for cross-machine message delivery #425/daytona + sdk work #431) close out the demo end-to-end.

🤖 Generated with Claude Code

Phase B of the multi-repo cloud workflow rollout (relay#774, cloud#302)
shipped the CLI-side regex parser and the cloud-side bootstrap, but
never added a fluent `.paths(...)` method on the SDK WorkflowBuilder.
Workflows that called `.paths(...)` therefore tarballed correctly at
submit time but threw `TypeError: ... .paths is not a function` once
the runtime evaluated the file inside the sandbox, because the method
didn't exist on the builder the sandbox imports from
`@agent-relay/sdk/workflows`.

Add the missing builder method:

  workflow('multi-repo')
    .paths([
      { name: 'alpha', path: 'alpha' },
      { name: 'beta', path: 'beta' },
    ])
    .step(...)
    .run();

The runner does not consume `paths` to execute steps — that's still a
CLI/cloud concern — but recording it on the built RelayYamlConfig
keeps single-source-of-truth for tools that walk the config (dry-run
reports, dashboards, the cloud bootstrap). Validation is up front:
non-arrays, entries missing name/path, and duplicate names all throw
at builder time so misconfiguration surfaces locally before submit.

`PathDefinition` already existed in `types.ts`; this PR only wires
the fluent setter that callers expect to exist.

Tests: 7 unit tests for the new method (recording, omission when
unset, copy-on-input, validation errors, chain return). SDK suite
otherwise unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@khaliqgant khaliqgant requested a review from willwashburn as a code owner May 5, 2026 07:58
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

📝 Walkthrough

Walkthrough

The PR adds a fluent .paths() method to WorkflowBuilder that accepts an array of path definitions with name and path strings. The method validates input, stores the definitions internally, and optionally emits them via toConfig().

Changes

Path Definitions API

Layer / File(s) Summary
Data Shape & Storage
packages/sdk/src/workflows/builder.ts (lines 147–162)
New private field _paths?: PathDefinition[] stores declared filesystem paths.
Core Implementation
packages/sdk/src/workflows/builder.ts (lines 248–279)
.paths(paths: PathDefinition[]): this method validates array shape, required name/path string fields, duplicate name detection, and clones input; returns this for chaining.
Config Emission
packages/sdk/src/workflows/builder.ts (lines 418–420)
toConfig() conditionally sets config.paths from stored definitions when non-empty.
Tests & Validation
packages/sdk/src/workflows/__tests__/builder-paths.test.ts
Comprehensive test suite covering config emission, omission when unset, mutation guarding, array validation, required fields, duplicate detection, and method chaining.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A path is declared with validation so keen,
Builder flows gently through fields in between,
No mutations sneaking, no duplicates here,
Config emits cleanly—the API is clear! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(sdk): add WorkflowBuilder.paths() for multi-repo cloud workflows' clearly and specifically describes the main change—adding a new fluent .paths() method to WorkflowBuilder for handling filesystem paths in workflows.
Description check ✅ Passed The description fully addresses the template sections with a comprehensive summary explaining the problem, changes made, validation approach, and test plan with specific test results (7/7 passing, 956 SDK suite passing).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sdk-add-paths-builder

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/sdk/src/workflows/builder.ts`:
- Around line 268-270: The current .paths() validation only checks that p.name
and p.path are strings but allows empty or whitespace-only values; update the
validation in builder.ts (the .paths() handling where p is validated) to reject
blank values by trimming p.name and p.path and ensuring their trimmed length is
> 0, and throw a clear error (e.g., ".paths() entries must each have non-empty
string `name` and `path` fields") referencing p.name and p.path when the check
fails.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: db5c0771-3631-48b4-b539-db1ddb6d650c

📥 Commits

Reviewing files that changed from the base of the PR and between ff3e8c9 and 3a7f39e.

📒 Files selected for processing (2)
  • packages/sdk/src/workflows/__tests__/builder-paths.test.ts
  • packages/sdk/src/workflows/builder.ts

Comment on lines +268 to +270
if (!p || typeof p.name !== 'string' || typeof p.path !== 'string') {
throw new Error('.paths() entries must each have string `name` and `path` fields');
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Reject blank name/path values in .paths() validation.

Current validation allows empty/whitespace strings, which can produce invalid declared paths in emitted config.

Suggested patch
-      if (!p || typeof p.name !== 'string' || typeof p.path !== 'string') {
-        throw new Error('.paths() entries must each have string `name` and `path` fields');
+      if (
+        !p ||
+        typeof p.name !== 'string' ||
+        typeof p.path !== 'string' ||
+        p.name.trim().length === 0 ||
+        p.path.trim().length === 0
+      ) {
+        throw new Error('.paths() entries must each have non-empty string `name` and `path` fields');
       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!p || typeof p.name !== 'string' || typeof p.path !== 'string') {
throw new Error('.paths() entries must each have string `name` and `path` fields');
}
if (
!p ||
typeof p.name !== 'string' ||
typeof p.path !== 'string' ||
p.name.trim().length === 0 ||
p.path.trim().length === 0
) {
throw new Error('.paths() entries must each have non-empty string `name` and `path` fields');
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/sdk/src/workflows/builder.ts` around lines 268 - 270, The current
.paths() validation only checks that p.name and p.path are strings but allows
empty or whitespace-only values; update the validation in builder.ts (the
.paths() handling where p is validated) to reject blank values by trimming
p.name and p.path and ensuring their trimmed length is > 0, and throw a clear
error (e.g., ".paths() entries must each have non-empty string `name` and `path`
fields") referencing p.name and p.path when the check fails.

@khaliqgant khaliqgant merged commit f127138 into main May 5, 2026
41 checks passed
@khaliqgant khaliqgant deleted the sdk-add-paths-builder branch May 5, 2026 08:05
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