@alquimia-ai/ui 2.2.4 → 2.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.
@@ -3,7 +3,9 @@ import { Message } from 'ai';
3
3
  import { TTSResult, Tooler, ToolFactory, RatingData } from '../../types/index.mjs';
4
4
  import * as React$1 from 'react';
5
5
  import { AlquimiaSDK } from '@alquimia-ai/tools/sdk';
6
+ export { T as ToolApprovalCard, a as ToolApprovalCardProps, b as ToolApprovalView } from '../../tool-approval-K8aLzb1_.mjs';
6
7
  import '@alquimia-ai/tools/types';
8
+ import '@alquimia-ai/tools/hooks';
7
9
 
8
10
  interface WhisperProps extends React.HTMLAttributes<HTMLDivElement> {
9
11
  message: Message;
@@ -3,7 +3,9 @@ import { Message } from 'ai';
3
3
  import { TTSResult, Tooler, ToolFactory, RatingData } from '../../types/index.js';
4
4
  import * as React$1 from 'react';
5
5
  import { AlquimiaSDK } from '@alquimia-ai/tools/sdk';
6
+ export { T as ToolApprovalCard, a as ToolApprovalCardProps, b as ToolApprovalView } from '../../tool-approval-K8aLzb1_.js';
6
7
  import '@alquimia-ai/tools/types';
8
+ import '@alquimia-ai/tools/hooks';
7
9
 
8
10
  interface WhisperProps extends React.HTMLAttributes<HTMLDivElement> {
9
11
  message: Message;
@@ -358,6 +358,9 @@ __export(organisms_exports, {
358
358
  SpeechToText: function() {
359
359
  return SpeechToText;
360
360
  },
361
+ ToolApprovalCard: function() {
362
+ return ToolApprovalCard;
363
+ },
361
364
  Whisper: function() {
362
365
  return Whisper;
363
366
  }
@@ -3718,4 +3721,195 @@ function RatingDialog(param) {
3718
3721
  })
3719
3722
  });
3720
3723
  }
