Skip to content

Add custom step extension API, bump to 1.1.0#34

Merged
pallaoro merged 1 commit intomainfrom
worktree-custom-step
May 7, 2026
Merged

Add custom step extension API, bump to 1.1.0#34
pallaoro merged 1 commit intomainfrom
worktree-custom-step

Conversation

@pallaoro
Copy link
Copy Markdown
Member

@pallaoro pallaoro commented May 7, 2026

Summary

Public extension API: registerStepType() lets host applications add domain-specific step types (e.g. signed callouts to internal APIs) alongside built-ins without forking. Custom steps participate in the same do: dispatch, validation, and trace pipeline as native types.

What's new

  • StepRegistryregister/get/has/names/clear; module-level defaultRegistry
  • registerStepType({ name, allowedKeys, validate?, run }) — collision with built-ins and duplicate registration throw at register time
  • CustomStepContext — frozen state, env, prefixed logger, per-flow AbortSignal, nodeName, resolveTemplate()
  • Pre-resolves {{ template }} strings in input fields, mirroring do: http
  • Validator errors surface with the native { node, field, message } shape — indistinguishable from built-in validation
  • PluginConfig.customSteps — pass a private registry for test isolation or multi-runner scenarios

Design notes

  • No new schema-library dependency. Validator is (input) => { ok, errors } — plugin authors wrap Zod/Ajv if they want.
  • AbortSignal is wired to a per-flow controller now; flow-level cancel can call abort() later without API change.
  • No retry helper on ctx — node-level retry: already covers this.
  • Module-level registerStepType() writes to a singleton; opt out via cfg.customSteps.

Public API

import { registerStepType } from "@clawnify/clawflow";

registerStepType({
  name: "clawnify_app",
  allowedKeys: ["app_id", "method", "path", "body"],
  validate: (input) => { /* return { ok, errors } */ },
  async run(input, ctx) {
    const res = await fetch(url, { signal: ctx.abortSignal });
    return { status: res.status, ok: res.ok, body: await res.json() };
  },
});

Flow JSON unchanged: { "do": "clawnify_app", "name": "...", "app_id": "..." }.

Test plan

  • npm run lint — clean
  • npm test — 128 tests pass (11 new + 117 existing)
  • Smoke-test against a real consumer plugin before publishing

Release

Merging this PR + cutting a v1.1.0 GitHub release will auto-publish to npm.

Public registerStepType() lets host applications add domain-specific step
types alongside built-ins (ai, code, http, …) without forking. Custom
steps participate in the same do: dispatch and validation as native types.

- StepRegistry with register/get/has/names/clear; module-level defaultRegistry
- registerStepType({ name, allowedKeys, validate?, run }) + collision/duplicate guards
- ctx: frozen state, env, prefixed logger, per-flow AbortSignal, nodeName, resolveTemplate
- Pre-resolves {{ template }} fields like do: http
- Validator errors share the native { node, field, message } shape
- PluginConfig.customSteps for test isolation / multi-runner cases
@pallaoro pallaoro merged commit 2ef2ea8 into main May 7, 2026
1 check passed
@pallaoro pallaoro deleted the worktree-custom-step branch May 7, 2026 10:02
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