@korso/shepherd-ui 0.4.0 → 0.5.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/LICENSE +661 -0
- package/dist/client.d.ts +6 -0
- package/dist/client.js +14 -0
- package/dist/config/ConfigPanel.js +1 -1
- package/dist/config/ConnectAgent.d.ts +1 -2
- package/dist/config/ConnectAgent.js +6 -12
- package/dist/lib/{Dashboard-CTXdGRxM.js → Dashboard-C48qY8R2.js} +123 -109
- package/dist/lib/index.d.ts +7 -2
- package/dist/lib/index.js +233 -235
- package/dist/lib/selfhost.js +1 -1
- package/dist/preview.js +12 -0
- package/dist/selfhost/assets/{index-BSnsUIT-.js → index-adPvx18g.js} +8 -8
- package/dist/selfhost/index.html +1 -1
- package/dist/test/mockClient.js +3 -0
- package/package.json +2 -2
package/dist/client.js
CHANGED
|
@@ -177,6 +177,20 @@ export function createShepherdClient(config) {
|
|
|
177
177
|
revokeToken(workspaceId, tokenId) {
|
|
178
178
|
return request("DELETE", `/workspaces/${enc(workspaceId)}/tokens/${enc(tokenId)}`);
|
|
179
179
|
},
|
|
180
|
+
mintAccountToken(body) {
|
|
181
|
+
return request("POST", "/tokens", {
|
|
182
|
+
body,
|
|
183
|
+
schema: MintTokenResponse,
|
|
184
|
+
});
|
|
185
|
+
},
|
|
186
|
+
listAccountTokens() {
|
|
187
|
+
return request("GET", "/tokens", {
|
|
188
|
+
schema: ListTokensResponse,
|
|
189
|
+
});
|
|
190
|
+
},
|
|
191
|
+
revokeAccountToken(id) {
|
|
192
|
+
return request("DELETE", `/tokens/${enc(id)}`);
|
|
193
|
+
},
|
|
180
194
|
createInvite(workspaceId, body) {
|
|
181
195
|
return request("POST", `/workspaces/${enc(workspaceId)}/invites`, {
|
|
182
196
|
body,
|
|
@@ -12,5 +12,5 @@ const SECTIONS = [
|
|
|
12
12
|
export function ConfigPanel({ workspace, hubUrl, membersRefreshKey, onMembersChanged, onLeft, }) {
|
|
13
13
|
const [section, setSection] = useState("general");
|
|
14
14
|
const isAdmin = workspace.role === "admin";
|
|
15
|
-
return (_jsxs("div", { className: "config-layout", children: [_jsx("nav", { className: "config-nav", "aria-label": "Configuration sections", children: SECTIONS.map(({ id, label }) => (_jsx("button", { type: "button", className: "config-nav__item" + (section === id ? " config-nav__item--on" : ""), "aria-current": section === id ? "page" : undefined, onClick: () => setSection(id), children: label }, id))) }), _jsxs("div", { className: "config-panel", children: [section === "general" && (_jsx(GeneralSettings, { workspace: workspace, onLeft: onLeft })), section === "members" && (_jsxs(_Fragment, { children: [_jsx(Members, { workspaceId: workspace.id, refreshKey: membersRefreshKey, canRemove: isAdmin }), isAdmin && (_jsx(Invites, { workspaceId: workspace.id, onMembersChanged: onMembersChanged }))] })), section === "agent" && _jsx(ConnectAgent, {
|
|
15
|
+
return (_jsxs("div", { className: "config-layout", children: [_jsx("nav", { className: "config-nav", "aria-label": "Configuration sections", children: SECTIONS.map(({ id, label }) => (_jsx("button", { type: "button", className: "config-nav__item" + (section === id ? " config-nav__item--on" : ""), "aria-current": section === id ? "page" : undefined, onClick: () => setSection(id), children: label }, id))) }), _jsxs("div", { className: "config-panel", children: [section === "general" && (_jsx(GeneralSettings, { workspace: workspace, onLeft: onLeft })), section === "members" && (_jsxs(_Fragment, { children: [_jsx(Members, { workspaceId: workspace.id, refreshKey: membersRefreshKey, canRemove: isAdmin }), isAdmin && (_jsx(Invites, { workspaceId: workspace.id, onMembersChanged: onMembersChanged }))] })), section === "agent" && _jsx(ConnectAgent, { hubUrl: hubUrl })] })] }));
|
|
16
16
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export interface ConnectAgentProps {
|
|
2
|
-
workspaceId: string;
|
|
3
2
|
/**
|
|
4
3
|
* The DIRECT Hub URL the agent connects to (public Cloud Run URL when hosted).
|
|
5
4
|
* Defaults to the dashboard client's baseUrl, which is correct for self-host
|
|
@@ -7,4 +6,4 @@ export interface ConnectAgentProps {
|
|
|
7
6
|
*/
|
|
8
7
|
hubUrl?: string;
|
|
9
8
|
}
|
|
10
|
-
export declare function ConnectAgent({
|
|
9
|
+
export declare function ConnectAgent({ hubUrl }: ConnectAgentProps): import("react").JSX.Element;
|
|
@@ -45,7 +45,7 @@ function installCommand(tool, hubUrl, token) {
|
|
|
45
45
|
" -- npx -y @korso/shepherd",
|
|
46
46
|
].join("\n");
|
|
47
47
|
}
|
|
48
|
-
export function ConnectAgent({
|
|
48
|
+
export function ConnectAgent({ hubUrl }) {
|
|
49
49
|
const client = useShepherdClient();
|
|
50
50
|
const directHubUrl = hubUrl ?? client.baseUrl;
|
|
51
51
|
const headingId = useId();
|
|
@@ -66,7 +66,7 @@ export function ConnectAgent({ workspaceId, hubUrl }) {
|
|
|
66
66
|
const [revokingId, setRevokingId] = useState(null);
|
|
67
67
|
async function loadTokens() {
|
|
68
68
|
try {
|
|
69
|
-
const res = await client.
|
|
69
|
+
const res = await client.listAccountTokens();
|
|
70
70
|
setTokens(res.tokens);
|
|
71
71
|
}
|
|
72
72
|
catch (err) {
|
|
@@ -80,18 +80,12 @@ export function ConnectAgent({ workspaceId, hubUrl }) {
|
|
|
80
80
|
setLoading(true);
|
|
81
81
|
void loadTokens();
|
|
82
82
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
83
|
-
}, [client
|
|
84
|
-
// The component is re-rendered (not remounted) across a workspace switch, so
|
|
85
|
-
// clear the once-shown raw token so it never leaks into another workspace's
|
|
86
|
-
// install command (mirrors Workspaces' setInvite(null) reset).
|
|
87
|
-
useEffect(() => {
|
|
88
|
-
setRawToken(null);
|
|
89
|
-
}, [workspaceId]);
|
|
83
|
+
}, [client]);
|
|
90
84
|
async function generate() {
|
|
91
85
|
setBusy(true);
|
|
92
86
|
setError(null);
|
|
93
87
|
try {
|
|
94
|
-
const res = await client.
|
|
88
|
+
const res = await client.mintAccountToken(name.trim() ? { name: name.trim() } : {});
|
|
95
89
|
setRawToken(res.token);
|
|
96
90
|
setName("");
|
|
97
91
|
await loadTokens();
|
|
@@ -110,7 +104,7 @@ export function ConnectAgent({ workspaceId, hubUrl }) {
|
|
|
110
104
|
setError(null);
|
|
111
105
|
setStatus(null);
|
|
112
106
|
try {
|
|
113
|
-
await client.
|
|
107
|
+
await client.revokeAccountToken(tokenId);
|
|
114
108
|
setTokens((prev) => prev.filter((t) => t.id !== tokenId));
|
|
115
109
|
setStatus("Token revoked");
|
|
116
110
|
}
|
|
@@ -127,7 +121,7 @@ export function ConnectAgent({ workspaceId, hubUrl }) {
|
|
|
127
121
|
setCopied(true);
|
|
128
122
|
setTimeout(() => setCopied(false), 2000);
|
|
129
123
|
}
|
|
130
|
-
return (_jsxs("section", { className: "shepherd-connect-agent", "aria-labelledby": headingId, children: [_jsxs("div", { className: "card-head", children: [_jsx("h3", { id: headingId, children: "Connect your agent" }), _jsx("p", { className: "card-sub", children: "Generate a token
|
|
124
|
+
return (_jsxs("section", { className: "shepherd-connect-agent", "aria-labelledby": headingId, children: [_jsxs("div", { className: "card-head", children: [_jsx("h3", { id: headingId, children: "Connect your agent" }), _jsx("p", { className: "card-sub", children: "Generate a token \u2014 it works across all your workspaces \u2014 then paste the command into your coding tool." }), _jsx("p", { className: "card-sub", children: "The first time the agent opens a repo, it'll ask which workspace to coordinate that repo with." })] }), _jsxs("div", { className: "card-body", children: [_jsxs("div", { className: "field", children: [_jsx("label", { htmlFor: "connect-tool", children: "Tool" }), _jsx("select", { id: "connect-tool", value: tool, onChange: (e) => setTool(e.target.value), children: TOOLS.map((t) => (_jsx("option", { value: t.id, children: t.label }, t.id))) })] }), _jsxs("div", { className: "field generate", children: [_jsx("label", { htmlFor: "token-name", children: "Token name (optional)" }), _jsxs("div", { className: "field__row", children: [_jsx("input", { id: "token-name", type: "text", value: name, onChange: (e) => setName(e.target.value), placeholder: "e.g. laptop" }), _jsx("button", { type: "button", onClick: () => void generate(), disabled: busy, children: "Generate token" })] })] }), error && _jsx("p", { role: "alert", children: error }), status && _jsx("p", { role: "status", children: status }), rawToken && (_jsx("p", { className: "token-once", role: "status", children: "Copy this token now \u2014 it won't be shown again." })), _jsxs("div", { className: "install-command", children: [_jsx("pre", { "data-testid": "install-command", children: command }), _jsx("button", { type: "button", className: "install-command__copy", "aria-label": copied ? "Copied" : "Copy command", title: copied ? "Copied" : "Copy", onClick: () => void copyCommand(), children: copied ? (_jsx("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "M20 6 9 17l-5-5" }) })) : (_jsxs("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }), _jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })] })) })] }), _jsx("h4", { children: "Existing tokens" }), loading ? (_jsx("p", { role: "status", children: "Loading\u2026" })) : tokens.length === 0 ? (_jsx("p", { children: "No tokens yet." })) : (_jsx("ul", { children: tokens.map((t) => {
|
|
131
125
|
const name = t.name ?? t.id;
|
|
132
126
|
return (_jsxs("li", { children: [_jsx("span", { children: name }), _jsx("span", { className: "token-meta", children: tokenMeta(t, Date.now()) }), t.revokedAt ? (_jsx("span", { className: "revoked", children: "revoked" })) : (_jsx("button", { type: "button", "aria-label": `Revoke token ${name}`, onClick: () => void revoke(t.id), disabled: revokingId === t.id, children: "Revoke" }))] }, t.id));
|
|
133
127
|
}) }))] })] }));
|