@agents24/chat-react 0.1.10 → 0.3.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/ui/index.cjs CHANGED
@@ -797,65 +797,6 @@ var import_lucide_react4 = require("lucide-react");
797
797
  var React4 = __toESM(require("react"), 1);
798
798
  var import_lucide_react3 = require("lucide-react");
799
799
 
800
- // src/ui/mcp-connect-required-card.tsx
801
- var import_jsx_runtime5 = require("react/jsx-runtime");
802
- var STATUS_LABELS = {
803
- pending: "Connect",
804
- connecting: "Connecting",
805
- connected: "Connected",
806
- resuming: "Resuming",
807
- error: "Try again"
808
- };
809
- function McpConnectRequiredCard({
810
- serverName,
811
- providerKey,
812
- message,
813
- status = "pending",
814
- disabled = false,
815
- loading = false,
816
- error,
817
- onConnect,
818
- className,
819
- ...props
820
- }) {
821
- const label = String(serverName || providerKey || "MCP server").trim();
822
- const isBusy = loading || status === "connecting" || status === "resuming";
823
- const isConnected = status === "connected";
824
- const buttonDisabled = disabled || isBusy || isConnected || !onConnect;
825
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
826
- "div",
827
- {
828
- "data-agents24-mcp-connect-card": true,
829
- "data-status": status,
830
- className: cn(
831
- "w-full rounded-lg border border-border/50 bg-muted/25 p-3 text-sm text-foreground",
832
- className
833
- ),
834
- ...props,
835
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex min-w-0 items-start justify-between gap-3", children: [
836
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "min-w-0", children: [
837
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "truncate text-sm font-medium", children: label }),
838
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mt-1 text-sm text-muted-foreground", children: message || "Connect your account to continue." }),
839
- status === "error" && error ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mt-2 text-sm text-destructive", children: error }) : null
840
- ] }),
841
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
842
- "button",
843
- {
844
- type: "button",
845
- className: cn(
846
- "shrink-0 rounded-md border px-3 py-1.5 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-60",
847
- status === "pending" || status === "error" ? "border-neutral-900 bg-neutral-900 text-white hover:bg-neutral-800" : "border-border bg-background text-foreground hover:bg-muted"
848
- ),
849
- disabled: buttonDisabled,
850
- onClick: onConnect,
851
- children: STATUS_LABELS[status]
852
- }
853
- )
854
- ] })
855
- }
856
- );
857
- }
858
-
859
800
  // src/ui/message-response.tsx
860
801
  var React3 = __toESM(require("react"), 1);
861
802
  var import_streamdown = require("streamdown");
@@ -990,7 +931,7 @@ function useStreamingText({
990
931
  }
991
932
 
992
933
  // src/ui/message-response.tsx
993
- var import_jsx_runtime6 = require("react/jsx-runtime");
934
+ var import_jsx_runtime5 = require("react/jsx-runtime");
994
935
  var BLOCK_MARKDOWN_TAGS = /* @__PURE__ */ new Set([
995
936
  "blockquote",
996
937
  "div",
@@ -1033,12 +974,12 @@ function MessageMarkdownParagraph({
1033
974
  );
1034
975
  const isImageOnly = childArray.length === 1 && React3.isValidElement(childArray[0]) && childArray[0].props.node?.tagName === "img";
1035
976
  if (isImageOnly) {
1036
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children });
977
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children });
1037
978
  }
1038
979
  if (childArray.some(hasBlockMarkdownChild)) {
1039
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ...domProps, children });
980
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { ...domProps, children });
1040
981
  }
1041
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { ...domProps, children });
982
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { ...domProps, children });
1042
983
  }
