@solidxai/core-ui 0.1.19 → 0.1.20-beta.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/components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget.d.ts.map +1 -1
- package/dist/components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget.js +3 -10
- package/dist/components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget.js.map +1 -1
- package/dist/components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget.tsx +3 -8
- package/dist/components/layout/AdminHeaderActions.d.ts.map +1 -1
- package/dist/components/layout/AdminHeaderActions.js +1 -29
- package/dist/components/layout/AdminHeaderActions.js.map +1 -1
- package/dist/components/layout/AdminHeaderActions.tsx +0 -42
- package/dist/components/layout/SolidAiStudioLayout.d.ts +0 -1
- package/dist/components/layout/SolidAiStudioLayout.d.ts.map +1 -1
- package/dist/components/layout/SolidAiStudioLayout.js +9 -161
- package/dist/components/layout/SolidAiStudioLayout.js.map +1 -1
- package/dist/components/layout/SolidAiStudioLayout.tsx +7 -136
- package/dist/routes/AppEventListener.d.ts.map +1 -1
- package/dist/routes/AppEventListener.js +3 -3
- package/dist/routes/AppEventListener.js.map +1 -1
- package/dist/routes/AppEventListener.tsx +1 -2
- package/dist/routes/pages/admin/core/AgentHubTagsField.css +21 -0
- package/dist/routes/pages/admin/core/AgentHubTagsField.d.ts +17 -0
- package/dist/routes/pages/admin/core/AgentHubTagsField.d.ts.map +1 -0
- package/dist/routes/pages/admin/core/AgentHubTagsField.js +171 -0
- package/dist/routes/pages/admin/core/AgentHubTagsField.js.map +1 -0
- package/dist/routes/pages/admin/core/AgentHubTagsField.tsx +125 -0
- package/dist/routes/pages/admin/core/AgentRegistryEditorPage.css +7 -0
- package/dist/routes/pages/admin/core/AgentRegistryEditorPage.d.ts.map +1 -1
- package/dist/routes/pages/admin/core/AgentRegistryEditorPage.js +65 -52
- package/dist/routes/pages/admin/core/AgentRegistryEditorPage.js.map +1 -1
- package/dist/routes/pages/admin/core/AgentRegistryEditorPage.tsx +53 -11
- package/dist/routes/pages/admin/core/AgentSkillRegistryEditorPage.d.ts.map +1 -1
- package/dist/routes/pages/admin/core/AgentSkillRegistryEditorPage.js +14 -69
- package/dist/routes/pages/admin/core/AgentSkillRegistryEditorPage.js.map +1 -1
- package/dist/routes/pages/admin/core/AgentSkillRegistryEditorPage.tsx +15 -83
- package/dist/routes/pages/admin/core/AgentToolActivationDialog.d.ts +11 -0
- package/dist/routes/pages/admin/core/AgentToolActivationDialog.d.ts.map +1 -0
- package/dist/routes/pages/admin/core/AgentToolActivationDialog.js +166 -0
- package/dist/routes/pages/admin/core/AgentToolActivationDialog.js.map +1 -0
- package/dist/routes/pages/admin/core/AgentToolActivationDialog.tsx +140 -0
- package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.css +26 -0
- package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.d.ts.map +1 -1
- package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.js +94 -71
- package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.js.map +1 -1
- package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.tsx +60 -52
- package/package.json +1 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { ArrowLeft,
|
|
2
|
+
import { ArrowLeft, RefreshCw } from "lucide-react";
|
|
3
3
|
import { useDispatch } from "react-redux";
|
|
4
4
|
import { useNavigate, useParams } from "react-router-dom";
|
|
5
5
|
import { createSolidEntityApi } from "../../../../redux/api/solidEntityApi";
|
|
6
6
|
import { showToast } from "../../../../redux/features/toastSlice";
|
|
7
7
|
import { AgentRegistryAuditPanel } from "./AgentRegistryAuditPanel";
|
|
8
|
+
import { AgentHubTagsField, agentHubTagsFrom, agentHubTagsPayload, type AgentHubTag } from "./AgentHubTagsField";
|
|
8
9
|
import {
|
|
9
10
|
SolidButton,
|
|
10
11
|
SolidCodeEditor,
|
|
@@ -30,7 +31,7 @@ type SkillRecord = {
|
|
|
30
31
|
iconName?: string | null;
|
|
31
32
|
description?: string;
|
|
32
33
|
body?: string;
|
|
33
|
-
tags?:
|
|
34
|
+
tags?: AgentHubTag[];
|
|
34
35
|
agentSkills?: AgentReference[] | AgentReference | null;
|
|
35
36
|
};
|
|
36
37
|
|
|
@@ -45,25 +46,6 @@ function extractEntityRecord(response: unknown): Record<string, any> | undefined
|
|
|
45
46
|
return candidate && typeof candidate === "object" ? candidate as Record<string, any> : undefined;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
function parseTags(value: unknown): string[] {
|
|
49
|
-
if (Array.isArray(value)) {
|
|
50
|
-
return value.map((tag) => String(tag).trim()).filter(Boolean);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (typeof value !== "string" || !value.trim()) return [];
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
const parsed = JSON.parse(value);
|
|
57
|
-
if (Array.isArray(parsed)) {
|
|
58
|
-
return parsed.map((tag) => String(tag).trim()).filter(Boolean);
|
|
59
|
-
}
|
|
60
|
-
} catch {
|
|
61
|
-
return value === "{}" ? [] : value.split(",").map((tag) => tag.trim()).filter(Boolean);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return [];
|
|
65
|
-
}
|
|
66
|
-
|
|
67
49
|
function formatErrorMessage(value: unknown): string | undefined {
|
|
68
50
|
if (typeof value === "string") return value.trim() || undefined;
|
|
69
51
|
if (Array.isArray(value)) {
|
|
@@ -125,7 +107,7 @@ export function AgentSkillRegistryEditorPage() {
|
|
|
125
107
|
const { data: response, isLoading, isFetching, refetch } = useGetSolidEntityByIdQuery(
|
|
126
108
|
{
|
|
127
109
|
id,
|
|
128
|
-
qs: "populate[0]=agentSkills&populate[1]=agentSkills.agentRegistry",
|
|
110
|
+
qs: "populate[0]=agentSkills&populate[1]=agentSkills.agentRegistry&populate[2]=tags",
|
|
129
111
|
},
|
|
130
112
|
{ skip: !id || id === "new" },
|
|
131
113
|
);
|
|
@@ -139,47 +121,36 @@ export function AgentSkillRegistryEditorPage() {
|
|
|
139
121
|
const [iconName, setIconName] = React.useState("");
|
|
140
122
|
const [description, setDescription] = React.useState("");
|
|
141
123
|
const [body, setBody] = React.useState("");
|
|
142
|
-
const [tags, setTags] = React.useState<
|
|
143
|
-
const [
|
|
124
|
+
const [tags, setTags] = React.useState<AgentHubTag[]>([]);
|
|
125
|
+
const [creatingTag, setCreatingTag] = React.useState(false);
|
|
144
126
|
const [fieldErrors, setFieldErrors] = React.useState<Record<string, string>>({});
|
|
145
127
|
const [auditRefreshVersion, setAuditRefreshVersion] = React.useState(0);
|
|
146
128
|
const [confirmRefresh, setConfirmRefresh] = React.useState(false);
|
|
147
129
|
const baseline = React.useRef("");
|
|
148
|
-
const currentForm = () => JSON.stringify({ name, type, iconName, description, body, tags
|
|
130
|
+
const currentForm = () => JSON.stringify({ name, type, iconName, description, body, tags });
|
|
149
131
|
|
|
150
132
|
React.useEffect(() => {
|
|
151
|
-
const nextTags =
|
|
133
|
+
const nextTags = agentHubTagsFrom(record?.tags);
|
|
152
134
|
setName(record?.name ?? "");
|
|
153
135
|
setType(record?.type ?? "custom");
|
|
154
136
|
setIconName(record?.iconName ?? "");
|
|
155
137
|
setDescription(record?.description ?? "");
|
|
156
138
|
setBody(record?.body ?? "");
|
|
157
139
|
setTags(nextTags);
|
|
158
|
-
|
|
159
|
-
baseline.current = JSON.stringify({ name: record?.name ?? "", type: record?.type ?? "custom", iconName: record?.iconName ?? "", description: record?.description ?? "", body: record?.body ?? "", tags: nextTags, tagDraft: "" });
|
|
140
|
+
baseline.current = JSON.stringify({ name: record?.name ?? "", type: record?.type ?? "custom", iconName: record?.iconName ?? "", description: record?.description ?? "", body: record?.body ?? "", tags: nextTags });
|
|
160
141
|
}, [record]);
|
|
161
142
|
|
|
162
143
|
const isReadOnly = record?.type === "solidx";
|
|
163
144
|
const isDirty = Boolean(record?.id) && currentForm() !== baseline.current;
|
|
164
145
|
const requestRefresh = () => isDirty ? setConfirmRefresh(true) : void refetch();
|
|
165
146
|
|
|
166
|
-
const addTag = () => {
|
|
167
|
-
const nextTag = tagDraft.trim();
|
|
168
|
-
if (!nextTag) return;
|
|
169
|
-
if (!tags.some((tag) => tag.toLowerCase() === nextTag.toLowerCase())) {
|
|
170
|
-
setTags((current) => [...current, nextTag]);
|
|
171
|
-
}
|
|
172
|
-
setTagDraft("");
|
|
173
|
-
setFieldErrors((current) => ({ ...current, tags: "" }));
|
|
174
|
-
};
|
|
175
|
-
|
|
176
147
|
const handleSave = async () => {
|
|
148
|
+
if (creatingTag) return;
|
|
177
149
|
const nextErrors: Record<string, string> = {};
|
|
178
150
|
if (!name.trim()) nextErrors.name = "Name is required.";
|
|
179
151
|
if (!type.trim()) nextErrors.type = "Skill type is required.";
|
|
180
152
|
if (!description.trim()) nextErrors.description = "Description is required.";
|
|
181
153
|
if (!body.trim()) nextErrors.body = "Skill instructions are required.";
|
|
182
|
-
if (tags.length === 0) nextErrors.tags = "At least one tag is required.";
|
|
183
154
|
|
|
184
155
|
setFieldErrors(nextErrors);
|
|
185
156
|
if (Object.keys(nextErrors).length > 0) {
|
|
@@ -198,7 +169,7 @@ export function AgentSkillRegistryEditorPage() {
|
|
|
198
169
|
iconName: iconName || null,
|
|
199
170
|
description: description.trim(),
|
|
200
171
|
body,
|
|
201
|
-
|
|
172
|
+
...agentHubTagsPayload(tags),
|
|
202
173
|
};
|
|
203
174
|
|
|
204
175
|
try {
|
|
@@ -229,14 +200,14 @@ export function AgentSkillRegistryEditorPage() {
|
|
|
229
200
|
const errorDetail = getSaveErrorMessage(error);
|
|
230
201
|
const serverFieldErrors: Record<string, string> = {};
|
|
231
202
|
if (/required|not be empty|cannot be empty|should not be empty/i.test(errorDetail)) {
|
|
232
|
-
for (const field of ["name", "type", "description", "body"
|
|
203
|
+
for (const field of ["name", "type", "description", "body"]) {
|
|
233
204
|
if (!new RegExp(`\\b${field}\\b`, "i").test(errorDetail)) continue;
|
|
234
205
|
serverFieldErrors[field] = `${field === "body" ? "Skill instructions" : field[0].toUpperCase() + field.slice(1)} is required.`;
|
|
235
206
|
}
|
|
236
207
|
}
|
|
237
208
|
if (Object.keys(serverFieldErrors).length > 0) {
|
|
238
209
|
setFieldErrors(serverFieldErrors);
|
|
239
|
-
setActiveTab(serverFieldErrors.body
|
|
210
|
+
setActiveTab(serverFieldErrors.body ? "skill" : "general");
|
|
240
211
|
}
|
|
241
212
|
dispatch(showToast({
|
|
242
213
|
severity: "error",
|
|
@@ -306,46 +277,7 @@ export function AgentSkillRegistryEditorPage() {
|
|
|
306
277
|
</select>
|
|
307
278
|
{fieldErrors.type && <small id="agent-skill-type-error" className="agent-skill-editor__field-error">{fieldErrors.type}</small>}
|
|
308
279
|
</label>
|
|
309
|
-
<
|
|
310
|
-
<span>Tags <b>*</b></span>
|
|
311
|
-
<div className={`agent-skill-editor__tag-input${fieldErrors.tags ? " agent-skill-editor__tag-input--invalid" : ""}`}>
|
|
312
|
-
{tags.map((tag, index) => (
|
|
313
|
-
<span className="agent-skill-editor__tag" key={`${tag}-${index}`}>
|
|
314
|
-
{tag}
|
|
315
|
-
<button
|
|
316
|
-
type="button"
|
|
317
|
-
aria-label={`Remove ${tag}`}
|
|
318
|
-
onClick={() => {
|
|
319
|
-
setTags((current) => {
|
|
320
|
-
const nextTags = current.filter((_, tagIndex) => tagIndex !== index);
|
|
321
|
-
if (nextTags.length > 0) setFieldErrors((errors) => ({ ...errors, tags: "" }));
|
|
322
|
-
return nextTags;
|
|
323
|
-
});
|
|
324
|
-
}}
|
|
325
|
-
>
|
|
326
|
-
<X size={13} />
|
|
327
|
-
</button>
|
|
328
|
-
</span>
|
|
329
|
-
))}
|
|
330
|
-
<input
|
|
331
|
-
value={tagDraft}
|
|
332
|
-
aria-label="Add a tag"
|
|
333
|
-
placeholder="Type a tag and press Enter"
|
|
334
|
-
onChange={(event) => setTagDraft(event.target.value)}
|
|
335
|
-
onKeyDown={(event) => {
|
|
336
|
-
if (event.key === "Enter") {
|
|
337
|
-
event.preventDefault();
|
|
338
|
-
addTag();
|
|
339
|
-
}
|
|
340
|
-
}}
|
|
341
|
-
/>
|
|
342
|
-
<SolidButton type="button" variant="secondary" size="small" onClick={addTag}>
|
|
343
|
-
<Plus size={14} /> Add
|
|
344
|
-
</SolidButton>
|
|
345
|
-
</div>
|
|
346
|
-
{fieldErrors.tags && <small className="agent-skill-editor__field-error">{fieldErrors.tags}</small>}
|
|
347
|
-
<small>Tags are saved as a JSON array.</small>
|
|
348
|
-
</div>
|
|
280
|
+
<AgentHubTagsField value={tags} onChange={setTags} disabled={isReadOnly || isCreating || isSaving} onBusyChange={setCreatingTag} />
|
|
349
281
|
</fieldset>
|
|
350
282
|
),
|
|
351
283
|
},
|
|
@@ -415,7 +347,7 @@ export function AgentSkillRegistryEditorPage() {
|
|
|
415
347
|
Back
|
|
416
348
|
</SolidButton>
|
|
417
349
|
{!isReadOnly && (
|
|
418
|
-
<SolidButton loading={isCreating || isSaving} onClick={handleSave}>
|
|
350
|
+
<SolidButton loading={isCreating || isSaving} disabled={creatingTag} onClick={handleSave}>
|
|
419
351
|
Save Skill
|
|
420
352
|
</SolidButton>
|
|
421
353
|
)}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
open: boolean;
|
|
3
|
+
toolId: number;
|
|
4
|
+
checksum: string;
|
|
5
|
+
toolName: string;
|
|
6
|
+
onOpenChange: (open: boolean) => void;
|
|
7
|
+
onActivated: () => Promise<void>;
|
|
8
|
+
};
|
|
9
|
+
export declare function AgentToolActivationDialog({ open, toolId, checksum, toolName, onOpenChange, onActivated }: Props): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=AgentToolActivationDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentToolActivationDialog.d.ts","sourceRoot":"","sources":["../../../../../src/routes/pages/admin/core/AgentToolActivationDialog.tsx"],"names":[],"mappings":"AAYA,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC,CAAC;AAuCF,wBAAgB,yBAAyB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,EAAE,KAAK,2CAiF/G"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
11
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
12
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
13
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
14
|
+
function step(op) {
|
|
15
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
16
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
17
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
18
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
19
|
+
switch (op[0]) {
|
|
20
|
+
case 0: case 1: t = op; break;
|
|
21
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
22
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
23
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
24
|
+
default:
|
|
25
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
26
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
27
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
28
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
29
|
+
if (t[2]) _.ops.pop();
|
|
30
|
+
_.trys.pop(); continue;
|
|
31
|
+
}
|
|
32
|
+
op = body.call(thisArg, _);
|
|
33
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
34
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
38
|
+
import React from "react";
|
|
39
|
+
import { CheckCircle2, Circle, Loader2, ShieldCheck, XCircle } from "lucide-react";
|
|
40
|
+
import { solidPost } from "../../../../http/solidHttp";
|
|
41
|
+
import { SolidButton, SolidDialog, SolidDialogBody } from "../../../../components/shad-cn-ui";
|
|
42
|
+
function unwrapReport(response) {
|
|
43
|
+
var value = response === null || response === void 0 ? void 0 : response.data;
|
|
44
|
+
for (var depth = 0; depth < 5 && value; depth += 1) {
|
|
45
|
+
if (value.config && value.init)
|
|
46
|
+
return value;
|
|
47
|
+
value = value.data;
|
|
48
|
+
}
|
|
49
|
+
throw new Error("The server returned an invalid tool check result.");
|
|
50
|
+
}
|
|
51
|
+
function errorMessage(error) {
|
|
52
|
+
var _a, _b, _c, _d, _e;
|
|
53
|
+
var body = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data;
|
|
54
|
+
var message = (_e = (_d = (_c = (_b = body === null || body === void 0 ? void 0 : body.data) === null || _b === void 0 ? void 0 : _b.message) !== null && _c !== void 0 ? _c : body === null || body === void 0 ? void 0 : body.message) !== null && _d !== void 0 ? _d : body === null || body === void 0 ? void 0 : body.detail) !== null && _e !== void 0 ? _e : error === null || error === void 0 ? void 0 : error.message;
|
|
55
|
+
return Array.isArray(message) ? message.join(" ") : typeof message === "string" ? message : "Checks failed. Please retry.";
|
|
56
|
+
}
|
|
57
|
+
function CheckStep(_a) {
|
|
58
|
+
var _b;
|
|
59
|
+
var title = _a.title, step = _a.step, number = _a.number;
|
|
60
|
+
var Icon = step.status === "running" ? Loader2 : step.status === "passed" ? CheckCircle2
|
|
61
|
+
: step.status === "failed" ? XCircle : Circle;
|
|
62
|
+
var label = step.status === "running" ? "Checking" : step.status === "waiting" ? "Waiting" : step.status;
|
|
63
|
+
return _jsxs("section", { className: "agent-tool-check is-".concat(step.status), "aria-label": "".concat(title, ": ").concat(label), children: [_jsx("div", { className: "agent-tool-check__icon", children: _jsx(Icon, { size: 23, className: step.status === "running" ? "is-spinning" : undefined }) }), _jsxs("div", { className: "agent-tool-check__content", children: [_jsxs("div", { className: "agent-tool-check__heading", children: [_jsxs("h3", { children: [number, ". ", title] }), _jsx("span", { children: label })] }), _jsx("p", { children: step.message }), !!((_b = step.requiredSecrets) === null || _b === void 0 ? void 0 : _b.length) && _jsx("ul", { className: "agent-tool-check__secrets", "aria-label": "Required secrets", children: step.requiredSecrets.map(function (name) {
|
|
64
|
+
var _a, _b;
|
|
65
|
+
var missing = (_a = step.missingSecrets) === null || _a === void 0 ? void 0 : _a.includes(name);
|
|
66
|
+
var verified = step.status === "passed" || Boolean((_b = step.missingSecrets) === null || _b === void 0 ? void 0 : _b.length);
|
|
67
|
+
return _jsxs("li", { className: missing ? "is-missing" : verified ? "is-available" : "", children: [_jsx("code", { children: name }), _jsx("span", { children: missing ? "Missing, empty, or inactive" : verified ? "Available" : "Not verified" })] }, name);
|
|
68
|
+
}) })] })] });
|
|
69
|
+
}
|
|
70
|
+
export function AgentToolActivationDialog(_a) {
|
|
71
|
+
var _this = this;
|
|
72
|
+
var open = _a.open, toolId = _a.toolId, checksum = _a.checksum, toolName = _a.toolName, onOpenChange = _a.onOpenChange, onActivated = _a.onActivated;
|
|
73
|
+
var _b = React.useState({ status: "running", message: "Checking configuration and required secrets…" }), config = _b[0], setConfig = _b[1];
|
|
74
|
+
var _c = React.useState({ status: "waiting", message: "Waiting for configuration to pass." }), init = _c[0], setInit = _c[1];
|
|
75
|
+
var _d = React.useState(true), busy = _d[0], setBusy = _d[1];
|
|
76
|
+
var _e = React.useState(false), activated = _e[0], setActivated = _e[1];
|
|
77
|
+
var _f = React.useState(""), activationError = _f[0], setActivationError = _f[1];
|
|
78
|
+
var _g = React.useState(0), attempt = _g[0], setAttempt = _g[1];
|
|
79
|
+
var callbacks = React.useRef({ onActivated: onActivated });
|
|
80
|
+
callbacks.current = { onActivated: onActivated };
|
|
81
|
+
React.useEffect(function () {
|
|
82
|
+
if (!open)
|
|
83
|
+
return;
|
|
84
|
+
var controller = new AbortController();
|
|
85
|
+
var cancelled = false;
|
|
86
|
+
var run = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
87
|
+
var phase, requestOptions, checkUrl, configuration, _a, initialization, _b, error_1, failed;
|
|
88
|
+
return __generator(this, function (_c) {
|
|
89
|
+
switch (_c.label) {
|
|
90
|
+
case 0:
|
|
91
|
+
phase = "config";
|
|
92
|
+
setBusy(true);
|
|
93
|
+
setActivated(false);
|
|
94
|
+
setActivationError("");
|
|
95
|
+
setConfig({ status: "running", message: "Checking configuration and required secrets…" });
|
|
96
|
+
setInit({ status: "waiting", message: "Waiting for configuration to pass." });
|
|
97
|
+
_c.label = 1;
|
|
98
|
+
case 1:
|
|
99
|
+
_c.trys.push([1, 5, 6, 7]);
|
|
100
|
+
requestOptions = { signal: controller.signal, timeout: 60000 };
|
|
101
|
+
checkUrl = "/agent-tool-registry/".concat(toolId, "/check");
|
|
102
|
+
_a = unwrapReport;
|
|
103
|
+
return [4 /*yield*/, solidPost(checkUrl, { checksum: checksum, phase: "config" }, requestOptions)];
|
|
104
|
+
case 2:
|
|
105
|
+
configuration = _a.apply(void 0, [_c.sent()]);
|
|
106
|
+
if (configuration.toolId !== toolId || configuration.checksum !== checksum)
|
|
107
|
+
throw new Error("The server checked a different tool version.");
|
|
108
|
+
if (cancelled)
|
|
109
|
+
return [2 /*return*/];
|
|
110
|
+
setConfig(configuration.config);
|
|
111
|
+
if (configuration.config.status !== "passed") {
|
|
112
|
+
setInit({ status: "skipped", message: "Configuration must pass before initialization can run." });
|
|
113
|
+
return [2 /*return*/];
|
|
114
|
+
}
|
|
115
|
+
phase = "init";
|
|
116
|
+
setInit({ status: "running", message: "Running the tool’s initialization check…" });
|
|
117
|
+
_b = unwrapReport;
|
|
118
|
+
return [4 /*yield*/, solidPost(checkUrl, { checksum: checksum, phase: "init" }, requestOptions)];
|
|
119
|
+
case 3:
|
|
120
|
+
initialization = _b.apply(void 0, [_c.sent()]);
|
|
121
|
+
if (initialization.toolId !== toolId || initialization.checksum !== checksum)
|
|
122
|
+
throw new Error("The server checked a different tool version.");
|
|
123
|
+
if (cancelled)
|
|
124
|
+
return [2 /*return*/];
|
|
125
|
+
setConfig(initialization.config);
|
|
126
|
+
setInit(initialization.init);
|
|
127
|
+
if (initialization.config.status !== "passed" || initialization.init.status !== "passed")
|
|
128
|
+
return [2 /*return*/];
|
|
129
|
+
phase = "activate";
|
|
130
|
+
return [4 /*yield*/, callbacks.current.onActivated()];
|
|
131
|
+
case 4:
|
|
132
|
+
_c.sent();
|
|
133
|
+
if (cancelled)
|
|
134
|
+
return [2 /*return*/];
|
|
135
|
+
setActivated(true);
|
|
136
|
+
return [3 /*break*/, 7];
|
|
137
|
+
case 5:
|
|
138
|
+
error_1 = _c.sent();
|
|
139
|
+
if (cancelled)
|
|
140
|
+
return [2 /*return*/];
|
|
141
|
+
failed = { status: "failed", message: errorMessage(error_1) };
|
|
142
|
+
if (phase === "config") {
|
|
143
|
+
setConfig(failed);
|
|
144
|
+
setInit({ status: "skipped", message: "Configuration must pass before initialization can run." });
|
|
145
|
+
}
|
|
146
|
+
else if (phase === "init")
|
|
147
|
+
setInit(failed);
|
|
148
|
+
else
|
|
149
|
+
setActivationError(errorMessage(error_1));
|
|
150
|
+
return [3 /*break*/, 7];
|
|
151
|
+
case 6:
|
|
152
|
+
if (!cancelled)
|
|
153
|
+
setBusy(false);
|
|
154
|
+
return [7 /*endfinally*/];
|
|
155
|
+
case 7: return [2 /*return*/];
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}); };
|
|
159
|
+
// Avoid duplicate requests during React StrictMode effect replay.
|
|
160
|
+
var timer = setTimeout(function () { return void run(); }, 0);
|
|
161
|
+
return function () { cancelled = true; clearTimeout(timer); controller.abort(); };
|
|
162
|
+
}, [open, toolId, checksum, attempt]);
|
|
163
|
+
return _jsx(SolidDialog, { open: open, onOpenChange: function (next) { if (!busy)
|
|
164
|
+
onOpenChange(next); }, className: busy ? "agent-tool-activation-dialog is-checking" : "agent-tool-activation-dialog", header: "Activate tool", dismissible: !busy, style: { width: "min(36rem, 94vw)" }, footer: _jsxs(_Fragment, { children: [_jsx(SolidButton, { variant: "secondary", disabled: busy, onClick: function () { return onOpenChange(false); }, children: activated ? "Done" : "Close" }), !activated && _jsx(SolidButton, { loading: busy, onClick: function () { setBusy(true); setAttempt(function (value) { return value + 1; }); }, children: busy ? "Checking…" : "Retry checks" })] }), children: _jsx(SolidDialogBody, { children: _jsxs("div", { className: "agent-tool-activation", "aria-live": "polite", "aria-busy": busy, children: [_jsxs("p", { className: "agent-tool-activation__intro", children: [_jsx("strong", { children: toolName }), " will activate after configuration and initialization both pass."] }), _jsx(CheckStep, { title: "Configuration", step: config, number: 1 }), _jsx(CheckStep, { title: "Initialization", step: init, number: 2 }), activated ? _jsxs("div", { className: "agent-tool-activation__success", role: "status", children: [_jsx(ShieldCheck, { size: 20 }), _jsxs("div", { children: [_jsx("strong", { children: "Tool activated" }), _jsx("p", { children: "Both checks passed. Restart linked agent processes to apply the change." })] })] }) : !busy && _jsx("p", { className: "agent-tool-activation__failure", role: "alert", children: activationError ? "Checks passed, but activation failed: ".concat(activationError) : "The tool remains inactive. Resolve the reported issue and retry the checks." })] }) }) });
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=AgentToolActivationDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentToolActivationDialog.js","sourceRoot":"","sources":["../../../../../src/routes/pages/admin/core/AgentToolActivationDialog.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from \"react\";\nimport { CheckCircle2, Circle, Loader2, ShieldCheck, XCircle } from \"lucide-react\";\nimport { solidPost } from \"../../../../http/solidHttp\";\nimport { SolidButton, SolidDialog, SolidDialogBody } from \"../../../../components/shad-cn-ui\";\n\ntype Step = {\n status: \"waiting\" | \"running\" | \"passed\" | \"failed\" | \"skipped\";\n message: string;\n requiredSecrets?: string[];\n missingSecrets?: string[];\n};\ntype Report = { toolId?: number; checksum?: string; config: Step; init: Step };\ntype Props = {\n open: boolean;\n toolId: number;\n checksum: string;\n toolName: string;\n onOpenChange: (open: boolean) => void;\n onActivated: () => Promise<void>;\n};\n\nfunction unwrapReport(response: any): Report {\n let value = response?.data;\n for (let depth = 0; depth < 5 && value; depth += 1) {\n if (value.config && value.init) return value as Report;\n value = value.data;\n }\n throw new Error(\"The server returned an invalid tool check result.\");\n}\n\nfunction errorMessage(error: any): string {\n const body = error?.response?.data;\n const message = body?.data?.message ?? body?.message ?? body?.detail ?? error?.message;\n return Array.isArray(message) ? message.join(\" \") : typeof message === \"string\" ? message : \"Checks failed. Please retry.\";\n}\n\nfunction CheckStep({ title, step, number }: { title: string; step: Step; number: number }) {\n const Icon = step.status === \"running\" ? Loader2 : step.status === \"passed\" ? CheckCircle2\n : step.status === \"failed\" ? XCircle : Circle;\n const label = step.status === \"running\" ? \"Checking\" : step.status === \"waiting\" ? \"Waiting\" : step.status;\n return <section className={`agent-tool-check is-${step.status}`} aria-label={`${title}: ${label}`}>\n <div className=\"agent-tool-check__icon\"><Icon size={23} className={step.status === \"running\" ? \"is-spinning\" : undefined} /></div>\n <div className=\"agent-tool-check__content\">\n <div className=\"agent-tool-check__heading\"><h3>{number}. {title}</h3><span>{label}</span></div>\n <p>{step.message}</p>\n {!!step.requiredSecrets?.length && <ul className=\"agent-tool-check__secrets\" aria-label=\"Required secrets\">\n {step.requiredSecrets.map((name) => {\n const missing = step.missingSecrets?.includes(name);\n const verified = step.status === \"passed\" || Boolean(step.missingSecrets?.length);\n return <li key={name} className={missing ? \"is-missing\" : verified ? \"is-available\" : \"\"}>\n <code>{name}</code><span>{missing ? \"Missing, empty, or inactive\" : verified ? \"Available\" : \"Not verified\"}</span>\n </li>;\n })}\n </ul>}\n </div>\n </section>;\n}\n\nexport function AgentToolActivationDialog({ open, toolId, checksum, toolName, onOpenChange, onActivated }: Props) {\n const [config, setConfig] = React.useState<Step>({ status: \"running\", message: \"Checking configuration and required secrets…\" });\n const [init, setInit] = React.useState<Step>({ status: \"waiting\", message: \"Waiting for configuration to pass.\" });\n const [busy, setBusy] = React.useState(true);\n const [activated, setActivated] = React.useState(false);\n const [activationError, setActivationError] = React.useState(\"\");\n const [attempt, setAttempt] = React.useState(0);\n const callbacks = React.useRef({ onActivated });\n callbacks.current = { onActivated };\n\n React.useEffect(() => {\n if (!open) return;\n const controller = new AbortController();\n let cancelled = false;\n const run = async () => {\n let phase: \"config\" | \"init\" | \"activate\" = \"config\";\n setBusy(true);\n setActivated(false);\n setActivationError(\"\");\n setConfig({ status: \"running\", message: \"Checking configuration and required secrets…\" });\n setInit({ status: \"waiting\", message: \"Waiting for configuration to pass.\" });\n try {\n const requestOptions = { signal: controller.signal, timeout: 60000 };\n const checkUrl = `/agent-tool-registry/${toolId}/check`;\n const configuration = unwrapReport(await solidPost(checkUrl, { checksum, phase: \"config\" }, requestOptions));\n if (configuration.toolId !== toolId || configuration.checksum !== checksum) throw new Error(\"The server checked a different tool version.\");\n if (cancelled) return;\n setConfig(configuration.config);\n if (configuration.config.status !== \"passed\") {\n setInit({ status: \"skipped\", message: \"Configuration must pass before initialization can run.\" });\n return;\n }\n phase = \"init\";\n setInit({ status: \"running\", message: \"Running the tool’s initialization check…\" });\n const initialization = unwrapReport(await solidPost(checkUrl, { checksum, phase: \"init\" }, requestOptions));\n if (initialization.toolId !== toolId || initialization.checksum !== checksum) throw new Error(\"The server checked a different tool version.\");\n if (cancelled) return;\n setConfig(initialization.config);\n setInit(initialization.init);\n if (initialization.config.status !== \"passed\" || initialization.init.status !== \"passed\") return;\n phase = \"activate\";\n await callbacks.current.onActivated();\n if (cancelled) return;\n setActivated(true);\n } catch (error) {\n if (cancelled) return;\n const failed: Step = { status: \"failed\", message: errorMessage(error) };\n if (phase === \"config\") {\n setConfig(failed);\n setInit({ status: \"skipped\", message: \"Configuration must pass before initialization can run.\" });\n } else if (phase === \"init\") setInit(failed);\n else setActivationError(errorMessage(error));\n } finally {\n if (!cancelled) setBusy(false);\n }\n };\n // Avoid duplicate requests during React StrictMode effect replay.\n const timer = setTimeout(() => void run(), 0);\n return () => { cancelled = true; clearTimeout(timer); controller.abort(); };\n }, [open, toolId, checksum, attempt]);\n\n return <SolidDialog open={open} onOpenChange={(next) => { if (!busy) onOpenChange(next); }}\n className={busy ? \"agent-tool-activation-dialog is-checking\" : \"agent-tool-activation-dialog\"}\n header=\"Activate tool\" dismissible={!busy} style={{ width: \"min(36rem, 94vw)\" }}\n footer={<>\n <SolidButton variant=\"secondary\" disabled={busy} onClick={() => onOpenChange(false)}>{activated ? \"Done\" : \"Close\"}</SolidButton>\n {!activated && <SolidButton loading={busy} onClick={() => { setBusy(true); setAttempt((value) => value + 1); }}>\n {busy ? \"Checking…\" : \"Retry checks\"}\n </SolidButton>}\n </>}>\n <SolidDialogBody>\n <div className=\"agent-tool-activation\" aria-live=\"polite\" aria-busy={busy}>\n <p className=\"agent-tool-activation__intro\"><strong>{toolName}</strong> will activate after configuration and initialization both pass.</p>\n <CheckStep title=\"Configuration\" step={config} number={1} />\n <CheckStep title=\"Initialization\" step={init} number={2} />\n {activated ? <div className=\"agent-tool-activation__success\" role=\"status\"><ShieldCheck size={20} />\n <div><strong>Tool activated</strong><p>Both checks passed. Restart linked agent processes to apply the change.</p></div>\n </div> : !busy && <p className=\"agent-tool-activation__failure\" role=\"alert\">{activationError ? `Checks passed, but activation failed: ${activationError}` : \"The tool remains inactive. Resolve the reported issue and retry the checks.\"}</p>}\n </div>\n </SolidDialogBody>\n </SolidDialog>;\n}\n"]}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { CheckCircle2, Circle, Loader2, ShieldCheck, XCircle } from "lucide-react";
|
|
3
|
+
import { solidPost } from "../../../../http/solidHttp";
|
|
4
|
+
import { SolidButton, SolidDialog, SolidDialogBody } from "../../../../components/shad-cn-ui";
|
|
5
|
+
|
|
6
|
+
type Step = {
|
|
7
|
+
status: "waiting" | "running" | "passed" | "failed" | "skipped";
|
|
8
|
+
message: string;
|
|
9
|
+
requiredSecrets?: string[];
|
|
10
|
+
missingSecrets?: string[];
|
|
11
|
+
};
|
|
12
|
+
type Report = { toolId?: number; checksum?: string; config: Step; init: Step };
|
|
13
|
+
type Props = {
|
|
14
|
+
open: boolean;
|
|
15
|
+
toolId: number;
|
|
16
|
+
checksum: string;
|
|
17
|
+
toolName: string;
|
|
18
|
+
onOpenChange: (open: boolean) => void;
|
|
19
|
+
onActivated: () => Promise<void>;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function unwrapReport(response: any): Report {
|
|
23
|
+
let value = response?.data;
|
|
24
|
+
for (let depth = 0; depth < 5 && value; depth += 1) {
|
|
25
|
+
if (value.config && value.init) return value as Report;
|
|
26
|
+
value = value.data;
|
|
27
|
+
}
|
|
28
|
+
throw new Error("The server returned an invalid tool check result.");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function errorMessage(error: any): string {
|
|
32
|
+
const body = error?.response?.data;
|
|
33
|
+
const message = body?.data?.message ?? body?.message ?? body?.detail ?? error?.message;
|
|
34
|
+
return Array.isArray(message) ? message.join(" ") : typeof message === "string" ? message : "Checks failed. Please retry.";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function CheckStep({ title, step, number }: { title: string; step: Step; number: number }) {
|
|
38
|
+
const Icon = step.status === "running" ? Loader2 : step.status === "passed" ? CheckCircle2
|
|
39
|
+
: step.status === "failed" ? XCircle : Circle;
|
|
40
|
+
const label = step.status === "running" ? "Checking" : step.status === "waiting" ? "Waiting" : step.status;
|
|
41
|
+
return <section className={`agent-tool-check is-${step.status}`} aria-label={`${title}: ${label}`}>
|
|
42
|
+
<div className="agent-tool-check__icon"><Icon size={23} className={step.status === "running" ? "is-spinning" : undefined} /></div>
|
|
43
|
+
<div className="agent-tool-check__content">
|
|
44
|
+
<div className="agent-tool-check__heading"><h3>{number}. {title}</h3><span>{label}</span></div>
|
|
45
|
+
<p>{step.message}</p>
|
|
46
|
+
{!!step.requiredSecrets?.length && <ul className="agent-tool-check__secrets" aria-label="Required secrets">
|
|
47
|
+
{step.requiredSecrets.map((name) => {
|
|
48
|
+
const missing = step.missingSecrets?.includes(name);
|
|
49
|
+
const verified = step.status === "passed" || Boolean(step.missingSecrets?.length);
|
|
50
|
+
return <li key={name} className={missing ? "is-missing" : verified ? "is-available" : ""}>
|
|
51
|
+
<code>{name}</code><span>{missing ? "Missing, empty, or inactive" : verified ? "Available" : "Not verified"}</span>
|
|
52
|
+
</li>;
|
|
53
|
+
})}
|
|
54
|
+
</ul>}
|
|
55
|
+
</div>
|
|
56
|
+
</section>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function AgentToolActivationDialog({ open, toolId, checksum, toolName, onOpenChange, onActivated }: Props) {
|
|
60
|
+
const [config, setConfig] = React.useState<Step>({ status: "running", message: "Checking configuration and required secrets…" });
|
|
61
|
+
const [init, setInit] = React.useState<Step>({ status: "waiting", message: "Waiting for configuration to pass." });
|
|
62
|
+
const [busy, setBusy] = React.useState(true);
|
|
63
|
+
const [activated, setActivated] = React.useState(false);
|
|
64
|
+
const [activationError, setActivationError] = React.useState("");
|
|
65
|
+
const [attempt, setAttempt] = React.useState(0);
|
|
66
|
+
const callbacks = React.useRef({ onActivated });
|
|
67
|
+
callbacks.current = { onActivated };
|
|
68
|
+
|
|
69
|
+
React.useEffect(() => {
|
|
70
|
+
if (!open) return;
|
|
71
|
+
const controller = new AbortController();
|
|
72
|
+
let cancelled = false;
|
|
73
|
+
const run = async () => {
|
|
74
|
+
let phase: "config" | "init" | "activate" = "config";
|
|
75
|
+
setBusy(true);
|
|
76
|
+
setActivated(false);
|
|
77
|
+
setActivationError("");
|
|
78
|
+
setConfig({ status: "running", message: "Checking configuration and required secrets…" });
|
|
79
|
+
setInit({ status: "waiting", message: "Waiting for configuration to pass." });
|
|
80
|
+
try {
|
|
81
|
+
const requestOptions = { signal: controller.signal, timeout: 60000 };
|
|
82
|
+
const checkUrl = `/agent-tool-registry/${toolId}/check`;
|
|
83
|
+
const configuration = unwrapReport(await solidPost(checkUrl, { checksum, phase: "config" }, requestOptions));
|
|
84
|
+
if (configuration.toolId !== toolId || configuration.checksum !== checksum) throw new Error("The server checked a different tool version.");
|
|
85
|
+
if (cancelled) return;
|
|
86
|
+
setConfig(configuration.config);
|
|
87
|
+
if (configuration.config.status !== "passed") {
|
|
88
|
+
setInit({ status: "skipped", message: "Configuration must pass before initialization can run." });
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
phase = "init";
|
|
92
|
+
setInit({ status: "running", message: "Running the tool’s initialization check…" });
|
|
93
|
+
const initialization = unwrapReport(await solidPost(checkUrl, { checksum, phase: "init" }, requestOptions));
|
|
94
|
+
if (initialization.toolId !== toolId || initialization.checksum !== checksum) throw new Error("The server checked a different tool version.");
|
|
95
|
+
if (cancelled) return;
|
|
96
|
+
setConfig(initialization.config);
|
|
97
|
+
setInit(initialization.init);
|
|
98
|
+
if (initialization.config.status !== "passed" || initialization.init.status !== "passed") return;
|
|
99
|
+
phase = "activate";
|
|
100
|
+
await callbacks.current.onActivated();
|
|
101
|
+
if (cancelled) return;
|
|
102
|
+
setActivated(true);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
if (cancelled) return;
|
|
105
|
+
const failed: Step = { status: "failed", message: errorMessage(error) };
|
|
106
|
+
if (phase === "config") {
|
|
107
|
+
setConfig(failed);
|
|
108
|
+
setInit({ status: "skipped", message: "Configuration must pass before initialization can run." });
|
|
109
|
+
} else if (phase === "init") setInit(failed);
|
|
110
|
+
else setActivationError(errorMessage(error));
|
|
111
|
+
} finally {
|
|
112
|
+
if (!cancelled) setBusy(false);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
// Avoid duplicate requests during React StrictMode effect replay.
|
|
116
|
+
const timer = setTimeout(() => void run(), 0);
|
|
117
|
+
return () => { cancelled = true; clearTimeout(timer); controller.abort(); };
|
|
118
|
+
}, [open, toolId, checksum, attempt]);
|
|
119
|
+
|
|
120
|
+
return <SolidDialog open={open} onOpenChange={(next) => { if (!busy) onOpenChange(next); }}
|
|
121
|
+
className={busy ? "agent-tool-activation-dialog is-checking" : "agent-tool-activation-dialog"}
|
|
122
|
+
header="Activate tool" dismissible={!busy} style={{ width: "min(36rem, 94vw)" }}
|
|
123
|
+
footer={<>
|
|
124
|
+
<SolidButton variant="secondary" disabled={busy} onClick={() => onOpenChange(false)}>{activated ? "Done" : "Close"}</SolidButton>
|
|
125
|
+
{!activated && <SolidButton loading={busy} onClick={() => { setBusy(true); setAttempt((value) => value + 1); }}>
|
|
126
|
+
{busy ? "Checking…" : "Retry checks"}
|
|
127
|
+
</SolidButton>}
|
|
128
|
+
</>}>
|
|
129
|
+
<SolidDialogBody>
|
|
130
|
+
<div className="agent-tool-activation" aria-live="polite" aria-busy={busy}>
|
|
131
|
+
<p className="agent-tool-activation__intro"><strong>{toolName}</strong> will activate after configuration and initialization both pass.</p>
|
|
132
|
+
<CheckStep title="Configuration" step={config} number={1} />
|
|
133
|
+
<CheckStep title="Initialization" step={init} number={2} />
|
|
134
|
+
{activated ? <div className="agent-tool-activation__success" role="status"><ShieldCheck size={20} />
|
|
135
|
+
<div><strong>Tool activated</strong><p>Both checks passed. Restart linked agent processes to apply the change.</p></div>
|
|
136
|
+
</div> : !busy && <p className="agent-tool-activation__failure" role="alert">{activationError ? `Checks passed, but activation failed: ${activationError}` : "The tool remains inactive. Resolve the reported issue and retry the checks."}</p>}
|
|
137
|
+
</div>
|
|
138
|
+
</SolidDialogBody>
|
|
139
|
+
</SolidDialog>;
|
|
140
|
+
}
|
|
@@ -122,4 +122,30 @@
|
|
|
122
122
|
@media(max-width:900px) { .agent-tool-editor__sessions { height:auto; min-height:0; grid-template-columns:minmax(0,1fr); grid-template-rows:auto minmax(24rem,1fr); max-height:none; } .agent-tool-editor__sessions-sidebar { max-height:18rem; border-right:0; border-bottom:1px solid var(--surface-border,var(--border)); } .agent-tool-editor__event-filters>label { flex:1 1 8rem; } }
|
|
123
123
|
@media(max-width:600px) { .agent-tool-editor { padding:1rem; } .agent-tool-editor__header { align-items:flex-start; flex-direction:column; } .agent-tool-editor__actions { width:100%; } }
|
|
124
124
|
fieldset.agent-tool-editor__general { min-width:0; margin:0; padding:0; border:0; }
|
|
125
|
+
.agent-tool-activation { display:flex; flex-direction:column; gap:1rem; }
|
|
126
|
+
.agent-tool-activation-dialog.is-checking .solid-radix-dialog-close { visibility:hidden; }
|
|
127
|
+
.agent-tool-activation__intro { margin:0 0 .25rem; color:var(--text-color-secondary,var(--muted-foreground)); line-height:1.6; }
|
|
128
|
+
.agent-tool-activation__intro strong { color:var(--text-color,var(--foreground)); }
|
|
129
|
+
.agent-tool-check { display:flex; align-items:flex-start; gap:.85rem; padding:1rem; border:1px solid var(--surface-border,var(--border)); border-radius:.75rem; background:var(--surface-ground,var(--background)); }
|
|
130
|
+
.agent-tool-check__icon { display:flex; flex:0 0 2.4rem; align-items:center; justify-content:center; height:2.4rem; border-radius:50%; background:var(--surface-card,var(--card)); color:var(--text-color-secondary,var(--muted-foreground)); }
|
|
131
|
+
.agent-tool-check__content { flex:1; min-width:0; }
|
|
132
|
+
.agent-tool-check__heading { display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:.5rem; }
|
|
133
|
+
.agent-tool-check__heading h3 { margin:0; font-size:.95rem; }
|
|
134
|
+
.agent-tool-check__heading>span { padding:.15rem .55rem; border:1px solid currentColor; border-radius:999px; font-size:.7rem; font-weight:650; text-transform:capitalize; }
|
|
135
|
+
.agent-tool-check p { margin:.45rem 0 0; font-size:.82rem; line-height:1.5; overflow-wrap:anywhere; color:var(--text-color-secondary,var(--muted-foreground)); }
|
|
136
|
+
.agent-tool-check.is-running .agent-tool-check__icon,.agent-tool-check.is-running .agent-tool-check__heading>span { color:var(--primary-color,var(--primary)); }
|
|
137
|
+
.agent-tool-check.is-passed .agent-tool-check__icon,.agent-tool-check.is-passed .agent-tool-check__heading>span { color:#16a34a; }
|
|
138
|
+
.agent-tool-check.is-failed .agent-tool-check__icon,.agent-tool-check.is-failed .agent-tool-check__heading>span { color:#dc2626; }
|
|
139
|
+
.agent-tool-check__secrets { display:flex; flex-direction:column; gap:.4rem; padding:0; margin:.8rem 0 0; list-style:none; }
|
|
140
|
+
.agent-tool-check__secrets li { display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:.35rem; font-size:.75rem; }
|
|
141
|
+
.agent-tool-check__secrets code { overflow-wrap:anywhere; }
|
|
142
|
+
.agent-tool-check__secrets .is-available>span { color:#16a34a; }
|
|
143
|
+
.agent-tool-check__secrets .is-missing>span { color:#dc2626; }
|
|
144
|
+
.agent-tool-activation__success { display:flex; gap:.65rem; padding:.85rem 1rem; border-radius:.65rem; background:color-mix(in srgb,#16a34a 9%,var(--surface-card,var(--card))); color:#16a34a; }
|
|
145
|
+
.agent-tool-activation__success svg { flex-shrink:0; }
|
|
146
|
+
.agent-tool-activation__success p { margin:.25rem 0 0; font-size:.8rem; color:var(--text-color-secondary,var(--muted-foreground)); }
|
|
147
|
+
.agent-tool-activation__failure { margin:0; font-size:.82rem; color:var(--text-color-secondary,var(--muted-foreground)); }
|
|
148
|
+
.agent-tool-check .is-spinning { animation:agent-tool-check-spin 1s linear infinite; }
|
|
149
|
+
@keyframes agent-tool-check-spin { to { transform:rotate(360deg); } }
|
|
150
|
+
@media(prefers-reduced-motion:reduce) { .agent-tool-check .is-spinning { animation:none; } }
|
|
125
151
|
.agent-tool-editor__readonly-note { margin:0; padding:.75rem 1rem; border:1px solid var(--surface-border,var(--border)); border-radius:.5rem; color:var(--text-color-secondary,var(--muted-foreground)); background:var(--surface-ground,var(--background)); font-size:.875rem; }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentToolRegistryEditorPage.d.ts","sourceRoot":"","sources":["../../../../../src/routes/pages/admin/core/AgentToolRegistryEditorPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AgentToolRegistryEditorPage.d.ts","sourceRoot":"","sources":["../../../../../src/routes/pages/admin/core/AgentToolRegistryEditorPage.tsx"],"names":[],"mappings":"AAaA,OAAO,mCAAmC,CAAC;AA6D3C,wBAAgB,2BAA2B,4CAgN1C"}
|