Skip to main content
Lightweight HTTP client for a running Smithers server. Start/resume runs, stream events, manage approvals, query status.

Import

import {
  runWorkflow,
  resume,
  approve,
  deny,
  streamEvents,
  getStatus,
  getFrames,
  cancel,
  listRuns,
} from "smithers-orchestrator/pi-plugin";

Defaults

All functions accept optional baseUrl and apiKey:
ParameterDefault
baseUrlhttp://127.0.0.1:7331
apiKeyundefined (no auth header)
If apiKey is provided, it is sent as Authorization: Bearer <token>.

Functions

runWorkflow

Start a new workflow run.
async function runWorkflow(args: {
  workflowPath: string;
  input: unknown;
  runId?: string;
  baseUrl?: string;
  apiKey?: string;
}): Promise<{ runId: string }>
ParameterTypeRequiredDescription
workflowPathstringYesPath to .tsx workflow file on the server
inputunknownYesWorkflow input data
runIdstringNoCustom run ID
baseUrlstringNoServer URL
apiKeystringNoAuth token
const run = await runWorkflow({
  workflowPath: "./workflows/bugfix.tsx",
  input: { description: "Auth tokens expire silently" },
  apiKey: "sk-my-token",
});
console.log(run.runId);

resume

Resume a paused or failed run.
async function resume(args: {
  workflowPath: string;
  runId: string;
  baseUrl?: string;
  apiKey?: string;
}): Promise<{ runId: string }>
ParameterTypeRequiredDescription
workflowPathstringYesPath to .tsx workflow file
runIdstringYesRun ID to resume
baseUrlstringNoServer URL
apiKeystringNoAuth token
Calls POST /v1/runs with resume: true.

approve

Approve a node waiting for human approval.
async function approve(args: {
  runId: string;
  nodeId: string;
  iteration?: number;
  note?: string;
  baseUrl?: string;
  apiKey?: string;
}): Promise<{ runId: string }>
ParameterTypeRequiredDescription
runIdstringYesRun ID
nodeIdstringYesNode ID
iterationnumberNoLoop iteration (default: 0)
notestringNoApproval note
baseUrlstringNoServer URL
apiKeystringNoAuth token

deny

Deny a node waiting for human approval.
async function deny(args: {
  runId: string;
  nodeId: string;
  iteration?: number;
  note?: string;
  baseUrl?: string;
  apiKey?: string;
}): Promise<{ runId: string }>
ParameterTypeRequiredDescription
runIdstringYesRun ID
nodeIdstringYesNode ID
iterationnumberNoLoop iteration (default: 0)
notestringNoDenial reason
baseUrlstringNoServer URL
apiKeystringNoAuth token

streamEvents

Stream lifecycle events via SSE. Returns AsyncIterable<SmithersEvent>.
async function* streamEvents(args: {
  runId: string;
  baseUrl?: string;
  apiKey?: string;
}): AsyncIterable<SmithersEvent>
ParameterTypeRequiredDescription
runIdstringYesRun ID
baseUrlstringNoServer URL
apiKeystringNoAuth token
for await (const event of streamEvents({ runId: "smi_abc123" })) {
  if (event.type === "RunFinished") break;
  if (event.type === "RunFailed") break;
  if (event.type === "NodeWaitingApproval") {
    console.log(`Node ${event.nodeId} needs approval.`);
  }
}
Connects to GET /v1/runs/:runId/events. Keep-alive comments are filtered. Completes when the stream closes.

getStatus

Get run status and summary.
async function getStatus(args: {
  runId: string;
  baseUrl?: string;
  apiKey?: string;
}): Promise<{
  runId: string;
  workflowName: string;
  status: string;
  startedAtMs: number | null;
  finishedAtMs: number | null;
  summary: Record<string, number>;
}>
const status = await getStatus({ runId: "smi_abc123" });
console.log(status.status);  // "running" | "finished" | "failed" | ...
console.log(status.summary); // { finished: 3, pending: 2, "in-progress": 1 }

getFrames

List render frames for a run.
async function getFrames(args: {
  runId: string;
  tail?: number;
  baseUrl?: string;
  apiKey?: string;
}): Promise<any[]>
ParameterTypeRequiredDescription
runIdstringYesRun ID
tailnumberNoMax frames (default: 20)
baseUrlstringNoServer URL
apiKeystringNoAuth token

cancel

Cancel a running workflow.
async function cancel(args: {
  runId: string;
  baseUrl?: string;
  apiKey?: string;
}): Promise<{ runId: string }>

listRuns

List all runs. Requires server db.
async function listRuns(args?: {
  limit?: number;
  status?: string;
  baseUrl?: string;
  apiKey?: string;
}): Promise<any[]>
ParameterTypeRequiredDescription
limitnumberNoMax runs (default: server default of 50)
statusstringNoFilter by status
baseUrlstringNoServer URL
apiKeystringNoAuth token

Complete Example

import {
  runWorkflow,
  streamEvents,
  approve,
  getStatus,
} from "smithers-orchestrator/pi-plugin";

const apiKey = process.env.SMITHERS_API_KEY;

const run = await runWorkflow({
  workflowPath: "./workflows/deploy.tsx",
  input: { branch: "main", environment: "staging" },
  apiKey,
});

for await (const event of streamEvents({ runId: run.runId, apiKey })) {
  switch (event.type) {
    case "NodeStarted":
      console.log(`Task ${event.nodeId} started (attempt ${event.attempt})`);
      break;
    case "NodeFinished":
      console.log(`Task ${event.nodeId} completed`);
      break;
    case "NodeWaitingApproval":
      await approve({
        runId: run.runId,
        nodeId: event.nodeId,
        note: "Auto-approved for staging",
        apiKey,
      });
      break;
    case "RunFinished":
      console.log("Deployment complete.");
      break;
    case "RunFailed":
      console.error("Deployment failed:", event.error);
      break;
  }
}

const status = await getStatus({ runId: run.runId, apiKey });
console.log(`Final status: ${status.status}`);