@sigrun/sigrun 0.4.2 → 0.6.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 +92 -1
- package/README.md +63 -33
- package/dist/commands/expand.js +37 -5
- package/dist/curation/attribution.js +135 -0
- package/dist/curation/deletion.js +32 -0
- package/dist/curation/gate.js +50 -0
- package/dist/curation/host.js +342 -0
- package/dist/curation/internal.js +54 -0
- package/dist/curation/names.js +5 -0
- package/dist/curation/overlays.js +325 -0
- package/dist/curation/paths.js +17 -0
- package/dist/curation/run-doc.js +64 -0
- package/dist/curation/runs.js +579 -0
- package/dist/curation/scan.js +30 -0
- package/dist/curation/skill-tool.js +308 -0
- package/dist/curation/store.js +444 -0
- package/dist/curation/targets.js +77 -0
- package/dist/curation/usage.js +124 -0
- package/dist/curation/wrap.js +212 -0
- package/dist/extension.d.ts +336 -1
- package/dist/harness/boot.js +236 -13
- package/dist/harness/builtins.js +19 -12
- package/dist/harness/event-bus.js +64 -0
- package/dist/harness/identity/primary-admin.js +19 -0
- package/dist/harness/loader.js +114 -1
- package/dist/harness/naming.js +6 -0
- package/dist/harness/packages.js +14 -9
- package/dist/harness/reserved-sections.js +4 -0
- package/dist/harness/seam-host.js +154 -26
- package/dist/harness/sections/context-files.js +6 -3
- package/dist/harness/sections/job-state.js +24 -0
- package/dist/harness/settings.js +2 -2
- package/dist/harness/tools.js +70 -0
- package/dist/harness/workspace.js +30 -3
- package/dist/jobs/fire.js +37 -14
- package/dist/jobs/index.js +34 -7
- package/dist/jobs/reconcile.js +9 -0
- package/dist/jobs/skills-refs.js +40 -0
- package/dist/jobs/state-dir.js +16 -0
- package/dist/jobs/transfer.js +14 -0
- package/dist/sandbox/policy.js +27 -4
- package/dist/serve.js +5 -3
- package/dist/server/blocks/answers.js +9 -3
- package/dist/server/conversation-ops.js +34 -3
- package/dist/server/helpers.js +1 -1
- package/dist/server/host-bridge.js +31 -1
- package/dist/server/notifications.js +108 -16
- package/dist/server/routes/jobs.js +31 -0
- package/dist/server/routes/meta.js +8 -3
- package/dist/server/routes/submissions.js +5 -0
- package/dist/server/routes/surfaces.js +3 -1
- package/dist/server/routes/users.js +7 -0
- package/dist/server/schema-fixture.js +168 -0
- package/dist/server/session-meta.js +12 -10
- package/dist/settings/core-sections.js +18 -0
- package/dist/settings/registry.js +12 -0
- package/dist/skills/index.js +88 -19
- package/node_modules/@sigrun/shared/CHANGELOG.md +6 -1
- package/node_modules/@sigrun/shared/dist/access.d.ts +3 -0
- package/node_modules/@sigrun/shared/dist/access.js +8 -0
- package/node_modules/@sigrun/shared/dist/session-meta.d.ts +15 -4
- package/node_modules/@sigrun/shared/dist/settings.d.ts +7 -5
- package/node_modules/@sigrun/shared/package.json +1 -1
- package/package.json +9 -7
- package/webui/dist/assets/index-BR0di0OG.css +1 -0
- package/webui/dist/assets/{index-DWmsAQl2.js → index-BzrA1T4g.js} +5 -5
- package/webui/dist/index.html +2 -2
- package/webui/dist/assets/index-h7zDY9vD.css +0 -1
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
* other's fields (the mutation line serializes commits).
|
|
30
30
|
*
|
|
31
31
|
* Server-owned fields (`autoName`, `autoNameAttempts`,
|
|
32
|
-
* `lastActivityAt`, `jobId`, `deliver`) are written by host
|
|
33
|
-
* (activity.ts, the A2 auto-namer, fire.ts's job stamp
|
|
34
|
-
* patch surface — the strict
|
|
35
|
-
* `invalid_field`.
|
|
32
|
+
* `lastActivityAt`, `jobId`, `deliver`, `internal`) are written by host
|
|
33
|
+
* code only (activity.ts, the A2 auto-namer, fire.ts's job stamp, the
|
|
34
|
+
* curator's creating commit); they are NOT patch surface — the strict
|
|
35
|
+
* validator keeps rejecting them as `invalid_field`.
|
|
36
36
|
*/
|
|
37
37
|
import { defineDoc } from "@earendil-works/pi-durable";
|
|
38
38
|
import { isSharing } from "@sigrun/shared/access";
|
|
@@ -158,12 +158,14 @@ export function validateSessionMetaPatch(body) {
|
|
|
158
158
|
case "source":
|
|
159
159
|
case "owner":
|
|
160
160
|
case "jobId":
|
|
161
|
-
case "deliver":
|
|
162
|
-
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
//
|
|
166
|
-
//
|
|
161
|
+
case "deliver":
|
|
162
|
+
case "internal": {
|
|
163
|
+
// Server-only (spec §5.9 + gateway C7 + curator P5): the KEY
|
|
164
|
+
// itself is the client error, whatever the value — even a `null`
|
|
165
|
+
// clear. The job stamp fields move with the fire (fire.ts's
|
|
166
|
+
// creating commit) and the delivery targets ride the job spec,
|
|
167
|
+
// never a meta patch; the internal-run marker moves with the
|
|
168
|
+
// curator's creating commit (markInternal) alone.
|
|
167
169
|
return { error: "invalid_field", field: key };
|
|
168
170
|
}
|
|
169
171
|
case "sharing": {
|
|
@@ -496,6 +496,15 @@ export const CORE_SETTINGS_SECTIONS = [
|
|
|
496
496
|
help: "The built-in tool-search extension — applies at restart",
|
|
497
497
|
apply: applyOf("builtinExtensions.toolSearch"),
|
|
498
498
|
},
|
|
499
|
+
{
|
|
500
|
+
type: "toggle",
|
|
501
|
+
// Absent means ON (the built-in set defaults enabled).
|
|
502
|
+
default: true,
|
|
503
|
+
name: "builtinExtensions.gateway",
|
|
504
|
+
label: "Gateway",
|
|
505
|
+
help: "The built-in channel gateway engine — applies at restart",
|
|
506
|
+
apply: applyOf("builtinExtensions.gateway"),
|
|
507
|
+
},
|
|
499
508
|
{
|
|
500
509
|
type: "toggle",
|
|
501
510
|
default: true,
|
|
@@ -504,6 +513,15 @@ export const CORE_SETTINGS_SECTIONS = [
|
|
|
504
513
|
help: "The built-in OIDC/OAuth2 login extension — applies at restart",
|
|
505
514
|
apply: applyOf("builtinExtensions.oauth"),
|
|
506
515
|
},
|
|
516
|
+
{
|
|
517
|
+
type: "toggle",
|
|
518
|
+
// Absent means ON (the built-in set defaults enabled).
|
|
519
|
+
default: true,
|
|
520
|
+
name: "builtinExtensions.curator",
|
|
521
|
+
label: "Curator",
|
|
522
|
+
help: "The built-in curator extension — applies at restart",
|
|
523
|
+
apply: applyOf("builtinExtensions.curator"),
|
|
524
|
+
},
|
|
507
525
|
],
|
|
508
526
|
},
|
|
509
527
|
],
|
|
@@ -169,12 +169,24 @@ export const CORE_SETTING_KEYS = [
|
|
|
169
169
|
section: "extensions",
|
|
170
170
|
reason: "the built-in set resolves at boot (a disabled built-in never loads)",
|
|
171
171
|
},
|
|
172
|
+
{
|
|
173
|
+
key: "builtinExtensions.gateway",
|
|
174
|
+
apply: "restart",
|
|
175
|
+
section: "extensions",
|
|
176
|
+
reason: "the built-in set resolves at boot (a disabled built-in never loads)",
|
|
177
|
+
},
|
|
172
178
|
{
|
|
173
179
|
key: "builtinExtensions.oauth",
|
|
174
180
|
apply: "restart",
|
|
175
181
|
section: "extensions",
|
|
176
182
|
reason: "the built-in set resolves at boot (a disabled built-in never loads)",
|
|
177
183
|
},
|
|
184
|
+
{
|
|
185
|
+
key: "builtinExtensions.curator",
|
|
186
|
+
apply: "restart",
|
|
187
|
+
section: "extensions",
|
|
188
|
+
reason: "the built-in set resolves at boot (a disabled built-in never loads)",
|
|
189
|
+
},
|
|
178
190
|
{
|
|
179
191
|
key: "autoEnableCodemode",
|
|
180
192
|
apply: "live",
|
package/dist/skills/index.js
CHANGED
|
@@ -3,16 +3,20 @@
|
|
|
3
3
|
* package.
|
|
4
4
|
*
|
|
5
5
|
* v1 discovered ONE root: `skills/<dir>/SKILL.md` in the conversation
|
|
6
|
-
* workspace. W5 Task 4 (spec §9.4)
|
|
7
|
-
*
|
|
6
|
+
* workspace. W5 Task 4 (spec §9.4) grew discovery to THREE roots, and
|
|
7
|
+
* curator A3 (P2) adds a fourth — the conversation OWNER's learned
|
|
8
|
+
* skills. First-wins precedence in this order:
|
|
8
9
|
*
|
|
9
10
|
* 1. the WORKSPACE root — `skills/` under the conversation workspace, read
|
|
10
11
|
* through the conversation `ExecutionEnv` (the section via
|
|
11
12
|
* `PromptInput.env`, the tool via `ToolExecutionApi.env`), so discovery
|
|
12
13
|
* follows the resolved workspace;
|
|
13
|
-
* 2. the
|
|
14
|
+
* 2. the LEARNED root — the owner's `<dataDir>/users/<owner>/skills/`,
|
|
15
|
+
* read from the host filesystem; only for OWNED conversations (an
|
|
16
|
+
* ownerless conversation has no learned root);
|
|
17
|
+
* 3. the USER root — `<configDir>/skills/` (a named config-root entry),
|
|
14
18
|
* read from the host filesystem;
|
|
15
|
-
*
|
|
19
|
+
* 4. PACKAGE roots — skill directories shipped by extension packages
|
|
16
20
|
* (manifest `sigrun.skills`/`pi.skills` dirs and factory-result `skills`
|
|
17
21
|
* dirs, collected by the loader in install order), read from the host
|
|
18
22
|
* filesystem.
|
|
@@ -60,6 +64,21 @@ import { Type } from "@earendil-works/pi-ai";
|
|
|
60
64
|
import { defineExtension, defineTool, section, } from "@earendil-works/pi-durable";
|
|
61
65
|
import { readdirSync, readFileSync } from "node:fs";
|
|
62
66
|
import { join } from "node:path";
|
|
67
|
+
import { overlayForSkill, resolveUpstream, withOverlay } from "../curation/overlays.js";
|
|
68
|
+
import { buildSkillManageTool } from "../curation/skill-tool.js";
|
|
69
|
+
import { SessionMetaDoc } from "../server/session-meta.js";
|
|
70
|
+
/**
|
|
71
|
+
* Resolve a conversation's owner through any `DocumentReader` (curator
|
|
72
|
+
* A3): the section's `PromptInput.read` and the tool's `ToolExecutionApi`
|
|
73
|
+
* both carry one. `undefined` for an ownerless conversation — and for a
|
|
74
|
+
* bare test double without the reader surface (no learned root then).
|
|
75
|
+
*/
|
|
76
|
+
async function conversationOwner(read, conversationId, context) {
|
|
77
|
+
if (typeof read?.snapshot !== "function")
|
|
78
|
+
return undefined;
|
|
79
|
+
const meta = await read.snapshot(SessionMetaDoc, conversationId, context);
|
|
80
|
+
return meta?.owner;
|
|
81
|
+
}
|
|
63
82
|
/** The section key the skills list renders under. */
|
|
64
83
|
export const SKILLS_SECTION_KEY = "skills";
|
|
65
84
|
/** Total rendered-section budget (spec §3.2: 4KB, notice included). */
|
|
@@ -68,8 +87,8 @@ const SKILLS_DIRECTORY = "skills";
|
|
|
68
87
|
const SKILL_FILE = "SKILL.md";
|
|
69
88
|
const FRONTMATTER_DELIMITER = "---";
|
|
70
89
|
const SKILLS_SECTION_HEADER = "Workspace skills. Call the load_skill tool with a skill's name to read its full instructions; each entry shows the skill's path, so you can also read its SKILL.md directly.";
|
|
71
|
-
/** The
|
|
72
|
-
const ROOT_PRECEDENCE = ["workspace", "user dir", "package"];
|
|
90
|
+
/** The discovery roots, in precedence order (§9.4 + curator P2). */
|
|
91
|
+
const ROOT_PRECEDENCE = ["workspace", "learned", "user dir", "package"];
|
|
73
92
|
const encoder = new TextEncoder();
|
|
74
93
|
/** UTF-8 byte length — the unit the section cap is measured in. */
|
|
75
94
|
function byteLength(text) {
|
|
@@ -129,7 +148,7 @@ function parseSkillFile(text) {
|
|
|
129
148
|
* rules with a log. `displayDir` is the path named in the logs and the
|
|
130
149
|
* section entry; `fileLabel` names the file in skip logs.
|
|
131
150
|
*/
|
|
132
|
-
function skillFromFile(text, displayDir, fileLabel) {
|
|
151
|
+
function skillFromFile(text, displayDir, fileLabel, root) {
|
|
133
152
|
const parsed = parseSkillFile(text);
|
|
134
153
|
if (parsed === undefined) {
|
|
135
154
|
console.warn(`skills: skipping ${fileLabel} (the frontmatter block is required)`);
|
|
@@ -149,6 +168,7 @@ function skillFromFile(text, displayDir, fileLabel) {
|
|
|
149
168
|
body: parsed.body,
|
|
150
169
|
dir: displayDir,
|
|
151
170
|
disableModelInvocation: parsed.disableModelInvocation,
|
|
171
|
+
root,
|
|
152
172
|
};
|
|
153
173
|
}
|
|
154
174
|
/** Directory-name comparison (plain code-point order, locale-independent). */
|
|
@@ -179,7 +199,7 @@ async function readSkill(env, dir, context) {
|
|
|
179
199
|
cause: read.error,
|
|
180
200
|
});
|
|
181
201
|
}
|
|
182
|
-
return skillFromFile(read.value, `${SKILLS_DIRECTORY}/${dir.name}`, relative);
|
|
202
|
+
return skillFromFile(read.value, `${SKILLS_DIRECTORY}/${dir.name}`, relative, "workspace");
|
|
183
203
|
}
|
|
184
204
|
/**
|
|
185
205
|
* Scan the workspace's skills through the conversation `ExecutionEnv`.
|
|
@@ -236,7 +256,7 @@ export async function scanSkills(env, context, opts) {
|
|
|
236
256
|
* `disable-model-invocation: true` skills (the `listSkills` path); the
|
|
237
257
|
* default hides them with a log, exactly like the workspace root.
|
|
238
258
|
*/
|
|
239
|
-
function scanFsRoot(root, opts) {
|
|
259
|
+
export function scanFsRoot(root, rootLabel, opts) {
|
|
240
260
|
let entries;
|
|
241
261
|
try {
|
|
242
262
|
entries = readdirSync(root, { withFileTypes: true });
|
|
@@ -263,7 +283,7 @@ function scanFsRoot(root, opts) {
|
|
|
263
283
|
}
|
|
264
284
|
throw new Error(`Failed to read ${file}: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
|
|
265
285
|
}
|
|
266
|
-
const skill = skillFromFile(text, join(root, entry.name), file);
|
|
286
|
+
const skill = skillFromFile(text, join(root, entry.name), file, rootLabel);
|
|
267
287
|
if (skill === undefined)
|
|
268
288
|
continue;
|
|
269
289
|
if (skill.disableModelInvocation && opts?.includeHidden !== true) {
|
|
@@ -320,9 +340,15 @@ export async function discoverSkills(env, context, opts, options) {
|
|
|
320
340
|
if (env !== undefined) {
|
|
321
341
|
merge(await scanSkills(env, context, options), "workspace");
|
|
322
342
|
}
|
|
323
|
-
|
|
343
|
+
// The learned root (curator P2): the owner's own skills, between the
|
|
344
|
+
// workspace and the deployment's user dir. Ownerless → none.
|
|
345
|
+
const learnedRoot = opts.learnedRoot?.(options?.owner);
|
|
346
|
+
if (learnedRoot !== undefined) {
|
|
347
|
+
merge(scanFsRoot(learnedRoot, "learned", options), "learned");
|
|
348
|
+
}
|
|
349
|
+
merge(scanFsRoot(opts.userDir, "user dir", options), "user dir");
|
|
324
350
|
for (const root of opts.packageRoots()) {
|
|
325
|
-
merge(scanFsRoot(root.dir, options), "package", root.extension);
|
|
351
|
+
merge(scanFsRoot(root.dir, "package", options), "package", root.extension);
|
|
326
352
|
}
|
|
327
353
|
return [...byName.values()].map((entry) => entry.skill).sort(bySkillName);
|
|
328
354
|
}
|
|
@@ -333,8 +359,11 @@ export async function discoverSkills(env, context, opts, options) {
|
|
|
333
359
|
* them while the section and `load_skill` keep them hidden. Read LIVE
|
|
334
360
|
* per call (the same posture as the section's per-render scan).
|
|
335
361
|
*/
|
|
336
|
-
export async function listSkills(env, context, opts) {
|
|
337
|
-
return discoverSkills(env, context, opts, {
|
|
362
|
+
export async function listSkills(env, context, opts, options) {
|
|
363
|
+
return discoverSkills(env, context, opts, {
|
|
364
|
+
includeHidden: true,
|
|
365
|
+
...(options?.owner === undefined ? {} : { owner: options.owner }),
|
|
366
|
+
});
|
|
338
367
|
}
|
|
339
368
|
/**
|
|
340
369
|
* Assemble the section text: the header plus one `- name: description
|
|
@@ -373,9 +402,10 @@ export function renderSkillList(skills, limitBytes) {
|
|
|
373
402
|
// rendering — it says skills exist and how many were cut).
|
|
374
403
|
return `(skill list truncated: ${lines.length} more not shown — call load_skill by name)`;
|
|
375
404
|
}
|
|
376
|
-
/** Section render: discover all
|
|
405
|
+
/** Section render: discover all roots, list the winning skills. */
|
|
377
406
|
async function renderSkills(input, context, opts) {
|
|
378
|
-
const
|
|
407
|
+
const owner = await conversationOwner(input.read, input.conversationId, context);
|
|
408
|
+
const skills = await discoverSkills(input.env, context, opts, { owner });
|
|
379
409
|
return renderSkillList(skills, opts.sectionMaxBytes());
|
|
380
410
|
}
|
|
381
411
|
/** An explicit tool error: text content the model can read and recover from. */
|
|
@@ -393,7 +423,8 @@ function buildLoadSkillTool(opts) {
|
|
|
393
423
|
}),
|
|
394
424
|
}),
|
|
395
425
|
async execute(args, api, context) {
|
|
396
|
-
const
|
|
426
|
+
const owner = await conversationOwner(api, api.conversationId, context);
|
|
427
|
+
const skills = await discoverSkills(api.env, context, opts, { owner });
|
|
397
428
|
const skill = skills.find((candidate) => candidate.name === args.name);
|
|
398
429
|
if (skill === undefined) {
|
|
399
430
|
if (skills.length === 0) {
|
|
@@ -402,7 +433,19 @@ function buildLoadSkillTool(opts) {
|
|
|
402
433
|
const available = skills.map((candidate) => candidate.name).join(", ");
|
|
403
434
|
return skillError(`load_skill: unknown skill "${args.name}"; available skills: ${available}`);
|
|
404
435
|
}
|
|
405
|
-
|
|
436
|
+
// Curator A5 (P2): an overlay for this owner rides on the upstream
|
|
437
|
+
// body — upstream, then the heading, then the overlay text. The
|
|
438
|
+
// section is unchanged (the skill lists once, plain).
|
|
439
|
+
const overlay = await overlayForSkill(opts, owner, skill, api.env);
|
|
440
|
+
api.output(overlay === undefined ? skill.body : withOverlay(skill.body, overlay));
|
|
441
|
+
// Curator A6 (P4): a learned-root skill load counts as usage.
|
|
442
|
+
if (skill.root === "learned" && owner !== undefined) {
|
|
443
|
+
const usage = opts.usage?.(owner);
|
|
444
|
+
if (usage !== undefined) {
|
|
445
|
+
usage.bump(skill.name, "load");
|
|
446
|
+
void usage.flush();
|
|
447
|
+
}
|
|
448
|
+
}
|
|
406
449
|
return {};
|
|
407
450
|
},
|
|
408
451
|
});
|
|
@@ -419,6 +462,32 @@ export function createSkillsExtension(opts) {
|
|
|
419
462
|
sections: [
|
|
420
463
|
section(SKILLS_SECTION_KEY, (input, context) => renderSkills(input, context, opts)),
|
|
421
464
|
],
|
|
422
|
-
tools: [
|
|
465
|
+
tools: [
|
|
466
|
+
buildLoadSkillTool(opts),
|
|
467
|
+
// Curator A6 (P3): the skill_manage tool installs once the options
|
|
468
|
+
// carry the curation wiring (a skill-store seam) — the read actions
|
|
469
|
+
// for every owned conversation, the mutating actions for curator
|
|
470
|
+
// runs. The overlay actions resolve the CURRENT upstream through
|
|
471
|
+
// A5's machinery over the same discovery roots (the final review
|
|
472
|
+
// fix wave: hashing the learned root stored `""` for every overlay).
|
|
473
|
+
...(opts.skillStore === undefined
|
|
474
|
+
? []
|
|
475
|
+
: [
|
|
476
|
+
buildSkillManageTool({
|
|
477
|
+
storesOf: (user) => {
|
|
478
|
+
const store = opts.skillStore?.(user);
|
|
479
|
+
const overlays = opts.overlays?.(user);
|
|
480
|
+
return store === undefined || overlays === undefined
|
|
481
|
+
? undefined
|
|
482
|
+
: { store, overlays };
|
|
483
|
+
},
|
|
484
|
+
upstreamOf: (key, env, ctx) => resolveUpstream(key, env, ctx, {
|
|
485
|
+
userDir: opts.userDir,
|
|
486
|
+
packageRoots: opts.packageRoots,
|
|
487
|
+
}),
|
|
488
|
+
workspaceOf: (env) => opts.workspaceRoot?.() ?? env?.cwd,
|
|
489
|
+
}),
|
|
490
|
+
]),
|
|
491
|
+
],
|
|
423
492
|
});
|
|
424
493
|
}
|
|
@@ -5,8 +5,12 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [
|
|
8
|
+
## [0.6.0] - 2026-11-02
|
|
9
9
|
|
|
10
|
+
Version-companion release for sigrun 0.6.0 (no shared changes).
|
|
11
|
+
## [0.5.0] - 2026-11-02
|
|
12
|
+
|
|
13
|
+
Version-companion release for sigrun 0.5.0 (no shared changes).
|
|
10
14
|
## [0.4.2] - 2026-10-31
|
|
11
15
|
|
|
12
16
|
### Fixed
|
|
@@ -60,3 +64,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
60
64
|
conversation/turn shaping, the channel wire types, session-meta,
|
|
61
65
|
commands, interactions, ambient records, access, settings, views,
|
|
62
66
|
view-delta, and jobs — the surfaces the webui, TUI, and server share.
|
|
67
|
+
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
*
|
|
10
10
|
* The rules, in order (first match wins):
|
|
11
11
|
*
|
|
12
|
+
* 0. internal resource → none (curator P5: a conversation created for
|
|
13
|
+
* curator work is invisible to EVERY caller — the superuser included);
|
|
12
14
|
* 1. superuser → write;
|
|
13
15
|
* 2. ownerless resource → household write (everyone);
|
|
14
16
|
* 3. user === owner → write;
|
|
@@ -48,6 +50,7 @@ export interface AccessPrincipal {
|
|
|
48
50
|
export declare function accessOf(p: AccessPrincipal, r: {
|
|
49
51
|
readonly owner?: string;
|
|
50
52
|
readonly sharing?: Sharing;
|
|
53
|
+
readonly internal?: true;
|
|
51
54
|
}): Access;
|
|
52
55
|
/**
|
|
53
56
|
* Type guard for the wire value: every scope shape checked strictly
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
*
|
|
10
10
|
* The rules, in order (first match wins):
|
|
11
11
|
*
|
|
12
|
+
* 0. internal resource → none (curator P5: a conversation created for
|
|
13
|
+
* curator work is invisible to EVERY caller — the superuser included);
|
|
12
14
|
* 1. superuser → write;
|
|
13
15
|
* 2. ownerless resource → household write (everyone);
|
|
14
16
|
* 3. user === owner → write;
|
|
@@ -26,6 +28,12 @@
|
|
|
26
28
|
* module doc; the first matching rule wins.
|
|
27
29
|
*/
|
|
28
30
|
export function accessOf(p, r) {
|
|
31
|
+
// 0. Internal (curator P5): invisible to everyone, the superuser
|
|
32
|
+
// included — BEFORE any other rule can widen access. The marker is
|
|
33
|
+
// server-owned (written once in the creating commit), so no caller,
|
|
34
|
+
// share, or role can ever open an internal resource.
|
|
35
|
+
if (r.internal === true)
|
|
36
|
+
return "none";
|
|
29
37
|
// 1. The superuser always writes.
|
|
30
38
|
if (p.superuser === true)
|
|
31
39
|
return "write";
|
|
@@ -25,10 +25,10 @@ export type { Sharing } from "./access.js";
|
|
|
25
25
|
* `invalid_field`.
|
|
26
26
|
*
|
|
27
27
|
* Server-owned fields (`autoName`, `autoNameAttempts`,
|
|
28
|
-
* `lastActivityAt`, `jobId`, `deliver`) are written by host
|
|
29
|
-
* (activity.ts, the A2 auto-namer, fire.ts's job stamp
|
|
30
|
-
* patch surface — the strict
|
|
31
|
-
* `invalid_field`.
|
|
28
|
+
* `lastActivityAt`, `jobId`, `deliver`, `internal`) are written by host
|
|
29
|
+
* code only (activity.ts, the A2 auto-namer, fire.ts's job stamp, the
|
|
30
|
+
* curator's creating commit); they are NOT patch surface — the strict
|
|
31
|
+
* validator keeps rejecting them as `invalid_field`.
|
|
32
32
|
*/
|
|
33
33
|
/** The per-conversation session metadata (spec §5). */
|
|
34
34
|
export type SessionMeta = {
|
|
@@ -85,6 +85,17 @@ export type SessionMeta = {
|
|
|
85
85
|
* strict validator rejects the key as `invalid_field`.
|
|
86
86
|
*/
|
|
87
87
|
deliver?: string[];
|
|
88
|
+
/**
|
|
89
|
+
* Server-owned internal-run marker (curator P5, spec §6.1): true on a
|
|
90
|
+
* conversation created for curator work — hidden from every list and
|
|
91
|
+
* view, 404 on every `:id` route for every caller (superuser
|
|
92
|
+
* included), never named, never notified, never idle-clocked, and
|
|
93
|
+
* absent from every event surface. Written ONCE by the curator's
|
|
94
|
+
* creating commit (`markInternal`); the flag never changes after
|
|
95
|
+
* creation. Never patchable — the strict validator rejects the key
|
|
96
|
+
* as `invalid_field`.
|
|
97
|
+
*/
|
|
98
|
+
internal?: true;
|
|
88
99
|
/**
|
|
89
100
|
* The §5.9 per-resource sharing state; absent = private (owner and
|
|
90
101
|
* superuser only). Patchable by the OWNER or a superuser (403
|
|
@@ -303,11 +303,11 @@ export interface NotificationsSettings {
|
|
|
303
303
|
readonly runSettled?: "unwatched" | "cron" | "always" | "never";
|
|
304
304
|
}
|
|
305
305
|
/**
|
|
306
|
-
* The built-in extensions toggles: codemode, MCP, tool search
|
|
307
|
-
* ship WITH core. Each key defaults to
|
|
308
|
-
* removes the built-in entirely (absent from
|
|
309
|
-
* ignored with one log line).
|
|
310
|
-
* at boot, like `extensions`.
|
|
306
|
+
* The built-in extensions toggles: codemode, MCP, tool search, the
|
|
307
|
+
* gateway, OAuth and the curator ship WITH core. Each key defaults to
|
|
308
|
+
* `true`; `false` removes the built-in entirely (absent from
|
|
309
|
+
* `/v1/extensions`, its config ignored with one log line).
|
|
310
|
+
* RESTART-REQUIRED: the built-in set resolves at boot, like `extensions`.
|
|
311
311
|
*/
|
|
312
312
|
export interface BuiltinExtensionsSettings {
|
|
313
313
|
readonly codemode?: boolean;
|
|
@@ -317,6 +317,8 @@ export interface BuiltinExtensionsSettings {
|
|
|
317
317
|
readonly gateway?: boolean;
|
|
318
318
|
/** OAuth login providers (multi-user M3b), default true. */
|
|
319
319
|
readonly oauth?: boolean;
|
|
320
|
+
/** Curator (Task B1): the per-user curation loops, default true. */
|
|
321
|
+
readonly curator?: boolean;
|
|
320
322
|
}
|
|
321
323
|
/**
|
|
322
324
|
* The persisted shape: HarnessSettings pass-throughs + sigrun fields.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sigrun/sigrun",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "Self-hosted, multi-user personal-assistant server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./dist/index.js",
|
|
@@ -45,11 +45,12 @@
|
|
|
45
45
|
"@earendil-works/pi-tui": "^1.3.0",
|
|
46
46
|
"@fastify/static": "^10.1.7",
|
|
47
47
|
"@sigrun/ext-codemode": "0.1.2",
|
|
48
|
-
"@sigrun/ext-
|
|
48
|
+
"@sigrun/ext-curator": "0.1.0",
|
|
49
|
+
"@sigrun/ext-gateway": "0.1.10",
|
|
49
50
|
"@sigrun/ext-mcp": "0.2.2",
|
|
50
51
|
"@sigrun/ext-tool-search": "0.1.2",
|
|
51
52
|
"@sigrun/oauth": "0.1.1",
|
|
52
|
-
"@sigrun/shared": "0.
|
|
53
|
+
"@sigrun/shared": "0.6.0",
|
|
53
54
|
"croner": "^10.0.1",
|
|
54
55
|
"fastify": "^5.12.7",
|
|
55
56
|
"semver": "^7.8.5",
|
|
@@ -60,11 +61,12 @@
|
|
|
60
61
|
"@sigrun/shared"
|
|
61
62
|
],
|
|
62
63
|
"optionalDependencies": {
|
|
63
|
-
"@sigrun/sandbox-linux-arm64": "0.
|
|
64
|
-
"@sigrun/sandbox-linux-x64": "0.
|
|
65
|
-
"@sigrun/tui": "0.
|
|
64
|
+
"@sigrun/sandbox-linux-arm64": "0.6.0",
|
|
65
|
+
"@sigrun/sandbox-linux-x64": "0.6.0",
|
|
66
|
+
"@sigrun/tui": "0.6.0"
|
|
66
67
|
},
|
|
67
68
|
"devDependencies": {
|
|
69
|
+
"@sigrun/memory-markdown": "file:../sigrun-memory-markdown",
|
|
68
70
|
"@types/node": "^26.6.4",
|
|
69
71
|
"@types/semver": "^7.8.0",
|
|
70
72
|
"fast-check": "^4.10.2",
|
|
@@ -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>.blk-surface-toast{position:fixed;bottom:1rem;right:1rem}.blk-chat-toast{margin:.25rem 0 0}: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}.ext-surface{flex-direction:column;flex:1;min-width:0;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{overscroll-behavior-x:none;flex:1;min-height:0;padding:28px 24px 8rem;overflow:hidden 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{overflow-wrap:anywhere;background:var(--surface-2);border:1px solid var(--border);border-radius:14px 14px 4px;max-width:min(60ch,100%);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}.entry-blocks{border:1px solid var(--border);border-radius:8px;margin:.5rem 0;padding:.5rem .75rem}.entry-blocks-title{color:var(--muted);margin-bottom:.25rem;font-size:.8rem}.entry-blocks-unknown{font-size:.8rem;font-style:italic}.entry-note summary{cursor:pointer;color:var(--muted);font-size:.8rem}.entry-note-text{color:var(--muted);white-space:pre-wrap;padding:6px 10px;font-size:.8rem}.entry-answer-chip{border:1px solid var(--border);color:var(--muted);border-radius:6px;margin-top:.3rem;padding:.1rem .5rem;font-size:.75rem;display:inline-block}.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-scroll{overscroll-behavior-x:contain;overflow-x:auto}.md-tbl table{border-collapse:collapse;width:100%}.md-tbl th,.md-tbl td{word-break:normal;overflow-wrap:normal}.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:nowrap;align-items:center;gap:4px;min-width:0;display:flex}.composer-toolbar>*{flex-shrink:0}.composer-toolbar>.composer-picker-model{flex-shrink:1;min-width:0}.composer-picker-model .composer-pill{min-width:0;max-width:100%}.composer-pill-label{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}@media (width<=600px){.composer-pill-prefix{display:none}}.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{min-width:0;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{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;padding:6px 8px}.outline-text{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.outline-item[data-clamped=true] .outline-text{-webkit-mask-image:linear-gradient(#000 calc(100% - .7em),#0000);mask-image:linear-gradient(#000 calc(100% - .7em),#0000)}.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%)}.side-drawer[data-open]{transform:translate(0);box-shadow:0 0 32px #00000059}.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}.settings-layout{flex-direction:column;gap:.5rem;padding:.6rem 12px .6rem 16px}.settings-nav{flex-flow:row;gap:.2rem;width:auto;padding-left:0;overflow:auto hidden}.settings-nav .settings-nav-group{flex-direction:row;align-items:center;gap:.2rem}.settings-nav-item{white-space:nowrap;flex:none}.settings-section{padding:0 4px 1.5rem 0;overflow-y:auto}}.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-page{background:var(--bg);flex-direction:column;flex:1;min-width:0;min-height:0;display:flex}.settings-panel{flex-direction:column;flex:1;min-height:0;padding:0;display:flex}.settings-head{border-bottom:1px solid var(--border);background:var(--bg);flex:none;align-items:center;gap:.5rem;height:48px;padding:0 16px 0 24px;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{flex:1;gap:.75rem;min-width:0;min-height:0;padding:.75rem 1rem .75rem 0;display:flex}.settings-nav{flex-direction:column;flex:none;gap:.2rem;width:11rem;padding-left:.5rem;display:flex;overflow-y:auto}.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-nav-group{flex-direction:column;gap:.2rem;display:flex}.settings-section{flex:1;min-width:0;padding:0 1rem 1.5rem .5rem;overflow-y:auto}.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}.token-reveal{border:1px solid color-mix(in srgb, var(--accent) 40%, var(--border))}.token-secret,.token-snippet{font-family:var(--mono);background:var(--bg);border:1px solid var(--border);word-break:break-all;-webkit-user-select:all;user-select:all;border-radius:4px;margin-top:.25rem;padding:.3rem .45rem;font-size:12px;display:block}.token-secret{color:var(--accent)}.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}
|