@lukeashford/aurelius 3.2.1 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -846,23 +846,17 @@ interface TodosListProps extends React$1.HTMLAttributes<HTMLDivElement> {
846
846
  * @default "Tasks"
847
847
  */
848
848
  title?: string;
849
+ /**
850
+ * Called when the "Stop All Tasks" button is clicked.
851
+ * Only shown when at least one task is in_progress.
852
+ * The consumer decides what stopping means (cancel API calls, mark cancelled, etc.).
853
+ *
854
+ * May return a Promise. While the Promise is pending, the button becomes
855
+ * disabled and displays a spinner with "Stopping tasks" to give the user
856
+ * feedback that the stop request is in flight.
857
+ */
858
+ onStopAllTasks?: () => void | Promise<void>;
849
859
  }
850
- /**
851
- * TodosList displays a structured list of tasks with status indicators.
852
- *
853
- * Features:
854
- * - Nested tasks with indentation
855
- * - Status indicators: done (checkmark), in_progress (snake animation), pending (empty),
856
- * cancelled, failed
857
- * - Done tasks are crossed out with golden checkmark
858
- * - Cancelled/failed tasks are crossed out with subtle styling and sorted to bottom of their local
859
- * group
860
- * - Max 1/4 screen height with scroll
861
- * - Subtasks appear when parent task is in_progress or done
862
- *
863
- * The component automatically sorts cancelled/failed tasks to the bottom of their local group
864
- * (not globally), so just changing a task's status will reorder it appropriately.
865
- */
866
860
  declare const TodosList: React$1.ForwardRefExoticComponent<TodosListProps & React$1.RefAttributes<HTMLDivElement>>;
867
861
  /**
868
862
  * Returns true when every task (and subtask, recursively) is in a
@@ -1402,6 +1396,16 @@ interface ChatInterfaceProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>
1402
1396
  * @default "Tasks"
1403
1397
  */
1404
1398
  tasksTitle?: string;
1399
+ /**
1400
+ * Called when the "Stop All Tasks" button is clicked in the tasks panel.
1401
+ * Only shown when at least one task has in_progress status.
1402
+ * The consumer app decides what stopping means (cancel API calls, mark tasks cancelled, etc.).
1403
+ *
1404
+ * May return a Promise. While the Promise is pending, the button becomes
1405
+ * disabled and displays a spinner with "Stopping tasks" so the user knows
1406
+ * the stop request is in flight.
1407
+ */
1408
+ onStopAllTasks?: () => void | Promise<void>;
1405
1409
  /**
1406
1410
  * Additional tools to add to the tool sidebars. Each ExternalToolDefinition provides
1407
1411
  * an id, icon, label, group ('top-left' | 'bottom-left' | 'top-right' | 'bottom-right'),
package/dist/index.d.ts CHANGED
@@ -846,23 +846,17 @@ interface TodosListProps extends React$1.HTMLAttributes<HTMLDivElement> {
846
846
  * @default "Tasks"
847
847
  */
848
848
  title?: string;
849
+ /**
850
+ * Called when the "Stop All Tasks" button is clicked.
851
+ * Only shown when at least one task is in_progress.
852
+ * The consumer decides what stopping means (cancel API calls, mark cancelled, etc.).
853
+ *
854
+ * May return a Promise. While the Promise is pending, the button becomes
855
+ * disabled and displays a spinner with "Stopping tasks" to give the user
856
+ * feedback that the stop request is in flight.
857
+ */
858
+ onStopAllTasks?: () => void | Promise<void>;
849
859
  }
