langchain_agentx_stream_ui 0.2.2 → 0.2.5

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.
@@ -10,4 +10,4 @@ function truncatePreview(text, maxChars = 120) {
10
10
  export {
11
11
  truncatePreview
12
12
  };
13
- //# sourceMappingURL=chunk-6Z4ZF36Z.js.map
13
+ //# sourceMappingURL=chunk-DP7V33X7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/view/tools/presentation/textHelpers.ts"],"sourcesContent":["/**\n * textHelpers.ts — 标题预览截断\n *\n * 对齐参考:CLI widgets/tools/helpers.py truncate_preview\n */\nexport function truncatePreview(text: string, maxChars = 120): string {\n const line = (text || '').trim().split('\\n', 1)[0] ?? '';\n if (line.length > maxChars) {\n return `${line.slice(0, maxChars - 1)}…`;\n }\n return line;\n}\n"],"mappings":";AAKO,SAAS,gBAAgB,MAAc,WAAW,KAAa;AACpE,QAAM,QAAQ,QAAQ,IAAI,KAAK,EAAE,MAAM,MAAM,CAAC,EAAE,CAAC,KAAK;AACtD,MAAI,KAAK,SAAS,UAAU;AAC1B,WAAO,GAAG,KAAK,MAAM,GAAG,WAAW,CAAC,CAAC;AAAA,EACvC;AACA,SAAO;AACT;","names":[]}
package/dist/index.d.ts CHANGED
@@ -955,6 +955,67 @@ declare class MissingApplicationKindError extends Error {
955
955
  constructor();
956
956
  }
957
957
 
958
+ /**
959
+ * 职责:SSE transport profile / policy 解析与终态、重连预算语义(D31 P1)。
960
+ * 链路位置:createAgentxSseSource 入口 → resolveSseTransportPolicy → 连接状态机。
961
+ * 当前裁剪范围:三预设 profile + 显式 policy 覆写;不含 backend replayMode。
962
+ */
963
+
964
+ type SseTransportProfile = 'oneshot' | 'oneshot-workflow' | 'replayable-workflow';
965
+ type SseReplayMode = 'none' | 'resume' | 'history';
966
+ type SseReconnectMode = 'off' | 'bounded' | 'unbounded';
967
+ interface SseReconnectPolicy {
968
+ mode: SseReconnectMode;
969
+ maxReconnects: number;
970
+ reconnectTimeoutMs: number;
971
+ reconnectDelayMs: number;
972
+ }
973
+ interface SseTerminalPolicy {
974
+ primary: readonly string[];
975
+ allowFinishFallback: boolean;
976
+ }
977
+ interface SseTransportPolicy {
978
+ profile?: SseTransportProfile;
979
+ replay: SseReplayMode;
980
+ reconnect: SseReconnectPolicy;
981
+ terminal: SseTerminalPolicy;
982
+ }
983
+ interface SseTransportPolicyOverride {
984
+ replay?: SseReplayMode;
985
+ reconnect?: Partial<SseReconnectPolicy>;
986
+ terminal?: Partial<SseTerminalPolicy>;
987
+ }
988
+ interface ResolveSseTransportPolicyInput {
989
+ profile?: SseTransportProfile;
990
+ policy?: SseTransportPolicyOverride;
991
+ /** @deprecated 使用 profile 或 policy.reconnect */
992
+ autoReconnect?: boolean;
993
+ /** @deprecated 使用 policy.reconnect.reconnectDelayMs */
994
+ reconnectDelayMs?: number;
995
+ expectedApplicationKind?: ApplicationKind;
996
+ }
997
+ declare const BOUNDED_DEFAULTS: {
998
+ readonly maxReconnects: 5;
999
+ readonly reconnectTimeoutMs: 60000;
1000
+ readonly reconnectDelayMs: 1000;
1001
+ };
1002
+ declare const PROFILE_PRESETS: Record<SseTransportProfile, SseTransportPolicy>;
1003
+ /** 将 profile / policy / 旧 autoReconnect 选项解析为完整 transport 策略。 */
1004
+ declare function resolveSseTransportPolicy(input: ResolveSseTransportPolicyInput): SseTransportPolicy;
1005
+ /** 判断 agentx 帧是否为传输层终态(触发 benign close / 停止重连)。 */
1006
+ declare function isSseStreamTerminalEvent(agentEvent: LangchainAgentEvent, terminal: SseTerminalPolicy, expectedApplicationKind?: ApplicationKind): boolean;
1007
+ /** bounded reconnect 预算:次数 + 总时长双门禁。 */
1008
+ declare class ReconnectBudget {
1009
+ private readonly maxReconnects;
1010
+ private readonly timeoutMs;
1011
+ private readonly startedAtMs;
1012
+ private attemptCount;
1013
+ constructor(maxReconnects: number, timeoutMs: number, startedAtMs?: number);
1014
+ get attempts(): number;
1015
+ canRetry(nowMs?: number): boolean;
1016
+ recordAttempt(): void;
1017
+ }
1018
+
958
1019
  /**
959
1020
  * 职责:浏览器 EventSource 封装,解码 meta/agentx 命名帧并校验协议版本。
960
1021
  * 链路位置:业务页面 createAgentxSseSource({ url }) → AgentSession source prop。
@@ -967,14 +1028,24 @@ declare class MissingApplicationKindError extends Error {
967
1028
 
968
1029
  declare const EXPECTED_PROTOCOL_VERSION = "1";
969
1030
  /** 传输层 terminal 失败(须排查/fix);与 agentx error 帧(业务错误)分离。 */
970
- type SseTransportFailureKind = 'handshake_failed' | 'premature_close';
1031
+ type SseTransportFailureKind = 'handshake_failed' | 'premature_close' | 'reconnect_budget_exhausted';
971
1032
  declare class SseTransportTerminalError extends Error {
972
1033
  readonly kind: SseTransportFailureKind;
973
1034
  constructor(kind: SseTransportFailureKind, message: string);
974
1035
  }
975
1036
  interface AgentxSseSourceOptions {
976
1037
  url: string;
1038
+ /** D31:预设 transport 策略(ask / 短 workflow / 可回放 workflow) */
1039
+ profile?: SseTransportProfile;
1040
+ /** D31:在 profile 基础上显式覆写策略字段 */
1041
+ policy?: SseTransportPolicyOverride;
1042
+ /**
1043
+ * @deprecated 使用 profile 或 policy.reconnect;未指定 profile 时仍生效
1044
+ */
977
1045
  autoReconnect?: boolean;
1046
+ /**
1047
+ * @deprecated 使用 policy.reconnect.reconnectDelayMs
1048
+ */
978
1049
  reconnectDelayMs?: number;
979
1050
  /** 每收到 agentx 帧 SSE id 时回调(含续传重叠 id) */
980
1051
  onLastEventId?: (id: string) => void;
@@ -989,6 +1060,7 @@ interface AgentxMetaFrame {
989
1060
  started_at?: number;
990
1061
  application_kind?: ApplicationKind;
991
1062
  }
1063
+ /** 手动重连时追加 resume 查询参数(EventSource 无法设 Last-Event-ID 请求头)。 */
992
1064
  declare function buildResumeStreamUrl(baseUrl: string, lastEventId: string | null | undefined, queryParam?: string): string;
993
1065
  declare function createAgentxSseSource(options: AgentxSseSourceOptions): Source;
994
1066
  /** 测试/Story 用:内存事件源 */
@@ -1130,4 +1202,4 @@ interface ClassifyContext {
1130
1202
  declare function resolveEventTier(eventType: string, overrides?: TierOverrides): EventTier;
1131
1203
  declare function classifyEvent(event: LangchainAgentEvent, ctx: ClassifyContext, overrides?: TierOverrides, eventIndex?: number): ClassifiedEvent;
1132
1204
 
1133
- export { Agent, AgentLoopView, type AgentLoopViewProps, AgentSession, type AgentSessionProps, type AgentxMetaFrame, type AgentxSseSourceOptions, type ApplicationKind, ApplicationKindMismatchError, AskUserQuestion, Bash, CanonicalNodeRef, type ClassifiedEvent, type ClassifyContext, CollapseKind, CollapsedExploreNode, type CollapsedExploreNodeProps, DEFAULT_WORKFLOW_SCALE_OPTIONS, type DiagramFitLayout, DiagramZoomShell, type DiagramZoomShellProps, DiagramZoomView, type DiagramZoomViewProps, DisplayMode, EXPECTED_PROTOCOL_VERSION, Edit, ErrorCard, EventTier, ExploreCollapseAccumulator, GROUPABLE_TOOL_NAMES, Glob, Grep, GroupedToolUseAccumulator, type HydrateLoopSessionAsyncOptions, InteractionBus, LangchainAgentEvent, MIN_HINT_DISPLAY_MS, MarkdownRenderer, MermaidDiagram, type MermaidDiagramProps, type MermaidInitOptions, type MermaidThemeName, MissingApplicationKindError, NodeRegistry, PermissionCard, PermissionUiMode, PlantUMLBlock, type PlantUMLBlockProps, PlantUMLDiagram, type PlantUMLDiagramProps, type ProjectedTimelineItem, ProjectionContext, DisplayMode as ProjectionDisplayMode, Read, ReasoningBubble, type ReduceOptions, ReducerError, RenderableEntry, RenderableTimelineProjector, type ReplayOptions, type ReplaySourceOptions, RichMarkdown, type RichMarkdownProps, SHELL_PROGRESS_MIN_ELAPSED_SECONDS, SessionNode, SessionNodeKind, SessionStatus, SessionTree, Skill, Source, SourceEventContext, Spinner, type SpinnerProps, type SseTransportFailureKind, SseTransportTerminalError, StepCard, SubAgentBlock, SystemSummaryAccumulator, SystemSummaryNode, Task, TaskList, TaskListFooter, TextBubble, TierOverrides, Timeline, TimelineItem, ToolBodyMode, ToolCallCard, ToolDisplayRegistry, ToolProjectionClassifier, UnknownCard, WORKFLOW_STRUCTURE_EVENT_PREFIXES, WORKFLOW_STRUCTURE_EVENT_TYPES, WebFetch, WebSearch, WorkflowChrome, type WorkflowChromeProps, type WorkflowLoopReplayHandler, WorkflowLoopReplayProvider, type WorkflowProgressState, WorkflowScaleContext, type WorkflowScaleOptions, type WorkflowScopeFrame, WorkflowSession, type WorkflowSessionProps, type WorkflowSessionState, type WorkflowSessionStore, type WorkflowSessionStoreOptions, type WorkflowSessionStoreState, type WorkflowStageProgress, WorkflowTaskListFooter, Write, buildCanonicalFromTree, buildRelevantMemoriesCanonical, buildResumeStreamUrl, buildSystemEventCanonical, buildTimelineEntries, classifyEvent, commandAsHint, computeViewportFitTransform, configureMermaid, configurePlantumlServer, createAgentxSseSource, createDefaultRegistry, createEmptyWorkflowSessionState, createMockSource, createReplaySource, createWorkflowSessionStore, deriveLoopSessionIdFromAgentEvent, entryKey, filterAgentLoopReplayEvents, fixDiagramSvg, formatAgentTitle, formatExploreSummaryText, formatHookFinishedSummary, formatShellProgressSuffix, formatTaskFooterLabel, getChildIds, getMainStageIds, isAgentLoopReplayEventType, isGitOperationCommand, isGroupableToolName, isMcpToolName, isWorkflowStructureEventType, iterMountCandidates, partitionWorkflowStages, projectCanonical, projectTimeline, reduceAgentLoopEvent, reduceEvents, reduceTree, reduceWorkflowEvents, reduceWorkflowSession, replayEvents, replayTree, resolveEventTier, resolveResponseId, resolveShellProgressFromPayload, shouldShowTaskListFooter, streamChunk, useChildren, useInteractionBus, useInternalErrors, useMinDisplayTime, useNode, useNodeTyped, useProjectedTimeline, useReplayTree, useSessionMeta, useSessionStatus, useTimeline, useWorkflowSessionStatus, useWorkflowSessionStoreApi };
1205
+ export { Agent, AgentLoopView, type AgentLoopViewProps, AgentSession, type AgentSessionProps, type AgentxMetaFrame, type AgentxSseSourceOptions, type ApplicationKind, ApplicationKindMismatchError, AskUserQuestion, BOUNDED_DEFAULTS, Bash, CanonicalNodeRef, type ClassifiedEvent, type ClassifyContext, CollapseKind, CollapsedExploreNode, type CollapsedExploreNodeProps, DEFAULT_WORKFLOW_SCALE_OPTIONS, type DiagramFitLayout, DiagramZoomShell, type DiagramZoomShellProps, DiagramZoomView, type DiagramZoomViewProps, DisplayMode, EXPECTED_PROTOCOL_VERSION, Edit, ErrorCard, EventTier, ExploreCollapseAccumulator, GROUPABLE_TOOL_NAMES, Glob, Grep, GroupedToolUseAccumulator, type HydrateLoopSessionAsyncOptions, InteractionBus, LangchainAgentEvent, MIN_HINT_DISPLAY_MS, MarkdownRenderer, MermaidDiagram, type MermaidDiagramProps, type MermaidInitOptions, type MermaidThemeName, MissingApplicationKindError, NodeRegistry, PROFILE_PRESETS, PermissionCard, PermissionUiMode, PlantUMLBlock, type PlantUMLBlockProps, PlantUMLDiagram, type PlantUMLDiagramProps, type ProjectedTimelineItem, ProjectionContext, DisplayMode as ProjectionDisplayMode, Read, ReasoningBubble, ReconnectBudget, type ReduceOptions, ReducerError, RenderableEntry, RenderableTimelineProjector, type ReplayOptions, type ReplaySourceOptions, RichMarkdown, type RichMarkdownProps, SHELL_PROGRESS_MIN_ELAPSED_SECONDS, SessionNode, SessionNodeKind, SessionStatus, SessionTree, Skill, Source, SourceEventContext, Spinner, type SpinnerProps, type SseReconnectMode, type SseReconnectPolicy, type SseReplayMode, type SseTerminalPolicy, type SseTransportFailureKind, type SseTransportPolicy, type SseTransportPolicyOverride, type SseTransportProfile, SseTransportTerminalError, StepCard, SubAgentBlock, SystemSummaryAccumulator, SystemSummaryNode, Task, TaskList, TaskListFooter, TextBubble, TierOverrides, Timeline, TimelineItem, ToolBodyMode, ToolCallCard, ToolDisplayRegistry, ToolProjectionClassifier, UnknownCard, WORKFLOW_STRUCTURE_EVENT_PREFIXES, WORKFLOW_STRUCTURE_EVENT_TYPES, WebFetch, WebSearch, WorkflowChrome, type WorkflowChromeProps, type WorkflowLoopReplayHandler, WorkflowLoopReplayProvider, type WorkflowProgressState, WorkflowScaleContext, type WorkflowScaleOptions, type WorkflowScopeFrame, WorkflowSession, type WorkflowSessionProps, type WorkflowSessionState, type WorkflowSessionStore, type WorkflowSessionStoreOptions, type WorkflowSessionStoreState, type WorkflowStageProgress, WorkflowTaskListFooter, Write, buildCanonicalFromTree, buildRelevantMemoriesCanonical, buildResumeStreamUrl, buildSystemEventCanonical, buildTimelineEntries, classifyEvent, commandAsHint, computeViewportFitTransform, configureMermaid, configurePlantumlServer, createAgentxSseSource, createDefaultRegistry, createEmptyWorkflowSessionState, createMockSource, createReplaySource, createWorkflowSessionStore, deriveLoopSessionIdFromAgentEvent, entryKey, filterAgentLoopReplayEvents, fixDiagramSvg, formatAgentTitle, formatExploreSummaryText, formatHookFinishedSummary, formatShellProgressSuffix, formatTaskFooterLabel, getChildIds, getMainStageIds, isAgentLoopReplayEventType, isGitOperationCommand, isGroupableToolName, isMcpToolName, isSseStreamTerminalEvent, isWorkflowStructureEventType, iterMountCandidates, partitionWorkflowStages, projectCanonical, projectTimeline, reduceAgentLoopEvent, reduceEvents, reduceTree, reduceWorkflowEvents, reduceWorkflowSession, replayEvents, replayTree, resolveEventTier, resolveResponseId, resolveShellProgressFromPayload, resolveSseTransportPolicy, shouldShowTaskListFooter, streamChunk, useChildren, useInteractionBus, useInternalErrors, useMinDisplayTime, useNode, useNodeTyped, useProjectedTimeline, useReplayTree, useSessionMeta, useSessionStatus, useTimeline, useWorkflowSessionStatus, useWorkflowSessionStoreApi };
package/dist/index.js CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  fixDiagramSvg,
24
24
  markEventIdSeen,
25
25
  shouldSkipDuplicateEvent
26
- } from "./chunk-DGC43A5L.js";
26
+ } from "./chunk-AVSPJ252.js";
27
27
  import {
28
28
  DefaultToolBody,
29
29
  InteractionBusContext,
@@ -32,8 +32,8 @@ import {
32
32
  getNoopInteractionBus,
33
33
  resolveToolBody,
34
34
  useInteractionBus
35
- } from "./chunk-T626YBJX.js";
36
- import "./chunk-6Z4ZF36Z.js";
35
+ } from "./chunk-6DYISADG.js";
36
+ import "./chunk-DP7V33X7.js";
37
37
  import {
38
38
  CollapseKind,
39
39
  CollapsedExploreNode,
@@ -111,7 +111,7 @@ import {
111
111
  useSessionStatus,
112
112
  useSessionViewOptions,
113
113
  useTimeline
114
- } from "./chunk-OFXC2GZI.js";
114
+ } from "./chunk-D4BG3I7P.js";
115
115
  import {
116
116
  Agent,
117
117
  AgentToolBody,
@@ -138,7 +138,7 @@ import {
138
138
  WriteToolBody,
139
139
  createDefaultToolRegistry,
140
140
  formatAgentTitle
141
- } from "./chunk-YUZXTGJJ.js";
141
+ } from "./chunk-7CLAU74Y.js";
142
142
  import {
143
143
  BodyBlockList,
144
144
  DiffView,
@@ -154,7 +154,7 @@ import {
154
154
  formatTimeoutFooter,
155
155
  parseDiffText,
156
156
  truncateCommand
157
- } from "./chunk-GBY5DJ7L.js";
157
+ } from "./chunk-4RIOBLGB.js";
158
158
 
159
159
  // src/view/AgentSession.tsx
160
160
  import { useEffect as useEffect2, useMemo, useRef as useRef2 } from "react";
@@ -257,6 +257,163 @@ var MissingApplicationKindError = class extends Error {
257
257
  }
258
258
  };
