@swirls/looms 0.1.0 → 0.2.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/CHANGELOG.md +15 -0
- package/dist/actor/host.js +2 -1
- package/dist/agent/debugger/agent-chat.d.ts +2 -0
- package/dist/agent/debugger/agent-chat.js +176 -0
- package/dist/agent/debugger/index.d.ts +5 -0
- package/dist/agent/debugger/index.js +19 -0
- package/dist/agent/debugger/summarize.d.ts +2 -0
- package/dist/agent/debugger/summarize.js +51 -0
- package/dist/agent/debugger/token-usage.d.ts +3 -0
- package/dist/agent/debugger/token-usage.js +11 -0
- package/dist/agent/definitions.d.ts +3 -11
- package/dist/agent/definitions.js +5 -6
- package/dist/agent/signals.d.ts +2 -0
- package/dist/agent/signals.js +18 -16
- package/dist/agent/tool-schema.d.ts +1 -17
- package/dist/agent/tool-schema.js +3 -42
- package/dist/ai-vercel/index.d.ts +1 -1
- package/dist/ai-vercel/vercel-evaluator.d.ts +21 -8
- package/dist/ai-vercel/vercel-evaluator.js +7 -2
- package/dist/approval/debugger/approvals-view.d.ts +3 -0
- package/dist/approval/debugger/approvals-view.js +16 -0
- package/dist/approval/debugger/index.d.ts +4 -0
- package/dist/approval/debugger/index.js +11 -0
- package/dist/approval/debugger/summarize.d.ts +2 -0
- package/dist/approval/debugger/summarize.js +17 -0
- package/dist/client/client.d.ts +18 -0
- package/dist/client/client.js +3 -1
- package/dist/cloudflare/router.d.ts +1 -1
- package/dist/cloudflare/router.js +2 -2
- package/dist/core/compose.js +1 -0
- package/dist/core/debugger-host.d.ts +16 -0
- package/dist/core/debugger-host.js +1 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +1 -0
- package/dist/core/module.d.ts +2 -0
- package/dist/core/published.d.ts +43 -0
- package/dist/core/published.js +44 -0
- package/dist/core/schema.d.ts +3 -1
- package/dist/core/schema.js +38 -0
- package/dist/core/snapshot-store.d.ts +4 -0
- package/dist/core/snapshot-store.js +7 -0
- package/dist/core/sqlite-store.js +39 -0
- package/dist/debugger/app/assets/index-B3Ah8WAE.css +2 -0
- package/dist/debugger/app/assets/index-Qb371t_O.js +22 -0
- package/dist/debugger/app/assets/rolldown-runtime-CbXtAM7H.js +1 -0
- package/dist/debugger/app/assets/routes-CjtEHgPQ.js +47 -0
- package/dist/debugger/app/index.html +14 -0
- package/dist/debugger/components/composer.d.ts +17 -0
- package/dist/debugger/components/composer.js +25 -0
- package/dist/debugger/components/debugger-split.d.ts +2 -1
- package/dist/debugger/components/debugger-split.js +2 -2
- package/dist/debugger/components/event-inspector.d.ts +2 -1
- package/dist/debugger/components/event-inspector.js +25 -16
- package/dist/debugger/components/event-stream.d.ts +2 -1
- package/dist/debugger/components/event-stream.js +12 -71
- package/dist/debugger/components/follow-list.d.ts +19 -0
- package/dist/debugger/components/follow-list.js +96 -0
- package/dist/debugger/components/json-tree.d.ts +11 -0
- package/dist/debugger/components/json-tree.js +120 -0
- package/dist/debugger/components/json-view.js +2 -2
- package/dist/debugger/components/run-tree.js +53 -20
- package/dist/debugger/components/status-dot.d.ts +4 -0
- package/dist/debugger/components/status-dot.js +6 -2
- package/dist/debugger/context.d.ts +14 -0
- package/dist/debugger/context.js +17 -0
- package/dist/debugger/contracts.d.ts +7 -4
- package/dist/debugger/events/builtin-families.d.ts +3 -0
- package/dist/debugger/events/builtin-families.js +9 -0
- package/dist/debugger/events/catalog.d.ts +3 -4
- package/dist/debugger/events/catalog.js +27 -17
- package/dist/debugger/events/protocol-summarize.d.ts +1 -2
- package/dist/debugger/events/protocol-summarize.js +29 -37
- package/dist/debugger/index.d.ts +20 -6
- package/dist/debugger/index.js +19 -5
- package/dist/debugger/lib/cn.d.ts +1 -0
- package/dist/debugger/lib/cn.js +3 -0
- package/dist/debugger/lib/event-meta.d.ts +2 -3
- package/dist/debugger/lib/event-meta.js +6 -11
- package/dist/debugger/lib/json.d.ts +25 -0
- package/dist/debugger/lib/json.js +87 -0
- package/dist/debugger/lib/payload.d.ts +7 -0
- package/dist/debugger/lib/payload.js +11 -0
- package/dist/debugger/lib/time.d.ts +3 -0
- package/dist/debugger/lib/time.js +24 -0
- package/dist/debugger/plugin.d.ts +36 -0
- package/dist/debugger/plugin.js +14 -0
- package/dist/debugger/server/index.d.ts +14 -0
- package/dist/debugger/server/index.js +114 -0
- package/dist/debugger/shell/debugger-shell.d.ts +15 -0
- package/dist/debugger/shell/debugger-shell.js +43 -0
- package/dist/debugger/shell/definition-key.d.ts +3 -0
- package/dist/debugger/shell/definition-key.js +4 -0
- package/dist/debugger/shell/events-pane.d.ts +12 -0
- package/dist/debugger/shell/events-pane.js +25 -0
- package/dist/debugger/shell/projections-panel.d.ts +4 -0
- package/dist/debugger/shell/projections-panel.js +59 -0
- package/dist/debugger/shell/run-controls.d.ts +4 -0
- package/dist/debugger/shell/run-controls.js +72 -0
- package/dist/debugger/shell/run-search.d.ts +6 -0
- package/dist/debugger/shell/run-search.js +102 -0
- package/dist/debugger/shell/run-type-menu.d.ts +6 -0
- package/dist/debugger/shell/run-type-menu.js +11 -0
- package/dist/debugger/shell/schema-form.d.ts +31 -0
- package/dist/debugger/shell/schema-form.js +117 -0
- package/dist/debugger/shell/start-form.d.ts +3 -0
- package/dist/debugger/shell/start-form.js +75 -0
- package/dist/debugger/shell/use-start-run.d.ts +14 -0
- package/dist/debugger/shell/use-start-run.js +32 -0
- package/dist/debugger/shell/workspace.d.ts +6 -0
- package/dist/debugger/shell/workspace.js +15 -0
- package/dist/debugger/styles.css +111 -27
- package/dist/debugger/ui/button.d.ts +24 -0
- package/dist/debugger/ui/button.js +24 -0
- package/dist/debugger/ui/command.d.ts +9 -0
- package/dist/debugger/ui/command.js +24 -0
- package/dist/debugger/ui/dropdown-menu.d.ts +13 -0
- package/dist/debugger/ui/dropdown-menu.js +37 -0
- package/dist/debugger/ui/panel.d.ts +14 -0
- package/dist/debugger/ui/panel.js +16 -0
- package/dist/debugger/ui/popover.d.ts +7 -0
- package/dist/debugger/ui/popover.js +17 -0
- package/dist/debugger/ui/resizable.d.ts +7 -0
- package/dist/debugger/ui/resizable.js +14 -0
- package/dist/debugger/ui/scroll-area.d.ts +2 -1
- package/dist/debugger/ui/scroll-area.js +5 -3
- package/dist/debugger/ui/select.d.ts +10 -0
- package/dist/debugger/ui/select.js +21 -0
- package/dist/debugger/ui/tabs.js +2 -2
- package/dist/debugger/ui/textarea.d.ts +3 -0
- package/dist/debugger/ui/textarea.js +7 -0
- package/dist/react/store.d.ts +1 -1
- package/dist/react/store.js +1 -1
- package/dist/runtime/looms.d.ts +9 -1
- package/dist/runtime/looms.js +4 -2
- package/dist/runtime/repository.js +16 -1
- package/dist/runtime/runtime.js +16 -1
- package/dist/runtime/server/auth.d.ts +1 -0
- package/dist/runtime/server/auth.js +5 -0
- package/dist/runtime/server/debugger-host.d.ts +11 -0
- package/dist/runtime/server/debugger-host.js +32 -0
- package/dist/runtime/server/fetch-handler.d.ts +5 -1
- package/dist/runtime/server/fetch-handler.js +24 -13
- package/dist/runtime/server/http.d.ts +1 -0
- package/dist/runtime/server/http.js +4 -0
- package/dist/runtime/server/routes/definitions.d.ts +3 -0
- package/dist/runtime/server/routes/definitions.js +20 -0
- package/dist/runtime/server/routes/runs.js +8 -1
- package/dist/runtime/server.d.ts +3 -1
- package/dist/runtime/server.js +3 -1
- package/dist/runtime/types.d.ts +3 -1
- package/dist/s2/snapshot-store.js +43 -1
- package/dist/workflow/debugger/index.d.ts +4 -0
- package/dist/workflow/debugger/index.js +11 -0
- package/dist/workflow/debugger/nodes-view.d.ts +3 -0
- package/dist/workflow/debugger/nodes-view.js +13 -0
- package/dist/workflow/debugger/summarize.d.ts +2 -0
- package/dist/workflow/debugger/summarize.js +30 -0
- package/package.json +20 -1
- package/dist/debugger/events/domain-summarize.d.ts +0 -3
- package/dist/debugger/events/domain-summarize.js +0 -107
- package/dist/debugger/events/family.d.ts +0 -8
- package/dist/debugger/events/family.js +0 -44
|
@@ -1,16 +1,29 @@
|
|
|
1
|
+
import { experimental_evaluate } from 'ai';
|
|
1
2
|
import type { EvaluatorAdapter, EvaluatorAnswers, EvaluatorQuestions } from '@swirls/looms/evaluator';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
type EvaluateOptions = Parameters<typeof experimental_evaluate>[0];
|
|
4
|
+
type EvaluationModel = Exclude<EvaluateOptions['model'], string>;
|
|
5
|
+
/** An AI SDK provider with evaluation models, such as `createTypeSafeAi({ apiKey })`. */
|
|
6
|
+
export interface EvaluationModelProvider {
|
|
7
|
+
readonly evaluationModel: (modelId: string) => EvaluationModel;
|
|
8
|
+
}
|
|
9
|
+
interface VercelEvaluatorBaseOptions {
|
|
5
10
|
/** Abort the hosted call after this many milliseconds. Defaults to 2000. */
|
|
6
11
|
readonly timeoutMs?: number;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
readonly zeroDataRetention?: boolean;
|
|
10
|
-
};
|
|
11
|
-
};
|
|
12
|
+
/** Defaults to AI Gateway zero data retention when no `provider` is set. */
|
|
13
|
+
readonly providerOptions?: EvaluateOptions['providerOptions'];
|
|
12
14
|
}
|
|
15
|
+
export type VercelEvaluatorOptions = VercelEvaluatorBaseOptions & ({
|
|
16
|
+
/** AI Gateway model id. Defaults to TypeSafe Jev (`typesafe-ai/jev`). */
|
|
17
|
+
readonly model?: string;
|
|
18
|
+
readonly provider?: undefined;
|
|
19
|
+
} | {
|
|
20
|
+
/** Default model id for `provider`. A definition's own `model` takes precedence. */
|
|
21
|
+
readonly model: string;
|
|
22
|
+
/** Resolves model ids with your own provider and key instead of the AI Gateway. */
|
|
23
|
+
readonly provider: EvaluationModelProvider;
|
|
24
|
+
});
|
|
13
25
|
interface EvaluateAnswer {
|
|
26
|
+
readonly type?: 'boolean' | 'choice' | 'score';
|
|
14
27
|
readonly probability?: number;
|
|
15
28
|
readonly choice?: string;
|
|
16
29
|
readonly score?: number;
|
|
@@ -44,11 +44,16 @@ export function toEvaluatorAnswers(questions, raw) {
|
|
|
44
44
|
}
|
|
45
45
|
export function vercelEvaluator(options = {}) {
|
|
46
46
|
const timeoutMs = options.timeoutMs ?? 2000;
|
|
47
|
-
const providerOptions = options.providerOptions ??
|
|
47
|
+
const providerOptions = options.providerOptions ??
|
|
48
|
+
(options.provider ? undefined : { gateway: { zeroDataRetention: true } });
|
|
49
|
+
function resolveModel(modelId) {
|
|
50
|
+
const id = modelId ?? options.model ?? DEFAULT_EVALUATOR_MODEL;
|
|
51
|
+
return options.provider ? options.provider.evaluationModel(id) : id;
|
|
52
|
+
}
|
|
48
53
|
return {
|
|
49
54
|
evaluate: (args) => Effect.runPromise(Effect.tryPromise({
|
|
50
55
|
try: () => experimental_evaluate({
|
|
51
|
-
model: args.model
|
|
56
|
+
model: resolveModel(args.model),
|
|
52
57
|
state: args.state,
|
|
53
58
|
abortSignal: abortSignalFor(timeoutMs, args.signal),
|
|
54
59
|
maxRetries: 0,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, StatusBadge, useDebugger } from '@swirls/looms/debugger';
|
|
3
|
+
import { useProjection, useRunStore } from '@swirls/looms/react';
|
|
4
|
+
import { pendingApprovals } from '../projections.js';
|
|
5
|
+
import { decision } from '../signals.js';
|
|
6
|
+
export function ApprovalsView({ runId }) {
|
|
7
|
+
const { client } = useDebugger();
|
|
8
|
+
const state = useProjection(useRunStore(runId), pendingApprovals);
|
|
9
|
+
if (state.items.length === 0) {
|
|
10
|
+
return _jsx("p", { className: "text-muted-foreground text-xs", children: "No approvals requested." });
|
|
11
|
+
}
|
|
12
|
+
function decide(approvalId, outcome) {
|
|
13
|
+
void client.signal(runId, [decision(approvalId, outcome)]);
|
|
14
|
+
}
|
|
15
|
+
return (_jsx("ul", { className: "grid gap-2", children: state.items.map((item) => (_jsxs("li", { className: "border-border bg-card/60 rounded-lg border p-2.5", children: [_jsxs("div", { className: "flex items-center gap-2 text-xs", children: [_jsx("span", { className: "min-w-0 flex-1 truncate font-medium", children: item.title || item.approvalId }), _jsx(StatusBadge, { status: item.status })] }), item.status === 'pending' ? (_jsxs("div", { className: "mt-2 flex gap-1.5", children: [_jsx(Button, { size: "xs", onClick: () => decide(item.approvalId, 'approve'), children: "Approve" }), _jsx(Button, { size: "xs", variant: "outline", onClick: () => decide(item.approvalId, 'reject'), children: "Reject" })] })) : null] }, item.approvalId))) }));
|
|
16
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { pendingApprovals } from '../projections.js';
|
|
2
|
+
import { ApprovalsView } from './approvals-view.js';
|
|
3
|
+
import { summarizeApprovalEvent } from './summarize.js';
|
|
4
|
+
export const approvalDebugger = {
|
|
5
|
+
name: 'approval',
|
|
6
|
+
families: [
|
|
7
|
+
{ family: 'approval', color: 'oklch(0.72 0.15 45)', summarize: summarizeApprovalEvent },
|
|
8
|
+
],
|
|
9
|
+
projections: [{ name: pendingApprovals.name, component: ApprovalsView }],
|
|
10
|
+
};
|
|
11
|
+
export { ApprovalsView };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsonFields, jsonText } from '@swirls/looms/debugger';
|
|
2
|
+
export function summarizeApprovalEvent(event) {
|
|
3
|
+
const payload = jsonFields(event.payload);
|
|
4
|
+
switch (event.type) {
|
|
5
|
+
case 'approval.requested':
|
|
6
|
+
return { title: 'approval requested', detail: jsonText(payload.title) };
|
|
7
|
+
case 'approval.decided':
|
|
8
|
+
return {
|
|
9
|
+
title: `approval ${jsonText(payload.outcome) ?? 'decided'}`,
|
|
10
|
+
detail: jsonText(payload.approvalId),
|
|
11
|
+
};
|
|
12
|
+
case 'approval.timed_out':
|
|
13
|
+
return { title: 'approval timed out', detail: jsonText(payload.approvalId) };
|
|
14
|
+
default:
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
}
|
package/dist/client/client.d.ts
CHANGED
|
@@ -901,6 +901,24 @@ export declare function createLoomsClient(options?: LoomsClientOptions): {
|
|
|
901
901
|
readonly processedIdempotencyKeys: readonly string[];
|
|
902
902
|
};
|
|
903
903
|
}>;
|
|
904
|
+
listRunSummaries: () => Promise<{
|
|
905
|
+
readonly runs: readonly {
|
|
906
|
+
readonly runId: string;
|
|
907
|
+
readonly status: "cancelled" | "completed" | "failed" | "running";
|
|
908
|
+
readonly kind: string | null;
|
|
909
|
+
readonly definitionName: string | null;
|
|
910
|
+
}[];
|
|
911
|
+
}>;
|
|
912
|
+
listDefinitions: () => Promise<{
|
|
913
|
+
readonly definitions: readonly {
|
|
914
|
+
readonly kind: string;
|
|
915
|
+
readonly name: string;
|
|
916
|
+
readonly version: string;
|
|
917
|
+
readonly description?: string | undefined;
|
|
918
|
+
readonly inputSchema?: Schema.Json | undefined;
|
|
919
|
+
}[];
|
|
920
|
+
readonly projections: readonly string[];
|
|
921
|
+
}>;
|
|
904
922
|
replayTo: (runId: string, seq: number) => Promise<{
|
|
905
923
|
readonly runId: string;
|
|
906
924
|
readonly step: {
|
package/dist/client/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Data, Effect, Option, Schema, Stream } from 'effect';
|
|
2
|
-
import { createRunId, EventEnvelopeSchema, ReplayStepSchema, RunStateSchema, stringifyJson, } from '@swirls/looms/core';
|
|
2
|
+
import { createRunId, DefinitionCatalogSchema, EventEnvelopeSchema, ReplayStepSchema, RunStateSchema, RunSummariesSchema, stringifyJson, } from '@swirls/looms/core';
|
|
3
3
|
import { consumeSseStreamEffect, eventsFromSseData, sseFrames } from './sse.js';
|
|
4
4
|
class LoomsClientError extends Data.TaggedError('LoomsClientError') {
|
|
5
5
|
constructor(message, cause) {
|
|
@@ -159,6 +159,8 @@ export function createLoomsClient(options = {}) {
|
|
|
159
159
|
}),
|
|
160
160
|
wake: (runId) => request(`/runs/${encodeURIComponent(runId)}/wake`, RunResultSchema, { method: 'POST' }),
|
|
161
161
|
workerCallback,
|
|
162
|
+
listRunSummaries: () => request('/runs/summaries', RunSummariesSchema),
|
|
163
|
+
listDefinitions: () => request('/definitions', DefinitionCatalogSchema),
|
|
162
164
|
replayTo: (runId, seq) => request(`/runs/${encodeURIComponent(runId)}/replay?seq=${seq}`, ReplayResultSchema),
|
|
163
165
|
project: (runId, name) => request(`/runs/${encodeURIComponent(runId)}/projections/${encodeURIComponent(name)}`, ProjectionResultSchema),
|
|
164
166
|
subscribeEvents,
|
|
@@ -6,7 +6,7 @@ export interface DurableObjectNamespaceLike<T extends DurableObjectStubLike = Du
|
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
8
|
* Routes incoming HTTP requests to the appropriate Durable Object actor cell.
|
|
9
|
-
* Handles `/health` locally, returns 501 for global
|
|
9
|
+
* Handles `/health` locally, returns 501 for global run lists, and forwards
|
|
10
10
|
* all other run and event-stream requests to `namespace.getByName(runId)`.
|
|
11
11
|
*/
|
|
12
12
|
export declare function routeToDurableObject(namespace: DurableObjectNamespaceLike, req: Request): Promise<Response | null>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolveRunTarget, RunTargetError } from '@swirls/looms/actor';
|
|
2
2
|
/**
|
|
3
3
|
* Routes incoming HTTP requests to the appropriate Durable Object actor cell.
|
|
4
|
-
* Handles `/health` locally, returns 501 for global
|
|
4
|
+
* Handles `/health` locally, returns 501 for global run lists, and forwards
|
|
5
5
|
* all other run and event-stream requests to `namespace.getByName(runId)`.
|
|
6
6
|
*/
|
|
7
7
|
export function routeToDurableObject(namespace, req) {
|
|
@@ -9,7 +9,7 @@ export function routeToDurableObject(namespace, req) {
|
|
|
9
9
|
if (url.pathname === '/health') {
|
|
10
10
|
return Promise.resolve(Response.json({ ok: true }));
|
|
11
11
|
}
|
|
12
|
-
if (req.method === 'GET' && url.pathname === '/runs') {
|
|
12
|
+
if (req.method === 'GET' && (url.pathname === '/runs' || url.pathname === '/runs/summaries')) {
|
|
13
13
|
return Promise.resolve(Response.json({
|
|
14
14
|
error: 'Global run listing is not supported in the Durable Object backend without a global index',
|
|
15
15
|
}, { status: 501 }));
|
package/dist/core/compose.js
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** A request the runtime has matched and authorized under the debugger mount. */
|
|
2
|
+
export interface DebuggerRequest {
|
|
3
|
+
/** Mount path without a trailing slash, such as `/debugger`. */
|
|
4
|
+
readonly basePath: string;
|
|
5
|
+
/** Path below the mount: empty for the mount itself, otherwise it starts with `/`. */
|
|
6
|
+
readonly path: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Serves a debugger UI under `basePath`. The runtime matches, authorizes, and strips the mount
|
|
10
|
+
* path; the host only serves files.
|
|
11
|
+
*/
|
|
12
|
+
export interface DebuggerHost {
|
|
13
|
+
/** Absolute mount path, such as `/debugger`. Must not overlap the HTTP API. */
|
|
14
|
+
readonly basePath: string;
|
|
15
|
+
fetch(req: Request, mount: DebuggerRequest): Promise<Response | null>;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/core/index.d.ts
CHANGED
package/dist/core/index.js
CHANGED
package/dist/core/module.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export interface DefinitionRef {
|
|
|
24
24
|
readonly name: string;
|
|
25
25
|
readonly version?: string;
|
|
26
26
|
readonly input?: SchemaInput | undefined;
|
|
27
|
+
readonly description?: string | undefined;
|
|
27
28
|
}
|
|
28
29
|
export declare const DEFAULT_DEFINITION_VERSION = "v1";
|
|
29
30
|
export declare function definitionKey(kind: string, name: string, version: string): string;
|
|
@@ -33,6 +34,7 @@ export interface RegisteredDefinition {
|
|
|
33
34
|
readonly name: string;
|
|
34
35
|
readonly version: string;
|
|
35
36
|
readonly input?: SchemaInput | undefined;
|
|
37
|
+
readonly description?: string | undefined;
|
|
36
38
|
readonly value: DefinitionRef;
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Schema } from 'effect';
|
|
2
|
+
import type { RegisteredDefinition } from './module';
|
|
3
|
+
import { type RunState } from './state';
|
|
4
|
+
/** A registered definition as `GET /definitions` publishes it. */
|
|
5
|
+
export declare const PublishedDefinitionSchema: Schema.Struct<{
|
|
6
|
+
readonly kind: Schema.String;
|
|
7
|
+
readonly name: Schema.String;
|
|
8
|
+
readonly version: Schema.String;
|
|
9
|
+
readonly description: Schema.optional<Schema.String>;
|
|
10
|
+
/** JSON Schema derived from the definition's `input`. */
|
|
11
|
+
readonly inputSchema: Schema.optional<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
|
|
12
|
+
}>;
|
|
13
|
+
export type PublishedDefinition = Schema.Schema.Type<typeof PublishedDefinitionSchema>;
|
|
14
|
+
export declare const DefinitionCatalogSchema: Schema.Struct<{
|
|
15
|
+
readonly definitions: Schema.$Array<Schema.Struct<{
|
|
16
|
+
readonly kind: Schema.String;
|
|
17
|
+
readonly name: Schema.String;
|
|
18
|
+
readonly version: Schema.String;
|
|
19
|
+
readonly description: Schema.optional<Schema.String>;
|
|
20
|
+
/** JSON Schema derived from the definition's `input`. */
|
|
21
|
+
readonly inputSchema: Schema.optional<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
|
|
22
|
+
}>>;
|
|
23
|
+
readonly projections: Schema.$Array<Schema.String>;
|
|
24
|
+
}>;
|
|
25
|
+
export type DefinitionCatalog = Schema.Schema.Type<typeof DefinitionCatalogSchema>;
|
|
26
|
+
export declare function publishDefinition(definition: RegisteredDefinition): PublishedDefinition;
|
|
27
|
+
/** A run as `GET /runs/summaries` lists it. */
|
|
28
|
+
export declare const RunSummarySchema: Schema.Struct<{
|
|
29
|
+
readonly runId: Schema.String;
|
|
30
|
+
readonly status: Schema.Union<readonly [Schema.Literal<"running">, Schema.Literal<"completed">, Schema.Literal<"failed">, Schema.Literal<"cancelled">]>;
|
|
31
|
+
readonly kind: Schema.NullOr<Schema.String>;
|
|
32
|
+
readonly definitionName: Schema.NullOr<Schema.String>;
|
|
33
|
+
}>;
|
|
34
|
+
export type RunSummary = Schema.Schema.Type<typeof RunSummarySchema>;
|
|
35
|
+
export declare function summarizeRun(state: RunState): RunSummary;
|
|
36
|
+
export declare const RunSummariesSchema: Schema.Struct<{
|
|
37
|
+
readonly runs: Schema.$Array<Schema.Struct<{
|
|
38
|
+
readonly runId: Schema.String;
|
|
39
|
+
readonly status: Schema.Union<readonly [Schema.Literal<"running">, Schema.Literal<"completed">, Schema.Literal<"failed">, Schema.Literal<"cancelled">]>;
|
|
40
|
+
readonly kind: Schema.NullOr<Schema.String>;
|
|
41
|
+
readonly definitionName: Schema.NullOr<Schema.String>;
|
|
42
|
+
}>>;
|
|
43
|
+
}>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Schema } from 'effect';
|
|
2
|
+
import { JsonValueSchema } from './envelope.js';
|
|
3
|
+
import { jsonSchemaOfInput } from './schema.js';
|
|
4
|
+
import { RunStateSchema } from './state.js';
|
|
5
|
+
/** A registered definition as `GET /definitions` publishes it. */
|
|
6
|
+
export const PublishedDefinitionSchema = Schema.Struct({
|
|
7
|
+
kind: Schema.String,
|
|
8
|
+
name: Schema.String,
|
|
9
|
+
version: Schema.String,
|
|
10
|
+
description: Schema.optional(Schema.String),
|
|
11
|
+
/** JSON Schema derived from the definition's `input`. */
|
|
12
|
+
inputSchema: Schema.optional(JsonValueSchema),
|
|
13
|
+
});
|
|
14
|
+
export const DefinitionCatalogSchema = Schema.Struct({
|
|
15
|
+
definitions: Schema.Array(PublishedDefinitionSchema),
|
|
16
|
+
projections: Schema.Array(Schema.String),
|
|
17
|
+
});
|
|
18
|
+
export function publishDefinition(definition) {
|
|
19
|
+
return {
|
|
20
|
+
kind: definition.kind,
|
|
21
|
+
name: definition.name,
|
|
22
|
+
version: definition.version,
|
|
23
|
+
description: definition.description,
|
|
24
|
+
inputSchema: jsonSchemaOfInput(definition.input),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** A run as `GET /runs/summaries` lists it. */
|
|
28
|
+
export const RunSummarySchema = Schema.Struct({
|
|
29
|
+
runId: Schema.String,
|
|
30
|
+
status: RunStateSchema.fields.status,
|
|
31
|
+
kind: Schema.NullOr(Schema.String),
|
|
32
|
+
definitionName: Schema.NullOr(Schema.String),
|
|
33
|
+
});
|
|
34
|
+
export function summarizeRun(state) {
|
|
35
|
+
return {
|
|
36
|
+
runId: state.runId,
|
|
37
|
+
status: state.status,
|
|
38
|
+
kind: state.startIdentity?.kind ?? null,
|
|
39
|
+
definitionName: state.startIdentity?.definitionName ?? null,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export const RunSummariesSchema = Schema.Struct({
|
|
43
|
+
runs: Schema.Array(RunSummarySchema),
|
|
44
|
+
});
|
package/dist/core/schema.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
2
|
import { Effect, Schema } from 'effect';
|
|
3
|
-
import type
|
|
3
|
+
import { type JsonValue } from './types';
|
|
4
4
|
declare const InvalidInputError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
5
5
|
readonly _tag: "InvalidInputError";
|
|
6
6
|
} & Readonly<A>;
|
|
@@ -21,4 +21,6 @@ export declare function validateInput<TSchema extends SchemaInput>(schema: TSche
|
|
|
21
21
|
export declare function validateInput(schema: null | undefined, raw: JsonValue): Promise<JsonValue>;
|
|
22
22
|
export declare function validateInputSync<TSchema extends SchemaInput>(schema: TSchema, raw: JsonValue): InferSchemaOutput<TSchema>;
|
|
23
23
|
export declare function validateInputSync(schema: null | undefined, raw: JsonValue): JsonValue;
|
|
24
|
+
/** JSON Schema for a definition input, when the schema can describe itself. */
|
|
25
|
+
export declare function jsonSchemaOfInput(input: SchemaInput | null | undefined): JsonValue | undefined;
|
|
24
26
|
export {};
|
package/dist/core/schema.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Data, Effect, Predicate, Schema } from 'effect';
|
|
2
|
+
import { isJsonObject } from './types.js';
|
|
2
3
|
export class InvalidInputError extends Data.TaggedError('InvalidInputError') {
|
|
3
4
|
issues;
|
|
4
5
|
constructor(text, issues = []) {
|
|
@@ -73,3 +74,40 @@ export function validateInputSync(schema, raw) {
|
|
|
73
74
|
}
|
|
74
75
|
return result.value;
|
|
75
76
|
}
|
|
77
|
+
function isStandardJsonSchemaHolder(value) {
|
|
78
|
+
return '~standard' in value;
|
|
79
|
+
}
|
|
80
|
+
function jsonSchemaFromHolder(value) {
|
|
81
|
+
if (!isStandardJsonSchemaHolder(value)) {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
const input = value['~standard'].jsonSchema?.input;
|
|
85
|
+
if (!input) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const schema = input({ target: 'draft-2020-12' });
|
|
90
|
+
return isJsonObject(schema) ? schema : undefined;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** JSON Schema for a definition input, when the schema can describe itself. */
|
|
97
|
+
export function jsonSchemaOfInput(input) {
|
|
98
|
+
if (!input) {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
if (isStandardSchema(input)) {
|
|
102
|
+
return jsonSchemaFromHolder(input);
|
|
103
|
+
}
|
|
104
|
+
if (!Schema.isSchema(input)) {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
return jsonSchemaFromHolder(Schema.toStandardJSONSchemaV1(input));
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Context, Effect, Option } from 'effect';
|
|
2
2
|
import { SnapshotPayloadTooLargeError } from './limits';
|
|
3
|
+
import type { RunSummary } from './published';
|
|
3
4
|
import type { RunState } from './state';
|
|
4
5
|
import type { EventStore } from './store';
|
|
5
6
|
/**
|
|
@@ -29,6 +30,9 @@ export interface SnapshotStore {
|
|
|
29
30
|
readonly save: (snapshot: RunSnapshot) => Effect.Effect<void, SnapshotStoreError | SnapshotPayloadTooLargeError>;
|
|
30
31
|
readonly listCursors?: (runId: string) => Effect.Effect<number[], SnapshotStoreError>;
|
|
31
32
|
readonly prune?: (runId: string, keepLatest: number) => Effect.Effect<void, SnapshotStoreError>;
|
|
33
|
+
/** Upsert the list-row for a run. Written where the cursor already advanced. */
|
|
34
|
+
readonly saveHeader: (header: RunSummary) => Effect.Effect<void, SnapshotStoreError>;
|
|
35
|
+
readonly listHeaders: Effect.Effect<readonly RunSummary[], SnapshotStoreError>;
|
|
32
36
|
}
|
|
33
37
|
declare const SnapshotStoreTag_base: Context.ServiceClass<SnapshotStoreTag, "looms/SnapshotStore", SnapshotStore>;
|
|
34
38
|
export declare class SnapshotStoreTag extends SnapshotStoreTag_base {
|
|
@@ -21,6 +21,7 @@ export function snapshotStoreOf(store) {
|
|
|
21
21
|
}
|
|
22
22
|
export const makeMemorySnapshotStore = Effect.gen(function* () {
|
|
23
23
|
const snapshots = yield* Ref.make(new Map());
|
|
24
|
+
const headers = yield* Ref.make(new Map());
|
|
24
25
|
const service = {
|
|
25
26
|
loadLatest: (runId) => Effect.gen(function* () {
|
|
26
27
|
const map = yield* Ref.get(snapshots);
|
|
@@ -54,6 +55,12 @@ export const makeMemorySnapshotStore = Effect.gen(function* () {
|
|
|
54
55
|
next.set(runId, list.slice(list.length - keepLatest));
|
|
55
56
|
return next;
|
|
56
57
|
}),
|
|
58
|
+
saveHeader: (header) => Ref.update(headers, (map) => {
|
|
59
|
+
const next = new Map(map);
|
|
60
|
+
next.set(header.runId, header);
|
|
61
|
+
return next;
|
|
62
|
+
}),
|
|
63
|
+
listHeaders: Ref.get(headers).pipe(Effect.map((map) => [...map.values()])),
|
|
57
64
|
};
|
|
58
65
|
return service;
|
|
59
66
|
});
|
|
@@ -35,6 +35,13 @@ CREATE TABLE IF NOT EXISTS looms_commands (
|
|
|
35
35
|
committed_tail INTEGER NOT NULL,
|
|
36
36
|
PRIMARY KEY (run_id, idempotency_key)
|
|
37
37
|
);
|
|
38
|
+
|
|
39
|
+
CREATE TABLE IF NOT EXISTS looms_run_headers (
|
|
40
|
+
run_id TEXT PRIMARY KEY,
|
|
41
|
+
status TEXT NOT NULL,
|
|
42
|
+
kind TEXT,
|
|
43
|
+
definition_name TEXT
|
|
44
|
+
);
|
|
38
45
|
`.trim();
|
|
39
46
|
const StreamRowSchema = Schema.Struct({
|
|
40
47
|
run_id: Schema.String,
|
|
@@ -124,6 +131,21 @@ function toSnapshot(row) {
|
|
|
124
131
|
state,
|
|
125
132
|
};
|
|
126
133
|
}
|
|
134
|
+
const HeaderRowSchema = Schema.Struct({
|
|
135
|
+
run_id: Schema.String,
|
|
136
|
+
status: RunStateSchema.fields.status,
|
|
137
|
+
kind: Schema.NullOr(Schema.String),
|
|
138
|
+
definition_name: Schema.NullOr(Schema.String),
|
|
139
|
+
});
|
|
140
|
+
const decodeHeaderRow = Schema.decodeUnknownSync(HeaderRowSchema);
|
|
141
|
+
function headerFromRow(row) {
|
|
142
|
+
return {
|
|
143
|
+
runId: row.run_id,
|
|
144
|
+
status: row.status,
|
|
145
|
+
kind: row.kind,
|
|
146
|
+
definitionName: row.definition_name,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
127
149
|
function createSqliteSnapshotStore(exec) {
|
|
128
150
|
return {
|
|
129
151
|
loadLatest: (runId) => Effect.try({
|
|
@@ -175,6 +197,23 @@ function createSqliteSnapshotStore(exec) {
|
|
|
175
197
|
},
|
|
176
198
|
catch: (cause) => new SnapshotStoreError(`Failed to prune snapshots for ${runId}`, cause),
|
|
177
199
|
}),
|
|
200
|
+
saveHeader: (header) => Effect.try({
|
|
201
|
+
try: () => {
|
|
202
|
+
exec.run(`INSERT INTO looms_run_headers (run_id, status, kind, definition_name)
|
|
203
|
+
VALUES (?, ?, ?, ?)
|
|
204
|
+
ON CONFLICT (run_id) DO UPDATE SET
|
|
205
|
+
status = excluded.status,
|
|
206
|
+
kind = excluded.kind,
|
|
207
|
+
definition_name = excluded.definition_name`, [header.runId, header.status, header.kind, header.definitionName]);
|
|
208
|
+
},
|
|
209
|
+
catch: (cause) => new SnapshotStoreError(`Failed to save run header for ${header.runId}`, cause),
|
|
210
|
+
}),
|
|
211
|
+
listHeaders: Effect.try({
|
|
212
|
+
try: () => exec
|
|
213
|
+
.rows('SELECT run_id, status, kind, definition_name FROM looms_run_headers')
|
|
214
|
+
.map((row) => headerFromRow(decodeHeaderRow(row))),
|
|
215
|
+
catch: (cause) => new SnapshotStoreError('Failed to list run headers', cause),
|
|
216
|
+
}),
|
|
178
217
|
};
|
|
179
218
|
}
|
|
180
219
|
function createSqliteEventStore(exec) {
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-content:""}}}@layer theme{:root,:host{--color-black:#000;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-light:300;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--leading-relaxed:1.625;--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:ui-sans-serif, system-ui, -apple-system, sans-serif;--default-mono-font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;--color-border:var(--border)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:root{--background:oklch(16% .005 260);--foreground:oklch(93% .01 260);--card:oklch(19% .006 260);--card-foreground:oklch(93% .01 260);--primary:oklch(93% .01 260);--primary-foreground:oklch(20% .006 260);--secondary:oklch(24% .008 260);--secondary-foreground:oklch(93% .01 260);--muted:oklch(24% .008 260);--muted-foreground:oklch(68% .015 260);--accent:oklch(26% .01 260);--accent-foreground:oklch(95% .01 260);--destructive:oklch(65% .18 25);--border:oklch(100% 0 0/.1);--input:oklch(100% 0 0/.12);--ring:oklch(55% .02 260);--sidebar:oklch(18% .006 260);--sidebar-foreground:oklch(93% .01 260)}:where(.looms-debugger,.debugger-pop),:where(.looms-debugger,.debugger-pop) *,:where(.looms-debugger,.debugger-pop) :before,:where(.looms-debugger,.debugger-pop) :after{border-color:var(--color-border)}}@layer components;@layer utilities{.\@container{container-type:inline-size}.pointer-events-none{pointer-events:none}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-y-0{inset-block:0}.top-0{top:0}.top-0\.5{top:calc(var(--spacing) * .5)}.top-1\/2{top:50%}.top-2{top:calc(var(--spacing) * 2)}.right-0{right:0}.right-0\.5{right:calc(var(--spacing) * .5)}.bottom-3{bottom:calc(var(--spacing) * 3)}.left-0{left:0}.left-1\/2{left:50%}.left-2{left:calc(var(--spacing) * 2)}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.-mx-1{margin-inline:calc(var(--spacing) * -1)}.mx-2{margin-inline:calc(var(--spacing) * 2)}.my-1{margin-block:var(--spacing)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mr-1{margin-right:var(--spacing)}.mr-2{margin-right:calc(var(--spacing) * 2)}.mb-1{margin-bottom:var(--spacing)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.ml-1\.5{margin-left:calc(var(--spacing) * 1.5)}.ml-auto{margin-left:auto}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.field-sizing-content{field-sizing:content}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-2\.5{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.5)}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-full{width:100%;height:100%}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-10{height:calc(var(--spacing) * 10)}.h-11{height:calc(var(--spacing) * 11)}.h-\[26px\]{height:26px}.h-\[45\%\]{height:45%}.h-full{height:100%}.h-px{height:1px}.max-h-\(--radix-dropdown-menu-content-available-height\){max-height:var(--radix-dropdown-menu-content-available-height)}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-80{max-height:calc(var(--spacing) * 80)}.min-h-0{min-height:0}.min-h-11{min-height:calc(var(--spacing) * 11)}.min-h-16{min-height:calc(var(--spacing) * 16)}.min-h-20{min-height:calc(var(--spacing) * 20)}.min-h-28{min-height:calc(var(--spacing) * 28)}.min-h-32{min-height:calc(var(--spacing) * 32)}.min-h-40{min-height:calc(var(--spacing) * 40)}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-2\.5{width:calc(var(--spacing) * 2.5)}.w-3{width:calc(var(--spacing) * 3)}.w-7{width:calc(var(--spacing) * 7)}.w-12{width:calc(var(--spacing) * 12)}.w-14{width:calc(var(--spacing) * 14)}.w-60{width:calc(var(--spacing) * 60)}.w-72{width:calc(var(--spacing) * 72)}.w-80{width:calc(var(--spacing) * 80)}.w-\[26rem\]{width:26rem}.w-\[calc\(100\%\+0\.5rem\)\]{width:calc(100% + .5rem)}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-60{max-width:calc(var(--spacing) * 60)}.max-w-64{max-width:calc(var(--spacing) * 64)}.max-w-full{max-width:100%}.min-w-0{min-width:0}.min-w-5{min-width:calc(var(--spacing) * 5)}.min-w-40{min-width:calc(var(--spacing) * 40)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.rotate-90{rotate:90deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-default{cursor:default}.touch-none{touch-action:none}.resize-none{resize:none}.scroll-py-1{scroll-padding-block:var(--spacing)}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-rows-\[minmax\(0\,38\%\)_minmax\(0\,1fr\)\]{grid-template-rows:minmax(0,38%) minmax(0,1fr)}.flex-col{flex-direction:column}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0{gap:0}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.overscroll-contain{overscroll-behavior:contain}.rounded{border-radius:.25rem}.rounded-\[1px\]{border-radius:1px}.rounded-\[3px\]{border-radius:3px}.rounded-\[inherit\]{border-radius:inherit}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) * .8)}.rounded-sm{border-radius:calc(var(--radius) * .6)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-border,.border-border\/70{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.border-border\/70{border-color:color-mix(in oklab, var(--border) 70%, transparent)}}.border-input{border-color:var(--input)}.border-t-transparent{border-top-color:#0000}.border-l-transparent{border-left-color:#0000}.bg-accent{background-color:var(--accent)}.bg-background,.bg-background\/40{background-color:var(--background)}@supports (color:color-mix(in lab, red, red)){.bg-background\/40{background-color:color-mix(in oklab, var(--background) 40%, transparent)}}.bg-background\/60{background-color:var(--background)}@supports (color:color-mix(in lab, red, red)){.bg-background\/60{background-color:color-mix(in oklab, var(--background) 60%, transparent)}}.bg-background\/95{background-color:var(--background)}@supports (color:color-mix(in lab, red, red)){.bg-background\/95{background-color:color-mix(in oklab, var(--background) 95%, transparent)}}.bg-border{background-color:var(--border)}.bg-card,.bg-card\/60{background-color:var(--card)}@supports (color:color-mix(in lab, red, red)){.bg-card\/60{background-color:color-mix(in oklab, var(--card) 60%, transparent)}}.bg-card\/90{background-color:var(--card)}@supports (color:color-mix(in lab, red, red)){.bg-card\/90{background-color:color-mix(in oklab, var(--card) 90%, transparent)}}.bg-card\/95{background-color:var(--card)}@supports (color:color-mix(in lab, red, red)){.bg-card\/95{background-color:color-mix(in oklab, var(--card) 95%, transparent)}}.bg-current\/10{background-color:currentColor}@supports (color:color-mix(in lab, red, red)){.bg-current\/10{background-color:color-mix(in oklab, currentcolor 10%, transparent)}}.bg-foreground,.bg-foreground\/15{background-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.bg-foreground\/15{background-color:color-mix(in oklab, var(--foreground) 15%, transparent)}}.bg-foreground\/70{background-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.bg-foreground\/70{background-color:color-mix(in oklab, var(--foreground) 70%, transparent)}}.bg-primary{background-color:var(--primary)}.bg-secondary,.bg-secondary\/70{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.bg-secondary\/70{background-color:color-mix(in oklab, var(--secondary) 70%, transparent)}}.bg-sidebar{background-color:var(--sidebar)}.bg-status-cancelled{background-color:var(--status-cancelled)}.bg-status-completed{background-color:var(--status-completed)}.bg-status-failed,.bg-status-failed\/10{background-color:var(--status-failed)}@supports (color:color-mix(in lab, red, red)){.bg-status-failed\/10{background-color:color-mix(in oklab, var(--status-failed) 10%, transparent)}}.bg-status-running{background-color:var(--status-running)}.bg-status-waiting{background-color:var(--status-waiting)}.bg-transparent{background-color:#0000}.p-0{padding:0}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1{padding:var(--spacing)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.p-px{padding:1px}.px-0\.5{padding-inline:calc(var(--spacing) * .5)}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-px{padding-block:1px}.pt-0\.5{padding-top:calc(var(--spacing) * .5)}.pt-1\.5{padding-top:calc(var(--spacing) * 1.5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-2\.5{padding-top:calc(var(--spacing) * 2.5)}.pr-0\.5{padding-right:calc(var(--spacing) * .5)}.pr-1{padding-right:var(--spacing)}.pr-1\.5{padding-right:calc(var(--spacing) * 1.5)}.pr-2{padding-right:calc(var(--spacing) * 2)}.pb-1{padding-bottom:var(--spacing)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-0{padding-left:0}.pl-1{padding-left:var(--spacing)}.pl-1\.5{padding-left:calc(var(--spacing) * 1.5)}.pl-2\.5{padding-left:calc(var(--spacing) * 2.5)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-4{padding-left:calc(var(--spacing) * 4)}.pl-7{padding-left:calc(var(--spacing) * 7)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.align-\[-2px\]{vertical-align:-2px}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.font-sans{font-family:ui-sans-serif,system-ui,-apple-system,sans-serif}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.leading-3\.5{--tw-leading:calc(var(--spacing) * 3.5);line-height:calc(var(--spacing) * 3.5)}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-light{--tw-font-weight:var(--font-weight-light);font-weight:var(--font-weight-light)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.break-words{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-background{color:var(--background)}.text-border{color:var(--border)}.text-card-foreground{color:var(--card-foreground)}.text-foreground{color:var(--foreground)}.text-json-boolean{color:var(--json-boolean)}.text-json-key{color:var(--json-key)}.text-json-null{color:var(--json-null)}.text-json-number{color:var(--json-number)}.text-json-string{color:var(--json-string)}.text-muted-foreground,.text-muted-foreground\/60{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\/60{color:color-mix(in oklab, var(--muted-foreground) 60%, transparent)}}.text-muted-foreground\/70{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\/70{color:color-mix(in oklab, var(--muted-foreground) 70%, transparent)}}.text-muted-foreground\/80{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\/80{color:color-mix(in oklab, var(--muted-foreground) 80%, transparent)}}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-status-cancelled{color:var(--status-cancelled)}.text-status-completed{color:var(--status-completed)}.text-status-failed{color:var(--status-failed)}.text-status-running{color:var(--status-running)}.text-status-waiting{color:var(--status-waiting)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-black\/30{--tw-shadow-color:#0000004d}@supports (color:color-mix(in lab, red, red)){.shadow-black\/30{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-black) 30%, transparent) var(--tw-shadow-alpha), transparent)}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition-\[border-color\,box-shadow\]{transition-property:border-color,box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[transform\,background-color\,color\,opacity\]{transition-property:transform,background-color,color,opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}.duration-150{--tw-duration:.15s;transition-duration:.15s}.ease-snappy{--tw-ease:var(--debugger-ease);transition-timing-function:var(--debugger-ease)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.group-hover\/branch\:text-foreground:is(:where(.group\/branch):hover *){color:var(--foreground)}.group-hover\/json\:opacity-100:is(:where(.group\/json):hover *){opacity:1}}.placeholder\:text-muted-foreground::placeholder{color:var(--muted-foreground)}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:inset-y-0:after{content:var(--tw-content);inset-block:0}.after\:left-1\/2:after{content:var(--tw-content);left:50%}.after\:w-2:after{content:var(--tw-content);width:calc(var(--spacing) * 2)}.after\:-translate-x-1\/2:after{content:var(--tw-content);--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.focus-within\:border-ring\/70:focus-within{border-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-within\:border-ring\/70:focus-within{border-color:color-mix(in oklab, var(--ring) 70%, transparent)}}.focus-within\:ring-\[3px\]:focus-within{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-within\:ring-ring\/25:focus-within{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-within\:ring-ring\/25:focus-within{--tw-ring-color:color-mix(in oklab, var(--ring) 25%, transparent)}}@media (hover:hover){.hover\:border-ring\/40:hover{border-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.hover\:border-ring\/40:hover{border-color:color-mix(in oklab, var(--ring) 40%, transparent)}}.hover\:bg-accent:hover,.hover\:bg-accent\/40:hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-accent\/40:hover{background-color:color-mix(in oklab, var(--accent) 40%, transparent)}}.hover\:bg-accent\/50:hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-accent\/50:hover{background-color:color-mix(in oklab, var(--accent) 50%, transparent)}}.hover\:bg-accent\/60:hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-accent\/60:hover{background-color:color-mix(in oklab, var(--accent) 60%, transparent)}}.hover\:bg-background\/40:hover{background-color:var(--background)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-background\/40:hover{background-color:color-mix(in oklab, var(--background) 40%, transparent)}}.hover\:bg-background\/60:hover{background-color:var(--background)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-background\/60:hover{background-color:color-mix(in oklab, var(--background) 60%, transparent)}}.hover\:bg-foreground\/25:hover{background-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-foreground\/25:hover{background-color:color-mix(in oklab, var(--foreground) 25%, transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--primary) 90%, transparent)}}.hover\:bg-status-failed\/15:hover{background-color:var(--status-failed)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-status-failed\/15:hover{background-color:color-mix(in oklab, var(--status-failed) 15%, transparent)}}.hover\:text-accent-foreground:hover{color:var(--accent-foreground)}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:text-status-failed:hover{color:var(--status-failed)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:bg-accent:focus{background-color:var(--accent)}.focus\:text-accent-foreground:focus{color:var(--accent-foreground)}.focus-visible\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\:opacity-100:focus-visible{opacity:1}.focus-visible\:ring-\[3px\]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.active\:scale-\[0\.97\]:active{scale:.97}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.aria-pressed\:bg-accent[aria-pressed=true]{background-color:var(--accent)}.aria-pressed\:text-foreground[aria-pressed=true]{color:var(--foreground)}.aria-\[orientation\=vertical\]\:flex-col[aria-orientation=vertical]{flex-direction:column}.data-disabled\:pointer-events-none[data-disabled]{pointer-events:none}.data-disabled\:opacity-50[data-disabled]{opacity:.5}.data-\[disabled\=true\]\:pointer-events-none[data-disabled=true]{pointer-events:none}.data-\[disabled\=true\]\:opacity-50[data-disabled=true]{opacity:.5}.data-\[selected\=true\]\:bg-accent[data-selected=true]{background-color:var(--accent)}.data-\[selected\=true\]\:text-accent-foreground[data-selected=true]{color:var(--accent-foreground)}.data-\[separator\=active\]\:bg-ring[data-separator=active],.data-\[separator\=focus\]\:bg-ring[data-separator=focus],.data-\[separator\=hover\]\:bg-ring\/60[data-separator=hover]{background-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.data-\[separator\=hover\]\:bg-ring\/60[data-separator=hover]{background-color:color-mix(in oklab, var(--ring) 60%, transparent)}}.data-\[state\=active\]\:bg-background[data-state=active]{background-color:var(--background)}.data-\[state\=active\]\:text-foreground[data-state=active]{color:var(--foreground)}.data-\[state\=active\]\:shadow-sm[data-state=active]{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.data-\[state\=checked\]\:bg-foreground[data-state=checked]{background-color:var(--foreground)}.data-\[state\=checked\]\:text-background[data-state=checked]{color:var(--background)}.data-\[state\=hidden\]\:opacity-0[data-state=hidden]{opacity:0}.data-\[state\=open\]\:border-ring\/60[data-state=open]{border-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.data-\[state\=open\]\:border-ring\/60[data-state=open]{border-color:color-mix(in oklab, var(--ring) 60%, transparent)}}.data-\[state\=open\]\:bg-accent[data-state=open]{background-color:var(--accent)}.data-\[state\=open\]\:text-foreground[data-state=open]{color:var(--foreground)}@media (width>=36rem){.min-\[36rem\]\:grid-cols-\[14rem_minmax\(0\,1fr\)\]{grid-template-columns:14rem minmax(0,1fr)}.min-\[36rem\]\:border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.min-\[36rem\]\:border-b-0{border-bottom-style:var(--tw-border-style);border-bottom-width:0}}@container (width>=24rem){.\@sm\:ml-0{margin-left:0}.\@sm\:flex{display:flex}}@container (width>=28rem){.\@md\:flex{display:flex}.\@md\:max-w-64{max-width:calc(var(--spacing) * 64)}}@container (width>=32rem){.\@lg\:inline{display:inline}}.\[\&_\[cmdk-group-heading\]\]\:px-2 [cmdk-group-heading]{padding-inline:calc(var(--spacing) * 2)}.\[\&_\[cmdk-group-heading\]\]\:pt-2 [cmdk-group-heading]{padding-top:calc(var(--spacing) * 2)}.\[\&_\[cmdk-group-heading\]\]\:pb-1 [cmdk-group-heading]{padding-bottom:var(--spacing)}.\[\&_\[cmdk-group-heading\]\]\:text-\[11px\] [cmdk-group-heading]{font-size:11px}.\[\&_\[cmdk-group-heading\]\]\:font-medium [cmdk-group-heading]{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.\[\&_\[cmdk-group-heading\]\]\:text-muted-foreground [cmdk-group-heading]{color:var(--muted-foreground)}.\[\&_svg\]\:size-3 svg{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.\[\&_svg\]\:size-3\.5 svg{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.\[\&_svg\]\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&\>div\]\:block\!>div{display:block!important}}:root{--debugger-ease:cubic-bezier(.23, 1, .32, 1);--status-running:oklch(74% .12 240);--status-waiting:oklch(80% .14 85);--status-completed:oklch(76% .13 155);--status-failed:oklch(68% .18 25);--status-cancelled:oklch(62% .01 260);--json-key:oklch(80% .06 280);--json-string:oklch(80% .1 150);--json-number:oklch(80% .1 230);--json-boolean:oklch(82% .11 70);--json-null:oklch(60% .01 260)}@keyframes debugger-pop-in{0%{opacity:0;transform:scale(.97)}}@keyframes debugger-fade-in{0%{opacity:0}}.debugger-pop{transform-origin:var(--radix-popper-transform-origin);animation:debugger-pop-in .15s var(--debugger-ease)}.debugger-pop[data-instant]{animation:none}.debugger-float-in{transition:opacity .15s var(--debugger-ease), transform .15s var(--debugger-ease), scale .15s var(--debugger-ease), background-color .15s var(--debugger-ease)}@starting-style{.debugger-float-in{opacity:0;transform:translateY(4px)}}@media (prefers-reduced-motion:reduce){.debugger-pop{animation-name:debugger-fade-in}.debugger-float-in{transition-property:opacity}}.debugger-event-stream{container-type:inline-size}.debugger-event-offset,.debugger-event-causation,.debugger-event-thread{display:none}@container (width>=24rem){.debugger-event-offset{display:inline}}@container (width>=34rem){.debugger-event-thread{display:inline}}@container (width>=44rem){.debugger-event-causation{display:inline}}:root{--radius:.375rem}html,body,#root{height:100%}html,body{overscroll-behavior:none}body{margin:0}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}
|