1043
984
  var MESSAGE_RESPONSE_COMPONENTS = {
1044
985
  p: MessageMarkdownParagraph
@@ -1084,7 +1025,7 @@ var MessageResponse = React3.memo(
1084
1025
  () => ({ ...MESSAGE_RESPONSE_COMPONENTS, ...components }),
1085
1026
  [components]
1086
1027
  );
1087
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1028
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1088
1029
  import_streamdown.Streamdown,
1089
1030
  {
1090
1031
  className: cn("size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", className),
@@ -1100,9 +1041,7 @@ var MessageResponse = React3.memo(
1100
1041
  MessageResponse.displayName = "MessageResponse";
1101
1042
 
1102
1043
  // src/ui/agent-response-timeline.tsx
1103
- var import_jsx_runtime7 = require("react/jsx-runtime");
1104
- var CONNECT_DECISION = "connect";
1105
- var HITL_DECISIONS = ["approve", "edit", "reject", "respond", "connect"];
1044
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1106
1045
  function asRecord(value) {
1107
1046
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
1108
1047
  }
@@ -1130,7 +1069,7 @@ function isActiveTool(part, activeToolId) {
1130
1069
  return part.id === activeToolId || part.toolCallId === activeToolId || part.state === "input-available" || part.state === "input-streaming";
1131
1070
  }
1132
1071
  function Shimmer({ children, className }) {
1133
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: cn("inline-block animate-pulse", className), children });
1072
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: cn("inline-block animate-pulse", className), children });
1134
1073
  }
1135
1074
  function CompactTask({
1136
1075
  children,
@@ -1142,12 +1081,12 @@ function CompactTask({
1142
1081
  }) {
1143
1082
  const [open, setOpen] = React4.useState(defaultOpen);
1144
1083
  const expandable = Boolean(children || detail);
1145
- const content = loading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shimmer, { children: label }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: label });
1084
+ const content = loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Shimmer, { children: label }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: label });
1146
1085
  if (!expandable) {
1147
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: cn("flex min-w-0 items-center gap-1.5 text-sm", error ? "text-destructive" : "text-muted-foreground"), children: content });
1086
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: cn("flex min-w-0 items-center gap-1.5 text-sm", error ? "text-destructive" : "text-muted-foreground"), children: content });
1148
1087
  }
1149
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "w-full", children: [
1150
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1088
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "w-full", children: [
1089
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1151
1090
  "button",
1152
1091
  {
1153
1092
  "aria-expanded": open,
@@ -1159,12 +1098,12 @@ function CompactTask({
1159
1098
  type: "button",
1160
1099
  children: [
1161
1100
  content,
1162
- open ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react3.ChevronDown, { className: "size-3" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react3.ChevronRight, { className: "size-3 opacity-70" })
1101
+ open ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react3.ChevronDown, { className: "size-3" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react3.ChevronRight, { className: "size-3 opacity-70" })
1163
1102
  ]
1164
1103
  }
1165
1104
  ),
1166
- open ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mt-1 pl-4 text-sm text-muted-foreground", children: [
1167
- detail ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { children: detail }) : null,
1105
+ open ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mt-1 pl-4 text-sm text-muted-foreground", children: [
1106
+ detail ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { children: detail }) : null,
1168
1107
  children
1169
1108
  ] }) : null
1170
1109
  ] });
@@ -1173,7 +1112,7 @@ function ToolPartRow({
1173
1112
  activeToolId,
1174
1113
  part
1175
1114
  }) {
1176
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { "data-agents24-tool-part": part.type, "data-state": part.state, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1115
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { "data-agents24-tool-part": part.type, "data-state": part.state, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1177
1116
  CompactTask,
1178
1117
  {
1179
1118
  defaultOpen: part.state === "output-error",
@@ -1189,40 +1128,23 @@ function ToolGroup({
1189
1128
  parts
1190
1129
  }) {
1191
1130
  const loading = parts.some((part) => isActiveTool(part, activeToolId));
1192
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CompactTask, { label: groupLabel(parts[0]), loading, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "space-y-1", children: parts.map((part) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1131
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CompactTask, { label: groupLabel(parts[0]), loading, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "space-y-1", children: parts.map((part) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1193
1132
  "div",
1194
1133
  {
1195
1134
  className: cn("text-sm", part.state === "output-error" ? "text-destructive" : "text-muted-foreground"),
1196
1135
  children: [
1197
- isActiveTool(part, activeToolId) ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shimmer, { children: toolLabel(part) }) : toolLabel(part),
1198
- toolDetail(part) ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ml-1 text-xs text-muted-foreground/75", children: toolDetail(part) }) : null
1136
+ isActiveTool(part, activeToolId) ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Shimmer, { children: toolLabel(part) }) : toolLabel(part),
1137
+ toolDetail(part) ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "ml-1 text-xs text-muted-foreground/75", children: toolDetail(part) }) : null
1199
1138
  ]
1200
1139
  },
1201
1140
  part.id
1202
1141
  )) }) });
