// Props
import { DecisionTable } from "smithers-orchestrator";
type DecisionTableProps = {
id?: string;
rules: DecisionRule[];
default?: ReactElement; // rendered when no rule matches
strategy?: "first-match" | "all-match"; // default "first-match"
skipIf?: boolean;
};
type DecisionRule = {
when: boolean; // evaluated at render time
then: ReactElement;
label?: string;
};
<DecisionTable
rules={[
{
when: triage.severity === "critical",
then: (
<Task id="page-oncall" output={outputs.page} agent={pagerAgent}>
Page the on-call engineer immediately.
</Task>
),
},
{
when: triage.severity === "high",
then: <Task id="assign-senior" output={outputs.assign}>{{ assignee: "senior-pool" }}</Task>,
},
]}
default={<Task id="default-assign" output={outputs.assign}>{{ assignee: "general-pool" }}</Task>}
/>
Notes
first-matchbuilds nested Branches; order matters.all-matchwraps every matching rule in a Parallel; no ordering guarantee.
Source
The<DecisionTable> implementation and the files it imports, straight from the package source. This section is generated; edit the source, not this block.
// @smithers-type-exports-begin
/** @typedef {import("./DecisionRule.ts").DecisionRule} DecisionRule */
/** @typedef {import("./DecisionTableProps.ts").DecisionTableProps} DecisionTableProps */
// @smithers-type-exports-end
import React from "react";
import { Branch } from "./Branch.js";
import { Parallel } from "./Parallel.js";
/**
* Structured deterministic routing. Replaces deeply nested Branches with a
* flat, declarative rule table.
*
* - `"first-match"` builds nested Branch elements so the first matching rule wins.
* - `"all-match"` gathers all matching rules' `then` elements into a Parallel.
*
* Composes Branch and Parallel internally.
* @param {DecisionTableProps} props
*/
export function DecisionTable(props) {
if (props.skipIf)
return null;
const { rules, strategy = "first-match" } = props;
if (strategy === "all-match") {
const matching = rules.filter((r) => r.when).map((r) => r.then);
if (matching.length === 0) {
return props.default ?? null;
}
return React.createElement(Parallel, { id: props.id }, ...matching);
}
// "first-match": build nested Branches from the last rule backward.
// The innermost else is the default fallback.
let fallback = props.default ?? null;
for (let i = rules.length - 1; i >= 0; i--) {
const rule = rules[i];
fallback = React.createElement(Branch, {
if: rule.when,
then: rule.then,
else: fallback,
});
}
return fallback;
}