ankka-console 0.12.0 → 0.13.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/ankka-mark.png +0 -0
- package/dist/client/schemas.d.ts +149 -1
- package/dist/client/schemas.js +40 -1
- package/dist/routes/front.d.ts +14 -0
- package/dist/routes/logs.d.ts +10 -0
- package/dist/routes/project.d.ts +10 -0
- package/dist/routes/service-topology.d.ts +10 -0
- package/dist/routes/service.d.ts +10 -0
- package/dist/routes/service.js +2 -1
- package/dist/styles.css +1 -1
- package/dist/testing/fake-control-plane.d.ts +14 -0
- package/dist/testing/fake-control-plane.js +21 -0
- package/dist/ui/buckets.d.ts +14 -0
- package/dist/ui/buckets.js +9 -0
- package/dist/ui/shell.js +5 -1
- package/dist/ui/topology/Table.d.ts +8 -0
- package/dist/ui/topology/Table.js +8 -1
- package/dist/ui/use-stream.d.ts +20 -0
- package/package.json +1 -1
|
Binary file
|
package/dist/client/schemas.d.ts
CHANGED
|
@@ -68,9 +68,46 @@ export declare const installationSecretsSchema: z.ZodObject<{
|
|
|
68
68
|
auditLog: z.ZodDefault<z.ZodString>;
|
|
69
69
|
}, z.core.$strip>;
|
|
70
70
|
export type InstallationSecrets = z.infer<typeof installationSecretsSchema>;
|
|
71
|
+
/** One model the installation's model server declares: its state, and its digest once served (feature 053). */
|
|
72
|
+
export declare const modelLineSchema: z.ZodObject<{
|
|
73
|
+
name: z.ZodString;
|
|
74
|
+
state: z.ZodString;
|
|
75
|
+
digest: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
76
|
+
detail: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
77
|
+
}, z.core.$strip>;
|
|
78
|
+
export type ModelLine = z.infer<typeof modelLineSchema>;
|
|
79
|
+
/** One cluster's model server, read live through its door. */
|
|
80
|
+
export declare const clusterModelsSchema: z.ZodObject<{
|
|
81
|
+
cluster: z.ZodString;
|
|
82
|
+
server: z.ZodString;
|
|
83
|
+
ready: z.ZodBoolean;
|
|
84
|
+
models: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
85
|
+
name: z.ZodString;
|
|
86
|
+
state: z.ZodString;
|
|
87
|
+
digest: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
88
|
+
detail: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
89
|
+
}, z.core.$strip>>>;
|
|
90
|
+
detail: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
91
|
+
}, z.core.$strip>;
|
|
92
|
+
export type ClusterModels = z.infer<typeof clusterModelsSchema>;
|
|
93
|
+
export declare const installationModelsSchema: z.ZodObject<{
|
|
94
|
+
clusters: z.ZodArray<z.ZodObject<{
|
|
95
|
+
cluster: z.ZodString;
|
|
96
|
+
server: z.ZodString;
|
|
97
|
+
ready: z.ZodBoolean;
|
|
98
|
+
models: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
99
|
+
name: z.ZodString;
|
|
100
|
+
state: z.ZodString;
|
|
101
|
+
digest: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
102
|
+
detail: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
103
|
+
}, z.core.$strip>>>;
|
|
104
|
+
detail: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
105
|
+
}, z.core.$strip>>;
|
|
106
|
+
}, z.core.$strip>;
|
|
107
|
+
export type InstallationModels = z.infer<typeof installationModelsSchema>;
|
|
71
108
|
/**
|
|
72
109
|
* `GET /installation`: the platform's version, and its cloud when it names a provider; and its
|
|
73
|
-
* backups (feature 041);
|
|
110
|
+
* backups (feature 041); where it keeps its secrets (feature 038); and its model server (feature 053).
|
|
74
111
|
*/
|
|
75
112
|
export declare const installationSchema: z.ZodObject<{
|
|
76
113
|
platformVersion: z.ZodString;
|
|
@@ -211,6 +248,46 @@ export declare const installationSchema: z.ZodObject<{
|
|
|
211
248
|
recordRetention: string;
|
|
212
249
|
auditLog: string;
|
|
213
250
|
} | null | undefined>>;
|
|
251
|
+
models: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
252
|
+
clusters: z.ZodArray<z.ZodObject<{
|
|
253
|
+
cluster: z.ZodString;
|
|
254
|
+
server: z.ZodString;
|
|
255
|
+
ready: z.ZodBoolean;
|
|
256
|
+
models: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
257
|
+
name: z.ZodString;
|
|
258
|
+
state: z.ZodString;
|
|
259
|
+
digest: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
260
|
+
detail: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
261
|
+
}, z.core.$strip>>>;
|
|
262
|
+
detail: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
263
|
+
}, z.core.$strip>>;
|
|
264
|
+
}, z.core.$strip>>>, z.ZodTransform<{
|
|
265
|
+
clusters: {
|
|
266
|
+
cluster: string;
|
|
267
|
+
server: string;
|
|
268
|
+
ready: boolean;
|
|
269
|
+
models: {
|
|
270
|
+
name: string;
|
|
271
|
+
state: string;
|
|
272
|
+
digest: string | undefined;
|
|
273
|
+
detail: string | undefined;
|
|
274
|
+
}[];
|
|
275
|
+
detail: string | undefined;
|
|
276
|
+
}[];
|
|
277
|
+
} | undefined, {
|
|
278
|
+
clusters: {
|
|
279
|
+
cluster: string;
|
|
280
|
+
server: string;
|
|
281
|
+
ready: boolean;
|
|
282
|
+
models: {
|
|
283
|
+
name: string;
|
|
284
|
+
state: string;
|
|
285
|
+
digest: string | undefined;
|
|
286
|
+
detail: string | undefined;
|
|
287
|
+
}[];
|
|
288
|
+
detail: string | undefined;
|
|
289
|
+
}[];
|
|
290
|
+
} | null | undefined>>;
|
|
214
291
|
}, z.core.$strip>;
|
|
215
292
|
export type Installation = z.infer<typeof installationSchema>;
|
|
216
293
|
export declare const quotaSchema: z.ZodObject<{
|
|
@@ -389,6 +466,21 @@ export declare const dnsRecordSchema: z.ZodObject<{
|
|
|
389
466
|
value: z.ZodString;
|
|
390
467
|
}, z.core.$strip>;
|
|
391
468
|
export type DnsRecord = z.infer<typeof dnsRecordSchema>;
|
|
469
|
+
/**
|
|
470
|
+
* One named bucket of a service, as the operator reported it (feature 055): kept ones are those the
|
|
471
|
+
* descriptor no longer names, which the platform never deletes.
|
|
472
|
+
*/
|
|
473
|
+
export declare const bucketReportSchema: z.ZodObject<{
|
|
474
|
+
name: z.ZodString;
|
|
475
|
+
phase: z.ZodString;
|
|
476
|
+
store: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
477
|
+
bucket: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
478
|
+
exposure: z.ZodDefault<z.ZodString>;
|
|
479
|
+
publicAddress: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
480
|
+
kept: z.ZodDefault<z.ZodBoolean>;
|
|
481
|
+
detail: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
482
|
+
}, z.core.$strip>;
|
|
483
|
+
export type BucketReport = z.infer<typeof bucketReportSchema>;
|
|
392
484
|
/** One custom hostname of a service: where it stands, and the record that points it at the installation. */
|
|
393
485
|
export declare const customHostnameSchema: z.ZodObject<{
|
|
394
486
|
hostname: z.ZodString;
|
|
@@ -622,6 +714,34 @@ export declare const serviceStatusSchema: z.ZodObject<{
|
|
|
622
714
|
bucketLocation: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
623
715
|
softDeleteDays: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodNumber>>, z.ZodTransform<number | undefined, number | null | undefined>>;
|
|
624
716
|
storageMove: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
717
|
+
buckets: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
718
|
+
name: z.ZodString;
|
|
719
|
+
phase: z.ZodString;
|
|
720
|
+
store: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
721
|
+
bucket: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
722
|
+
exposure: z.ZodDefault<z.ZodString>;
|
|
723
|
+
publicAddress: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
724
|
+
kept: z.ZodDefault<z.ZodBoolean>;
|
|
725
|
+
detail: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
726
|
+
}, z.core.$strip>>>>, z.ZodTransform<{
|
|
727
|
+
name: string;
|
|
728
|
+
phase: string;
|
|
729
|
+
store: string | undefined;
|
|
730
|
+
bucket: string | undefined;
|
|
731
|
+
exposure: string;
|
|
732
|
+
publicAddress: string | undefined;
|
|
733
|
+
kept: boolean;
|
|
734
|
+
detail: string | undefined;
|
|
735
|
+
}[] | undefined, {
|
|
736
|
+
name: string;
|
|
737
|
+
phase: string;
|
|
738
|
+
store: string | undefined;
|
|
739
|
+
bucket: string | undefined;
|
|
740
|
+
exposure: string;
|
|
741
|
+
publicAddress: string | undefined;
|
|
742
|
+
kept: boolean;
|
|
743
|
+
detail: string | undefined;
|
|
744
|
+
}[] | null | undefined>>;
|
|
625
745
|
databaseCluster: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
626
746
|
grants: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
627
747
|
crossProjectTopics: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodLazy<z.ZodObject<{
|
|
@@ -939,6 +1059,34 @@ export declare const rolledBackSchema: z.ZodObject<{
|
|
|
939
1059
|
bucketLocation: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
940
1060
|
softDeleteDays: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodNumber>>, z.ZodTransform<number | undefined, number | null | undefined>>;
|
|
941
1061
|
storageMove: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
1062
|
+
buckets: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
1063
|
+
name: z.ZodString;
|
|
1064
|
+
phase: z.ZodString;
|
|
1065
|
+
store: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
1066
|
+
bucket: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
1067
|
+
exposure: z.ZodDefault<z.ZodString>;
|
|
1068
|
+
publicAddress: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
1069
|
+
kept: z.ZodDefault<z.ZodBoolean>;
|
|
1070
|
+
detail: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
1071
|
+
}, z.core.$strip>>>>, z.ZodTransform<{
|
|
1072
|
+
name: string;
|
|
1073
|
+
phase: string;
|
|
1074
|
+
store: string | undefined;
|
|
1075
|
+
bucket: string | undefined;
|
|
1076
|
+
exposure: string;
|
|
1077
|
+
publicAddress: string | undefined;
|
|
1078
|
+
kept: boolean;
|
|
1079
|
+
detail: string | undefined;
|
|
1080
|
+
}[] | undefined, {
|
|
1081
|
+
name: string;
|
|
1082
|
+
phase: string;
|
|
1083
|
+
store: string | undefined;
|
|
1084
|
+
bucket: string | undefined;
|
|
1085
|
+
exposure: string;
|
|
1086
|
+
publicAddress: string | undefined;
|
|
1087
|
+
kept: boolean;
|
|
1088
|
+
detail: string | undefined;
|
|
1089
|
+
}[] | null | undefined>>;
|
|
942
1090
|
databaseCluster: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
943
1091
|
grants: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
944
1092
|
crossProjectTopics: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodLazy<z.ZodObject<{
|
package/dist/client/schemas.js
CHANGED
|
@@ -57,9 +57,27 @@ export const installationSecretsSchema = z.object({
|
|
|
57
57
|
recordRetention: z.string(),
|
|
58
58
|
auditLog: z.string().default("unknown"),
|
|
59
59
|
});
|
|
60
|
+
/** One model the installation's model server declares: its state, and its digest once served (feature 053). */
|
|
61
|
+
export const modelLineSchema = z.object({
|
|
62
|
+
name: z.string(),
|
|
63
|
+
state: z.string(),
|
|
64
|
+
digest: optional(z.string()),
|
|
65
|
+
detail: optional(z.string()),
|
|
66
|
+
});
|
|
67
|
+
/** One cluster's model server, read live through its door. */
|
|
68
|
+
export const clusterModelsSchema = z.object({
|
|
69
|
+
cluster: z.string(),
|
|
70
|
+
server: z.string(),
|
|
71
|
+
ready: z.boolean(),
|
|
72
|
+
models: z.array(modelLineSchema).default([]),
|
|
73
|
+
detail: optional(z.string()),
|
|
74
|
+
});
|
|
75
|
+
export const installationModelsSchema = z.object({
|
|
76
|
+
clusters: z.array(clusterModelsSchema),
|
|
77
|
+
});
|
|
60
78
|
/**
|
|
61
79
|
* `GET /installation`: the platform's version, and its cloud when it names a provider; and its
|
|
62
|
-
* backups (feature 041);
|
|
80
|
+
* backups (feature 041); where it keeps its secrets (feature 038); and its model server (feature 053).
|
|
63
81
|
*/
|
|
64
82
|
export const installationSchema = z.object({
|
|
65
83
|
platformVersion: z.string(),
|
|
@@ -67,6 +85,7 @@ export const installationSchema = z.object({
|
|
|
67
85
|
// Lazily: its schema is with the other backup schemas, below.
|
|
68
86
|
backups: optional(z.lazy(() => installationStatusSchema)),
|
|
69
87
|
secrets: optional(installationSecretsSchema),
|
|
88
|
+
models: optional(installationModelsSchema),
|
|
70
89
|
});
|
|
71
90
|
export const quotaSchema = z.object({
|
|
72
91
|
projects: optional(z.number().int()),
|
|
@@ -140,6 +159,24 @@ export const dnsRecordSchema = z.object({
|
|
|
140
159
|
kind: z.string(),
|
|
141
160
|
value: z.string(),
|
|
142
161
|
});
|
|
162
|
+
/**
|
|
163
|
+
* One named bucket of a service, as the operator reported it (feature 055): kept ones are those the
|
|
164
|
+
* descriptor no longer names, which the platform never deletes.
|
|
165
|
+
*/
|
|
166
|
+
export const bucketReportSchema = z.object({
|
|
167
|
+
name: z.string(),
|
|
168
|
+
phase: z.string(),
|
|
169
|
+
/** `garage` or `gcs`; absent for a supplied bucket. */
|
|
170
|
+
store: optional(z.string()),
|
|
171
|
+
/** Its name in the store. */
|
|
172
|
+
bucket: optional(z.string()),
|
|
173
|
+
/** `private`, `signed`, `public` or `supplied`. */
|
|
174
|
+
exposure: z.string().default("private"),
|
|
175
|
+
/** Where a public or signed bucket is on the internet. */
|
|
176
|
+
publicAddress: optional(z.string()),
|
|
177
|
+
kept: z.boolean().default(false),
|
|
178
|
+
detail: optional(z.string()),
|
|
179
|
+
});
|
|
143
180
|
/** One custom hostname of a service: where it stands, and the record that points it at the installation. */
|
|
144
181
|
export const customHostnameSchema = z.object({
|
|
145
182
|
hostname: z.string(),
|
|
@@ -190,6 +227,8 @@ export const serviceStatusSchema = z.object({
|
|
|
190
227
|
softDeleteDays: optional(z.number().int()),
|
|
191
228
|
/** Where a move of the bucket from Garage is, as a phrase; its detail is in `detail`. */
|
|
192
229
|
storageMove: optional(z.string()),
|
|
230
|
+
/** Each named bucket, in the descriptor's order, then the kept ones (feature 055); absent when none. */
|
|
231
|
+
buckets: optional(z.array(bucketReportSchema)),
|
|
193
232
|
/** The project database cluster the service is on, when a member switched it to a restore. */
|
|
194
233
|
databaseCluster: optional(z.string()),
|
|
195
234
|
/** `mounted` when the service's instances read their project's grants (feature 040). */
|
package/dist/routes/front.d.ts
CHANGED
|
@@ -76,6 +76,20 @@ export declare function loader({ context }: LoaderFunctionArgs): Promise<{
|
|
|
76
76
|
recordRetention: string;
|
|
77
77
|
auditLog: string;
|
|
78
78
|
} | undefined;
|
|
79
|
+
models: {
|
|
80
|
+
clusters: {
|
|
81
|
+
cluster: string;
|
|
82
|
+
server: string;
|
|
83
|
+
ready: boolean;
|
|
84
|
+
models: {
|
|
85
|
+
name: string;
|
|
86
|
+
state: string;
|
|
87
|
+
digest: string | undefined;
|
|
88
|
+
detail: string | undefined;
|
|
89
|
+
}[];
|
|
90
|
+
detail: string | undefined;
|
|
91
|
+
}[];
|
|
92
|
+
} | undefined;
|
|
79
93
|
};
|
|
80
94
|
hold: {
|
|
81
95
|
held: boolean;
|
package/dist/routes/logs.d.ts
CHANGED
|
@@ -87,6 +87,16 @@ export declare function loader({ request, params, context }: LoaderFunctionArgs)
|
|
|
87
87
|
bucketLocation: string | undefined;
|
|
88
88
|
softDeleteDays: number | undefined;
|
|
89
89
|
storageMove: string | undefined;
|
|
90
|
+
buckets: {
|
|
91
|
+
name: string;
|
|
92
|
+
phase: string;
|
|
93
|
+
store: string | undefined;
|
|
94
|
+
bucket: string | undefined;
|
|
95
|
+
exposure: string;
|
|
96
|
+
publicAddress: string | undefined;
|
|
97
|
+
kept: boolean;
|
|
98
|
+
detail: string | undefined;
|
|
99
|
+
}[] | undefined;
|
|
90
100
|
databaseCluster: string | undefined;
|
|
91
101
|
grants: string | undefined;
|
|
92
102
|
crossProjectTopics: {
|
package/dist/routes/project.d.ts
CHANGED
|
@@ -120,6 +120,16 @@ export declare function loader({ params, context }: LoaderFunctionArgs): Promise
|
|
|
120
120
|
bucketLocation: string | undefined;
|
|
121
121
|
softDeleteDays: number | undefined;
|
|
122
122
|
storageMove: string | undefined;
|
|
123
|
+
buckets: {
|
|
124
|
+
name: string;
|
|
125
|
+
phase: string;
|
|
126
|
+
store: string | undefined;
|
|
127
|
+
bucket: string | undefined;
|
|
128
|
+
exposure: string;
|
|
129
|
+
publicAddress: string | undefined;
|
|
130
|
+
kept: boolean;
|
|
131
|
+
detail: string | undefined;
|
|
132
|
+
}[] | undefined;
|
|
123
133
|
databaseCluster: string | undefined;
|
|
124
134
|
grants: string | undefined;
|
|
125
135
|
crossProjectTopics: {
|
|
@@ -87,6 +87,16 @@ export declare function loader({ params, context }: LoaderFunctionArgs): Promise
|
|
|
87
87
|
bucketLocation: string | undefined;
|
|
88
88
|
softDeleteDays: number | undefined;
|
|
89
89
|
storageMove: string | undefined;
|
|
90
|
+
buckets: {
|
|
91
|
+
name: string;
|
|
92
|
+
phase: string;
|
|
93
|
+
store: string | undefined;
|
|
94
|
+
bucket: string | undefined;
|
|
95
|
+
exposure: string;
|
|
96
|
+
publicAddress: string | undefined;
|
|
97
|
+
kept: boolean;
|
|
98
|
+
detail: string | undefined;
|
|
99
|
+
}[] | undefined;
|
|
90
100
|
databaseCluster: string | undefined;
|
|
91
101
|
grants: string | undefined;
|
|
92
102
|
crossProjectTopics: {
|
package/dist/routes/service.d.ts
CHANGED
|
@@ -92,6 +92,16 @@ export declare function loader({ params, context }: LoaderFunctionArgs): Promise
|
|
|
92
92
|
bucketLocation: string | undefined;
|
|
93
93
|
softDeleteDays: number | undefined;
|
|
94
94
|
storageMove: string | undefined;
|
|
95
|
+
buckets: {
|
|
96
|
+
name: string;
|
|
97
|
+
phase: string;
|
|
98
|
+
store: string | undefined;
|
|
99
|
+
bucket: string | undefined;
|
|
100
|
+
exposure: string;
|
|
101
|
+
publicAddress: string | undefined;
|
|
102
|
+
kept: boolean;
|
|
103
|
+
detail: string | undefined;
|
|
104
|
+
}[] | undefined;
|
|
95
105
|
databaseCluster: string | undefined;
|
|
96
106
|
grants: string | undefined;
|
|
97
107
|
crossProjectTopics: {
|
package/dist/routes/service.js
CHANGED
|
@@ -12,6 +12,7 @@ import { Select } from "../ui/primitives/select.js";
|
|
|
12
12
|
import { Page, SectionTitle, ServiceSections } from "../ui/shell.js";
|
|
13
13
|
import { Shape } from "../ui/shape.js";
|
|
14
14
|
import { runsAs } from "../ui/hosting.js";
|
|
15
|
+
import { bucketRows } from "../ui/buckets.js";
|
|
15
16
|
import { Refused, useRefusal } from "../ui/refused.js";
|
|
16
17
|
import { Lifecycle } from "../ui/status.js";
|
|
17
18
|
import { useServiceStream } from "../ui/use-stream.js";
|
|
@@ -132,6 +133,6 @@ export default function Service() {
|
|
|
132
133
|
const { status: s, state } = useServiceStream(p.id, data.service.name, data.service);
|
|
133
134
|
const deleteRefused = useRefusal("delete") !== undefined;
|
|
134
135
|
const inspector = (_jsxs(_Fragment, { children: [_jsxs("section", { className: "ac-ops", "aria-labelledby": "operations-title", children: [_jsx(SectionTitle, { children: _jsx("span", { id: "operations-title", children: "Operations" }) }), s.paused ? _jsx(Operation, { intent: "resume", label: "Resume", operation: "service.resume", entity: s }) : _jsx(Operation, { intent: "pause", label: "Pause", operation: "service.pause", entity: s }), _jsx(Operation, { intent: "restart", label: "Restart", operation: "service.restart", entity: s }), s.exposed ? _jsx(Operation, { intent: "unexpose", label: "Unexpose", operation: "service.unexpose", entity: s }) : _jsx(Operation, { intent: "expose", label: "Expose", operation: "service.expose", entity: s })] }), _jsx(HostnameOperations, { service: s }), serviceOperations.map((op) => (_jsx(Refused, { intent: op }, op))), _jsx(Storage, { s: s }), _jsxs("details", { className: "ac-more", open: deleteRefused || undefined, children: [_jsx("summary", { children: "Delete" }), _jsxs("div", { className: "ac-danger-zone", children: [_jsxs("p", { children: ["Deleting ", s.name, " stops it and removes it from the project. Its database is kept, and so is its bucket if it has one: applying a descriptor with this name again brings the service back with its data."] }), _jsx(Operation, { intent: "delete", label: "Delete service", operation: "service.delete", danger: true, entity: s }), _jsx(Refused, { intent: "delete" })] })] })] }));
|
|
135
|
-
return (_jsxs(Page, { inspector: inspector, children: [_jsxs("div", { className: "ac-head", children: [_jsx("h1", { children: s.name }), _jsxs("p", { "aria-live": "polite", className: "ac-actions ac-state-line", children: [_jsx("span", { className: "ac-pill", children: _jsx(Lifecycle, { lifecycle: s.lifecycle, confirmed: s.confirmed }) }), state === "live" ? _jsx("span", { className: "ac-live", children: " Updating as the platform reports" }) : null] }), _jsx(ServiceSections, { projectId: p.id, name: s.name, current: "overview" })] }), s.detail ? _jsx("p", { className: "ac-notice", children: s.detail }) : null, _jsx(Shape, { service: s }), _jsx(Hostnames, { service: s }), _jsxs("section", { className: "ac-card", "aria-labelledby": "reported", children: [_jsx("h2", { id: "reported", children: "Reported by the cluster" }), _jsxs("dl", { className: "ac-facts", children: [_jsx("dt", { children: "Instances" }), _jsxs("dd", { children: [s.readyInstances, " ready of ", s.desiredInstances] }), _jsx("dt", { children: "Image" }), _jsx("dd", { children: s.image }), _jsx("dt", { children: "Generation" }), _jsx("dd", { children: s.generation }), _jsx("dt", { children: "Database" }), _jsx("dd", { children: s.hosting === "web" ? "None" : (s.database ?? "Nothing reported yet") }), _jsx("dt", { children: "Object storage" }), _jsxs("dd", { children: [objectStorage(s), s.bucketAddress ? _jsxs("span", { className: "ac-hint", "data-bucket-address": true, children: [" ", s.bucketAddress] }) : null] }), s.objectStore ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Object store" }), _jsx("dd", { "data-object-store": s.objectStore, children: stores[s.objectStore] ?? s.objectStore })] })) : null, s.bucketLocation ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Bucket location" }), _jsx("dd", { children: s.bucketLocation })] })) : null, s.softDeleteDays !== undefined && s.softDeleteDays !== null ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Deleted objects" }), _jsxs("dd", { children: ["Recoverable for ", s.softDeleteDays, " days"] })] })) : null, s.storageMove ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Bucket move" }), _jsx("dd", { "data-storage-move": true, children: s.storageMove })] })) : null, s.broker ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Broker" }), _jsx("dd", { children: s.broker })] })) : null, s.grants ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Grants" }), _jsx("dd", { "data-grants": true, children: s.grants })] })) : null, s.crossProjectTopics && s.crossProjectTopics.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Cross-project topics" }), _jsx("dd", { children: _jsx("ul", { className: "ac-topics", children: s.crossProjectTopics.map((t) => (_jsxs("li", { "data-cross-project-topic": `${t.project}/${t.topic}`, "data-granted": t.status === "granted" ? "yes" : "no", children: [_jsx("code", { children: `${t.project}/${t.topic}` }), " ", t.right, " ", t.status === "granted" ? t.status : _jsx("span", { className: "ac-notice", children: t.status })] }, `${t.project}/${t.topic}/${t.right}`))) }) })] })) : null, s.undeclaredTopics && s.undeclaredTopics.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Undeclared topics" }), _jsx("dd", { children: _jsx("ul", { className: "ac-topics", children: s.undeclaredTopics.map((t) => (_jsx("li", { "data-topic": t, children: _jsx("code", { children: t }) }, t))) }) })] })) : null, s.warnings && s.warnings.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Warnings" }), _jsx("dd", { children: _jsx("ul", { className: "ac-topics", children: s.warnings.map((w) => (_jsx("li", { "data-warning": w.kind, children: _jsx("span", { className: "ac-notice", children: w.message }) }, `${w.kind}/${w.component}/${w.topic}`))) }) })] })) : null, s.topicSources && s.topicSources.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Topic sources" }), _jsx("dd", { children: _jsx("div", { className: "ac-table-wrap", children: _jsxs("table", { className: "ac-table", "data-topic-sources": true, children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { scope: "col", children: "Component" }), _jsx("th", { scope: "col", children: "Topic" }), _jsx("th", { scope: "col", children: "Group" }), _jsx("th", { scope: "col", className: "ac-num", children: "Version" }), _jsx("th", { scope: "col", className: "ac-num", children: "Lag" }), _jsx("th", { scope: "col", children: "Failing" }), _jsx("th", { scope: "col", children: "Retained" })] }) }), _jsx("tbody", { children: s.topicSources.map((t) => (_jsxs("tr", { "data-topic-source": t.component, "data-failing": t.failing ? "yes" : "no", children: [_jsx("td", { children: t.component }), _jsxs("td", { children: [_jsx("code", { children: t.broker ? `${t.topic}@${t.broker}` : t.topic }), t.contract ? ` as ${t.contract}` : ""] }), _jsx("td", { children: _jsx("code", { children: t.group }) }), _jsx("td", { className: "ac-num", children: t.version }), _jsx("td", { className: "ac-num", children: t.lag ?? "—" }), _jsx("td", { children: t.failing ? _jsx("span", { className: "ac-notice", children: t.failing }) : "—" }), _jsx("td", { "data-gap": t.gap ? (t.gap.compacted ? "compacted" : t.gap.gone ? "gone" : "everything") : "unknown", children: t.gap === undefined || t.gap === null ? ("—") : t.gap.compacted ? ("compacted") : !t.gap.gone ? ("everything") : (_jsxs("details", { children: [_jsx("summary", { children: "earlier messages gone" }), _jsx("ul", { className: "ac-topics", children: t.gap.partitions.map((p) => (_jsxs("li", { "data-partition": p.partition, children: ["p", p.partition, " from ", p.beginning, " (", p.earliestRetained ?? "holds nothing", ")"] }, p.partition))) })] })) })] }, t.component))) })] }) }) })] })) : null, s.topicChecks && s.topicChecks.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Topic checks" }), _jsx("dd", { children: _jsx("ul", { className: "ac-topics", children: s.topicChecks.map((c) => (_jsxs("li", { "data-check": c.state, children: [c.component, " ", c.direction, ": ", c.state, c.state === "mismatch" ? ` (${c.stated ?? "none"})` : ""] }, `${c.component}/${c.direction}`))) }) })] })) : null, _jsx("dt", { children: "Runs as" }), _jsx("dd", { children: runsAs(s) }), s.hosting === "web" ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Admits" }), _jsx("dd", { children: ["The internet", ...s.callers.map((c) => (c === "*" ? `Every service in ${p.name}` : c))].join(", ") }), _jsx("dt", { children: "Mounts" }), _jsx("dd", { children: s.mounts.length === 0 ? ("None") : (_jsx("ul", { className: "ac-mounts", children: s.mounts.map((m) => (_jsxs("li", { "data-mount": m.path, children: [_jsx("code", { children: m.path }), " \u2192 ", m.service, m.state && m.state !== "ok" ? ` (${m.state})` : ""] }, m.path))) })) })] })) : null, _jsx("dt", { children: "Stopped by" }), _jsx("dd", { children: s.suspended ? "Its organization is disabled" : s.paused ? "Its members paused it" : "Nobody" }), _jsx("dt", { children: "Report" }), _jsx("dd", { children: s.confirmed ? "Confirmed by the cluster" : "The last known state; the cluster has not confirmed it" })] })] }), _jsx(Panels, { kind: "service", entity: s, loaded: panels })] }));
|
|
136
|
+
return (_jsxs(Page, { inspector: inspector, children: [_jsxs("div", { className: "ac-head", children: [_jsx("h1", { children: s.name }), _jsxs("p", { "aria-live": "polite", className: "ac-actions ac-state-line", children: [_jsx("span", { className: "ac-pill", children: _jsx(Lifecycle, { lifecycle: s.lifecycle, confirmed: s.confirmed }) }), state === "live" ? _jsx("span", { className: "ac-live", children: " Updating as the platform reports" }) : null] }), _jsx(ServiceSections, { projectId: p.id, name: s.name, current: "overview" })] }), s.detail ? _jsx("p", { className: "ac-notice", children: s.detail }) : null, _jsx(Shape, { service: s }), _jsx(Hostnames, { service: s }), _jsxs("section", { className: "ac-card", "aria-labelledby": "reported", children: [_jsx("h2", { id: "reported", children: "Reported by the cluster" }), _jsxs("dl", { className: "ac-facts", children: [_jsx("dt", { children: "Instances" }), _jsxs("dd", { children: [s.readyInstances, " ready of ", s.desiredInstances] }), _jsx("dt", { children: "Image" }), _jsx("dd", { children: s.image }), _jsx("dt", { children: "Generation" }), _jsx("dd", { children: s.generation }), _jsx("dt", { children: "Database" }), _jsx("dd", { children: s.hosting === "web" ? "None" : (s.database ?? "Nothing reported yet") }), _jsx("dt", { children: "Object storage" }), _jsxs("dd", { children: [objectStorage(s), s.bucketAddress ? _jsxs("span", { className: "ac-hint", "data-bucket-address": true, children: [" ", s.bucketAddress] }) : null] }), s.objectStore ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Object store" }), _jsx("dd", { "data-object-store": s.objectStore, children: stores[s.objectStore] ?? s.objectStore })] })) : null, s.bucketLocation ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Bucket location" }), _jsx("dd", { children: s.bucketLocation })] })) : null, s.softDeleteDays !== undefined && s.softDeleteDays !== null ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Deleted objects" }), _jsxs("dd", { children: ["Recoverable for ", s.softDeleteDays, " days"] })] })) : null, s.storageMove ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Bucket move" }), _jsx("dd", { "data-storage-move": true, children: s.storageMove })] })) : null, s.buckets && s.buckets.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Named buckets" }), _jsx("dd", { children: _jsx("div", { className: "ac-table-wrap", children: _jsxs("table", { className: "ac-table", "data-buckets": true, children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { scope: "col", children: "Name" }), _jsx("th", { scope: "col", children: "Exposure" }), _jsx("th", { scope: "col", children: "Bucket" }), _jsx("th", { scope: "col", children: "Address" })] }) }), _jsx("tbody", { children: bucketRows(s.buckets).map((b) => (_jsxs("tr", { "data-bucket": b.name, children: [_jsx("th", { scope: "row", children: b.name }), _jsx("td", { "data-bucket-exposure": true, children: b.exposure }), _jsx("td", { children: b.bucket ?? "" }), _jsxs("td", { children: [b.address ? _jsx("a", { href: b.address, children: b.address }) : null, b.note ? _jsx("span", { className: "ac-hint", "data-bucket-note": true, children: b.note }) : null] })] }, b.name))) })] }) }) })] })) : null, s.broker ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Broker" }), _jsx("dd", { children: s.broker })] })) : null, s.grants ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Grants" }), _jsx("dd", { "data-grants": true, children: s.grants })] })) : null, s.crossProjectTopics && s.crossProjectTopics.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Cross-project topics" }), _jsx("dd", { children: _jsx("ul", { className: "ac-topics", children: s.crossProjectTopics.map((t) => (_jsxs("li", { "data-cross-project-topic": `${t.project}/${t.topic}`, "data-granted": t.status === "granted" ? "yes" : "no", children: [_jsx("code", { children: `${t.project}/${t.topic}` }), " ", t.right, " ", t.status === "granted" ? t.status : _jsx("span", { className: "ac-notice", children: t.status })] }, `${t.project}/${t.topic}/${t.right}`))) }) })] })) : null, s.undeclaredTopics && s.undeclaredTopics.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Undeclared topics" }), _jsx("dd", { children: _jsx("ul", { className: "ac-topics", children: s.undeclaredTopics.map((t) => (_jsx("li", { "data-topic": t, children: _jsx("code", { children: t }) }, t))) }) })] })) : null, s.warnings && s.warnings.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Warnings" }), _jsx("dd", { children: _jsx("ul", { className: "ac-topics", children: s.warnings.map((w) => (_jsx("li", { "data-warning": w.kind, children: _jsx("span", { className: "ac-notice", children: w.message }) }, `${w.kind}/${w.component}/${w.topic}`))) }) })] })) : null, s.topicSources && s.topicSources.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Topic sources" }), _jsx("dd", { children: _jsx("div", { className: "ac-table-wrap", children: _jsxs("table", { className: "ac-table", "data-topic-sources": true, children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { scope: "col", children: "Component" }), _jsx("th", { scope: "col", children: "Topic" }), _jsx("th", { scope: "col", children: "Group" }), _jsx("th", { scope: "col", className: "ac-num", children: "Version" }), _jsx("th", { scope: "col", className: "ac-num", children: "Lag" }), _jsx("th", { scope: "col", children: "Failing" }), _jsx("th", { scope: "col", children: "Retained" })] }) }), _jsx("tbody", { children: s.topicSources.map((t) => (_jsxs("tr", { "data-topic-source": t.component, "data-failing": t.failing ? "yes" : "no", children: [_jsx("td", { children: t.component }), _jsxs("td", { children: [_jsx("code", { children: t.broker ? `${t.topic}@${t.broker}` : t.topic }), t.contract ? ` as ${t.contract}` : ""] }), _jsx("td", { children: _jsx("code", { children: t.group }) }), _jsx("td", { className: "ac-num", children: t.version }), _jsx("td", { className: "ac-num", children: t.lag ?? "—" }), _jsx("td", { children: t.failing ? _jsx("span", { className: "ac-notice", children: t.failing }) : "—" }), _jsx("td", { "data-gap": t.gap ? (t.gap.compacted ? "compacted" : t.gap.gone ? "gone" : "everything") : "unknown", children: t.gap === undefined || t.gap === null ? ("—") : t.gap.compacted ? ("compacted") : !t.gap.gone ? ("everything") : (_jsxs("details", { children: [_jsx("summary", { children: "earlier messages gone" }), _jsx("ul", { className: "ac-topics", children: t.gap.partitions.map((p) => (_jsxs("li", { "data-partition": p.partition, children: ["p", p.partition, " from ", p.beginning, " (", p.earliestRetained ?? "holds nothing", ")"] }, p.partition))) })] })) })] }, t.component))) })] }) }) })] })) : null, s.topicChecks && s.topicChecks.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Topic checks" }), _jsx("dd", { children: _jsx("ul", { className: "ac-topics", children: s.topicChecks.map((c) => (_jsxs("li", { "data-check": c.state, children: [c.component, " ", c.direction, ": ", c.state, c.state === "mismatch" ? ` (${c.stated ?? "none"})` : ""] }, `${c.component}/${c.direction}`))) }) })] })) : null, _jsx("dt", { children: "Runs as" }), _jsx("dd", { children: runsAs(s) }), s.hosting === "web" ? (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Admits" }), _jsx("dd", { children: ["The internet", ...s.callers.map((c) => (c === "*" ? `Every service in ${p.name}` : c))].join(", ") }), _jsx("dt", { children: "Mounts" }), _jsx("dd", { children: s.mounts.length === 0 ? ("None") : (_jsx("ul", { className: "ac-mounts", children: s.mounts.map((m) => (_jsxs("li", { "data-mount": m.path, children: [_jsx("code", { children: m.path }), " \u2192 ", m.service, m.state && m.state !== "ok" ? ` (${m.state})` : ""] }, m.path))) })) })] })) : null, _jsx("dt", { children: "Stopped by" }), _jsx("dd", { children: s.suspended ? "Its organization is disabled" : s.paused ? "Its members paused it" : "Nobody" }), _jsx("dt", { children: "Report" }), _jsx("dd", { children: s.confirmed ? "Confirmed by the cluster" : "The last known state; the cluster has not confirmed it" })] })] }), _jsx(Panels, { kind: "service", entity: s, loaded: panels })] }));
|
|
136
137
|
}
|
|
137
138
|
export const ErrorBoundary = ConsoleErrorBoundary;
|
package/dist/styles.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
-
@layer theme{:root,:host{--ac-spacing:.25rem;--ac-color-mesh-base:#111f26;--ac-color-mesh-slate:#1e2e3a;--ac-color-glow:#d4805857;--ac-color-peach:#deaa8429;--ac-color-dot:#ffffff14;--ac-color-glass:#ffffff0d;--ac-color-glass-strong:#ffffff17;--ac-color-glass-line:#fff3;--ac-color-tile:#ffffff0f;--ac-color-tile-line:#ffffff24;--ac-color-node:#ffffff1a;--ac-color-node-line:#ffffff61;--ac-color-inset:#0003;--ac-color-edge:#ffffffb3;--ac-color-ink:#f5f8f7;--ac-color-ink-2:#dfe8e6;--ac-color-ink-3:#ccd9d6;--ac-color-amber:#f0b83c;--ac-color-amber-ink:#13343b;--ac-color-green:#8fe0ad;--ac-color-red:#ffc4bc;--ac-color-red-wash:#ff8a8029;--ac-shadow-part:0 18px 50px #050f1247;--ac-radius-panel:20px;--ac-radius-card:14px;--ac-radius-control:10px;--ac-radius-node:18px;--ac-font-sans:"Inter Variable", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--ac-font-mono:ui-monospace, "SF Mono", Menlo, Consolas, monospace;--ac-size-rail:56px;--ac-size-panel:232px;--ac-size-inspector:300px;--ac-size-bar:64px}:root:has(.ac-light){--ac-color-mesh-base:#e6eeee;--ac-color-mesh-slate:#cfe0dc;--ac-color-glow:#e0a5264d;--ac-color-peach:#f1d5c2cc;--ac-color-dot:#13343b1a;--ac-color-glass:#ffffff80;--ac-color-glass-strong:#ffffffd9;--ac-color-glass-line:#13343b24;--ac-color-tile:#ffffff80;--ac-color-tile-line:#13343b1a;--ac-color-node:#ffffff9e;--ac-color-node-line:#13343b38;--ac-color-inset:#13343b0f;--ac-color-edge:#13343b8c;--ac-color-ink:#13343b;--ac-color-ink-2:#33504f;--ac-color-ink-3:#4a6465;--ac-color-amber:#e0a526;--ac-color-amber-ink:#13343b;--ac-color-green:#1f6b3a;--ac-color-red:#a8231b;--ac-color-red-wash:#fbe9e7;--ac-shadow-part:0 18px 50px #13343b1a}}@layer base{.ac-root{color-scheme:dark;isolation:isolate;min-height:100vh;color:var(--ac-color-ink);font-family:var(--ac-font-sans);font-variant-numeric:tabular-nums;-webkit-font-smoothing:antialiased;font-size:.875rem;line-height:1.5;position:relative}.ac-root.ac-light{color-scheme:light}.ac-root *,.ac-root :before,.ac-root :after{box-sizing:border-box}.ac-root h1,.ac-root h2,.ac-root h3,.ac-root p,.ac-root dl,.ac-root dd,.ac-root figure{margin:0}.ac-root h1{letter-spacing:-.01em;text-wrap:balance;font-size:1.5rem;font-weight:600;line-height:1.2}.ac-root h2{font-size:.9375rem;font-weight:600}.ac-root h3{font-size:.875rem;font-weight:600}.ac-root p{max-width:72ch}.ac-root a{color:inherit;-webkit-text-decoration-color:var(--ac-color-ink-3);-webkit-text-decoration-color:var(--ac-color-ink-3);text-decoration-color:var(--ac-color-ink-3);text-underline-offset:.2em}.ac-root a:hover{-webkit-text-decoration-color:var(--ac-color-amber);-webkit-text-decoration-color:var(--ac-color-amber);text-decoration-color:var(--ac-color-amber);text-decoration-thickness:2px}.ac-root :focus-visible{outline:3px solid var(--ac-color-amber);outline-offset:2px;border-radius:4px}.ac-root code,.ac-root pre{font-family:var(--ac-font-mono)}.ac-root input,.ac-root select,.ac-root textarea{font:inherit;color:var(--ac-color-ink);background:var(--ac-color-inset);border:1px solid var(--ac-color-glass-line);border-radius:var(--ac-radius-control);width:100%;padding:.5rem .75rem}.ac-root input::placeholder,.ac-root textarea::placeholder{color:var(--ac-color-ink-3)}.ac-root textarea{font-family:var(--ac-font-mono);min-height:16rem;font-size:.8125rem}.ac-root input[type=checkbox],.ac-root input[type=radio]{width:auto;accent-color:var(--ac-color-amber)}.ac-root input[type=file]{padding:.4rem}.ac-root [aria-invalid=true]{border-color:var(--ac-color-red)}}@layer components{.ac-backdrop{z-index:-1;pointer-events:none;background:radial-gradient(var(--ac-color-dot) 1px, transparent 1.3px) 0 0 / 16px 16px, radial-gradient(42% 46% at 56% 52%, var(--ac-color-glow) 0%, transparent 72%), radial-gradient(40% 50% at 90% 88%, var(--ac-color-peach) 0%, transparent 65%), radial-gradient(55% 60% at 8% 10%, var(--ac-color-mesh-slate) 0%, transparent 70%), linear-gradient(160deg, var(--ac-color-mesh-base), var(--ac-color-mesh-slate));position:fixed;inset:0}.ac-rail,.ac-bar,.ac-listing,.ac-inspector{background:var(--ac-color-glass);-webkit-backdrop-filter:blur(20px)saturate(150%);backdrop-filter:blur(20px)saturate(150%);border:1px solid var(--ac-color-glass-line);border-radius:var(--ac-radius-panel)}@supports not ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){.ac-rail,.ac-bar,.ac-listing,.ac-inspector,.ac-card,.ac-panel,.ac-part{background:linear-gradient(var(--ac-color-glass), var(--ac-color-glass)), var(--ac-color-mesh-base)}}.ac-shell{--ac-shell-gap:12px;--ac-shell-rail:0px;--ac-shell-listing:0px;--ac-shell-inspector:0px;grid-template-columns:var(--ac-shell-rail) var(--ac-shell-listing) minmax(0, 1fr) var(--ac-shell-inspector);column-gap:0;row-gap:var(--ac-shell-gap);padding:var(--ac-shell-gap);grid-template-rows:auto 1fr;align-items:start;display:grid}.ac-shell:has(>.ac-rail){--ac-shell-rail:calc(var(--ac-size-rail) + var(--ac-shell-gap))}.ac-shell:has(>.ac-listing){--ac-shell-listing:calc(var(--ac-size-panel) + var(--ac-shell-gap))}.ac-shell:has(.ac-inspector){--ac-shell-inspector:calc(var(--ac-size-inspector) + var(--ac-shell-gap))}.ac-rail{top:var(--ac-shell-gap);max-height:calc(100vh - 2 * var(--ac-shell-gap));grid-area:1/1/3;margin-inline-end:var(--ac-shell-gap);position:sticky}.ac-bar{grid-area:1/2/auto/-1}.ac-listing{top:calc(var(--ac-size-bar) + 2 * var(--ac-shell-gap));max-height:calc(100vh - var(--ac-size-bar) - 3 * var(--ac-shell-gap));grid-area:2/2;margin-inline-end:var(--ac-shell-gap);position:sticky}.ac-page{display:contents}.ac-body{flex-direction:column;grid-area:2/3;gap:16px;min-width:0;padding-block-end:24px;display:flex}.ac-inspector{top:calc(var(--ac-size-bar) + 2 * var(--ac-shell-gap));max-height:calc(100vh - var(--ac-size-bar) - 3 * var(--ac-shell-gap));flex-direction:column;grid-area:2/4;gap:14px;margin-inline-start:var(--ac-shell-gap);padding:14px;display:flex;position:sticky;overflow:auto}.ac-rail{flex-direction:column;align-items:center;gap:6px;padding:10px 0;display:flex}.ac-rail-areas{flex-direction:column;align-items:center;gap:6px;margin:0;padding:0;list-style:none;display:flex}.ac-rail-foot{margin-top:auto}.ac-mark{width:40px;height:40px;color:var(--ac-color-ink);place-items:center;margin-bottom:8px;display:grid}.ac-rail-item{width:40px;height:40px;color:var(--ac-color-ink-2);cursor:pointer;background:0 0;border:0;border-radius:12px;place-items:center;padding:0;display:grid}.ac-rail-item svg{width:20px;height:20px}a.ac-rail-item:hover,button.ac-rail-item:hover{background:var(--ac-color-glass-strong);color:var(--ac-color-ink)}.ac-rail-item[aria-current]{background:var(--ac-color-amber);color:var(--ac-color-amber-ink)}.ac-rail-item[aria-disabled=true]{color:var(--ac-color-ink-3);opacity:.5;cursor:default}.ac-bar{min-height:var(--ac-size-bar);grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);align-items:center;gap:16px;padding:8px 16px;display:grid}.ac-bar-start,.ac-bar-end{align-items:center;gap:16px;min-width:0;display:flex}.ac-bar-end{justify-content:flex-end}.ac-wordmark{letter-spacing:-.01em;white-space:nowrap;font-size:1rem;font-weight:600}.ac-root a.ac-wordmark{text-decoration:none}.ac-wordmark span{color:var(--ac-color-ink-2);font-weight:400}.ac-person{background:var(--ac-color-glass-strong);border:1px solid var(--ac-color-glass-line);border-radius:50%;flex:none;place-items:center;width:32px;height:32px;font-size:.75rem;font-weight:600;display:grid}.ac-crumbs ol{color:var(--ac-color-ink-2);white-space:nowrap;align-items:center;gap:8px;margin:0;padding:0;list-style:none;display:flex}.ac-crumbs li+li:before{content:"/";color:var(--ac-color-ink-3);margin-right:8px}.ac-root .ac-crumbs a{text-decoration:none}.ac-root .ac-crumbs a:hover{color:var(--ac-color-ink);text-decoration:underline;-webkit-text-decoration-color:var(--ac-color-amber);-webkit-text-decoration-color:var(--ac-color-amber);text-decoration-color:var(--ac-color-amber)}.ac-crumbs [aria-current=page]{color:var(--ac-color-ink);font-weight:500}.ac-listing{flex-direction:column;gap:12px;min-height:0;padding:14px;display:flex}.ac-listing-items{gap:4px;min-height:0;margin:0;padding:0;list-style:none;display:grid;overflow:auto}.ac-listing-items>li:has(>[aria-current=page]){z-index:1;position:sticky;top:0;bottom:0}.ac-listing-item{border-radius:var(--ac-radius-control);background:var(--ac-color-tile);border:1px solid #0000;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:2px 8px;padding:8px 10px;display:grid}.ac-root a.ac-listing-item{text-decoration:none}.ac-listing-item:hover{background:var(--ac-color-glass-strong)}.ac-listing-item[aria-current=page]{background:linear-gradient(var(--ac-color-glass-strong), var(--ac-color-glass-strong)), var(--ac-color-mesh-base);border-color:var(--ac-color-glass-line)}.ac-listing-name{text-overflow:ellipsis;white-space:nowrap;font-weight:500;overflow:hidden}.ac-listing-count{color:var(--ac-color-ink-2);grid-area:1/2/3;font-size:.75rem}.ac-section-title{letter-spacing:.08em;text-transform:uppercase;color:var(--ac-color-ink-3);justify-content:space-between;align-items:center;margin:0;font-size:.6875rem;font-weight:600;display:flex}.ac-seg{background:var(--ac-color-inset);border-radius:999px;grid-auto-columns:1fr;grid-auto-flow:column;padding:3px;display:inline-grid}.ac-seg a{text-align:center;color:var(--ac-color-ink-2);white-space:nowrap;border-radius:999px;padding:6px 14px;font-weight:500}.ac-root .ac-seg a{text-decoration:none}.ac-seg a[aria-current=page]{background:var(--ac-color-glass-strong);color:var(--ac-color-ink);box-shadow:0 1px 2px #0003}.ac-head{flex-wrap:wrap;align-items:center;gap:12px 16px;padding:4px 6px 0;display:flex}.ac-head .ac-seg{margin-left:auto}.ac-lede,.ac-hint,.ac-empty{color:var(--ac-color-ink-2)}.ac-hint{font-size:.8125rem}.ac-card,.ac-panel{background:var(--ac-color-tile);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);border:1px solid var(--ac-color-tile-line);border-radius:var(--ac-radius-card);flex-direction:column;gap:12px;min-width:0;padding:16px;display:flex}.ac-panel-failed{color:var(--ac-color-red)}.ac-table-wrap{overflow-x:auto}.ac-table{border-collapse:collapse;width:100%}.ac-table th,.ac-table td{text-align:left;border-top:1px solid var(--ac-color-tile-line);vertical-align:top;padding:9px 12px 9px 0}.ac-table thead th{color:var(--ac-color-ink-2);border-top:0;padding-top:0;font-size:.8125rem;font-weight:500}.ac-table .ac-num{text-align:right}.ac-facts{grid-template-columns:minmax(8rem,max-content) minmax(0,1fr);column-gap:24px;display:grid}.ac-facts dt,.ac-facts dd{border-top:1px solid var(--ac-color-tile-line);padding:9px 0}.ac-facts dt{color:var(--ac-color-ink-2)}.ac-facts dd{overflow-wrap:anywhere}.ac-facts>div{display:contents}.ac-status{white-space:nowrap;align-items:baseline;gap:6px;font-weight:500;display:inline-flex}.ac-status-mark{letter-spacing:-.15em;font-size:.75em}.ac-status-ready .ac-status-mark{color:var(--ac-color-green)}.ac-status-moving .ac-status-mark,.ac-status-partial .ac-status-mark{color:var(--ac-color-amber)}.ac-status-trouble{color:var(--ac-color-red)}.ac-status-stopped .ac-status-mark,.ac-status-idle .ac-status-mark{color:var(--ac-color-ink-3)}.ac-status-note{color:var(--ac-color-ink-2);font-weight:400}.ac-pill{background:var(--ac-color-glass-strong);border:1px solid var(--ac-color-glass-line);border-radius:999px;padding:4px 10px 4px 8px}.ac-live{color:var(--ac-color-ink-2);align-items:center;gap:8px;font-size:.8125rem;display:inline-flex}.ac-live:before{content:"";background:var(--ac-color-amber);border-radius:50%;flex:none;width:8px;height:8px}@media (prefers-reduced-motion:no-preference){.ac-live:before{animation:2.4s ease-out infinite ac-ripple}}.ac-field{gap:4px;min-width:0;max-width:32rem;display:grid}.ac-field label{font-weight:500}.ac-field-error{color:var(--ac-color-red)}.ac-form{gap:16px;display:grid}.ac-inline{flex-wrap:wrap;align-items:end;gap:8px;display:flex}.ac-inline .ac-field{flex:12rem}.ac-inspector .ac-inline{flex-direction:column;align-items:stretch}.ac-inspector .ac-inline .ac-field{flex:none}.ac-inspector .ac-field{max-width:none}.ac-switch{cursor:pointer;align-items:center;gap:10px;display:inline-flex}.ac-root .ac-switch input{opacity:0;width:1px;height:1px;position:absolute}.ac-switch-track{background:var(--ac-color-inset);border:1px solid var(--ac-color-glass-line);border-radius:999px;flex:none;width:40px;height:24px;position:relative}.ac-switch-track:after{content:"";background:var(--ac-color-ink);border-radius:50%;width:18px;height:18px;position:absolute;top:2px;left:2px}.ac-switch input:checked+.ac-switch-track{background:var(--ac-color-amber);border-color:var(--ac-color-amber)}.ac-switch input:checked+.ac-switch-track:after{background:var(--ac-color-amber-ink);transform:translate(16px)}.ac-switch input:focus-visible+.ac-switch-track{outline:3px solid var(--ac-color-amber);outline-offset:2px}@media (prefers-reduced-motion:no-preference){.ac-switch-track,.ac-switch-track:after{transition:background .15s,transform .15s}}.ac-button{font:inherit;border:1px solid var(--ac-color-glass-line);background:var(--ac-color-glass-strong);color:var(--ac-color-ink);cursor:pointer;white-space:nowrap;border-radius:999px;justify-content:center;align-items:center;gap:8px;padding:7px 14px;font-weight:500;display:inline-flex}.ac-root a.ac-button{color:var(--ac-color-ink);text-decoration:none}.ac-button svg{width:16px;height:16px}.ac-button:hover{background:var(--ac-color-glass-line)}.ac-button-primary,.ac-root a.ac-button-primary{background:var(--ac-color-amber);border-color:var(--ac-color-amber);color:var(--ac-color-amber-ink)}.ac-button-primary:hover{background:var(--ac-color-amber)}@supports (color:color-mix(in lab, red, red)){.ac-button-primary:hover{background:color-mix(in srgb, var(--ac-color-amber) 88%, white)}}.ac-button-danger,.ac-root a.ac-button-danger{background:var(--ac-color-red);border-color:var(--ac-color-red);color:var(--ac-color-mesh-base)}.ac-button-danger:hover{background:var(--ac-color-red)}@supports (color:color-mix(in lab, red, red)){.ac-button-danger:hover{background:color-mix(in srgb, var(--ac-color-red) 88%, white)}}.ac-button-quiet{background:0 0}.ac-button-small{padding:4px 10px;font-size:.8125rem}.ac-button[disabled]{opacity:.55;cursor:progress}.ac-actions{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.ac-actions form{display:inline}.ac-ops{gap:8px;display:grid}.ac-ops>form,.ac-ops>.ac-button,.ac-ops>form>.ac-button{width:100%}.ac-more{border-top:1px solid var(--ac-color-glass-line);padding-top:12px}.ac-more summary{cursor:pointer;font-weight:500}.ac-more[open]>*+*{margin-top:12px}.ac-danger-zone{border-left:3px solid var(--ac-color-red);gap:10px;padding:8px 0 8px 12px;display:grid}.ac-danger-zone p{color:var(--ac-color-ink-2);font-size:.8125rem}.ac-refusal{border-left:3px solid var(--ac-color-red);background:var(--ac-color-red-wash);border-radius:0 var(--ac-radius-control) var(--ac-radius-control) 0;padding:10px 14px}.ac-refusal ul{margin:6px 0 0;padding-left:1.2rem}.ac-notice{border-left:3px solid var(--ac-color-amber);background:var(--ac-color-tile);border-radius:0 var(--ac-radius-control) var(--ac-radius-control) 0;padding:10px 14px}.ac-secret{font-family:var(--ac-font-mono);background:var(--ac-color-inset);border:1px dashed var(--ac-color-ink-3);border-radius:var(--ac-radius-control);overflow-wrap:anywhere;-webkit-user-select:all;user-select:all;padding:10px;display:block}.ac-log{font-family:var(--ac-font-mono);background:var(--ac-color-inset);border:1px solid var(--ac-color-tile-line);border-radius:var(--ac-radius-control);white-space:pre-wrap;overflow-wrap:anywhere;max-height:32rem;margin:0;padding:12px;font-size:.8125rem;overflow:auto}.ac-mounts{gap:4px;margin:0;padding:0;list-style:none;display:grid}.ac-visually-hidden{clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.ac-shape{border-radius:var(--ac-radius-panel);border:1px solid var(--ac-color-glass-line);padding:28px 20px 20px}.ac-tree{justify-items:center;max-width:720px;margin:0 auto;display:grid}.ac-row{justify-items:center;width:100%;display:grid}.ac-row-many{gap:24px}.ac-part{background:var(--ac-color-node);-webkit-backdrop-filter:blur(18px)saturate(140%);backdrop-filter:blur(18px)saturate(140%);border:1px solid var(--ac-color-node-line);border-radius:var(--ac-radius-node);width:100%;max-width:300px;box-shadow:var(--ac-shadow-part);grid-template-columns:auto minmax(0,1fr);align-items:center;gap:2px 12px;padding:16px 16px 14px;display:grid;position:relative}.ac-part-self{box-shadow:var(--ac-shadow-part), 0 0 0 2px var(--ac-color-amber), 0 0 24px var(--ac-color-amber)}@supports (color:color-mix(in lab, red, red)){.ac-part-self{box-shadow:var(--ac-shadow-part), 0 0 0 2px var(--ac-color-amber), 0 0 24px color-mix(in srgb, var(--ac-color-amber) 45%, transparent)}}.ac-part-icon{width:40px;height:40px;color:var(--ac-color-ink);grid-row:1/3}.ac-part-icon svg{width:40px;height:40px}.ac-part-title,.ac-part-sub{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.ac-part-title{font-weight:500}.ac-part-sub{color:var(--ac-color-ink-2);font-size:.8125rem}.ac-part-inset{background:var(--ac-color-inset);border-radius:10px;grid-column:1/3;justify-content:space-between;align-items:center;gap:8px;margin-top:10px;padding:7px 12px;font-size:.8125rem;display:flex}.ac-part-up:before,.ac-part-down:after{content:"";background:var(--ac-color-node);border:1px solid var(--ac-color-node-line);width:12px;height:7px;position:absolute;left:50%;transform:translate(-50%)}.ac-part-down:after{border-top:0;border-radius:0 0 7px 7px;bottom:-7px}.ac-part-up:before{border-bottom:0;border-radius:7px 7px 0 0;top:-7px}.ac-part-tab{background:var(--ac-color-node);border:1px solid var(--ac-color-node-line);border-bottom:0;border-radius:12px 12px 0 0;gap:2px;padding:2px 8px 6px;display:flex;position:absolute;top:-27px;left:50%;transform:translate(-50%)}.ac-part-tab form{display:contents}.ac-tab-control{width:24px;height:20px;color:var(--ac-color-ink);cursor:pointer;background:0 0;border:0;border-radius:6px;place-items:center;padding:0;display:grid}.ac-tab-control:hover{background:var(--ac-color-glass-strong)}.ac-tab-control svg{width:14px;height:14px}.ac-part-tabbed{margin-top:27px}.ac-part-tabbed.ac-part-up:before{display:none}.ac-edge{width:100%;height:48px;color:var(--ac-color-edge);display:block;overflow:visible}.ac-edge path{fill:none;stroke:currentColor;stroke-width:1.5px;vector-effect:non-scaling-stroke}.ac-topology{align-items:flex-start;gap:16px;display:flex}.ac-topology-picture{border-radius:var(--ac-radius-panel);border:1px solid var(--ac-color-glass-line);flex:1;min-width:0;padding:8px;overflow-x:auto}.ac-topology-detail{flex:0 0 18rem}.ac-topology-node rect{fill:var(--ac-color-node);stroke:var(--ac-color-node-line);stroke-width:1px}.ac-topology-node{cursor:pointer}.ac-topology-node:focus-visible rect,.ac-topology-selected rect{stroke:var(--ac-color-amber);stroke-width:2px}.ac-topology-node:focus{outline:none}.ac-topology-outside rect,.ac-topology-differs rect{stroke-dasharray:4 3}.ac-topology-platform rect{fill:var(--ac-color-inset)}.ac-topology-name{fill:var(--ac-color-ink);font-size:12px;font-weight:600}.ac-topology-kind{fill:var(--ac-color-ink-2);font-size:11px}.ac-topology-declared{fill:none;stroke:var(--ac-color-edge);stroke-width:1.25px}.ac-topology-call{fill:none;stroke:var(--ac-color-ink);stroke-dasharray:5 4}.ac-topology-warning{stroke:var(--ac-color-red)}.ac-topology-mark{fill:var(--ac-color-red);font-size:14px;font-weight:700}@media (forced-colors:active){.ac-rail,.ac-bar,.ac-listing,.ac-inspector,.ac-card,.ac-panel,.ac-part,.ac-listing-item{border:1px solid canvastext}.ac-button,.ac-rail-item,.ac-seg a{border:1px solid buttontext}.ac-rail-item[aria-current],.ac-seg a[aria-current=page],.ac-listing-item[aria-current=page]{outline:2px solid highlight}}@media (max-width:1180px){.ac-shell,.ac-shell:has(>.ac-listing),.ac-shell:has(.ac-inspector){grid-template-columns:var(--ac-shell-rail) minmax(0, 1fr);grid-template-rows:none;grid-auto-rows:auto}.ac-rail{grid-row:1/span 5}.ac-bar,.ac-listing,.ac-body,.ac-inspector{grid-area:auto/2;max-height:none;margin-inline:0;position:static}.ac-listing-items{grid-template-columns:repeat(auto-fill,minmax(200px,1fr));max-height:18rem}}@media (max-width:720px){.ac-shell,.ac-shell:has(>.ac-rail),.ac-shell:has(>.ac-listing),.ac-shell:has(.ac-inspector){grid-template-columns:minmax(0,1fr)}.ac-rail{flex-flow:wrap;grid-area:auto/1;justify-content:flex-start;max-height:none;margin:0;padding:8px 10px;position:static}.ac-rail-areas{flex-flow:wrap}.ac-mark{margin:0 6px 0 0}.ac-rail-foot{margin-top:0;margin-left:auto}.ac-bar,.ac-listing,.ac-body,.ac-inspector{grid-column:1}.ac-bar{grid-template-columns:minmax(0,1fr) auto}.ac-bar-start{overflow:hidden}.ac-wordmark span{display:none}.ac-crumbs{grid-area:2/1/auto/-1}.ac-crumbs ol{white-space:normal;flex-wrap:wrap;row-gap:2px}.ac-head .ac-seg{width:100%;margin-left:0}.ac-row-many{gap:20px;grid-template-columns:minmax(0,1fr)!important}.ac-edge-split{display:none}.ac-facts{grid-template-columns:minmax(0,1fr)}.ac-facts dd{border-top:0;padding-top:0}.ac-topology{flex-direction:column}.ac-topology-detail{flex-basis:auto;width:100%}}}@layer utilities;@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./fonts/inter-latin-wght-normal.woff2)format("woff2-variations");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./fonts/inter-latin-ext-wght-normal.woff2)format("woff2-variations");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@keyframes ac-ripple{0%{box-shadow:0 0 0 0 color-mix(in srgb, var(--ac-color-amber) 60%, transparent)}to{box-shadow:0 0 0 .6rem #0000}}
|
|
2
|
+
@layer theme{:root,:host{--ac-spacing:.25rem;--ac-color-mesh-base:#111f26;--ac-color-mesh-slate:#1e2e3a;--ac-color-glow:#d4805857;--ac-color-peach:#deaa8429;--ac-color-dot:#ffffff14;--ac-color-glass:#ffffff0d;--ac-color-glass-strong:#ffffff17;--ac-color-glass-line:#fff3;--ac-color-tile:#ffffff0f;--ac-color-tile-line:#ffffff24;--ac-color-node:#ffffff1a;--ac-color-node-line:#ffffff61;--ac-color-inset:#0003;--ac-color-edge:#ffffffb3;--ac-color-ink:#f5f8f7;--ac-color-ink-2:#dfe8e6;--ac-color-ink-3:#ccd9d6;--ac-color-amber:#f0b83c;--ac-color-amber-ink:#13343b;--ac-color-green:#8fe0ad;--ac-color-red:#ffc4bc;--ac-color-red-wash:#ff8a8029;--ac-shadow-part:0 18px 50px #050f1247;--ac-radius-panel:20px;--ac-radius-card:14px;--ac-radius-control:10px;--ac-radius-node:18px;--ac-font-sans:"Inter Variable", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--ac-font-mono:ui-monospace, "SF Mono", Menlo, Consolas, monospace;--ac-size-rail:56px;--ac-size-panel:232px;--ac-size-inspector:300px;--ac-size-bar:64px}:root:has(.ac-light){--ac-color-mesh-base:#e6eeee;--ac-color-mesh-slate:#cfe0dc;--ac-color-glow:#e0a5264d;--ac-color-peach:#f1d5c2cc;--ac-color-dot:#13343b1a;--ac-color-glass:#ffffff80;--ac-color-glass-strong:#ffffffd9;--ac-color-glass-line:#13343b24;--ac-color-tile:#ffffff80;--ac-color-tile-line:#13343b1a;--ac-color-node:#ffffff9e;--ac-color-node-line:#13343b38;--ac-color-inset:#13343b0f;--ac-color-edge:#13343b8c;--ac-color-ink:#13343b;--ac-color-ink-2:#33504f;--ac-color-ink-3:#4a6465;--ac-color-amber:#e0a526;--ac-color-amber-ink:#13343b;--ac-color-green:#1f6b3a;--ac-color-red:#a8231b;--ac-color-red-wash:#fbe9e7;--ac-shadow-part:0 18px 50px #13343b1a}}@layer base{.ac-root{color-scheme:dark;isolation:isolate;min-height:100vh;color:var(--ac-color-ink);font-family:var(--ac-font-sans);font-variant-numeric:tabular-nums;-webkit-font-smoothing:antialiased;font-size:.875rem;line-height:1.5;position:relative}.ac-root.ac-light{color-scheme:light}.ac-root *,.ac-root :before,.ac-root :after{box-sizing:border-box}.ac-root h1,.ac-root h2,.ac-root h3,.ac-root p,.ac-root dl,.ac-root dd,.ac-root figure{margin:0}.ac-root h1{letter-spacing:-.01em;text-wrap:balance;font-size:1.5rem;font-weight:600;line-height:1.2}.ac-root h2{font-size:.9375rem;font-weight:600}.ac-root h3{font-size:.875rem;font-weight:600}.ac-root p{max-width:72ch}.ac-root a{color:inherit;-webkit-text-decoration-color:var(--ac-color-ink-3);-webkit-text-decoration-color:var(--ac-color-ink-3);text-decoration-color:var(--ac-color-ink-3);text-underline-offset:.2em}.ac-root a:hover{-webkit-text-decoration-color:var(--ac-color-amber);-webkit-text-decoration-color:var(--ac-color-amber);text-decoration-color:var(--ac-color-amber);text-decoration-thickness:2px}.ac-root :focus-visible{outline:3px solid var(--ac-color-amber);outline-offset:2px;border-radius:4px}.ac-root code,.ac-root pre{font-family:var(--ac-font-mono)}.ac-root input,.ac-root select,.ac-root textarea{font:inherit;color:var(--ac-color-ink);background:var(--ac-color-inset);border:1px solid var(--ac-color-glass-line);border-radius:var(--ac-radius-control);width:100%;padding:.5rem .75rem}.ac-root input::placeholder,.ac-root textarea::placeholder{color:var(--ac-color-ink-3)}.ac-root textarea{font-family:var(--ac-font-mono);min-height:16rem;font-size:.8125rem}.ac-root input[type=checkbox],.ac-root input[type=radio]{width:auto;accent-color:var(--ac-color-amber)}.ac-root input[type=file]{padding:.4rem}.ac-root [aria-invalid=true]{border-color:var(--ac-color-red)}}@layer components{.ac-backdrop{z-index:-1;pointer-events:none;background:radial-gradient(var(--ac-color-dot) 1px, transparent 1.3px) 0 0 / 16px 16px, radial-gradient(42% 46% at 56% 52%, var(--ac-color-glow) 0%, transparent 72%), radial-gradient(40% 50% at 90% 88%, var(--ac-color-peach) 0%, transparent 65%), radial-gradient(55% 60% at 8% 10%, var(--ac-color-mesh-slate) 0%, transparent 70%), linear-gradient(160deg, var(--ac-color-mesh-base), var(--ac-color-mesh-slate));position:fixed;inset:0}.ac-rail,.ac-bar,.ac-listing,.ac-inspector{background:var(--ac-color-glass);-webkit-backdrop-filter:blur(20px)saturate(150%);backdrop-filter:blur(20px)saturate(150%);border:1px solid var(--ac-color-glass-line);border-radius:var(--ac-radius-panel)}@supports not ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){.ac-rail,.ac-bar,.ac-listing,.ac-inspector,.ac-card,.ac-panel,.ac-part{background:linear-gradient(var(--ac-color-glass), var(--ac-color-glass)), var(--ac-color-mesh-base)}}.ac-shell{--ac-shell-gap:12px;--ac-shell-rail:0px;--ac-shell-listing:0px;--ac-shell-inspector:0px;grid-template-columns:var(--ac-shell-rail) var(--ac-shell-listing) minmax(0, 1fr) var(--ac-shell-inspector);column-gap:0;row-gap:var(--ac-shell-gap);padding:var(--ac-shell-gap);grid-template-rows:auto 1fr;align-items:start;display:grid}.ac-shell:has(>.ac-rail){--ac-shell-rail:calc(var(--ac-size-rail) + var(--ac-shell-gap))}.ac-shell:has(>.ac-listing){--ac-shell-listing:calc(var(--ac-size-panel) + var(--ac-shell-gap))}.ac-shell:has(.ac-inspector){--ac-shell-inspector:calc(var(--ac-size-inspector) + var(--ac-shell-gap))}.ac-rail{top:var(--ac-shell-gap);max-height:calc(100vh - 2 * var(--ac-shell-gap));grid-area:1/1/3;margin-inline-end:var(--ac-shell-gap);position:sticky}.ac-bar{grid-area:1/2/auto/-1}.ac-listing{top:calc(var(--ac-size-bar) + 2 * var(--ac-shell-gap));max-height:calc(100vh - var(--ac-size-bar) - 3 * var(--ac-shell-gap));grid-area:2/2;margin-inline-end:var(--ac-shell-gap);position:sticky}.ac-page{display:contents}.ac-body{flex-direction:column;grid-area:2/3;gap:16px;min-width:0;padding-block-end:24px;display:flex}.ac-inspector{top:calc(var(--ac-size-bar) + 2 * var(--ac-shell-gap));max-height:calc(100vh - var(--ac-size-bar) - 3 * var(--ac-shell-gap));flex-direction:column;grid-area:2/4;gap:14px;margin-inline-start:var(--ac-shell-gap);padding:14px;display:flex;position:sticky;overflow:auto}.ac-rail{flex-direction:column;align-items:center;gap:6px;padding:10px 0;display:flex}.ac-rail-areas{flex-direction:column;align-items:center;gap:6px;margin:0;padding:0;list-style:none;display:flex}.ac-rail-foot{margin-top:auto}.ac-mark{width:40px;height:40px;color:var(--ac-color-ink);place-items:center;margin-bottom:8px;display:grid}.ac-mark-image{background-color:currentColor;width:32px;height:32px;-webkit-mask:url(./ankka-mark.png) 50%/contain no-repeat;mask:url(./ankka-mark.png) 50%/contain no-repeat}.ac-rail-item{width:40px;height:40px;color:var(--ac-color-ink-2);cursor:pointer;background:0 0;border:0;border-radius:12px;place-items:center;padding:0;display:grid}.ac-rail-item svg{width:20px;height:20px}a.ac-rail-item:hover,button.ac-rail-item:hover{background:var(--ac-color-glass-strong);color:var(--ac-color-ink)}.ac-rail-item[aria-current]{background:var(--ac-color-amber);color:var(--ac-color-amber-ink)}.ac-rail-item[aria-disabled=true]{color:var(--ac-color-ink-3);opacity:.5;cursor:default}.ac-bar{min-height:var(--ac-size-bar);grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);align-items:center;gap:16px;padding:8px 16px;display:grid}.ac-bar-start,.ac-bar-end{align-items:center;gap:16px;min-width:0;display:flex}.ac-bar-end{justify-content:flex-end}.ac-wordmark{letter-spacing:-.01em;white-space:nowrap;font-size:1rem;font-weight:600}.ac-root a.ac-wordmark{text-decoration:none}.ac-wordmark span{color:var(--ac-color-ink-2);font-weight:400}.ac-person{background:var(--ac-color-glass-strong);border:1px solid var(--ac-color-glass-line);border-radius:50%;flex:none;place-items:center;width:32px;height:32px;font-size:.75rem;font-weight:600;display:grid}.ac-crumbs ol{color:var(--ac-color-ink-2);white-space:nowrap;align-items:center;gap:8px;margin:0;padding:0;list-style:none;display:flex}.ac-crumbs li+li:before{content:"/";color:var(--ac-color-ink-3);margin-right:8px}.ac-root .ac-crumbs a{text-decoration:none}.ac-root .ac-crumbs a:hover{color:var(--ac-color-ink);text-decoration:underline;-webkit-text-decoration-color:var(--ac-color-amber);-webkit-text-decoration-color:var(--ac-color-amber);text-decoration-color:var(--ac-color-amber)}.ac-crumbs [aria-current=page]{color:var(--ac-color-ink);font-weight:500}.ac-listing{flex-direction:column;gap:12px;min-height:0;padding:14px;display:flex}.ac-listing-items{gap:4px;min-height:0;margin:0;padding:0;list-style:none;display:grid;overflow:auto}.ac-listing-items>li:has(>[aria-current=page]){z-index:1;position:sticky;top:0;bottom:0}.ac-listing-item{border-radius:var(--ac-radius-control);background:var(--ac-color-tile);border:1px solid #0000;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:2px 8px;padding:8px 10px;display:grid}.ac-root a.ac-listing-item{text-decoration:none}.ac-listing-item:hover{background:var(--ac-color-glass-strong)}.ac-listing-item[aria-current=page]{background:linear-gradient(var(--ac-color-glass-strong), var(--ac-color-glass-strong)), var(--ac-color-mesh-base);border-color:var(--ac-color-glass-line)}.ac-listing-name{text-overflow:ellipsis;white-space:nowrap;font-weight:500;overflow:hidden}.ac-listing-count{color:var(--ac-color-ink-2);grid-area:1/2/3;font-size:.75rem}.ac-section-title{letter-spacing:.08em;text-transform:uppercase;color:var(--ac-color-ink-3);justify-content:space-between;align-items:center;margin:0;font-size:.6875rem;font-weight:600;display:flex}.ac-seg{background:var(--ac-color-inset);border-radius:999px;grid-auto-columns:1fr;grid-auto-flow:column;padding:3px;display:inline-grid}.ac-seg a{text-align:center;color:var(--ac-color-ink-2);white-space:nowrap;border-radius:999px;padding:6px 14px;font-weight:500}.ac-root .ac-seg a{text-decoration:none}.ac-seg a[aria-current=page]{background:var(--ac-color-glass-strong);color:var(--ac-color-ink);box-shadow:0 1px 2px #0003}.ac-head{flex-wrap:wrap;align-items:center;gap:12px 16px;padding:4px 6px 0;display:flex}.ac-head .ac-seg{margin-left:auto}.ac-lede,.ac-hint,.ac-empty{color:var(--ac-color-ink-2)}.ac-hint{font-size:.8125rem}.ac-card,.ac-panel{background:var(--ac-color-tile);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);border:1px solid var(--ac-color-tile-line);border-radius:var(--ac-radius-card);flex-direction:column;gap:12px;min-width:0;padding:16px;display:flex}.ac-panel-failed{color:var(--ac-color-red)}.ac-table-wrap{overflow-x:auto}.ac-table{border-collapse:collapse;width:100%}.ac-table th,.ac-table td{text-align:left;border-top:1px solid var(--ac-color-tile-line);vertical-align:top;padding:9px 12px 9px 0}.ac-table thead th{color:var(--ac-color-ink-2);border-top:0;padding-top:0;font-size:.8125rem;font-weight:500}.ac-table .ac-num{text-align:right}.ac-facts{grid-template-columns:minmax(8rem,max-content) minmax(0,1fr);column-gap:24px;display:grid}.ac-facts dt,.ac-facts dd{border-top:1px solid var(--ac-color-tile-line);padding:9px 0}.ac-facts dt{color:var(--ac-color-ink-2)}.ac-facts dd{overflow-wrap:anywhere}.ac-facts>div{display:contents}.ac-status{white-space:nowrap;align-items:baseline;gap:6px;font-weight:500;display:inline-flex}.ac-status-mark{letter-spacing:-.15em;font-size:.75em}.ac-status-ready .ac-status-mark{color:var(--ac-color-green)}.ac-status-moving .ac-status-mark,.ac-status-partial .ac-status-mark{color:var(--ac-color-amber)}.ac-status-trouble{color:var(--ac-color-red)}.ac-status-stopped .ac-status-mark,.ac-status-idle .ac-status-mark{color:var(--ac-color-ink-3)}.ac-status-note{color:var(--ac-color-ink-2);font-weight:400}.ac-pill{background:var(--ac-color-glass-strong);border:1px solid var(--ac-color-glass-line);border-radius:999px;padding:4px 10px 4px 8px}.ac-live{color:var(--ac-color-ink-2);align-items:center;gap:8px;font-size:.8125rem;display:inline-flex}.ac-live:before{content:"";background:var(--ac-color-amber);border-radius:50%;flex:none;width:8px;height:8px}@media (prefers-reduced-motion:no-preference){.ac-live:before{animation:2.4s ease-out infinite ac-ripple}}.ac-field{gap:4px;min-width:0;max-width:32rem;display:grid}.ac-field label{font-weight:500}.ac-field-error{color:var(--ac-color-red)}.ac-form{gap:16px;display:grid}.ac-inline{flex-wrap:wrap;align-items:end;gap:8px;display:flex}.ac-inline .ac-field{flex:12rem}.ac-inspector .ac-inline{flex-direction:column;align-items:stretch}.ac-inspector .ac-inline .ac-field{flex:none}.ac-inspector .ac-field{max-width:none}.ac-switch{cursor:pointer;align-items:center;gap:10px;display:inline-flex}.ac-root .ac-switch input{opacity:0;width:1px;height:1px;position:absolute}.ac-switch-track{background:var(--ac-color-inset);border:1px solid var(--ac-color-glass-line);border-radius:999px;flex:none;width:40px;height:24px;position:relative}.ac-switch-track:after{content:"";background:var(--ac-color-ink);border-radius:50%;width:18px;height:18px;position:absolute;top:2px;left:2px}.ac-switch input:checked+.ac-switch-track{background:var(--ac-color-amber);border-color:var(--ac-color-amber)}.ac-switch input:checked+.ac-switch-track:after{background:var(--ac-color-amber-ink);transform:translate(16px)}.ac-switch input:focus-visible+.ac-switch-track{outline:3px solid var(--ac-color-amber);outline-offset:2px}@media (prefers-reduced-motion:no-preference){.ac-switch-track,.ac-switch-track:after{transition:background .15s,transform .15s}}.ac-button{font:inherit;border:1px solid var(--ac-color-glass-line);background:var(--ac-color-glass-strong);color:var(--ac-color-ink);cursor:pointer;white-space:nowrap;border-radius:999px;justify-content:center;align-items:center;gap:8px;padding:7px 14px;font-weight:500;display:inline-flex}.ac-root a.ac-button{color:var(--ac-color-ink);text-decoration:none}.ac-button svg{width:16px;height:16px}.ac-button:hover{background:var(--ac-color-glass-line)}.ac-button-primary,.ac-root a.ac-button-primary{background:var(--ac-color-amber);border-color:var(--ac-color-amber);color:var(--ac-color-amber-ink)}.ac-button-primary:hover{background:var(--ac-color-amber)}@supports (color:color-mix(in lab, red, red)){.ac-button-primary:hover{background:color-mix(in srgb, var(--ac-color-amber) 88%, white)}}.ac-button-danger,.ac-root a.ac-button-danger{background:var(--ac-color-red);border-color:var(--ac-color-red);color:var(--ac-color-mesh-base)}.ac-button-danger:hover{background:var(--ac-color-red)}@supports (color:color-mix(in lab, red, red)){.ac-button-danger:hover{background:color-mix(in srgb, var(--ac-color-red) 88%, white)}}.ac-button-quiet{background:0 0}.ac-button-small{padding:4px 10px;font-size:.8125rem}.ac-button[disabled]{opacity:.55;cursor:progress}.ac-actions{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.ac-actions form{display:inline}.ac-ops{gap:8px;display:grid}.ac-ops>form,.ac-ops>.ac-button,.ac-ops>form>.ac-button{width:100%}.ac-more{border-top:1px solid var(--ac-color-glass-line);padding-top:12px}.ac-more summary{cursor:pointer;font-weight:500}.ac-more[open]>*+*{margin-top:12px}.ac-danger-zone{border-left:3px solid var(--ac-color-red);gap:10px;padding:8px 0 8px 12px;display:grid}.ac-danger-zone p{color:var(--ac-color-ink-2);font-size:.8125rem}.ac-refusal{border-left:3px solid var(--ac-color-red);background:var(--ac-color-red-wash);border-radius:0 var(--ac-radius-control) var(--ac-radius-control) 0;padding:10px 14px}.ac-refusal ul{margin:6px 0 0;padding-left:1.2rem}.ac-notice{border-left:3px solid var(--ac-color-amber);background:var(--ac-color-tile);border-radius:0 var(--ac-radius-control) var(--ac-radius-control) 0;padding:10px 14px}.ac-secret{font-family:var(--ac-font-mono);background:var(--ac-color-inset);border:1px dashed var(--ac-color-ink-3);border-radius:var(--ac-radius-control);overflow-wrap:anywhere;-webkit-user-select:all;user-select:all;padding:10px;display:block}.ac-log{font-family:var(--ac-font-mono);background:var(--ac-color-inset);border:1px solid var(--ac-color-tile-line);border-radius:var(--ac-radius-control);white-space:pre-wrap;overflow-wrap:anywhere;max-height:32rem;margin:0;padding:12px;font-size:.8125rem;overflow:auto}.ac-mounts{gap:4px;margin:0;padding:0;list-style:none;display:grid}.ac-visually-hidden{clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.ac-shape{border-radius:var(--ac-radius-panel);border:1px solid var(--ac-color-glass-line);padding:28px 20px 20px}.ac-tree{justify-items:center;max-width:720px;margin:0 auto;display:grid}.ac-row{justify-items:center;width:100%;display:grid}.ac-row-many{gap:24px}.ac-part{background:var(--ac-color-node);-webkit-backdrop-filter:blur(18px)saturate(140%);backdrop-filter:blur(18px)saturate(140%);border:1px solid var(--ac-color-node-line);border-radius:var(--ac-radius-node);width:100%;max-width:300px;box-shadow:var(--ac-shadow-part);grid-template-columns:auto minmax(0,1fr);align-items:center;gap:2px 12px;padding:16px 16px 14px;display:grid;position:relative}.ac-part-self{box-shadow:var(--ac-shadow-part), 0 0 0 2px var(--ac-color-amber), 0 0 24px var(--ac-color-amber)}@supports (color:color-mix(in lab, red, red)){.ac-part-self{box-shadow:var(--ac-shadow-part), 0 0 0 2px var(--ac-color-amber), 0 0 24px color-mix(in srgb, var(--ac-color-amber) 45%, transparent)}}.ac-part-icon{width:40px;height:40px;color:var(--ac-color-ink);grid-row:1/3}.ac-part-icon svg{width:40px;height:40px}.ac-part-title,.ac-part-sub{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.ac-part-title{font-weight:500}.ac-part-sub{color:var(--ac-color-ink-2);font-size:.8125rem}.ac-part-inset{background:var(--ac-color-inset);border-radius:10px;grid-column:1/3;justify-content:space-between;align-items:center;gap:8px;margin-top:10px;padding:7px 12px;font-size:.8125rem;display:flex}.ac-part-up:before,.ac-part-down:after{content:"";background:var(--ac-color-node);border:1px solid var(--ac-color-node-line);width:12px;height:7px;position:absolute;left:50%;transform:translate(-50%)}.ac-part-down:after{border-top:0;border-radius:0 0 7px 7px;bottom:-7px}.ac-part-up:before{border-bottom:0;border-radius:7px 7px 0 0;top:-7px}.ac-part-tab{background:var(--ac-color-node);border:1px solid var(--ac-color-node-line);border-bottom:0;border-radius:12px 12px 0 0;gap:2px;padding:2px 8px 6px;display:flex;position:absolute;top:-27px;left:50%;transform:translate(-50%)}.ac-part-tab form{display:contents}.ac-tab-control{width:24px;height:20px;color:var(--ac-color-ink);cursor:pointer;background:0 0;border:0;border-radius:6px;place-items:center;padding:0;display:grid}.ac-tab-control:hover{background:var(--ac-color-glass-strong)}.ac-tab-control svg{width:14px;height:14px}.ac-part-tabbed{margin-top:27px}.ac-part-tabbed.ac-part-up:before{display:none}.ac-edge{width:100%;height:48px;color:var(--ac-color-edge);display:block;overflow:visible}.ac-edge path{fill:none;stroke:currentColor;stroke-width:1.5px;vector-effect:non-scaling-stroke}.ac-topology{align-items:flex-start;gap:16px;display:flex}.ac-topology-picture{border-radius:var(--ac-radius-panel);border:1px solid var(--ac-color-glass-line);flex:1;min-width:0;padding:8px;overflow-x:auto}.ac-topology-detail{flex:0 0 18rem}.ac-topology-node rect{fill:var(--ac-color-node);stroke:var(--ac-color-node-line);stroke-width:1px}.ac-topology-node{cursor:pointer}.ac-topology-node:focus-visible rect,.ac-topology-selected rect{stroke:var(--ac-color-amber);stroke-width:2px}.ac-topology-node:focus{outline:none}.ac-topology-outside rect,.ac-topology-differs rect{stroke-dasharray:4 3}.ac-topology-platform rect{fill:var(--ac-color-inset)}.ac-topology-name{fill:var(--ac-color-ink);font-size:12px;font-weight:600}.ac-topology-kind{fill:var(--ac-color-ink-2);font-size:11px}.ac-topology-declared{fill:none;stroke:var(--ac-color-edge);stroke-width:1.25px}.ac-topology-call{fill:none;stroke:var(--ac-color-ink);stroke-dasharray:5 4}.ac-topology-warning{stroke:var(--ac-color-red)}.ac-topology-mark{fill:var(--ac-color-red);font-size:14px;font-weight:700}@media (forced-colors:active){.ac-rail,.ac-bar,.ac-listing,.ac-inspector,.ac-card,.ac-panel,.ac-part,.ac-listing-item{border:1px solid canvastext}.ac-button,.ac-rail-item,.ac-seg a{border:1px solid buttontext}.ac-rail-item[aria-current],.ac-seg a[aria-current=page],.ac-listing-item[aria-current=page]{outline:2px solid highlight}}@media (max-width:1180px){.ac-shell,.ac-shell:has(>.ac-listing),.ac-shell:has(.ac-inspector){grid-template-columns:var(--ac-shell-rail) minmax(0, 1fr);grid-template-rows:none;grid-auto-rows:auto}.ac-rail{grid-row:1/span 5}.ac-bar,.ac-listing,.ac-body,.ac-inspector{grid-area:auto/2;max-height:none;margin-inline:0;position:static}.ac-listing-items{grid-template-columns:repeat(auto-fill,minmax(200px,1fr));max-height:18rem}}@media (max-width:720px){.ac-shell,.ac-shell:has(>.ac-rail),.ac-shell:has(>.ac-listing),.ac-shell:has(.ac-inspector){grid-template-columns:minmax(0,1fr)}.ac-rail{flex-flow:wrap;grid-area:auto/1;justify-content:flex-start;max-height:none;margin:0;padding:8px 10px;position:static}.ac-rail-areas{flex-flow:wrap}.ac-mark{margin:0 6px 0 0}.ac-rail-foot{margin-top:0;margin-left:auto}.ac-bar,.ac-listing,.ac-body,.ac-inspector{grid-column:1}.ac-bar{grid-template-columns:minmax(0,1fr) auto}.ac-bar-start{overflow:hidden}.ac-wordmark span{display:none}.ac-crumbs{grid-area:2/1/auto/-1}.ac-crumbs ol{white-space:normal;flex-wrap:wrap;row-gap:2px}.ac-head .ac-seg{width:100%;margin-left:0}.ac-row-many{gap:20px;grid-template-columns:minmax(0,1fr)!important}.ac-edge-split{display:none}.ac-facts{grid-template-columns:minmax(0,1fr)}.ac-facts dd{border-top:0;padding-top:0}.ac-topology{flex-direction:column}.ac-topology-detail{flex-basis:auto;width:100%}}}@layer utilities;@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./fonts/inter-latin-wght-normal.woff2)format("woff2-variations");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./fonts/inter-latin-ext-wght-normal.woff2)format("woff2-variations");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@keyframes ac-ripple{0%{box-shadow:0 0 0 0 color-mix(in srgb, var(--ac-color-amber) 60%, transparent)}to{box-shadow:0 0 0 .6rem #0000}}
|
|
@@ -204,6 +204,16 @@ interface TopicCheckRecord {
|
|
|
204
204
|
stated?: string;
|
|
205
205
|
state: string;
|
|
206
206
|
}
|
|
207
|
+
/** A named bucket as the operator reports it (feature 055). */
|
|
208
|
+
export interface BucketRecord {
|
|
209
|
+
name: string;
|
|
210
|
+
phase: string;
|
|
211
|
+
store?: string;
|
|
212
|
+
bucket?: string;
|
|
213
|
+
exposure: string;
|
|
214
|
+
publicAddress?: string;
|
|
215
|
+
kept?: boolean;
|
|
216
|
+
}
|
|
207
217
|
interface Service {
|
|
208
218
|
name: string;
|
|
209
219
|
projectId: string;
|
|
@@ -273,6 +283,8 @@ interface Service {
|
|
|
273
283
|
bucketLocation?: string;
|
|
274
284
|
/** Where a move of its bucket from Garage is, as the control plane phrases it. */
|
|
275
285
|
storageMove?: string;
|
|
286
|
+
/** Its named buckets as the operator would report them (feature 055), kept ones last. */
|
|
287
|
+
buckets?: BucketRecord[];
|
|
276
288
|
/** What the instances report when asked for the topology; generated from the service when unset. */
|
|
277
289
|
topology?: FakeTopology;
|
|
278
290
|
}
|
|
@@ -445,6 +457,8 @@ export interface FakeSeed {
|
|
|
445
457
|
/** The store its bucket is in, `garage` or `gcs`. */
|
|
446
458
|
objectStore?: string;
|
|
447
459
|
bucketLocation?: string;
|
|
460
|
+
/** Its named buckets as the operator reports them (feature 055). */
|
|
461
|
+
buckets?: BucketRecord[];
|
|
448
462
|
}[];
|
|
449
463
|
/** Project secrets, by name and entry: a value each, never listed. */
|
|
450
464
|
secrets?: {
|
|
@@ -165,6 +165,25 @@ export async function fakeControlPlane(options = {}) {
|
|
|
165
165
|
s.provisionObjectStorage = d.service?.provisionObjectStorage ?? false;
|
|
166
166
|
s.exposeObjectStorage = d.service?.exposeObjectStorage ?? false;
|
|
167
167
|
s.ownObjectStore = (d.service?.env ?? []).some((e) => e.name.startsWith("ANKKA_S3_"));
|
|
168
|
+
// Named buckets (feature 055): one report each, and one the descriptor stopped naming is kept.
|
|
169
|
+
const named = (d.service?.buckets ?? []).map((b) => {
|
|
170
|
+
if (b.supplied)
|
|
171
|
+
return { name: b.name, phase: "Supplied", bucket: b.supplied.bucket, exposure: "supplied" };
|
|
172
|
+
const exposure = b.exposure ?? "private";
|
|
173
|
+
const bucket = `${s.projectId}.${s.name}.${b.name}`;
|
|
174
|
+
return {
|
|
175
|
+
name: b.name,
|
|
176
|
+
phase: "Provisioned",
|
|
177
|
+
store: "garage",
|
|
178
|
+
bucket,
|
|
179
|
+
exposure,
|
|
180
|
+
...(exposure === "private" ? {} : { publicAddress: `https://storage.${options.baseDomain ?? "example.test"}/${bucket}` }),
|
|
181
|
+
};
|
|
182
|
+
});
|
|
183
|
+
const dropped = (s.buckets ?? [])
|
|
184
|
+
.filter((b) => b.phase !== "Supplied" && !named.some((n) => n.name === b.name))
|
|
185
|
+
.map((b) => ({ ...b, phase: "Kept", kept: true }));
|
|
186
|
+
s.buckets = [...named, ...dropped];
|
|
168
187
|
if (s.provisionObjectStorage && !s.objectStore) {
|
|
169
188
|
s.objectStore = objectStore;
|
|
170
189
|
if (objectStore === "gcs")
|
|
@@ -222,6 +241,7 @@ export async function fakeControlPlane(options = {}) {
|
|
|
222
241
|
bucketLocation: s.provisionObjectStorage && s.objectStore === "gcs" ? (s.bucketLocation ?? null) : null,
|
|
223
242
|
softDeleteDays: s.provisionObjectStorage && s.objectStore === "gcs" ? 7 : null,
|
|
224
243
|
storageMove: s.storageMove ?? null,
|
|
244
|
+
...(s.buckets && s.buckets.length > 0 ? { buckets: s.buckets } : {}),
|
|
225
245
|
customHostnames: (s.customHostnames ?? []).map((hostname) => ({
|
|
226
246
|
hostname,
|
|
227
247
|
// The fake has no authority to wait for: an exposed service's hostnames serve at once.
|
|
@@ -1827,6 +1847,7 @@ export async function fakeControlPlane(options = {}) {
|
|
|
1827
1847
|
ownObjectStore: s.ownObjectStore,
|
|
1828
1848
|
objectStore: s.objectStore,
|
|
1829
1849
|
bucketLocation: s.bucketLocation,
|
|
1850
|
+
buckets: s.buckets,
|
|
1830
1851
|
});
|
|
1831
1852
|
}
|
|
1832
1853
|
for (const sec of seed.secrets ?? []) {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { BucketReport } from "../client/schemas.ts";
|
|
2
|
+
/** One row of a service's named buckets, as the service page shows it (feature 055). */
|
|
3
|
+
export interface BucketRow {
|
|
4
|
+
name: string;
|
|
5
|
+
/** The exposure, `supplied` for a bucket the developer made, or `kept` for one no longer named. */
|
|
6
|
+
exposure: string;
|
|
7
|
+
/** Its name in the store, when reported. */
|
|
8
|
+
bucket: string | null;
|
|
9
|
+
/** Where it is on the internet, as a link, when it is. */
|
|
10
|
+
address: string | null;
|
|
11
|
+
/** Said of a bucket the descriptor no longer names, which is kept rather than deleted. */
|
|
12
|
+
note: string | null;
|
|
13
|
+
}
|
|
14
|
+
export declare function bucketRows(buckets: readonly BucketReport[] | null | undefined): BucketRow[];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function bucketRows(buckets) {
|
|
2
|
+
return (buckets ?? []).map((b) => ({
|
|
3
|
+
name: b.name,
|
|
4
|
+
exposure: b.kept ? "kept" : b.phase === "Supplied" || b.exposure === "supplied" ? "supplied" : b.exposure,
|
|
5
|
+
bucket: b.bucket ?? null,
|
|
6
|
+
address: b.kept ? null : (b.publicAddress ?? null),
|
|
7
|
+
note: b.kept ? "kept, no longer named" : null,
|
|
8
|
+
}));
|
|
9
|
+
}
|
package/dist/ui/shell.js
CHANGED
|
@@ -15,8 +15,12 @@ export function Shell({ children, className, theme = "dark" }) {
|
|
|
15
15
|
export function Backdrop() {
|
|
16
16
|
return _jsx("div", { className: "ac-backdrop", "aria-hidden": "true" });
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* The mark: the duck, as a mask over the current colour, so it follows `--ac-color-ink` and a host's
|
|
20
|
+
* override of it in either theme with one asset. The build copies the image beside the stylesheet.
|
|
21
|
+
*/
|
|
18
22
|
function Mark() {
|
|
19
|
-
return (
|
|
23
|
+
return _jsx("span", { className: "ac-mark-image", "aria-hidden": "true" });
|
|
20
24
|
}
|
|
21
25
|
const initials = (name) => name
|
|
22
26
|
.split(/[\s@.]+/)
|
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
* read. Handled and unanswered are separate columns, because they are separate facts.
|
|
4
4
|
*/
|
|
5
5
|
import type { Pair, View } from "./layout.ts";
|
|
6
|
+
/**
|
|
7
|
+
* A handler as the table names it: a tool, an agent's or an MCP endpoint's, is marked with a tool
|
|
8
|
+
* glyph and the word, so an MCP endpoint's tools read apart from its routes, to a screen reader too.
|
|
9
|
+
*/
|
|
10
|
+
export declare function handlerInWords(h: {
|
|
11
|
+
name: string;
|
|
12
|
+
type: string;
|
|
13
|
+
}): string;
|
|
6
14
|
export declare function duration(pair: Pair): string;
|
|
7
15
|
export declare function Table({ shown, differs }: {
|
|
8
16
|
shown: View;
|
|
@@ -5,10 +5,17 @@ function nameOf(shown, id) {
|
|
|
5
5
|
function kindInWords(kind) {
|
|
6
6
|
return kind.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase();
|
|
7
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* A handler as the table names it: a tool, an agent's or an MCP endpoint's, is marked with a tool
|
|
10
|
+
* glyph and the word, so an MCP endpoint's tools read apart from its routes, to a screen reader too.
|
|
11
|
+
*/
|
|
12
|
+
export function handlerInWords(h) {
|
|
13
|
+
return h.type === "tool" ? `🔧 ${h.name} (tool)` : h.name;
|
|
14
|
+
}
|
|
8
15
|
export function duration(pair) {
|
|
9
16
|
const d = pair.durationMillis;
|
|
10
17
|
return d ? `~${d.p50} / ~${d.p99} / ~${d.max} ms` : "";
|
|
11
18
|
}
|
|
12
19
|
export function Table({ shown, differs }) {
|
|
13
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "ac-table-wrap", children: _jsxs("table", { className: "ac-table", "aria-label": "Components", children: [_jsx("caption", { className: "ac-visually-hidden", children: "Components" }), _jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { scope: "col", children: "Name" }), _jsx("th", { scope: "col", children: "Kind" }), _jsx("th", { scope: "col", children: "Handlers" })] }) }), _jsx("tbody", { children: shown.nodes.map((n) => (_jsxs("tr", { "data-node": n.id, children: [_jsx("td", { children: n.label }), _jsxs("td", { children: [kindInWords(n.kind), n.platform ? ", platform" : "", differs.has(n.id) ? `, only on ${differs.get(n.id).join(", ")}` : ""] }), _jsx("td", { children: n.handlers.map(
|
|
20
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "ac-table-wrap", children: _jsxs("table", { className: "ac-table", "aria-label": "Components", children: [_jsx("caption", { className: "ac-visually-hidden", children: "Components" }), _jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { scope: "col", children: "Name" }), _jsx("th", { scope: "col", children: "Kind" }), _jsx("th", { scope: "col", children: "Handlers" })] }) }), _jsx("tbody", { children: shown.nodes.map((n) => (_jsxs("tr", { "data-node": n.id, children: [_jsx("td", { children: n.label }), _jsxs("td", { children: [kindInWords(n.kind), n.platform ? ", platform" : "", differs.has(n.id) ? `, only on ${differs.get(n.id).join(", ")}` : ""] }), _jsx("td", { children: n.handlers.map(handlerInWords).join(", ") })] }, n.id))) })] }) }), shown.declared.length > 0 ? (_jsx("div", { className: "ac-table-wrap", children: _jsxs("table", { className: "ac-table", "aria-label": "Declared connections", children: [_jsx("caption", { className: "ac-visually-hidden", children: "Declared connections" }), _jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { scope: "col", children: "From" }), _jsx("th", { scope: "col", children: "To" }), _jsx("th", { scope: "col", children: "As" })] }) }), _jsx("tbody", { children: shown.declared.map((e) => (_jsxs("tr", { children: [_jsx("td", { children: nameOf(shown, e.from) }), _jsx("td", { children: nameOf(shown, e.to) }), _jsx("td", { children: e.kind })] }, `${e.from}>${e.to}:${e.kind}`))) })] }) })) : null, shown.calls.length > 0 ? (_jsx("div", { className: "ac-table-wrap", children: _jsxs("table", { className: "ac-table", "aria-label": "Observed calls", children: [_jsx("caption", { className: "ac-visually-hidden", children: "Observed calls" }), _jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { scope: "col", children: "From" }), _jsx("th", { scope: "col", children: "To" }), _jsx("th", { scope: "col", children: "Handler to handler" }), _jsx("th", { scope: "col", className: "ac-num", children: "Ok" }), _jsx("th", { scope: "col", className: "ac-num", children: "Refused" }), _jsx("th", { scope: "col", className: "ac-num", children: "Failed" }), _jsx("th", { scope: "col", className: "ac-num", children: "Timed out" }), _jsx("th", { scope: "col", className: "ac-num", children: "Undelivered" }), _jsx("th", { scope: "col", children: "p50 / p99 / max" })] }) }), _jsx("tbody", { children: shown.calls.flatMap((c) => c.pairs.map((p) => (_jsxs("tr", { "data-pair": `${p.caller} -> ${p.callee}`, children: [_jsx("td", { children: nameOf(shown, c.from) }), _jsx("td", { children: nameOf(shown, c.to) }), _jsxs("td", { children: [p.caller, " \u2192 ", p.callee, p.streaming ? " (stream)" : ""] }), _jsx("td", { className: "ac-num", children: p.handled?.ok ?? 0 }), _jsx("td", { className: "ac-num", children: p.handled?.refused ?? 0 }), _jsx("td", { className: "ac-num", children: p.handled?.failed ?? 0 }), _jsx("td", { className: "ac-num", children: p.unanswered?.timedOut ?? 0 }), _jsx("td", { className: "ac-num", children: p.unanswered?.undelivered ?? 0 }), _jsx("td", { children: duration(p) })] }, `${c.from}>${c.to}:${p.caller}>${p.callee}`)))) })] }) })) : null] }));
|
|
14
21
|
}
|
package/dist/ui/use-stream.d.ts
CHANGED
|
@@ -85,6 +85,16 @@ export declare function useProjectStream(projectId: string, initial: ServiceStat
|
|
|
85
85
|
bucketLocation: string | undefined;
|
|
86
86
|
softDeleteDays: number | undefined;
|
|
87
87
|
storageMove: string | undefined;
|
|
88
|
+
buckets: {
|
|
89
|
+
name: string;
|
|
90
|
+
phase: string;
|
|
91
|
+
store: string | undefined;
|
|
92
|
+
bucket: string | undefined;
|
|
93
|
+
exposure: string;
|
|
94
|
+
publicAddress: string | undefined;
|
|
95
|
+
kept: boolean;
|
|
96
|
+
detail: string | undefined;
|
|
97
|
+
}[] | undefined;
|
|
88
98
|
databaseCluster: string | undefined;
|
|
89
99
|
grants: string | undefined;
|
|
90
100
|
crossProjectTopics: {
|
|
@@ -208,6 +218,16 @@ export declare function useServiceStream(projectId: string, name: string, initia
|
|
|
208
218
|
bucketLocation: string | undefined;
|
|
209
219
|
softDeleteDays: number | undefined;
|
|
210
220
|
storageMove: string | undefined;
|
|
221
|
+
buckets: {
|
|
222
|
+
name: string;
|
|
223
|
+
phase: string;
|
|
224
|
+
store: string | undefined;
|
|
225
|
+
bucket: string | undefined;
|
|
226
|
+
exposure: string;
|
|
227
|
+
publicAddress: string | undefined;
|
|
228
|
+
kept: boolean;
|
|
229
|
+
detail: string | undefined;
|
|
230
|
+
}[] | undefined;
|
|
211
231
|
databaseCluster: string | undefined;
|
|
212
232
|
grants: string | undefined;
|
|
213
233
|
crossProjectTopics: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ankka-console",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "The ankka console as a package: the control plane client, sign-in and sessions, and the pages as routes a React Router host mounts.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|