@getcatalystiq/agent-plane-ui 0.1.12 → 0.1.13
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/chunk-HMB7OKXO.js +201 -0
- package/dist/chunk-TZGIXZON.cjs +242 -0
- package/dist/editor.cjs +551 -0
- package/dist/editor.d.cts +30 -1
- package/dist/editor.d.ts +30 -1
- package/dist/editor.js +545 -0
- package/dist/index.cjs +590 -458
- package/dist/index.d.cts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +306 -223
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -103,6 +103,18 @@ interface AgentPlaneClient {
|
|
|
103
103
|
get(marketplaceId: string): Promise<unknown>;
|
|
104
104
|
listPlugins(marketplaceId: string): Promise<unknown[]>;
|
|
105
105
|
getPlugin(marketplaceId: string, pluginName: string): Promise<unknown>;
|
|
106
|
+
getPluginFiles(marketplaceId: string, pluginName: string): Promise<unknown>;
|
|
107
|
+
savePluginFiles(marketplaceId: string, pluginName: string, data: {
|
|
108
|
+
skills: {
|
|
109
|
+
path: string;
|
|
110
|
+
content: string;
|
|
111
|
+
}[];
|
|
112
|
+
agents: {
|
|
113
|
+
path: string;
|
|
114
|
+
content: string;
|
|
115
|
+
}[];
|
|
116
|
+
mcpJson: string | null;
|
|
117
|
+
}): Promise<unknown>;
|
|
106
118
|
create(params: Record<string, unknown>): Promise<unknown>;
|
|
107
119
|
delete(marketplaceId: string): Promise<void>;
|
|
108
120
|
updateToken(marketplaceId: string, params: Record<string, unknown>): Promise<unknown>;
|
package/dist/index.d.ts
CHANGED
|
@@ -103,6 +103,18 @@ interface AgentPlaneClient {
|
|
|
103
103
|
get(marketplaceId: string): Promise<unknown>;
|
|
104
104
|
listPlugins(marketplaceId: string): Promise<unknown[]>;
|
|
105
105
|
getPlugin(marketplaceId: string, pluginName: string): Promise<unknown>;
|
|
106
|
+
getPluginFiles(marketplaceId: string, pluginName: string): Promise<unknown>;
|
|
107
|
+
savePluginFiles(marketplaceId: string, pluginName: string, data: {
|
|
108
|
+
skills: {
|
|
109
|
+
path: string;
|
|
110
|
+
content: string;
|
|
111
|
+
}[];
|
|
112
|
+
agents: {
|
|
113
|
+
path: string;
|
|
114
|
+
content: string;
|
|
115
|
+
}[];
|
|
116
|
+
mcpJson: string | null;
|
|
117
|
+
}): Promise<unknown>;
|
|
106
118
|
create(params: Record<string, unknown>): Promise<unknown>;
|
|
107
119
|
delete(marketplaceId: string): Promise<void>;
|
|
108
120
|
updateToken(marketplaceId: string, params: Record<string, unknown>): Promise<unknown>;
|
package/dist/index.js
CHANGED
|
@@ -1,202 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { cn, Card, CardHeader, CardTitle, CardContent, Button, Badge, useNavigation, useApi, Skeleton, useAgentPlaneClient, Input, supportsClaudeRunner, buttonVariants } from './chunk-HMB7OKXO.js';
|
|
2
|
+
export { AgentPlaneProvider, Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Input, Skeleton, badgeVariants, buttonVariants, cn, useAgentPlaneClient, useApi, useAuthError, useNavigation } from './chunk-HMB7OKXO.js';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { cva } from 'class-variance-authority';
|
|
4
|
+
import * as React3 from 'react';
|
|
5
|
+
import React3__default, { lazy, useState, useCallback, useMemo, useRef, useEffect, Suspense } from 'react';
|
|
6
|
+
import { useSWRConfig } from 'swr';
|
|
8
7
|
import ReactMarkdown from 'react-markdown';
|
|
9
8
|
import { Command } from 'cmdk';
|
|
10
9
|
import * as Popover from '@radix-ui/react-popover';
|
|
11
10
|
|
|
12
|
-
// src/provider.tsx
|
|
13
|
-
var ClientContext = createContext(null);
|
|
14
|
-
var NavigationContext = createContext(
|
|
15
|
-
null
|
|
16
|
-
);
|
|
17
|
-
function DefaultLink({ href, children, className }) {
|
|
18
|
-
return /* @__PURE__ */ jsx("a", { href, className, children });
|
|
19
|
-
}
|
|
20
|
-
function AgentPlaneProvider({
|
|
21
|
-
client,
|
|
22
|
-
onNavigate,
|
|
23
|
-
LinkComponent = DefaultLink,
|
|
24
|
-
onAuthError,
|
|
25
|
-
basePath = "",
|
|
26
|
-
children
|
|
27
|
-
}) {
|
|
28
|
-
const clientRef = useRef(client);
|
|
29
|
-
clientRef.current = client;
|
|
30
|
-
const onAuthErrorRef = useRef(onAuthError);
|
|
31
|
-
onAuthErrorRef.current = onAuthError;
|
|
32
|
-
const clientValue = useMemo(
|
|
33
|
-
() => ({
|
|
34
|
-
// Expose a stable object whose `.client` always points to the latest ref.
|
|
35
|
-
get client() {
|
|
36
|
-
return clientRef.current;
|
|
37
|
-
},
|
|
38
|
-
get onAuthError() {
|
|
39
|
-
return onAuthErrorRef.current;
|
|
40
|
-
}
|
|
41
|
-
}),
|
|
42
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps -- intentionally stable
|
|
43
|
-
[]
|
|
44
|
-
);
|
|
45
|
-
const navigationValue = useMemo(
|
|
46
|
-
() => ({
|
|
47
|
-
onNavigate,
|
|
48
|
-
LinkComponent,
|
|
49
|
-
basePath
|
|
50
|
-
}),
|
|
51
|
-
[onNavigate, LinkComponent, basePath]
|
|
52
|
-
);
|
|
53
|
-
return /* @__PURE__ */ jsx(ClientContext.Provider, { value: clientValue, children: /* @__PURE__ */ jsx(NavigationContext.Provider, { value: navigationValue, children }) });
|
|
54
|
-
}
|
|
55
|
-
function useAgentPlaneClient() {
|
|
56
|
-
const ctx = useContext(ClientContext);
|
|
57
|
-
if (!ctx) {
|
|
58
|
-
throw new Error(
|
|
59
|
-
"useAgentPlaneClient must be used within an <AgentPlaneProvider>"
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
return ctx.client;
|
|
63
|
-
}
|
|
64
|
-
function useAuthError() {
|
|
65
|
-
const ctx = useContext(ClientContext);
|
|
66
|
-
if (!ctx) {
|
|
67
|
-
throw new Error(
|
|
68
|
-
"useAuthError must be used within an <AgentPlaneProvider>"
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
return ctx.onAuthError;
|
|
72
|
-
}
|
|
73
|
-
function useNavigation() {
|
|
74
|
-
const ctx = useContext(NavigationContext);
|
|
75
|
-
if (!ctx) {
|
|
76
|
-
throw new Error(
|
|
77
|
-
"useNavigation must be used within an <AgentPlaneProvider>"
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
return ctx;
|
|
81
|
-
}
|
|
82
|
-
function useApi(key, fetcher, options) {
|
|
83
|
-
const client = useAgentPlaneClient();
|
|
84
|
-
const onAuthError = useAuthError();
|
|
85
|
-
return useSWR(
|
|
86
|
-
key,
|
|
87
|
-
() => fetcher(client),
|
|
88
|
-
{
|
|
89
|
-
revalidateOnFocus: false,
|
|
90
|
-
errorRetryCount: 3,
|
|
91
|
-
onError: (err) => {
|
|
92
|
-
if (onAuthError && err && typeof err === "object" && "status" in err && err.status === 401) {
|
|
93
|
-
onAuthError(err instanceof Error ? err : new Error(String(err)));
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
...options
|
|
97
|
-
}
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
function cn(...inputs) {
|
|
101
|
-
return twMerge(clsx(inputs));
|
|
102
|
-
}
|
|
103
|
-
function supportsClaudeRunner(model) {
|
|
104
|
-
return !model.includes("/") || model.startsWith("anthropic/");
|
|
105
|
-
}
|
|
106
|
-
var buttonVariants = cva(
|
|
107
|
-
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
108
|
-
{
|
|
109
|
-
variants: {
|
|
110
|
-
variant: {
|
|
111
|
-
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
112
|
-
destructive: "bg-destructive text-white shadow-sm hover:bg-destructive/90",
|
|
113
|
-
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
114
|
-
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
115
|
-
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
116
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
117
|
-
},
|
|
118
|
-
size: {
|
|
119
|
-
default: "h-9 px-4 py-2",
|
|
120
|
-
sm: "h-8 rounded-md px-3 text-xs",
|
|
121
|
-
lg: "h-10 rounded-md px-8",
|
|
122
|
-
icon: "h-9 w-9"
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
defaultVariants: {
|
|
126
|
-
variant: "default",
|
|
127
|
-
size: "default"
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
);
|
|
131
|
-
var Button = React3.forwardRef(
|
|
132
|
-
({ className, variant, size, ...props }, ref) => {
|
|
133
|
-
return /* @__PURE__ */ jsx(
|
|
134
|
-
"button",
|
|
135
|
-
{
|
|
136
|
-
className: cn(buttonVariants({ variant, size, className })),
|
|
137
|
-
ref,
|
|
138
|
-
...props
|
|
139
|
-
}
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
);
|
|
143
|
-
Button.displayName = "Button";
|
|
144
|
-
var Card = React3.forwardRef(
|
|
145
|
-
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("rounded-xl border bg-card text-card-foreground shadow", className), ...props })
|
|
146
|
-
);
|
|
147
|
-
Card.displayName = "Card";
|
|
148
|
-
var CardHeader = React3.forwardRef(
|
|
149
|
-
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("flex flex-col space-y-1.5 p-6", className), ...props })
|
|
150
|
-
);
|
|
151
|
-
CardHeader.displayName = "CardHeader";
|
|
152
|
-
var CardTitle = React3.forwardRef(
|
|
153
|
-
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("font-semibold leading-none tracking-tight", className), ...props })
|
|
154
|
-
);
|
|
155
|
-
CardTitle.displayName = "CardTitle";
|
|
156
|
-
var CardDescription = React3.forwardRef(
|
|
157
|
-
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("text-sm text-muted-foreground", className), ...props })
|
|
158
|
-
);
|
|
159
|
-
CardDescription.displayName = "CardDescription";
|
|
160
|
-
var CardContent = React3.forwardRef(
|
|
161
|
-
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props })
|
|
162
|
-
);
|
|
163
|
-
CardContent.displayName = "CardContent";
|
|
164
|
-
var badgeVariants = cva(
|
|
165
|
-
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
166
|
-
{
|
|
167
|
-
variants: {
|
|
168
|
-
variant: {
|
|
169
|
-
default: "border-transparent bg-primary text-primary-foreground shadow",
|
|
170
|
-
secondary: "border-transparent bg-secondary text-secondary-foreground",
|
|
171
|
-
destructive: "border-transparent bg-destructive text-white shadow",
|
|
172
|
-
outline: "text-foreground"
|
|
173
|
-
}
|
|
174
|
-
},
|
|
175
|
-
defaultVariants: {
|
|
176
|
-
variant: "default"
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
);
|
|
180
|
-
function Badge({ className, variant, ...props }) {
|
|
181
|
-
return /* @__PURE__ */ jsx("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
182
|
-
}
|
|
183
|
-
var Input = React3.forwardRef(
|
|
184
|
-
({ className, type, ...props }, ref) => {
|
|
185
|
-
return /* @__PURE__ */ jsx(
|
|
186
|
-
"input",
|
|
187
|
-
{
|
|
188
|
-
type,
|
|
189
|
-
className: cn(
|
|
190
|
-
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
|
|
191
|
-
className
|
|
192
|
-
),
|
|
193
|
-
ref,
|
|
194
|
-
...props
|
|
195
|
-
}
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
);
|
|
199
|
-
Input.displayName = "Input";
|
|
200
11
|
function Select({ className = "", ...props }) {
|
|
201
12
|
return /* @__PURE__ */ jsxs("div", { className: "relative w-full", children: [
|
|
202
13
|
/* @__PURE__ */ jsx(
|
|
@@ -265,9 +76,6 @@ function DetailPageHeader({ backHref, backLabel, title, actions, badge, subtitle
|
|
|
265
76
|
subtitle && /* @__PURE__ */ jsx("div", { className: "mt-1", children: subtitle })
|
|
266
77
|
] });
|
|
267
78
|
}
|
|
268
|
-
function Skeleton({ className, ...props }) {
|
|
269
|
-
return /* @__PURE__ */ jsx("div", { className: cn("animate-pulse rounded-md bg-muted/50", className), ...props });
|
|
270
|
-
}
|
|
271
79
|
function MetricCard({ label, children, className }) {
|
|
272
80
|
return /* @__PURE__ */ jsxs(Card, { className, children: [
|
|
273
81
|
/* @__PURE__ */ jsx(CardHeader, { className: "pb-2", children: /* @__PURE__ */ jsx(CardTitle, { className: "text-sm font-medium text-muted-foreground", children: label }) }),
|
|
@@ -1523,46 +1331,248 @@ function PluginMarketplaceDetailPage({ marketplaceId, initialData, initialPlugin
|
|
|
1523
1331
|
] })
|
|
1524
1332
|
] });
|
|
1525
1333
|
}
|
|
1526
|
-
function AgentsTab({
|
|
1334
|
+
function AgentsTab({
|
|
1335
|
+
agents,
|
|
1336
|
+
onSelectAgent,
|
|
1337
|
+
selectedFilename
|
|
1338
|
+
}) {
|
|
1527
1339
|
if (agents.length === 0) {
|
|
1528
1340
|
return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground py-4", children: "No agents defined in this plugin." });
|
|
1529
1341
|
}
|
|
1530
|
-
return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: agents.map((agent) => /* @__PURE__ */ jsxs(
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1342
|
+
return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: agents.map((agent) => /* @__PURE__ */ jsxs(
|
|
1343
|
+
Card,
|
|
1344
|
+
{
|
|
1345
|
+
className: `cursor-pointer transition-colors hover:border-primary/50 ${selectedFilename === agent.filename ? "border-primary ring-1 ring-primary/30" : ""}`,
|
|
1346
|
+
onClick: () => onSelectAgent(agent.filename),
|
|
1347
|
+
children: [
|
|
1348
|
+
/* @__PURE__ */ jsx(CardHeader, { className: "pb-2", children: /* @__PURE__ */ jsx(CardTitle, { className: "text-sm font-medium", children: agent.name }) }),
|
|
1349
|
+
/* @__PURE__ */ jsxs(CardContent, { children: [
|
|
1350
|
+
agent.description ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: agent.description }) : /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground italic", children: "No description" }),
|
|
1351
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground/60 mt-2 font-mono", children: agent.filename })
|
|
1352
|
+
] })
|
|
1353
|
+
]
|
|
1354
|
+
},
|
|
1355
|
+
agent.filename
|
|
1356
|
+
)) });
|
|
1537
1357
|
}
|
|
1538
|
-
function SkillsTab({
|
|
1358
|
+
function SkillsTab({
|
|
1359
|
+
skills,
|
|
1360
|
+
onSelectSkill,
|
|
1361
|
+
selectedSkill
|
|
1362
|
+
}) {
|
|
1539
1363
|
if (skills.length === 0) {
|
|
1540
1364
|
return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground py-4", children: "No skills defined in this plugin." });
|
|
1541
1365
|
}
|
|
1542
|
-
return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: skills.map((skill) => /* @__PURE__ */ jsxs(
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
"
|
|
1546
|
-
skill,
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1366
|
+
return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: skills.map((skill) => /* @__PURE__ */ jsxs(
|
|
1367
|
+
Card,
|
|
1368
|
+
{
|
|
1369
|
+
className: `cursor-pointer transition-colors hover:border-primary/50 ${selectedSkill === skill ? "border-primary ring-1 ring-primary/30" : ""}`,
|
|
1370
|
+
onClick: () => onSelectSkill(skill),
|
|
1371
|
+
children: [
|
|
1372
|
+
/* @__PURE__ */ jsx(CardHeader, { className: "pb-2", children: /* @__PURE__ */ jsx(CardTitle, { className: "text-sm font-medium", children: skill }) }),
|
|
1373
|
+
/* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground font-mono", children: [
|
|
1374
|
+
"skills/",
|
|
1375
|
+
skill,
|
|
1376
|
+
"/"
|
|
1377
|
+
] }) })
|
|
1378
|
+
]
|
|
1379
|
+
},
|
|
1380
|
+
skill
|
|
1381
|
+
)) });
|
|
1550
1382
|
}
|
|
1551
|
-
function ConnectorsTab({
|
|
1383
|
+
function ConnectorsTab({
|
|
1384
|
+
hasMcpJson,
|
|
1385
|
+
mcpJsonContent,
|
|
1386
|
+
onSelectConnector,
|
|
1387
|
+
selected
|
|
1388
|
+
}) {
|
|
1552
1389
|
if (!hasMcpJson) {
|
|
1553
1390
|
return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground py-4", children: "No connectors defined in this plugin." });
|
|
1554
1391
|
}
|
|
1555
|
-
return /* @__PURE__ */ jsxs(
|
|
1556
|
-
|
|
1557
|
-
|
|
1392
|
+
return /* @__PURE__ */ jsxs(
|
|
1393
|
+
Card,
|
|
1394
|
+
{
|
|
1395
|
+
className: `cursor-pointer transition-colors hover:border-primary/50 ${selected ? "border-primary ring-1 ring-primary/30" : ""}`,
|
|
1396
|
+
onClick: onSelectConnector,
|
|
1397
|
+
children: [
|
|
1398
|
+
/* @__PURE__ */ jsx(CardHeader, { className: "pb-2", children: /* @__PURE__ */ jsx(CardTitle, { className: "text-sm font-medium", children: ".mcp.json" }) }),
|
|
1399
|
+
/* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "This plugin includes an MCP connector configuration that will be suggested to agents using it." }) })
|
|
1400
|
+
]
|
|
1401
|
+
}
|
|
1402
|
+
);
|
|
1403
|
+
}
|
|
1404
|
+
function FileEditorInline({
|
|
1405
|
+
filePath,
|
|
1406
|
+
content,
|
|
1407
|
+
onChange,
|
|
1408
|
+
onSave,
|
|
1409
|
+
onClose,
|
|
1410
|
+
saving,
|
|
1411
|
+
saveError,
|
|
1412
|
+
saveSuccess,
|
|
1413
|
+
readOnly
|
|
1414
|
+
}) {
|
|
1415
|
+
return /* @__PURE__ */ jsxs("div", { className: "mt-4 border border-border rounded-md overflow-hidden", children: [
|
|
1416
|
+
/* @__PURE__ */ jsxs("div", { className: "px-3 py-2 bg-muted/50 border-b border-border flex items-center justify-between", children: [
|
|
1417
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground font-mono", children: filePath }),
|
|
1418
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1419
|
+
saveError && /* @__PURE__ */ jsx("span", { className: "text-xs text-destructive", children: saveError }),
|
|
1420
|
+
saveSuccess && /* @__PURE__ */ jsx("span", { className: "text-xs text-green-500", children: saveSuccess }),
|
|
1421
|
+
!readOnly && /* @__PURE__ */ jsx(Button, { size: "sm", onClick: onSave, disabled: saving, className: "h-7 text-xs", children: saving ? "Saving..." : "Save" }),
|
|
1422
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", onClick: onClose, className: "h-7 text-xs", children: "Close" })
|
|
1423
|
+
] })
|
|
1424
|
+
] }),
|
|
1425
|
+
/* @__PURE__ */ jsx(
|
|
1426
|
+
"textarea",
|
|
1427
|
+
{
|
|
1428
|
+
value: content,
|
|
1429
|
+
onChange: (e) => onChange(e.target.value),
|
|
1430
|
+
readOnly,
|
|
1431
|
+
className: "w-full min-h-[400px] p-3 bg-background text-foreground text-sm font-mono resize-y focus:outline-none",
|
|
1432
|
+
spellCheck: false
|
|
1433
|
+
}
|
|
1434
|
+
)
|
|
1558
1435
|
] });
|
|
1559
1436
|
}
|
|
1560
1437
|
function PluginDetailPage({ marketplaceId, pluginName }) {
|
|
1561
1438
|
const { LinkComponent, basePath } = useNavigation();
|
|
1439
|
+
const client = useAgentPlaneClient();
|
|
1562
1440
|
const { data: plugin, error, isLoading } = useApi(
|
|
1563
1441
|
`marketplace-${marketplaceId}-plugin-${pluginName}`,
|
|
1564
1442
|
(c) => c.pluginMarketplaces.getPlugin(marketplaceId, pluginName)
|
|
1565
1443
|
);
|
|
1444
|
+
const [editorState, setEditorState] = useState(null);
|
|
1445
|
+
const [pluginFiles, setPluginFiles] = useState(null);
|
|
1446
|
+
const [filesLoading, setFilesLoading] = useState(false);
|
|
1447
|
+
const [filesError, setFilesError] = useState("");
|
|
1448
|
+
const [editedContent, setEditedContent] = useState(/* @__PURE__ */ new Map());
|
|
1449
|
+
const [saving, setSaving] = useState(false);
|
|
1450
|
+
const [saveError, setSaveError] = useState("");
|
|
1451
|
+
const [saveSuccess, setSaveSuccess] = useState("");
|
|
1452
|
+
const fetchFiles = useCallback(async () => {
|
|
1453
|
+
if (pluginFiles) return pluginFiles;
|
|
1454
|
+
setFilesLoading(true);
|
|
1455
|
+
setFilesError("");
|
|
1456
|
+
try {
|
|
1457
|
+
const files = await client.pluginMarketplaces.getPluginFiles(marketplaceId, pluginName);
|
|
1458
|
+
setPluginFiles(files);
|
|
1459
|
+
return files;
|
|
1460
|
+
} catch (err) {
|
|
1461
|
+
setFilesError(err instanceof Error ? err.message : "Failed to load files");
|
|
1462
|
+
return null;
|
|
1463
|
+
} finally {
|
|
1464
|
+
setFilesLoading(false);
|
|
1465
|
+
}
|
|
1466
|
+
}, [client, marketplaceId, pluginName, pluginFiles]);
|
|
1467
|
+
const handleSelectAgent = useCallback(async (filename) => {
|
|
1468
|
+
if (editorState?.type === "agent" && editorState.identifier === filename) {
|
|
1469
|
+
setEditorState(null);
|
|
1470
|
+
return;
|
|
1471
|
+
}
|
|
1472
|
+
setSaveError("");
|
|
1473
|
+
setSaveSuccess("");
|
|
1474
|
+
const files = await fetchFiles();
|
|
1475
|
+
if (files) {
|
|
1476
|
+
setEditorState({ type: "agent", identifier: filename });
|
|
1477
|
+
}
|
|
1478
|
+
}, [editorState, fetchFiles]);
|
|
1479
|
+
const handleSelectSkill = useCallback(async (skill) => {
|
|
1480
|
+
if (editorState?.type === "skill" && editorState.identifier === skill) {
|
|
1481
|
+
setEditorState(null);
|
|
1482
|
+
return;
|
|
1483
|
+
}
|
|
1484
|
+
setSaveError("");
|
|
1485
|
+
setSaveSuccess("");
|
|
1486
|
+
const files = await fetchFiles();
|
|
1487
|
+
if (files) {
|
|
1488
|
+
setEditorState({ type: "skill", identifier: skill });
|
|
1489
|
+
}
|
|
1490
|
+
}, [editorState, fetchFiles]);
|
|
1491
|
+
const handleSelectConnector = useCallback(async () => {
|
|
1492
|
+
if (editorState?.type === "connector") {
|
|
1493
|
+
setEditorState(null);
|
|
1494
|
+
return;
|
|
1495
|
+
}
|
|
1496
|
+
setSaveError("");
|
|
1497
|
+
setSaveSuccess("");
|
|
1498
|
+
const files = await fetchFiles();
|
|
1499
|
+
if (files) {
|
|
1500
|
+
setEditorState({ type: "connector", identifier: ".mcp.json" });
|
|
1501
|
+
}
|
|
1502
|
+
}, [editorState, fetchFiles]);
|
|
1503
|
+
function getEditorFile() {
|
|
1504
|
+
if (!editorState || !pluginFiles) return null;
|
|
1505
|
+
if (editorState.type === "agent") {
|
|
1506
|
+
const file = pluginFiles.agents.find((f) => f.path === editorState.identifier);
|
|
1507
|
+
if (!file) return null;
|
|
1508
|
+
const editedKey = `agents/${file.path}`;
|
|
1509
|
+
return {
|
|
1510
|
+
path: `agents/${file.path}`,
|
|
1511
|
+
content: editedContent.has(editedKey) ? editedContent.get(editedKey) : file.content
|
|
1512
|
+
};
|
|
1513
|
+
}
|
|
1514
|
+
if (editorState.type === "skill") {
|
|
1515
|
+
const skillFiles = pluginFiles.skills.filter((f) => f.path.startsWith(editorState.identifier + "/") || f.path === editorState.identifier);
|
|
1516
|
+
const file = skillFiles.length > 0 ? skillFiles[0] : null;
|
|
1517
|
+
if (!file) return null;
|
|
1518
|
+
const editedKey = `skills/${file.path}`;
|
|
1519
|
+
return {
|
|
1520
|
+
path: `skills/${file.path}`,
|
|
1521
|
+
content: editedContent.has(editedKey) ? editedContent.get(editedKey) : file.content
|
|
1522
|
+
};
|
|
1523
|
+
}
|
|
1524
|
+
if (editorState.type === "connector") {
|
|
1525
|
+
const editedKey = ".mcp.json";
|
|
1526
|
+
return {
|
|
1527
|
+
path: ".mcp.json",
|
|
1528
|
+
content: editedContent.has(editedKey) ? editedContent.get(editedKey) : pluginFiles.mcpJson ?? ""
|
|
1529
|
+
};
|
|
1530
|
+
}
|
|
1531
|
+
return null;
|
|
1532
|
+
}
|
|
1533
|
+
function handleContentChange(content) {
|
|
1534
|
+
const file = getEditorFile();
|
|
1535
|
+
if (!file) return;
|
|
1536
|
+
setEditedContent((prev) => new Map(prev).set(file.path, content));
|
|
1537
|
+
}
|
|
1538
|
+
async function handleSave() {
|
|
1539
|
+
if (!pluginFiles) return;
|
|
1540
|
+
setSaving(true);
|
|
1541
|
+
setSaveError("");
|
|
1542
|
+
setSaveSuccess("");
|
|
1543
|
+
const updatedSkills = pluginFiles.skills.map((f) => {
|
|
1544
|
+
const key = `skills/${f.path}`;
|
|
1545
|
+
return editedContent.has(key) ? { ...f, content: editedContent.get(key) } : f;
|
|
1546
|
+
});
|
|
1547
|
+
const updatedAgents = pluginFiles.agents.map((f) => {
|
|
1548
|
+
const key = `agents/${f.path}`;
|
|
1549
|
+
return editedContent.has(key) ? { ...f, content: editedContent.get(key) } : f;
|
|
1550
|
+
});
|
|
1551
|
+
const updatedMcpJson = editedContent.has(".mcp.json") ? editedContent.get(".mcp.json") : pluginFiles.mcpJson;
|
|
1552
|
+
try {
|
|
1553
|
+
const result = await client.pluginMarketplaces.savePluginFiles(
|
|
1554
|
+
marketplaceId,
|
|
1555
|
+
pluginName,
|
|
1556
|
+
{
|
|
1557
|
+
skills: updatedSkills,
|
|
1558
|
+
agents: updatedAgents,
|
|
1559
|
+
mcpJson: updatedMcpJson || null
|
|
1560
|
+
}
|
|
1561
|
+
);
|
|
1562
|
+
setPluginFiles({
|
|
1563
|
+
...pluginFiles,
|
|
1564
|
+
skills: updatedSkills,
|
|
1565
|
+
agents: updatedAgents,
|
|
1566
|
+
mcpJson: updatedMcpJson ?? null
|
|
1567
|
+
});
|
|
1568
|
+
setEditedContent(/* @__PURE__ */ new Map());
|
|
1569
|
+
setSaveSuccess(`Saved (commit ${result.commitSha.slice(0, 7)})`);
|
|
1570
|
+
} catch (err) {
|
|
1571
|
+
setSaveError(err instanceof Error ? err.message : "Failed to save");
|
|
1572
|
+
} finally {
|
|
1573
|
+
setSaving(false);
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1566
1576
|
if (error) {
|
|
1567
1577
|
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-[40vh]", children: /* @__PURE__ */ jsxs("p", { className: "text-destructive", children: [
|
|
1568
1578
|
"Failed to load plugin: ",
|
|
@@ -1576,18 +1586,90 @@ function PluginDetailPage({ marketplaceId, pluginName }) {
|
|
|
1576
1586
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-64 rounded-lg" })
|
|
1577
1587
|
] });
|
|
1578
1588
|
}
|
|
1589
|
+
const readOnly = pluginFiles ? !pluginFiles.isOwned : true;
|
|
1590
|
+
const editorFile = getEditorFile();
|
|
1579
1591
|
const tabs = [
|
|
1580
1592
|
{
|
|
1581
1593
|
label: `Agents (${plugin.agents.length})`,
|
|
1582
|
-
content: /* @__PURE__ */
|
|
1594
|
+
content: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1595
|
+
/* @__PURE__ */ jsx(
|
|
1596
|
+
AgentsTab,
|
|
1597
|
+
{
|
|
1598
|
+
agents: plugin.agents,
|
|
1599
|
+
onSelectAgent: handleSelectAgent,
|
|
1600
|
+
selectedFilename: editorState?.type === "agent" ? editorState.identifier : null
|
|
1601
|
+
}
|
|
1602
|
+
),
|
|
1603
|
+
editorState?.type === "agent" && editorFile && (filesLoading ? /* @__PURE__ */ jsx("div", { className: "mt-4", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[400px] rounded-md" }) }) : filesError ? /* @__PURE__ */ jsx("p", { className: "mt-4 text-sm text-destructive", children: filesError }) : /* @__PURE__ */ jsx(
|
|
1604
|
+
FileEditorInline,
|
|
1605
|
+
{
|
|
1606
|
+
filePath: editorFile.path,
|
|
1607
|
+
content: editorFile.content,
|
|
1608
|
+
onChange: handleContentChange,
|
|
1609
|
+
onSave: handleSave,
|
|
1610
|
+
onClose: () => setEditorState(null),
|
|
1611
|
+
saving,
|
|
1612
|
+
saveError,
|
|
1613
|
+
saveSuccess,
|
|
1614
|
+
readOnly
|
|
1615
|
+
}
|
|
1616
|
+
))
|
|
1617
|
+
] })
|
|
1583
1618
|
},
|
|
1584
1619
|
{
|
|
1585
1620
|
label: `Skills (${plugin.skills.length})`,
|
|
1586
|
-
content: /* @__PURE__ */
|
|
1621
|
+
content: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1622
|
+
/* @__PURE__ */ jsx(
|
|
1623
|
+
SkillsTab,
|
|
1624
|
+
{
|
|
1625
|
+
skills: plugin.skills,
|
|
1626
|
+
onSelectSkill: handleSelectSkill,
|
|
1627
|
+
selectedSkill: editorState?.type === "skill" ? editorState.identifier : null
|
|
1628
|
+
}
|
|
1629
|
+
),
|
|
1630
|
+
editorState?.type === "skill" && editorFile && (filesLoading ? /* @__PURE__ */ jsx("div", { className: "mt-4", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[400px] rounded-md" }) }) : filesError ? /* @__PURE__ */ jsx("p", { className: "mt-4 text-sm text-destructive", children: filesError }) : /* @__PURE__ */ jsx(
|
|
1631
|
+
FileEditorInline,
|
|
1632
|
+
{
|
|
1633
|
+
filePath: editorFile.path,
|
|
1634
|
+
content: editorFile.content,
|
|
1635
|
+
onChange: handleContentChange,
|
|
1636
|
+
onSave: handleSave,
|
|
1637
|
+
onClose: () => setEditorState(null),
|
|
1638
|
+
saving,
|
|
1639
|
+
saveError,
|
|
1640
|
+
saveSuccess,
|
|
1641
|
+
readOnly
|
|
1642
|
+
}
|
|
1643
|
+
))
|
|
1644
|
+
] })
|
|
1587
1645
|
},
|
|
1588
1646
|
{
|
|
1589
1647
|
label: `Connectors (${plugin.hasMcpJson ? 1 : 0})`,
|
|
1590
|
-
content: /* @__PURE__ */
|
|
1648
|
+
content: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1649
|
+
/* @__PURE__ */ jsx(
|
|
1650
|
+
ConnectorsTab,
|
|
1651
|
+
{
|
|
1652
|
+
hasMcpJson: plugin.hasMcpJson,
|
|
1653
|
+
mcpJsonContent: pluginFiles?.mcpJson ?? null,
|
|
1654
|
+
onSelectConnector: handleSelectConnector,
|
|
1655
|
+
selected: editorState?.type === "connector"
|
|
1656
|
+
}
|
|
1657
|
+
),
|
|
1658
|
+
editorState?.type === "connector" && editorFile && (filesLoading ? /* @__PURE__ */ jsx("div", { className: "mt-4", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[400px] rounded-md" }) }) : filesError ? /* @__PURE__ */ jsx("p", { className: "mt-4 text-sm text-destructive", children: filesError }) : /* @__PURE__ */ jsx(
|
|
1659
|
+
FileEditorInline,
|
|
1660
|
+
{
|
|
1661
|
+
filePath: editorFile.path,
|
|
1662
|
+
content: editorFile.content,
|
|
1663
|
+
onChange: handleContentChange,
|
|
1664
|
+
onSave: handleSave,
|
|
1665
|
+
onClose: () => setEditorState(null),
|
|
1666
|
+
saving,
|
|
1667
|
+
saveError,
|
|
1668
|
+
saveSuccess,
|
|
1669
|
+
readOnly
|
|
1670
|
+
}
|
|
1671
|
+
))
|
|
1672
|
+
] })
|
|
1591
1673
|
}
|
|
1592
1674
|
];
|
|
1593
1675
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
@@ -1605,7 +1687,8 @@ function PluginDetailPage({ marketplaceId, pluginName }) {
|
|
|
1605
1687
|
plugin.version && /* @__PURE__ */ jsxs(Badge, { variant: "outline", children: [
|
|
1606
1688
|
"v",
|
|
1607
1689
|
plugin.version
|
|
1608
|
-
] })
|
|
1690
|
+
] }),
|
|
1691
|
+
pluginFiles && (pluginFiles.isOwned ? /* @__PURE__ */ jsx(Badge, { variant: "secondary", children: "Editable" }) : /* @__PURE__ */ jsx(Badge, { variant: "outline", children: "Read-only" }))
|
|
1609
1692
|
] }),
|
|
1610
1693
|
plugin.description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: plugin.description })
|
|
1611
1694
|
] }),
|
|
@@ -4288,4 +4371,4 @@ function ScheduleCard({
|
|
|
4288
4371
|
] });
|
|
4289
4372
|
}
|
|
4290
4373
|
|
|
4291
|
-
export { AdminTable, AdminTableHead, AdminTableRow, AgentA2aInfo, AgentConnectorsManager, AgentDetailPage, AgentEditForm, AgentListPage,
|
|
4374
|
+
export { AdminTable, AdminTableHead, AdminTableRow, AgentA2aInfo, AgentConnectorsManager, AgentDetailPage, AgentEditForm, AgentListPage, AgentPluginManager, AgentRuns, AgentScheduleForm, AgentSkillManager, ConfirmDialog, CopyButton, DashboardPage, DetailPageHeader, Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, EmptyRow, FormError, FormField, LocalDate, McpServerListPage, MetricCard, ModelSelector, PaginationBar, PluginDetailPage, PluginMarketplaceDetailPage, PluginMarketplaceListPage, RunDetailPage, RunListPage, RunSourceBadge, RunStatusBadge, SectionHeader, Select, SettingsPage, Tabs, Textarea, Th, ToolkitMultiselect, TranscriptViewer, parsePaginationParams };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getcatalystiq/agent-plane-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "Embeddable React component library for AgentPlane",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"@codemirror/lang-json": "^6.0.0",
|
|
56
56
|
"@codemirror/lang-markdown": "^6.0.0",
|
|
57
57
|
"@codemirror/theme-one-dark": "^6.0.0",
|
|
58
|
-
"@getcatalystiq/agent-plane": "^0.5.
|
|
58
|
+
"@getcatalystiq/agent-plane": "^0.5.10",
|
|
59
59
|
"@uiw/react-codemirror": "^4.0.0",
|
|
60
60
|
"react": "^18.0.0 || ^19.0.0",
|
|
61
61
|
"react-dom": "^18.0.0 || ^19.0.0",
|