850
- /**
851
- * TodosList displays a structured list of tasks with status indicators.
852
- *
853
- * Features:
854
- * - Nested tasks with indentation
855
- * - Status indicators: done (checkmark), in_progress (snake animation), pending (empty),
856
- * cancelled, failed
857
- * - Done tasks are crossed out with golden checkmark
858
- * - Cancelled/failed tasks are crossed out with subtle styling and sorted to bottom of their local
859
- * group
860
- * - Max 1/4 screen height with scroll
861
- * - Subtasks appear when parent task is in_progress or done
862
- *
863
- * The component automatically sorts cancelled/failed tasks to the bottom of their local group
864
- * (not globally), so just changing a task's status will reorder it appropriately.
865
- */
866
860
  declare const TodosList: React$1.ForwardRefExoticComponent<TodosListProps & React$1.RefAttributes<HTMLDivElement>>;
867
861
  /**
868
862
  * Returns true when every task (and subtask, recursively) is in a
@@ -1402,6 +1396,16 @@ interface ChatInterfaceProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>
1402
1396
  * @default "Tasks"
1403
1397
  */
1404
1398
  tasksTitle?: string;
1399
+ /**
1400
+ * Called when the "Stop All Tasks" button is clicked in the tasks panel.
1401
+ * Only shown when at least one task has in_progress status.
1402
+ * The consumer app decides what stopping means (cancel API calls, mark tasks cancelled, etc.).
1403
+ *
1404
+ * May return a Promise. While the Promise is pending, the button becomes
1405
+ * disabled and displays a spinner with "Stopping tasks" so the user knows
1406
+ * the stop request is in flight.
1407
+ */
1408
+ onStopAllTasks?: () => void | Promise<void>;
1405
1409
  /**
1406
1410
  * Additional tools to add to the tool sidebars. Each ExternalToolDefinition provides
1407
1411
  * an id, icon, label, group ('top-left' | 'bottom-left' | 'top-right' | 'bottom-right'),
package/dist/index.js CHANGED
@@ -6061,6 +6061,7 @@ ArtifactsPanelToggle.displayName = "ArtifactsPanelToggle";
6061
6061
 
6062
6062
  // src/components/chat/TodosList.tsx
6063
6063
  var import_react73 = __toESM(require("react"));
6064
+ var import_lucide_react14 = require("lucide-react");
6064
6065
  var TASK_STATUSES = {
6065
6066
  PENDING: "pending",
6066
6067
  IN_PROGRESS: "in_progress",
@@ -6126,9 +6127,26 @@ function TaskItem({ task, depth = 0 }) {
6126
6127
  )
6127
6128
  ), showSubtasks && /* @__PURE__ */ import_react73.default.createElement("div", { className: "flex flex-col" }, sortedSubtasks.map((subtask) => /* @__PURE__ */ import_react73.default.createElement(TaskItem, { key: subtask.id, task: subtask, depth: depth + 1 }))));
6128
6129
  }
