@sigrun/sigrun 0.1.4 → 0.1.6
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 +61 -0
- package/README.md +24 -2
- package/THIRD_PARTY_NOTICES.md +23 -0
- package/dist/blocks/builders.js +125 -0
- package/dist/blocks/images.js +57 -0
- package/dist/blocks/index.js +20 -0
- package/dist/blocks/limits.js +26 -0
- package/dist/blocks/placements.js +99 -0
- package/dist/blocks/schema.js +559 -0
- package/dist/blocks/validate.js +602 -0
- package/dist/config.js +31 -0
- package/dist/extension.d.ts +476 -9
- package/dist/harness/agent-env.js +62 -0
- package/dist/harness/boot.js +8 -1
- package/dist/harness/event-bus.js +33 -0
- package/dist/harness/identity/users.js +3 -2
- package/dist/harness/loader.js +369 -13
- package/dist/harness/packages.js +71 -2
- package/dist/harness/seam-host.js +69 -2
- package/dist/harness/settings.js +5 -0
- package/dist/harness/workspace.js +6 -4
- package/dist/jobs/fire.js +11 -0
- package/dist/jobs/spec.js +19 -0
- package/dist/serve.js +29 -39
- package/dist/server/auth/pipeline.js +16 -1
- package/dist/server/conversation-ops.js +482 -10
- package/dist/server/gateway.js +122 -0
- package/dist/server/helpers.js +26 -0
- package/dist/server/host-bridge.js +141 -4
- package/dist/server/index.js +27 -0
- package/dist/server/notifications.js +6 -2
- package/dist/server/routes/conversations.js +37 -93
- package/dist/server/routes/events.js +39 -0
- package/dist/server/routes/ext-assets.js +84 -0
- package/dist/server/routes/extensions.js +31 -1
- package/dist/server/routes/files.js +38 -83
- package/dist/server/routes/meta.js +35 -1
- package/dist/server/routes/providers.js +5 -21
- package/dist/server/routes/submissions.js +36 -111
- package/dist/server/routes/surfaces.js +387 -0
- package/dist/server/routes/users.js +6 -1
- package/dist/server/session-meta.js +12 -6
- package/dist/server/shutdown.js +85 -0
- package/dist/server/surfaces/access-cache.js +43 -0
- package/dist/server/surfaces/dedup.js +67 -0
- package/dist/server/surfaces/instance.js +42 -0
- package/dist/server/surfaces/mime.js +73 -0
- package/dist/server/surfaces/rate-limit.js +63 -0
- package/dist/server/surfaces/service.js +493 -0
- package/dist/server/surfaces/watchers.js +94 -0
- package/node_modules/@sigrun/shared/CHANGELOG.md +9 -0
- package/node_modules/@sigrun/shared/dist/blocks/format.d.ts +28 -0
- package/node_modules/@sigrun/shared/dist/blocks/format.js +199 -0
- package/node_modules/@sigrun/shared/dist/blocks/icons.d.ts +12 -0
- package/node_modules/@sigrun/shared/dist/blocks/icons.js +64 -0
- package/node_modules/@sigrun/shared/dist/blocks/index.d.ts +25 -0
- package/node_modules/@sigrun/shared/dist/blocks/index.js +21 -0
- package/node_modules/@sigrun/shared/dist/blocks/instance.d.ts +29 -0
- package/node_modules/@sigrun/shared/dist/blocks/instance.js +51 -0
- package/node_modules/@sigrun/shared/dist/blocks/lttb.d.ts +16 -0
- package/node_modules/@sigrun/shared/dist/blocks/lttb.js +67 -0
- package/node_modules/@sigrun/shared/dist/blocks/ops.d.ts +44 -0
- package/node_modules/@sigrun/shared/dist/blocks/ops.js +294 -0
- package/node_modules/@sigrun/shared/dist/blocks/text.d.ts +43 -0
- package/node_modules/@sigrun/shared/dist/blocks/text.js +790 -0
- package/node_modules/@sigrun/shared/dist/blocks/transport.d.ts +77 -0
- package/node_modules/@sigrun/shared/dist/blocks/transport.js +11 -0
- package/node_modules/@sigrun/shared/dist/blocks/types.d.ts +541 -0
- package/node_modules/@sigrun/shared/dist/blocks/types.js +17 -0
- package/node_modules/@sigrun/shared/dist/jobs.d.ts +9 -0
- package/node_modules/@sigrun/shared/dist/live.d.ts +71 -0
- package/node_modules/@sigrun/shared/dist/live.js +82 -0
- package/node_modules/@sigrun/shared/dist/session-meta.d.ts +19 -3
- package/node_modules/@sigrun/shared/dist/settings.d.ts +7 -0
- package/node_modules/@sigrun/shared/dist/views.d.ts +81 -3
- package/node_modules/@sigrun/shared/package.json +10 -2
- package/package.json +11 -5
- package/webui/dist/assets/index-CiYInlLx.css +1 -0
- package/webui/dist/assets/index-JDfOQV9z.js +52 -0
- package/webui/dist/index.html +2 -2
- package/webui/dist/assets/index-BiSMljer.css +0 -1
- package/webui/dist/assets/index-hVLvsizV.js +0 -50
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `docs["pi.live"]` LiveState narrowing (gateway plan 1, Task 1).
|
|
3
|
+
*
|
|
4
|
+
* `pi.live` is the harness's live-run document — `run` while a generation
|
|
5
|
+
* is in flight, `generation.message` (the committed throttled partial of
|
|
6
|
+
* the response), `tools` (live tool slots), `compactions`, and
|
|
7
|
+
* `compactionFailure` (shape per pi-durable dist/harness/live.d.ts).
|
|
8
|
+
* `ConversationViewBase` types `docs` values as `JsonObject`: named
|
|
9
|
+
* LiveDocs are narrowed by their consumers, and this module is that
|
|
10
|
+
* narrowing for `pi.live` — shared by the webui, the tui and the gateway
|
|
11
|
+
* engine so every reader narrows the doc identically.
|
|
12
|
+
*
|
|
13
|
+
* Purity: a shared wire module — `import type` sibling-only (the purity
|
|
14
|
+
* guard in test/views-purity.test.ts); the runtime functions below are
|
|
15
|
+
* dependency-free so both clients (DOM-only webui, NodeNext tui) and the
|
|
16
|
+
* server read the same doc the same way.
|
|
17
|
+
*/
|
|
18
|
+
import type { ConversationViewBase } from "./views.js";
|
|
19
|
+
/** One live tool slot of `docs["pi.live"]` (the LiveState tools list). */
|
|
20
|
+
export interface LiveToolSlotWire {
|
|
21
|
+
readonly callId: string;
|
|
22
|
+
readonly name: string;
|
|
23
|
+
readonly status: string;
|
|
24
|
+
readonly output?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The `docs["pi.live"]` LiveState doc, narrowed to what the channels read:
|
|
28
|
+
* `run` (present exactly while busy — the steer field derives from it
|
|
29
|
+
* server-side), `generation.message` (the committed throttled partial of
|
|
30
|
+
* the in-flight response), `tools` (live tool slots), `compactions` (live
|
|
31
|
+
* compaction tasks), `compactionFailure` (the newest failure — a
|
|
32
|
+
* completed compaction clears it; nothing-to-compact or a fault leaves
|
|
33
|
+
* it).
|
|
34
|
+
*/
|
|
35
|
+
export interface LiveDocWire {
|
|
36
|
+
readonly run?: unknown;
|
|
37
|
+
readonly generation?: {
|
|
38
|
+
readonly message?: unknown;
|
|
39
|
+
};
|
|
40
|
+
readonly tools?: readonly LiveToolSlotWire[];
|
|
41
|
+
readonly compactions?: readonly unknown[];
|
|
42
|
+
readonly compactionFailure?: {
|
|
43
|
+
readonly error?: unknown;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The view's `pi.live` doc, or undefined when absent (idle and never-run
|
|
48
|
+
* conversations carry no doc). A cast, not a validation: the shape is
|
|
49
|
+
* pinned by the harness writer and the fail-soft reads below absorb
|
|
50
|
+
* drift.
|
|
51
|
+
*/
|
|
52
|
+
export declare function liveDoc(view: ConversationViewBase): LiveDocWire | undefined;
|
|
53
|
+
/** The live tool slots of the view's `pi.live` doc (empty when absent). */
|
|
54
|
+
export declare function liveToolSlots(view: ConversationViewBase): readonly LiveToolSlotWire[];
|
|
55
|
+
/**
|
|
56
|
+
* The in-flight generation's committed partial message, or undefined when
|
|
57
|
+
* idle (or the doc shape is unexpected — fail soft to absent; upstream
|
|
58
|
+
* drift surfaces in the schema fixture first).
|
|
59
|
+
*/
|
|
60
|
+
export declare function liveGenerationPartial(view: ConversationViewBase): object | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* The in-flight generation's visible text: the partial's text blocks
|
|
63
|
+
* (`{type: "text"}`) joined with `""` — thinking and tool-call blocks
|
|
64
|
+
* contribute nothing. `""` when idle or the content is not an array; a
|
|
65
|
+
* string `content` returns as-is.
|
|
66
|
+
*/
|
|
67
|
+
export declare function liveGenerationText(view: ConversationViewBase): string;
|
|
68
|
+
/** How many compaction tasks are live right now (0 = none). */
|
|
69
|
+
export declare function liveCompactions(view: ConversationViewBase): number;
|
|
70
|
+
/** The newest compaction failure's error text, when one is surfaced. */
|
|
71
|
+
export declare function liveCompactionFailure(view: ConversationViewBase): string | undefined;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `docs["pi.live"]` LiveState narrowing (gateway plan 1, Task 1).
|
|
3
|
+
*
|
|
4
|
+
* `pi.live` is the harness's live-run document — `run` while a generation
|
|
5
|
+
* is in flight, `generation.message` (the committed throttled partial of
|
|
6
|
+
* the response), `tools` (live tool slots), `compactions`, and
|
|
7
|
+
* `compactionFailure` (shape per pi-durable dist/harness/live.d.ts).
|
|
8
|
+
* `ConversationViewBase` types `docs` values as `JsonObject`: named
|
|
9
|
+
* LiveDocs are narrowed by their consumers, and this module is that
|
|
10
|
+
* narrowing for `pi.live` — shared by the webui, the tui and the gateway
|
|
11
|
+
* engine so every reader narrows the doc identically.
|
|
12
|
+
*
|
|
13
|
+
* Purity: a shared wire module — `import type` sibling-only (the purity
|
|
14
|
+
* guard in test/views-purity.test.ts); the runtime functions below are
|
|
15
|
+
* dependency-free so both clients (DOM-only webui, NodeNext tui) and the
|
|
16
|
+
* server read the same doc the same way.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* The view's `pi.live` doc, or undefined when absent (idle and never-run
|
|
20
|
+
* conversations carry no doc). A cast, not a validation: the shape is
|
|
21
|
+
* pinned by the harness writer and the fail-soft reads below absorb
|
|
22
|
+
* drift.
|
|
23
|
+
*/
|
|
24
|
+
export function liveDoc(view) {
|
|
25
|
+
// SAFETY: `docs` values are `JsonObject` by wire contract; `pi.live` is
|
|
26
|
+
// the harness's own LiveState document. The cast narrows the wire type,
|
|
27
|
+
// it does not validate — every reader below is fail-soft against drift.
|
|
28
|
+
return view.docs["pi.live"];
|
|
29
|
+
}
|
|
30
|
+
/** The live tool slots of the view's `pi.live` doc (empty when absent). */
|
|
31
|
+
export function liveToolSlots(view) {
|
|
32
|
+
return liveDoc(view)?.tools ?? [];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The in-flight generation's committed partial message, or undefined when
|
|
36
|
+
* idle (or the doc shape is unexpected — fail soft to absent; upstream
|
|
37
|
+
* drift surfaces in the schema fixture first).
|
|
38
|
+
*/
|
|
39
|
+
export function liveGenerationPartial(view) {
|
|
40
|
+
const message = liveDoc(view)?.generation?.message;
|
|
41
|
+
if (typeof message !== "object" || message === null)
|
|
42
|
+
return undefined;
|
|
43
|
+
return message;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The in-flight generation's visible text: the partial's text blocks
|
|
47
|
+
* (`{type: "text"}`) joined with `""` — thinking and tool-call blocks
|
|
48
|
+
* contribute nothing. `""` when idle or the content is not an array; a
|
|
49
|
+
* string `content` returns as-is.
|
|
50
|
+
*/
|
|
51
|
+
export function liveGenerationText(view) {
|
|
52
|
+
const partial = liveGenerationPartial(view);
|
|
53
|
+
if (partial === undefined)
|
|
54
|
+
return "";
|
|
55
|
+
const content = partial.content;
|
|
56
|
+
if (typeof content === "string")
|
|
57
|
+
return content;
|
|
58
|
+
if (!Array.isArray(content))
|
|
59
|
+
return "";
|
|
60
|
+
let text = "";
|
|
61
|
+
for (const block of content) {
|
|
62
|
+
if (typeof block !== "object" || block === null)
|
|
63
|
+
continue;
|
|
64
|
+
const typed = block;
|
|
65
|
+
if (typed.type !== "text" || typeof typed.text !== "string")
|
|
66
|
+
continue;
|
|
67
|
+
text += typed.text;
|
|
68
|
+
}
|
|
69
|
+
return text;
|
|
70
|
+
}
|
|
71
|
+
/** How many compaction tasks are live right now (0 = none). */
|
|
72
|
+
export function liveCompactions(view) {
|
|
73
|
+
return liveDoc(view)?.compactions?.length ?? 0;
|
|
74
|
+
}
|
|
75
|
+
/** The newest compaction failure's error text, when one is surfaced. */
|
|
76
|
+
export function liveCompactionFailure(view) {
|
|
77
|
+
const failure = liveDoc(view)?.compactionFailure;
|
|
78
|
+
if (typeof failure !== "object" || failure === null)
|
|
79
|
+
return undefined;
|
|
80
|
+
const error = failure.error;
|
|
81
|
+
return typeof error === "string" && error !== "" ? error : undefined;
|
|
82
|
+
}
|
|
@@ -25,9 +25,10 @@ export type { Sharing } from "./access.js";
|
|
|
25
25
|
* `invalid_field`.
|
|
26
26
|
*
|
|
27
27
|
* Server-owned fields (`autoName`, `autoNameAttempts`,
|
|
28
|
-
* `lastActivityAt`) are written by host code only
|
|
29
|
-
* auto-namer); they are NOT
|
|
30
|
-
* rejecting them as
|
|
28
|
+
* `lastActivityAt`, `jobId`, `deliver`) are written by host code only
|
|
29
|
+
* (activity.ts, the A2 auto-namer, fire.ts's job stamp); they are NOT
|
|
30
|
+
* patch surface — the strict validator keeps rejecting them as
|
|
31
|
+
* `invalid_field`.
|
|
31
32
|
*/
|
|
32
33
|
/** The per-conversation session metadata (spec §5). */
|
|
33
34
|
export type SessionMeta = {
|
|
@@ -69,6 +70,21 @@ export type SessionMeta = {
|
|
|
69
70
|
* patchable — the strict validator rejects the key as `invalid_field`.
|
|
70
71
|
*/
|
|
71
72
|
lastActivityAt?: string;
|
|
73
|
+
/**
|
|
74
|
+
* Server-owned job stamp (gateway C7, spec §8.0): the id of the job
|
|
75
|
+
* whose fire created this conversation (`fire.ts` writes it inside the
|
|
76
|
+
* creating commit). Never patchable — the strict validator rejects
|
|
77
|
+
* the key as `invalid_field`.
|
|
78
|
+
*/
|
|
79
|
+
jobId?: string;
|
|
80
|
+
/**
|
|
81
|
+
* Server-owned job delivery targets (gateway C7, spec §8.0): the job
|
|
82
|
+
* action's `deliver` array, stamped onto the run conversation by
|
|
83
|
+
* `fire.ts` in the creating commit — the gateway's runSettled delivery
|
|
84
|
+
* reads it to route the answer to chats. Never patchable — the
|
|
85
|
+
* strict validator rejects the key as `invalid_field`.
|
|
86
|
+
*/
|
|
87
|
+
deliver?: string[];
|
|
72
88
|
/**
|
|
73
89
|
* The §5.9 per-resource sharing state; absent = private (owner and
|
|
74
90
|
* superuser only). Patchable by the OWNER or a superuser (403
|
|
@@ -195,6 +195,13 @@ export interface ServerSettings {
|
|
|
195
195
|
readonly metrics?: {
|
|
196
196
|
readonly public?: boolean;
|
|
197
197
|
};
|
|
198
|
+
/**
|
|
199
|
+
* The development flag (spec §14.2/§14.4): `SIGRUN_DEV` (strict
|
|
200
|
+
* true/false — the spec's `SIGRUN_DEV=1` form reads as true) over this
|
|
201
|
+
* key, default `false`. Surfaces on `GET /v1/meta` (`dev`); gates the
|
|
202
|
+
* U1 blocks gallery, U3's development error bodies, and U4.
|
|
203
|
+
*/
|
|
204
|
+
readonly dev?: boolean;
|
|
198
205
|
/**
|
|
199
206
|
* The backup target — exactly one of the two shapes (mirroring the
|
|
200
207
|
* env rule: `SIGRUN_BACKUP_PATH` XOR `SIGRUN_BACKUP_S3_BUCKET`), plus
|
|
@@ -402,6 +402,14 @@ export interface MetaResponse {
|
|
|
402
402
|
* worker's first run.
|
|
403
403
|
*/
|
|
404
404
|
readonly workers?: readonly WorkerStatus[];
|
|
405
|
+
/**
|
|
406
|
+
* The declared surfaces (UI-blocks U3 Task 5): the flattened
|
|
407
|
+
* view + panel rows the channels register their rail/panel
|
|
408
|
+
* entries from. Absent when the extension declared none. The
|
|
409
|
+
* meta response carries the DECLARATION (id/title/icon/
|
|
410
|
+
* placement); access filtering is render-time (§6.5).
|
|
411
|
+
*/
|
|
412
|
+
readonly surfaces?: readonly ExtensionSurfaceInfo[];
|
|
405
413
|
}[];
|
|
406
414
|
/**
|
|
407
415
|
* §5 health: pure aggregation over boot-retained §3 producers (spec
|
|
@@ -424,8 +432,15 @@ export interface MetaResponse {
|
|
|
424
432
|
readonly memory: HealthStatus;
|
|
425
433
|
/** Any contributor's §3 producer degraded → "degraded"; empty → "ok". */
|
|
426
434
|
readonly providers: HealthStatus;
|
|
435
|
+
/**
|
|
436
|
+
* The gateway engine's health (gateway C2): present ONLY when an
|
|
437
|
+
* engine loaded (a no-engine deploy reports NO gateway health —
|
|
438
|
+
* degenerate "ok" by absence, never a synthesized field); the
|
|
439
|
+
* wrapped engine health (a throwing `health()` reads "degraded";
|
|
440
|
+
* a rejected `start` latches degraded until restart).
|
|
441
|
+
*/
|
|
442
|
+
readonly gateway?: HealthStatus;
|
|
427
443
|
};
|
|
428
|
-
/**
|
|
429
444
|
/**
|
|
430
445
|
* The auth block (core hardening W1 Task 6, spec §5.7): the effective
|
|
431
446
|
* authenticator list (`ctx.methods` — loopback-derived or explicit) and
|
|
@@ -450,6 +465,13 @@ export interface MetaResponse {
|
|
|
450
465
|
readonly backup: boolean;
|
|
451
466
|
readonly channels: readonly string[];
|
|
452
467
|
};
|
|
468
|
+
/**
|
|
469
|
+
* The development flag (spec §14.2/§14.4): `server.dev` / `SIGRUN_DEV`,
|
|
470
|
+
* default `false`. Gates the U1 blocks gallery, U3's development
|
|
471
|
+
* error bodies (validation errors in `surface_failed` responses) and
|
|
472
|
+
* U4 — a boot constant, like the rest of meta.
|
|
473
|
+
*/
|
|
474
|
+
readonly dev: boolean;
|
|
453
475
|
/**
|
|
454
476
|
* The seam inventory (docs/approval-ux-seams.md): per extension, the
|
|
455
477
|
* interaction kinds / ambient surface keys its factory declared.
|
|
@@ -575,6 +597,23 @@ export interface ExtensionInfo {
|
|
|
575
597
|
readonly workers: readonly WorkerStatus[];
|
|
576
598
|
/** The declared HTTP routes, one `{method, path, auth}` each (W5 Task 2). */
|
|
577
599
|
routes?: readonly ExtensionRouteInfo[];
|
|
600
|
+
/** The declared surfaces, one `{id, title, icon, placement}` each (U3 Task 1); absent when none. */
|
|
601
|
+
surfaces?: readonly ExtensionSurfaceInfo[];
|
|
602
|
+
/**
|
|
603
|
+
* The channel ids this extension contributes (gateway C1, spec §7):
|
|
604
|
+
* present only on rows of extensions whose factory result carried
|
|
605
|
+
* `channels`; unique across every loaded extension (a collision
|
|
606
|
+
* quarantines the later loader). Absent when the extension declared
|
|
607
|
+
* none.
|
|
608
|
+
*/
|
|
609
|
+
readonly channels?: readonly string[];
|
|
610
|
+
/**
|
|
611
|
+
* The inert marker (gateway C2): `"no gateway"` on rows of
|
|
612
|
+
* extensions that contributed `channels` while NO gateway engine
|
|
613
|
+
* loaded — their adapters are inert (nothing drives them; one boot
|
|
614
|
+
* warning says so). Absent everywhere else.
|
|
615
|
+
*/
|
|
616
|
+
readonly inert?: "no gateway";
|
|
578
617
|
/**
|
|
579
618
|
* Built-in extensions (Task 2, pi parity): `true` marks a core-shipped
|
|
580
619
|
* built-in (codemode / MCP / tool search); ABSENT on configured
|
|
@@ -593,6 +632,26 @@ export interface ExtensionRouteInfo {
|
|
|
593
632
|
readonly path: string;
|
|
594
633
|
readonly auth: string;
|
|
595
634
|
}
|
|
635
|
+
/**
|
|
636
|
+
* One `GET /v1/extensions` surface row (UI-blocks U3 Task 1, spec
|
|
637
|
+
* §7.1): the extension-declared views and panels — what the channels'
|
|
638
|
+
* rail (views) and right panel (panels) register from. One row per
|
|
639
|
+
* declared surface, in declaration order (views before panels).
|
|
640
|
+
*/
|
|
641
|
+
export interface ExtensionSurfaceInfo {
|
|
642
|
+
readonly id: string;
|
|
643
|
+
readonly title: string;
|
|
644
|
+
readonly icon: string;
|
|
645
|
+
/** The declared placement; `settings` sections (§13.3) are not in this workstream. */
|
|
646
|
+
readonly placement: "view" | "panel";
|
|
647
|
+
/** The declared refresh cadence (spec §7.1); channels refetch data on
|
|
648
|
+
* this interval while the surface is visible. Absent → no cadence. */
|
|
649
|
+
readonly refreshMs?: number;
|
|
650
|
+
/** §7.3 shared-data flag: a sharedData surface's `since` fetches may
|
|
651
|
+
* answer with `ops` and NO `data` — channels fall back to a full
|
|
652
|
+
* fetch (ops folding is U1). Absent → per-instance data. */
|
|
653
|
+
readonly sharedData?: boolean;
|
|
654
|
+
}
|
|
596
655
|
/** The `GET /v1/extensions` payload (spec §7.7). */
|
|
597
656
|
export interface ExtensionsResponse {
|
|
598
657
|
readonly extensions: readonly ExtensionInfo[];
|
|
@@ -616,7 +675,11 @@ export type { SessionMeta, SessionMetaPatch } from "./session-meta.js";
|
|
|
616
675
|
* The `GET /v1/auth/whoami` payload (core hardening W1 Task 3, spec
|
|
617
676
|
* §5.8): the resolved principal, verbatim. `user` is absent only under
|
|
618
677
|
* the naive empty-method path with no `X-Sigrun-User` header;
|
|
619
|
-
* `service` marks the env service token.
|
|
678
|
+
* `service` marks the env service token. `method` mirrors the extension
|
|
679
|
+
* contract's `Principal.method` (gateway C4b added `"host"` — an
|
|
680
|
+
* in-process host-built principal; no HTTP route ever resolves one, but
|
|
681
|
+
* the two unions stay aligned so the whoami build from a principal can
|
|
682
|
+
* never drift from the wire type).
|
|
620
683
|
*/
|
|
621
684
|
export interface WhoamiResponse {
|
|
622
685
|
readonly user?: string;
|
|
@@ -624,7 +687,7 @@ export interface WhoamiResponse {
|
|
|
624
687
|
readonly email?: string;
|
|
625
688
|
readonly admin: boolean;
|
|
626
689
|
readonly service: boolean;
|
|
627
|
-
readonly method: "none" | "token" | "proxy";
|
|
690
|
+
readonly method: "none" | "token" | "proxy" | "host";
|
|
628
691
|
}
|
|
629
692
|
/**
|
|
630
693
|
* The `GET /v1/onboarding` payload (core hardening W1 Task 4, spec
|
|
@@ -648,12 +711,19 @@ export interface OnboardingState {
|
|
|
648
711
|
* One directory user on the wire (Task 4): the full record — emails are
|
|
649
712
|
* admin-visible material and the routes that serve this type are
|
|
650
713
|
* admin-gated. `createdAt` is epoch ms.
|
|
714
|
+
*
|
|
715
|
+
* `admin` is the STORED flag (the users-admin UI toggles it); the proxy
|
|
716
|
+
* group grant rides separately as `groupAdmin` (gateway C8): effective
|
|
717
|
+
* admin is `admin || groupAdmin === true`, and the last-admin guard
|
|
718
|
+
* counts `admin` alone.
|
|
651
719
|
*/
|
|
652
720
|
export interface UserWire {
|
|
653
721
|
readonly user: string;
|
|
654
722
|
readonly name?: string;
|
|
655
723
|
readonly email?: string;
|
|
656
724
|
readonly admin: boolean;
|
|
725
|
+
/** The persisted proxy-group grant — present only under `adminGroups`. */
|
|
726
|
+
readonly groupAdmin?: boolean;
|
|
657
727
|
readonly createdAt: number;
|
|
658
728
|
readonly source: "proxy" | "invite" | "cli";
|
|
659
729
|
}
|
|
@@ -741,4 +811,12 @@ export type HostEventWire = {
|
|
|
741
811
|
/** W4 Task 4 (§8.4): the changed job's summary, WITHOUT `access` — the events stream computes `accessOf` per principal and adds it before delivery (a hidden job's event is withheld entirely). */
|
|
742
812
|
readonly type: "job.changed";
|
|
743
813
|
readonly job: Omit<JobWire, "access">;
|
|
814
|
+
} | {
|
|
815
|
+
/** UI-blocks U3 Task 4 (spec §7.3): one surface instance changed. `k` is the hashed instance key (sha256(slug + "\0" + id + "\0" + key) hex) — the event NEVER carries params or data (render/data are principal-specific; the watcher refetches as itself). Delivered only to streams in the watcher registry whose stored access is not `"none"`. */
|
|
816
|
+
readonly type: "surface.changed";
|
|
817
|
+
readonly slug: string;
|
|
818
|
+
readonly id: string;
|
|
819
|
+
readonly k: string;
|
|
820
|
+
readonly rev: number;
|
|
821
|
+
readonly treeRev: number;
|
|
744
822
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sigrun/shared",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "sigrun shared leaf package
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "sigrun shared leaf package \u2014 theme tokens, turn/conversation shaping, and the channel wire types (pure leaf, zero dependencies)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./themes": {
|
|
@@ -44,6 +44,10 @@
|
|
|
44
44
|
"types": "./dist/views.d.ts",
|
|
45
45
|
"default": "./dist/views.js"
|
|
46
46
|
},
|
|
47
|
+
"./live": {
|
|
48
|
+
"types": "./dist/live.d.ts",
|
|
49
|
+
"default": "./dist/live.js"
|
|
50
|
+
},
|
|
47
51
|
"./view-delta": {
|
|
48
52
|
"types": "./dist/view-delta.d.ts",
|
|
49
53
|
"default": "./dist/view-delta.js"
|
|
@@ -51,6 +55,10 @@
|
|
|
51
55
|
"./jobs": {
|
|
52
56
|
"types": "./dist/jobs.d.ts",
|
|
53
57
|
"default": "./dist/jobs.js"
|
|
58
|
+
},
|
|
59
|
+
"./blocks": {
|
|
60
|
+
"types": "./dist/blocks/index.d.ts",
|
|
61
|
+
"default": "./dist/blocks/index.js"
|
|
54
62
|
}
|
|
55
63
|
},
|
|
56
64
|
"scripts": {
|
package/package.json
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sigrun/sigrun",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Durable personal assistant on pi-durable",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./dist/index.js",
|
|
8
8
|
"./extension": {
|
|
9
9
|
"types": "./dist/extension.d.ts"
|
|
10
|
+
},
|
|
11
|
+
"./blocks": {
|
|
12
|
+
"types": "./dist/blocks/index.d.ts",
|
|
13
|
+
"default": "./dist/blocks/index.js"
|
|
10
14
|
}
|
|
11
15
|
},
|
|
12
16
|
"bin": {
|
|
@@ -39,22 +43,24 @@
|
|
|
39
43
|
"@earendil-works/pi-ai": "1.3.0",
|
|
40
44
|
"@earendil-works/pi-durable": "1.3.0",
|
|
41
45
|
"@earendil-works/pi-tui": "^1.3.0",
|
|
42
|
-
"@fastify/static": "^
|
|
46
|
+
"@fastify/static": "^10.1.7",
|
|
43
47
|
"@sigrun/ext-codemode": "0.1.0",
|
|
44
48
|
"@sigrun/ext-mcp": "0.2.0",
|
|
45
49
|
"@sigrun/ext-tool-search": "0.1.0",
|
|
46
|
-
"@sigrun/shared": "0.1.
|
|
50
|
+
"@sigrun/shared": "0.1.2",
|
|
47
51
|
"croner": "^10.0.1",
|
|
48
|
-
"fastify": "^5.12.
|
|
52
|
+
"fastify": "^5.12.7",
|
|
53
|
+
"typebox": "1.3.27"
|
|
49
54
|
},
|
|
50
55
|
"bundleDependencies": [
|
|
51
56
|
"@sigrun/shared"
|
|
52
57
|
],
|
|
53
58
|
"optionalDependencies": {
|
|
54
|
-
"@sigrun/tui": "0.1.
|
|
59
|
+
"@sigrun/tui": "0.1.1"
|
|
55
60
|
},
|
|
56
61
|
"devDependencies": {
|
|
57
62
|
"@types/node": "^26.6.4",
|
|
63
|
+
"fast-check": "^4.10.2",
|
|
58
64
|
"tsx": "^4.23.15",
|
|
59
65
|
"typescript": "^7.0.2",
|
|
60
66
|
"vitest": "^5.0.3",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.blk{min-width:0;margin:0}.blk-width{width:100%;container-type:inline-size}.blk-icon{vertical-align:-.15em;flex:none}.blk-unsupported{border:1px dashed var(--border);color:var(--muted);border-radius:8px;padding:.75rem 1rem;font-size:.9em}.blk-unsupported-note{color:var(--faint);margin:.25rem 0 0;font-size:.85em}.blk-stack{flex-direction:column;display:flex}.blk-columns{gap:1rem;display:flex}.blk-columns[data-stacked=true]{flex-direction:column}.blk-column{min-width:0}.blk-grid{gap:1rem;display:grid}.blk-grid-item[data-span=full]{grid-column:1/-1}.blk-section{border:1px solid var(--border);background:var(--surface);border-radius:10px;padding:.9rem 1.1rem}.blk-section-head{flex-wrap:wrap;align-items:baseline;gap:.25rem .75rem;margin-bottom:.6rem;display:flex}.blk-section-title{color:var(--text);font-size:.95em;font-weight:600}.blk-section-subtitle{color:var(--faint);font-size:.85em}.blk-section-toggle{color:inherit;cursor:pointer;font:inherit;background:0 0;border:0;align-items:center;gap:.4rem;padding:0;display:flex}.blk-section-caret{color:var(--faint);width:1em}.blk-markdown .md{font-size:.95em}.blk-fields dl{gap:.35rem;margin:0;display:grid}.blk-field-row{justify-content:space-between;gap:1rem;display:flex}.blk-field-row dt{color:var(--muted);flex:none}.blk-field-row dd{overflow-wrap:anywhere;text-align:end;gap:.4rem;margin:0;display:flex}.blk-stat{flex-direction:column;gap:.15rem;display:flex}.blk-stat[data-size=s]{font-size:.9em}.blk-stat[data-size=l]{font-size:1.15em}.blk-stat-top{color:var(--muted);align-items:center;gap:.4rem;font-size:.85em;display:flex}.blk-stat-value{font-variant-numeric:tabular-nums;font-size:1.6em;font-weight:650;line-height:1.2}.blk-stat[data-size=s] .blk-stat-value{font-size:1.3em}.blk-stat[data-size=l] .blk-stat-value{font-size:2em}.blk-stat-unit{color:var(--muted);font-size:.6em;font-weight:400}.blk-stat-caption{color:var(--faint);font-size:.8em}.blk-spark{color:var(--muted);width:100%;height:24px;margin-top:.25rem;display:block}.blk-callout{border-left:3px solid var(--muted);border-radius:0 8px 8px 0;padding:.6rem .9rem}.blk-callout[data-tone=accent]{border-left-color:var(--accent);background:var(--accent-bg)}.blk-callout[data-tone=good]{border-left-color:var(--ok);background:color-mix(in srgb, var(--ok) 10%, transparent)}.blk-callout[data-tone=warn]{border-left-color:var(--warn);background:color-mix(in srgb, var(--warn) 12%, transparent)}.blk-callout[data-tone=bad]{border-left-color:var(--danger);background:color-mix(in srgb, var(--danger) 10%, transparent)}.blk-callout[data-tone=info]{border-left-color:var(--muted);background:var(--code)}.blk-callout-title{font-weight:650}.blk-callout-body{margin-top:.25rem;font-size:.9em}.blk-image{border-radius:8px;max-width:100%;height:auto}.blk-image-fallback{border:1px dashed var(--border);color:var(--muted);border-radius:8px;padding:.75rem;font-size:.9em}.blk-diff-path{color:var(--faint);font-family:var(--mono);margin-bottom:.35rem;font-size:.8em}.blk-diff-panes{border-radius:8px;grid-template-columns:1fr 1fr;gap:.5rem;display:grid;overflow-x:auto}.blk-diff-panes pre{background:var(--code);font-family:var(--mono);white-space:pre-wrap;border-radius:6px;margin:0;padding:.6rem .75rem;font-size:.82em}.blk-diff-after{border:1px solid color-mix(in srgb, var(--ok) 35%, transparent)}.blk-diff-before{border:1px solid color-mix(in srgb, var(--danger) 35%, transparent)}@container (width<=40rem){.blk-diff-panes{grid-template-columns:1fr}}.blk-details summary{color:var(--muted);cursor:pointer;font-size:.9em}.blk-details-json{background:var(--code);font-family:var(--mono);white-space:pre-wrap;border-radius:6px;margin:.5rem 0 0;padding:.6rem .75rem;font-size:.82em}:root{--chart-1:var(--accent);--chart-2:#6fb3e0;--chart-3:#86c79b;--chart-4:#d9a35a;--chart-5:#b48ead;--chart-6:#e08f7a;--chart-7:#7fc7c7;--chart-8:#a9b665}[data-mode=light]{--chart-2:#3e78a8;--chart-3:#4a8a5f;--chart-4:#8a6116;--chart-5:#83619c;--chart-6:#b35c42;--chart-7:#3d8f8f;--chart-8:#6f7a2f}.blk-chart{flex-direction:column;gap:.35rem;min-width:0;display:flex}.blk-chart-head{flex-wrap:wrap;align-items:baseline;gap:.25rem .75rem;display:flex}.blk-chart-title{color:var(--muted);font-size:.85em}.blk-chart-legend{flex-wrap:wrap;gap:.25rem .9rem;margin-left:auto;display:flex}.blk-chart-legend[data-legend=below]{margin-left:0}.blk-chart-legend-item{color:var(--muted);align-items:center;gap:.35rem;font-size:.8em;display:inline-flex}.blk-chart-swatch{border-radius:2px;width:.9em;height:.6em;display:inline-block}.blk-chart-svg{width:100%;display:block}.blk-chart-grid{stroke:var(--border);stroke-dasharray:2 4;stroke-width:1px}.blk-chart-tick{fill:var(--faint);font-size:11px}.blk-chart-tick-line{stroke:var(--faint);stroke-width:1px}.blk-chart-y-caption{font-size:10px}.blk-chart-threshold{stroke-dasharray:6 4;stroke-width:1.5px}.blk-chart-threshold[data-tone=neutral]{stroke:var(--text)}.blk-chart-threshold[data-tone=accent]{stroke:var(--accent)}.blk-chart-threshold[data-tone=good]{stroke:var(--ok)}.blk-chart-threshold[data-tone=warn]{stroke:var(--warn)}.blk-chart-threshold[data-tone=bad]{stroke:var(--danger)}.blk-chart-threshold[data-tone=info]{stroke:var(--muted)}.blk-chart-threshold-label{font-size:10px}.blk-chart-threshold-label[data-tone=neutral]{fill:var(--text)}.blk-chart-threshold-label[data-tone=accent]{fill:var(--accent)}.blk-chart-threshold-label[data-tone=good]{fill:var(--ok)}.blk-chart-threshold-label[data-tone=warn]{fill:var(--warn)}.blk-chart-threshold-label[data-tone=bad]{fill:var(--danger)}.blk-chart-threshold-label[data-tone=info]{fill:var(--muted)}.blk-chart-spark-row{align-items:baseline;gap:.5rem;display:flex}.blk-chart-spark{flex:1;min-width:0;height:24px}.blk-chart-spark-name{color:var(--muted);text-overflow:ellipsis;white-space:nowrap;flex:none;font-size:.8em;overflow:hidden}.blk-chart-spark-value{font-variant-numeric:tabular-nums;flex:none;font-size:.9em;font-weight:650}.blk-meter{flex-direction:column;gap:.3rem;display:flex}.blk-meter-head{justify-content:space-between;gap:.75rem;display:flex}.blk-meter-label{color:var(--muted);font-size:.85em}.blk-meter-value{font-variant-numeric:tabular-nums;font-size:.9em}.blk-meter-track{background:var(--code);border-radius:999px;width:100%;height:8px;overflow:hidden}.blk-meter-fill{background:var(--muted);border-radius:999px;height:100%;transition:width .2s}.blk-meter[data-tone=accent] .blk-meter-fill{background:var(--accent)}.blk-meter[data-tone=good] .blk-meter-fill{background:var(--ok)}.blk-meter[data-tone=warn] .blk-meter-fill{background:var(--warn)}.blk-meter[data-tone=bad] .blk-meter-fill{background:var(--danger)}.blk-meter[data-tone=info] .blk-meter-fill{background:var(--muted)}.blk-log-lines{background:var(--code);font-family:var(--mono);border-radius:8px;max-height:20rem;padding:.55rem .75rem;font-size:.82em;line-height:1.45;overflow-y:auto}.blk-log-line{gap:.6rem;display:flex}.blk-log-line[data-wrap=true] .blk-log-text{white-space:pre-wrap}.blk-log-time{color:var(--faint);flex:none;font-size:.9em}.blk-log-level{text-transform:uppercase;flex:none;min-width:3.5em;font-size:.85em;font-weight:650}.blk-log-text{white-space:pre}.blk-tree{flex-direction:column;display:flex}.blk-tree-row{cursor:pointer;border-radius:6px;align-items:center;gap:.35rem;padding:.15rem .25rem;display:flex}.blk-tree-row:hover{background:var(--code)}.blk-tree-toggle{color:var(--faint);cursor:pointer;font:inherit;background:0 0;border:0;flex:none;justify-content:center;align-items:center;width:1.1rem;padding:0;display:inline-flex}.blk-tree-toggle:disabled{cursor:default}.blk-tree-caret{transition:transform .15s}.blk-tree-caret[data-open=true]{transform:rotate(90deg)}.blk-tree-dot{width:3px;height:3px;display:inline-block}.blk-tree-label{overflow-wrap:anywhere}.blk-tree-children{flex-direction:column;display:flex}.blk-tree-pending{color:var(--faint);padding:.15rem .25rem}.blk-actions{flex-wrap:wrap;gap:.5rem;margin-top:.5rem;display:flex}.blk-action{background:var(--surface-2);border:1px solid var(--border);color:var(--text);cursor:pointer;font:inherit;border-radius:8px;align-items:center;gap:.4rem;padding:.3rem .7rem;font-size:.85em;display:inline-flex}.blk-action:hover{border-color:var(--accent)}.blk-confirm{background:var(--surface);border:1px solid var(--border);border-radius:10px;max-width:24rem;margin-top:.5rem;padding:.8rem 1rem}.blk-confirm[data-tone=bad]{border-color:color-mix(in srgb, var(--danger) 50%, var(--border))}.blk-confirm[data-tone=warn]{border-color:color-mix(in srgb, var(--warn) 50%, var(--border))}.blk-confirm-title{font-weight:650}.blk-confirm-body{color:var(--muted);margin-top:.3rem;font-size:.9em}.blk-confirm-row{justify-content:flex-end;gap:.5rem;margin-top:.7rem;display:flex}.blk-confirm-row button{background:var(--surface-2);border:1px solid var(--border);color:var(--text);cursor:pointer;font:inherit;border-radius:8px;padding:.3rem .8rem;font-size:.85em}.blk-confirm-row .blk-confirm-ok{background:var(--accent-bg);border-color:var(--accent)}.blk-card{background:var(--surface-2);border:1px solid var(--border);border-radius:10px;gap:.6rem;min-width:0;display:flex;position:relative;overflow:hidden}.blk-card-stripe{width:3px;position:absolute;top:0;bottom:0;left:0}.blk-card-image[data-layout=top]{aspect-ratio:16/9;object-fit:cover;width:100%;height:auto;display:block}.blk-card-image[data-layout=thumb]{object-fit:cover;border-radius:8px;align-self:flex-start;width:3rem;height:3rem;margin:.6rem 0 .6rem .6rem}.blk-card:has(.blk-card-image[data-layout=top]){flex-direction:column}.blk-card-main{flex-direction:column;flex:1;gap:.35rem;min-width:0;padding:.6rem .7rem;display:flex}.blk-card-head{align-items:flex-start;gap:.5rem;min-width:0;display:flex}.blk-card-icon{color:var(--muted);margin-top:.1rem;display:inline-flex}.blk-card-titles{flex:1;min-width:0}.blk-card-eyebrow{color:var(--muted);overflow-wrap:anywhere;font-size:.78em}.blk-card-title{overflow-wrap:anywhere;font-weight:600}.blk-card-subtitle{color:var(--muted);overflow-wrap:anywhere;text-overflow:ellipsis;white-space:nowrap;font-size:.88em;overflow:hidden}.blk-card-body{min-width:0;font-size:.9em}.blk-card-body[data-clamped]{-webkit-line-clamp:4;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.blk-card-badges,.blk-card-meta,.blk-card-metrics{flex-wrap:wrap;gap:.4rem;display:flex}.blk-card-badge{background:var(--accent-bg);border-radius:999px;padding:.05rem .5rem;font-size:.75em}.blk-card-badge[data-tone=good]{color:var(--ok)}.blk-card-badge[data-tone=warn]{color:var(--warn)}.blk-card-badge[data-tone=bad]{color:var(--danger)}.blk-card-badge[data-tone=neutral]{color:var(--text)}.blk-card-badge[data-tone=info]{color:var(--muted)}.blk-card-meta{color:var(--muted);font-size:.8em}.blk-card-meta-item{overflow-wrap:anywhere;align-items:center;gap:.25rem;display:inline-flex}.blk-card-metric{flex-direction:column;display:inline-flex}.blk-card-metric-value{font-weight:600}.blk-card-metric-label{color:var(--muted);font-size:.75em}.blk-card-deps{color:var(--muted);overflow-wrap:anywhere;font-size:.8em}.blk-card-status{border:1px solid var(--border);white-space:nowrap;border-radius:999px;align-items:center;gap:.3rem;padding:.05rem .5rem;font-size:.75em;display:inline-flex}.blk-card-status[data-tone=good]{color:var(--ok)}.blk-card-status[data-tone=warn]{color:var(--warn)}.blk-card-status[data-tone=bad]{color:var(--danger)}.blk-card-spinner{border:2px solid var(--border);border-top-color:currentColor;border-radius:50%;width:.7em;height:.7em;animation:.9s linear infinite blk-card-spin;display:inline-block}@keyframes blk-card-spin{to{transform:rotate(360deg)}}.blk-card-actions{justify-content:flex-end;align-items:center;gap:.4rem;display:flex}.blk-card-actions .blk-actions{justify-content:flex-start;margin-top:0}.blk-card-overflow{position:relative}.blk-card-overflow>summary{cursor:pointer;list-style:none}.blk-card-overflow[open]>.blk-actions{background:var(--surface-2);border:1px solid var(--border);z-index:5;border-radius:8px;flex-direction:column;padding:.4rem;position:absolute;right:0}.blk-collection{flex-direction:column;gap:.6rem;display:flex}.blk-list-rows{flex-direction:column;gap:.4rem;margin:0;padding:0;list-style:none;display:flex}.blk-list-line{align-items:flex-start;gap:.5rem;min-width:0;display:flex}.blk-list-card{flex:1;min-width:0}.blk-list-card[role=button]{cursor:pointer}.blk-list-number{color:var(--muted);text-align:end;min-width:1.2rem;margin-top:.7rem;font-size:.85em}.blk-list-nested{margin:.4rem 0 0;padding:0;list-style:none}.blk-list-group{flex-direction:column;gap:.4rem;display:flex}.blk-list-heading{border-bottom:1px solid var(--border);overflow-wrap:anywhere;padding-bottom:.2rem;font-weight:600}.blk-quiet-toggle{color:var(--accent);cursor:pointer;font:inherit;background:0 0;border:none;align-self:flex-start;padding:.2rem 0;font-size:.85em}.blk-select,.blk-check{margin-top:.9rem}.blk-bulk{flex-wrap:wrap;align-items:center;gap:.4rem;display:flex}.blk-bulk-action,.blk-bulk-submit{background:var(--surface-2);border:1px solid var(--border);color:var(--text);cursor:pointer;font:inherit;border-radius:8px;padding:.3rem .8rem;font-size:.85em}.blk-bulk-form{align-items:center;gap:.4rem;display:flex}.blk-bulk-form input{background:var(--surface-2);border:1px solid var(--border);color:var(--text);font:inherit;border-radius:8px;padding:.25rem .5rem}.blk-table-wrap{overflow-x:auto}.blk-table{border-collapse:collapse;width:100%}.blk-table th{border-bottom:1px solid var(--border);text-align:start;padding:.4rem .6rem;font-weight:600}.blk-table td{border-bottom:1px solid var(--border);overflow-wrap:anywhere;padding:.4rem .6rem}.blk-table-sort{color:var(--text);cursor:pointer;font:inherit;background:0 0;border:none;padding:0;font-weight:600}.blk-table-sort[data-dir]:after{content:" " attr(data-dir)}.blk-table-pager{justify-content:center;align-items:center;gap:.6rem;margin-top:.6rem;display:flex}.blk-table-pager button{background:var(--surface-2);border:1px solid var(--border);color:var(--text);cursor:pointer;font:inherit;border-radius:8px;padding:.3rem .8rem}.blk-table-pager button:disabled{opacity:.5}.blk-table-compact{flex-direction:column;gap:.6rem;display:flex}.blk-table-card{border:1px solid var(--border);border-radius:10px;overflow:hidden}.blk-table-high,.blk-table-low-fields{grid-template-columns:auto 1fr;gap:.2rem .8rem;padding:.4rem .7rem;display:grid}.blk-table-field{display:contents}.blk-table-field dt{color:var(--muted);font-size:.8em}.blk-table-field dd{overflow-wrap:anywhere;margin:0}.blk-table-expand{color:var(--accent);cursor:pointer;font:inherit;background:0 0;border:none;padding:.2rem .7rem;font-size:.85em}.blk-grid-items{gap:.6rem;display:grid}.blk-grid-display[data-overflow=scroll] .blk-grid-items{grid-template-columns:none;grid-auto-flow:column}.blk-grid-card{cursor:pointer;min-width:0}.blk-lanes-row{align-items:flex-start;gap:.8rem;display:flex;overflow-x:auto}.blk-lane{flex:1 1 0;min-width:14rem}.blk-lane-heading{padding:.2rem .4rem;font-weight:600}.blk-lane-card{cursor:pointer;min-width:0;margin:.3rem 0}.blk-lane-switcher{font:inherit;margin-block-end:.4rem}.blk-move-to{position:relative}.blk-move-to-target{font:inherit;display:block}.blk-calendar-grid{grid-template-columns:repeat(7,1fr);gap:.2rem;display:grid}.blk-calendar-day{border:1px solid color-mix(in srgb, currentColor 12%, transparent);min-height:3.5rem;padding:.2rem}.blk-calendar-daynum{opacity:.6;font-size:.75em}.blk-calendar-item{cursor:pointer;font-size:.85em;position:relative}.blk-calendar-resize{cursor:ew-resize;inset-inline-end:0;width:.6rem;height:.6rem;display:inline-block;position:absolute;bottom:0}.blk-agenda-row{cursor:pointer;gap:.6rem;padding:.2rem 0;display:flex}.blk-agenda-when{opacity:.7;white-space:nowrap;font-size:.8em}.blk-lane-card,.blk-calendar-item,.blk-calendar-resize{touch-action:none}.blk-form{gap:var(--sp-3,.75rem);flex-direction:column;display:flex}.blk-form[data-mode=inline]{flex-direction:row;align-items:flex-end}.blk-field{flex-direction:column;gap:.25rem;display:flex}.blk-field-label{font-weight:500}.blk-field-help{color:var(--fg-dim,#888);font-size:.875em}.blk-field-error{color:var(--bad,#d33);font-size:.875em}.blk-choice{gap:1rem;display:flex}.blk-choice[data-preview=beside]{flex-direction:row}.blk-choice[data-preview=below]{flex-direction:column}.blk-choice-options{flex-direction:column;gap:.25rem;display:flex}.blk-choice-option{align-items:baseline;gap:.5rem;display:flex}.blk-choice-description{color:var(--fg-dim,#888);font-size:.875em}.blk-choice-preview{min-width:12rem}.blk-secret{align-items:center;gap:.5rem;display:flex}.blk-secret-status{color:var(--fg-dim,#888);font-size:.875em}.blk-list-entry{align-items:flex-start;gap:.5rem;display:flex}.blk-daterange{flex-wrap:wrap;gap:.5rem;display:flex}.blk-stepper-progress{color:var(--fg-dim,#888);font-size:.875em}.blk-stepper-nav{gap:.5rem;display:flex}.blk-page{flex-direction:column;height:100%;min-height:0;display:flex}.blk-page-header{border-bottom:1px solid var(--border,#333);flex-wrap:wrap;align-items:center;gap:.75rem;padding:.75rem 1rem;display:flex}.blk-page-titles{flex:auto;min-width:0}.blk-page-title{margin:0;font-size:1.1rem}.blk-page-subtitle{color:var(--fg-subtle,#999);margin:0;font-size:.85rem}.blk-page-body{flex:auto;gap:1rem;min-height:0;padding:1rem;display:flex}.blk-page-sidebar{flex:0 0 16rem;overflow:auto}.blk-page-main{flex:auto;min-width:0;overflow:auto}.blk-page-detail{flex:0 0 24rem;overflow:auto}.blk-page-empty{text-align:center;color:var(--fg-subtle,#999);padding:3rem 1rem}.blk-page-empty-title{color:var(--fg,#ddd);font-size:1rem;font-weight:600}.blk-page-switcher{gap:.5rem;display:inline-flex}.blk-page-action{align-items:center;gap:.25rem;display:inline-flex}.blk-page-toggle{display:none}@container (width<=39.99rem){.blk-page-toggle{display:inline-flex}.blk-page-sidebar,.blk-page-detail{display:none}.blk-page-sidebar[data-open],.blk-page-detail[data-open]{background:var(--bg,#111);z-index:20;padding:1rem;display:block;position:absolute;inset:0;overflow:auto}.blk-page{position:relative}}.blk-surface{min-height:0}.blk-surface-toast{position:fixed;bottom:1rem;right:1rem}:root{--bg:#090d16;--surface:#0f1524;--surface-2:#161e31;--border:#1f2942;--text:#e2e8f3;--muted:#8e9ab2;--faint:#5d6984;--ok:#5fd4a8;--code:#ffffff0f;--accent:#d6a24a;--accent-bg:#d6a24a24;--warn:#d9a35a;--danger:#e0707a;--serif:Georgia, "Iowan Old Style", serif;--sans:Inter, -apple-system, "Segoe UI", system-ui, sans-serif;--mono:"JetBrains Mono", ui-monospace, Menlo, monospace;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}[data-mode=light]{--warn:#8a6116;--danger:#b3363f;--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light}a{color:var(--accent)}[data-mode=light] a{color:var(--text);text-decoration:underline;-webkit-text-decoration-color:var(--accent);text-decoration-color:var(--accent)}*{box-sizing:border-box}html,body{height:100%;margin:0}body{font:14px/1.5 var(--sans);background:var(--bg);color:var(--text);overflow:hidden}#root{height:100%}.app-root{height:100%;display:flex;overflow:hidden}.app-boot,.app-refused{height:100%;color:var(--muted);text-align:center;flex-direction:column;justify-content:center;align-items:center;gap:.5rem;padding:2rem;display:flex}.app-refused h1{color:var(--danger);margin:0;font-size:1.1rem}.app-refused p{max-width:70ch;font-family:var(--mono);word-break:break-all;font-size:.8rem}.side-drawer{background:var(--bg);flex:none;min-width:0;display:flex}.rail{border-right:1px solid var(--border);background:var(--bg);flex-direction:column;flex:none;align-items:center;gap:4px;width:52px;padding:12px 0;display:flex}.rail-brand{width:30px;height:30px;color:var(--accent);border:1px solid var(--border);border-radius:8px;place-items:center;margin-bottom:14px;display:grid}.rail-brand svg{width:18px;height:18px}.rail-btn{width:36px;height:36px;color:var(--faint);cursor:pointer;background:0 0;border:none;border-radius:8px;place-items:center;padding:0;display:grid;position:relative}.rail-btn:hover,.rail-btn-active{color:var(--text);background:var(--surface-2)}.rail-btn-active:before{content:"";background:var(--accent);border-radius:2px;width:2px;position:absolute;top:9px;bottom:9px;left:-8px}.rail-btn svg{width:18px;height:18px}.rail-spacer{flex:1}.rail-health{background:var(--ok);width:8px;height:8px;box-shadow:0 0 0 3px color-mix(in srgb, var(--ok) 15%, transparent);border-radius:50%;flex:none;margin:8px 0 10px}.rail-health[data-health=degraded]{background:var(--warn);box-shadow:0 0 0 3px color-mix(in srgb, var(--warn) 18%, transparent)}.rail-user{text-overflow:ellipsis;white-space:nowrap;max-width:44px;color:var(--muted);text-align:center;flex:none;margin:6px 0 2px;font-size:.68rem;overflow:hidden}.session-list{background:var(--surface);border-right:1px solid var(--border);flex-direction:column;flex:none;width:264px;min-height:0;padding:.4rem;display:flex}.session-search-row{gap:8px;margin:4px 2px 6px;display:flex}.session-search{border:1px solid var(--border);background:var(--bg);min-width:0;height:32px;color:var(--text);font:inherit;border-radius:8px;flex:1;padding:0 10px;font-size:13px}.session-search::placeholder{color:var(--faint)}.session-search:focus-visible{border-color:var(--accent);outline:none}.session-new{border:1px solid var(--border);width:32px;height:32px;color:var(--text);cursor:pointer;background:0 0;border-radius:8px;flex:none;place-items:center;padding:0;display:grid}.session-new:hover,.session-new:focus-visible{background:var(--surface-2)}.session-new svg{width:16px;height:16px}.session-list ul{flex:1;margin:.25rem 0 0;padding:0;list-style:none;overflow:auto}.session-group{letter-spacing:.04em;color:var(--faint);padding:10px 16px 4px;font-size:11px}.session-item{min-height:32px;color:var(--muted);border-radius:6px;align-items:center;gap:6px;margin:1px 8px;padding:0 6px 0 10px;display:flex;position:relative}.session-item:hover,.session-item:focus-within{background:var(--surface-2);color:var(--text)}.session-item-active{background:var(--accent-bg);color:var(--text)}.session-fork-mark{width:14px;color:var(--faint);text-align:right;flex:none;font-size:12px}.session-select{text-align:left;min-width:0;color:inherit;cursor:pointer;font:inherit;background:0 0;border:none;flex:1;padding:6px 0;display:block}.session-name{white-space:nowrap;text-overflow:ellipsis;display:block;overflow:hidden}.session-age{color:var(--faint);flex:none;font-size:11px}.session-row-actions{flex:none;display:flex;position:relative}.session-menu-toggle{width:22px;height:22px;color:var(--faint);cursor:pointer;background:0 0;border:none;border-radius:5px;place-items:center;padding:0;font-size:13px;line-height:1;display:grid}.session-menu-toggle svg{width:14px;height:14px}.session-menu-toggle{opacity:0;transition:opacity 80ms}.session-item:hover .session-menu-toggle,.session-item:focus-within .session-menu-toggle{opacity:1}.session-item:hover .session-age,.session-item:focus-within .session-age{opacity:0}.session-menu-toggle:hover,.session-menu-toggle:focus-visible{color:var(--text);background:var(--bg)}.session-menu{z-index:30;border:1px solid var(--border);background:var(--surface-2);border-radius:8px;flex-direction:column;min-width:130px;padding:4px;display:flex;position:absolute;top:24px;right:0;box-shadow:0 8px 24px #0000004d}.session-menu button{color:var(--text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:6px;padding:6px 10px;font-size:13px}.session-menu button:hover,.session-menu button:focus-visible{background:var(--accent-bg)}.session-rename-input{border:1px solid var(--accent);background:var(--bg);min-width:0;color:var(--text);font:inherit;border-radius:6px;flex:1;padding:3px 6px;font-size:13px}.session-empty{color:var(--faint);text-align:center;padding:16px;font-size:13px}.session-archived-toggle{width:calc(100% - 16px);color:var(--faint);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:6px;flex:none;margin:6px 8px 2px;padding:5px 10px;font-size:12px}.session-archived-toggle:hover,.session-archived-toggle:focus-visible{background:var(--surface-2);color:var(--muted)}.session-archived-toggle[aria-pressed=true]{color:var(--text)}.session-item-archived{opacity:.55}.side-error{color:var(--danger);margin:0;padding:6px 10px;font-size:12px}.main-column{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex}.main-body{flex:1;min-height:0;display:flex}.chat-header{border-bottom:1px solid var(--border);background:var(--bg);flex:none;align-items:center;gap:10px;min-width:0;height:48px;padding:0 16px 0 24px;display:flex}.chat-title{color:var(--text);cursor:text;white-space:nowrap;text-overflow:ellipsis;background:0 0;border:none;min-width:0;padding:0;font-family:inherit;font-size:14px;font-weight:600;overflow:hidden}.chat-title-input{font:inherit;color:var(--text);background:var(--surface);border:1px solid var(--accent);border-radius:6px;width:min(360px,60vw);min-width:0;max-width:100%;padding:2px 8px;font-size:14px;font-weight:600}.chat-header-spacer{flex:1;min-width:12px}.icon-btn{width:30px;height:30px;color:var(--muted);cursor:pointer;background:0 0;border:none;border-radius:6px;flex:none;place-items:center;padding:0;display:grid}.icon-btn:hover{background:var(--surface-2);color:var(--text)}.icon-btn[aria-pressed=true]{color:var(--text);background:var(--surface-2)}.icon-btn svg{width:16px;height:16px}.chat-menu-slot{display:inline-flex;position:relative}.chat-menu{z-index:60;background:var(--surface);border:1px solid var(--border);border-radius:8px;flex-direction:column;min-width:148px;padding:4px;display:flex;position:absolute;top:34px;right:0;box-shadow:0 10px 28px #00000059}.chat-menu button{color:var(--text);text-align:left;font:inherit;cursor:pointer;background:0 0;border:none;border-radius:6px;padding:6px 10px;font-size:13px}.chat-menu button:hover{background:var(--surface-2)}.shell-error{color:var(--danger);border-bottom:1px solid var(--border);margin:0;padding:.35rem 24px;font-size:12.5px}.chat-menu-toggle{display:none}.chat-column{background:var(--bg);flex-direction:column;flex:1;min-width:0;min-height:0;display:flex;position:relative}.chat-center{flex:1;min-height:0;padding:28px 24px 8rem;overflow-y:auto}.chat-fade{z-index:1;pointer-events:none;background:linear-gradient(to bottom, transparent 0%, color-mix(in srgb, var(--bg) 85%, transparent) 45%, var(--bg) 70%);-webkit-backdrop-filter:blur(1.5px);backdrop-filter:blur(1.5px);height:12rem;position:absolute;bottom:0;left:0;right:0;-webkit-mask-image:linear-gradient(#0000,#000 40%);mask-image:linear-gradient(#0000,#000 40%)}.chat-empty,.chat-loading{color:var(--faint);text-align:center}.turn-list{flex-direction:column;gap:1.1rem;width:100%;max-width:720px;margin:0 auto;display:flex}.turn{flex-direction:column;align-items:stretch;min-width:0;display:flex}.turn-user{align-items:flex-end}.turn-lineage{color:var(--faint);font:inherit;cursor:pointer;background:0 0;border:none;align-self:flex-start;padding:0;font-size:12px}.turn-lineage:hover,.turn-lineage:focus-visible{color:var(--muted);text-underline-offset:3px;text-decoration:underline}.entry-user{flex-direction:column;align-items:stretch;display:flex}.entry-user-message{background:var(--surface-2);border:1px solid var(--border);border-radius:14px 14px 4px;max-width:60ch;padding:9px 14px}.entry-user-message p{margin:.25rem 0}.entry-expanded{flex-direction:column;align-items:flex-end;gap:.3rem;display:flex}.entry-expanded-chip{border:1px solid var(--border);color:var(--muted);cursor:pointer;background:0 0;border-radius:6px;padding:.1rem .5rem;font-size:.75rem}.entry-expanded-chip:hover{color:var(--text)}.entry-expanded-text{border:1px dashed var(--border);max-width:min(78%,60ch);color:var(--muted);white-space:pre-wrap;word-break:break-word;border-radius:8px;align-self:flex-end;padding:6px 10px;font-size:.8rem}.turn-prose{word-break:break-word;min-width:0}.md{min-width:0}.md-prose{font-family:var(--serif);font-size:15px;line-height:1.65}.md-bubble{font-size:14px;line-height:1.5}.md>:last-child{margin-bottom:0}.md p{margin:0 0 .75rem}.md-bubble p{margin:.25rem 0}.md h1,.md h2,.md h3,.md h4,.md h5,.md h6{font-family:var(--sans);color:var(--text);margin:1.1rem 0 .5rem;line-height:1.3}.md h1{font-size:1.25rem}.md h2{font-size:1.15rem}.md h3{font-size:1.05rem}.md h4,.md h5,.md h6{font-size:1rem}.md ul,.md ol{margin:0 0 .75rem;padding-left:1.4rem}.md li{margin:.15rem 0}.md blockquote{border-left:2px solid var(--border);color:var(--muted);margin:0 0 .75rem;padding:.1rem 0 .1rem .75rem}.md hr{border:0;border-top:1px solid var(--border);margin:1rem 0}.md img{max-width:100%}.md code{font-family:var(--mono);background:var(--code);border-radius:4px;padding:.1em .35em;font-size:.88em}.md-tbl{border:1px solid var(--border);font-family:var(--sans);border-radius:10px;margin:.35rem 0 .9rem;font-size:13px;overflow:hidden}.md-tbl-bar{border-bottom:1px solid var(--border);background:var(--surface);color:var(--faint);align-items:center;gap:.5rem;padding:.35rem .6rem;font-size:12px;display:flex}.md-tbl-bar input{min-width:0;color:var(--text);font:12px var(--sans);background:0 0;border:none;outline:none;flex:1}.md-tbl-count{color:var(--faint);white-space:nowrap;margin-left:auto;font-size:12px}.md-tbl table{border-collapse:collapse;width:100%}.md-tbl th{text-align:left;color:var(--muted);border-bottom:1px solid var(--border);background:var(--surface);padding:7px 10px;font-weight:500}.md-tbl td{border-bottom:1px solid var(--border);color:var(--text);padding:7px 10px}.md-tbl tbody tr:last-child td{border-bottom:none}.md-code{border:1px solid var(--border);background:color-mix(in srgb, var(--surface) 55%, var(--bg));border-radius:10px;margin:.35rem 0 .9rem}.md-code-head{border-bottom:1px solid var(--border);font-family:var(--sans);color:var(--faint);justify-content:space-between;align-items:center;padding:.3rem .6rem;font-size:11px;display:flex}.md-code-lang{font-family:var(--mono)}.md-code-copy{color:var(--faint);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:5px;padding:1px 7px}.md-code-copy:hover,.md-code-copy:focus-visible{color:var(--text);background:var(--surface-2)}.md-code-copy[data-copied]{color:var(--ok)}.md-code pre{font:12.5px/1.55 var(--mono);color:var(--text);margin:0;padding:.6rem .75rem;overflow-x:auto}.md-code pre code{font:inherit;background:0 0;border-radius:0;padding:0}.entry-attachment{font-family:var(--mono);color:var(--muted);margin-left:.4rem;font-size:.75rem}.message-actions{opacity:0;align-items:center;gap:.15rem;min-height:24px;margin-top:2px;transition:opacity 80ms;display:flex}.message-actions[data-kind=user]{justify-content:flex-end}.turn:hover .message-actions,.turn:focus-within .message-actions{opacity:1}.message-action{color:var(--faint);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:5px;padding:2px 7px;font-size:12px}.message-action:hover,.message-action:focus-visible{color:var(--text);background:var(--surface-2)}.message-action[data-copied]{color:var(--ok)}.message-meta{color:var(--faint);font-family:var(--mono);white-space:nowrap;margin-left:auto;font-size:11px}.activity-line{flex-direction:column;align-items:flex-start;margin-top:.35rem;display:flex}.activity-toggle{color:var(--muted);font-family:var(--mono);cursor:pointer;background:0 0;border:none;align-items:center;gap:.45rem;padding:1px 0;font-size:11.5px;display:inline-flex}.activity-toggle:hover,.activity-toggle:focus-visible{color:var(--text)}.activity-failed{color:var(--danger)}.activity-body{border-left:2px solid var(--border);flex-direction:column;gap:.15rem;width:100%;margin-top:.25rem;padding-left:.85rem;display:flex}.activity-thinking{color:var(--faint);white-space:pre-wrap;margin:.1rem 0 .25rem;font-size:.82rem;font-style:italic}.activity-spinner,.tool-row-spinner{border:1.5px solid var(--border);border-top-color:var(--accent);border-radius:50%;flex:none;width:9px;height:9px;animation:.8s linear infinite activity-spin}@keyframes activity-spin{to{transform:rotate(360deg)}}.entry-system,.entry-unknown{color:var(--muted);font-size:.8rem}.turn-compaction{color:var(--faint);letter-spacing:.05em;align-items:center;gap:12px;font-size:11px;display:flex}.turn-compaction:before,.turn-compaction:after{content:"";border-top:1px solid var(--border);flex:1}.chat-working{color:var(--muted);align-items:center;gap:.3rem;padding:.4rem .2rem;font-size:.8rem;display:flex}.chat-working-dot{background:var(--muted);border-radius:50%;width:6px;height:6px;animation:1.2s ease-in-out infinite working-bounce}.chat-working-dot:nth-child(2){animation-delay:.15s}.chat-working-dot:nth-child(3){animation-delay:.3s}@keyframes working-bounce{0%,to{opacity:.25;transform:translateY(0)}50%{opacity:1;transform:translateY(-3px)}}.chat-working-label{margin-left:.25rem}.chat-compaction-failure{color:var(--danger);margin:.25rem 0;font-size:.8rem}.tool-row{flex-direction:column;min-width:0;display:flex}.tool-row-head{align-items:center;gap:.4rem;min-width:0;display:flex}.tool-row-toggle{min-width:0;color:var(--muted);font-family:var(--mono);text-align:left;cursor:pointer;background:0 0;border:none;flex:1;align-items:baseline;gap:.5rem;padding:1px 0;font-size:12px;display:flex}.tool-row-toggle:hover,.tool-row-toggle:focus-visible{color:var(--text)}.tool-row[data-error] .tool-row-toggle{color:var(--danger)}.tool-row-glyph{flex:none}.tool-row-glyph[data-glyph=ok]{color:var(--ok)}.tool-row-glyph[data-glyph=error]{color:var(--danger)}.tool-row-glyph[data-glyph=pending]{color:var(--faint)}.tool-row-name{flex:none}.tool-row-preview{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.tool-row-actions{opacity:0;flex:none;gap:.15rem;transition:opacity 80ms;display:flex}.tool-row:hover .tool-row-actions,.tool-row:focus-within .tool-row-actions{opacity:1}.tool-row-detail{flex-direction:column;gap:.35rem;margin:.25rem 0 .35rem;display:flex}.tool-row-args,.tool-row-output{background:var(--code);font-family:var(--mono);white-space:pre;border-radius:6px;max-height:240px;margin:0;padding:.45rem .6rem;font-size:12px;overflow:auto}.tool-row-more{color:var(--faint);font:inherit;cursor:pointer;background:0 0;border:none;align-self:flex-start;padding:0;font-size:12px}.tool-row-more:hover,.tool-row-more:focus-visible{color:var(--text);text-underline-offset:3px;text-decoration:underline}.tool-row-diff{background:var(--code);font-family:var(--mono);white-space:pre;border-radius:6px;max-height:240px;margin:0;padding:.45rem .6rem;font-size:12px;overflow:auto}.tool-row-diff .diff-line-add{color:var(--ok)}.tool-row-diff .diff-line-del{color:var(--danger)}.tool-row-diff .diff-line-ctx{color:var(--muted)}.composer-slot{z-index:2;background:var(--bg);padding:.75rem 24px 1.1rem;position:absolute;bottom:0;left:0;right:0}.composer{border:1px solid var(--border);background:var(--surface);border-radius:14px;flex-direction:column;gap:.55rem;max-width:720px;margin:0 auto;padding:12px;display:flex}.composer-input{resize:none;width:100%;color:var(--text);font:inherit;background:0 0;border:none;min-height:1.6rem;max-height:40vh;padding:.35rem .25rem .45rem;transition:height .12s ease-out;overflow-y:auto}.composer-input:focus-visible{outline:1px solid var(--border);outline-offset:3px;border-radius:6px}.composer-toolbar{flex-wrap:wrap;align-items:center;gap:4px;display:flex}.composer-toolbar-spacer{flex:1}.composer-pill{height:28px;color:var(--muted);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:7px;align-items:center;gap:6px;padding:0 9px;font-size:12.5px;display:inline-flex}.composer-pill:hover,.composer-pill[aria-expanded=true]{background:var(--surface-2);color:var(--text)}.composer-pill:disabled{opacity:.55;cursor:default}.composer-pill svg{width:15px;height:15px}.composer-pill-caret{color:var(--faint);font-size:10px}.composer-picker{display:inline-flex;position:relative}.composer-picker-menu{z-index:60;background:var(--surface);border:1px solid var(--border);border-radius:8px;flex-direction:column;gap:1px;min-width:210px;max-height:16rem;margin:0;padding:4px;list-style:none;display:flex;position:absolute;bottom:calc(100% + 6px);left:0;overflow:auto;box-shadow:0 10px 28px #00000059}.composer-picker-menu li{color:var(--text);cursor:pointer;white-space:nowrap;border-radius:6px;align-items:baseline;gap:8px;padding:6px 10px;font-size:13px;display:flex}.composer-picker-menu li[data-highlighted]{background:var(--accent-bg)}.composer-picker-check{color:var(--accent);font-size:12px}.composer-picker-id{color:var(--muted);font-family:var(--mono);margin-left:auto;padding-left:12px;font-size:11.5px}.composer-ring{color:var(--faint);justify-content:center;align-items:center;gap:6px;margin-right:6px;font-size:11.5px;display:inline-flex}.composer-ring-track{fill:none;stroke:var(--border);stroke-width:3px}.composer-ring-fill{fill:none;stroke:var(--accent);stroke-width:3px;stroke-linecap:round}.composer-send{background:var(--accent);width:30px;height:30px;color:var(--bg);cursor:pointer;border:0;border-radius:8px;flex:none;place-items:center;padding:0;display:grid}.composer-send svg{width:16px;height:16px}.composer-send.composer-send-disabled{background:var(--surface-2);color:var(--faint);cursor:default}.composer-queued{color:var(--warn);white-space:nowrap;font-size:12px}.composer-attach{padding:0 7px}.composer-attach[data-uploading]{opacity:.6;cursor:default}.composer-hint{text-align:center;max-width:720px;color:var(--faint);margin:6px auto 0;font-size:11px}.composer-attachments{flex-wrap:wrap;gap:.4rem;margin:0;padding:0;list-style:none;display:flex}.composer-attachment{border:1px solid var(--border);color:var(--text);border-radius:6px;align-items:center;gap:.35rem;padding:.15rem .5rem;font-size:.78rem;display:flex}.composer-attachment-remove{color:var(--muted);cursor:pointer;background:0 0;border:none;padding:0;font-size:.9rem}.right-panel{background:var(--surface);border-left:1px solid var(--border);flex-direction:column;flex:none;width:280px;min-height:0;display:flex}.right-panel-title{color:var(--faint);letter-spacing:.04em;margin:14px 10px 8px;font-size:11px;font-weight:500}.right-panel-body{flex-direction:column;flex:1;min-height:0;display:flex}.outline{flex-direction:column;flex:1;gap:1px;min-height:0;padding:0 .5rem .75rem;display:flex;overflow-y:auto}.outline-empty{color:var(--faint);margin:.25rem .75rem;font-size:12.5px}.outline-item{-webkit-line-clamp:2;text-align:left;color:var(--muted);font:12.5px/1.35 var(--sans);cursor:pointer;background:0 0;border:none;border-left:2px solid #0000;border-radius:0 6px 6px 0;-webkit-box-orient:vertical;padding:6px 8px;display:-webkit-box;overflow:hidden}.outline-item:hover,.outline-item:focus-visible{background:var(--surface-2);color:var(--text)}.outline-item[aria-current=true]{color:var(--text);border-left-color:var(--accent)}.workspace-browser{flex-direction:column;height:100%;min-height:0;padding:.6rem .8rem;display:flex}.workspace-title{color:var(--faint);text-transform:uppercase;letter-spacing:.5px;align-items:center;margin:0 0 .6rem;font-size:12px;font-weight:600;display:flex}.workspace-close{color:var(--muted);cursor:pointer;text-transform:none;background:0 0;border:none;margin-left:auto;padding:0 .2rem;font-size:14px;display:none}.workspace-tree,.workspace-children{margin:0;padding:0;list-style:none}.workspace-tree{font-family:var(--mono);flex:1;min-height:0;font-size:12px;overflow:auto}.workspace-dir,.workspace-file{width:100%;color:inherit;text-align:left;cursor:pointer;font:inherit;background:0 0;border:none;border-radius:5px;padding:.2rem .3rem;display:block}.workspace-file{color:var(--muted)}.workspace-dir:hover,.workspace-file:hover{background:var(--surface-2)}.workspace-file:hover{color:var(--text)}.workspace-file[data-selected]{background:var(--surface-2);color:var(--text)}.file-preview{border-top:1px solid var(--border);background:var(--surface-2);max-height:40%;padding:.6rem .8rem;overflow:auto}.file-preview-path{color:var(--muted);word-break:break-all;margin:0 0 .4rem;font-size:.75rem}.file-preview-content{font-family:var(--mono);white-space:pre-wrap;word-break:break-word;margin:0;font-size:11px;overflow:auto}.file-preview-binary,.file-preview-loading,.workspace-empty,.workspace-loading{color:var(--faint);font-size:.8rem}.jobs-panel{flex-direction:column;height:100%;min-height:0;padding:.6rem .8rem;display:flex}.jobs-list{flex:1;min-height:0;margin:0;padding:0;list-style:none;overflow-y:auto}.job-row{border-bottom:1px solid var(--border);padding:.35rem 0}.job-summary{text-align:left;cursor:pointer;font:inherit;background:0 0;border:none;border-radius:5px;grid-template-columns:1fr;gap:1px;padding:2px 4px;display:grid}.job-summary:hover{background:var(--surface-2)}.job-name{color:var(--text);font-size:12.5px;font-weight:500}.job-schedule,.job-next,.job-last{color:var(--muted);font-size:11.5px;font-family:var(--mono)}.job-summary-side{justify-content:flex-end;align-items:center;gap:.4rem;padding:0 4px .25rem;display:flex}.job-conversation{color:var(--accent);font:11.5px var(--mono);cursor:pointer;background:0 0;border:none;padding:0;text-decoration:underline}.job-runnow{border:1px solid var(--border);color:var(--text);font:11px var(--sans);cursor:pointer;background:0 0;border-radius:5px;padding:1px 8px}.job-runnow:hover{border-color:var(--accent);color:var(--accent)}.job-detail{padding:.3rem .4rem .5rem}.job-section-title{color:var(--faint);text-transform:uppercase;letter-spacing:.5px;margin:.4rem 0 .25rem;font-size:10.5px;font-weight:600}.job-run-row,.job-revision-meta{font:11px var(--mono);color:var(--muted);flex-wrap:wrap;align-items:baseline;gap:.5rem;padding:1px 0;display:flex}.job-run-version,.job-revision-version{color:var(--faint)}.job-run-manual{border:1px solid var(--border);border-radius:4px;padding:0 4px;font-size:10px}.job-run-outcome[data-outcome=failed],.job-run-error{color:var(--danger)}.job-run-outcome[data-outcome=succeeded]{color:var(--ok)}.job-run-error{white-space:nowrap;text-overflow:ellipsis;max-width:100%;overflow:hidden}.job-revision-row{margin:.25rem 0}.job-revision-changedBy{color:var(--text)}.job-revision-row .interaction-diff{margin:.25rem 0}.job-empty{color:var(--faint);margin:.1rem 0;font-size:11.5px}.drawer-backdrop,.panel-backdrop{display:none}@media (width<=900px){.side-drawer{z-index:90;transition:transform .18s;position:fixed;top:0;bottom:0;left:0;transform:translate(-100%);box-shadow:0 0 32px #00000059}.side-drawer[data-open]{transform:translate(0)}.chat-menu-toggle{display:grid}.right-panel{z-index:90;width:min(320px,85vw);position:fixed;top:0;bottom:0;right:0;box-shadow:-12px 0 32px #00000073}.workspace-close{display:block}.drawer-backdrop,.panel-backdrop{z-index:85;background:#00000059;display:block;position:fixed;inset:0}.chat-center{padding:20px 16px 8rem}.chat-header{padding:0 12px 0 16px}.composer-slot{padding:.5rem 16px .9rem}}.composer-notice{color:var(--muted);margin:.25rem 0;font-size:.8rem}.composer-command-menu{border:1px solid var(--border);background:var(--surface-2);border-radius:8px;max-height:12rem;margin:0;padding:.25rem 0;font-size:.8rem;list-style:none;overflow:auto}.composer-command-menu li{cursor:pointer;align-items:baseline;gap:.5rem;padding:.3rem .6rem;display:flex}.composer-command-menu li[data-highlighted]{background:var(--accent-bg)}.composer-command-name{font-weight:600}.composer-command-args{color:var(--muted);font-family:var(--mono)}.composer-command-description{color:var(--muted)}.settings-overlay{z-index:100;background:#0006;justify-content:center;align-items:flex-start;padding-top:6vh;display:flex;position:fixed;inset:0}.settings-panel{background:var(--surface);border:1px solid var(--border);border-radius:12px;flex-direction:column;gap:.625rem;width:min(26rem,92vw);max-height:82vh;padding:.75rem .875rem;display:flex;overflow-y:auto;box-shadow:0 18px 48px #0006}.settings-head{align-items:center;gap:.5rem;display:flex}.settings-title{letter-spacing:.2px;font-weight:650}.settings-head .spacer{flex:1}.settings-close{color:var(--muted);cursor:pointer;background:0 0;border:none;font-size:13px}.settings-body{flex-direction:column;gap:.625rem;min-width:0;max-width:100%;display:flex}.settings-layout{gap:.75rem;min-width:0;display:flex}.settings-nav{flex-direction:column;flex:none;gap:.2rem;display:flex}.settings-nav-item{text-align:left;color:var(--muted);cursor:pointer;background:0 0;border:none;border-radius:5px;padding:.3rem .6rem;font-size:13px}.settings-nav-item:hover{background:var(--surface-2)}.settings-nav-item[data-active]{background:var(--accent-bg);color:var(--text)}.settings-section{flex:1;min-width:0}.settings-field{border:none;flex-direction:column;gap:.25rem;margin:0;padding:0;display:flex}.settings-label{color:var(--muted);font-size:12px;font-family:var(--sans)}.settings-checkbox{flex-flow:wrap;align-items:center;gap:.4rem;font-size:13px}.settings-checkbox .settings-note{flex-basis:100%}.settings-tools{flex-flow:wrap;gap:.25rem .75rem;display:flex}.settings-tools .settings-note{flex-basis:100%;min-width:0}.settings-note{color:var(--faint);margin:0;font-size:11px}.settings-select-wrap{width:fit-content;max-width:100%;position:relative}.settings-select-wrap:after{content:"▾";color:var(--muted);pointer-events:none;font-size:11px;position:absolute;top:50%;right:.55rem;transform:translateY(-50%)}.settings-field select{appearance:none;background:var(--bg);color:var(--text);border:1px solid var(--border);font:inherit;cursor:pointer;border-radius:6px;max-width:100%;padding:.35rem 1.7rem .35rem .6rem;font-size:13px}.settings-mode-row{background:var(--bg);border:1px solid var(--border);border-radius:8px;gap:3px;width:fit-content;padding:3px;display:flex}.settings-mode{color:var(--muted);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:6px;padding:.25rem .85rem;font-size:13px}.settings-mode:hover{color:var(--text)}.settings-mode[aria-pressed=true]{background:var(--surface-2);color:var(--text);box-shadow:inset 0 0 0 1px var(--border)}.settings-palettes{flex-wrap:wrap;gap:8px;display:flex}.settings-palette{border:1px solid var(--border);cursor:pointer;border-radius:8px;justify-content:center;align-items:center;gap:5px;width:56px;height:34px;padding:0;display:flex}.settings-palette[aria-pressed=true]{outline:2px solid var(--accent);outline-offset:2px}.settings-swatch-dot{border-radius:50%;flex:none;width:8px;height:8px}.settings-accents{flex-wrap:wrap;gap:10px;display:flex}.settings-accent{border:1px solid var(--border);cursor:pointer;border-radius:50%;width:20px;height:20px;padding:0}.settings-accent[aria-pressed=true]{outline:2px solid var(--accent);outline-offset:2px}.settings-thinking{font-family:var(--mono);background:var(--bg);color:var(--text);border:1px solid var(--border);resize:vertical;box-sizing:border-box;border-radius:4px;width:100%;max-width:100%;padding:.4rem;font-size:12px}.settings-actions{align-items:center;gap:.625rem;display:flex}.settings-save{background:var(--accent);color:var(--bg);cursor:pointer;border:none;border-radius:6px;padding:.3rem .9rem;font-weight:600}.settings-save:disabled{opacity:.5;cursor:default}.interaction-cards,.ambient-panels{max-height:40vh;overflow-y:auto}.interaction-cards{flex-direction:column;gap:.5rem;display:flex}.interaction-card{border:1px solid var(--warn);background:color-mix(in srgb, var(--warn) 8%, var(--surface));border-radius:8px;max-width:720px;padding:.7rem .9rem}.interaction-card-title{align-items:center;gap:.5rem;margin-bottom:.35rem;display:flex}.interaction-kind{font-family:var(--mono);color:var(--muted);background:color-mix(in srgb, var(--warn) 14%, transparent);border-radius:4px;padding:.1rem .45rem;font-size:11px}.interaction-expiry{color:var(--muted);font-size:.75rem}.interaction-text{white-space:pre-wrap;margin:.35rem 0}.interaction-diff{grid-template-columns:1fr 1fr;gap:.5rem;margin:.5rem 0;display:grid}.interaction-diff pre{background:var(--surface);font-family:var(--mono);border-radius:6px;max-height:16rem;margin:0;padding:.5rem;font-size:12px;overflow:auto}.interaction-diff-before{color:var(--danger)}.interaction-diff-after{color:var(--ok)}.interaction-options,.interaction-fields{flex-direction:column;gap:.4rem;margin:.5rem 0;display:flex}.interaction-option{border:1px solid var(--border);cursor:pointer;border-radius:6px;grid-template-columns:auto 1fr;align-items:baseline;gap:.4rem;padding:.4rem .6rem;display:grid}.interaction-option input{align-self:center}.interaction-option-label{font-weight:500}.interaction-option-danger{border-color:color-mix(in srgb, var(--danger) 45%, var(--border))}.interaction-option-warn{border-color:color-mix(in srgb, var(--warn) 45%, var(--border))}.interaction-option-ok{border-color:color-mix(in srgb, var(--ok) 45%, var(--border))}.interaction-option-description{color:var(--muted);grid-column:2;font-size:.8rem}.interaction-field{flex-direction:column;gap:.25rem;display:flex}.interaction-field-label{color:var(--muted);font-size:.8rem}.interaction-field input{border:1px solid var(--border);background:var(--surface);color:var(--text);font:inherit;border-radius:6px;padding:.4rem .6rem}.interaction-submit{border:1px solid var(--border);background:var(--ok);color:var(--bg);cursor:pointer;border-radius:6px;align-self:flex-start;padding:.35rem .9rem;font-weight:600}.interaction-submit:disabled{opacity:.5;cursor:default}.interaction-details,.ambient-details{color:var(--muted);margin-top:.4rem;font-size:.75rem}.interaction-details pre,.ambient-details pre{background:var(--surface);border-radius:6px;max-height:12rem;margin:.3rem 0 0;padding:.5rem;overflow:auto}.ambient-panels{flex-direction:column;gap:.5rem;display:flex}.ambient-surface{border:1px solid var(--border);background:var(--surface);border-radius:8px;max-width:720px;padding:.5rem .7rem}.ambient-surface-title{color:var(--faint);justify-content:space-between;margin-bottom:.3rem;font-size:.72rem;display:flex}.ambient-key{font-family:var(--mono)}.ambient-line{font-family:var(--mono);white-space:pre-wrap;flex-wrap:wrap;gap:.75rem;font-size:12px;display:flex}.ambient-segment-right{margin-left:auto}.ambient-rows{flex-direction:column;gap:.2rem;margin:.25rem 0 0;padding:0;list-style:none;display:flex}.ambient-row{align-items:baseline;gap:.45rem;font-size:.85rem;display:flex}.ambient-row[data-status=running] .ambient-row-glyph{color:var(--warn)}.ambient-row[data-status=completed],.ambient-row[data-status=complete],.ambient-row[data-status=passed]{color:var(--muted);text-decoration:line-through;-webkit-text-decoration-color:color-mix(in srgb, var(--muted) 60%, transparent);text-decoration-color:color-mix(in srgb, var(--muted) 60%, transparent)}.ambient-row[data-status=failed],.ambient-row[data-status=blocked]{color:var(--danger)}.ambient-row-glyph{font-family:var(--mono);flex:none}.ambient-row-spinner{color:var(--muted);font-size:.78rem;font-style:italic}.ambient-row-detail{color:var(--muted);font-size:.8rem}.ambient-row-deps{color:var(--muted);font-family:var(--mono);font-size:.72rem}.ambient-metrics{color:var(--muted);font-family:var(--mono);margin-left:auto;font-size:.72rem}.ambient-quiet-summary{color:var(--faint);font-size:.75rem}.ambient-gauge{flex-direction:column;gap:.35rem;display:flex}.ambient-gauge-label{color:var(--muted);font-size:.8rem}.ambient-gauge-bar{background:color-mix(in srgb, var(--faint) 25%, transparent);border-radius:3px;height:6px;overflow:hidden}.ambient-gauge-fill{background:var(--ok);height:100%;transition:width .3s}.ambient-recent-output{background:color-mix(in srgb, var(--border) 40%, transparent);font-family:var(--mono);border-radius:6px;max-height:8rem;margin:0;padding:.4rem;font-size:11px;overflow:auto}.ambient-ledger{flex-direction:column;gap:.2rem;max-height:10rem;margin:.25rem 0 0;padding:0;list-style:none;display:flex;overflow:auto}.ambient-ledger-entry{align-items:baseline;gap:.45rem;font-size:.8rem;display:flex}.ambient-ledger-kind{font-family:var(--mono);color:var(--muted);flex:none;font-size:.7rem}.ambient-ledger-detail{color:var(--muted);font-size:.75rem}.auth-screen{place-items:center;height:100%;padding:1rem;display:grid;overflow:auto}.auth-card{background:var(--surface);border:1px solid var(--border);border-radius:12px;flex-direction:column;gap:.9rem;width:min(24rem,100%);padding:1.5rem 1.5rem 1.25rem;display:flex;box-shadow:0 12px 40px #00000040}.auth-card h1{font-size:1.15rem;font-family:var(--serif);margin:0}.auth-message{color:var(--muted);margin:0;font-size:.85rem}.auth-identity{font-family:var(--mono);color:var(--text);word-break:break-all;margin:0;font-size:.85rem}.auth-field{color:var(--muted);flex-direction:column;gap:.3rem;font-size:.8rem;display:flex}.auth-field input{font:inherit;color:var(--text);background:var(--bg);border:1px solid var(--border);border-radius:8px;padding:.5rem .65rem}.auth-field input:focus-visible{outline:1px solid var(--accent);border-color:var(--accent)}.auth-optional{color:var(--faint);font-size:.72rem}.auth-submit{font:inherit;color:var(--text);background:var(--accent-bg);border:1px solid var(--accent);cursor:pointer;border-radius:8px;padding:.5rem .9rem}.auth-submit:disabled{opacity:.6;cursor:default}.auth-error{color:var(--danger);word-break:break-word;margin:0;font-size:.8rem}.share-overlay{z-index:60;background:#00000073;place-items:center;padding:1rem;display:grid;position:fixed;inset:0}.share-menu{background:var(--surface);border:1px solid var(--border);border-radius:12px;flex-direction:column;gap:.8rem;width:min(22rem,100%);padding:1rem 1.25rem 1.1rem;display:flex;box-shadow:0 12px 40px #00000040}.share-head{justify-content:space-between;align-items:baseline;gap:.5rem;display:flex}.share-head h2{font-size:1rem;font-family:var(--serif);margin:0}.share-close{font:inherit;color:var(--muted);cursor:pointer;background:0 0;border:none;padding:0;font-size:.75rem}.share-close:hover{color:var(--text)}.share-scopes{flex-direction:column;gap:.4rem;display:flex}.share-scope{font:inherit;text-align:left;color:var(--text);background:var(--bg);border:1px solid var(--border);cursor:pointer;border-radius:8px;flex-direction:column;gap:.1rem;padding:.45rem .65rem;display:flex}.share-scope[data-selected]{border-color:var(--accent);background:var(--accent-bg)}.share-scope-hint{color:var(--muted);font-size:.72rem}.share-level{gap:.4rem;display:flex}.share-level-btn{font:inherit;color:var(--muted);background:var(--bg);border:1px solid var(--border);cursor:pointer;border-radius:8px;flex:1;padding:.35rem .5rem;font-size:.8rem}.share-level-btn[data-selected]{color:var(--text);border-color:var(--accent);background:var(--accent-bg)}.share-field{color:var(--muted);flex-direction:column;gap:.3rem;font-size:.8rem;display:flex}.share-field input{font:inherit;color:var(--text);background:var(--bg);border:1px solid var(--border);border-radius:8px;padding:.45rem .6rem}.share-warning{color:var(--warn);margin:0;font-size:.8rem}.settings-ext-list{gap:.75rem}.settings-ext{border:1px solid var(--border);border-radius:4px;margin:0;padding:.5rem .75rem .75rem}.settings-ext-name{padding:0 .35rem;font-weight:600}.settings-ext-meta{color:var(--muted);margin-left:.4rem;font-size:11px;font-weight:400}.settings-ext-settings{font-family:var(--mono);background:var(--bg);color:var(--text);border:1px solid var(--border);resize:vertical;box-sizing:border-box;border-radius:4px;width:100%;max-width:100%;padding:.4rem;font-size:12px}.settings-ext-row{flex-wrap:wrap;align-items:center;gap:.4rem;margin-top:.35rem;display:flex}.settings-ext-key{font-family:var(--mono);font-size:12px}.settings-ext-source{color:var(--muted);font-size:11px}.settings-ext-row input{font-family:var(--mono);background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:4px;min-width:8rem;padding:.25rem .4rem;font-size:12px}.settings-provider-list{gap:.75rem}.settings-provider{border:1px solid var(--border);border-radius:4px;margin:0;padding:.5rem .75rem .75rem}.settings-provider-name{flex-wrap:wrap;align-items:center;gap:.4rem;padding:0 .35rem;font-weight:600;display:flex}.settings-provider-status{font-size:10px;font-weight:600;font-family:var(--mono);border:1px solid var(--border);color:var(--muted);white-space:nowrap;border-radius:999px;padding:.05rem .4rem}.settings-provider-status[data-status=ready]{color:var(--ok);border-color:color-mix(in srgb, var(--ok) 40%, transparent)}.settings-provider-status[data-status=degraded],.settings-provider-status[data-status=invalid]{color:var(--danger);border-color:color-mix(in srgb, var(--danger) 40%, transparent)}.settings-provider-meta{color:var(--muted);font-size:11px;font-weight:400}.settings-provider-row{flex-wrap:wrap;align-items:center;gap:.4rem;margin-top:.35rem;display:flex}.settings-provider-row input{font-family:var(--mono);background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:4px;flex:10rem;min-width:10rem;max-width:22rem;padding:.25rem .4rem;font-size:12px}.turn-timeline{flex-direction:column;gap:.5rem;display:flex}.turn-timeline>*+*{border-top:1px solid color-mix(in srgb, var(--border) 55%, transparent);padding-top:.5rem}.timeline-thinking{opacity:.75;white-space:pre-wrap;font-style:italic}.turn-assistant[data-live=true] .turn-timeline{border-left:2px solid color-mix(in srgb, var(--border) 80%, transparent);padding-left:.6rem}.settings-version{color:var(--text-dim,color-mix(in srgb, var(--text) 55%, transparent));-webkit-user-select:text;user-select:text;margin:.8rem 0 0;font-size:.82rem}.gallery{height:100%;min-height:0;display:flex}.gallery-list{border-right:1px solid var(--border,#333);flex:0 0 14rem;padding:1rem;overflow:auto}.gallery-list ul{margin:0;padding:0;list-style:none}.gallery-list button{text-align:left;width:100%;padding:.25rem .5rem;display:block}.gallery-main{flex:auto;min-width:0;padding:1rem;overflow:auto}.gallery-hint{color:var(--fg-subtle,#999)}.gallery-sample{flex-direction:column;min-width:0;height:100%;display:flex}.gallery-sample>.blk-surface{flex:auto;min-height:0}
|