1203
1142
  }
1204
- function collectHitlDecisions(part) {
1205
- const configs = Array.isArray(part.hitl.review_configs) ? part.hitl.review_configs : [];
1206
- const decisions = configs.flatMap((config) => {
1207
- const record = asRecord(config);
1208
- const allowed = Array.isArray(record?.allowed_decisions) ? record?.allowed_decisions : [];
1209
- return allowed.filter((item) => HITL_DECISIONS.includes(String(item)));
1210
- });
1211
- return Array.from(new Set(decisions));
1212
- }
1213
- function isMcpConnectHitl(part) {
1214
- const kind = `${part.hitlKind || optionalString(part.hitl.kind) || ""}`.toLowerCase();
1215
- const decisions = collectHitlDecisions(part);
1216
- return decisions.includes(CONNECT_DECISION) || kind.includes("mcp") || kind.includes("connection");
1217
- }
1218
- function mcpConnectLabel(part) {
1219
- const payload = asRecord(part.hitl.client_safe_payload);
1220
- const origin = asRecord(part.hitl.origin);
1221
- return optionalString(part.hitl.server_name) || optionalString(part.hitl.provider_name) || optionalString(payload?.server_name) || optionalString(payload?.provider_name) || optionalString(origin?.server_name) || optionalString(origin?.provider_name) || "MCP server";
1222
- }
1223
- function normalizedMcpStatus(status) {
1224
- if (status === "connecting" || status === "connected" || status === "resuming" || status === "error") return status;
1225
- return "pending";
1143
+ function actionLabel(part, action) {
1144
+ if (action === "approve") return part.hitlKind === "tool_review" ? "Allow once" : "Approve";
1145
+ if (action === "reject") return part.hitlKind === "tool_review" ? "Don\u2019t allow" : "Reject";
1146
+ if (action === "connect") return "Connect";
1147
+ return "Skip";
1226
1148
  }
1227
1149
  function HitlPartRow({
1228
1150
  getHitlActionState,
@@ -1231,36 +1153,68 @@ function HitlPartRow({
1231
1153
  part
1232
1154
  }) {
1233
1155
  const state = getHitlActionState?.(part);
1234
- const message = optionalString(part.hitl.message) || optionalString(part.hitl.text) || "Input is required to continue.";
1235
- if (isMcpConnectHitl(part)) {
1236
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1237
- McpConnectRequiredCard,
1156
+ const [comment, setComment] = React4.useState("");
1157
+ const presentation = part.presentation || {};
1158
+ const details = asRecord(presentation.sanitized_arguments);
1159
+ const requireComment = presentation.require_comment === true;
1160
+ const isTerminal = part.status !== "pending";
1161
+ if (isTerminal) {
1162
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "rounded-xl border border-border/60 bg-muted/30 px-3 py-2 text-sm text-muted-foreground", children: [
1163
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-medium text-foreground", children: part.resolution?.outcome || part.status }),
1164
+ part.resolution?.reason ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "ml-1", children: [
1165
+ "\xB7 ",
1166
+ part.resolution.reason
1167
+ ] }) : null
1168
+ ] });
1169
+ }
1170
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "space-y-3 rounded-xl border border-amber-500/30 bg-amber-500/5 p-3", children: [
1171
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "space-y-1", children: [
1172
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "text-sm font-semibold text-foreground", children: optionalString(presentation.tool_name) || optionalString(presentation.server_name) || "Action required" }),
1173
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MessageResponse, { children: part.message }),
1174
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
1175
+ optionalString(presentation.source) ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
1176
+ "Source: ",
1177
+ optionalString(presentation.source)
1178
+ ] }) : null,
1179
+ optionalString(presentation.risk) ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
1180
+ "Risk: ",
1181
+ optionalString(presentation.risk)
1182
+ ] }) : null,
1183
+ optionalString(presentation.credential_scope) ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
1184
+ "Credentials: ",
1185
+ optionalString(presentation.credential_scope)
1186
+ ] }) : null
1187
+ ] })
1188
+ ] }),
1189
+ details ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("details", { className: "text-xs text-muted-foreground", children: [
1190
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("summary", { className: "cursor-pointer select-none font-medium", children: "Details" }),
1191
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { className: "mt-2 max-h-48 overflow-auto rounded-lg bg-background/80 p-2 text-[11px]", children: JSON.stringify(details, null, 2) })
1192
+ ] }) : null,
1193
+ requireComment ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1194
+ "textarea",
1238
1195
  {
1239
- error: state?.error,
1240
- message,
1241
- onConnect: onHitlAction ? () => onHitlAction(part, CONNECT_DECISION) : void 0,
1242
- serverName: mcpConnectLabel(part),
1243
- status: normalizedMcpStatus(state?.status)
1196
+ "aria-label": "Approval comment",
1197
+ className: "min-h-20 w-full resize-y rounded-lg border border-border bg-background px-3 py-2 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring",
1198
+ onChange: (event) => setComment(event.target.value),
1199
+ placeholder: "Comment required",
1200
+ value: comment
1244
1201
  }