6130
+ function hasInProgressTask(tasks) {
6131
+ return tasks.some((t) => {
6132
+ if (t.status === "in_progress") return true;
6133
+ if (t.subtasks && t.subtasks.length > 0) return hasInProgressTask(t.subtasks);
6134
+ return false;
6135
+ });
6136
+ }
6129
6137
  var TodosList = import_react73.default.forwardRef(
6130
- ({ tasks, title = "Tasks", className, ...rest }, ref) => {
6138
+ ({ tasks, title = "Tasks", onStopAllTasks, className, ...rest }, ref) => {
6131
6139
  const sortedTasks = (0, import_react73.useMemo)(() => sortTasks(tasks), [tasks]);
6140
+ const [isStopping, setIsStopping] = (0, import_react73.useState)(false);
6141
+ const handleStopClick = (0, import_react73.useCallback)(async () => {
6142
+ if (!onStopAllTasks || isStopping) return;
6143
+ try {
6144
+ setIsStopping(true);
6145
+ await onStopAllTasks();
6146
+ } finally {
6147
+ setIsStopping(false);
6148
+ }
6149
+ }, [onStopAllTasks, isStopping]);
6132
6150
  const countCompleted = (taskList) => {
6133
6151
  let count = 0;
6134
6152
  for (const task of taskList) {
@@ -6150,6 +6168,7 @@ var TodosList = import_react73.default.forwardRef(
6150
6168
  }
6151
6169
  return count;
6152
6170
  };
6171
+ const showStopButton = !!onStopAllTasks && (hasInProgressTask(tasks) || isStopping);
6153
6172
  if (tasks.length === 0) {
6154
6173
  return null;
6155
6174
  }
@@ -6172,7 +6191,26 @@ var TodosList = import_react73.default.forwardRef(
6172
6191
  /* @__PURE__ */ import_react73.default.createElement("h4", { className: "text-xs font-medium text-white" }, title),
6173
6192
  /* @__PURE__ */ import_react73.default.createElement("span", { className: "text-xs text-silver/60" }, countCompleted(tasks), "/", countTotal(tasks))
6174
6193
  ),
6175
- /* @__PURE__ */ import_react73.default.createElement("div", { className: "flex-1 overflow-y-auto px-4 py-2" }, sortedTasks.map((task) => /* @__PURE__ */ import_react73.default.createElement(TaskItem, { key: task.id, task })))
6194
+ /* @__PURE__ */ import_react73.default.createElement("div", { className: "flex-1 overflow-y-auto px-4 py-2" }, sortedTasks.map((task) => /* @__PURE__ */ import_react73.default.createElement(TaskItem, { key: task.id, task }))),
6195
+ showStopButton && /* @__PURE__ */ import_react73.default.createElement("div", { className: "px-4 py-2 border-t border-ash/40 flex-shrink-0" }, /* @__PURE__ */ import_react73.default.createElement(
6196
+ "button",
6197
+ {
6198
+ type: "button",
6199
+ onClick: handleStopClick,
6200
+ disabled: isStopping,
6201
+ "aria-busy": isStopping,
6202
+ "aria-label": isStopping ? "Stopping tasks" : "Stop all tasks",
6203
+ className: cx(
6204
+ "w-full flex items-center justify-center gap-2 px-3 py-1.5",
6205
+ "bg-error/10 text-error",
6206
+ "border border-error/30",
6207
+ "text-xs font-medium",
6208
+ "transition-colors duration-200",
6209
+ isStopping ? "cursor-not-allowed opacity-70" : "hover:bg-error/20"
6210
+ )
6211
+ },
6212
+ isStopping ? /* @__PURE__ */ import_react73.default.createElement(import_react73.default.Fragment, null, /* @__PURE__ */ import_react73.default.createElement(import_lucide_react14.Loader2, { className: "w-3 h-3 animate-spin" }), "Stopping tasks") : /* @__PURE__ */ import_react73.default.createElement(import_react73.default.Fragment, null, /* @__PURE__ */ import_react73.default.createElement(import_lucide_react14.Square, { className: "w-3 h-3 fill-current" }), "Stop All Tasks")
6213
+ ))
6176
6214
  );
6177
6215
  }
6178
6216
  );
@@ -6438,6 +6476,7 @@ var ChatInterface = import_react77.default.forwardRef(
6438
6476
  onArtifactsPanelOpenChange,
6439
6477
  tasks = [],
6440
6478
  tasksTitle,
6479
+ onStopAllTasks,
6441
6480
  tools: externalTools = [],
6442
6481
  className,
6443
6482
  ...rest
@@ -6698,7 +6737,7 @@ var ChatInterface = import_react77.default.forwardRef(
6698
6737
  }
6699
6738
  );
6700
6739
  case "todos":
6701
- return tasks.length > 0 ? /* @__PURE__ */ import_react77.default.createElement(TodosList, { tasks, title: tasksTitle, className: "h-full" }) : /* @__PURE__ */ import_react77.default.createElement("div", { className: "h-full flex flex-col" }, /* @__PURE__ */ import_react77.default.createElement("div", { className: "flex items-center p-4 border-b border-ash/40 shrink-0" }, /* @__PURE__ */ import_react77.default.createElement("h3", { className: "text-xs font-medium text-white" }, "Tasks")), /* @__PURE__ */ import_react77.default.createElement("div", { className: "flex-1 flex items-center justify-center" }, /* @__PURE__ */ import_react77.default.createElement("p", { className: "text-xs text-silver/60" }, "No tasks")));
6740
+ return tasks.length > 0 ? /* @__PURE__ */ import_react77.default.createElement(TodosList, { tasks, title: tasksTitle, onStopAllTasks, className: "h-full" }) : /* @__PURE__ */ import_react77.default.createElement("div", { className: "h-full flex flex-col" }, /* @__PURE__ */ import_react77.default.createElement("div", { className: "flex items-center p-4 border-b border-ash/40 shrink-0" }, /* @__PURE__ */ import_react77.default.createElement("h3", { className: "text-xs font-medium text-white" }, "Tasks")), /* @__PURE__ */ import_react77.default.createElement("div", { className: "flex-1 flex items-center justify-center" }, /* @__PURE__ */ import_react77.default.createElement("p", { className: "text-xs text-silver/60" }, "No tasks")));
6702
6741
  default: {
6703
6742
  const externalTool = externalTools.find((t) => t.id === toolId);
6704
6743
  return externalTool?.content ?? null;
@@ -6796,7 +6835,7 @@ ChatInterface.displayName = "ChatInterface";
6796
6835
 
6797
6836
  // src/components/chat/MessageActions.tsx
6798
6837
  var import_react78 = __toESM(require("react"));
6799
- var import_lucide_react14 = require("lucide-react");
6838
+ var import_lucide_react15 = require("lucide-react");
6800
6839
  var ActionButton2 = ({ onClick, label, children, className, disabled }) => /* @__PURE__ */ import_react78.default.createElement(
6801
6840
  "button",
6802
6841
  {
@@ -6917,7 +6956,7 @@ var MessageActions = import_react78.default.forwardRef(
6917
6956
  label: "Cancel edit",
6918
6957
  className: "text-silver/60 hover:text-error"
6919
6958
  },
6920
- /* @__PURE__ */ import_react78.default.createElement(import_lucide_react14.X, { className: "w-4 h-4" })
6959
+ /* @__PURE__ */ import_react78.default.createElement(import_lucide_react15.X, { className: "w-4 h-4" })
6921
6960
  ), /* @__PURE__ */ import_react78.default.createElement(
6922
6961
  ActionButton2,
6923
6962
  {
@@ -6926,7 +6965,7 @@ var MessageActions = import_react78.default.forwardRef(
6926
6965
  className: "text-silver/60 hover:text-gold",
6927
6966
  disabled: !editValue.trim() || editValue.trim() === content
6928
6967
  },
6929
- /* @__PURE__ */ import_react78.default.createElement(import_lucide_react14.Send, { className: "w-4 h-4" })
6968
+ /* @__PURE__ */ import_react78.default.createElement(import_lucide_react15.Send, { className: "w-4 h-4" })
6930
6969
  ))
6931
6970
  ),
6932
6971
  /* @__PURE__ */ import_react78.default.createElement("p", { className: "text-xs text-silver/50 mt-1" }, "Press Enter to submit, Esc to cancel. This will create a new branch.")
@@ -6943,9 +6982,9 @@ var MessageActions = import_react78.default.forwardRef(
6943
6982
  ),
6944
6983
  ...rest
6945
6984
  },
6946
- /* @__PURE__ */ import_react78.default.createElement(ActionButton2, { onClick: handleCopy, label: copied ? "Copied!" : "Copy message" }, copied ? /* @__PURE__ */ import_react78.default.createElement(import_lucide_react14.Check, { className: "w-3.5 h-3.5 text-success" }) : /* @__PURE__ */ import_react78.default.createElement(import_lucide_react14.Copy, { className: "w-3.5 h-3.5" })),
6947
- isUser && onEdit && /* @__PURE__ */ import_react78.default.createElement(ActionButton2, { onClick: handleStartEdit, label: "Edit message" }, /* @__PURE__ */ import_react78.default.createElement(import_lucide_react14.Pencil, { className: "w-3.5 h-3.5" })),
6948
- !isUser && onRetry && /* @__PURE__ */ import_react78.default.createElement(ActionButton2, { onClick: onRetry, label: "Regenerate response" }, /* @__PURE__ */ import_react78.default.createElement(import_lucide_react14.RotateCcw, { className: "w-3.5 h-3.5" }))
6985
+ /* @__PURE__ */ import_react78.default.createElement(ActionButton2, { onClick: handleCopy, label: copied ? "Copied!" : "Copy message" }, copied ? /* @__PURE__ */ import_react78.default.createElement(import_lucide_react15.Check, { className: "w-3.5 h-3.5 text-success" }) : /* @__PURE__ */ import_react78.default.createElement(import_lucide_react15.Copy, { className: "w-3.5 h-3.5" })),
6986
+ isUser && onEdit && /* @__PURE__ */ import_react78.default.createElement(ActionButton2, { onClick: handleStartEdit, label: "Edit message" }, /* @__PURE__ */ import_react78.default.createElement(import_lucide_react15.Pencil, { className: "w-3.5 h-3.5" })),
6987
+ !isUser && onRetry && /* @__PURE__ */ import_react78.default.createElement(ActionButton2, { onClick: onRetry, label: "Regenerate response" }, /* @__PURE__ */ import_react78.default.createElement(import_lucide_react15.RotateCcw, { className: "w-3.5 h-3.5" }))
6949
6988
  );
