selftune 0.2.26 → 0.2.28
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/apps/local-dashboard/dist/assets/{index-BIZDNtRp.js → index-MMLFlnVn.js} +8 -8
- package/apps/local-dashboard/dist/index.html +1 -1
- package/cli/selftune/dashboard-server.ts +46 -14
- package/cli/selftune/status.ts +7 -1
- package/package.json +1 -1
- package/packages/dashboard-core/src/routes/manifest.ts +8 -8
- package/packages/dashboard-core/src/screens/overview/OverviewCompositionSurface.test.tsx +1 -0
- package/packages/dashboard-core/src/screens/overview/OverviewCompositionSurface.tsx +1 -1
- package/packages/dashboard-core/src/screens/skill-report/SkillReportScaffold.tsx +5 -1
- package/skill/SKILL.md +1 -1
- package/skill/workflows/Registry.md +1 -1
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>selftune — Dashboard</title>
|
|
7
7
|
<link rel="icon" type="image/png" href="/favicon.png" />
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-MMLFlnVn.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-Dw2cE7zH.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-C5oyHiV1.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/vendor-ui-B3BPIYy7.js">
|
|
@@ -185,6 +185,50 @@ const MIME_TYPES: Record<string, string> = {
|
|
|
185
185
|
".ico": "image/x-icon",
|
|
186
186
|
};
|
|
187
187
|
|
|
188
|
+
async function serveSpaShell(spaDir: string | null): Promise<Response> {
|
|
189
|
+
if (!spaDir) {
|
|
190
|
+
return new Response("Dashboard build not found. Run `bun run build:dashboard` first.", {
|
|
191
|
+
status: 503,
|
|
192
|
+
headers: { "Content-Type": "text/plain; charset=utf-8", ...corsHeaders() },
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const indexPath = join(spaDir, "index.html");
|
|
197
|
+
const indexFile = Bun.file(indexPath);
|
|
198
|
+
if (!(await indexFile.exists())) {
|
|
199
|
+
return new Response(
|
|
200
|
+
"Dashboard assets are updating. Retry in a moment or run `selftune dashboard --restart`.",
|
|
201
|
+
{
|
|
202
|
+
status: 503,
|
|
203
|
+
headers: {
|
|
204
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
205
|
+
"Retry-After": "1",
|
|
206
|
+
...corsHeaders(),
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
const html = await indexFile.text();
|
|
214
|
+
return new Response(html, {
|
|
215
|
+
headers: { "Content-Type": "text/html; charset=utf-8", ...corsHeaders() },
|
|
216
|
+
});
|
|
217
|
+
} catch {
|
|
218
|
+
return new Response(
|
|
219
|
+
"Dashboard assets are updating. Retry in a moment or run `selftune dashboard --restart`.",
|
|
220
|
+
{
|
|
221
|
+
status: 503,
|
|
222
|
+
headers: {
|
|
223
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
224
|
+
"Retry-After": "1",
|
|
225
|
+
...corsHeaders(),
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
188
232
|
async function computeStatusFromDb(): Promise<StatusResult> {
|
|
189
233
|
const db = getDb();
|
|
190
234
|
const telemetry = querySessionTelemetry(db);
|
|
@@ -519,16 +563,7 @@ export async function startDashboardServer(
|
|
|
519
563
|
|
|
520
564
|
// ---- GET / ---- Serve SPA shell
|
|
521
565
|
if (url.pathname === "/" && req.method === "GET") {
|
|
522
|
-
|
|
523
|
-
const html = await Bun.file(join(spaDir, "index.html")).text();
|
|
524
|
-
return new Response(html, {
|
|
525
|
-
headers: { "Content-Type": "text/html; charset=utf-8", ...corsHeaders() },
|
|
526
|
-
});
|
|
527
|
-
}
|
|
528
|
-
return new Response("Dashboard build not found. Run `bun run build:dashboard` first.", {
|
|
529
|
-
status: 503,
|
|
530
|
-
headers: { "Content-Type": "text/plain; charset=utf-8", ...corsHeaders() },
|
|
531
|
-
});
|
|
566
|
+
return serveSpaShell(spaDir);
|
|
532
567
|
}
|
|
533
568
|
|
|
534
569
|
// ---- POST /api/actions/{watch,evolve,rollback,watchlist} ----
|
|
@@ -672,10 +707,7 @@ export async function startDashboardServer(
|
|
|
672
707
|
|
|
673
708
|
// ---- SPA fallback ----
|
|
674
709
|
if (spaDir && req.method === "GET" && !url.pathname.startsWith("/api/")) {
|
|
675
|
-
|
|
676
|
-
return new Response(html, {
|
|
677
|
-
headers: { "Content-Type": "text/html; charset=utf-8", ...corsHeaders() },
|
|
678
|
-
});
|
|
710
|
+
return serveSpaShell(spaDir);
|
|
679
711
|
}
|
|
680
712
|
|
|
681
713
|
return new Response("Not Found", { status: 404, headers: corsHeaders() });
|
package/cli/selftune/status.ts
CHANGED
|
@@ -581,7 +581,13 @@ export function formatAlphaStatus(info: AlphaStatusInfo | null): string {
|
|
|
581
581
|
lines.push(` Failed: ${info.stats.failed}`);
|
|
582
582
|
lines.push(` Sent: ${info.stats.sent}`);
|
|
583
583
|
|
|
584
|
-
|
|
584
|
+
const lastErrorIsCurrent =
|
|
585
|
+
info.lastError &&
|
|
586
|
+
(!info.lastSuccess ||
|
|
587
|
+
new Date(info.lastError.updated_at).getTime() >
|
|
588
|
+
new Date(info.lastSuccess.updated_at).getTime());
|
|
589
|
+
|
|
590
|
+
if (lastErrorIsCurrent) {
|
|
585
591
|
lines.push(` Last error: ${info.lastError.last_error ?? "unknown"}`);
|
|
586
592
|
}
|
|
587
593
|
|
package/package.json
CHANGED
|
@@ -213,27 +213,27 @@ export const DASHBOARD_ROUTE_MANIFEST: readonly DashboardRouteManifestEntry[] =
|
|
|
213
213
|
{
|
|
214
214
|
id: "registry",
|
|
215
215
|
label: "Registry",
|
|
216
|
-
tooltip: "
|
|
216
|
+
tooltip: "Cloud skill registry",
|
|
217
217
|
icon: PackageIcon,
|
|
218
218
|
feature: "registry",
|
|
219
219
|
discoverableFeature: "registry",
|
|
220
|
-
lockedTitle: "
|
|
220
|
+
lockedTitle: "Cloud Registry lives in Selftune Cloud",
|
|
221
221
|
lockedBody:
|
|
222
222
|
"Publish versioned skills, watch installations across projects, and roll back bad versions from a single cloud workspace.",
|
|
223
223
|
lockedHighlights: [
|
|
224
224
|
"Version timeline with rollback controls",
|
|
225
225
|
"Installation map across your team",
|
|
226
|
-
"Managed publish flow for
|
|
226
|
+
"Managed publish flow for Pro and Team creators",
|
|
227
227
|
],
|
|
228
|
-
lockedPrimaryCtaLabel: "
|
|
229
|
-
lockedPrimaryCtaHref: "https://selftune.dev/
|
|
230
|
-
lockedSecondaryCtaLabel: "
|
|
231
|
-
lockedSecondaryCtaHref: "https://
|
|
228
|
+
lockedPrimaryCtaLabel: "Read registry docs",
|
|
229
|
+
lockedPrimaryCtaHref: "https://docs.selftune.dev/cloud/registry",
|
|
230
|
+
lockedSecondaryCtaLabel: "View cloud plans",
|
|
231
|
+
lockedSecondaryCtaHref: "https://selftune.dev/pricing",
|
|
232
232
|
hosts: {
|
|
233
233
|
cloud: {
|
|
234
234
|
path: "/registry",
|
|
235
235
|
title: "Registry",
|
|
236
|
-
badge: "
|
|
236
|
+
badge: "Cloud",
|
|
237
237
|
backHref: "/",
|
|
238
238
|
backLabel: "Dashboard",
|
|
239
239
|
activePatterns: [{ mode: "exact", value: "/registry" }],
|
|
@@ -86,6 +86,7 @@ describe("OverviewCompositionSurface", () => {
|
|
|
86
86
|
expect(html).toContain("After Feed");
|
|
87
87
|
expect(html.indexOf("Comparison 1")).toBeLessThan(html.indexOf("Before Feed"));
|
|
88
88
|
expect(html.indexOf("Run Summary 4")).toBeLessThan(html.indexOf("After Feed"));
|
|
89
|
+
expect(html).toContain('<div class="col-span-12"><div>Before Feed</div></div>');
|
|
89
90
|
});
|
|
90
91
|
|
|
91
92
|
it("omits the comparison block when there are no rows", () => {
|
|
@@ -48,7 +48,7 @@ export function OverviewCompositionSurface({
|
|
|
48
48
|
<OverviewComparisonSurface {...comparison} renderSkillLink={renderSkillLink} />
|
|
49
49
|
</div>
|
|
50
50
|
) : null}
|
|
51
|
-
{sectionsBeforeFeed}
|
|
51
|
+
{sectionsBeforeFeed ? <div className="col-span-12">{sectionsBeforeFeed}</div> : null}
|
|
52
52
|
</>
|
|
53
53
|
) : null;
|
|
54
54
|
|
|
@@ -28,6 +28,7 @@ export interface SkillReportScaffoldProps {
|
|
|
28
28
|
summary?: ReactNode;
|
|
29
29
|
showOnboardingBanner?: boolean;
|
|
30
30
|
guideButtonLabel?: string;
|
|
31
|
+
prioritizeChildren?: boolean;
|
|
31
32
|
nextAction: SkillReportNextAction;
|
|
32
33
|
trustState: TrustState;
|
|
33
34
|
coverage?: TrustFields["coverage"];
|
|
@@ -52,6 +53,7 @@ export function SkillReportScaffold({
|
|
|
52
53
|
summary,
|
|
53
54
|
showOnboardingBanner = false,
|
|
54
55
|
guideButtonLabel = "How to read this page",
|
|
56
|
+
prioritizeChildren = false,
|
|
55
57
|
nextAction,
|
|
56
58
|
trustState,
|
|
57
59
|
coverage,
|
|
@@ -115,6 +117,8 @@ export function SkillReportScaffold({
|
|
|
115
117
|
}
|
|
116
118
|
/>
|
|
117
119
|
|
|
120
|
+
{prioritizeChildren && children ? <div className="space-y-4">{children}</div> : null}
|
|
121
|
+
|
|
118
122
|
<SkillTrustNarrativePanel
|
|
119
123
|
trustState={trustState}
|
|
120
124
|
coverage={coverage}
|
|
@@ -141,7 +145,7 @@ export function SkillReportScaffold({
|
|
|
141
145
|
/>
|
|
142
146
|
</div>
|
|
143
147
|
|
|
144
|
-
{children ? (
|
|
148
|
+
{children && !prioritizeChildren ? (
|
|
145
149
|
<div className="space-y-4 border-t border-border/10 pt-4">{children}</div>
|
|
146
150
|
) : null}
|
|
147
151
|
</div>
|
package/skill/SKILL.md
CHANGED
|
@@ -55,7 +55,7 @@ Manage versioned skill distribution across your team. Push skill folders to the
|
|
|
55
55
|
## Prerequisites
|
|
56
56
|
|
|
57
57
|
- Must be authenticated (`selftune alpha upload` to set up API key)
|
|
58
|
-
- Push and rollback require
|
|
58
|
+
- Push and rollback require Pro plan or higher and admin role
|
|
59
59
|
- Install requires Pro plan or higher
|
|
60
60
|
|
|
61
61
|
## Output Format
|