3724
+ // src/components/organisms/tool-approval.tsx
3725
+ var React38 = __toESM(require("react"));
3726
+ var import_lucide_react19 = require("lucide-react");
3727
+ var import_jsx_runtime50 = require("react/jsx-runtime");
3728
+ function formatArguments(args) {
3729
+ if (args === null || args === void 0) return null;
3730
+ if (typeof args === "string") return args;
3731
+ try {
3732
+ return JSON.stringify(args, null, 2);
3733
+ } catch (e) {
3734
+ return String(args);
3735
+ }
3736
+ }
3737
+ function blockedMessage(approval, channelName) {
3738
+ var _approval_lastResult;
3739
+ var outcome = (_approval_lastResult = approval.lastResult) === null || _approval_lastResult === void 0 ? void 0 : _approval_lastResult.outcome;
3740
+ if (approval.channelOwned || outcome === "wrong-channel") {
3741
+ return "This approval has to be answered in ".concat(channelName !== null && channelName !== void 0 ? channelName : "the channel the conversation came from", ". It can't be answered here.");
3742
+ }
3743
+ switch(outcome){
3744
+ case "already-decided":
3745
+ return "Someone else already answered this request. Waiting for the agent to continue.";
3746
+ case "not-pending":
3747
+ return "This request is no longer waiting for a decision.";
3748
+ case "not-found":
3749
+ return "This conversation has ended, so the request can no longer be answered.";
3750
+ case "forbidden":
3751
+ return "You don't have permission to answer this request.";
3752
+ default:
3753
+ return null;
3754
+ }
3755
+ }
3756
+ function ToolApprovalCard(param) {
3757
+ var approval = param.approval, onDecide = param.onDecide, channelName = param.channelName, className = param.className;
3758
+ var _React38_useState = _sliced_to_array(React38.useState(false), 2), rejecting = _React38_useState[0], setRejecting = _React38_useState[1];
3759
+ var _React38_useState1 = _sliced_to_array(React38.useState(""), 2), reason = _React38_useState1[0], setReason = _React38_useState1[1];
3760
+ var args = formatArguments(approval.arguments);
3761
+ var _approval_toolName;
3762
+ var toolLabel = (_approval_toolName = approval.toolName) !== null && _approval_toolName !== void 0 ? _approval_toolName : "a tool";
3763
+ var submitting = approval.status === "submitting";
3764
+ var settled = approval.status === "approved" || approval.status === "rejected";
3765
+ var blocked = !settled && !submitting && !approval.canAnswer ? blockedMessage(approval, channelName) : null;
3766
+ var failed = !settled && !submitting && approval.canAnswer && approval.lastResult && approval.lastResult.outcome !== "accepted" ? approval.lastResult : null;
3767
+ var decide = function(approved) {
3768
+ var said = reason.trim();
3769
+ void onDecide(approval.controlId, approved, approved || !said ? void 0 : said);
3770
+ };
3771
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("section", {
3772
+ "aria-label": "Approval request for ".concat(toolLabel),
3773
+ "data-status": approval.status,
3774
+ className: cn("alq--tool-approval w-full max-w-[95%] rounded-2xl border bg-card p-4 shadow-sm", settled ? "border-border/60" : "border-amber-500/50", className),
3775
+ children: [
3776
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("header", {
3777
+ className: "flex items-start gap-2",
3778
+ children: [
3779
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_lucide_react19.ShieldAlert, {
3780
+ "aria-hidden": true,
3781
+ className: cn("mt-0.5 h-4 w-4 shrink-0", settled ? "text-muted-foreground" : "text-amber-500")
3782
+ }),
3783
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", {
3784
+ className: "min-w-0 flex-1",
3785
+ children: [
3786
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", {
3787
+ className: "text-sm font-medium text-foreground",
3788
+ children: settled ? "Approval request" : "The agent needs your approval"
3789
+ }),
3790
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("p", {
3791
+ className: "text-sm text-muted-foreground",
3792
+ children: [
3793
+ "Run ",
3794
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("code", {
3795
+ className: "rounded bg-muted px-1 py-0.5 font-mono text-xs text-foreground",
3796
+ children: toolLabel
3797
+ })
3798
+ ]
3799
+ })
3800
+ ]
3801
+ }),
3802
+ settled && /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", {
3803
+ className: cn("flex shrink-0 items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium", approval.status === "approved" ? "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400" : "bg-destructive/10 text-destructive"),
3804
+ children: [
3805
+ approval.status === "approved" ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_lucide_react19.Check, {
3806
+ className: "h-3 w-3"
3807
+ }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_lucide_react19.X, {
3808
+ className: "h-3 w-3"
3809
+ }),
3810
+ approval.status === "approved" ? "Approved" : "Rejected",
3811
+ approval.decidedHere ? " by you" : " elsewhere"
3812
+ ]
3813
+ })
3814
+ ]
3815
+ }),
3816
+ args !== null && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("pre", {
3817
+ "aria-label": "Arguments",
3818
+ className: "mt-3 max-h-48 overflow-auto rounded-lg bg-muted/60 p-3 font-mono text-xs text-foreground",
3819
+ children: args
3820
+ }),
3821
+ settled && approval.status === "rejected" && approval.reason && /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("p", {
3822
+ className: "mt-3 text-sm text-muted-foreground",
3823
+ children: [
3824
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", {
3825
+ className: "font-medium text-foreground",
3826
+ children: "Reason:"
3827
+ }),
3828
+ " ",
3829
+ approval.reason
3830
+ ]
3831
+ }),
3832
+ blocked && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", {
3833
+ role: "status",
3834
+ className: "mt-3 text-sm text-muted-foreground",
3835
+ children: blocked
3836
+ }),
3837
+ failed && /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("p", {
3838
+ role: "alert",
3839
+ className: "mt-3 text-sm text-destructive",
3840
+ children: [
3841
+ "Couldn't send your decision",
3842
+ failed.detail ? ": ".concat(failed.detail) : ".",
3843
+ " Try again."
3844
+ ]
3845
+ }),
3846
+ !settled && (submitting || approval.canAnswer) && /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", {
3847
+ className: "mt-3 flex flex-col gap-2",
3848
+ children: [
3849
+ rejecting && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Textarea, {
3850
+ "aria-label": "Reason for rejecting (optional)",
3851
+ placeholder: "Reason for rejecting (optional)",
3852
+ value: reason,
3853
+ disabled: submitting,
3854
+ onChange: function(e) {
3855
+ return setReason(e.target.value);
3856
+ },
3857
+ className: "min-h-[64px] text-sm"
3858
+ }),
3859
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", {
3860
+ className: "flex flex-wrap items-center justify-end gap-2",
3861
+ children: [
3862
+ submitting && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_lucide_react19.Loader2, {
3863
+ "aria-label": "Sending decision",
3864
+ className: "h-4 w-4 animate-spin text-muted-foreground"
3865
+ }),
3866
+ rejecting ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_jsx_runtime50.Fragment, {
3867
+ children: [
3868
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Button, {
3869
+ size: "sm",
3870
+ variant: "ghost",
3871
+ disabled: submitting,
3872
+ onClick: function() {
3873
+ return setRejecting(false);
3874
+ },
3875
+ children: "Cancel"
3876
+ }),
3877
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Button, {
3878
+ size: "sm",
3879
+ variant: "destructive",
3880
+ disabled: submitting,
3881
+ onClick: function() {
3882
+ return decide(false);
3883
+ },
3884
+ children: "Reject"
3885
+ })
3886
+ ]
3887
+ }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_jsx_runtime50.Fragment, {
3888
+ children: [
3889
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Button, {
3890
+ size: "sm",
3891
+ variant: "outline",
3892
+ disabled: submitting,
3893
+ onClick: function() {
3894
+ return setRejecting(true);
3895
+ },
3896
+ children: "Reject\u2026"
3897
+ }),
3898
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Button, {
3899
+ size: "sm",
3900
+ disabled: submitting,
3901
+ onClick: function() {
3902
+ return decide(true);
3903
+ },
3904
+ children: "Approve"
3905
+ })
3906
+ ]
3907
+ })
3908
+ ]
3909
+ })
3910
+ ]
3911
+ })
3912
+ ]
3913
+ });
3914
+ }
3721
3915
  //# sourceMappingURL=index.js.map