6950
6989
  }
6951
6990
  );
@@ -6953,7 +6992,7 @@ MessageActions.displayName = "MessageActions";
6953
6992
 
6954
6993
  // src/components/chat/BranchNavigator.tsx
6955
6994
  var import_react79 = __toESM(require("react"));
6956
- var import_lucide_react15 = require("lucide-react");
6995
+ var import_lucide_react16 = require("lucide-react");
6957
6996
  var BranchNavigator = import_react79.default.forwardRef(
6958
6997
  ({
6959
6998
  current,
@@ -6985,7 +7024,7 @@ var BranchNavigator = import_react79.default.forwardRef(
6985
7024
  "aria-label": "Branch navigation",
6986
7025
  ...rest
6987
7026
  },
6988
- showIcon && /* @__PURE__ */ import_react79.default.createElement(import_lucide_react15.GitBranch, { className: cx(iconSize, "mr-0.5 text-silver/50"), "aria-hidden": "true" }),
7027
+ showIcon && /* @__PURE__ */ import_react79.default.createElement(import_lucide_react16.GitBranch, { className: cx(iconSize, "mr-0.5 text-silver/50"), "aria-hidden": "true" }),
6989
7028
  /* @__PURE__ */ import_react79.default.createElement(
6990
7029
  "button",
6991
7030
  {
@@ -6999,7 +7038,7 @@ var BranchNavigator = import_react79.default.forwardRef(
6999
7038
  ),
7000
7039
  "aria-label": "Previous branch"
7001
7040
  },
7002
- /* @__PURE__ */ import_react79.default.createElement(import_lucide_react15.ChevronLeft, { className: iconSize })
7041
+ /* @__PURE__ */ import_react79.default.createElement(import_lucide_react16.ChevronLeft, { className: iconSize })
7003
7042
  ),
7004
7043
  /* @__PURE__ */ import_react79.default.createElement("span", { className: cx(textSize, "tabular-nums min-w-6 text-center") }, current, "/", total),
7005
7044
  /* @__PURE__ */ import_react79.default.createElement(
@@ -7015,7 +7054,7 @@ var BranchNavigator = import_react79.default.forwardRef(
7015
7054
  ),
7016
7055
  "aria-label": "Next branch"
7017
7056
  },
7018
- /* @__PURE__ */ import_react79.default.createElement(import_lucide_react15.ChevronRight, { className: iconSize })
7057
+ /* @__PURE__ */ import_react79.default.createElement(import_lucide_react16.ChevronRight, { className: iconSize })
7019
7058
  )
7020
7059
  );
7021
7060
  }