1245
- );
1246
- }
1247
- const decisions = collectHitlDecisions(part);
1248
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-3", children: [
1249
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MessageResponse, { children: message }),
1250
- state?.error ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-sm text-destructive", children: state.error }) : null,
1251
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-wrap items-center gap-2", children: decisions.map((decision) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1202
+ ) : null,
1203
+ state?.error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "text-sm text-destructive", children: state.error }) : null,
1204
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex flex-wrap items-center gap-2", children: part.allowedActions.map((action) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1252
1205
  "button",
1253
1206
  {
1207
+ "aria-label": actionLabel(part, action),
1254
1208
  className: cn(
1255
1209
  "min-w-24 rounded-md border px-3 py-1.5 text-sm font-medium transition-colors disabled:pointer-events-none disabled:opacity-60",
1256
- decision === "approve" || decision === "connect" ? "border-neutral-900 bg-neutral-900 text-white hover:bg-neutral-800" : "border-border bg-background text-foreground hover:bg-muted"
1210
+ action === "approve" || action === "connect" ? "border-neutral-900 bg-neutral-900 text-white hover:bg-neutral-800" : "border-border bg-background text-foreground hover:bg-muted"
1257
1211
  ),
1258
- disabled: !onHitlAction || isLoading || state?.status === "connecting" || state?.status === "resuming",
1259
- onClick: () => onHitlAction?.(part, decision),
1212
+ disabled: !onHitlAction || isLoading || state?.status === "connecting" || state?.status === "resuming" || requireComment && !comment.trim(),
1213
+ onClick: () => onHitlAction?.(part, action, comment.trim() || void 0),
1260
1214
  type: "button",
1261
- children: decision === "connect" ? "Connect" : decision
1215
+ children: actionLabel(part, action)
1262
1216
  },
1263
- decision
1217
+ action
1264
1218
  )) })
1265
1219
  ] });
1266
1220
  }
@@ -1272,20 +1226,20 @@ function DefaultPartRow({
1272
1226
  onHitlAction,
1273
1227
  part
1274
1228
  }) {
1275
- if (part.kind === "text") return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MessageResponse, { children: part.text });
1276
- if (part.kind === "tool") return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ToolPartRow, { activeToolId, part });
1229
+ if (part.kind === "text") return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MessageResponse, { children: part.text });
1230
+ if (part.kind === "tool") return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ToolPartRow, { activeToolId, part });
1277
1231
  if (part.kind === "reasoning") {
1278
1232
  const label = part.text || part.label || "Thinking";
1279
- return part.status === "running" || part.status === "streaming" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shimmer, { className: "text-sm text-muted-foreground", children: label }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-sm text-muted-foreground", children: label });
1233
+ return part.status === "running" || part.status === "streaming" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Shimmer, { className: "text-sm text-muted-foreground", children: label }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "text-sm text-muted-foreground", children: label });
1280
1234
  }
1281
1235
  if (part.kind === "ui-blocks") {
1282
1236
  if (part.state === "output-error") {
1283
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-sm text-destructive", children: part.errorText || "Failed to render UI content." });
1237
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "text-sm text-destructive", children: part.errorText || "Failed to render UI content." });
1284
1238
  }
1285
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CompactTask, { label: part.state === "input-streaming" ? "Rendering UI block" : "Rendered UI block", loading: part.state === "input-streaming" });
1239
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CompactTask, { label: part.state === "input-streaming" ? "Rendering UI block" : "Rendered UI block", loading: part.state === "input-streaming" });
1286
1240
  }
