@polos/sdk 0.2.1 → 0.2.3

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.js CHANGED
@@ -722,6 +722,11 @@ var OrchestratorClient = class {
722
722
  if (request.waitForSubworkflow !== void 0)
723
723
  body["wait_for_subworkflow"] = request.waitForSubworkflow;
724
724
  if (request.otelTraceparent !== void 0) body["otel_traceparent"] = request.otelTraceparent;
725
+ if (request.channelContext !== void 0)
726
+ body["channel_context"] = {
727
+ channel_id: request.channelContext.channelId,
728
+ source: request.channelContext.source
729
+ };
725
730
  return this.request("POST", "/api/v1/workflows/batch_run", {
726
731
  body
727
732
  });
@@ -3355,6 +3360,187 @@ function defineAgent(config) {
3355
3360
  });
3356
3361
  return agentWorkflow;
3357
3362
  }
3363
+
3364
+ // src/channels/slack.ts
3365
+ var SlackChannel = class {
3366
+ id = "slack";
3367
+ outputMode = "per_step";
3368
+ config;
3369
+ constructor(config) {
3370
+ if (!config.botToken.startsWith("xoxb-")) {
3371
+ throw new Error(
3372
+ `Invalid Slack bot token: must start with "xoxb-". Use the Bot User OAuth Token from your Slack app's OAuth & Permissions page.`
3373
+ );
3374
+ }
3375
+ this.config = config;
3376
+ }
3377
+ async notify(notification) {
3378
+ const overrides = notification.channelOverrides;
3379
+ const channel = overrides?.["channel"] ?? this.config.defaultChannel;
3380
+ const threadTs = overrides?.["thread_ts"] ?? overrides?.["threadTs"];
3381
+ const blocks = this.buildBlocks(notification);
3382
+ const text = notification.title ?? "Agent needs your input";
3383
+ const messageTs = await this.postMessage(channel, threadTs, text, blocks);
3384
+ return {
3385
+ slack_channel: channel,
3386
+ slack_message_ts: messageTs,
3387
+ slack_blocks: blocks
3388
+ };
3389
+ }
3390
+ async sendOutput(context2, event) {
3391
+ const channel = context2.source["channel"];
3392
+ const threadTs = context2.source["threadTs"];
3393
+ if (!channel) return;
3394
+ const text = this.formatOutputEvent(event);
3395
+ if (!text) return;
3396
+ await this.postMessage(channel, threadTs, text);
3397
+ }
3398
+ async postMessage(channel, threadTs, text, blocks) {
3399
+ const body = { channel, text };
3400
+ if (threadTs) body["thread_ts"] = threadTs;
3401
+ if (blocks) body["blocks"] = blocks;
3402
+ const response = await fetch("https://slack.com/api/chat.postMessage", {
3403
+ method: "POST",
3404
+ headers: {
3405
+ Authorization: `Bearer ${this.config.botToken}`,
3406
+ "Content-Type": "application/json"
3407
+ },
3408
+ body: JSON.stringify(body)
3409
+ });
3410
+ const data = await response.json();
3411
+ if (!data.ok) {
3412
+ throw new Error(`Slack API error: ${data.error ?? "unknown"}`);
3413
+ }
3414
+ return data.ts ?? "";
3415
+ }
3416
+ formatOutputEvent(event) {
3417
+ const eventType = event.eventType;
3418
+ if (eventType === "workflow_finish" || eventType === "agent_finish") {
3419
+ const metadata = event.data["_metadata"];
3420
+ const rawResult = event.data["result"];
3421
+ const error = event.data["error"];
3422
+ const workflowId = metadata?.["workflow_id"];
3423
+ if (error) {
3424
+ return `\u274C *${workflowId ?? "Workflow"} failed:* ${error}`;
3425
+ }
3426
+ const result = typeof rawResult === "object" && rawResult !== null && "result" in rawResult ? rawResult["result"] : rawResult;
3427
+ const resultStr = typeof result === "string" ? result : JSON.stringify(result, null, 2);
3428
+ if (resultStr) {
3429
+ return resultStr;
3430
+ }
3431
+ return `\u2705 *${workflowId ?? "Workflow"} finished*`;
3432
+ }
3433
+ if (eventType === "tool_call") {
3434
+ const toolCall = event.data["tool_call"];
3435
+ if (toolCall) {
3436
+ const fn = toolCall["function"];
3437
+ const name = fn?.["name"];
3438
+ if (name) {
3439
+ return `\u{1F527} Calling tool: \`${name}\``;
3440
+ }
3441
+ }
3442
+ return null;
3443
+ }
3444
+ if (eventType === "step_finish") {
3445
+ const stepKey = event.data["step_key"];
3446
+ const error = event.data["error"];
3447
+ if (error) {
3448
+ return `\u26A0\uFE0F Step \`${stepKey ?? "unknown"}\` failed: ${error}`;
3449
+ }
3450
+ return null;
3451
+ }
3452
+ return null;
3453
+ }
3454
+ buildBlocks(n) {
3455
+ const blocks = [];
3456
+ blocks.push({
3457
+ type: "header",
3458
+ text: { type: "plain_text", text: n.title ?? "Agent needs your input" }
3459
+ });
3460
+ if (n.description) {
3461
+ blocks.push({
3462
+ type: "section",
3463
+ text: { type: "mrkdwn", text: n.description }
3464
+ });
3465
+ }
3466
+ if (n.source || n.tool) {
3467
+ const parts = [];
3468
+ if (n.source) parts.push(`*Source:* ${n.source}`);
3469
+ if (n.tool) parts.push(`*Tool:* \`${n.tool}\``);
3470
+ blocks.push({
3471
+ type: "context",
3472
+ elements: [{ type: "mrkdwn", text: parts.join(" | ") }]
3473
+ });
3474
+ }
3475
+ if (n.context && Object.keys(n.context).length > 0) {
3476
+ const contextText = JSON.stringify(n.context, null, 2);
3477
+ blocks.push({
3478
+ type: "section",
3479
+ text: { type: "mrkdwn", text: "```" + contextText + "```" }
3480
+ });
3481
+ }
3482
+ if (n.expiresAt) {
3483
+ blocks.push({
3484
+ type: "context",
3485
+ elements: [{ type: "mrkdwn", text: `Expires: ${n.expiresAt}` }]
3486
+ });
3487
+ }
3488
+ if (this.isSimpleApproval(n)) {
3489
+ const approveValue = JSON.stringify({
3490
+ executionId: n.executionId,
3491
+ stepKey: n.stepKey,
3492
+ approved: true
3493
+ });
3494
+ const rejectValue = JSON.stringify({
3495
+ executionId: n.executionId,
3496
+ stepKey: n.stepKey,
3497
+ approved: false
3498
+ });
3499
+ blocks.push({
3500
+ type: "actions",
3501
+ elements: [
3502
+ {
3503
+ type: "button",
3504
+ action_id: "polos_approve",
3505
+ text: { type: "plain_text", text: "Approve" },
3506
+ style: "primary",
3507
+ value: approveValue
3508
+ },
3509
+ {
3510
+ type: "button",
3511
+ action_id: "polos_reject",
3512
+ text: { type: "plain_text", text: "Reject" },
3513
+ style: "danger",
3514
+ value: rejectValue
3515
+ },
3516
+ {
3517
+ type: "button",
3518
+ text: { type: "plain_text", text: "View Details" },
3519
+ url: n.approvalUrl
3520
+ }
3521
+ ]
3522
+ });
3523
+ } else {
3524
+ blocks.push({
3525
+ type: "actions",
3526
+ elements: [
3527
+ {
3528
+ type: "button",
3529
+ text: { type: "plain_text", text: "Respond" },
3530
+ url: n.approvalUrl,
3531
+ style: "primary"
3532
+ }
3533
+ ]
3534
+ });
3535
+ }
3536
+ return blocks;
3537
+ }
3538
+ isSimpleApproval(n) {
3539
+ const fields = n.formFields;
3540
+ if (!fields || fields.length === 0) return false;
3541
+ return fields.some((f) => f["key"] === "approved" && f["type"] === "boolean");
3542
+ }
3543
+ };
3358
3544
  var logger4 = createLogger({ name: "worker-server" });