259
259
 
260
+ // src/transport/sseTransportPolicy.ts
261
+ var BOUNDED_DEFAULTS = {
262
+ maxReconnects: 5,
263
+ reconnectTimeoutMs: 6e4,
264
+ reconnectDelayMs: 1e3
265
+ };
266
+ var AGENT_TERMINAL = {
267
+ primary: ["finish"],
268
+ allowFinishFallback: false
269
+ };
270
+ var WORKFLOW_TERMINAL_STRICT = {
271
+ primary: ["workflow-end", "workflow-failed"],
272
+ allowFinishFallback: false
273
+ };
274
+ var WORKFLOW_TERMINAL_WITH_FALLBACK = {
275
+ primary: ["workflow-end", "workflow-failed"],
276
+ allowFinishFallback: true
277
+ };
278
+ var PROFILE_PRESETS = {
279
+ oneshot: {
280
+ profile: "oneshot",
281
+ replay: "none",
282
+ reconnect: {
283
+ mode: "off",
284
+ maxReconnects: 0,
285
+ reconnectTimeoutMs: 0,
286
+ reconnectDelayMs: BOUNDED_DEFAULTS.reconnectDelayMs
287
+ },
288
+ terminal: AGENT_TERMINAL
289
+ },
290
+ "oneshot-workflow": {
291
+ profile: "oneshot-workflow",
292
+ replay: "none",
293
+ reconnect: {
294
+ mode: "off",
295
+ maxReconnects: 0,
296
+ reconnectTimeoutMs: 0,
297
+ reconnectDelayMs: BOUNDED_DEFAULTS.reconnectDelayMs
298
+ },
299
+ terminal: WORKFLOW_TERMINAL_WITH_FALLBACK
300
+ },
301
+ "replayable-workflow": {
302
+ profile: "replayable-workflow",
303
+ replay: "history",
304
+ reconnect: {
305
+ mode: "bounded",
306
+ ...BOUNDED_DEFAULTS
307
+ },
308
+ terminal: WORKFLOW_TERMINAL_WITH_FALLBACK
309
+ }
310
+ };
311
+ function legacyTerminal(expectedApplicationKind) {
312
+ if (expectedApplicationKind === "workflow") {
313
+ return WORKFLOW_TERMINAL_STRICT;
314
+ }
315
+ return AGENT_TERMINAL;
316
+ }
317
+ function legacyReconnect(autoReconnect, reconnectDelayMs) {
318
+ if (autoReconnect === false) {
319
+ return {
320
+ mode: "off",
321
+ maxReconnects: 0,
322
+ reconnectTimeoutMs: 0,
323
+ reconnectDelayMs: reconnectDelayMs ?? BOUNDED_DEFAULTS.reconnectDelayMs
324
+ };
325
+ }
326
+ return {
327
+ mode: "unbounded",
328
+ maxReconnects: Number.POSITIVE_INFINITY,
329
+ reconnectTimeoutMs: Number.POSITIVE_INFINITY,
330
+ reconnectDelayMs: reconnectDelayMs ?? BOUNDED_DEFAULTS.reconnectDelayMs
331
+ };
332
+ }
333
+ function mergePolicy(base, override) {
334
+ if (!override) return base;
335
+ return {
336
+ profile: base.profile,
337
+ replay: override.replay ?? base.replay,
338
+ reconnect: {
339
+ ...base.reconnect,
340
+ ...override.reconnect
341
+ },
342
+ terminal: {
343
+ primary: override.terminal?.primary ?? base.terminal.primary,
344
+ allowFinishFallback: override.terminal?.allowFinishFallback ?? base.terminal.allowFinishFallback
345
+ }
346
+ };
347
+ }
348
+ function resolveSseTransportPolicy(input) {
349
+ const {
350
+ profile,
351
+ policy: policyOverride,
352
+ autoReconnect,
353
+ reconnectDelayMs,
354
+ expectedApplicationKind
355
+ } = input;
356
+ let base;
357
+ if (profile) {
358
+ base = { ...PROFILE_PRESETS[profile] };
359
+ } else {
360
+ base = {
361
+ replay: "history",
362
+ reconnect: legacyReconnect(autoReconnect, reconnectDelayMs),
363
+ terminal: legacyTerminal(expectedApplicationKind)
364
+ };
365
+ }
366
+ return mergePolicy(base, policyOverride);
367
+ }
368
+ function isSseStreamTerminalEvent(agentEvent, terminal, expectedApplicationKind) {
369
+ const eventType = agentEvent.event_type;
370
+ if (eventType === "error") return true;
371
+ if (terminal.primary.includes(eventType)) return true;
372
+ if (terminal.allowFinishFallback && eventType === "finish" && expectedApplicationKind === "workflow") {
373
+ return true;
374
+ }
375
+ if (!profileUsesWorkflowTerminal(terminal) && expectedApplicationKind !== "workflow" && eventType === "finish") {
376
+ return true;
377
+ }
378
+ return false;
379
+ }
380
+ function profileUsesWorkflowTerminal(terminal) {
381
+ return terminal.primary.includes("workflow-end") || terminal.primary.includes("workflow-failed");
382
+ }
383
+ var ReconnectBudget = class {
384
+ constructor(maxReconnects, timeoutMs, startedAtMs = Date.now()) {
385
+ this.maxReconnects = maxReconnects;
386
+ this.timeoutMs = timeoutMs;
387
+ this.startedAtMs = startedAtMs;
388
+ }
389
+ maxReconnects;
390
+ timeoutMs;
391
+ startedAtMs;
392
+ attemptCount = 0;
393
+ get attempts() {
394
+ return this.attemptCount;
395
+ }
396
+ canRetry(nowMs = Date.now()) {
397
+ if (this.maxReconnects <= 0) return false;
398
+ if (!Number.isFinite(this.maxReconnects) && !Number.isFinite(this.timeoutMs)) {
399
+ return true;
400
+ }
401
+ if (Number.isFinite(this.maxReconnects) && this.attemptCount >= this.maxReconnects) {
402
+ return false;
403
+ }
404
+ if (Number.isFinite(this.timeoutMs) && nowMs - this.startedAtMs > this.timeoutMs) {
405
+ return false;
406
+ }
407
+ return true;
408
+ }
409
+ recordAttempt() {
410
+ this.attemptCount += 1;
411
+ }
412
+ };
413
+ function shouldAutoReconnect(reconnect) {
414
+ return reconnect.mode !== "off";
415
+ }
416
+
260
417
  // src/transport/createAgentxSseSource.ts