1287
1241
  if (part.kind === "hitl") {
1288
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1242
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1289
1243
  HitlPartRow,
1290
1244
  {
1291
1245
  getHitlActionState,
@@ -1295,8 +1249,8 @@ function DefaultPartRow({
1295
1249
  }
1296
1250
  );
1297
1251
  }
1298
- if (part.kind === "error") return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-sm text-destructive", children: part.errorText });
1299
- if (part.kind === "data") return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { "data-agents24-data-part": part.name, className: "hidden", children: message.id });
1252
+ if (part.kind === "error") return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "text-sm text-destructive", children: part.errorText });
1253
+ if (part.kind === "data") return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { "data-agents24-data-part": part.name, className: "hidden", children: message.id });
1300
1254
  return null;
1301
1255
  }
1302
1256
  function AgentResponseTimeline({
@@ -1321,11 +1275,11 @@ function AgentResponseTimeline({
1321
1275
  group.push(candidate);
1322
1276
  index += 1;
1323
1277
  }
1324
- rendered.push(group.length === 1 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ToolPartRow, { activeToolId, part: group[0] }, group[0].id) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ToolGroup, { activeToolId, parts: group }, `tool-group-${key}-${group[0].id}`));
1278
+ rendered.push(group.length === 1 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ToolPartRow, { activeToolId, part: group[0] }, group[0].id) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ToolGroup, { activeToolId, parts: group }, `tool-group-${key}-${group[0].id}`));
1325
1279
  continue;
1326
1280
  }
1327
1281
  rendered.push(
1328
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(React4.Fragment, { children: renderPart ? renderPart(part, message) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1282
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(React4.Fragment, { children: renderPart ? renderPart(part, message) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1329
1283
  DefaultPartRow,
1330
1284
  {
1331
1285
  activeToolId,
@@ -1340,16 +1294,16 @@ function AgentResponseTimeline({
1340
1294
  index += 1;
1341
1295
  }
1342
1296
  if (rendered.length === 0 && message.content) {
1343
- rendered.push(/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MessageResponse, { children: message.content }, `${message.id}-fallback`));
1297
+ rendered.push(/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MessageResponse, { children: message.content }, `${message.id}-fallback`));
1344
1298
  }
1345
1299
  if (rendered.length === 0 && isLoading) {
1346
- rendered.push(/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-sm text-muted-foreground", children: "Thinking" }, `${message.id}-thinking`));
1300
+ rendered.push(/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "text-sm text-muted-foreground", children: "Thinking" }, `${message.id}-thinking`));
1347
1301
  }
1348
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "space-y-3", children: rendered });
1302
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "space-y-3", children: rendered });
1349
1303
  }
1350
1304
 
1351
1305
  // src/ui/agent-chat-message.tsx
1352
- var import_jsx_runtime8 = require("react/jsx-runtime");
1306
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1353
1307
  var DEFAULT_USER_MESSAGE_COLLAPSE_THRESHOLD = 360;
1354
1308
  var DEFAULT_USER_MESSAGE_COLLAPSED_LINES = 4;
1355
1309
  function shouldCollapseUserMessage(content, threshold = DEFAULT_USER_MESSAGE_COLLAPSE_THRESHOLD) {
@@ -1372,9 +1326,9 @@ function AgentChatUserMessageContent({
1372
1326
  display: "-webkit-box",
1373
1327
  overflow: "hidden"
1374
1328
  } : void 0;
1375
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex min-w-0 flex-col gap-3", children: [
1376
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { id: contentId, className: "min-w-0", style: clampedStyle, children: content }),
1377
- shouldCollapse ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1329
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-0 flex-col gap-3", children: [
1330
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { id: contentId, className: "min-w-0", style: clampedStyle, children: content }),
1331
+ shouldCollapse ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1378
1332
  "button",
1379
1333
  {
1380
1334
  "aria-controls": contentId,
@@ -1387,7 +1341,7 @@ function AgentChatUserMessageContent({
1387
1341
  type: "button",
1388
1342
  children: [
1389
1343
  isExpanded ? showLessLabel : showMoreLabel,
1390
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Icon, { "aria-hidden": "true", className: "size-4", strokeWidth: 2 })
1344
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { "aria-hidden": "true", className: "size-4", strokeWidth: 2 })
1391
1345
  ]
1392
1346
  }
1393
1347
  ) : null