3359
3545
  var WorkerServer = class {
3360
3546
  app;
@@ -4208,7 +4394,8 @@ function createOrchestratorStepHelper(orchestratorClient, cachedSteps, execCtx,
4208
4394
  otelTraceparent: getCurrentTraceparent(),
4209
4395
  waitForSubworkflow: options?.waitForSubworkflow ?? false,
4210
4396
  initialState: options?.initialState,
4211
- runTimeoutSeconds: options?.runTimeoutSeconds
4397
+ runTimeoutSeconds: options?.runTimeoutSeconds,
4398
+ channelContext
4212
4399
  });
4213
4400
  if (options?.waitForSubworkflow) {
4214
4401
  return [void 0, false];
@@ -4396,7 +4583,8 @@ function createOrchestratorStepHelper(orchestratorClient, cachedSteps, execCtx,
4396
4583
  sessionId: execCtx.sessionId,
4397
4584
  userId: execCtx.userId,
4398
4585
  waitForSubworkflow: false,
4399
- otelTraceparent: getCurrentTraceparent()
4586
+ otelTraceparent: getCurrentTraceparent(),
4587
+ channelContext
4400
4588
  });
4401
4589
  const handleData = response.executions.map((exec, i) => {
4402
4590
  const item = items[i];
@@ -4472,7 +4660,8 @@ function createOrchestratorStepHelper(orchestratorClient, cachedSteps, execCtx,
4472
4660
  sessionId: execCtx.sessionId,
4473
4661
  userId: execCtx.userId,
4474
4662
  waitForSubworkflow: true,
4475
- otelTraceparent: getCurrentTraceparent()
4663
+ otelTraceparent: getCurrentTraceparent(),
4664
+ channelContext
4476
4665
  });
4477
4666
  const workflowIds = items.map((item) => typeof item.workflow === "string" ? item.workflow : item.workflow.id).join(", ");
4478
4667
  throw new WaitError(`Waiting for sub-workflows [${workflowIds}] to complete`, {
@@ -4668,7 +4857,7 @@ function createOrchestratorStepHelper(orchestratorClient, cachedSteps, execCtx,
4668
4857
  if (channelContext !== void 0) {
4669
4858
  notification.channelContext = channelContext;
4670
4859
  }
4671
- await Promise.allSettled(
4860
+ const notifyResults = await Promise.allSettled(
4672
4861
  channels.map(async (ch) => {
4673
4862
  try {
4674
4863
  let overrides = notifyConfig?.[ch.id];
@@ -4676,12 +4865,35 @@ function createOrchestratorStepHelper(orchestratorClient, cachedSteps, execCtx,
4676
4865
  overrides = { ...channelContext.source, ...overrides };
4677
4866
  }
4678
4867
  const n = overrides !== void 0 ? { ...notification, channelOverrides: overrides } : notification;
4679
- await ch.notify(n);
4868
+ const meta = await ch.notify(n);
4869
+ return meta ? { channelId: ch.id, ...meta } : void 0;
4680
4870
  } catch (err) {
4681
4871
  logger6.warn(`Channel ${ch.id} notification failed`, { error: String(err) });
4872
+ return void 0;
4682
4873
  }
4683
4874
  })
4684
4875
  );
4876
+ const metaEntries = [];
4877
+ for (const r of notifyResults) {
4878
+ if (r.status === "fulfilled" && r.value != null) {
4879
+ metaEntries.push(r.value);
4880
+ }
4881
+ }
4882
+ if (metaEntries.length > 0) {
4883
+ orchestratorClient.publishEvent({
4884
+ topic,
4885
+ events: [
4886
+ {
4887
+ eventType: `notification_meta_${key}`,
4888
+ data: { channels: metaEntries }
4889
+ }
4890
+ ],
4891
+ executionId: execCtx.executionId,
4892
+ rootExecutionId: execCtx.rootExecutionId
4893
+ }).catch((err) => {
4894
+ logger6.warn("Failed to publish notification metadata", { error: String(err) });
4895
+ });
4896
+ }
4685
4897
  }
4686
4898
  throw new WaitError(`Waiting for resume event: ${topic}`, { topic });
4687
4899
  },
@@ -5322,7 +5534,27 @@ function spawnCommand(command, args, options) {
5322
5534
  killed = true;
5323
5535
  proc.kill("SIGKILL");
5324
5536
  }, timeoutMs);
5537
+ let exitGraceTimer = null;
5538
+ let exitCode = null;
5539
+ proc.on("exit", (code) => {
5540
+ exitCode = code;
5541
+ exitGraceTimer = setTimeout(() => {
5542
+ clearTimeout(timer);
5543
+ settle(() => {
5544
+ if (killed) {
5545
+ resolve10({
5546
+ exitCode: 137,
5547
+ stdout,
5548
+ stderr: stderr + "\n[Process killed: timeout exceeded]"
5549
+ });
5550
+ } else {
5551
+ resolve10({ exitCode: exitCode ?? 1, stdout, stderr });
5552
+ }
5553
+ });
5554
+ }, 2e3);
5555
+ });
5325
5556
  proc.on("close", (code) => {
5557
+ if (exitGraceTimer) clearTimeout(exitGraceTimer);
5326
5558
  clearTimeout(timer);
5327
5559
  settle(() => {
5328
5560
  if (killed) {
@@ -5332,11 +5564,12 @@ function spawnCommand(command, args, options) {
5332
5564
  stderr: stderr + "\n[Process killed: timeout exceeded]"
5333
5565
  });
5334
5566
  } else {
5335
- resolve10({ exitCode: code ?? 1, stdout, stderr });
5567
+ resolve10({ exitCode: code ?? exitCode ?? 1, stdout, stderr });
5336
5568
  }
5337
5569
  });
5338
5570
  });
5339
5571
  proc.on("error", (err) => {
5572
+ if (exitGraceTimer) clearTimeout(exitGraceTimer);
5340
5573
  clearTimeout(timer);
5341
5574
  settle(() => {
5342
5575
  reject(err);
@@ -5582,7 +5815,27 @@ function spawnLocal(command, options) {
5582
5815
  killed = true;
5583
5816
  proc.kill("SIGKILL");
5584
5817
  }, timeoutMs);
5818
+ let exitGraceTimer = null;
5819
+ let exitCode = null;
5820
+ proc.on("exit", (code) => {
5821
+ exitCode = code;
5822
+ exitGraceTimer = setTimeout(() => {
5823
+ clearTimeout(timer);
5824
+ settle(() => {
5825
+ if (killed) {
5826
+ resolve10({
5827
+ exitCode: 137,
5828
+ stdout,
5829
+ stderr: stderr + "\n[Process killed: timeout exceeded]"
5830
+ });
5831
+ } else {
5832
+ resolve10({ exitCode: exitCode ?? 1, stdout, stderr });
5833
+ }
5834
+ });
5835
+ }, 2e3);
5836
+ });
5585
5837
  proc.on("close", (code) => {
5838
+ if (exitGraceTimer) clearTimeout(exitGraceTimer);
5586
5839
  clearTimeout(timer);
5587
5840
  settle(() => {
5588
5841
  if (killed) {
@@ -5592,11 +5845,12 @@ function spawnLocal(command, options) {
5592
5845
  stderr: stderr + "\n[Process killed: timeout exceeded]"
5593
5846
  });
5594
5847
  } else {
5595
- resolve10({ exitCode: code ?? 1, stdout, stderr });
5848
+ resolve10({ exitCode: code ?? exitCode ?? 1, stdout, stderr });
5596
5849
  }
5597
5850
  });
5598
5851
  });
5599
5852
  proc.on("error", (err) => {
5853
+ if (exitGraceTimer) clearTimeout(exitGraceTimer);
5600
5854
  clearTimeout(timer);
5601
5855
  settle(() => {
5602
5856
  reject(err);
@@ -6227,10 +6481,24 @@ var Worker = class {
6227
6481
  state = "stopped";
6228
6482
  heartbeatInterval = null;
6229
6483
  activeExecutions = /* @__PURE__ */ new Map();
6484
+ /** Tracks running channel bridges so we don't start duplicates on re-dispatch. */
6485
+ activeChannelBridges = /* @__PURE__ */ new Set();
6230
6486
  signalHandler = null;
6231
6487
  constructor(config) {
6232
6488
  this.config = config;
6233
6489
  this.channels = config.channels ?? [];
6490
+ if (!this.channels.some((ch) => ch.id === "slack")) {
6491
+ const slackBotToken = process.env["SLACK_BOT_TOKEN"];
6492
+ if (slackBotToken) {
6493
+ this.channels.push(
6494
+ new SlackChannel({
6495
+ botToken: slackBotToken,
6496
+ defaultChannel: process.env["SLACK_CHANNEL"] ?? "#general"
6497
+ })
6498
+ );
6499
+ logger9.info("Auto-registered SlackChannel from SLACK_BOT_TOKEN env var");
6500
+ }
6501
+ }
6234
6502
  this.maxConcurrentWorkflows = config.maxConcurrentWorkflows ?? 100;
6235
6503
  this.workerServerUrl = config.workerServerUrl ?? `http://localhost:${String(config.port ?? 8e3)}`;
6236
6504
  this.port = config.port ?? 8e3;
@@ -6764,6 +7032,11 @@ var Worker = class {
6764
7032
  };
6765
7033
  const hasWorkflowChannels = workflow.config.channels !== void 0;
6766
7034
  const resolvedChannels = workflow.config.channels ?? this.channels;
7035
+ if (data.channelContext && !data.parentExecutionId) {
7036
+ const rootExecId = data.rootExecutionId ?? executionId;
7037
+ const rootWfId = data.rootWorkflowId ?? workflowId;
7038
+ this.startChannelBridge(rootExecId, rootWfId, data.channelContext, workflow);
7039
+ }
6767
7040
  result = await executeWorkflow({
6768
7041
  workflow,
6769
7042
  payload: data.payload,
@@ -6775,9 +7048,6 @@ var Worker = class {
6775
7048
  sandboxManager: this.sandboxManager,
6776
7049
  channelContext: hasWorkflowChannels ? void 0 : data.channelContext
6777
7050
  });
6778
- if (data.channelContext) {
6779
- this.startChannelBridge(executionId, workflowId, data.channelContext, workflow);
6780
- }
6781
7051
  await this.handleExecutionResult(executionId, workflowId, context2, result);
6782
7052
  retryableFailure = !result.success && !result.waiting && (result.retryable ?? true);
6783
7053
  } catch (error) {
@@ -6920,15 +7190,20 @@ var Worker = class {
6920
7190
  /**
6921
7191
  * Start a channel bridge that streams execution events back to the originating channel.
6922
7192
  */
6923
- startChannelBridge(executionId, workflowId, channelCtx, workflow) {
7193
+ startChannelBridge(rootExecutionId, rootWorkflowId, channelCtx, workflow) {
7194
+ if (this.activeChannelBridges.has(rootExecutionId)) return;
6924
7195
  const channel = this.channels.find((ch) => ch.id === channelCtx.channelId);
6925
- if (!channel?.sendOutput) return;
7196
+ if (!channel) {
7197
+ logger9.error(
7198
+ `No channel registered for "${channelCtx.channelId}". ` + (channelCtx.channelId === "slack" ? "Set the SLACK_BOT_TOKEN environment variable so the worker can respond to Slack." : `Register a channel with id "${channelCtx.channelId}" on the worker.`),
7199
+ { executionId: rootExecutionId }
7200
+ );
7201
+ return;
7202
+ }
7203
+ if (!channel.sendOutput) return;
6926
7204
  const outputMode = workflow.config["channelOutputMode"] ?? channel.outputMode ?? "per_step";
6927
7205
  if (outputMode === "none") return;
6928
- const execution = this.activeExecutions.get(executionId);
6929
- if (!execution) return;
6930
- const rootExecutionId = execution.abortController.signal.aborted ? executionId : executionId;
6931
- const rootWorkflowId = workflowId;
7206
+ this.activeChannelBridges.add(rootExecutionId);
6932
7207
  void (async () => {
6933
7208
  try {
6934
7209
  const stream = this.orchestratorClient.streamEvents({
@@ -6936,13 +7211,14 @@ var Worker = class {
6936
7211
  workflowRunId: rootExecutionId
6937
7212
  });
6938
7213
  for await (const event of stream) {
6939
- if (execution.abortController.signal.aborted) break;
6940
7214
  if (shouldForwardEvent(event, outputMode)) {
6941
7215
  await channel.sendOutput?.(channelCtx, event);
6942
7216
  }
6943
7217
  }
6944
7218
  } catch (err) {
6945
- logger9.warn("Channel bridge error", { error: String(err), executionId });
7219
+ logger9.warn("Channel bridge error", { error: String(err), executionId: rootExecutionId });
7220
+ } finally {
7221
+ this.activeChannelBridges.delete(rootExecutionId);
6946
7222
  }
6947
7223
  })();
6948
7224
  }
@@ -7647,181 +7923,6 @@ function sandboxTools(config) {
7647
7923
  return tools;
7648
7924
  }
7649
7925
 
7650
- // src/channels/slack.ts
7651
- var SlackChannel = class {
7652
- id = "slack";
7653
- outputMode = "per_step";
7654
- config;
7655
- constructor(config) {
7656
- if (!config.botToken.startsWith("xoxb-")) {
7657
- throw new Error(
7658
- `Invalid Slack bot token: must start with "xoxb-". Use the Bot User OAuth Token from your Slack app's OAuth & Permissions page.`
7659
- );
7660
- }
7661
- this.config = config;
7662
- }
7663
- async notify(notification) {
7664
- const overrides = notification.channelOverrides;
7665
- const channel = overrides?.["channel"] ?? this.config.defaultChannel;
7666
- const threadTs = overrides?.["thread_ts"];
7667
- const blocks = this.buildBlocks(notification);
7668
- const text = notification.title ?? "Agent needs your input";
7669
- await this.postMessage(channel, threadTs, text, blocks);
7670
- }
7671
- async sendOutput(context2, event) {
7672
- const channel = context2.source["channel"];
7673
- const threadTs = context2.source["threadTs"];
7674
- if (!channel) return;
7675
- const text = this.formatOutputEvent(event);
7676
- if (!text) return;
7677
- await this.postMessage(channel, threadTs, text);
7678
- }
7679
- async postMessage(channel, threadTs, text, blocks) {
7680
- const body = { channel, text };
7681
- if (threadTs) body["thread_ts"] = threadTs;
7682
- if (blocks) body["blocks"] = blocks;
7683
- const response = await fetch("https://slack.com/api/chat.postMessage", {
7684
- method: "POST",
7685
- headers: {
7686
- Authorization: `Bearer ${this.config.botToken}`,
7687
- "Content-Type": "application/json"
7688
- },
7689
- body: JSON.stringify(body)
7690
- });
7691
- const data = await response.json();
7692
- if (!data.ok) {
7693
- throw new Error(`Slack API error: ${data.error ?? "unknown"}`);
7694
- }
7695
- }
7696
- formatOutputEvent(event) {
7697
- const eventType = event.eventType;
7698
- if (eventType === "workflow_finish" || eventType === "agent_finish") {
7699
- const metadata = event.data["_metadata"];
7700
- const result = event.data["result"];
7701
- const error = event.data["error"];
7702
- const workflowId = metadata?.["workflow_id"];
7703
- if (error) {
7704
- return `\u274C *${workflowId ?? "Workflow"} failed:* ${error}`;
7705
- }
7706
- const resultStr = typeof result === "string" ? result : JSON.stringify(result, null, 2);
7707
- if (resultStr) {
7708
- return `\u2705 *${workflowId ?? "Workflow"} finished:*
7709
- ${resultStr}`;
7710
- }
7711
- return `\u2705 *${workflowId ?? "Workflow"} finished*`;
7712
- }
7713
- if (eventType === "tool_call") {
7714
- const toolCall = event.data["tool_call"];
7715
- if (toolCall) {
7716
- const fn = toolCall["function"];
7717
- const name = fn?.["name"];
7718
- if (name) {
7719
- return `\u{1F527} Calling tool: \`${name}\``;
7720
- }
7721
- }
7722
- return null;
7723
- }
7724
- if (eventType === "step_finish") {
7725
- const stepKey = event.data["step_key"];
7726
- const error = event.data["error"];
7727
- if (error) {
7728
- return `\u26A0\uFE0F Step \`${stepKey ?? "unknown"}\` failed: ${error}`;
7729
- }
7730
- return null;
7731
- }
7732
- return null;
7733
- }
7734
- buildBlocks(n) {
7735
- const blocks = [];
7736
- blocks.push({
7737
- type: "header",
7738
- text: { type: "plain_text", text: n.title ?? "Agent needs your input" }
7739
- });
7740
- if (n.description) {
7741
- blocks.push({
7742
- type: "section",
7743
- text: { type: "mrkdwn", text: n.description }
7744
- });
7745
- }
7746
- if (n.source || n.tool) {
7747
- const parts = [];
7748
- if (n.source) parts.push(`*Source:* ${n.source}`);
7749
- if (n.tool) parts.push(`*Tool:* \`${n.tool}\``);
7750
- blocks.push({
7751
- type: "context",
7752
- elements: [{ type: "mrkdwn", text: parts.join(" | ") }]
7753
- });
7754
- }
7755
- if (n.context && Object.keys(n.context).length > 0) {
7756
- const contextText = JSON.stringify(n.context, null, 2);
7757
- blocks.push({
7758
- type: "section",
7759
- text: { type: "mrkdwn", text: "```" + contextText + "```" }
7760
- });
7761
- }
7762
- if (n.expiresAt) {
7763
- blocks.push({
7764
- type: "context",
7765
- elements: [{ type: "mrkdwn", text: `Expires: ${n.expiresAt}` }]
7766
- });
7767
- }
7768
- if (this.isSimpleApproval(n)) {
7769
- const approveValue = JSON.stringify({
7770
- executionId: n.executionId,
7771
- stepKey: n.stepKey,
7772
- approved: true
7773
- });
7774
- const rejectValue = JSON.stringify({
7775
- executionId: n.executionId,
7776
- stepKey: n.stepKey,
7777
- approved: false
7778
- });
7779
- blocks.push({
7780
- type: "actions",
7781
- elements: [
7782
- {
7783
- type: "button",
7784
- action_id: "polos_approve",
7785
- text: { type: "plain_text", text: "Approve" },
7786
- style: "primary",
7787
- value: approveValue
7788
- },
7789
- {
7790
- type: "button",
7791
- action_id: "polos_reject",
7792
- text: { type: "plain_text", text: "Reject" },
7793
- style: "danger",
7794
- value: rejectValue
7795
- },
7796
- {
7797
- type: "button",
7798
- text: { type: "plain_text", text: "View Details" },
7799
- url: n.approvalUrl
7800
- }
7801
- ]
7802
- });
7803
- } else {
7804
- blocks.push({
7805
- type: "actions",
7806
- elements: [
7807
- {
7808
- type: "button",
7809
- text: { type: "plain_text", text: "Respond" },
7810
- url: n.approvalUrl,
7811
- style: "primary"
7812
- }
7813
- ]
7814
- });
7815
- }
7816
- return blocks;
7817
- }
7818
- isSimpleApproval(n) {
7819
- const fields = n.formFields;
7820
- if (!fields || fields.length === 0) return false;
7821
- return fields.some((f) => f["key"] === "approved" && f["type"] === "boolean");
7822
- }
7823
- };
7824
-
7825
7926
  export { AgentRunConfig, DockerEnvironment, DuplicateWorkflowError, ExecutionHandle, GuardrailError, GuardrailResult2 as GuardrailResult, HookExecutionError, HookResult, LLM, ManagedSandbox, GuardrailResult as MiddlewareGuardrailResult, OrchestratorApiError, OrchestratorClient, Polos, PolosClient, Queue, SandboxManager, SlackChannel, StateSizeError, StateValidationError, StepExecutionError, StreamResult, WaitError, Worker, WorkerServer, WorkflowNotFoundError, agentStreamFunction, assertSafePath, batchAgentInvoke, batchInvoke, buildSummaryMessages, compactIfNeeded, composeGuardrails, composeHooks, conditionalHook, configureLogging, convertFinishReason, convertMiddlewareToolCallToPython, convertPythonToolCallToMiddleware, convertToolResultsToMessages, convertToolsToVercel, convertVercelToolCallToPython, convertVercelUsageToPython, createAskUserTool, createEditTool, createExecTool, createGlobTool, createGrepTool, createLogger, createReadTool, createStepHelper, createStepStore, createWebSearchTool, createWorkflowRegistry, createWriteTool, defineAgent, defineGuardrail, defineHook, defineTool, defineWorkflow, estimateMessageTokens, estimateMessagesTokens, estimateTokens, evaluateAllowlist, executeGuardrailChain, executeGuardrailsOrThrow, executeHookChain, executeHooksOrThrow, executeWorkflow, executedTool, extractTraceparent, generateTraceIdFromExecutionId, getTracer, globalRegistry, hasText, initializeOtel, initializeState, isAgentWorkflow, isBinary, isGuardrail, isHook, isOtelAvailable, isToolWorkflow, isWaitError, llmGenerate, llmStream, maxSteps, maxTokens, normalizeGuardrail, normalizeGuardrails, normalizeHook, normalizeHooks, parseGrepOutput, retry, sandboxTools, serializeFinalState, sleep, stopCondition, stripAnsi, truncateOutput, validateState };
7826
7927
  //# sourceMappingURL=index.js.map
7827
7928
  //# sourceMappingURL=index.js.map