261
418
  var EXPECTED_PROTOCOL_VERSION = "1";
262
419
  var SseTransportTerminalError = class extends Error {
@@ -275,14 +432,6 @@ function transportLog(message, level = "warn") {
275
432
  console.warn(line);
276
433
  }
277
434
  }
278
- function isSseStreamTerminalEvent(agentEvent, expectedApplicationKind) {
279
- const eventType = agentEvent.event_type;
280
- if (eventType === "error") return true;
281
- if (expectedApplicationKind === "workflow") {
282
- return eventType === "workflow-end" || eventType === "workflow-failed";
283
- }
284
- return eventType === "finish";
285
- }
286
435
  function buildResumeStreamUrl(baseUrl, lastEventId, queryParam = "last_event_id") {
287
436
  if (!lastEventId) return baseUrl;
288
437
  const sep = baseUrl.includes("?") ? "&" : "?";
@@ -291,12 +440,26 @@ function buildResumeStreamUrl(baseUrl, lastEventId, queryParam = "last_event_id"
291
440
  function createAgentxSseSource(options) {
292
441
  const {
293
442
  url,
294
- autoReconnect = true,
295
- reconnectDelayMs = 1e3,
443
+ profile,
444
+ policy: policyOverride,
445
+ autoReconnect,
446
+ reconnectDelayMs,
296
447
  onLastEventId,
297
448
  EventSourceImpl = EventSource,
298
449
  expectedApplicationKind
299
450
  } = options;
451
+ const transportPolicy = resolveSseTransportPolicy({
452
+ profile,
453
+ policy: policyOverride,
454
+ autoReconnect,
455
+ reconnectDelayMs,
456
+ expectedApplicationKind
457
+ });
458
+ const reconnectDelay = transportPolicy.reconnect.reconnectDelayMs;
459
+ const reconnectBudget = transportPolicy.reconnect.mode === "bounded" ? new ReconnectBudget(
460
+ transportPolicy.reconnect.maxReconnects,
461
+ transportPolicy.reconnect.reconnectTimeoutMs
462
+ ) : null;
300
463
  return {
301
464
  start(handler, signal) {
302
465
  return new Promise((resolve, reject) => {
@@ -428,7 +591,11 @@ function createAgentxSseSource(options) {
428
591
  } else {
429
592
  flushBufferedDelta();
430
593
  handler(agentEvent, ctx);
431
- if (isSseStreamTerminalEvent(agentEvent, expectedApplicationKind)) {
594
+ if (isSseStreamTerminalEvent(
595
+ agentEvent,
596
+ transportPolicy.terminal,
597
+ expectedApplicationKind
598
+ )) {
432
599
  streamTerminal = true;
433
600
  }
434
601
  }
@@ -454,9 +621,22 @@ function createAgentxSseSource(options) {
454
621
  finish(error);
455
622
  return;
456
623
  }
457
- if (autoReconnect) {
624
+ if (shouldAutoReconnect(transportPolicy.reconnect)) {
625
+ if (transportPolicy.reconnect.mode === "bounded" && reconnectBudget && !reconnectBudget.canRetry()) {
626
+ const error = new SseTransportTerminalError(
627
+ "reconnect_budget_exhausted",
628
+ "SSE reconnect budget exhausted"
629
+ );
630
+ transportLog(error.message, "error");
631
+ cleanup();
632
+ finish(error);
633
+ return;
634
+ }
635
+ if (reconnectBudget) {
636
+ reconnectBudget.recordAttempt();
637
+ }
458
638
  cleanup();
459
- setTimeout(() => connect(lastEventId), reconnectDelayMs);
639
+ setTimeout(() => connect(lastEventId), reconnectDelay);
460
640
  return;
461
641
  }
462
642
  failPrematureClose();
@@ -1837,6 +2017,9 @@ function resolveParallelItemLoopSessionId(eventType, eventSessionId, derivedLoop
1837
2017
  if (itemKey && parsed?.taskKey === itemKey) {
1838
2018
  return eventSessionId;
1839
2019
  }
2020
+ if (itemKey && eventSessionId.endsWith(`-${itemKey}`)) {
2021
+ return eventSessionId;
2022
+ }
1840
2023
  return null;
1841
2024
  }
1842
2025
  function resolveStructureOpenLoopSessionId(eventType, eventSessionId, derivedLoopSessionId, data) {
@@ -3426,11 +3609,12 @@ function WorkflowStageContainerInner({
3426
3609
  }
3427
3610
  }, [shouldAutoExpandRunning, effectivelyDone, isSkipped]);
3428
3611
  const requestLoopHydration = useCallback2(() => {
3612
+ if (suppressHostScopedLoop) return;
3429
3613
  const loopSessionId = node.loopSessionId;
3430
3614
  if (!loopSessionId || loopTree) return;
3431
3615
  pinLoopSession(loopSessionId);
3432
3616
  void replayHandler?.(loopSessionId);
3433
- }, [node.loopSessionId, loopTree, pinLoopSession, replayHandler]);
3617
+ }, [suppressHostScopedLoop, node.loopSessionId, loopTree, pinLoopSession, replayHandler]);
3434
3618
  const toggleExpanded = useCallback2(() => {
3435
3619
  setExpanded((prev) => {
3436
3620
  const next = !prev;
@@ -3546,7 +3730,7 @@ function WorkflowStageContainerInner({
3546
3730
  groupParallelTools,
3547
3731
  bodyClassName: isItem ? "lax-workflow-parallel-item__body lax-workflow-stage-container__body" : "lax-workflow-stage-container__body"
3548
3732
  }
3549
- ) : /* @__PURE__ */ jsxs5(
3733
+ ) : suppressHostScopedLoop ? null : /* @__PURE__ */ jsxs5(
3550
3734
  "div",
3551
3735
  {
3552
3736
  className: "lax-workflow-stage-container__body lax-workflow-loop-replay-pending",
@@ -4542,6 +4726,7 @@ export {
4542
4726
  ApplicationKindMismatchError,
4543
4727
  AskUserQuestion,
4544
4728
  AskUserQuestionToolBody,
4729
+ BOUNDED_DEFAULTS,
4545
4730
  Bash,
4546
4731
  BashToolBody,
4547
4732
  BodyBlockList,
@@ -4574,6 +4759,7 @@ export {
4574
4759
  MissingApplicationKindError,
4575
4760
  MultiAgentSession,
4576
4761
  NodeRegistry,
4762
+ PROFILE_PRESETS,
4577
4763
  PermissionCard,
4578
4764
  PlantUMLBlock,
4579
4765
  PlantUMLDiagram,
@@ -4581,6 +4767,7 @@ export {
4581
4767
  Read,
4582
4768
  ReadToolBody,
4583
4769
  ReasoningBubble,
4770
+ ReconnectBudget,
4584
4771
  RenderableTimelineProjector,
4585
4772
  RichMarkdown,
4586
4773
  SHELL_PROGRESS_MIN_ELAPSED_SECONDS,
@@ -4665,6 +4852,7 @@ export {
4665
4852
  isGitOperationCommand,
4666
4853
  isGroupableToolName,
4667
4854
  isMcpToolName,
4855
+ isSseStreamTerminalEvent,
4668
4856
  isWorkflowStructureEventType,
4669
4857
  iterMountCandidates,
4670
4858
  parseDiffText,
@@ -4682,6 +4870,7 @@ export {
4682
4870
  resolveEventTier,
4683
4871
  resolveResponseId,
4684
4872
  resolveShellProgressFromPayload,
4873
+ resolveSseTransportPolicy,
4685
4874
  resolveToolBody,
4686
4875
  shouldApplyGrouping,
4687
4876
  shouldShowExploreDetail,