@codewithahsan/paperclip-plugin-gsd 0.1.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 +21 -0
- package/README.md +231 -0
- package/dist/manifest.js +99 -0
- package/dist/manifest.js.map +7 -0
- package/dist/ui/index.js +536 -0
- package/dist/ui/index.js.map +7 -0
- package/dist/worker.js +7106 -0
- package/dist/worker.js.map +7 -0
- package/package.json +62 -0
package/dist/ui/index.js
ADDED
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
// src/ui/index.tsx
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import {
|
|
4
|
+
usePluginAction,
|
|
5
|
+
usePluginData,
|
|
6
|
+
usePluginToast
|
|
7
|
+
} from "@paperclipai/plugin-sdk/ui";
|
|
8
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
var card = {
|
|
10
|
+
border: "1px solid var(--border-secondary, #374151)",
|
|
11
|
+
borderRadius: 8,
|
|
12
|
+
padding: 16,
|
|
13
|
+
marginBottom: 12,
|
|
14
|
+
background: "var(--bg-secondary, #1f2937)"
|
|
15
|
+
};
|
|
16
|
+
var badge = (color) => ({
|
|
17
|
+
display: "inline-block",
|
|
18
|
+
padding: "2px 8px",
|
|
19
|
+
borderRadius: 4,
|
|
20
|
+
fontSize: 12,
|
|
21
|
+
fontWeight: 600,
|
|
22
|
+
color: "#fff",
|
|
23
|
+
background: color
|
|
24
|
+
});
|
|
25
|
+
var progressBar = {
|
|
26
|
+
height: 8,
|
|
27
|
+
borderRadius: 4,
|
|
28
|
+
background: "var(--border-secondary, #374151)",
|
|
29
|
+
overflow: "hidden",
|
|
30
|
+
marginTop: 4
|
|
31
|
+
};
|
|
32
|
+
var progressFill = (pct) => ({
|
|
33
|
+
height: "100%",
|
|
34
|
+
width: `${pct}%`,
|
|
35
|
+
background: pct === 100 ? "#22c55e" : "#3b82f6",
|
|
36
|
+
borderRadius: 4,
|
|
37
|
+
transition: "width 0.3s ease"
|
|
38
|
+
});
|
|
39
|
+
var muted = {
|
|
40
|
+
color: "var(--text-tertiary, #9ca3af)",
|
|
41
|
+
fontSize: 13
|
|
42
|
+
};
|
|
43
|
+
var heading = {
|
|
44
|
+
fontSize: 15,
|
|
45
|
+
fontWeight: 600,
|
|
46
|
+
marginBottom: 8
|
|
47
|
+
};
|
|
48
|
+
var emptyState = {
|
|
49
|
+
textAlign: "center",
|
|
50
|
+
padding: 32,
|
|
51
|
+
color: "var(--text-tertiary, #9ca3af)"
|
|
52
|
+
};
|
|
53
|
+
function phaseStatusColor(phase, isCurrent = false) {
|
|
54
|
+
const status = phase.computedStatus;
|
|
55
|
+
if (isCurrent) return "#3b82f6";
|
|
56
|
+
switch (status) {
|
|
57
|
+
case "complete":
|
|
58
|
+
return "#22c55e";
|
|
59
|
+
case "verifying":
|
|
60
|
+
return "#22c55e";
|
|
61
|
+
case "executing":
|
|
62
|
+
return "#f59e0b";
|
|
63
|
+
case "planned":
|
|
64
|
+
return "#8b5cf6";
|
|
65
|
+
case "researching":
|
|
66
|
+
return "#6366f1";
|
|
67
|
+
case "context":
|
|
68
|
+
return "#6366f1";
|
|
69
|
+
case "diagnosed":
|
|
70
|
+
return "#ef4444";
|
|
71
|
+
case "not-started":
|
|
72
|
+
default:
|
|
73
|
+
return "#94a3b8";
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function phaseStatusLabel(phase, isCurrent = false) {
|
|
77
|
+
if (isCurrent) {
|
|
78
|
+
const status = phase.computedStatus;
|
|
79
|
+
if (status === "researching" || status === "context") return "Researching";
|
|
80
|
+
if (status === "planned") return "Ready to Execute";
|
|
81
|
+
if (status === "diagnosed") return "Gaps Found";
|
|
82
|
+
if (status === "verifying") return "Verifying";
|
|
83
|
+
if (status === "complete") return "Finishing";
|
|
84
|
+
return "Executing";
|
|
85
|
+
}
|
|
86
|
+
switch (phase.computedStatus) {
|
|
87
|
+
case "complete":
|
|
88
|
+
return "Complete";
|
|
89
|
+
case "verifying":
|
|
90
|
+
return "Verifying";
|
|
91
|
+
case "diagnosed":
|
|
92
|
+
return "Gaps Found";
|
|
93
|
+
case "executing":
|
|
94
|
+
return "In Progress";
|
|
95
|
+
case "planned":
|
|
96
|
+
return "Planned";
|
|
97
|
+
case "researching":
|
|
98
|
+
return "Researched";
|
|
99
|
+
case "context":
|
|
100
|
+
return "Context Gathered";
|
|
101
|
+
case "not-started":
|
|
102
|
+
default:
|
|
103
|
+
return "Not Started";
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function GsdDashboardWidget({ context }) {
|
|
107
|
+
const { data, loading } = usePluginData("gsd-overview", { companyId: context.companyId });
|
|
108
|
+
if (loading) return /* @__PURE__ */ jsx("div", { style: muted, children: "Loading GSD status..." });
|
|
109
|
+
const projects = data?.projects ?? [];
|
|
110
|
+
if (projects.length === 0) {
|
|
111
|
+
return /* @__PURE__ */ jsxs("div", { style: emptyState, children: [
|
|
112
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: 24, marginBottom: 8 }, children: "No GSD projects" }),
|
|
113
|
+
/* @__PURE__ */ jsx("div", { children: "GSD state will appear here after agents run with GSD enabled." })
|
|
114
|
+
] });
|
|
115
|
+
}
|
|
116
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
117
|
+
/* @__PURE__ */ jsx("div", { style: heading, children: "GSD Progress" }),
|
|
118
|
+
projects.map((p) => /* @__PURE__ */ jsxs("div", { style: card, children: [
|
|
119
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 4 }, children: [
|
|
120
|
+
/* @__PURE__ */ jsx("strong", { children: p.projectName }),
|
|
121
|
+
p.milestone && /* @__PURE__ */ jsx("span", { style: badge("#6366f1"), children: p.milestone })
|
|
122
|
+
] }),
|
|
123
|
+
/* @__PURE__ */ jsxs("div", { style: muted, children: [
|
|
124
|
+
p.completedPhases,
|
|
125
|
+
"/",
|
|
126
|
+
p.totalPhases,
|
|
127
|
+
" phases \\u2022 ",
|
|
128
|
+
p.percent,
|
|
129
|
+
"%"
|
|
130
|
+
] }),
|
|
131
|
+
/* @__PURE__ */ jsx("div", { style: progressBar, children: /* @__PURE__ */ jsx("div", { style: progressFill(p.percent) }) })
|
|
132
|
+
] }, p.projectId))
|
|
133
|
+
] });
|
|
134
|
+
}
|
|
135
|
+
function GsdProjectTab({ context }) {
|
|
136
|
+
const projectId = context.entityId;
|
|
137
|
+
const { data, loading, refresh } = usePluginData(
|
|
138
|
+
"gsd-project-detail",
|
|
139
|
+
{ projectId }
|
|
140
|
+
);
|
|
141
|
+
const syncProject = usePluginAction("sync-project");
|
|
142
|
+
const toast = usePluginToast();
|
|
143
|
+
const handleSync = async () => {
|
|
144
|
+
await syncProject({ projectId, companyId: context.companyId });
|
|
145
|
+
refresh();
|
|
146
|
+
toast({ title: "GSD synced", tone: "success" });
|
|
147
|
+
};
|
|
148
|
+
if (loading) return /* @__PURE__ */ jsx("div", { style: muted, children: "Loading GSD state..." });
|
|
149
|
+
if (!data || data.phases.length === 0) {
|
|
150
|
+
return /* @__PURE__ */ jsxs("div", { style: emptyState, children: [
|
|
151
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: 20, marginBottom: 8 }, children: "No GSD data found" }),
|
|
152
|
+
/* @__PURE__ */ jsx("div", { style: { marginBottom: 16 }, children: "GSD state will appear here once an agent runs with GSD enabled in this project's workspace." }),
|
|
153
|
+
/* @__PURE__ */ jsx("button", { onClick: handleSync, style: syncButtonStyle, children: "Sync GSD" })
|
|
154
|
+
] });
|
|
155
|
+
}
|
|
156
|
+
const state = data.state;
|
|
157
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
158
|
+
/* @__PURE__ */ jsxs(
|
|
159
|
+
"div",
|
|
160
|
+
{
|
|
161
|
+
style: {
|
|
162
|
+
display: "flex",
|
|
163
|
+
justifyContent: "space-between",
|
|
164
|
+
alignItems: "center",
|
|
165
|
+
marginBottom: 16
|
|
166
|
+
},
|
|
167
|
+
children: [
|
|
168
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
169
|
+
/* @__PURE__ */ jsxs("div", { style: heading, children: [
|
|
170
|
+
"GSD Roadmap",
|
|
171
|
+
state?.milestone && /* @__PURE__ */ jsx("span", { style: { ...badge("#6366f1"), marginLeft: 8 }, children: state.milestone })
|
|
172
|
+
] }),
|
|
173
|
+
state && /* @__PURE__ */ jsxs("div", { style: muted, children: [
|
|
174
|
+
"Phase ",
|
|
175
|
+
state.currentPhase,
|
|
176
|
+
": ",
|
|
177
|
+
state.currentPhaseName,
|
|
178
|
+
" \\u2022",
|
|
179
|
+
" ",
|
|
180
|
+
state.status,
|
|
181
|
+
" \\u2022 ",
|
|
182
|
+
state.progress.percent,
|
|
183
|
+
"% overall"
|
|
184
|
+
] })
|
|
185
|
+
] }),
|
|
186
|
+
/* @__PURE__ */ jsx("button", { onClick: handleSync, style: syncButtonStyle, children: "Sync GSD" })
|
|
187
|
+
]
|
|
188
|
+
}
|
|
189
|
+
),
|
|
190
|
+
state && /* @__PURE__ */ jsxs("div", { style: { marginBottom: 16 }, children: [
|
|
191
|
+
/* @__PURE__ */ jsx("div", { style: progressBar, children: /* @__PURE__ */ jsx("div", { style: progressFill(state.progress.percent) }) }),
|
|
192
|
+
/* @__PURE__ */ jsxs("div", { style: { ...muted, marginTop: 4 }, children: [
|
|
193
|
+
state.progress.completedPhases,
|
|
194
|
+
"/",
|
|
195
|
+
state.progress.totalPhases,
|
|
196
|
+
" ",
|
|
197
|
+
"phases \\u2022 ",
|
|
198
|
+
state.progress.completedPlans,
|
|
199
|
+
"/",
|
|
200
|
+
state.progress.totalPlans,
|
|
201
|
+
" plans"
|
|
202
|
+
] })
|
|
203
|
+
] }),
|
|
204
|
+
data.phases.map((phase) => /* @__PURE__ */ jsx(
|
|
205
|
+
PhaseCard,
|
|
206
|
+
{
|
|
207
|
+
phase,
|
|
208
|
+
linkedIssueId: data.phaseIssueLinks[phase.number] ?? null,
|
|
209
|
+
isCurrent: state?.currentPhase === phase.number
|
|
210
|
+
},
|
|
211
|
+
phase.number
|
|
212
|
+
)),
|
|
213
|
+
data.lastSyncAt && /* @__PURE__ */ jsxs("div", { style: { ...muted, marginTop: 16 }, children: [
|
|
214
|
+
"Last synced: ",
|
|
215
|
+
new Date(data.lastSyncAt).toLocaleString()
|
|
216
|
+
] })
|
|
217
|
+
] });
|
|
218
|
+
}
|
|
219
|
+
function PhaseCard({
|
|
220
|
+
phase,
|
|
221
|
+
linkedIssueId,
|
|
222
|
+
isCurrent
|
|
223
|
+
}) {
|
|
224
|
+
const total = phase.plans.length;
|
|
225
|
+
const done = phase.plans.filter((p) => p.status === "complete").length;
|
|
226
|
+
const pct = total > 0 ? Math.round(done / total * 100) : 0;
|
|
227
|
+
return /* @__PURE__ */ jsxs(
|
|
228
|
+
"div",
|
|
229
|
+
{
|
|
230
|
+
style: {
|
|
231
|
+
...card,
|
|
232
|
+
borderLeft: isCurrent ? "3px solid #3b82f6" : "1px solid var(--border-secondary, #374151)"
|
|
233
|
+
},
|
|
234
|
+
children: [
|
|
235
|
+
/* @__PURE__ */ jsxs(
|
|
236
|
+
"div",
|
|
237
|
+
{
|
|
238
|
+
style: {
|
|
239
|
+
display: "flex",
|
|
240
|
+
justifyContent: "space-between",
|
|
241
|
+
alignItems: "center"
|
|
242
|
+
},
|
|
243
|
+
children: [
|
|
244
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
245
|
+
/* @__PURE__ */ jsxs("span", { style: { fontWeight: 600 }, children: [
|
|
246
|
+
"Phase ",
|
|
247
|
+
phase.number,
|
|
248
|
+
":",
|
|
249
|
+
" "
|
|
250
|
+
] }),
|
|
251
|
+
/* @__PURE__ */ jsx("span", { children: phase.slug.replace(/-/g, " ") }),
|
|
252
|
+
isCurrent && /* @__PURE__ */ jsx(
|
|
253
|
+
"span",
|
|
254
|
+
{
|
|
255
|
+
style: { ...badge("#3b82f6"), marginLeft: 8, fontSize: 11 },
|
|
256
|
+
children: "CURRENT"
|
|
257
|
+
}
|
|
258
|
+
)
|
|
259
|
+
] }),
|
|
260
|
+
/* @__PURE__ */ jsx("span", { style: badge(phaseStatusColor(phase, isCurrent)), children: phaseStatusLabel(phase, isCurrent) })
|
|
261
|
+
]
|
|
262
|
+
}
|
|
263
|
+
),
|
|
264
|
+
total > 0 && /* @__PURE__ */ jsxs("div", { style: { marginTop: 8 }, children: [
|
|
265
|
+
/* @__PURE__ */ jsx("div", { style: progressBar, children: /* @__PURE__ */ jsx("div", { style: progressFill(pct) }) }),
|
|
266
|
+
/* @__PURE__ */ jsxs("div", { style: { ...muted, marginTop: 2 }, children: [
|
|
267
|
+
done,
|
|
268
|
+
"/",
|
|
269
|
+
total,
|
|
270
|
+
" plans"
|
|
271
|
+
] })
|
|
272
|
+
] }),
|
|
273
|
+
/* @__PURE__ */ jsxs("div", { style: { marginTop: 6, display: "flex", gap: 6, flexWrap: "wrap" }, children: [
|
|
274
|
+
phase.hasContext && /* @__PURE__ */ jsx("span", { style: artifactBadge, children: "Context" }),
|
|
275
|
+
phase.hasResearch && /* @__PURE__ */ jsx("span", { style: artifactBadge, children: "Research" }),
|
|
276
|
+
phase.hasVerification && /* @__PURE__ */ jsx("span", { style: {
|
|
277
|
+
...artifactBadge,
|
|
278
|
+
color: phase.verificationStatus === "passed" ? "#22c55e" : phase.verificationStatus === "gaps_found" ? "#ef4444" : "#f59e0b"
|
|
279
|
+
}, children: phase.verificationStatus === "passed" ? "Verified" : phase.verificationStatus === "gaps_found" ? "Gaps Found" : phase.verificationStatus === "human_needed" ? "Needs Review" : "Verified" }),
|
|
280
|
+
phase.hasUat && /* @__PURE__ */ jsxs("span", { style: {
|
|
281
|
+
...artifactBadge,
|
|
282
|
+
color: phase.uatStatus === "complete" ? "#22c55e" : phase.uatStatus === "diagnosed" ? "#ef4444" : "#f59e0b"
|
|
283
|
+
}, children: [
|
|
284
|
+
"UAT ",
|
|
285
|
+
phase.uatStatus === "complete" ? "Passed" : phase.uatStatus === "diagnosed" ? "Diagnosed" : "Testing"
|
|
286
|
+
] }),
|
|
287
|
+
phase.hasContinueHere && /* @__PURE__ */ jsx("span", { style: { ...artifactBadge, color: "#f59e0b" }, children: "Paused" })
|
|
288
|
+
] }),
|
|
289
|
+
!linkedIssueId && /* @__PURE__ */ jsx("div", { style: { ...muted, marginTop: 4, fontStyle: "italic" }, children: "Not linked to an issue" })
|
|
290
|
+
]
|
|
291
|
+
}
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
function GsdIssueTab({ context }) {
|
|
295
|
+
const { data, loading } = usePluginData("gsd-issue-phase", {
|
|
296
|
+
issueId: context.entityId,
|
|
297
|
+
projectId: context.projectId ?? context.parentEntityId
|
|
298
|
+
});
|
|
299
|
+
if (loading) return /* @__PURE__ */ jsx("div", { style: muted, children: "Loading..." });
|
|
300
|
+
if (!data || !data.linked) {
|
|
301
|
+
return /* @__PURE__ */ jsxs("div", { style: emptyState, children: [
|
|
302
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: 18, marginBottom: 8 }, children: "No GSD phase linked" }),
|
|
303
|
+
/* @__PURE__ */ jsx("div", { children: "Link this issue to a GSD phase from the project's GSD tab." })
|
|
304
|
+
] });
|
|
305
|
+
}
|
|
306
|
+
if (!data.phase) {
|
|
307
|
+
return /* @__PURE__ */ jsx("div", { style: muted, children: "Linked phase not found in current GSD state." });
|
|
308
|
+
}
|
|
309
|
+
const phase = data.phase;
|
|
310
|
+
const total = phase.plans.length;
|
|
311
|
+
const done = phase.plans.filter((p) => p.status === "complete").length;
|
|
312
|
+
const pct = total > 0 ? Math.round(done / total * 100) : 0;
|
|
313
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
314
|
+
/* @__PURE__ */ jsxs("div", { style: heading, children: [
|
|
315
|
+
"Phase ",
|
|
316
|
+
phase.number,
|
|
317
|
+
": ",
|
|
318
|
+
phase.slug.replace(/-/g, " ")
|
|
319
|
+
] }),
|
|
320
|
+
/* @__PURE__ */ jsxs("div", { style: { marginBottom: 12 }, children: [
|
|
321
|
+
/* @__PURE__ */ jsx("span", { style: badge(phaseStatusColor(phase)), children: phaseStatusLabel(phase) }),
|
|
322
|
+
phase.hasVerification && /* @__PURE__ */ jsx("span", { style: { ...badge("#22c55e"), marginLeft: 8 }, children: "Verified" })
|
|
323
|
+
] }),
|
|
324
|
+
total > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
325
|
+
/* @__PURE__ */ jsx("div", { style: progressBar, children: /* @__PURE__ */ jsx("div", { style: progressFill(pct) }) }),
|
|
326
|
+
/* @__PURE__ */ jsxs("div", { style: { ...muted, marginTop: 4, marginBottom: 12 }, children: [
|
|
327
|
+
done,
|
|
328
|
+
"/",
|
|
329
|
+
total,
|
|
330
|
+
" plans complete (",
|
|
331
|
+
pct,
|
|
332
|
+
"%)"
|
|
333
|
+
] }),
|
|
334
|
+
phase.plans.map((plan) => /* @__PURE__ */ jsxs(
|
|
335
|
+
"div",
|
|
336
|
+
{
|
|
337
|
+
style: {
|
|
338
|
+
display: "flex",
|
|
339
|
+
alignItems: "center",
|
|
340
|
+
gap: 8,
|
|
341
|
+
padding: "4px 0",
|
|
342
|
+
borderBottom: "1px solid var(--border-secondary, #f1f5f9)"
|
|
343
|
+
},
|
|
344
|
+
children: [
|
|
345
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14 }, children: plan.status === "complete" ? "\u2705" : "\u2B1C" }),
|
|
346
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
347
|
+
"Plan ",
|
|
348
|
+
plan.planNumber,
|
|
349
|
+
plan.objective && /* @__PURE__ */ jsxs("span", { style: muted, children: [
|
|
350
|
+
" \\u2014 ",
|
|
351
|
+
plan.objective.slice(0, 80),
|
|
352
|
+
plan.objective.length > 80 ? "..." : ""
|
|
353
|
+
] })
|
|
354
|
+
] }),
|
|
355
|
+
plan.wave != null && /* @__PURE__ */ jsxs("span", { style: { ...muted, fontSize: 11 }, children: [
|
|
356
|
+
"wave ",
|
|
357
|
+
plan.wave
|
|
358
|
+
] })
|
|
359
|
+
]
|
|
360
|
+
},
|
|
361
|
+
`${plan.phaseNumber}-${plan.planNumber}`
|
|
362
|
+
))
|
|
363
|
+
] })
|
|
364
|
+
] });
|
|
365
|
+
}
|
|
366
|
+
function GsdSyncButton({ context }) {
|
|
367
|
+
const syncProject = usePluginAction("sync-project");
|
|
368
|
+
const toast = usePluginToast();
|
|
369
|
+
const handleSync = async () => {
|
|
370
|
+
await syncProject({
|
|
371
|
+
projectId: context.entityId,
|
|
372
|
+
companyId: context.companyId
|
|
373
|
+
});
|
|
374
|
+
toast({ title: "GSD synced", tone: "success" });
|
|
375
|
+
};
|
|
376
|
+
return /* @__PURE__ */ jsx("button", { onClick: handleSync, style: syncButtonStyle, children: "Sync GSD" });
|
|
377
|
+
}
|
|
378
|
+
function GsdSettingsPage({ context }) {
|
|
379
|
+
const { data: compatData, loading: compatLoading } = usePluginData("gsd-adapter-compat", { companyId: context.companyId });
|
|
380
|
+
const { data: configData, loading: configLoading, refresh: refreshConfig } = usePluginData("gsd-config", {});
|
|
381
|
+
const syncAll = usePluginAction("sync-all");
|
|
382
|
+
const updateConfig = usePluginAction("update-config");
|
|
383
|
+
const toast = usePluginToast();
|
|
384
|
+
const [autoSync, setAutoSync] = useState(null);
|
|
385
|
+
const [interval, setInterval] = useState("");
|
|
386
|
+
const [saving, setSaving] = useState(false);
|
|
387
|
+
const currentAutoSync = autoSync ?? configData?.autoSyncEnabled ?? true;
|
|
388
|
+
const currentInterval = interval || String(configData?.syncIntervalSeconds ?? 30);
|
|
389
|
+
const handleSyncAll = async () => {
|
|
390
|
+
const result = await syncAll({
|
|
391
|
+
companyId: context.companyId
|
|
392
|
+
});
|
|
393
|
+
toast({
|
|
394
|
+
title: `Synced ${result?.synced ?? 0} workspace(s)`,
|
|
395
|
+
tone: "success"
|
|
396
|
+
});
|
|
397
|
+
};
|
|
398
|
+
const handleSaveConfig = async () => {
|
|
399
|
+
const parsedInterval = Math.max(10, Math.min(600, Number(currentInterval) || 30));
|
|
400
|
+
setSaving(true);
|
|
401
|
+
try {
|
|
402
|
+
await updateConfig({
|
|
403
|
+
autoSyncEnabled: currentAutoSync,
|
|
404
|
+
syncIntervalSeconds: parsedInterval
|
|
405
|
+
});
|
|
406
|
+
refreshConfig();
|
|
407
|
+
setAutoSync(null);
|
|
408
|
+
setInterval("");
|
|
409
|
+
toast({ title: "Settings saved", tone: "success" });
|
|
410
|
+
} catch {
|
|
411
|
+
toast({ title: "Failed to save settings", tone: "error" });
|
|
412
|
+
} finally {
|
|
413
|
+
setSaving(false);
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
const hasChanges = autoSync !== null || interval !== "" && Number(interval) !== configData?.syncIntervalSeconds;
|
|
417
|
+
return /* @__PURE__ */ jsxs("div", { style: { maxWidth: 640 }, children: [
|
|
418
|
+
/* @__PURE__ */ jsx("div", { style: heading, children: "GSD Settings" }),
|
|
419
|
+
/* @__PURE__ */ jsxs("div", { style: { ...card, marginBottom: 24 }, children: [
|
|
420
|
+
/* @__PURE__ */ jsx("div", { style: { ...heading, marginBottom: 12 }, children: "Auto-Sync" }),
|
|
421
|
+
configLoading ? /* @__PURE__ */ jsx("div", { style: muted, children: "Loading configuration..." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
422
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", alignItems: "center", gap: 12, marginBottom: 12 }, children: /* @__PURE__ */ jsxs("label", { style: { display: "flex", alignItems: "center", gap: 8, cursor: "pointer" }, children: [
|
|
423
|
+
/* @__PURE__ */ jsx(
|
|
424
|
+
"input",
|
|
425
|
+
{
|
|
426
|
+
type: "checkbox",
|
|
427
|
+
checked: currentAutoSync,
|
|
428
|
+
onChange: (e) => setAutoSync(e.target.checked),
|
|
429
|
+
style: { width: 16, height: 16, cursor: "pointer" }
|
|
430
|
+
}
|
|
431
|
+
),
|
|
432
|
+
/* @__PURE__ */ jsx("span", { children: "Enable periodic sync" })
|
|
433
|
+
] }) }),
|
|
434
|
+
/* @__PURE__ */ jsxs("div", { style: { marginBottom: 12 }, children: [
|
|
435
|
+
/* @__PURE__ */ jsx("label", { style: { display: "block", marginBottom: 4 }, children: /* @__PURE__ */ jsx("span", { style: muted, children: "Sync interval (seconds, 10\\u2013600)" }) }),
|
|
436
|
+
/* @__PURE__ */ jsx(
|
|
437
|
+
"input",
|
|
438
|
+
{
|
|
439
|
+
type: "number",
|
|
440
|
+
min: 10,
|
|
441
|
+
max: 600,
|
|
442
|
+
value: currentInterval,
|
|
443
|
+
onChange: (e) => setInterval(e.target.value),
|
|
444
|
+
disabled: !currentAutoSync,
|
|
445
|
+
style: {
|
|
446
|
+
...inputStyle,
|
|
447
|
+
opacity: currentAutoSync ? 1 : 0.5
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
)
|
|
451
|
+
] }),
|
|
452
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8 }, children: [
|
|
453
|
+
/* @__PURE__ */ jsx(
|
|
454
|
+
"button",
|
|
455
|
+
{
|
|
456
|
+
onClick: handleSaveConfig,
|
|
457
|
+
disabled: saving || !hasChanges,
|
|
458
|
+
style: {
|
|
459
|
+
...syncButtonStyle,
|
|
460
|
+
opacity: saving || !hasChanges ? 0.5 : 1
|
|
461
|
+
},
|
|
462
|
+
children: saving ? "Saving..." : "Save"
|
|
463
|
+
}
|
|
464
|
+
),
|
|
465
|
+
/* @__PURE__ */ jsx("button", { onClick: handleSyncAll, style: syncButtonStyle, children: "Sync All Projects" })
|
|
466
|
+
] })
|
|
467
|
+
] })
|
|
468
|
+
] }),
|
|
469
|
+
/* @__PURE__ */ jsx("div", { style: heading, children: "Agent Compatibility" }),
|
|
470
|
+
compatLoading && /* @__PURE__ */ jsx("div", { style: muted, children: "Loading..." }),
|
|
471
|
+
compatData?.agents.map((agent) => /* @__PURE__ */ jsxs("div", { style: card, children: [
|
|
472
|
+
/* @__PURE__ */ jsxs(
|
|
473
|
+
"div",
|
|
474
|
+
{
|
|
475
|
+
style: {
|
|
476
|
+
display: "flex",
|
|
477
|
+
justifyContent: "space-between",
|
|
478
|
+
alignItems: "center"
|
|
479
|
+
},
|
|
480
|
+
children: [
|
|
481
|
+
/* @__PURE__ */ jsx("strong", { children: agent.agentName }),
|
|
482
|
+
/* @__PURE__ */ jsx(
|
|
483
|
+
"span",
|
|
484
|
+
{
|
|
485
|
+
style: badge(
|
|
486
|
+
agent.compatibility === "supported" ? "#22c55e" : agent.compatibility === "partial" ? "#f59e0b" : "#ef4444"
|
|
487
|
+
),
|
|
488
|
+
children: agent.compatibility
|
|
489
|
+
}
|
|
490
|
+
)
|
|
491
|
+
]
|
|
492
|
+
}
|
|
493
|
+
),
|
|
494
|
+
/* @__PURE__ */ jsxs("div", { style: { ...muted, marginTop: 4 }, children: [
|
|
495
|
+
agent.adapterType,
|
|
496
|
+
" \u2014 ",
|
|
497
|
+
agent.message
|
|
498
|
+
] })
|
|
499
|
+
] }, agent.agentId)),
|
|
500
|
+
!compatLoading && (!compatData?.agents || compatData.agents.length === 0) && /* @__PURE__ */ jsx("div", { style: muted, children: "No agents found for this company." })
|
|
501
|
+
] });
|
|
502
|
+
}
|
|
503
|
+
var artifactBadge = {
|
|
504
|
+
fontSize: 11,
|
|
505
|
+
color: "var(--text-tertiary, #9ca3af)",
|
|
506
|
+
border: "1px solid var(--border-secondary, #374151)",
|
|
507
|
+
borderRadius: 4,
|
|
508
|
+
padding: "1px 6px"
|
|
509
|
+
};
|
|
510
|
+
var syncButtonStyle = {
|
|
511
|
+
padding: "6px 16px",
|
|
512
|
+
borderRadius: 6,
|
|
513
|
+
border: "1px solid var(--border-secondary, #374151)",
|
|
514
|
+
background: "var(--bg-secondary, #1f2937)",
|
|
515
|
+
color: "var(--text-primary, #e5e7eb)",
|
|
516
|
+
cursor: "pointer",
|
|
517
|
+
fontSize: 13,
|
|
518
|
+
fontWeight: 500
|
|
519
|
+
};
|
|
520
|
+
var inputStyle = {
|
|
521
|
+
padding: "6px 10px",
|
|
522
|
+
borderRadius: 6,
|
|
523
|
+
border: "1px solid var(--border-secondary, #374151)",
|
|
524
|
+
background: "var(--bg-primary, #111827)",
|
|
525
|
+
color: "var(--text-primary, #e5e7eb)",
|
|
526
|
+
fontSize: 13,
|
|
527
|
+
width: 120
|
|
528
|
+
};
|
|
529
|
+
export {
|
|
530
|
+
GsdDashboardWidget,
|
|
531
|
+
GsdIssueTab,
|
|
532
|
+
GsdProjectTab,
|
|
533
|
+
GsdSettingsPage,
|
|
534
|
+
GsdSyncButton
|
|
535
|
+
};
|
|
536
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/ui/index.tsx"],
|
|
4
|
+
"sourcesContent": ["import { useState } from \"react\";\nimport {\n useHostContext,\n usePluginAction,\n usePluginData,\n usePluginToast,\n type PluginDetailTabProps,\n type PluginPageProps,\n type PluginWidgetProps,\n} from \"@paperclipai/plugin-sdk/ui\";\nimport type {\n GsdPhase,\n GsdPluginState,\n GsdProjectSummary,\n} from \"../gsd-types.js\";\n\n// --- Styles ---\n\nconst card: React.CSSProperties = {\n border: \"1px solid var(--border-secondary, #374151)\",\n borderRadius: 8,\n padding: 16,\n marginBottom: 12,\n background: \"var(--bg-secondary, #1f2937)\",\n};\n\nconst badge = (\n color: string,\n): React.CSSProperties => ({\n display: \"inline-block\",\n padding: \"2px 8px\",\n borderRadius: 4,\n fontSize: 12,\n fontWeight: 600,\n color: \"#fff\",\n background: color,\n});\n\nconst progressBar: React.CSSProperties = {\n height: 8,\n borderRadius: 4,\n background: \"var(--border-secondary, #374151)\",\n overflow: \"hidden\",\n marginTop: 4,\n};\n\nconst progressFill = (pct: number): React.CSSProperties => ({\n height: \"100%\",\n width: `${pct}%`,\n background: pct === 100 ? \"#22c55e\" : \"#3b82f6\",\n borderRadius: 4,\n transition: \"width 0.3s ease\",\n});\n\nconst muted: React.CSSProperties = {\n color: \"var(--text-tertiary, #9ca3af)\",\n fontSize: 13,\n};\n\nconst heading: React.CSSProperties = {\n fontSize: 15,\n fontWeight: 600,\n marginBottom: 8,\n};\n\nconst emptyState: React.CSSProperties = {\n textAlign: \"center\" as const,\n padding: 32,\n color: \"var(--text-tertiary, #9ca3af)\",\n};\n\n// --- Status helpers ---\n\nfunction phaseStatusColor(phase: GsdPhase, isCurrent = false): string {\n const status = phase.computedStatus;\n if (isCurrent) return \"#3b82f6\";\n switch (status) {\n case \"complete\": return \"#22c55e\";\n case \"verifying\": return \"#22c55e\";\n case \"executing\": return \"#f59e0b\";\n case \"planned\": return \"#8b5cf6\";\n case \"researching\": return \"#6366f1\";\n case \"context\": return \"#6366f1\";\n case \"diagnosed\": return \"#ef4444\";\n case \"not-started\":\n default: return \"#94a3b8\";\n }\n}\n\nfunction phaseStatusLabel(phase: GsdPhase, isCurrent = false): string {\n // Current phase in STATE.md means GSD is actively working on it \u2014\n // even if all SUMMARY.md exist, verification/UAT may still be running\n if (isCurrent) {\n const status = phase.computedStatus;\n if (status === \"researching\" || status === \"context\") return \"Researching\";\n if (status === \"planned\") return \"Ready to Execute\";\n if (status === \"diagnosed\") return \"Gaps Found\";\n if (status === \"verifying\") return \"Verifying\";\n // All plans done but still current phase \u2192 verification/UAT in progress\n if (status === \"complete\") return \"Finishing\";\n return \"Executing\";\n }\n switch (phase.computedStatus) {\n case \"complete\": return \"Complete\";\n case \"verifying\": return \"Verifying\";\n case \"diagnosed\": return \"Gaps Found\";\n case \"executing\": return \"In Progress\";\n case \"planned\": return \"Planned\";\n case \"researching\": return \"Researched\";\n case \"context\": return \"Context Gathered\";\n case \"not-started\":\n default: return \"Not Started\";\n }\n}\n\n// --- Dashboard Widget ---\n\nexport function GsdDashboardWidget({ context }: PluginWidgetProps) {\n const { data, loading } = usePluginData<{\n projects: GsdProjectSummary[];\n }>(\"gsd-overview\", { companyId: context.companyId });\n\n if (loading) return <div style={muted}>Loading GSD status...</div>;\n\n const projects = data?.projects ?? [];\n\n if (projects.length === 0) {\n return (\n <div style={emptyState}>\n <div style={{ fontSize: 24, marginBottom: 8 }}>No GSD projects</div>\n <div>GSD state will appear here after agents run with GSD enabled.</div>\n </div>\n );\n }\n\n return (\n <div>\n <div style={heading}>GSD Progress</div>\n {projects.map((p) => (\n <div key={p.projectId} style={card}>\n <div style={{ display: \"flex\", justifyContent: \"space-between\", marginBottom: 4 }}>\n <strong>{p.projectName}</strong>\n {p.milestone && (\n <span style={badge(\"#6366f1\")}>{p.milestone}</span>\n )}\n </div>\n <div style={muted}>\n {p.completedPhases}/{p.totalPhases} phases \\u2022 {p.percent}%\n </div>\n <div style={progressBar}>\n <div style={progressFill(p.percent)} />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\n// --- Project Detail Tab ---\n\nexport function GsdProjectTab({ context }: PluginDetailTabProps) {\n const projectId = context.entityId;\n const { data, loading, refresh } = usePluginData<GsdPluginState | null>(\n \"gsd-project-detail\",\n { projectId },\n );\n const syncProject = usePluginAction(\"sync-project\");\n const toast = usePluginToast();\n\n const handleSync = async () => {\n await syncProject({ projectId, companyId: context.companyId });\n refresh();\n toast({ title: \"GSD synced\", tone: \"success\" });\n };\n\n if (loading) return <div style={muted}>Loading GSD state...</div>;\n\n if (!data || data.phases.length === 0) {\n return (\n <div style={emptyState}>\n <div style={{ fontSize: 20, marginBottom: 8 }}>\n No GSD data found\n </div>\n <div style={{ marginBottom: 16 }}>\n GSD state will appear here once an agent runs with GSD enabled in\n this project's workspace.\n </div>\n <button onClick={handleSync} style={syncButtonStyle}>\n Sync GSD\n </button>\n </div>\n );\n }\n\n const state = data.state;\n\n return (\n <div>\n {/* Header */}\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: 16,\n }}\n >\n <div>\n <div style={heading}>\n GSD Roadmap\n {state?.milestone && (\n <span style={{ ...badge(\"#6366f1\"), marginLeft: 8 }}>\n {state.milestone}\n </span>\n )}\n </div>\n {state && (\n <div style={muted}>\n Phase {state.currentPhase}: {state.currentPhaseName} \\u2022{\" \"}\n {state.status} \\u2022 {state.progress.percent}% overall\n </div>\n )}\n </div>\n <button onClick={handleSync} style={syncButtonStyle}>\n Sync GSD\n </button>\n </div>\n\n {/* Overall progress */}\n {state && (\n <div style={{ marginBottom: 16 }}>\n <div style={progressBar}>\n <div style={progressFill(state.progress.percent)} />\n </div>\n <div style={{ ...muted, marginTop: 4 }}>\n {state.progress.completedPhases}/{state.progress.totalPhases}{\" \"}\n phases \\u2022 {state.progress.completedPlans}/\n {state.progress.totalPlans} plans\n </div>\n </div>\n )}\n\n {/* Phase list */}\n {data.phases.map((phase) => (\n <PhaseCard\n key={phase.number}\n phase={phase}\n linkedIssueId={data.phaseIssueLinks[phase.number] ?? null}\n isCurrent={state?.currentPhase === phase.number}\n />\n ))}\n\n {/* Last sync */}\n {data.lastSyncAt && (\n <div style={{ ...muted, marginTop: 16 }}>\n Last synced: {new Date(data.lastSyncAt).toLocaleString()}\n </div>\n )}\n </div>\n );\n}\n\nfunction PhaseCard({\n phase,\n linkedIssueId,\n isCurrent,\n}: {\n phase: GsdPhase;\n linkedIssueId: string | null;\n isCurrent: boolean;\n}) {\n const total = phase.plans.length;\n const done = phase.plans.filter((p) => p.status === \"complete\").length;\n const pct = total > 0 ? Math.round((done / total) * 100) : 0;\n\n return (\n <div\n style={{\n ...card,\n borderLeft: isCurrent\n ? \"3px solid #3b82f6\"\n : \"1px solid var(--border-secondary, #374151)\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <div>\n <span style={{ fontWeight: 600 }}>\n Phase {phase.number}:{\" \"}\n </span>\n <span>{phase.slug.replace(/-/g, \" \")}</span>\n {isCurrent && (\n <span\n style={{ ...badge(\"#3b82f6\"), marginLeft: 8, fontSize: 11 }}\n >\n CURRENT\n </span>\n )}\n </div>\n <span style={badge(phaseStatusColor(phase, isCurrent))}>\n {phaseStatusLabel(phase, isCurrent)}\n </span>\n </div>\n\n {total > 0 && (\n <div style={{ marginTop: 8 }}>\n <div style={progressBar}>\n <div style={progressFill(pct)} />\n </div>\n <div style={{ ...muted, marginTop: 2 }}>\n {done}/{total} plans\n </div>\n </div>\n )}\n\n {/* Phase artifacts */}\n <div style={{ marginTop: 6, display: \"flex\", gap: 6, flexWrap: \"wrap\" }}>\n {phase.hasContext && (\n <span style={artifactBadge}>Context</span>\n )}\n {phase.hasResearch && (\n <span style={artifactBadge}>Research</span>\n )}\n {phase.hasVerification && (\n <span style={{\n ...artifactBadge,\n color: phase.verificationStatus === \"passed\" ? \"#22c55e\"\n : phase.verificationStatus === \"gaps_found\" ? \"#ef4444\"\n : \"#f59e0b\",\n }}>\n {phase.verificationStatus === \"passed\" ? \"Verified\"\n : phase.verificationStatus === \"gaps_found\" ? \"Gaps Found\"\n : phase.verificationStatus === \"human_needed\" ? \"Needs Review\"\n : \"Verified\"}\n </span>\n )}\n {phase.hasUat && (\n <span style={{\n ...artifactBadge,\n color: phase.uatStatus === \"complete\" ? \"#22c55e\"\n : phase.uatStatus === \"diagnosed\" ? \"#ef4444\"\n : \"#f59e0b\",\n }}>\n UAT {phase.uatStatus === \"complete\" ? \"Passed\"\n : phase.uatStatus === \"diagnosed\" ? \"Diagnosed\"\n : \"Testing\"}\n </span>\n )}\n {phase.hasContinueHere && (\n <span style={{ ...artifactBadge, color: \"#f59e0b\" }}>Paused</span>\n )}\n </div>\n\n {!linkedIssueId && (\n <div style={{ ...muted, marginTop: 4, fontStyle: \"italic\" }}>\n Not linked to an issue\n </div>\n )}\n </div>\n );\n}\n\n// --- Issue Detail Tab ---\n\nexport function GsdIssueTab({ context }: PluginDetailTabProps) {\n const { data, loading } = usePluginData<{\n linked: boolean;\n phase: GsdPhase | null;\n state: { currentPhase: string; status: string } | null;\n } | null>(\"gsd-issue-phase\", {\n issueId: context.entityId,\n projectId: context.projectId ?? context.parentEntityId,\n });\n\n if (loading) return <div style={muted}>Loading...</div>;\n if (!data || !data.linked) {\n return (\n <div style={emptyState}>\n <div style={{ fontSize: 18, marginBottom: 8 }}>\n No GSD phase linked\n </div>\n <div>\n Link this issue to a GSD phase from the project's GSD tab.\n </div>\n </div>\n );\n }\n\n if (!data.phase) {\n return <div style={muted}>Linked phase not found in current GSD state.</div>;\n }\n\n const phase = data.phase;\n const total = phase.plans.length;\n const done = phase.plans.filter((p) => p.status === \"complete\").length;\n const pct = total > 0 ? Math.round((done / total) * 100) : 0;\n\n return (\n <div>\n <div style={heading}>\n Phase {phase.number}: {phase.slug.replace(/-/g, \" \")}\n </div>\n <div style={{ marginBottom: 12 }}>\n <span style={badge(phaseStatusColor(phase))}>\n {phaseStatusLabel(phase)}\n </span>\n {phase.hasVerification && (\n <span style={{ ...badge(\"#22c55e\"), marginLeft: 8 }}>\n Verified\n </span>\n )}\n </div>\n\n {total > 0 && (\n <>\n <div style={progressBar}>\n <div style={progressFill(pct)} />\n </div>\n <div style={{ ...muted, marginTop: 4, marginBottom: 12 }}>\n {done}/{total} plans complete ({pct}%)\n </div>\n\n {/* Plan list */}\n {phase.plans.map((plan) => (\n <div\n key={`${plan.phaseNumber}-${plan.planNumber}`}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"4px 0\",\n borderBottom:\n \"1px solid var(--border-secondary, #f1f5f9)\",\n }}\n >\n <span style={{ fontSize: 14 }}>\n {plan.status === \"complete\" ? \"\\u2705\" : \"\\u2B1C\"}\n </span>\n <span>\n Plan {plan.planNumber}\n {plan.objective && (\n <span style={muted}> \\u2014 {plan.objective.slice(0, 80)}{plan.objective.length > 80 ? \"...\" : \"\"}</span>\n )}\n </span>\n {plan.wave != null && (\n <span style={{ ...muted, fontSize: 11 }}>\n wave {plan.wave}\n </span>\n )}\n </div>\n ))}\n </>\n )}\n </div>\n );\n}\n\n// --- Sync Toolbar Button ---\n\nexport function GsdSyncButton({ context }: PluginDetailTabProps) {\n const syncProject = usePluginAction(\"sync-project\");\n const toast = usePluginToast();\n\n const handleSync = async () => {\n await syncProject({\n projectId: context.entityId,\n companyId: context.companyId,\n });\n toast({ title: \"GSD synced\", tone: \"success\" });\n };\n\n return (\n <button onClick={handleSync} style={syncButtonStyle}>\n Sync GSD\n </button>\n );\n}\n\n// --- Settings Page ---\n\nexport function GsdSettingsPage({ context }: PluginPageProps) {\n const { data: compatData, loading: compatLoading } = usePluginData<{\n agents: Array<{\n agentId: string;\n agentName: string;\n adapterType: string;\n compatibility: string;\n message: string;\n }>;\n }>(\"gsd-adapter-compat\", { companyId: context.companyId });\n const { data: configData, loading: configLoading, refresh: refreshConfig } = usePluginData<{\n autoSyncEnabled: boolean;\n syncIntervalSeconds: number;\n }>(\"gsd-config\", {});\n const syncAll = usePluginAction(\"sync-all\");\n const updateConfig = usePluginAction(\"update-config\");\n const toast = usePluginToast();\n\n const [autoSync, setAutoSync] = useState<boolean | null>(null);\n const [interval, setInterval] = useState<string>(\"\");\n const [saving, setSaving] = useState(false);\n\n // Use local state if set, otherwise fall back to server data\n const currentAutoSync = autoSync ?? configData?.autoSyncEnabled ?? true;\n const currentInterval = interval || String(configData?.syncIntervalSeconds ?? 30);\n\n const handleSyncAll = async () => {\n const result = (await syncAll({\n companyId: context.companyId,\n })) as { ok: boolean; synced: number } | undefined;\n toast({\n title: `Synced ${result?.synced ?? 0} workspace(s)`,\n tone: \"success\",\n });\n };\n\n const handleSaveConfig = async () => {\n const parsedInterval = Math.max(10, Math.min(600, Number(currentInterval) || 30));\n setSaving(true);\n try {\n await updateConfig({\n autoSyncEnabled: currentAutoSync,\n syncIntervalSeconds: parsedInterval,\n });\n refreshConfig();\n setAutoSync(null);\n setInterval(\"\");\n toast({ title: \"Settings saved\", tone: \"success\" });\n } catch {\n toast({ title: \"Failed to save settings\", tone: \"error\" });\n } finally {\n setSaving(false);\n }\n };\n\n const hasChanges =\n autoSync !== null ||\n (interval !== \"\" && Number(interval) !== configData?.syncIntervalSeconds);\n\n return (\n <div style={{ maxWidth: 640 }}>\n <div style={heading}>GSD Settings</div>\n\n {/* Auto-sync configuration */}\n <div style={{ ...card, marginBottom: 24 }}>\n <div style={{ ...heading, marginBottom: 12 }}>Auto-Sync</div>\n\n {configLoading ? (\n <div style={muted}>Loading configuration...</div>\n ) : (\n <>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 12, marginBottom: 12 }}>\n <label style={{ display: \"flex\", alignItems: \"center\", gap: 8, cursor: \"pointer\" }}>\n <input\n type=\"checkbox\"\n checked={currentAutoSync}\n onChange={(e) => setAutoSync(e.target.checked)}\n style={{ width: 16, height: 16, cursor: \"pointer\" }}\n />\n <span>Enable periodic sync</span>\n </label>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={{ display: \"block\", marginBottom: 4 }}>\n <span style={muted}>Sync interval (seconds, 10\\u2013600)</span>\n </label>\n <input\n type=\"number\"\n min={10}\n max={600}\n value={currentInterval}\n onChange={(e) => setInterval(e.target.value)}\n disabled={!currentAutoSync}\n style={{\n ...inputStyle,\n opacity: currentAutoSync ? 1 : 0.5,\n }}\n />\n </div>\n\n <div style={{ display: \"flex\", gap: 8 }}>\n <button\n onClick={handleSaveConfig}\n disabled={saving || !hasChanges}\n style={{\n ...syncButtonStyle,\n opacity: saving || !hasChanges ? 0.5 : 1,\n }}\n >\n {saving ? \"Saving...\" : \"Save\"}\n </button>\n <button onClick={handleSyncAll} style={syncButtonStyle}>\n Sync All Projects\n </button>\n </div>\n </>\n )}\n </div>\n\n {/* Agent compatibility */}\n <div style={heading}>Agent Compatibility</div>\n {compatLoading && <div style={muted}>Loading...</div>}\n\n {compatData?.agents.map((agent) => (\n <div key={agent.agentId} style={card}>\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <strong>{agent.agentName}</strong>\n <span\n style={badge(\n agent.compatibility === \"supported\"\n ? \"#22c55e\"\n : agent.compatibility === \"partial\"\n ? \"#f59e0b\"\n : \"#ef4444\",\n )}\n >\n {agent.compatibility}\n </span>\n </div>\n <div style={{ ...muted, marginTop: 4 }}>\n {agent.adapterType} \u2014 {agent.message}\n </div>\n </div>\n ))}\n\n {!compatLoading && (!compatData?.agents || compatData.agents.length === 0) && (\n <div style={muted}>No agents found for this company.</div>\n )}\n </div>\n );\n}\n\n// --- Shared styles ---\n\nconst artifactBadge: React.CSSProperties = {\n fontSize: 11,\n color: \"var(--text-tertiary, #9ca3af)\",\n border: \"1px solid var(--border-secondary, #374151)\",\n borderRadius: 4,\n padding: \"1px 6px\",\n};\n\nconst syncButtonStyle: React.CSSProperties = {\n padding: \"6px 16px\",\n borderRadius: 6,\n border: \"1px solid var(--border-secondary, #374151)\",\n background: \"var(--bg-secondary, #1f2937)\",\n color: \"var(--text-primary, #e5e7eb)\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 500,\n};\n\nconst inputStyle: React.CSSProperties = {\n padding: \"6px 10px\",\n borderRadius: 6,\n border: \"1px solid var(--border-secondary, #374151)\",\n background: \"var(--bg-primary, #111827)\",\n color: \"var(--text-primary, #e5e7eb)\",\n fontSize: 13,\n width: 120,\n};\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,gBAAgB;AACzB;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAiHe,SAySd,UAzSc,KAMhB,YANgB;AAxGtB,IAAM,OAA4B;AAAA,EAChC,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,SAAS;AAAA,EACT,cAAc;AAAA,EACd,YAAY;AACd;AAEA,IAAM,QAAQ,CACZ,WACyB;AAAA,EACzB,SAAS;AAAA,EACT,SAAS;AAAA,EACT,cAAc;AAAA,EACd,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,YAAY;AACd;AAEA,IAAM,cAAmC;AAAA,EACvC,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,WAAW;AACb;AAEA,IAAM,eAAe,CAAC,SAAsC;AAAA,EAC1D,QAAQ;AAAA,EACR,OAAO,GAAG,GAAG;AAAA,EACb,YAAY,QAAQ,MAAM,YAAY;AAAA,EACtC,cAAc;AAAA,EACd,YAAY;AACd;AAEA,IAAM,QAA6B;AAAA,EACjC,OAAO;AAAA,EACP,UAAU;AACZ;AAEA,IAAM,UAA+B;AAAA,EACnC,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,cAAc;AAChB;AAEA,IAAM,aAAkC;AAAA,EACtC,WAAW;AAAA,EACX,SAAS;AAAA,EACT,OAAO;AACT;AAIA,SAAS,iBAAiB,OAAiB,YAAY,OAAe;AACpE,QAAM,SAAS,MAAM;AACrB,MAAI,UAAW,QAAO;AACtB,UAAQ,QAAQ;AAAA,IACd,KAAK;AAAY,aAAO;AAAA,IACxB,KAAK;AAAa,aAAO;AAAA,IACzB,KAAK;AAAa,aAAO;AAAA,IACzB,KAAK;AAAW,aAAO;AAAA,IACvB,KAAK;AAAe,aAAO;AAAA,IAC3B,KAAK;AAAW,aAAO;AAAA,IACvB,KAAK;AAAa,aAAO;AAAA,IACzB,KAAK;AAAA,IACL;AAAS,aAAO;AAAA,EAClB;AACF;AAEA,SAAS,iBAAiB,OAAiB,YAAY,OAAe;AAGpE,MAAI,WAAW;AACb,UAAM,SAAS,MAAM;AACrB,QAAI,WAAW,iBAAiB,WAAW,UAAW,QAAO;AAC7D,QAAI,WAAW,UAAW,QAAO;AACjC,QAAI,WAAW,YAAa,QAAO;AACnC,QAAI,WAAW,YAAa,QAAO;AAEnC,QAAI,WAAW,WAAY,QAAO;AAClC,WAAO;AAAA,EACT;AACA,UAAQ,MAAM,gBAAgB;AAAA,IAC5B,KAAK;AAAY,aAAO;AAAA,IACxB,KAAK;AAAa,aAAO;AAAA,IACzB,KAAK;AAAa,aAAO;AAAA,IACzB,KAAK;AAAa,aAAO;AAAA,IACzB,KAAK;AAAW,aAAO;AAAA,IACvB,KAAK;AAAe,aAAO;AAAA,IAC3B,KAAK;AAAW,aAAO;AAAA,IACvB,KAAK;AAAA,IACL;AAAS,aAAO;AAAA,EAClB;AACF;AAIO,SAAS,mBAAmB,EAAE,QAAQ,GAAsB;AACjE,QAAM,EAAE,MAAM,QAAQ,IAAI,cAEvB,gBAAgB,EAAE,WAAW,QAAQ,UAAU,CAAC;AAEnD,MAAI,QAAS,QAAO,oBAAC,SAAI,OAAO,OAAO,mCAAqB;AAE5D,QAAM,WAAW,MAAM,YAAY,CAAC;AAEpC,MAAI,SAAS,WAAW,GAAG;AACzB,WACE,qBAAC,SAAI,OAAO,YACV;AAAA,0BAAC,SAAI,OAAO,EAAE,UAAU,IAAI,cAAc,EAAE,GAAG,6BAAe;AAAA,MAC9D,oBAAC,SAAI,2EAA6D;AAAA,OACpE;AAAA,EAEJ;AAEA,SACE,qBAAC,SACC;AAAA,wBAAC,SAAI,OAAO,SAAS,0BAAY;AAAA,IAChC,SAAS,IAAI,CAAC,MACb,qBAAC,SAAsB,OAAO,MAC5B;AAAA,2BAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,gBAAgB,iBAAiB,cAAc,EAAE,GAC9E;AAAA,4BAAC,YAAQ,YAAE,aAAY;AAAA,QACtB,EAAE,aACD,oBAAC,UAAK,OAAO,MAAM,SAAS,GAAI,YAAE,WAAU;AAAA,SAEhD;AAAA,MACA,qBAAC,SAAI,OAAO,OACT;AAAA,UAAE;AAAA,QAAgB;AAAA,QAAE,EAAE;AAAA,QAAY;AAAA,QAAgB,EAAE;AAAA,QAAQ;AAAA,SAC/D;AAAA,MACA,oBAAC,SAAI,OAAO,aACV,8BAAC,SAAI,OAAO,aAAa,EAAE,OAAO,GAAG,GACvC;AAAA,SAZQ,EAAE,SAaZ,CACD;AAAA,KACH;AAEJ;AAIO,SAAS,cAAc,EAAE,QAAQ,GAAyB;AAC/D,QAAM,YAAY,QAAQ;AAC1B,QAAM,EAAE,MAAM,SAAS,QAAQ,IAAI;AAAA,IACjC;AAAA,IACA,EAAE,UAAU;AAAA,EACd;AACA,QAAM,cAAc,gBAAgB,cAAc;AAClD,QAAM,QAAQ,eAAe;AAE7B,QAAM,aAAa,YAAY;AAC7B,UAAM,YAAY,EAAE,WAAW,WAAW,QAAQ,UAAU,CAAC;AAC7D,YAAQ;AACR,UAAM,EAAE,OAAO,cAAc,MAAM,UAAU,CAAC;AAAA,EAChD;AAEA,MAAI,QAAS,QAAO,oBAAC,SAAI,OAAO,OAAO,kCAAoB;AAE3D,MAAI,CAAC,QAAQ,KAAK,OAAO,WAAW,GAAG;AACrC,WACE,qBAAC,SAAI,OAAO,YACV;AAAA,0BAAC,SAAI,OAAO,EAAE,UAAU,IAAI,cAAc,EAAE,GAAG,+BAE/C;AAAA,MACA,oBAAC,SAAI,OAAO,EAAE,cAAc,GAAG,GAAG,yGAGlC;AAAA,MACA,oBAAC,YAAO,SAAS,YAAY,OAAO,iBAAiB,sBAErD;AAAA,OACF;AAAA,EAEJ;AAEA,QAAM,QAAQ,KAAK;AAEnB,SACE,qBAAC,SAEC;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,SAAS;AAAA,UACT,gBAAgB;AAAA,UAChB,YAAY;AAAA,UACZ,cAAc;AAAA,QAChB;AAAA,QAEA;AAAA,+BAAC,SACC;AAAA,iCAAC,SAAI,OAAO,SAAS;AAAA;AAAA,cAElB,OAAO,aACN,oBAAC,UAAK,OAAO,EAAE,GAAG,MAAM,SAAS,GAAG,YAAY,EAAE,GAC/C,gBAAM,WACT;AAAA,eAEJ;AAAA,YACC,SACC,qBAAC,SAAI,OAAO,OAAO;AAAA;AAAA,cACV,MAAM;AAAA,cAAa;AAAA,cAAG,MAAM;AAAA,cAAiB;AAAA,cAAQ;AAAA,cAC3D,MAAM;AAAA,cAAO;AAAA,cAAS,MAAM,SAAS;AAAA,cAAQ;AAAA,eAChD;AAAA,aAEJ;AAAA,UACA,oBAAC,YAAO,SAAS,YAAY,OAAO,iBAAiB,sBAErD;AAAA;AAAA;AAAA,IACF;AAAA,IAGC,SACC,qBAAC,SAAI,OAAO,EAAE,cAAc,GAAG,GAC7B;AAAA,0BAAC,SAAI,OAAO,aACV,8BAAC,SAAI,OAAO,aAAa,MAAM,SAAS,OAAO,GAAG,GACpD;AAAA,MACA,qBAAC,SAAI,OAAO,EAAE,GAAG,OAAO,WAAW,EAAE,GAClC;AAAA,cAAM,SAAS;AAAA,QAAgB;AAAA,QAAE,MAAM,SAAS;AAAA,QAAa;AAAA,QAAI;AAAA,QACnD,MAAM,SAAS;AAAA,QAAe;AAAA,QAC5C,MAAM,SAAS;AAAA,QAAW;AAAA,SAC7B;AAAA,OACF;AAAA,IAID,KAAK,OAAO,IAAI,CAAC,UAChB;AAAA,MAAC;AAAA;AAAA,QAEC;AAAA,QACA,eAAe,KAAK,gBAAgB,MAAM,MAAM,KAAK;AAAA,QACrD,WAAW,OAAO,iBAAiB,MAAM;AAAA;AAAA,MAHpC,MAAM;AAAA,IAIb,CACD;AAAA,IAGA,KAAK,cACJ,qBAAC,SAAI,OAAO,EAAE,GAAG,OAAO,WAAW,GAAG,GAAG;AAAA;AAAA,MACzB,IAAI,KAAK,KAAK,UAAU,EAAE,eAAe;AAAA,OACzD;AAAA,KAEJ;AAEJ;AAEA,SAAS,UAAU;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,QAAQ,MAAM,MAAM;AAC1B,QAAM,OAAO,MAAM,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,UAAU,EAAE;AAChE,QAAM,MAAM,QAAQ,IAAI,KAAK,MAAO,OAAO,QAAS,GAAG,IAAI;AAE3D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,GAAG;AAAA,QACH,YAAY,YACR,sBACA;AAAA,MACN;AAAA,MAEA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,SAAS;AAAA,cACT,gBAAgB;AAAA,cAChB,YAAY;AAAA,YACd;AAAA,YAEA;AAAA,mCAAC,SACC;AAAA,qCAAC,UAAK,OAAO,EAAE,YAAY,IAAI,GAAG;AAAA;AAAA,kBACzB,MAAM;AAAA,kBAAO;AAAA,kBAAE;AAAA,mBACxB;AAAA,gBACA,oBAAC,UAAM,gBAAM,KAAK,QAAQ,MAAM,GAAG,GAAE;AAAA,gBACpC,aACC;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO,EAAE,GAAG,MAAM,SAAS,GAAG,YAAY,GAAG,UAAU,GAAG;AAAA,oBAC3D;AAAA;AAAA,gBAED;AAAA,iBAEJ;AAAA,cACA,oBAAC,UAAK,OAAO,MAAM,iBAAiB,OAAO,SAAS,CAAC,GAClD,2BAAiB,OAAO,SAAS,GACpC;AAAA;AAAA;AAAA,QACF;AAAA,QAEC,QAAQ,KACP,qBAAC,SAAI,OAAO,EAAE,WAAW,EAAE,GACzB;AAAA,8BAAC,SAAI,OAAO,aACV,8BAAC,SAAI,OAAO,aAAa,GAAG,GAAG,GACjC;AAAA,UACA,qBAAC,SAAI,OAAO,EAAE,GAAG,OAAO,WAAW,EAAE,GAClC;AAAA;AAAA,YAAK;AAAA,YAAE;AAAA,YAAM;AAAA,aAChB;AAAA,WACF;AAAA,QAIF,qBAAC,SAAI,OAAO,EAAE,WAAW,GAAG,SAAS,QAAQ,KAAK,GAAG,UAAU,OAAO,GACnE;AAAA,gBAAM,cACL,oBAAC,UAAK,OAAO,eAAe,qBAAO;AAAA,UAEpC,MAAM,eACL,oBAAC,UAAK,OAAO,eAAe,sBAAQ;AAAA,UAErC,MAAM,mBACL,oBAAC,UAAK,OAAO;AAAA,YACX,GAAG;AAAA,YACH,OAAO,MAAM,uBAAuB,WAAW,YAC3C,MAAM,uBAAuB,eAAe,YAC5C;AAAA,UACN,GACG,gBAAM,uBAAuB,WAAW,aACrC,MAAM,uBAAuB,eAAe,eAC5C,MAAM,uBAAuB,iBAAiB,iBAC9C,YACN;AAAA,UAED,MAAM,UACL,qBAAC,UAAK,OAAO;AAAA,YACX,GAAG;AAAA,YACH,OAAO,MAAM,cAAc,aAAa,YACpC,MAAM,cAAc,cAAc,YAClC;AAAA,UACN,GAAG;AAAA;AAAA,YACI,MAAM,cAAc,aAAa,WAClC,MAAM,cAAc,cAAc,cAClC;AAAA,aACN;AAAA,UAED,MAAM,mBACL,oBAAC,UAAK,OAAO,EAAE,GAAG,eAAe,OAAO,UAAU,GAAG,oBAAM;AAAA,WAE/D;AAAA,QAEC,CAAC,iBACA,oBAAC,SAAI,OAAO,EAAE,GAAG,OAAO,WAAW,GAAG,WAAW,SAAS,GAAG,oCAE7D;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAIO,SAAS,YAAY,EAAE,QAAQ,GAAyB;AAC7D,QAAM,EAAE,MAAM,QAAQ,IAAI,cAIhB,mBAAmB;AAAA,IAC3B,SAAS,QAAQ;AAAA,IACjB,WAAW,QAAQ,aAAa,QAAQ;AAAA,EAC1C,CAAC;AAED,MAAI,QAAS,QAAO,oBAAC,SAAI,OAAO,OAAO,wBAAU;AACjD,MAAI,CAAC,QAAQ,CAAC,KAAK,QAAQ;AACzB,WACE,qBAAC,SAAI,OAAO,YACV;AAAA,0BAAC,SAAI,OAAO,EAAE,UAAU,IAAI,cAAc,EAAE,GAAG,iCAE/C;AAAA,MACA,oBAAC,SAAI,wEAEL;AAAA,OACF;AAAA,EAEJ;AAEA,MAAI,CAAC,KAAK,OAAO;AACf,WAAO,oBAAC,SAAI,OAAO,OAAO,0DAA4C;AAAA,EACxE;AAEA,QAAM,QAAQ,KAAK;AACnB,QAAM,QAAQ,MAAM,MAAM;AAC1B,QAAM,OAAO,MAAM,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,UAAU,EAAE;AAChE,QAAM,MAAM,QAAQ,IAAI,KAAK,MAAO,OAAO,QAAS,GAAG,IAAI;AAE3D,SACE,qBAAC,SACC;AAAA,yBAAC,SAAI,OAAO,SAAS;AAAA;AAAA,MACZ,MAAM;AAAA,MAAO;AAAA,MAAG,MAAM,KAAK,QAAQ,MAAM,GAAG;AAAA,OACrD;AAAA,IACA,qBAAC,SAAI,OAAO,EAAE,cAAc,GAAG,GAC7B;AAAA,0BAAC,UAAK,OAAO,MAAM,iBAAiB,KAAK,CAAC,GACvC,2BAAiB,KAAK,GACzB;AAAA,MACC,MAAM,mBACL,oBAAC,UAAK,OAAO,EAAE,GAAG,MAAM,SAAS,GAAG,YAAY,EAAE,GAAG,sBAErD;AAAA,OAEJ;AAAA,IAEC,QAAQ,KACP,iCACE;AAAA,0BAAC,SAAI,OAAO,aACV,8BAAC,SAAI,OAAO,aAAa,GAAG,GAAG,GACjC;AAAA,MACA,qBAAC,SAAI,OAAO,EAAE,GAAG,OAAO,WAAW,GAAG,cAAc,GAAG,GACpD;AAAA;AAAA,QAAK;AAAA,QAAE;AAAA,QAAM;AAAA,QAAkB;AAAA,QAAI;AAAA,SACtC;AAAA,MAGC,MAAM,MAAM,IAAI,CAAC,SAChB;AAAA,QAAC;AAAA;AAAA,UAEC,OAAO;AAAA,YACL,SAAS;AAAA,YACT,YAAY;AAAA,YACZ,KAAK;AAAA,YACL,SAAS;AAAA,YACT,cACE;AAAA,UACJ;AAAA,UAEA;AAAA,gCAAC,UAAK,OAAO,EAAE,UAAU,GAAG,GACzB,eAAK,WAAW,aAAa,WAAW,UAC3C;AAAA,YACA,qBAAC,UAAK;AAAA;AAAA,cACE,KAAK;AAAA,cACV,KAAK,aACJ,qBAAC,UAAK,OAAO,OAAO;AAAA;AAAA,gBAAS,KAAK,UAAU,MAAM,GAAG,EAAE;AAAA,gBAAG,KAAK,UAAU,SAAS,KAAK,QAAQ;AAAA,iBAAG;AAAA,eAEtG;AAAA,YACC,KAAK,QAAQ,QACZ,qBAAC,UAAK,OAAO,EAAE,GAAG,OAAO,UAAU,GAAG,GAAG;AAAA;AAAA,cACjC,KAAK;AAAA,eACb;AAAA;AAAA;AAAA,QAtBG,GAAG,KAAK,WAAW,IAAI,KAAK,UAAU;AAAA,MAwB7C,CACD;AAAA,OACH;AAAA,KAEJ;AAEJ;AAIO,SAAS,cAAc,EAAE,QAAQ,GAAyB;AAC/D,QAAM,cAAc,gBAAgB,cAAc;AAClD,QAAM,QAAQ,eAAe;AAE7B,QAAM,aAAa,YAAY;AAC7B,UAAM,YAAY;AAAA,MAChB,WAAW,QAAQ;AAAA,MACnB,WAAW,QAAQ;AAAA,IACrB,CAAC;AACD,UAAM,EAAE,OAAO,cAAc,MAAM,UAAU,CAAC;AAAA,EAChD;AAEA,SACE,oBAAC,YAAO,SAAS,YAAY,OAAO,iBAAiB,sBAErD;AAEJ;AAIO,SAAS,gBAAgB,EAAE,QAAQ,GAAoB;AAC5D,QAAM,EAAE,MAAM,YAAY,SAAS,cAAc,IAAI,cAQlD,sBAAsB,EAAE,WAAW,QAAQ,UAAU,CAAC;AACzD,QAAM,EAAE,MAAM,YAAY,SAAS,eAAe,SAAS,cAAc,IAAI,cAG1E,cAAc,CAAC,CAAC;AACnB,QAAM,UAAU,gBAAgB,UAAU;AAC1C,QAAM,eAAe,gBAAgB,eAAe;AACpD,QAAM,QAAQ,eAAe;AAE7B,QAAM,CAAC,UAAU,WAAW,IAAI,SAAyB,IAAI;AAC7D,QAAM,CAAC,UAAU,WAAW,IAAI,SAAiB,EAAE;AACnD,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAG1C,QAAM,kBAAkB,YAAY,YAAY,mBAAmB;AACnE,QAAM,kBAAkB,YAAY,OAAO,YAAY,uBAAuB,EAAE;AAEhF,QAAM,gBAAgB,YAAY;AAChC,UAAM,SAAU,MAAM,QAAQ;AAAA,MAC5B,WAAW,QAAQ;AAAA,IACrB,CAAC;AACD,UAAM;AAAA,MACJ,OAAO,UAAU,QAAQ,UAAU,CAAC;AAAA,MACpC,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAEA,QAAM,mBAAmB,YAAY;AACnC,UAAM,iBAAiB,KAAK,IAAI,IAAI,KAAK,IAAI,KAAK,OAAO,eAAe,KAAK,EAAE,CAAC;AAChF,cAAU,IAAI;AACd,QAAI;AACF,YAAM,aAAa;AAAA,QACjB,iBAAiB;AAAA,QACjB,qBAAqB;AAAA,MACvB,CAAC;AACD,oBAAc;AACd,kBAAY,IAAI;AAChB,kBAAY,EAAE;AACd,YAAM,EAAE,OAAO,kBAAkB,MAAM,UAAU,CAAC;AAAA,IACpD,QAAQ;AACN,YAAM,EAAE,OAAO,2BAA2B,MAAM,QAAQ,CAAC;AAAA,IAC3D,UAAE;AACA,gBAAU,KAAK;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,aACJ,aAAa,QACZ,aAAa,MAAM,OAAO,QAAQ,MAAM,YAAY;AAEvD,SACE,qBAAC,SAAI,OAAO,EAAE,UAAU,IAAI,GAC1B;AAAA,wBAAC,SAAI,OAAO,SAAS,0BAAY;AAAA,IAGjC,qBAAC,SAAI,OAAO,EAAE,GAAG,MAAM,cAAc,GAAG,GACtC;AAAA,0BAAC,SAAI,OAAO,EAAE,GAAG,SAAS,cAAc,GAAG,GAAG,uBAAS;AAAA,MAEtD,gBACC,oBAAC,SAAI,OAAO,OAAO,sCAAwB,IAE3C,iCACE;AAAA,4BAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,IAAI,cAAc,GAAG,GAC7E,+BAAC,WAAM,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,GAAG,QAAQ,UAAU,GAC/E;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS;AAAA,cACT,UAAU,CAAC,MAAM,YAAY,EAAE,OAAO,OAAO;AAAA,cAC7C,OAAO,EAAE,OAAO,IAAI,QAAQ,IAAI,QAAQ,UAAU;AAAA;AAAA,UACpD;AAAA,UACA,oBAAC,UAAK,kCAAoB;AAAA,WAC5B,GACF;AAAA,QAEA,qBAAC,SAAI,OAAO,EAAE,cAAc,GAAG,GAC7B;AAAA,8BAAC,WAAM,OAAO,EAAE,SAAS,SAAS,cAAc,EAAE,GAChD,8BAAC,UAAK,OAAO,OAAO,mDAAoC,GAC1D;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,KAAK;AAAA,cACL,KAAK;AAAA,cACL,OAAO;AAAA,cACP,UAAU,CAAC,MAAM,YAAY,EAAE,OAAO,KAAK;AAAA,cAC3C,UAAU,CAAC;AAAA,cACX,OAAO;AAAA,gBACL,GAAG;AAAA,gBACH,SAAS,kBAAkB,IAAI;AAAA,cACjC;AAAA;AAAA,UACF;AAAA,WACF;AAAA,QAEA,qBAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,KAAK,EAAE,GACpC;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,SAAS;AAAA,cACT,UAAU,UAAU,CAAC;AAAA,cACrB,OAAO;AAAA,gBACL,GAAG;AAAA,gBACH,SAAS,UAAU,CAAC,aAAa,MAAM;AAAA,cACzC;AAAA,cAEC,mBAAS,cAAc;AAAA;AAAA,UAC1B;AAAA,UACA,oBAAC,YAAO,SAAS,eAAe,OAAO,iBAAiB,+BAExD;AAAA,WACF;AAAA,SACF;AAAA,OAEJ;AAAA,IAGA,oBAAC,SAAI,OAAO,SAAS,iCAAmB;AAAA,IACvC,iBAAiB,oBAAC,SAAI,OAAO,OAAO,wBAAU;AAAA,IAE9C,YAAY,OAAO,IAAI,CAAC,UACvB,qBAAC,SAAwB,OAAO,MAC9B;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,SAAS;AAAA,YACT,gBAAgB;AAAA,YAChB,YAAY;AAAA,UACd;AAAA,UAEA;AAAA,gCAAC,YAAQ,gBAAM,WAAU;AAAA,YACzB;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL,MAAM,kBAAkB,cACpB,YACA,MAAM,kBAAkB,YACtB,YACA;AAAA,gBACR;AAAA,gBAEC,gBAAM;AAAA;AAAA,YACT;AAAA;AAAA;AAAA,MACF;AAAA,MACA,qBAAC,SAAI,OAAO,EAAE,GAAG,OAAO,WAAW,EAAE,GAClC;AAAA,cAAM;AAAA,QAAY;AAAA,QAAI,MAAM;AAAA,SAC/B;AAAA,SAvBQ,MAAM,OAwBhB,CACD;AAAA,IAEA,CAAC,kBAAkB,CAAC,YAAY,UAAU,WAAW,OAAO,WAAW,MACtE,oBAAC,SAAI,OAAO,OAAO,+CAAiC;AAAA,KAExD;AAEJ;AAIA,IAAM,gBAAqC;AAAA,EACzC,UAAU;AAAA,EACV,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,SAAS;AACX;AAEA,IAAM,kBAAuC;AAAA,EAC3C,SAAS;AAAA,EACT,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,YAAY;AACd;AAEA,IAAM,aAAkC;AAAA,EACtC,SAAS;AAAA,EACT,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,UAAU;AAAA,EACV,OAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|