@agent-relay/sdk 6.2.6 → 6.2.8

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.
@@ -23,7 +23,7 @@ import { createLocalJwksKeyPair, importPrivateKeyPem, RELAYAUTH_JWT_KID_ENV, REL
23
23
  import { collectCliSession } from './cli-session-collector.js';
24
24
  import { executeApiStep } from './api-executor.js';
25
25
  import { BudgetExceededError, BudgetTracker } from './budget-tracker.js';
26
- import { ChannelMessenger } from './channel-messenger.js';
26
+ import { ChannelMessenger, scrubForChannel as scrubWorkflowOutputForChannel } from './channel-messenger.js';
27
27
  import { InMemoryWorkflowDb } from './memory-db.js';
28
28
  import { buildCommand as buildProcessCommand, spawnProcess } from './process-spawner.js';
29
29
  import { createProcessBackendExecutor } from './process-backend-executor.js';
@@ -1500,7 +1500,7 @@ export class WorkflowRunner {
1500
1500
  (existing ? DEFAULT_WORKFLOW_MAX_RETRIES : DEFAULT_WORKFLOW_MAX_RETRIES);
1501
1501
  const repairRetries = existing?.repairRetries ??
1502
1502
  (hasRepairAgentCandidate
1503
- ? existing?.maxRetries ?? DEFAULT_WORKFLOW_REPAIR_RETRIES
1503
+ ? (existing?.maxRetries ?? DEFAULT_WORKFLOW_REPAIR_RETRIES)
1504
1504
  : existing?.repairRetries);
1505
1505
  return {
1506
1506
  ...config,
@@ -2850,7 +2850,7 @@ export class WorkflowRunner {
2850
2850
  * Fast, reliable, $0 LLM cost.
2851
2851
  */
2852
2852
  async executeDeterministicStep(step, state, stepStates, agentMap, runId, errorHandling, lifecycle) {
2853
- const repairRetries = errorHandling?.strategy === 'retry' ? errorHandling.repairRetries ?? 0 : 0;
2853
+ const repairRetries = errorHandling?.strategy === 'retry' ? (errorHandling.repairRetries ?? 0) : 0;
2854
2854
  const repairAgent = repairRetries > 0
2855
2855
  ? this.resolveWorkflowRepairAgent(step, stepStates, agentMap, errorHandling)
2856
2856
  : undefined;
@@ -5961,100 +5961,7 @@ export class WorkflowRunner {
5961
5961
  * The raw (ANSI-stripped) output is still written to disk for step chaining.
5962
5962
  */
5963
5963
  static scrubForChannel(text) {
5964
- // Strip system-reminder blocks (closed or unclosed)
5965
- const withoutSystemReminders = text
5966
- .replace(/<system-reminder>[\s\S]*?<\/system-reminder>/giu, '')
5967
- .replace(/<system-reminder>[\s\S]*/giu, '');
5968
- // Normalize CRLF and bare \r before stripping ANSI — PTY output often
5969
- // contains \r\r\n which leaves stray \r after stripping that confuse line splitting.
5970
- const normalized = withoutSystemReminders.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
5971
- const ansiStripped = stripAnsiFn(normalized);
5972
- // Unicode spinner / ornament characters used by Claude TUI animations.
5973
- // Includes block-element chars (▗▖▘▝) used in the Claude Code header bar.
5974
- const SPINNER = '\\u2756\\u2738\\u2739\\u273a\\u273b\\u273c\\u273d\\u2731\\u2732\\u2733\\u2734\\u2735\\u2736\\u2737\\u2743\\u2745\\u2746\\u25d6\\u25d7\\u25d8\\u25d9\\u2022\\u25cf\\u25cb\\u25a0\\u25a1\\u25b6\\u25c0\\u23f5\\u23f6\\u23f7\\u23f8\\u23f9\\u25e2\\u25e3\\u25e4\\u25e5\\u2597\\u2596\\u2598\\u259d\\u2bc8\\u2bc7\\u2bc5\\u2bc6\\u00b7' +
5975
- '\\u2590\\u258c\\u2588\\u2584\\u2580\\u259a\\u259e' + // additional block elements
5976
- '\\u2b21\\u2b22'; // hex-hollow ⬡ and hex-filled ⬢ (Cursor "Generating" spinner)
5977
- const spinnerRe = new RegExp(`[${SPINNER}]`, 'gu');
5978
- const spinnerClassRe = new RegExp(`^[\\s${SPINNER}]*$`, 'u');
5979
- // Line-level filters
5980
- const boxDrawingOnlyRe = /^[\s\u2500-\u257f\u2580-\u259f\u25a0-\u25ff\-_=~]{3,}$/u;
5981
- // Broker internal log lines: "2026-02-26T12:45:12.123Z INFO agent_relay_broker::..."
5982
- const brokerLogRe = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z\s+(?:INFO|WARN|ERROR|DEBUG)\s/u;
5983
- const claudeHeaderRe = /^(?:[\s\u2580-\u259f✢*·▗▖▘▝]+\s*)?(?:Claude\s+Code(?:\s+v?[\d.]+)?|(?:Sonnet|Haiku|Opus)\s*[\d.]+|claude-(?:sonnet|haiku|opus)-[\w.-]+|Running\s+on\s+claude)/iu;
5984
- // TUI directory breadcrumb lines (e.g. " ~/Projects/agent-workforce/relay-...")
5985
- const dirBreadcrumbRe = /^\s*~[\\/]/u;
5986
- const uiHintRe = /\b(?:Press\s+up\s+to\s+edit|tab\s+to\s+queue|bypass\s+permissions|esc\s+to\s+interrupt)\b/iu;
5987
- // Any spinner-prefixed word ending in … — catches all Claude thinking animations
5988
- // regardless of the specific word used (Thinking, Cascading, Flibbertigibbeting, etc.)
5989
- const thinkingLineRe = new RegExp(`^[\\s${SPINNER}]*\\s*\\w[\\w\\s]*\\u2026\\s*$`, 'u');
5990
- const cursorOnlyRe = /^[\s❯⎿›»◀▶←→↑↓⟨⟩⟪⟫·]+$/u;
5991
- // Cursor Agent TUI lines: generating animations, pasted text indicators, UI chrome
5992
- const cursorAgentRe = /^(?:Cursor Agent|[\s⬡⬢]*Generating[.\s]|\[Pasted text|Auto-run all|Add a follow-up|ctrl\+c to stop|shift\+tab|Auto$|\/\s*commands|@\s*files|!\s*shell|follow-ups?\s|The user ha)/iu;
5993
- const slashCommandRe = /^\/\w+\s*$/u;
5994
- const mcpJsonKvRe = /^\s*"(?:type|method|params|result|id|jsonrpc|tool|name|arguments|content|role|metadata)"\s*:/u;
5995
- const meaningfulContentRe = /[a-zA-Z0-9]/u;
5996
- const countJsonDepth = (line) => {
5997
- let depth = 0;
5998
- for (const ch of line) {
5999
- if (ch === '{' || ch === '[')
6000
- depth += 1;
6001
- if (ch === '}' || ch === ']')
6002
- depth -= 1;
6003
- }
6004
- return depth;
6005
- };
6006
- const lines = ansiStripped.split('\n');
6007
- const meaningful = [];
6008
- let jsonDepth = 0;
6009
- for (const line of lines) {
6010
- const trimmed = line.trim();
6011
- if (jsonDepth > 0) {
6012
- jsonDepth += countJsonDepth(line);
6013
- if (jsonDepth <= 0)
6014
- jsonDepth = 0;
6015
- continue;
6016
- }
6017
- if (trimmed.length === 0)
6018
- continue;
6019
- if (trimmed.startsWith('{') || /^\[\s*\{/.test(trimmed)) {
6020
- jsonDepth = Math.max(countJsonDepth(line), 0);
6021
- continue;
6022
- }
6023
- if (mcpJsonKvRe.test(line))
6024
- continue;
6025
- if (spinnerClassRe.test(trimmed))
6026
- continue;
6027
- if (boxDrawingOnlyRe.test(trimmed))
6028
- continue;
6029
- if (brokerLogRe.test(trimmed))
6030
- continue;
6031
- if (claudeHeaderRe.test(trimmed))
6032
- continue;
6033
- if (dirBreadcrumbRe.test(trimmed))
6034
- continue;
6035
- if (uiHintRe.test(trimmed))
6036
- continue;
6037
- if (thinkingLineRe.test(trimmed))
6038
- continue;
6039
- if (cursorOnlyRe.test(trimmed))
6040
- continue;
6041
- if (cursorAgentRe.test(trimmed))
6042
- continue;
6043
- if (slashCommandRe.test(trimmed))
6044
- continue;
6045
- if (!meaningfulContentRe.test(trimmed))
6046
- continue;
6047
- // Drop TUI animation frame fragments: lines where stripping spinners and
6048
- // whitespace leaves ≤ 3 alphanumeric characters (e.g. "F", "l b", "i g").
6049
- const alphanum = trimmed.replace(spinnerRe, '').replace(/\s+/g, '');
6050
- if (alphanum.replace(/[^a-zA-Z0-9]/g, '').length <= 3)
6051
- continue;
6052
- meaningful.push(line);
6053
- }
6054
- return meaningful
6055
- .join('\n')
6056
- .replace(/\n{3,}/g, '\n\n')
6057
- .trim();
5964
+ return scrubWorkflowOutputForChannel(text);
6058
5965
  }
6059
5966
  /** Sanitize a workflow name into a valid channel name. */
6060
5967
  sanitizeChannelName(name) {