@personaai/runtime 0.9.5 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -69,11 +69,15 @@ type RuntimeResponse = RuntimeBufferedResponse | RuntimeStreamResponse | Runtime
69
69
  interface RunContext {
70
70
  userId: string;
71
71
  /** Which endpoint started this run. */
72
- kind: 'chat' | 'architect';
73
- /** Absent for `kind: 'architect'` the Architect co-pilot has no target agentId, it builds/edits Agents itself. */
72
+ kind: 'chat' | 'architect' | 'workflow';
73
+ /** Absent for `kind: 'architect'` or `kind: 'workflow'` without an agent step. */
74
74
  agentId?: string;
75
+ /** Set when `kind: 'workflow'`. */
76
+ workflowId?: string;
75
77
  threadId?: string;
76
- messages: ChatMessageInput[];
78
+ messages?: ChatMessageInput[];
79
+ /** Input parameters provided to the workflow run. */
80
+ input?: unknown;
77
81
  }
78
82
  interface RunResult {
79
83
  /** Assembled assistant text (concatenated TEXT_MESSAGE_CHUNK deltas), same as `ChatResult.text`. */
@@ -87,8 +91,9 @@ interface RunResult {
87
91
  interface ErrorContext {
88
92
  userId: string | null;
89
93
  /** Which stage of request handling the error came from. */
90
- phase: 'auth' | 'chat' | 'architect';
94
+ phase: 'auth' | 'chat' | 'architect' | 'workflow';
91
95
  agentId?: string;
96
+ workflowId?: string;
92
97
  threadId?: string;
93
98
  }
94
99
  interface ToolCallContext {
@@ -99,6 +104,14 @@ interface ToolCallContext {
99
104
  toolName: string;
100
105
  toolCallId: string;
101
106
  }
107
+ interface WorkflowNodeContext {
108
+ userId: string;
109
+ workflowId: string;
110
+ nodeId: string;
111
+ nodeType: string;
112
+ nodeLabel: string;
113
+ input?: unknown;
114
+ }
102
115
  interface FileUploadContext {
103
116
  userId: string;
104
117
  fileName: string;
@@ -136,6 +149,10 @@ interface RuntimeHooks {
136
149
  beforeToolCall?(ctx: ToolCallContext): void | Promise<void>;
137
150
  /** Fires when the matching TOOL_CALL_RESULT event arrives. `result` is the raw (string or JSON-parsed) tool output. */
138
151
  afterToolCall?(ctx: ToolCallContext, result: unknown): void | Promise<void>;
152
+ /** Fires when a workflow node begins execution (CUSTOM event `workflow_node_started`). */
153
+ beforeWorkflowNode?(ctx: WorkflowNodeContext): void | Promise<void>;
154
+ /** Fires when a workflow node finishes execution (CUSTOM event `workflow_node_completed`). `output` is the step output. */
155
+ afterWorkflowNode?(ctx: WorkflowNodeContext, output: unknown): void | Promise<void>;
139
156
  /** Fires after a file finishes uploading via `POST /files`. */
140
157
  onFileUpload?(ctx: FileUploadContext): void | Promise<void>;
141
158
  /**
@@ -194,6 +211,8 @@ interface RuntimeCapabilities {
194
211
  auditLogs?: boolean;
195
212
  /** The Architect co-pilot — builds/edits Agents on the caller's behalf via tool calls. @default false */
196
213
  architect?: boolean;
214
+ /** Full Workflow CRUD, draft authoring, versions, and Mermaid export beyond the always-on execution routes. @default false */
215
+ workflowsWrite?: boolean;
197
216
  }
198
217
  /**
199
218
  * Serves a list of code-defined REST tools (built with `defineRestTool`
@@ -307,6 +326,6 @@ declare class RuntimeHttpError extends Error {
307
326
  constructor(status: number, code: string, message: string);
308
327
  }
309
328
 
310
- declare const RUNTIME_VERSION = "0.9.4";
329
+ declare const RUNTIME_VERSION = "0.10.0";
311
330
 
312
- export { type CreateRuntimeOptions, type ErrorContext, type FileUploadContext, type MemoryWriteContext, RUNTIME_VERSION, type RcpManifestOptions, type ResolveUser, type RestToolManifestEntry, type RestToolsManifestOptions, type RunContext, type RunResult, type Runtime, type RuntimeBinaryResponse, type RuntimeBufferedResponse, type RuntimeCapabilities, type RuntimeHooks, RuntimeHttpError, type RuntimeMethod, type RuntimeRequest, type RuntimeResponse, type RuntimeStreamResponse, type RuntimeUploadedFile, type ThreadCreateContext, type ToolCallContext, type VoiceSessionCreateContext, createRuntime };
331
+ export { type CreateRuntimeOptions, type ErrorContext, type FileUploadContext, type MemoryWriteContext, RUNTIME_VERSION, type RcpManifestOptions, type ResolveUser, type RestToolManifestEntry, type RestToolsManifestOptions, type RunContext, type RunResult, type Runtime, type RuntimeBinaryResponse, type RuntimeBufferedResponse, type RuntimeCapabilities, type RuntimeHooks, RuntimeHttpError, type RuntimeMethod, type RuntimeRequest, type RuntimeResponse, type RuntimeStreamResponse, type RuntimeUploadedFile, type ThreadCreateContext, type ToolCallContext, type VoiceSessionCreateContext, type WorkflowNodeContext, createRuntime };
package/dist/index.d.ts CHANGED
@@ -69,11 +69,15 @@ type RuntimeResponse = RuntimeBufferedResponse | RuntimeStreamResponse | Runtime
69
69
  interface RunContext {
70
70
  userId: string;
71
71
  /** Which endpoint started this run. */
72
- kind: 'chat' | 'architect';
73
- /** Absent for `kind: 'architect'` the Architect co-pilot has no target agentId, it builds/edits Agents itself. */
72
+ kind: 'chat' | 'architect' | 'workflow';
73
+ /** Absent for `kind: 'architect'` or `kind: 'workflow'` without an agent step. */
74
74
  agentId?: string;
75
+ /** Set when `kind: 'workflow'`. */
76
+ workflowId?: string;
75
77
  threadId?: string;
76
- messages: ChatMessageInput[];
78
+ messages?: ChatMessageInput[];
79
+ /** Input parameters provided to the workflow run. */
80
+ input?: unknown;
77
81
  }
78
82
  interface RunResult {
79
83
  /** Assembled assistant text (concatenated TEXT_MESSAGE_CHUNK deltas), same as `ChatResult.text`. */
@@ -87,8 +91,9 @@ interface RunResult {
87
91
  interface ErrorContext {
88
92
  userId: string | null;
89
93
  /** Which stage of request handling the error came from. */
90
- phase: 'auth' | 'chat' | 'architect';
94
+ phase: 'auth' | 'chat' | 'architect' | 'workflow';
91
95
  agentId?: string;
96
+ workflowId?: string;
92
97
  threadId?: string;
93
98
  }
94
99
  interface ToolCallContext {
@@ -99,6 +104,14 @@ interface ToolCallContext {
99
104
  toolName: string;
100
105
  toolCallId: string;
101
106
  }
107
+ interface WorkflowNodeContext {
108
+ userId: string;
109
+ workflowId: string;
110
+ nodeId: string;
111
+ nodeType: string;
112
+ nodeLabel: string;
113
+ input?: unknown;
114
+ }
102
115
  interface FileUploadContext {
103
116
  userId: string;
104
117
  fileName: string;
@@ -136,6 +149,10 @@ interface RuntimeHooks {
136
149
  beforeToolCall?(ctx: ToolCallContext): void | Promise<void>;
137
150
  /** Fires when the matching TOOL_CALL_RESULT event arrives. `result` is the raw (string or JSON-parsed) tool output. */
138
151
  afterToolCall?(ctx: ToolCallContext, result: unknown): void | Promise<void>;
152
+ /** Fires when a workflow node begins execution (CUSTOM event `workflow_node_started`). */
153
+ beforeWorkflowNode?(ctx: WorkflowNodeContext): void | Promise<void>;
154
+ /** Fires when a workflow node finishes execution (CUSTOM event `workflow_node_completed`). `output` is the step output. */
155
+ afterWorkflowNode?(ctx: WorkflowNodeContext, output: unknown): void | Promise<void>;
139
156
  /** Fires after a file finishes uploading via `POST /files`. */
140
157
  onFileUpload?(ctx: FileUploadContext): void | Promise<void>;
141
158
  /**
@@ -194,6 +211,8 @@ interface RuntimeCapabilities {
194
211
  auditLogs?: boolean;
195
212
  /** The Architect co-pilot — builds/edits Agents on the caller's behalf via tool calls. @default false */
196
213
  architect?: boolean;
214
+ /** Full Workflow CRUD, draft authoring, versions, and Mermaid export beyond the always-on execution routes. @default false */
215
+ workflowsWrite?: boolean;
197
216
  }
198
217
  /**
199
218
  * Serves a list of code-defined REST tools (built with `defineRestTool`
@@ -307,6 +326,6 @@ declare class RuntimeHttpError extends Error {
307
326
  constructor(status: number, code: string, message: string);
308
327
  }
309
328
 
310
- declare const RUNTIME_VERSION = "0.9.4";
329
+ declare const RUNTIME_VERSION = "0.10.0";
311
330
 
312
- export { type CreateRuntimeOptions, type ErrorContext, type FileUploadContext, type MemoryWriteContext, RUNTIME_VERSION, type RcpManifestOptions, type ResolveUser, type RestToolManifestEntry, type RestToolsManifestOptions, type RunContext, type RunResult, type Runtime, type RuntimeBinaryResponse, type RuntimeBufferedResponse, type RuntimeCapabilities, type RuntimeHooks, RuntimeHttpError, type RuntimeMethod, type RuntimeRequest, type RuntimeResponse, type RuntimeStreamResponse, type RuntimeUploadedFile, type ThreadCreateContext, type ToolCallContext, type VoiceSessionCreateContext, createRuntime };
331
+ export { type CreateRuntimeOptions, type ErrorContext, type FileUploadContext, type MemoryWriteContext, RUNTIME_VERSION, type RcpManifestOptions, type ResolveUser, type RestToolManifestEntry, type RestToolsManifestOptions, type RunContext, type RunResult, type Runtime, type RuntimeBinaryResponse, type RuntimeBufferedResponse, type RuntimeCapabilities, type RuntimeHooks, RuntimeHttpError, type RuntimeMethod, type RuntimeRequest, type RuntimeResponse, type RuntimeStreamResponse, type RuntimeUploadedFile, type ThreadCreateContext, type ToolCallContext, type VoiceSessionCreateContext, type WorkflowNodeContext, createRuntime };
package/dist/index.js CHANGED
@@ -131,7 +131,7 @@ function evictStaleRuns(runs, now, graceMs = DEFAULT_RUN_GRACE_MS, maxTracked =
131
131
  }
132
132
 
133
133
  // src/version.ts
134
- var RUNTIME_VERSION = "0.9.4";
134
+ var RUNTIME_VERSION = "0.10.0";
135
135
 
136
136
  // src/routes/health.ts
137
137
  var alwaysOnCapabilities = {
@@ -140,7 +140,8 @@ var alwaysOnCapabilities = {
140
140
  agents: true,
141
141
  files: true,
142
142
  memory: true,
143
- mcpOAuth: true
143
+ mcpOAuth: true,
144
+ workflows: true
144
145
  };
145
146
  var healthRoute = async (_request, ctx) => {
146
147
  try {
@@ -294,7 +295,8 @@ function newAccumulator() {
294
295
  interrupted: false,
295
296
  erroredInBand: false,
296
297
  threadCreateFired: false,
297
- toolNames: /* @__PURE__ */ new Map()
298
+ toolNames: /* @__PURE__ */ new Map(),
299
+ nodeMeta: /* @__PURE__ */ new Map()
298
300
  };
299
301
  }
300
302
  async function processEvent(event, acc, runCtx, hooks) {
@@ -314,7 +316,45 @@ async function processEvent(event, acc, runCtx, hooks) {
314
316
  break;
315
317
  }
316
318
  case EventType.CUSTOM: {
317
- if (e.name === "hitl_request" || e.name === "clarification_request") acc.interrupted = true;
319
+ if (e.name === "hitl_request" || e.name === "clarification_request") {
320
+ acc.interrupted = true;
321
+ } else if (e.name === "workflow_node_started") {
322
+ const val = e.value ?? {};
323
+ const nodeId = String(val.nodeId ?? "");
324
+ const nodeType = String(val.nodeType ?? "");
325
+ const nodeLabel = String(val.nodeLabel ?? "");
326
+ if (nodeId) acc.nodeMeta.set(nodeId, { nodeType, nodeLabel });
327
+ if (runCtx.workflowId) {
328
+ await hooks?.beforeWorkflowNode?.({
329
+ userId: runCtx.userId,
330
+ workflowId: runCtx.workflowId,
331
+ nodeId,
332
+ nodeType,
333
+ nodeLabel,
334
+ input: val.input
335
+ });
336
+ }
337
+ } else if (e.name === "workflow_node_completed") {
338
+ const val = e.value ?? {};
339
+ const nodeId = String(val.nodeId ?? "");
340
+ const meta = acc.nodeMeta.get(nodeId);
341
+ const nodeType = String(val.nodeType ?? meta?.nodeType ?? "");
342
+ const nodeLabel = String(val.nodeLabel ?? meta?.nodeLabel ?? "");
343
+ if (runCtx.workflowId) {
344
+ await hooks?.afterWorkflowNode?.(
345
+ {
346
+ userId: runCtx.userId,
347
+ workflowId: runCtx.workflowId,
348
+ nodeId,
349
+ nodeType,
350
+ nodeLabel
351
+ },
352
+ val.output ?? val
353
+ );
354
+ }
355
+ } else if (e.name === "workflow_node_failed") {
356
+ acc.erroredInBand = true;
357
+ }
318
358
  break;
319
359
  }
320
360
  case EventType.RUN_ERROR: {
@@ -421,6 +461,7 @@ var RunDriver = class {
421
461
  userId: this.runCtx.userId,
422
462
  phase: this.runCtx.kind,
423
463
  agentId: this.runCtx.agentId,
464
+ workflowId: this.runCtx.workflowId,
424
465
  threadId: this.runCtx.threadId
425
466
  },
426
467
  err
@@ -651,6 +692,7 @@ function parseArchitectBody(body) {
651
692
  }
652
693
  return {
653
694
  messages: b.messages,
695
+ threadId: typeof b.threadId === "string" ? b.threadId : void 0,
654
696
  resume: b.resume ?? void 0
655
697
  };
656
698
  }
@@ -659,6 +701,7 @@ var architectRoute = async (request, ctx) => {
659
701
  logger.debug("architectRoute start", { userId: request.userId });
660
702
  const body = parseArchitectBody(request.body);
661
703
  logger.trace("architectRoute body", {
704
+ threadId: body.threadId,
662
705
  messageCount: body.messages?.length ?? 0,
663
706
  hasResume: !!body.resume
664
707
  });
@@ -666,18 +709,20 @@ var architectRoute = async (request, ctx) => {
666
709
  const runCtx = {
667
710
  userId,
668
711
  kind: "architect",
712
+ threadId: body.threadId,
669
713
  messages: body.messages
670
714
  };
671
- logger.debug("beforeRun hook (architect)", { userId });
715
+ logger.debug("beforeRun hook (architect)", { userId, threadId: body.threadId });
672
716
  await ctx.hooks?.beforeRun?.(runCtx);
673
717
  logger.trace("beforeRun completed (architect)");
674
- logger.debug("starting architect stream");
718
+ logger.debug("starting architect stream", { threadId: body.threadId });
675
719
  const stream = ctx.client.architect.stream({
676
720
  messages: body.messages,
721
+ threadId: body.threadId,
677
722
  resume: body.resume
678
723
  });
679
724
  const runId = crypto.randomUUID();
680
- logger.info("architect run created", { runId, userId });
725
+ logger.info("architect run created", { runId, userId, threadId: body.threadId });
681
726
  const driver = new RunDriver(runId, runCtx, stream, ctx.hooks, ctx.mode);
682
727
  ctx.runs.set(runId, driver);
683
728
  logger.debug("architect driver registered", { runId, trackedRuns: ctx.runs.size });
@@ -1319,6 +1364,158 @@ var listAuditLogs = async (request, ctx) => {
1319
1364
  return json(200, items);
1320
1365
  };
1321
1366
 
1367
+ // src/routes/workflows.ts
1368
+ var listWorkflows = async (request, ctx) => {
1369
+ const items = await ctx.client.workflows.list({
1370
+ page: toInt(request.query.page),
1371
+ limit: toInt(request.query.limit),
1372
+ search: request.query.search,
1373
+ scope: request.query.scope,
1374
+ visibility: request.query.visibility,
1375
+ isEnabled: request.query.isEnabled !== void 0 ? request.query.isEnabled === "true" : void 0
1376
+ });
1377
+ return json(200, items);
1378
+ };
1379
+ var createWorkflow = async (request, ctx) => {
1380
+ const body = requireBodyObject(request.body);
1381
+ const input = {
1382
+ name: requireStringField(body, "name"),
1383
+ description: typeof body.description === "string" ? body.description : void 0,
1384
+ visibility: body.visibility,
1385
+ isEnabled: typeof body.isEnabled === "boolean" ? body.isEnabled : void 0,
1386
+ draft: body.draft ?? void 0
1387
+ };
1388
+ const idempotencyKey = request.headers["idempotency-key"];
1389
+ const workflow = await ctx.client.workflows.create(input, idempotencyKey);
1390
+ return json(201, workflow);
1391
+ };
1392
+ var getWorkflow = async (_request, ctx) => {
1393
+ const workflow = await ctx.client.workflows.get(requireParam(ctx.params, "id"));
1394
+ return json(200, workflow);
1395
+ };
1396
+ var updateWorkflow = async (request, ctx) => {
1397
+ const body = requireBodyObject(request.body);
1398
+ const input = {
1399
+ name: typeof body.name === "string" ? body.name : void 0,
1400
+ description: typeof body.description === "string" ? body.description : void 0,
1401
+ visibility: body.visibility,
1402
+ isEnabled: typeof body.isEnabled === "boolean" ? body.isEnabled : void 0,
1403
+ draft: body.draft ?? void 0
1404
+ };
1405
+ const updated = await ctx.client.workflows.update(
1406
+ requireParam(ctx.params, "id"),
1407
+ input
1408
+ );
1409
+ return json(200, updated);
1410
+ };
1411
+ var deleteWorkflow = async (_request, ctx) => {
1412
+ await ctx.client.workflows.delete(requireParam(ctx.params, "id"));
1413
+ return noContent();
1414
+ };
1415
+ var saveWorkflowDraft = async (request, ctx) => {
1416
+ const body = requireBodyObject(request.body);
1417
+ const draft = body;
1418
+ const updated = await ctx.client.workflows.saveDraft(
1419
+ requireParam(ctx.params, "id"),
1420
+ draft
1421
+ );
1422
+ return json(200, updated);
1423
+ };
1424
+ var publishWorkflow = async (_request, ctx) => {
1425
+ const version = await ctx.client.workflows.publish(requireParam(ctx.params, "id"));
1426
+ return json(201, version);
1427
+ };
1428
+ var listWorkflowVersions = async (request, ctx) => {
1429
+ const items = await ctx.client.workflows.listVersions(
1430
+ requireParam(ctx.params, "id"),
1431
+ {
1432
+ page: toInt(request.query.page),
1433
+ limit: toInt(request.query.limit)
1434
+ }
1435
+ );
1436
+ return json(200, items);
1437
+ };
1438
+ var getWorkflowVersion = async (_request, ctx) => {
1439
+ const versionNum = toInt(ctx.params.version);
1440
+ const version = await ctx.client.workflows.getVersion(
1441
+ requireParam(ctx.params, "id"),
1442
+ versionNum ?? 1
1443
+ );
1444
+ return json(200, version);
1445
+ };
1446
+ var getWorkflowMermaid = async (_request, ctx) => {
1447
+ const result = await ctx.client.workflows.getMermaid(requireParam(ctx.params, "id"));
1448
+ return json(200, result);
1449
+ };
1450
+ var listWorkflowRuns = async (request, ctx) => {
1451
+ const items = await ctx.client.workflows.listRuns(requireParam(ctx.params, "id"), {
1452
+ page: toInt(request.query.page),
1453
+ limit: toInt(request.query.limit),
1454
+ status: request.query.status,
1455
+ isDryRun: request.query.isDryRun !== void 0 ? request.query.isDryRun === "true" : void 0
1456
+ });
1457
+ return json(200, items);
1458
+ };
1459
+ var getWorkflowRun = async (_request, ctx) => {
1460
+ const run = await ctx.client.workflows.getRun(requireParam(ctx.params, "runId"));
1461
+ return json(200, run);
1462
+ };
1463
+ var cancelWorkflowRun = async (_request, ctx) => {
1464
+ const result = await ctx.client.workflows.cancel(requireParam(ctx.params, "runId"));
1465
+ return json(200, result);
1466
+ };
1467
+
1468
+ // src/routes/workflowStream.ts
1469
+ function parseWorkflowStreamBody(body) {
1470
+ if (body === void 0 || body === null) return {};
1471
+ if (typeof body !== "object") {
1472
+ throw new RuntimeHttpError(400, "INVALID_REQUEST", "Request body must be a JSON object.");
1473
+ }
1474
+ const b = body;
1475
+ return {
1476
+ input: b.input,
1477
+ dryRun: typeof b.dryRun === "boolean" ? b.dryRun : void 0,
1478
+ version: typeof b.version === "number" ? b.version : void 0
1479
+ };
1480
+ }
1481
+ var workflowStreamRoute = async (request, ctx) => {
1482
+ const workflowId = requireParam(ctx.params, "id");
1483
+ const body = parseWorkflowStreamBody(request.body);
1484
+ const userId = request.userId;
1485
+ const runCtx = {
1486
+ userId,
1487
+ kind: "workflow",
1488
+ workflowId,
1489
+ input: body.input
1490
+ };
1491
+ await ctx.hooks?.beforeRun?.(runCtx);
1492
+ const stream = ctx.client.workflows.stream(workflowId, {
1493
+ input: body.input,
1494
+ dryRun: body.dryRun,
1495
+ version: body.version
1496
+ });
1497
+ const runId = crypto.randomUUID();
1498
+ const driver = new RunDriver(runId, runCtx, stream, ctx.hooks, ctx.mode);
1499
+ ctx.runs.set(runId, driver);
1500
+ try {
1501
+ await driver.waitForFirstFrame();
1502
+ } catch (err) {
1503
+ ctx.runs.delete(runId);
1504
+ throw err;
1505
+ }
1506
+ return {
1507
+ kind: "stream",
1508
+ status: 200,
1509
+ headers: {
1510
+ "content-type": "text/event-stream",
1511
+ "cache-control": "no-cache",
1512
+ connection: "keep-alive",
1513
+ "x-persona-run-id": runId
1514
+ },
1515
+ body: withHeartbeats(driver.subscribe(-1), ctx.heartbeatIntervalMs)
1516
+ };
1517
+ };
1518
+
1322
1519
  // src/runtime.ts
1323
1520
  function resolveCapabilities(capabilities) {
1324
1521
  return {
@@ -1329,7 +1526,8 @@ function resolveCapabilities(capabilities) {
1329
1526
  knowledge: capabilities?.knowledge ?? false,
1330
1527
  stores: capabilities?.stores ?? false,
1331
1528
  auditLogs: capabilities?.auditLogs ?? false,
1332
- architect: capabilities?.architect ?? false
1529
+ architect: capabilities?.architect ?? false,
1530
+ workflowsWrite: capabilities?.workflowsWrite ?? false
1333
1531
  };
1334
1532
  }
1335
1533
  function buildRoutes(capabilities) {
@@ -1405,6 +1603,19 @@ function buildRoutes(capabilities) {
1405
1603
  method: "POST",
1406
1604
  pattern: ["mcps", ":id", "call-tool"],
1407
1605
  handler: callMcpTool
1606
+ },
1607
+ // Workflows — read-only discovery & execution always on; authoring ops behind workflowsWrite.
1608
+ { method: "GET", pattern: ["workflows"], handler: listWorkflows },
1609
+ { method: "POST", pattern: ["workflows", ":id", "stream"], handler: workflowStreamRoute },
1610
+ {
1611
+ method: "GET",
1612
+ pattern: ["workflows", "runs", ":runId", "resume"],
1613
+ handler: createResumeRoute("workflow")
1614
+ },
1615
+ {
1616
+ method: "POST",
1617
+ pattern: ["workflows", "runs", ":runId", "cancel"],
1618
+ handler: cancelWorkflowRun
1408
1619
  }
1409
1620
  ];
1410
1621
  if (capabilities.agentsWrite) {
@@ -1505,6 +1716,21 @@ function buildRoutes(capabilities) {
1505
1716
  }
1506
1717
  );
1507
1718
  }
1719
+ if (capabilities.workflowsWrite) {
1720
+ routes.push(
1721
+ { method: "POST", pattern: ["workflows"], handler: createWorkflow },
1722
+ { method: "GET", pattern: ["workflows", ":id"], handler: getWorkflow },
1723
+ { method: "PATCH", pattern: ["workflows", ":id"], handler: updateWorkflow },
1724
+ { method: "DELETE", pattern: ["workflows", ":id"], handler: deleteWorkflow },
1725
+ { method: "PUT", pattern: ["workflows", ":id", "draft"], handler: saveWorkflowDraft },
1726
+ { method: "POST", pattern: ["workflows", ":id", "publish"], handler: publishWorkflow },
1727
+ { method: "GET", pattern: ["workflows", ":id", "versions"], handler: listWorkflowVersions },
1728
+ { method: "GET", pattern: ["workflows", ":id", "versions", ":version"], handler: getWorkflowVersion },
1729
+ { method: "GET", pattern: ["workflows", ":id", "mermaid"], handler: getWorkflowMermaid },
1730
+ { method: "GET", pattern: ["workflows", ":id", "runs"], handler: listWorkflowRuns },
1731
+ { method: "GET", pattern: ["workflows", "runs", ":runId"], handler: getWorkflowRun }
1732
+ );
1733
+ }
1508
1734
  return routes;
1509
1735
  }
1510
1736
  function resolveMode(options) {