LLMSkillHub
mirroredCopied from gorango/flowcraft under MIT. gorango has not claimed this page, and is not affiliated with LLM SkillHub.

gorango / compiler-workflows

Write workflows using imperative TypeScript with the Flowcraft Compiler. Covers @flow and @step annotations, control flow patterns, subflows, configuration, and build tool integration. Use when the user mentions the compiler, imperative workflows, @flow, @step, or wants to write workflows without manually constructing graphs.

0
SKILL.md
4.6 KB

Compiler Workflows (Alpha)

Flowcraft's compiler transforms imperative TypeScript into declarative blueprints at build time. Write familiar async functions with control flow — the compiler generates the graph.

[!WARNING]
The compiler is in alpha. Contributions are welcome.

Quick start

Installation

npm install --save-dev @flowcraft/compiler

Write a workflow

/** @flow */
export async function myWorkflow(input: string) {
	const data = await fetchData(input)
	const result = await processData(data)
	return result
}

/** @step */
async function fetchData(input: string) {
	// Implementation — this becomes a durable node
	return fetch(`/api/data?q=${input}`).then((r) => r.json())
}

/** @step */
async function processData(data: unknown) {
	// Implementation — this becomes a durable node
	return { processed: true, data }
}

Execute

import { FlowRuntime } from 'flowcraft'
import manifest from './generated/manifest'

const runtime = new FlowRuntime()
const result = await runtime.run(manifest['myWorkflow'], { input: 'hello' })

The Golden Rules

  1. Mark orchestrators with `/ @flow \/`\* — Functions that define workflow orchestration
  2. Mark durable operations with `/ @step \/`\* — Async operations that should be retried/tracked
  3. Never await plain async functions — The compiler errors if you await a non-@step function

Supported Control Flow

PatternSyntaxCompiles to
Sequentialawait stepA(); await stepB()Linear nodes with edges
Conditionalif/else with @step callsConditional edges with actions
Switchswitch(val) { case ... } with @step callsConditional multi-branch
Loopsfor/while/do-while with @step callsLoop controller node
Fallbackstry/catch/finally with @step callsFallback/finally node routing
ParallelismPromise.all([...]), Promise.allSettled([...]), Promise.race([...])Fan-out/fan-in with join
Subflowsawait otherFlow(input)Subflow node

Configuration

Create flowcraft.config.ts:

import { defineConfig } from '@flowcraft/compiler'

export default defineConfig({
	entryPoints: ['./src/workflows/**/*.ts'],
	manifestPath: './src/generated/manifest.ts',
	tsConfigPath: './tsconfig.json',
})

Build Tool Integration

Compilation happens automatically with plugins:

// vite.config.ts
import flowcraft from '@flowcraft/plugin-vite'

export default {
	plugins: [flowcraft()],
}

Available plugins: Vite, Next.js, Nuxt, Astro, esbuild, tsup.

Unsupported Syntax

  • Complex variable re-assignments within loops
  • Dynamic function calls or eval
  • Generator functions or async generators
  • Class methods as steps (use standalone functions)

Runtime compilation (compileCode)

For testing, REPL environments, or low-frequency runtime configuration, use compileCode() to compile raw TypeScript strings into blueprints:

import { compileCode } from '@flowcraft/compiler'

const { blueprint, diagnostics } = compileCode(
	`
  /** @flow */
  export async function myFlow() {
    const data = await fetchData()
    return await processData(data)
  }

  /** @step */
  async function fetchData() { return { value: 42 } }

  /** @step */
  async function processData(d: any) { return { result: d.value * 2 } }
`,
	{ id: 'myFlow' },
)

Note: compileCode() writes temporary files and spins up a full compiler instance per call. For production, always use pre-compiled builds via compileProject() or framework plugins.

Advanced topics

  • Authoring detailed patterns: See [authoring-guide.md](authoring-guide.md)
  • Configuration options: See [configuration.md](configuration.md)