@personaai/runtime 0.9.4 → 0.10.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
@@ -837,6 +878,7 @@ var createAgent = async (request, ctx) => {
837
878
  socialLinks: body.socialLinks ?? void 0,
838
879
  modelName: typeof body.modelName === "string" ? body.modelName : void 0,
839
880
  webSearchEnabled: typeof body.webSearchEnabled === "boolean" ? body.webSearchEnabled : void 0,
881
+ sandboxEnabled: typeof body.sandboxEnabled === "boolean" ? body.sandboxEnabled : void 0,
840
882
  visibility: body.visibility,
841
883
  category: body.category,
842
884
  skills: Array.isArray(body.skills) ? body.skills : void 0,
@@ -1318,6 +1360,158 @@ var listAuditLogs = async (request, ctx) => {
1318
1360
  return json(200, items);
1319
1361
  };
1320
1362
 
1363
+ // src/routes/workflows.ts
1364
+ var listWorkflows = async (request, ctx) => {
1365
+ const items = await ctx.client.workflows.list({
1366
+ page: toInt(request.query.page),
1367
+ limit: toInt(request.query.limit),
1368
+ search: request.query.search,
1369
+ scope: request.query.scope,
1370
+ visibility: request.query.visibility,
1371
+ isEnabled: request.query.isEnabled !== void 0 ? request.query.isEnabled === "true" : void 0
1372
+ });
1373
+ return json(200, items);
1374
+ };
1375
+ var createWorkflow = async (request, ctx) => {
1376
+ const body = requireBodyObject(request.body);
1377
+ const input = {
1378
+ name: requireStringField(body, "name"),
1379
+ description: typeof body.description === "string" ? body.description : void 0,
1380
+ visibility: body.visibility,
1381
+ isEnabled: typeof body.isEnabled === "boolean" ? body.isEnabled : void 0,
1382
+ draft: body.draft ?? void 0
1383
+ };
1384
+ const idempotencyKey = request.headers["idempotency-key"];
1385
+ const workflow = await ctx.client.workflows.create(input, idempotencyKey);
1386
+ return json(201, workflow);
1387
+ };
1388
+ var getWorkflow = async (_request, ctx) => {
1389
+ const workflow = await ctx.client.workflows.get(requireParam(ctx.params, "id"));
1390
+ return json(200, workflow);
1391
+ };
1392
+ var updateWorkflow = async (request, ctx) => {
1393
+ const body = requireBodyObject(request.body);
1394
+ const input = {
1395
+ name: typeof body.name === "string" ? body.name : void 0,
1396
+ description: typeof body.description === "string" ? body.description : void 0,
1397
+ visibility: body.visibility,
1398
+ isEnabled: typeof body.isEnabled === "boolean" ? body.isEnabled : void 0,
1399
+ draft: body.draft ?? void 0
1400
+ };
1401
+ const updated = await ctx.client.workflows.update(
1402
+ requireParam(ctx.params, "id"),
1403
+ input
1404
+ );
1405
+ return json(200, updated);
1406
+ };
1407
+ var deleteWorkflow = async (_request, ctx) => {
1408
+ await ctx.client.workflows.delete(requireParam(ctx.params, "id"));
1409
+ return noContent();
1410
+ };
1411
+ var saveWorkflowDraft = async (request, ctx) => {
1412
+ const body = requireBodyObject(request.body);
1413
+ const draft = body;
1414
+ const updated = await ctx.client.workflows.saveDraft(
1415
+ requireParam(ctx.params, "id"),
1416
+ draft
1417
+ );
1418
+ return json(200, updated);
1419
+ };
1420
+ var publishWorkflow = async (_request, ctx) => {
1421
+ const version = await ctx.client.workflows.publish(requireParam(ctx.params, "id"));
1422
+ return json(201, version);
1423
+ };
1424
+ var listWorkflowVersions = async (request, ctx) => {
1425
+ const items = await ctx.client.workflows.listVersions(
1426
+ requireParam(ctx.params, "id"),
1427
+ {
1428
+ page: toInt(request.query.page),
1429
+ limit: toInt(request.query.limit)
1430
+ }
1431
+ );
1432
+ return json(200, items);
1433
+ };
1434
+ var getWorkflowVersion = async (_request, ctx) => {
1435
+ const versionNum = toInt(ctx.params.version);
1436
+ const version = await ctx.client.workflows.getVersion(
1437
+ requireParam(ctx.params, "id"),
1438
+ versionNum ?? 1
1439
+ );
1440
+ return json(200, version);
1441
+ };
1442
+ var getWorkflowMermaid = async (_request, ctx) => {
1443
+ const result = await ctx.client.workflows.getMermaid(requireParam(ctx.params, "id"));
1444
+ return json(200, result);
1445
+ };
1446
+ var listWorkflowRuns = async (request, ctx) => {
1447
+ const items = await ctx.client.workflows.listRuns(requireParam(ctx.params, "id"), {
1448
+ page: toInt(request.query.page),
1449
+ limit: toInt(request.query.limit),
1450
+ status: request.query.status,
1451
+ isDryRun: request.query.isDryRun !== void 0 ? request.query.isDryRun === "true" : void 0
1452
+ });
1453
+ return json(200, items);
1454
+ };
1455
+ var getWorkflowRun = async (_request, ctx) => {
1456
+ const run = await ctx.client.workflows.getRun(requireParam(ctx.params, "runId"));
1457
+ return json(200, run);
1458
+ };
1459
+ var cancelWorkflowRun = async (_request, ctx) => {
1460
+ const result = await ctx.client.workflows.cancel(requireParam(ctx.params, "runId"));
1461
+ return json(200, result);
1462
+ };
1463
+
1464
+ // src/routes/workflowStream.ts
1465
+ function parseWorkflowStreamBody(body) {
1466
+ if (body === void 0 || body === null) return {};
1467
+ if (typeof body !== "object") {
1468
+ throw new RuntimeHttpError(400, "INVALID_REQUEST", "Request body must be a JSON object.");
1469
+ }
1470
+ const b = body;
1471
+ return {
1472
+ input: b.input,
1473
+ dryRun: typeof b.dryRun === "boolean" ? b.dryRun : void 0,
1474
+ version: typeof b.version === "number" ? b.version : void 0
1475
+ };
1476
+ }
1477
+ var workflowStreamRoute = async (request, ctx) => {
1478
+ const workflowId = requireParam(ctx.params, "id");
1479
+ const body = parseWorkflowStreamBody(request.body);
1480
+ const userId = request.userId;
1481
+ const runCtx = {
1482
+ userId,
1483
+ kind: "workflow",
1484
+ workflowId,
1485
+ input: body.input
1486
+ };
1487
+ await ctx.hooks?.beforeRun?.(runCtx);
1488
+ const stream = ctx.client.workflows.stream(workflowId, {
1489
+ input: body.input,
1490
+ dryRun: body.dryRun,
1491
+ version: body.version
1492
+ });
1493
+ const runId = crypto.randomUUID();
1494
+ const driver = new RunDriver(runId, runCtx, stream, ctx.hooks, ctx.mode);
1495
+ ctx.runs.set(runId, driver);
1496
+ try {
1497
+ await driver.waitForFirstFrame();
1498
+ } catch (err) {
1499
+ ctx.runs.delete(runId);
1500
+ throw err;
1501
+ }
1502
+ return {
1503
+ kind: "stream",
1504
+ status: 200,
1505
+ headers: {
1506
+ "content-type": "text/event-stream",
1507
+ "cache-control": "no-cache",
1508
+ connection: "keep-alive",
1509
+ "x-persona-run-id": runId
1510
+ },
1511
+ body: withHeartbeats(driver.subscribe(-1), ctx.heartbeatIntervalMs)
1512
+ };
1513
+ };
1514
+
1321
1515
  // src/runtime.ts
1322
1516
  function resolveCapabilities(capabilities) {
1323
1517
  return {
@@ -1328,7 +1522,8 @@ function resolveCapabilities(capabilities) {
1328
1522
  knowledge: capabilities?.knowledge ?? false,
1329
1523
  stores: capabilities?.stores ?? false,
1330
1524
  auditLogs: capabilities?.auditLogs ?? false,
1331
- architect: capabilities?.architect ?? false
1525
+ architect: capabilities?.architect ?? false,
1526
+ workflowsWrite: capabilities?.workflowsWrite ?? false
1332
1527
  };
1333
1528
  }
1334
1529
  function buildRoutes(capabilities) {
@@ -1404,6 +1599,19 @@ function buildRoutes(capabilities) {
1404
1599
  method: "POST",
1405
1600
  pattern: ["mcps", ":id", "call-tool"],
1406
1601
  handler: callMcpTool
1602
+ },
1603
+ // Workflows — read-only discovery & execution always on; authoring ops behind workflowsWrite.
1604
+ { method: "GET", pattern: ["workflows"], handler: listWorkflows },
1605
+ { method: "POST", pattern: ["workflows", ":id", "stream"], handler: workflowStreamRoute },
1606
+ {
1607
+ method: "GET",
1608
+ pattern: ["workflows", "runs", ":runId", "resume"],
1609
+ handler: createResumeRoute("workflow")
1610
+ },
1611
+ {
1612
+ method: "POST",
1613
+ pattern: ["workflows", "runs", ":runId", "cancel"],
1614
+ handler: cancelWorkflowRun
1407
1615
  }
1408
1616
  ];
1409
1617
  if (capabilities.agentsWrite) {
@@ -1504,6 +1712,21 @@ function buildRoutes(capabilities) {
1504
1712
  }
1505
1713
  );
1506
1714
  }
1715
+ if (capabilities.workflowsWrite) {
1716
+ routes.push(
1717
+ { method: "POST", pattern: ["workflows"], handler: createWorkflow },
1718
+ { method: "GET", pattern: ["workflows", ":id"], handler: getWorkflow },
1719
+ { method: "PATCH", pattern: ["workflows", ":id"], handler: updateWorkflow },
1720
+ { method: "DELETE", pattern: ["workflows", ":id"], handler: deleteWorkflow },
1721
+ { method: "PUT", pattern: ["workflows", ":id", "draft"], handler: saveWorkflowDraft },
1722
+ { method: "POST", pattern: ["workflows", ":id", "publish"], handler: publishWorkflow },
1723
+ { method: "GET", pattern: ["workflows", ":id", "versions"], handler: listWorkflowVersions },
1724
+ { method: "GET", pattern: ["workflows", ":id", "versions", ":version"], handler: getWorkflowVersion },
1725
+ { method: "GET", pattern: ["workflows", ":id", "mermaid"], handler: getWorkflowMermaid },
1726
+ { method: "GET", pattern: ["workflows", ":id", "runs"], handler: listWorkflowRuns },
1727
+ { method: "GET", pattern: ["workflows", "runs", ":runId"], handler: getWorkflowRun }
1728
+ );
1729
+ }
1507
1730
  return routes;
1508
1731
  }
1509
1732
  function resolveMode(options) {