@@ -1419,9 +1373,9 @@ function AgentChatMessage({
1419
1373
  const resolvedUserContent = userMessageContent ?? message.content;
1420
1374
  const shouldRenderContent = isAssistant || Boolean(renderUserContent || resolvedUserContent);
1421
1375
  const showAttachments = Boolean(message.attachments?.length) && (message.role === "user" || showAssistantAttachments);
1422
- const renderedActions = actions ?? (actionHandlers ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(AgentChatDefaultActions, { handlers: actionHandlers, message }) : null);
1423
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(ChatMessage, { className, dir, from: message.role, children: [
1424
- showAttachments ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ChatAttachments, { className: "mb-2", dir, children: message.attachments?.map((attachment, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1376
+ const renderedActions = actions ?? (actionHandlers ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AgentChatDefaultActions, { handlers: actionHandlers, message }) : null);
1377
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(ChatMessage, { className, dir, from: message.role, children: [
1378
+ showAttachments ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChatAttachments, { className: "mb-2", dir, children: message.attachments?.map((attachment, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1425
1379
  ChatAttachment,
1426
1380
  {
1427
1381
  data: attachment,
@@ -1429,13 +1383,13 @@ function AgentChatMessage({
1429
1383
  },
1430
1384
  String(attachment.url || attachment.filename || index)
1431
1385
  )) }) : null,
1432
- shouldRenderContent ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1386
+ shouldRenderContent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1433
1387
  ChatMessageContent,
1434
1388
  {
1435
1389
  className: cn(isAssistant ? "bg-transparent p-0" : void 0, contentClassName),
1436
1390
  dir,
1437
1391
  children: [
1438
- isAssistant ? renderAssistantContent ? renderAssistantContent({ isStreaming, message }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1392
+ isAssistant ? renderAssistantContent ? renderAssistantContent({ isStreaming, message }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1439
1393
  AgentResponseTimeline,
1440
1394
  {
1441
1395
  getHitlActionState,
@@ -1445,7 +1399,7 @@ function AgentChatMessage({
1445
1399
  renderPart
1446
1400
  }
1447
1401
  ) : null,
1448
- !isAssistant ? renderUserContent ? renderUserContent({ message }) : resolvedUserContent ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1402
+ !isAssistant ? renderUserContent ? renderUserContent({ message }) : resolvedUserContent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1449
1403
  AgentChatUserMessageContent,
1450
1404
  {
1451
1405
  collapsedLines: userMessageCollapsedLines,
@@ -1458,16 +1412,16 @@ function AgentChatMessage({
1458
1412
  ]
1459
1413
  }
1460
1414
  ) : null,
1461
- renderedActions ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: cn(dir === "rtl" ? "mt-1 h-9 w-full translate-x-2" : "mt-1 h-9 w-full -translate-x-2", actionsClassName), children: renderedActions }) : null
1415
+ renderedActions ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: cn(dir === "rtl" ? "mt-1 h-9 w-full translate-x-2" : "mt-1 h-9 w-full -translate-x-2", actionsClassName), children: renderedActions }) : null
1462
1416
  ] });
1463
1417
  }
1464
1418
 
1465
1419
  // src/ui/bubble.tsx
1466
1420
  var import_class_variance_authority2 = require("class-variance-authority");
1467
1421
  var import_react_slot2 = require("@radix-ui/react-slot");
1468
- var import_jsx_runtime9 = require("react/jsx-runtime");
1422
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1469
1423
  function BubbleGroup({ className, ...props }) {
1470
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1424
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1471
1425
  "div",
1472
1426
  {
1473
1427
  "data-slot": "bubble-group",
@@ -1501,7 +1455,7 @@ function Bubble({
1501
1455
  className,
1502
1456
  ...props
1503
1457
  }) {
1504
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1458
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1505
1459
  "div",
1506
1460
  {
1507
1461
  "data-slot": "bubble",
@@ -1518,7 +1472,7 @@ function BubbleContent({
1518
1472
  ...props
1519
1473
  }) {
1520
1474
  const Comp = asChild ? import_react_slot2.Slot : "div";
1521
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1475
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1522
1476
  Comp,
1523
1477
  {
1524
1478
  "data-slot": "bubble-content",
@@ -1555,7 +1509,7 @@ function BubbleReactions({
1555
1509
  className,
1556
1510
  ...props
1557
1511
  }) {
1558
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1512
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1559
1513
  "div",
1560
1514
  {
1561
1515
  "data-slot": "bubble-reactions",
@@ -1570,7 +1524,7 @@ function BubbleReactions({
1570
1524
  // src/ui/marker.tsx
1571
1525
  var import_class_variance_authority3 = require("class-variance-authority");
1572
1526
  var import_react_slot3 = require("@radix-ui/react-slot");
1573
- var import_jsx_runtime10 = require("react/jsx-runtime");
1527
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1574
1528
  var markerVariants = (0, import_class_variance_authority3.cva)(
1575
1529
  "group/marker relative flex min-h-4 w-full items-center gap-2 text-left text-sm text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [a]:underline [a]:underline-offset-3 [a]:hover:text-foreground",
1576
1530
  {
@@ -1590,7 +1544,7 @@ function Marker({
1590
1544
  ...props
1591
1545
  }) {
1592
1546
  const Comp = asChild ? import_react_slot3.Slot : "div";
1593
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1547
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1594
1548
  Comp,
1595
1549
  {
1596
1550
  "data-slot": "marker",
@@ -1601,7 +1555,7 @@ function Marker({
1601
1555
  );
1602
1556
  }
1603
1557
  function MarkerIcon({ className, ...props }) {
1604
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1558
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1605
1559
  "span",
1606
1560
  {
1607
1561
  "data-slot": "marker-icon",
@@ -1615,7 +1569,7 @@ function MarkerIcon({ className, ...props }) {
1615
1569
  );
1616
1570
  }
1617
1571
  function MarkerContent({ className, ...props }) {
1618
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1572
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1619
1573
  "span",
1620
1574
  {
1621
1575
  "data-slot": "marker-content",
@@ -1627,6 +1581,65 @@ function MarkerContent({ className, ...props }) {
1627
1581
  }
1628
1582
  );
1629
1583
  }
1584
+
1585
+ // src/ui/mcp-connect-required-card.tsx
1586
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1587
+ var STATUS_LABELS = {
1588
+ pending: "Connect",
1589
+ connecting: "Connecting",
1590
+ connected: "Connected",
1591
+ resuming: "Resuming",
1592
+ error: "Try again"
1593
+ };
1594
+ function McpConnectRequiredCard({
1595
+ serverName,
1596
+ providerKey,
1597
+ message,
1598
+ status = "pending",
1599
+ disabled = false,
1600
+ loading = false,
1601
+ error,
1602
+ onConnect,
1603
+ className,
1604
+ ...props
1605
+ }) {
1606
+ const label = String(serverName || providerKey || "MCP server").trim();
1607
+ const isBusy = loading || status === "connecting" || status === "resuming";
1608
+ const isConnected = status === "connected";
1609
+ const buttonDisabled = disabled || isBusy || isConnected || !onConnect;
1610
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1611
+ "div",
1612
+ {
1613
+ "data-agents24-mcp-connect-card": true,
1614
+ "data-status": status,
1615
+ className: cn(
1616
+ "w-full rounded-lg border border-border/50 bg-muted/25 p-3 text-sm text-foreground",
1617
+ className
1618
+ ),
1619
+ ...props,
1620
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex min-w-0 items-start justify-between gap-3", children: [
1621
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "min-w-0", children: [
1622
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "truncate text-sm font-medium", children: label }),
1623
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-1 text-sm text-muted-foreground", children: message || "Connect your account to continue." }),
1624
+ status === "error" && error ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-2 text-sm text-destructive", children: error }) : null
1625
+ ] }),
1626
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1627
+ "button",
1628
+ {
1629
+ type: "button",
1630
+ className: cn(
1631
+ "shrink-0 rounded-md border px-3 py-1.5 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-60",
1632
+ status === "pending" || status === "error" ? "border-neutral-900 bg-neutral-900 text-white hover:bg-neutral-800" : "border-border bg-background text-foreground hover:bg-muted"
1633
+ ),
1634
+ disabled: buttonDisabled,
1635
+ onClick: onConnect,
1636
+ children: STATUS_LABELS[status]
1637
+ }
1638
+ )
1639
+ ] })
1640
+ }
1641
+ );
1642
+ }
1630
1643
  // Annotate the CommonJS export names for ESM import in node:
1631
1644
  0 && (module.exports = {
1632
1645
  AgentChatComposer,