@iblai/iblai-js 1.22.0 → 1.22.2

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.
@@ -261942,6 +261942,20 @@ function toArray(data) {
261942
261942
  }
261943
261943
  return [];
261944
261944
  }
261945
+ /** Page size requested for the paginated LTI list tabs. */
261946
+ const LTI_PAGE_SIZE = 10;
261947
+ /**
261948
+ * Total page count from a paginated LTI list envelope. Reads the backend's
261949
+ * `num_pages`; falls back to a single page when the response isn't paginated.
261950
+ */
261951
+ function getTotalPages(data) {
261952
+ if (data && typeof data === 'object') {
261953
+ const n = data.num_pages;
261954
+ if (typeof n === 'number' && n > 0)
261955
+ return n;
261956
+ }
261957
+ return 1;
261958
+ }
261945
261959
  /**
261946
261960
  * Pull a human-readable message out of an RTK Query / fetch error so we can
261947
261961
  * surface backend-supplied detail (e.g. "key is associated with tool X") to
@@ -262086,12 +262100,14 @@ function AgentLinksSection({ identity, labels, }) {
262086
262100
  const { platformKey, mentorId, mentorUniqueId, username, isLtiAccessible, isReady, isSettingsLoading } = identity;
262087
262101
  const [showCreate, setShowCreate] = React__default.useState(false);
262088
262102
  const [editingLink, setEditingLink] = React__default.useState(null);
262089
- const { data: allLinks, isLoading, isFetching, } = useGetLtiMentorsQuery({ platformKey, mentorId: mentorUniqueId }, { skip: !isReady });
262103
+ const [page, setPage] = React__default.useState(1);
262104
+ const { data: allLinks, isLoading, isFetching, } = useGetLtiMentorsQuery({ platformKey, mentorId: mentorUniqueId, page, pageSize: LTI_PAGE_SIZE }, { skip: !isReady });
262090
262105
  // The backend scopes the list to this agent via `mentor_id`; we still narrow
262091
262106
  // client-side by the unique_id as a defensive safety net.
262092
262107
  const links = React__default.useMemo(() => mentorUniqueId
262093
262108
  ? toArray(allLinks).filter((link) => { var _a; return ((_a = link.mentor_config) === null || _a === void 0 ? void 0 : _a.mentor) === mentorUniqueId; })
262094
262109
  : [], [allLinks, mentorUniqueId]);
262110
+ const totalPages = getTotalPages(allLinks);
262095
262111
  const busy = !isReady || isSettingsLoading || isLoading;
262096
262112
  const canCreate = !busy && links.length === 0 && Boolean(mentorUniqueId);
262097
262113
  return (jsxs("div", { className: "space-y-4", "data-testid": "lti-links-section", children: [jsxs("div", { className: "flex flex-col items-start justify-between gap-3 sm:flex-row sm:items-center", children: [jsx("p", { className: "text-xs text-gray-600", children: labels.links.description }), canCreate && (jsxs(Button$1, { onClick: () => setShowCreate(true), size: "sm", "data-testid": "lti-link-create-button", className: "cursor-pointer whitespace-nowrap bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: [jsx(Plus, { className: "h-4 w-4" }), labels.links.createButton] }))] }), busy ? (jsx("div", { className: "flex w-full items-center justify-center py-10", children: jsx(Spinner, {}) })) : links.length === 0 ? (jsxs("div", { className: "flex flex-col items-center justify-center gap-3 rounded-md border border-dashed border-gray-200 py-12 text-center", "data-testid": "lti-links-empty", children: [jsx(Link2, { className: "h-8 w-8 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm text-[#646464]", children: labels.links.empty })] })) : (jsxs("div", { className: "overflow-hidden rounded-md border", children: [jsx("div", { className: "overflow-x-auto", children: jsxs(Table$1, { className: "min-w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { className: "bg-muted/50 border-b", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.common.nameColumn }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.links.targetUriColumn }), jsx(TableHead, { className: "p-3 text-right text-sm whitespace-nowrap text-[#646464]", children: labels.common.actionsColumn })] }) }), jsx(TableBody, { children: links.map((link) => {
@@ -262100,7 +262116,7 @@ function AgentLinksSection({ identity, labels, }) {
262100
262116
  event.stopPropagation();
262101
262117
  setEditingLink(link);
262102
262118
  }, children: jsx(Pencil, { className: "h-4 w-4" }) }) })] }, link.id));
262103
- }) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), showCreate && (jsx(AgentLinkModal, { isOpen: showCreate, onClose: () => setShowCreate(false), platformKey: platformKey, mentorId: mentorId, mentorUniqueId: mentorUniqueId, username: username, isLtiAccessible: isLtiAccessible, labels: labels })), editingLink && (jsx(AgentLinkModal, { isOpen: Boolean(editingLink), onClose: () => setEditingLink(null), platformKey: platformKey, mentorId: mentorId, mentorUniqueId: mentorUniqueId, username: username, isLtiAccessible: isLtiAccessible, link: editingLink, labels: labels }))] }));
262119
+ }) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: busy || isFetching }), showCreate && (jsx(AgentLinkModal, { isOpen: showCreate, onClose: () => setShowCreate(false), platformKey: platformKey, mentorId: mentorId, mentorUniqueId: mentorUniqueId, username: username, isLtiAccessible: isLtiAccessible, labels: labels })), editingLink && (jsx(AgentLinkModal, { isOpen: Boolean(editingLink), onClose: () => setEditingLink(null), platformKey: platformKey, mentorId: mentorId, mentorUniqueId: mentorUniqueId, username: username, isLtiAccessible: isLtiAccessible, link: editingLink, labels: labels }))] }));
262104
262120
  }
262105
262121
 
262106
262122
  function KeyCreateModal({ isOpen, onClose, platformKey, labels }) {
@@ -262192,10 +262208,12 @@ function KeysSection({ identity, labels }) {
262192
262208
  const [showCreate, setShowCreate] = React__default.useState(false);
262193
262209
  const [selectedKey, setSelectedKey] = React__default.useState(null);
262194
262210
  const [keyToDelete, setKeyToDelete] = React__default.useState(null);
262195
- const { data: keysData, isLoading, isFetching, } = useGetLtiKeysQuery({ platformKey }, { skip: !isReady });
262211
+ const [page, setPage] = React__default.useState(1);
262212
+ const { data: keysData, isLoading, isFetching, } = useGetLtiKeysQuery({ platformKey, page, pageSize: LTI_PAGE_SIZE }, { skip: !isReady });
262196
262213
  const keys = React__default.useMemo(() => toArray(keysData), [keysData]);
262214
+ const totalPages = getTotalPages(keysData);
262197
262215
  const busy = !isReady || isLoading;
262198
- return (jsxs("div", { className: "space-y-4", "data-testid": "lti-keys-section", children: [jsxs("div", { className: "flex flex-col items-start justify-between gap-3 sm:flex-row sm:items-center", children: [jsx("p", { className: "text-xs text-gray-600", children: labels.keys.description }), jsxs(Button$1, { onClick: () => setShowCreate(true), size: "sm", "data-testid": "lti-key-create-button", className: "cursor-pointer whitespace-nowrap bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: [jsx(Plus, { className: "h-4 w-4" }), labels.keys.createButton] })] }), busy ? (jsx("div", { className: "flex w-full items-center justify-center py-10", children: jsx(Spinner, {}) })) : keys.length === 0 ? (jsxs("div", { className: "flex flex-col items-center justify-center gap-3 rounded-md border border-dashed border-gray-200 py-12 text-center", "data-testid": "lti-keys-empty", children: [jsx(KeyRound, { className: "h-8 w-8 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm text-[#646464]", children: labels.keys.empty })] })) : (jsxs("div", { className: "overflow-hidden rounded-md border", children: [jsx("div", { className: "overflow-x-auto", children: jsxs(Table$1, { className: "min-w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { className: "bg-muted/50 border-b", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.common.nameColumn }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.keys.publicKeyColumn }), jsx(TableHead, { className: "p-3 text-right text-sm whitespace-nowrap text-[#646464]", children: labels.common.actionsColumn })] }) }), jsx(TableBody, { children: keys.map((key) => (jsxs(TableRow$1, { "data-testid": "lti-key-row", className: "border-b last:border-0 hover:bg-muted/40", children: [jsx(TableCell$1, { className: "p-3 text-sm font-medium text-gray-900", children: key.name }), jsx(TableCell$1, { className: "p-3 font-mono text-xs text-[#646464]", children: truncateMiddle(key.public_key, 40) }), jsx(TableCell$1, { className: "p-3 text-right", children: jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsx(Button$1, { type: "button", variant: "ghost", size: "icon", "aria-label": labels.keys.actionsAria(key.name), children: jsx(EllipsisVertical, { className: "h-4 w-4" }) }) }), jsxs(DropdownMenuContent, { align: "end", children: [jsxs(DropdownMenuItem, { onClick: () => setSelectedKey(key), children: [jsx(Pencil, { className: "mr-2 h-4 w-4" }), labels.common.edit] }), jsxs(DropdownMenuItem, { className: "text-red-600 focus:text-red-700", onClick: () => setKeyToDelete(key), children: [jsx(Trash2, { className: "mr-2 h-4 w-4" }), labels.common.delete] })] })] }) })] }, key.id))) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), showCreate && (jsx(KeyCreateModal, { isOpen: showCreate, onClose: () => setShowCreate(false), platformKey: platformKey, labels: labels })), selectedKey && (jsx(KeyDetailModal, { isOpen: Boolean(selectedKey), onClose: () => setSelectedKey(null), platformKey: platformKey, ltiKey: selectedKey, labels: labels })), keyToDelete && (jsx(KeyDeleteModal, { isOpen: Boolean(keyToDelete), onClose: () => setKeyToDelete(null), platformKey: platformKey, ltiKey: keyToDelete, labels: labels }))] }));
262216
+ return (jsxs("div", { className: "space-y-4", "data-testid": "lti-keys-section", children: [jsxs("div", { className: "flex flex-col items-start justify-between gap-3 sm:flex-row sm:items-center", children: [jsx("p", { className: "text-xs text-gray-600", children: labels.keys.description }), jsxs(Button$1, { onClick: () => setShowCreate(true), size: "sm", "data-testid": "lti-key-create-button", className: "cursor-pointer whitespace-nowrap bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: [jsx(Plus, { className: "h-4 w-4" }), labels.keys.createButton] })] }), busy ? (jsx("div", { className: "flex w-full items-center justify-center py-10", children: jsx(Spinner, {}) })) : keys.length === 0 ? (jsxs("div", { className: "flex flex-col items-center justify-center gap-3 rounded-md border border-dashed border-gray-200 py-12 text-center", "data-testid": "lti-keys-empty", children: [jsx(KeyRound, { className: "h-8 w-8 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm text-[#646464]", children: labels.keys.empty })] })) : (jsxs("div", { className: "overflow-hidden rounded-md border", children: [jsx("div", { className: "overflow-x-auto", children: jsxs(Table$1, { className: "min-w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { className: "bg-muted/50 border-b", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.common.nameColumn }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.keys.publicKeyColumn }), jsx(TableHead, { className: "p-3 text-right text-sm whitespace-nowrap text-[#646464]", children: labels.common.actionsColumn })] }) }), jsx(TableBody, { children: keys.map((key) => (jsxs(TableRow$1, { "data-testid": "lti-key-row", className: "border-b last:border-0 hover:bg-muted/40", children: [jsx(TableCell$1, { className: "p-3 text-sm font-medium text-gray-900", children: key.name }), jsx(TableCell$1, { className: "p-3 font-mono text-xs text-[#646464]", children: truncateMiddle(key.public_key, 40) }), jsx(TableCell$1, { className: "p-3 text-right", children: jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsx(Button$1, { type: "button", variant: "ghost", size: "icon", "aria-label": labels.keys.actionsAria(key.name), children: jsx(EllipsisVertical, { className: "h-4 w-4" }) }) }), jsxs(DropdownMenuContent, { align: "end", children: [jsxs(DropdownMenuItem, { onClick: () => setSelectedKey(key), children: [jsx(Pencil, { className: "mr-2 h-4 w-4" }), labels.common.edit] }), jsxs(DropdownMenuItem, { className: "text-red-600 focus:text-red-700", onClick: () => setKeyToDelete(key), children: [jsx(Trash2, { className: "mr-2 h-4 w-4" }), labels.common.delete] })] })] }) })] }, key.id))) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: busy || isFetching }), showCreate && (jsx(KeyCreateModal, { isOpen: showCreate, onClose: () => setShowCreate(false), platformKey: platformKey, labels: labels })), selectedKey && (jsx(KeyDetailModal, { isOpen: Boolean(selectedKey), onClose: () => setSelectedKey(null), platformKey: platformKey, ltiKey: selectedKey, labels: labels })), keyToDelete && (jsx(KeyDeleteModal, { isOpen: Boolean(keyToDelete), onClose: () => setKeyToDelete(null), platformKey: platformKey, ltiKey: keyToDelete, labels: labels }))] }));
262199
262217
  }
262200
262218
 
262201
262219
  function FieldError({ field, }) {
@@ -262260,7 +262278,11 @@ function ToolModal({ isOpen, onClose, platformKey, tool, labels }) {
262260
262278
  auth_token_url: value.auth_token_url,
262261
262279
  auth_audience: ((_a = value.auth_audience) === null || _a === void 0 ? void 0 : _a.trim()) ? value.auth_audience.trim() : null,
262262
262280
  key_set_url: value.key_set_mode === 'url' ? (_b = value.key_set_url) === null || _b === void 0 ? void 0 : _b.trim() : null,
262263
- key_set: value.key_set_mode === 'raw' ? JSON.parse(value.key_set) : null,
262281
+ // The backend serializer stores key_set as a JSON *string* and
262282
+ // rejects a parsed object with 400 "Not a valid string." — send the
262283
+ // raw textarea value (the field validator already guarantees it
262284
+ // parses as JSON).
262285
+ key_set: value.key_set_mode === 'raw' ? value.key_set.trim() : null,
262264
262286
  tool_key: Number(value.tool_key),
262265
262287
  deployment_ids: parseDeploymentIds(value.deployment_ids),
262266
262288
  platform_key: platformKey,
@@ -262322,13 +262344,15 @@ function ToolsSection({ identity, labels }) {
262322
262344
  const { platformKey, isReady } = identity;
262323
262345
  const [showCreate, setShowCreate] = React__default.useState(false);
262324
262346
  const [editingTool, setEditingTool] = React__default.useState(null);
262325
- const { data: toolsData, isLoading, isFetching, } = useGetLtiToolsQuery({ platformKey }, { skip: !isReady });
262347
+ const [page, setPage] = React__default.useState(1);
262348
+ const { data: toolsData, isLoading, isFetching, } = useGetLtiToolsQuery({ platformKey, page, pageSize: LTI_PAGE_SIZE }, { skip: !isReady });
262326
262349
  const tools = React__default.useMemo(() => toArray(toolsData), [toolsData]);
262350
+ const totalPages = getTotalPages(toolsData);
262327
262351
  const busy = !isReady || isLoading;
262328
262352
  return (jsxs("div", { className: "space-y-4", "data-testid": "lti-tools-section", children: [jsxs("div", { className: "flex flex-col items-start justify-between gap-3 sm:flex-row sm:items-center", children: [jsx("p", { className: "text-xs text-gray-600", children: labels.tools.description }), jsxs(Button$1, { onClick: () => setShowCreate(true), size: "sm", "data-testid": "lti-tool-create-button", className: "cursor-pointer whitespace-nowrap bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: [jsx(Plus, { className: "h-4 w-4" }), labels.tools.createButton] })] }), busy ? (jsx("div", { className: "flex w-full items-center justify-center py-10", children: jsx(Spinner, {}) })) : !tools || tools.length === 0 ? (jsxs("div", { className: "flex flex-col items-center justify-center gap-3 rounded-md border border-dashed border-gray-200 py-12 text-center", "data-testid": "lti-tools-empty", children: [jsx(Wrench, { className: "h-8 w-8 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm text-[#646464]", children: labels.tools.empty })] })) : (jsxs("div", { className: "overflow-hidden rounded-md border", children: [jsx("div", { className: "overflow-x-auto", children: jsxs(Table$1, { className: "min-w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { className: "bg-muted/50 border-b", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.common.nameColumn }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.tools.issuerColumn }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.tools.clientIdColumn }), jsx(TableHead, { className: "p-3 text-right text-sm whitespace-nowrap text-[#646464]", children: labels.common.actionsColumn })] }) }), jsx(TableBody, { children: tools.map((tool) => (jsxs(TableRow$1, { "data-testid": "lti-tool-row", className: "cursor-pointer border-b last:border-0 hover:bg-muted/40", onClick: () => setEditingTool(tool), children: [jsx(TableCell$1, { className: "p-3 text-sm font-medium text-gray-900", children: tool.title }), jsx(TableCell$1, { className: "max-w-[260px] truncate p-3 text-sm text-[#646464]", children: tool.issuer }), jsx(TableCell$1, { className: "max-w-[200px] truncate p-3 text-sm text-[#646464]", children: tool.client_id }), jsx(TableCell$1, { className: "p-3 text-right", children: jsx(Button$1, { type: "button", variant: "outline", size: "icon", "aria-label": labels.tools.editAria(tool.title), onClick: (event) => {
262329
262353
  event.stopPropagation();
262330
262354
  setEditingTool(tool);
262331
- }, children: jsx(Pencil, { className: "h-4 w-4" }) }) })] }, tool.id))) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), showCreate && (jsx(ToolModal, { isOpen: showCreate, onClose: () => setShowCreate(false), platformKey: platformKey, labels: labels })), editingTool && (jsx(ToolModal, { isOpen: Boolean(editingTool), onClose: () => setEditingTool(null), platformKey: platformKey, tool: editingTool, labels: labels }))] }));
262355
+ }, children: jsx(Pencil, { className: "h-4 w-4" }) }) })] }, tool.id))) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: busy || isFetching }), showCreate && (jsx(ToolModal, { isOpen: showCreate, onClose: () => setShowCreate(false), platformKey: platformKey, labels: labels })), editingTool && (jsx(ToolModal, { isOpen: Boolean(editingTool), onClose: () => setEditingTool(null), platformKey: platformKey, tool: editingTool, labels: labels }))] }));
262332
262356
  }
262333
262357
 
262334
262358
  function ToolEndpointsSection({ identity, labels, }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iblai/iblai-js",
3
- "version": "1.22.0",
3
+ "version": "1.22.2",
4
4
  "description": "Unified JavaScript SDK for IBL.ai — re-exports data-layer, web-containers, and web-utils under a single package",
5
5
  "type": "module",
6
6
  "engines": {
@@ -66,10 +66,10 @@
66
66
  "axios": "1.13.6",
67
67
  "dotenv": "16.6.1",
68
68
  "winston": "3.19.0",
69
- "@iblai/data-layer": "1.9.0",
69
+ "@iblai/data-layer": "1.9.1",
70
70
  "@iblai/mcp": "1.7.8",
71
- "@iblai/web-containers": "1.12.0",
72
- "@iblai/web-utils": "1.11.9"
71
+ "@iblai/web-containers": "1.12.1",
72
+ "@iblai/web-utils": "1.11.10"
73
73
  },
74
74
  "peerDependencies": {
75
75
  "@radix-ui/react-dialog": "^1.1.7",