@covro/covro 0.2.0-beta.1 → 0.2.1-dev.1
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/README.md +21 -9
- package/README.zh-CN.md +21 -9
- package/dist/cli/background.js +103 -0
- package/dist/cli/background.js.map +7 -0
- package/dist/cli/daemon.js +6 -1
- package/dist/cli/daemon.js.map +2 -2
- package/dist/cli/doctor.js +92 -0
- package/dist/cli/doctor.js.map +7 -0
- package/dist/cli/launch-environment.js +85 -0
- package/dist/cli/launch-environment.js.map +7 -0
- package/dist/cli/launchd.js +172 -0
- package/dist/cli/launchd.js.map +7 -0
- package/dist/cli/main.js +7 -35
- package/dist/cli/main.js.map +2 -2
- package/dist/cli/service.js +23 -49
- package/dist/cli/service.js.map +2 -2
- package/dist/codex/adapter.js +68 -1
- package/dist/codex/adapter.js.map +2 -2
- package/dist/server/auth.js +1 -1
- package/dist/server/auth.js.map +2 -2
- package/dist/server/http.js +21 -0
- package/dist/server/http.js.map +2 -2
- package/dist/server/service.js +17 -2
- package/dist/server/service.js.map +2 -2
- package/dist/update-worker.cjs +419 -168
- package/dist/updates/worker.js +7 -61
- package/dist/updates/worker.js.map +2 -2
- package/dist/web/assets/index-BmbPtei8.css +1 -0
- package/dist/web/assets/index-ycdL3pt0.js +140 -0
- package/dist/web/index.html +2 -2
- package/package.json +6 -4
- package/dist/web/assets/index-Dr0Qkixk.css +0 -1
- package/dist/web/assets/index-z5RGzL8u.js +0 -138
package/dist/updates/worker.js
CHANGED
|
@@ -7,77 +7,23 @@ import { execFile } from "node:child_process";
|
|
|
7
7
|
import { promisify } from "node:util";
|
|
8
8
|
import { createRequire } from "node:module";
|
|
9
9
|
import { createHash } from "node:crypto";
|
|
10
|
-
import { access, readFile, mkdir,
|
|
10
|
+
import { access, readFile, mkdir, readdir, rm, rename } from "node:fs/promises";
|
|
11
11
|
import { constants } from "node:fs";
|
|
12
12
|
import { dirname, join } from "node:path";
|
|
13
13
|
import { setTimeout } from "node:timers/promises";
|
|
14
|
-
import { spawn } from "node:child_process";
|
|
15
|
-
import { homedir } from "node:os";
|
|
16
14
|
import lockfile from "proper-lockfile";
|
|
17
|
-
import { control, isNotRunning
|
|
15
|
+
import { control, isNotRunning } from "../cli/control.js";
|
|
16
|
+
import { startBackground, stopBackground } from "../cli/background.js";
|
|
18
17
|
import { copyDurable, readJson, saveJson } from "./files.js";
|
|
19
18
|
import { activateUpdate, transactionPaths } from "./transaction.js";
|
|
20
19
|
import { inspectInstallation, registry } from "./registry.js";
|
|
21
20
|
const exec = promisify(execFile);
|
|
22
21
|
const message = (error) => error instanceof Error ? error.message : String(error);
|
|
23
|
-
async function startService(context
|
|
24
|
-
|
|
25
|
-
join(context.location.state, "service.json")
|
|
26
|
-
);
|
|
27
|
-
if (installed) {
|
|
28
|
-
if (installed.platform === "darwin")
|
|
29
|
-
await exec("launchctl", [
|
|
30
|
-
"bootstrap",
|
|
31
|
-
`gui/${process.getuid()}`,
|
|
32
|
-
join(homedir(), "Library/LaunchAgents", `${installed.label}.plist`)
|
|
33
|
-
]);
|
|
34
|
-
else await exec("systemctl", ["--user", "start", `${installed.label}.service`]);
|
|
35
|
-
} else {
|
|
36
|
-
const log = await open(context.location.log, "a", 384);
|
|
37
|
-
try {
|
|
38
|
-
const child = spawn(
|
|
39
|
-
process.execPath,
|
|
40
|
-
[join(context.root, "bin/covro.mjs"), "run", "--config", context.location.config],
|
|
41
|
-
{
|
|
42
|
-
detached: true,
|
|
43
|
-
stdio: ["ignore", log.fd, log.fd],
|
|
44
|
-
windowsHide: true,
|
|
45
|
-
env: {
|
|
46
|
-
...process.env,
|
|
47
|
-
COVRO_HOME: context.location.home,
|
|
48
|
-
...activation ? { COVRO_ACTIVATING: activation } : {}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
);
|
|
52
|
-
await new Promise((done, reject) => {
|
|
53
|
-
child.once("spawn", done);
|
|
54
|
-
child.once("error", reject);
|
|
55
|
-
});
|
|
56
|
-
child.unref();
|
|
57
|
-
} finally {
|
|
58
|
-
await log.close();
|
|
59
|
-
}
|
|
60
|
-
}
|
|
22
|
+
async function startService(context) {
|
|
23
|
+
await startBackground(context.location, join(context.root, "bin/covro.mjs"));
|
|
61
24
|
}
|
|
62
25
|
async function stopService(context) {
|
|
63
|
-
await
|
|
64
|
-
const installed = await readJson(
|
|
65
|
-
join(context.location.state, "service.json")
|
|
66
|
-
);
|
|
67
|
-
if (installed?.platform === "linux")
|
|
68
|
-
await exec("systemctl", ["--user", "stop", `${installed.label}.service`]);
|
|
69
|
-
else if (installed?.platform === "darwin") {
|
|
70
|
-
const target = `gui/${process.getuid()}/${installed.label}`;
|
|
71
|
-
try {
|
|
72
|
-
await exec("launchctl", ["bootout", target]);
|
|
73
|
-
} catch (error) {
|
|
74
|
-
const stillLoaded = await exec("launchctl", ["print", target]).then(
|
|
75
|
-
() => true,
|
|
76
|
-
() => false
|
|
77
|
-
);
|
|
78
|
-
if (stillLoaded) throw error;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
26
|
+
await stopBackground(context.location);
|
|
81
27
|
}
|
|
82
28
|
async function verifyRestoredService(context, version) {
|
|
83
29
|
for (let attempt = 0; attempt < 240; attempt++) {
|
|
@@ -289,7 +235,7 @@ async function worker(directory) {
|
|
|
289
235
|
},
|
|
290
236
|
stop: () => stopService(context),
|
|
291
237
|
start: async (candidate2) => {
|
|
292
|
-
await startService(context
|
|
238
|
+
await startService(context);
|
|
293
239
|
if (!candidate2) await verifyRestoredService(context, record.from);
|
|
294
240
|
},
|
|
295
241
|
verify: async () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/updates/worker.ts"],
|
|
4
|
-
"sourcesContent": ["import { npmPackageName } from '../shared/package.js';\nimport {\n codexCompatibilitySchema,\n requireCodexCompatibility,\n} from '../shared/codex-compatibility.js';\n// Bundled with its pure JavaScript dependencies and copied outside the installation before launch.\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { createRequire } from 'node:module';\nimport { createHash } from 'node:crypto';\nimport { access, readFile, mkdir, open, readdir, rm, rename } from 'node:fs/promises';\nimport { constants } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { setTimeout } from 'node:timers/promises';\nimport { spawn } from 'node:child_process';\nimport { homedir } from 'node:os';\nimport lockfile from 'proper-lockfile';\nimport type Database from 'better-sqlite3';\nimport type { UpdateRun } from '../shared/updates.js';\nimport type { UpdateContext } from './manager.js';\nimport { control, isNotRunning, stopAndWait } from '../cli/control.js';\nimport { copyDurable, readJson, saveJson } from './files.js';\nimport { activateUpdate, transactionPaths } from './transaction.js';\nimport { inspectInstallation, registry } from './registry.js';\n\nconst exec = promisify(execFile);\nconst message = (error: unknown) => (error instanceof Error ? error.message : String(error));\ntype DaemonStatus = {\n version: string;\n pid: number;\n maintenance?: boolean;\n codexVersion?: string | null;\n codexReady?: boolean;\n};\n\nasync function startService(context: UpdateContext, activation?: string) {\n const installed = await readJson<{ platform: string; label: string }>(\n join(context.location.state, 'service.json'),\n );\n if (installed) {\n // The activation run is durable; a service does not need to inherit transient shell variables.\n if (installed.platform === 'darwin')\n await exec('launchctl', [\n 'bootstrap',\n `gui/${process.getuid!()}`,\n join(homedir(), 'Library/LaunchAgents', `${installed.label}.plist`),\n ]);\n else await exec('systemctl', ['--user', 'start', `${installed.label}.service`]);\n } else {\n const log = await open(context.location.log, 'a', 0o600);\n try {\n const child = spawn(\n process.execPath,\n [join(context.root, 'bin/covro.mjs'), 'run', '--config', context.location.config],\n {\n detached: true,\n stdio: ['ignore', log.fd, log.fd],\n windowsHide: true,\n env: {\n ...process.env,\n COVRO_HOME: context.location.home,\n ...(activation ? { COVRO_ACTIVATING: activation } : {}),\n },\n },\n );\n await new Promise<void>((done, reject) => {\n child.once('spawn', done);\n child.once('error', reject);\n });\n child.unref();\n } finally {\n await log.close();\n }\n }\n}\nasync function stopService(context: UpdateContext) {\n await stopAndWait(context.location);\n const installed = await readJson<{ platform: string; label: string }>(\n join(context.location.state, 'service.json'),\n );\n if (installed?.platform === 'linux')\n await exec('systemctl', ['--user', 'stop', `${installed.label}.service`]);\n else if (installed?.platform === 'darwin') {\n const target = `gui/${process.getuid!()}/${installed.label}`;\n try {\n await exec('launchctl', ['bootout', target]);\n } catch (error) {\n const stillLoaded = await exec('launchctl', ['print', target]).then(\n () => true,\n () => false,\n );\n if (stillLoaded) throw error;\n }\n }\n}\n\nasync function verifyRestoredService(context: UpdateContext, version: string) {\n for (let attempt = 0; attempt < 240; attempt++) {\n try {\n const restored = await control<DaemonStatus>(context.location, 'status');\n if (restored.version !== version || restored.maintenance)\n throw new Error('\u65E7\u7248\u6062\u590D\u8EAB\u4EFD\u4E0D\u5339\u914D');\n return;\n } catch (error) {\n if (attempt === 239) throw error;\n }\n await setTimeout(250);\n }\n}\n\nasync function verifyMigrations(context: UpdateContext, candidate: string) {\n // Loading the existing native addon happens before any package path is replaced.\n const require = createRequire(join(context.root, 'package.json'));\n const Sqlite = require('better-sqlite3') as typeof Database;\n const filename = join(context.dataDir, 'app.sqlite');\n try {\n await access(filename);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return;\n throw error;\n }\n const db = new Sqlite(filename, { readonly: true, fileMustExist: true });\n try {\n const table = db\n .prepare(\"SELECT name FROM sqlite_master WHERE name = '__drizzle_migrations'\")\n .get();\n if (!table) return;\n const applied = db\n .prepare('SELECT hash FROM __drizzle_migrations ORDER BY created_at')\n .all() as { hash: string }[];\n const journal = JSON.parse(\n await readFile(join(candidate, 'dist/drizzle/meta/_journal.json'), 'utf8'),\n ) as { entries: { tag: string }[] };\n const hashes = await Promise.all(\n journal.entries.map(async (entry) => {\n if (!/^[a-zA-Z0-9_-]+$/.test(entry.tag)) throw new Error('\u5019\u9009\u5305\u5305\u542B\u65E0\u6548\u8FC1\u79FB\u8DEF\u5F84');\n return createHash('sha256')\n .update(await readFile(join(candidate, 'dist/drizzle', `${entry.tag}.sql`)))\n .digest('hex');\n }),\n );\n if (applied.some((entry, i) => entry.hash !== hashes[i]))\n throw new Error('\u76EE\u6807\u7248\u672C\u4E0D\u517C\u5BB9\u5F53\u524D\u6570\u636E\u5E93\u8FC1\u79FB\u5386\u53F2\u3002\u8BF7\u7B49\u5F85\u517C\u5BB9\u7248\u672C\uFF0C\u6216\u4F7F\u7528\u72EC\u7ACB\u6D4B\u8BD5\u6570\u636E\u76EE\u5F55\u3002');\n } finally {\n db.close();\n }\n}\n\nasync function worker(directory: string) {\n await mkdir(directory, { recursive: true, mode: 0o700 });\n const release = await lockfile.lock(directory, {\n stale: 10_000,\n update: 2_000,\n retries: { retries: 30, minTimeout: 100, maxTimeout: 500 },\n });\n let record = await readJson<UpdateRun>(join(directory, 'run.json'));\n const context = await readJson<UpdateContext>(join(directory, 'context.json'));\n if (!record || !context) {\n await release();\n throw new Error('\u7F3A\u5C11\u5347\u7EA7\u8BB0\u5F55');\n }\n const update = async (phase: UpdateRun['phase'], detail: string) => {\n record = { ...record!, phase, message: detail, updatedAt: Date.now() };\n await saveJson(join(directory, 'run.json'), record);\n };\n const paths = transactionPaths(\n context.root,\n record.id,\n context.dataDir,\n context.location.config,\n join(directory, `backup-${record.id}`),\n );\n try {\n if (process.argv[3] === '--repair') {\n const active = await control<DaemonStatus>(context.location, 'status').catch(\n (error: unknown) => {\n if (isNotRunning(error)) return undefined;\n throw error;\n },\n );\n if (record.committed) return;\n if (active && !active.maintenance && active.version !== record.from)\n throw new Error('\u5F53\u524D\u670D\u52A1\u53EF\u80FD\u5DF2\u63A5\u53D7\u65B0\u7248\u4E1A\u52A1\u6570\u636E\uFF1B\u62D2\u7EDD\u6062\u590D\u65E7\u5FEB\u7167\uFF0C\u8BF7\u4F7F\u7528\u517C\u5BB9\u7248\u672C\u68C0\u67E5\u3002');\n const previous = await readJson<{ version: string; name: string }>(\n join(paths.previous, 'package.json'),\n );\n if (previous) {\n if (active && !active.maintenance)\n throw new Error('\u65E7\u670D\u52A1\u5DF2\u6062\u590D\u4E1A\u52A1\u5199\u5165\uFF1B\u62D2\u7EDD\u7528\u5347\u7EA7\u524D\u5FEB\u7167\u8986\u76D6\u73B0\u6709\u6570\u636E\uFF0C\u8BF7\u4FDD\u7559\u73B0\u573A\u68C0\u67E5\u3002');\n if (previous.name !== npmPackageName || previous.version !== record.from)\n throw new Error('\u65E7\u7248\u5907\u4EFD\u8EAB\u4EFD\u4E0D\u5339\u914D');\n const snapshot = await readJson<{ complete: boolean }>(join(paths.backup, 'snapshot.json'));\n if (!snapshot?.complete) throw new Error('\u6570\u636E\u5E93\u5907\u4EFD\u4E0D\u5B8C\u6574\uFF0C\u4FDD\u7559\u5168\u90E8\u73B0\u573A\u4F9B\u68C0\u67E5');\n } else {\n const original = await readJson<{ name: string; version: string }>(\n join(paths.root, 'package.json'),\n );\n if (original?.name !== npmPackageName || original.version !== record.from)\n throw new Error('\u672A\u627E\u5230\u5B8C\u6574\u7684\u4E0A\u4E00\u7248\u672C\u5B89\u88C5');\n }\n if (active && !active.maintenance) {\n const admission = await control<{ ready: boolean }>(context.location, 'prepare-update');\n if (!admission.ready) throw new Error('\u4ECD\u6709\u4EFB\u52A1\u3001\u5BA1\u6279\u6216\u5F85\u6838\u5BF9\u64CD\u4F5C\uFF0C\u4E0D\u80FD\u6062\u590D\u65E7\u5B89\u88C5');\n }\n await stopService(context);\n if (previous) {\n await rm(paths.root, { recursive: true, force: true });\n await rename(paths.previous, paths.root);\n for (const name of ['app.sqlite', 'app.sqlite-wal', 'app.sqlite-shm']) {\n await rm(join(paths.dataDir, name), { force: true });\n try {\n await copyDurable(join(paths.backup, name), join(paths.dataDir, name));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n }\n await copyDurable(join(paths.backup, 'config.json'), paths.config);\n }\n const restored = await readJson<{ name: string; version: string }>(\n join(paths.root, 'package.json'),\n );\n if (restored?.name !== npmPackageName || restored.version !== record.from)\n throw new Error('\u672A\u627E\u5230\u5B8C\u6574\u7684\u4E0A\u4E00\u7248\u672C\u5B89\u88C5');\n await update('rolledBack', '\u5DF2\u6062\u590D\u4E0A\u6B21\u672A\u5B8C\u6210\u7684\u5347\u7EA7\uFF0C\u6B63\u5728\u542F\u52A8\u4E0A\u4E00\u7248\u672C');\n try {\n await startService(context);\n await verifyRestoredService(context, record.from);\n await update('rolledBack', '\u5DF2\u6062\u590D\u4E0A\u6B21\u672A\u5B8C\u6210\u7684\u5347\u7EA7\uFF0C\u4E0A\u4E00\u7248\u672C\u5DF2\u5C31\u7EEA');\n } catch (error) {\n await update('failed', `\u65E7\u7248\u6062\u590D\u542F\u52A8\u5931\u8D25\uFF0C\u4FDD\u7559\u5907\u4EFD\uFF1A${message(error)}`);\n throw error;\n }\n return;\n }\n const reason = await inspectInstallation(context.root);\n if (reason) throw new Error(reason);\n // A second managed configuration must be stopped before replacing their shared npm package.\n for (const key of await readdir(join(context.location.home, 'instances'))) {\n if (key === context.location.key) continue;\n const instance = await readJson<{ root: string; config: string; socket: string }>(\n join(context.location.home, 'instances', key, 'instance.json'),\n );\n if (instance?.root !== context.root) continue;\n try {\n await control({ ...context.location, socket: instance.socket }, 'status');\n throw new Error('\u540C\u4E00 npm \u5B89\u88C5\u8FD8\u6709\u5176\u4ED6 Covro \u5B9E\u4F8B\uFF0C\u8BF7\u5148\u505C\u6B62\u5176\u4ED6\u5B9E\u4F8B\u518D\u5347\u7EA7\u3002');\n } catch (error) {\n if (!isNotRunning(error)) throw error;\n }\n }\n await access(dirname(context.root), constants.W_OK);\n // npm global layout keeps production dependencies nested in the package being swapped.\n await exec(\n 'npm',\n [\n 'install',\n '--global',\n '--prefix',\n paths.prefix,\n '--omit=dev',\n '--no-audit',\n '--no-fund',\n `--registry=${registry}`,\n '--allow-scripts=better-sqlite3',\n `${npmPackageName}@${record.target}`,\n ],\n { timeout: 10 * 60_000, maxBuffer: 2 * 1024 * 1024 },\n );\n const candidate = await readJson<{ name: string; version: string; covroCodex?: unknown }>(\n join(paths.candidate, 'package.json'),\n );\n if (candidate?.name !== npmPackageName || candidate.version !== record.target)\n throw new Error('\u5019\u9009\u5305\u8EAB\u4EFD\u6216\u7248\u672C\u4E0D\u5339\u914D');\n if (!record.codex) throw new Error('\u7F3A\u5C11 Codex \u5347\u7EA7\u6821\u9A8C\u8BB0\u5F55\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0');\n const manifest = codexCompatibilitySchema.parse(candidate.covroCodex);\n if (JSON.stringify(manifest) !== JSON.stringify(record.codex.manifest))\n throw new Error('\u5019\u9009\u5305\u7684 Codex \u517C\u5BB9\u58F0\u660E\u4E0E\u68C0\u67E5\u65F6\u4E0D\u4E00\u81F4\uFF0C\u62D2\u7EDD\u5207\u6362');\n const checkCodex = async (current?: DaemonStatus) => {\n const state = current ?? (await control<DaemonStatus>(context.location, 'status'));\n if (state.codexVersion !== record!.codex!.version)\n throw new Error('Codex \u7248\u672C\u5728\u7B49\u5F85\u5347\u7EA7\u671F\u95F4\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0');\n requireCodexCompatibility(\n manifest,\n state.codexVersion ?? null,\n record!.codex!.confirmedUnverified,\n );\n };\n await checkCodex();\n await exec(process.execPath, [join(paths.candidate, 'bin/covro.mjs'), '--version'], {\n timeout: 30_000,\n });\n const nativeProbe =\n 'const {createRequire}=await import(\"node:module\"); const r=createRequire(process.argv[1]); const DB=r(\"better-sqlite3\"); const db=new DB(\":memory:\"); db.close();';\n await exec(\n process.execPath,\n ['--input-type=module', '-e', nativeProbe, join(paths.candidate, 'package.json')],\n { timeout: 30_000 },\n );\n await verifyMigrations(context, paths.candidate);\n await activateUpdate(paths, {\n phase: update,\n waitForIdle: async () => {\n // Queue without blocking normal work; admission closes atomically only after all blockers clear.\n for (;;) {\n await checkCodex();\n const result = await control<{ ready: boolean; reason?: string }>(\n context.location,\n 'prepare-update',\n );\n if (result.ready) {\n await checkCodex();\n return;\n }\n await update('waiting', result.reason ?? '\u7B49\u5F85\u6240\u6709\u4EFB\u52A1\u7ED3\u675F');\n await setTimeout(2_000);\n }\n },\n stop: () => stopService(context),\n start: async (candidate) => {\n await startService(context, candidate ? record!.id : undefined);\n if (!candidate) await verifyRestoredService(context, record!.from);\n },\n verify: async () => {\n for (let attempt = 0; attempt < 240; attempt++) {\n const current = await control<DaemonStatus>(context.location, 'status').catch(\n () => undefined,\n );\n if (current) {\n if (current.version !== record!.target || !current.maintenance)\n throw new Error('\u65B0\u7248\u670D\u52A1\u8EAB\u4EFD\u6216\u7EF4\u62A4\u72B6\u6001\u4E0D\u5339\u914D');\n await checkCodex(current);\n if (current.codexReady) return;\n }\n await setTimeout(250);\n }\n throw new Error('\u65B0\u7248\u670D\u52A1\u6216 Codex \u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u62D2\u7EDD\u6FC0\u6D3B');\n },\n commit: async () => {\n // Gateway commits the durable result before reopening task admission.\n await control(context.location, 'activate-update', {\n id: record!.id,\n channel: record!.channel,\n });\n const final = await readJson<UpdateRun>(join(directory, 'run.json'));\n if (!final?.committed) throw new Error('\u65B0\u7248\u5C1A\u672A\u786E\u8BA4\u5347\u7EA7\u63D0\u4EA4');\n record = final;\n },\n hasCommitted: async () =>\n Boolean((await readJson<UpdateRun>(join(directory, 'run.json')))?.committed),\n resume: async () => {\n await control(context.location, 'cancel-update').catch(() => {});\n },\n });\n } catch (error) {\n const latest = await readJson<UpdateRun>(join(directory, 'run.json'));\n if (latest?.committed) {\n // A lost commit response cannot authorize restoring older data.\n record = latest;\n } else if (!['rolledBack', 'failed'].includes(record.phase))\n await update('failed', message(error));\n console.error(message(error));\n process.exitCode = record.committed || record.phase === 'rolledBack' ? 0 : 1;\n } finally {\n await release();\n // Keep the last good installation and database backup for explicit recovery.\n if (record.phase === 'succeeded' || record.phase === 'rolledBack') {\n await rm(paths.prefix, { recursive: true, force: true });\n }\n }\n}\n\nif (process.argv[2])\n void worker(process.argv[2]).catch((error: unknown) => {\n console.error(message(error));\n process.exitCode = 1;\n });\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,sBAAsB;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEP,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAC1B,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAC3B,SAAS,QAAQ,UAAU,OAAO,
|
|
4
|
+
"sourcesContent": ["import { npmPackageName } from '../shared/package.js';\nimport {\n codexCompatibilitySchema,\n requireCodexCompatibility,\n} from '../shared/codex-compatibility.js';\n// Bundled with its pure JavaScript dependencies and copied outside the installation before launch.\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { createRequire } from 'node:module';\nimport { createHash } from 'node:crypto';\nimport { access, readFile, mkdir, readdir, rm, rename } from 'node:fs/promises';\nimport { constants } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { setTimeout } from 'node:timers/promises';\nimport lockfile from 'proper-lockfile';\nimport type Database from 'better-sqlite3';\nimport type { UpdateRun } from '../shared/updates.js';\nimport type { UpdateContext } from './manager.js';\nimport { control, isNotRunning } from '../cli/control.js';\nimport { startBackground, stopBackground } from '../cli/background.js';\nimport { copyDurable, readJson, saveJson } from './files.js';\nimport { activateUpdate, transactionPaths } from './transaction.js';\nimport { inspectInstallation, registry } from './registry.js';\n\nconst exec = promisify(execFile);\nconst message = (error: unknown) => (error instanceof Error ? error.message : String(error));\ntype DaemonStatus = {\n version: string;\n pid: number;\n maintenance?: boolean;\n codexVersion?: string | null;\n codexReady?: boolean;\n};\n\nasync function startService(context: UpdateContext) {\n // Shared with `covro start`: never inherit a Background security session on macOS.\n // Activation is checked from the durable update record by the daemon.\n await startBackground(context.location, join(context.root, 'bin/covro.mjs'));\n}\nasync function stopService(context: UpdateContext) {\n await stopBackground(context.location);\n}\n\nasync function verifyRestoredService(context: UpdateContext, version: string) {\n for (let attempt = 0; attempt < 240; attempt++) {\n try {\n const restored = await control<DaemonStatus>(context.location, 'status');\n if (restored.version !== version || restored.maintenance)\n throw new Error('\u65E7\u7248\u6062\u590D\u8EAB\u4EFD\u4E0D\u5339\u914D');\n return;\n } catch (error) {\n if (attempt === 239) throw error;\n }\n await setTimeout(250);\n }\n}\n\nasync function verifyMigrations(context: UpdateContext, candidate: string) {\n // Loading the existing native addon happens before any package path is replaced.\n const require = createRequire(join(context.root, 'package.json'));\n const Sqlite = require('better-sqlite3') as typeof Database;\n const filename = join(context.dataDir, 'app.sqlite');\n try {\n await access(filename);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return;\n throw error;\n }\n const db = new Sqlite(filename, { readonly: true, fileMustExist: true });\n try {\n const table = db\n .prepare(\"SELECT name FROM sqlite_master WHERE name = '__drizzle_migrations'\")\n .get();\n if (!table) return;\n const applied = db\n .prepare('SELECT hash FROM __drizzle_migrations ORDER BY created_at')\n .all() as { hash: string }[];\n const journal = JSON.parse(\n await readFile(join(candidate, 'dist/drizzle/meta/_journal.json'), 'utf8'),\n ) as { entries: { tag: string }[] };\n const hashes = await Promise.all(\n journal.entries.map(async (entry) => {\n if (!/^[a-zA-Z0-9_-]+$/.test(entry.tag)) throw new Error('\u5019\u9009\u5305\u5305\u542B\u65E0\u6548\u8FC1\u79FB\u8DEF\u5F84');\n return createHash('sha256')\n .update(await readFile(join(candidate, 'dist/drizzle', `${entry.tag}.sql`)))\n .digest('hex');\n }),\n );\n if (applied.some((entry, i) => entry.hash !== hashes[i]))\n throw new Error('\u76EE\u6807\u7248\u672C\u4E0D\u517C\u5BB9\u5F53\u524D\u6570\u636E\u5E93\u8FC1\u79FB\u5386\u53F2\u3002\u8BF7\u7B49\u5F85\u517C\u5BB9\u7248\u672C\uFF0C\u6216\u4F7F\u7528\u72EC\u7ACB\u6D4B\u8BD5\u6570\u636E\u76EE\u5F55\u3002');\n } finally {\n db.close();\n }\n}\n\nasync function worker(directory: string) {\n await mkdir(directory, { recursive: true, mode: 0o700 });\n const release = await lockfile.lock(directory, {\n stale: 10_000,\n update: 2_000,\n retries: { retries: 30, minTimeout: 100, maxTimeout: 500 },\n });\n let record = await readJson<UpdateRun>(join(directory, 'run.json'));\n const context = await readJson<UpdateContext>(join(directory, 'context.json'));\n if (!record || !context) {\n await release();\n throw new Error('\u7F3A\u5C11\u5347\u7EA7\u8BB0\u5F55');\n }\n const update = async (phase: UpdateRun['phase'], detail: string) => {\n record = { ...record!, phase, message: detail, updatedAt: Date.now() };\n await saveJson(join(directory, 'run.json'), record);\n };\n const paths = transactionPaths(\n context.root,\n record.id,\n context.dataDir,\n context.location.config,\n join(directory, `backup-${record.id}`),\n );\n try {\n if (process.argv[3] === '--repair') {\n const active = await control<DaemonStatus>(context.location, 'status').catch(\n (error: unknown) => {\n if (isNotRunning(error)) return undefined;\n throw error;\n },\n );\n if (record.committed) return;\n if (active && !active.maintenance && active.version !== record.from)\n throw new Error('\u5F53\u524D\u670D\u52A1\u53EF\u80FD\u5DF2\u63A5\u53D7\u65B0\u7248\u4E1A\u52A1\u6570\u636E\uFF1B\u62D2\u7EDD\u6062\u590D\u65E7\u5FEB\u7167\uFF0C\u8BF7\u4F7F\u7528\u517C\u5BB9\u7248\u672C\u68C0\u67E5\u3002');\n const previous = await readJson<{ version: string; name: string }>(\n join(paths.previous, 'package.json'),\n );\n if (previous) {\n if (active && !active.maintenance)\n throw new Error('\u65E7\u670D\u52A1\u5DF2\u6062\u590D\u4E1A\u52A1\u5199\u5165\uFF1B\u62D2\u7EDD\u7528\u5347\u7EA7\u524D\u5FEB\u7167\u8986\u76D6\u73B0\u6709\u6570\u636E\uFF0C\u8BF7\u4FDD\u7559\u73B0\u573A\u68C0\u67E5\u3002');\n if (previous.name !== npmPackageName || previous.version !== record.from)\n throw new Error('\u65E7\u7248\u5907\u4EFD\u8EAB\u4EFD\u4E0D\u5339\u914D');\n const snapshot = await readJson<{ complete: boolean }>(join(paths.backup, 'snapshot.json'));\n if (!snapshot?.complete) throw new Error('\u6570\u636E\u5E93\u5907\u4EFD\u4E0D\u5B8C\u6574\uFF0C\u4FDD\u7559\u5168\u90E8\u73B0\u573A\u4F9B\u68C0\u67E5');\n } else {\n const original = await readJson<{ name: string; version: string }>(\n join(paths.root, 'package.json'),\n );\n if (original?.name !== npmPackageName || original.version !== record.from)\n throw new Error('\u672A\u627E\u5230\u5B8C\u6574\u7684\u4E0A\u4E00\u7248\u672C\u5B89\u88C5');\n }\n if (active && !active.maintenance) {\n const admission = await control<{ ready: boolean }>(context.location, 'prepare-update');\n if (!admission.ready) throw new Error('\u4ECD\u6709\u4EFB\u52A1\u3001\u5BA1\u6279\u6216\u5F85\u6838\u5BF9\u64CD\u4F5C\uFF0C\u4E0D\u80FD\u6062\u590D\u65E7\u5B89\u88C5');\n }\n await stopService(context);\n if (previous) {\n await rm(paths.root, { recursive: true, force: true });\n await rename(paths.previous, paths.root);\n for (const name of ['app.sqlite', 'app.sqlite-wal', 'app.sqlite-shm']) {\n await rm(join(paths.dataDir, name), { force: true });\n try {\n await copyDurable(join(paths.backup, name), join(paths.dataDir, name));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n }\n await copyDurable(join(paths.backup, 'config.json'), paths.config);\n }\n const restored = await readJson<{ name: string; version: string }>(\n join(paths.root, 'package.json'),\n );\n if (restored?.name !== npmPackageName || restored.version !== record.from)\n throw new Error('\u672A\u627E\u5230\u5B8C\u6574\u7684\u4E0A\u4E00\u7248\u672C\u5B89\u88C5');\n await update('rolledBack', '\u5DF2\u6062\u590D\u4E0A\u6B21\u672A\u5B8C\u6210\u7684\u5347\u7EA7\uFF0C\u6B63\u5728\u542F\u52A8\u4E0A\u4E00\u7248\u672C');\n try {\n await startService(context);\n await verifyRestoredService(context, record.from);\n await update('rolledBack', '\u5DF2\u6062\u590D\u4E0A\u6B21\u672A\u5B8C\u6210\u7684\u5347\u7EA7\uFF0C\u4E0A\u4E00\u7248\u672C\u5DF2\u5C31\u7EEA');\n } catch (error) {\n await update('failed', `\u65E7\u7248\u6062\u590D\u542F\u52A8\u5931\u8D25\uFF0C\u4FDD\u7559\u5907\u4EFD\uFF1A${message(error)}`);\n throw error;\n }\n return;\n }\n const reason = await inspectInstallation(context.root);\n if (reason) throw new Error(reason);\n // A second managed configuration must be stopped before replacing their shared npm package.\n for (const key of await readdir(join(context.location.home, 'instances'))) {\n if (key === context.location.key) continue;\n const instance = await readJson<{ root: string; config: string; socket: string }>(\n join(context.location.home, 'instances', key, 'instance.json'),\n );\n if (instance?.root !== context.root) continue;\n try {\n await control({ ...context.location, socket: instance.socket }, 'status');\n throw new Error('\u540C\u4E00 npm \u5B89\u88C5\u8FD8\u6709\u5176\u4ED6 Covro \u5B9E\u4F8B\uFF0C\u8BF7\u5148\u505C\u6B62\u5176\u4ED6\u5B9E\u4F8B\u518D\u5347\u7EA7\u3002');\n } catch (error) {\n if (!isNotRunning(error)) throw error;\n }\n }\n await access(dirname(context.root), constants.W_OK);\n // npm global layout keeps production dependencies nested in the package being swapped.\n await exec(\n 'npm',\n [\n 'install',\n '--global',\n '--prefix',\n paths.prefix,\n '--omit=dev',\n '--no-audit',\n '--no-fund',\n `--registry=${registry}`,\n '--allow-scripts=better-sqlite3',\n `${npmPackageName}@${record.target}`,\n ],\n { timeout: 10 * 60_000, maxBuffer: 2 * 1024 * 1024 },\n );\n const candidate = await readJson<{ name: string; version: string; covroCodex?: unknown }>(\n join(paths.candidate, 'package.json'),\n );\n if (candidate?.name !== npmPackageName || candidate.version !== record.target)\n throw new Error('\u5019\u9009\u5305\u8EAB\u4EFD\u6216\u7248\u672C\u4E0D\u5339\u914D');\n if (!record.codex) throw new Error('\u7F3A\u5C11 Codex \u5347\u7EA7\u6821\u9A8C\u8BB0\u5F55\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0');\n const manifest = codexCompatibilitySchema.parse(candidate.covroCodex);\n if (JSON.stringify(manifest) !== JSON.stringify(record.codex.manifest))\n throw new Error('\u5019\u9009\u5305\u7684 Codex \u517C\u5BB9\u58F0\u660E\u4E0E\u68C0\u67E5\u65F6\u4E0D\u4E00\u81F4\uFF0C\u62D2\u7EDD\u5207\u6362');\n const checkCodex = async (current?: DaemonStatus) => {\n const state = current ?? (await control<DaemonStatus>(context.location, 'status'));\n if (state.codexVersion !== record!.codex!.version)\n throw new Error('Codex \u7248\u672C\u5728\u7B49\u5F85\u5347\u7EA7\u671F\u95F4\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0');\n requireCodexCompatibility(\n manifest,\n state.codexVersion ?? null,\n record!.codex!.confirmedUnverified,\n );\n };\n await checkCodex();\n await exec(process.execPath, [join(paths.candidate, 'bin/covro.mjs'), '--version'], {\n timeout: 30_000,\n });\n const nativeProbe =\n 'const {createRequire}=await import(\"node:module\"); const r=createRequire(process.argv[1]); const DB=r(\"better-sqlite3\"); const db=new DB(\":memory:\"); db.close();';\n await exec(\n process.execPath,\n ['--input-type=module', '-e', nativeProbe, join(paths.candidate, 'package.json')],\n { timeout: 30_000 },\n );\n await verifyMigrations(context, paths.candidate);\n await activateUpdate(paths, {\n phase: update,\n waitForIdle: async () => {\n // Queue without blocking normal work; admission closes atomically only after all blockers clear.\n for (;;) {\n await checkCodex();\n const result = await control<{ ready: boolean; reason?: string }>(\n context.location,\n 'prepare-update',\n );\n if (result.ready) {\n await checkCodex();\n return;\n }\n await update('waiting', result.reason ?? '\u7B49\u5F85\u6240\u6709\u4EFB\u52A1\u7ED3\u675F');\n await setTimeout(2_000);\n }\n },\n stop: () => stopService(context),\n start: async (candidate) => {\n await startService(context);\n if (!candidate) await verifyRestoredService(context, record!.from);\n },\n verify: async () => {\n for (let attempt = 0; attempt < 240; attempt++) {\n const current = await control<DaemonStatus>(context.location, 'status').catch(\n () => undefined,\n );\n if (current) {\n if (current.version !== record!.target || !current.maintenance)\n throw new Error('\u65B0\u7248\u670D\u52A1\u8EAB\u4EFD\u6216\u7EF4\u62A4\u72B6\u6001\u4E0D\u5339\u914D');\n await checkCodex(current);\n if (current.codexReady) return;\n }\n await setTimeout(250);\n }\n throw new Error('\u65B0\u7248\u670D\u52A1\u6216 Codex \u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u62D2\u7EDD\u6FC0\u6D3B');\n },\n commit: async () => {\n // Gateway commits the durable result before reopening task admission.\n await control(context.location, 'activate-update', {\n id: record!.id,\n channel: record!.channel,\n });\n const final = await readJson<UpdateRun>(join(directory, 'run.json'));\n if (!final?.committed) throw new Error('\u65B0\u7248\u5C1A\u672A\u786E\u8BA4\u5347\u7EA7\u63D0\u4EA4');\n record = final;\n },\n hasCommitted: async () =>\n Boolean((await readJson<UpdateRun>(join(directory, 'run.json')))?.committed),\n resume: async () => {\n await control(context.location, 'cancel-update').catch(() => {});\n },\n });\n } catch (error) {\n const latest = await readJson<UpdateRun>(join(directory, 'run.json'));\n if (latest?.committed) {\n // A lost commit response cannot authorize restoring older data.\n record = latest;\n } else if (!['rolledBack', 'failed'].includes(record.phase))\n await update('failed', message(error));\n console.error(message(error));\n process.exitCode = record.committed || record.phase === 'rolledBack' ? 0 : 1;\n } finally {\n await release();\n // Keep the last good installation and database backup for explicit recovery.\n if (record.phase === 'succeeded' || record.phase === 'rolledBack') {\n await rm(paths.prefix, { recursive: true, force: true });\n }\n }\n}\n\nif (process.argv[2])\n void worker(process.argv[2]).catch((error: unknown) => {\n console.error(message(error));\n process.exitCode = 1;\n });\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["require", "candidate"]
|
|
7
7
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.collapsible-activity{--activity-sticky-offset:var(--conversation-sticky-offset,0px);--activity-surface:#fbfcfb;overflow:clip}.collapsible-activity.activity-failed{--activity-surface:#fff5f3}.collapsible-activity>summary{background:var(--activity-surface);border-radius:6px}.collapsible-activity[open]>summary{top:var(--activity-sticky-offset);z-index:1;border-bottom-right-radius:0;border-bottom-left-radius:0;position:sticky;box-shadow:0 1px #e8ebea}.collapsible-activity>summary:focus-visible{outline:2px solid var(--accent);outline-offset:-3px}.activity-collapse-hint{flex-shrink:0;font-size:10px;display:none}.collapsible-activity[open]>summary>.activity-collapse-hint{display:inline}.collapsible-activity-group{--activity-group-header-height:44px}.collapsible-activity-group>summary{min-height:44px}.collapsible-activity-group[open]>summary{z-index:2}.collapsible-activity-group .collapsible-activity{--activity-sticky-offset:calc(var(--conversation-sticky-offset,0px) + var(--activity-group-header-height))}.activity-group{--activity-surface:#f5f8f6;background:#fbfcfb;border:1px solid #e8ebea;border-radius:7px;min-width:0;margin:10px 0}.activity-group>summary{color:#7b8780;background:#f5f8f6;align-items:center;gap:8px;padding:11px 12px;font-size:11px;list-style:none;display:flex}.activity-group>summary>svg{flex-shrink:0}.activity-group>summary::-webkit-details-marker{display:none}.auto-review-card>summary::-webkit-details-marker{display:none}.activity-group[open]>summary>svg:last-child,.auto-review-card[open]>summary>svg:last-child{transform:rotate(90deg)}.activity-group>summary .activity-description{flex:1}.activity-group-reviews{color:#7b8780;flex-shrink:0;font-size:10px}.activity-group-status{color:#7b8780;flex-wrap:wrap;flex-shrink:0;justify-content:flex-end;gap:3px 8px;max-width:55%;font-size:10px;display:flex}.activity-group-status>span{white-space:nowrap}.activity-group-running{color:#55785f;font-weight:600}.activity-group-problem{color:var(--destructive);font-weight:600}.activity-group-attention{color:#8b6726;font-weight:600}.activity-group-items{border-top:1px solid #e8ebea;min-width:0;padding:1px 10px}.activity-group-items>.activity,.activity-group-items>.auto-review-card{margin:9px 0}.auto-review-card.collapsible-activity{--activity-surface:#fafcfb;padding:0}.auto-review-card.auto-review-inProgress,.auto-review-card.auto-review-timedOut{--activity-surface:#fdfbf5}.auto-review-card.auto-review-denied{--activity-surface:#fff6f4}.auto-review-card.collapsible-activity>summary{min-height:44px;color:inherit;align-items:center;gap:8px;padding:11px 12px;font-size:11px;list-style:none;display:flex}.auto-review-card.collapsible-activity .activity-description{flex:1}.auto-review-card.auto-review-denied>summary{color:#ae4c42}.auto-review-card.auto-review-inProgress>summary,.auto-review-card.auto-review-timedOut>summary{color:#8f7135}.auto-review-body{font-size:11px}@media (width<=760px){.activity-group-reviews,.activity-group>summary .command-summary{display:none}.activity-group>summary{gap:6px}.activity-group-status{gap:2px 6px;max-width:58%;font-size:9px}.activity-group-items{padding-inline:6px}}.shell-panel{border-top:1px solid var(--border);background:var(--surface,#fff);flex-direction:column;flex:none;min-height:0;max-height:60dvh;display:flex}.main-panel.shell-visible{overflow:hidden}.main-panel.shell-visible .conversation-area{min-height:0}.main-panel.shell-visible>.bottom-region{flex-shrink:1;min-height:0;max-height:22dvh}.main-panel.shell-visible .composer-box textarea{--composer-min-height:48px;--composer-max-height:90px;padding-top:9px}.shell-header{flex-shrink:0}.shell-header,.shell-heading,.shell-actions,.shell-result-toolbar,.shell-submit-row{align-items:center;gap:10px;display:flex}.shell-header{justify-content:space-between;padding:7px 24px}.shell-heading{min-width:0;font-size:12px}.shell-heading>span{text-overflow:ellipsis;white-space:nowrap;color:#737d87;overflow:hidden}.shell-heading .shell-running{color:#25724b;flex-shrink:0}.shell-body{flex:1;min-height:0;padding:0 24px 14px;overflow:auto}.shell-location{color:#737d87;align-items:baseline;gap:10px;font-size:11px;display:flex}.shell-location>span{flex-shrink:0}.shell-location code{overflow-wrap:anywhere;color:#3f4c58}.shell-help,.shell-collapsed-note,.shell-background{color:#737d87;margin:6px 0 10px;font-size:11px;line-height:1.6}.shell-collapsed-note{margin:-3px 24px 8px}.shell-background{color:#2f7255}.shell-warning{color:#975327;overflow-wrap:anywhere;background:#fff6e9;border-radius:6px;margin:6px 0;padding:7px 10px;font-size:12px;line-height:1.6}.shell-result{border:1px solid #dce2e5;border-radius:8px;overflow:hidden}.shell-result-toolbar{background:#f5f7f8;justify-content:space-between;padding:5px 10px}.shell-result-toolbar label{color:#737d87;flex:1;align-items:center;gap:8px;min-width:0;font-size:10px;display:flex}.shell-result-toolbar select{color:#3f4c58;min-width:0;max-width:100%;font:inherit;background:0 0;border:0;flex:1;padding:4px;font-size:11px}.shell-result-toolbar button{flex-shrink:0}.shell-command-line{color:#e2eaf0;background:#18212b;gap:10px;padding:10px 12px 0;font-size:12px;display:flex}.shell-command-line>span{color:#81c9a1}.shell-command-line code{white-space:pre-wrap;overflow-wrap:anywhere}.shell-output{color:#e2eaf0;white-space:pre-wrap;overflow-wrap:anywhere;background:#18212b;height:110px;margin:0;padding:10px 12px 16px;font:12px/1.6 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;overflow:auto}.shell-stderr{color:#ffb6a9}.shell-output-empty{color:#9aaaba}.shell-result-status{color:#3f6b52;background:#f5f7f8;flex-wrap:wrap;gap:14px;padding:6px 12px;font-size:11px;display:flex}.shell-status-failed,.shell-status-unknown{color:#a94f35}.shell-empty{text-align:center;color:#737d87;padding:20px 12px;font-size:12px}.shell-empty p{margin:7px 0}.shell-empty>span{font-size:11px}.shell-form{margin-top:10px}.shell-form textarea{box-sizing:border-box;resize:vertical;color:#28333d;background:#fff;border:1px solid #dce2e5;border-radius:7px;width:100%;max-height:120px;padding:9px 11px;font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;display:block}.shell-form textarea:focus{outline-offset:1px;outline:2px solid #8ba99a}.shell-submit-row{justify-content:space-between;margin-top:7px}.shell-submit-row>span{color:#737d87;font-size:10px}.shell-entry{gap:5px}.shell-entry-count{color:#2d6d48;background:#e5f2e9;border-radius:8px;padding:0 5px}.topbar{position:relative}.topbar .diagnostics-panel{top:calc(100% - 6px)}@media (width<=760px){.main-panel.shell-visible>.bottom-region{display:none}.shell-panel{max-height:70dvh}.shell-header{padding:5px 12px}.shell-body{padding:0 12px 10px}.shell-collapsed-note{margin-left:12px}.shell-output{height:110px}.shell-submit-row{gap:6px}.shell-submit-row>span{max-width:58%;line-height:1.5}.shell-entry{padding:6px}}:root{color:#252b32;font-synthesis:none;--border:#e6e8eb;--muted:#7b838c;--accent:#13765d;--accent-soft:#eaf4ef;--sidebar:#f7f8fa;--destructive:#ae3e39;background:#fff;font-family:DM Sans,-apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,Microsoft YaHei,sans-serif}*{box-sizing:border-box}body{margin:0}button,input,textarea,select{font:inherit}button,summary,select{-webkit-tap-highlight-color:transparent}button,select,summary{cursor:pointer}button:disabled,select:disabled{cursor:not-allowed;opacity:.5}button,input,textarea,select,summary,a{outline-offset:3px}:focus-visible{outline:2px solid #18866b}a{color:var(--accent);text-underline-offset:3px}p{line-height:1.7}h1,h2,h3,p{margin-top:0}pre,code,.mono{font-family:SFMono-Regular,Consolas,Liberation Mono,monospace}pre{white-space:pre-wrap;overflow-wrap:anywhere;font-size:12px;line-height:1.7;overflow-x:auto}svg{vertical-align:middle;flex-shrink:0}.button{white-space:nowrap;border:1px solid #0000;border-radius:8px;justify-content:center;align-items:center;gap:7px;min-height:38px;padding:8px 13px;font-size:13px;font-weight:550;text-decoration:none;transition:background .15s,border-color .15s,box-shadow .15s;display:inline-flex}.button-primary{color:#fff;background:#243d34;border-color:#243d34}.button-primary:hover:not(:disabled){background:#315346}.button-secondary{color:#343c43;background:#fff;border-color:#dde1e4;box-shadow:0 1px 2px #00000004}.button-secondary:hover:not(:disabled){background:#f4f6f5;border-color:#bfc7c2}.button-ghost{color:#727b85;background:0 0}.button-ghost:hover:not(:disabled){color:#35443d;background:#edf0ef}.button-destructive{color:#fff;background:#ae3e39}.button-small{min-height:32px;padding:6px 10px;font-size:12px}.button-icon{width:32px;height:32px;min-height:32px;padding:6px}.app-shell{height:100dvh;display:flex;overflow:hidden}.sidebar{border-right:1px solid var(--border);background:var(--sidebar);flex-direction:column;flex-shrink:0;width:292px;padding:16px 12px 18px;display:flex}.sidebar-header{flex-shrink:0;min-width:0}.brand{letter-spacing:-.7px;align-items:center;gap:8px;margin-bottom:12px;padding:0 2px;font-size:18px;font-weight:700;display:flex}.brand-mark{flex-shrink:0;width:28px;height:28px}.brand-mark img{display:block}.brand-name{flex:1;min-width:0}.brand>.button{flex-shrink:0}.project-search{margin-bottom:8px}.eyebrow{color:#9a9fa5;letter-spacing:1px;font-size:11px;font-weight:600;display:block}.project-search input{color:#303b35;background:#fff;border:1px solid #dce1e3;border-radius:8px;width:100%;min-width:0;min-height:36px;padding:8px 10px;font-size:12px}.project-search input::placeholder{color:#939ba2}.sidebar-toolbar{justify-content:space-between;align-items:center;gap:8px;margin-bottom:4px;display:flex}.project-list{overscroll-behavior:contain;flex:1;min-height:0;margin:4px -6px;padding:0 6px;scroll-padding-top:40px;overflow:hidden auto}.add-project{margin:0}.project-group{border-top:1px solid var(--border);padding:12px 0 16px}.project-group:first-child{border-top:0}.project-heading{z-index:2;background:var(--sidebar);align-items:center;gap:3px;margin:0;font-size:13px;display:flex;position:sticky;top:0}.project-heading>.control-hint{flex-shrink:0}.project-heading>.button,.project-heading>.control-hint>.button{color:#7b8881;flex-shrink:0}.project-link{color:#55635b;text-align:left;background:0 0;border:1px solid #0000;border-radius:7px;flex:1;align-items:center;gap:8px;width:100%;min-width:0;padding:8px;font-weight:600;display:flex}.project-dialog{border:1px solid var(--border);color:#303b35;background:#fff;border-radius:16px;width:min(500px,100vw - 32px);max-height:calc(100dvh - 32px);margin:auto;padding:22px;overflow-y:auto;box-shadow:0 20px 80px #172a2233}.project-dialog::backdrop{background:#172a2255}.project-dialog-heading,.project-dialog-heading>div{align-items:center;gap:10px;display:flex}.project-dialog-heading{justify-content:space-between;margin-bottom:12px}.project-dialog h2{margin:0;font-size:18px;font-weight:600}.project-dialog form>p{color:#748078;font-size:13px}.project-field{flex-direction:column;gap:8px;margin-top:19px;font-size:13px;font-weight:550;display:flex}.project-field input{color:#303b35;background:#fff;border:1px solid #d5ddd8;border-radius:8px;width:100%;min-width:0;min-height:42px;padding:10px 12px;font-size:14px}.project-field input::placeholder{color:#99a19c}.project-field small{color:#7b867f;font-size:12px;font-weight:400;line-height:1.7}.project-directory{background:#f4f7f5;border-radius:8px;flex-direction:column;gap:7px;padding:12px;font-size:12px;display:flex}.project-directory span{color:#748078}.project-directory code{overflow-wrap:anywhere;line-height:1.7}.project-dialog-actions{flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:25px;display:flex}.project-dialog-actions .project-remove-button{color:var(--destructive);margin-right:auto}.project-dialog form>.project-dialog-error{color:var(--destructive);overflow-wrap:anywhere;margin:16px 0 0}.project-removal-note{color:#687568;background:#f8f9f5;border:1px solid #e6e8df;border-radius:8px;padding:14px;font-size:13px}.project-removal-note p:last-child{margin-bottom:0}.project-link>span:first-of-type{white-space:nowrap;text-overflow:ellipsis;min-width:0;overflow:hidden}.project-link:hover{background:#eef0f2}.project-activity{color:#236443;text-align:center;background:#dcebe1;border-radius:10px;flex-shrink:0;min-width:19px;margin-left:auto;padding:2px 5px;font-size:10px}.project-error{overflow-wrap:anywhere;margin:8px}.thread-list{min-width:0}.thread-link{text-align:left;color:#879088;background:0 0;border:1px solid #0000;border-radius:8px;align-items:flex-start;gap:6px;width:100%;min-height:36px;padding:8px 10px;display:flex}.thread-link:hover{background:#eef0f2}.thread-link>svg{margin-top:1px}.thread-selected{color:#446451;background:#ebefec}.thread-selected:hover{background:#e7ece8}.thread-link-content{flex:1;min-width:0}.thread-title{color:#4d555e;text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:500;line-height:18px;display:block;overflow:hidden}.thread-selected .thread-title{color:#244734}.sidebar-empty{color:#9aa1a7;margin-bottom:0;padding:10px 12px;font-size:12px}.thread-pagination{text-align:center;flex-direction:column;display:flex}.sidebar-pagination-status,.load-more{border:1px solid #0000;margin:0;padding:2px 12px;font-size:11px;font-weight:400;line-height:16px}.sidebar-pagination-status,.load-more:disabled{color:#969da4}.load-more{justify-content:center;width:100%;min-height:22px}.load-more:disabled{opacity:1;cursor:wait}.load-more-error{color:#966724;background:#fbf5e9}.load-more-error:hover:not(:disabled){color:#80571d;background:#f5ead4}.sidebar-footer{border-top:1px solid var(--border);margin:18px 8px 0;padding-top:16px;position:relative}.privacy-mark{color:#66786c;align-items:center;gap:6px;font-size:11px;display:flex}.notification-settings-button{justify-content:flex-start;height:24px;min-height:24px;padding:2px 5px;font-size:11px;position:absolute;top:12px;right:0}.notification-settings-status{color:#748078;font-size:10px}.notification-dialog>p,.gateway-intro,.gateway-help,.gateway-review>p,.gateway-conflict p,.notification-background{color:#66786c;font-size:13px;line-height:1.7}.gateway-settings-button{height:26px;min-height:26px;margin:-5px 0 10px -5px;padding:3px 5px;font-size:12px}.gateway-settings-button~.notification-settings-button{top:11px}.gateway-dialog{width:min(800px,100vw - 24px);padding:24px}.gateway-dialog .project-dialog-heading{z-index:2;background:#fff;margin:-1px -1px 12px;padding:8px 0;position:sticky;top:-24px}.gateway-file{border:1px solid var(--border);background:#f7f9f7;border-radius:9px;gap:5px;padding:12px 14px;font-size:12px;display:grid}.gateway-file span{color:#748078}.gateway-file code,.gateway-changes span{overflow-wrap:anywhere;white-space:pre-wrap}.gateway-status{color:#375e47;background:#edf5ee;border-radius:9px;gap:6px;margin:14px 0;padding:12px 14px;font-size:12px;display:grid}.gateway-status[data-pending=true]{color:#795d20;background:#faf2dc}.gateway-tools{flex-wrap:wrap;gap:8px;margin-top:18px;display:flex}.gateway-section{border-top:1px solid var(--border);margin-top:22px;padding-top:18px}.gateway-section h3,.gateway-section>summary,.gateway-review h3{color:#354e40;margin:0;font-size:14px;font-weight:600}.gateway-section>summary{cursor:pointer}.gateway-fields{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:0 22px;display:grid}.gateway-fields .project-field{min-width:0;margin-top:15px}.gateway-fields textarea,.gateway-fields select{color:#303b35;width:100%;min-width:0;font:inherit;background:#fff;border:1px solid #d5ddd8;border-radius:8px;padding:10px 12px;font-weight:400}.gateway-dialog fieldset{border:0;min-width:0;margin:0;padding:0}.gateway-dialog input:disabled,.gateway-dialog textarea:disabled,.gateway-dialog select:disabled{opacity:.65}.project-field .gateway-running{color:#8a6a2d;overflow-wrap:anywhere;white-space:pre-wrap;border-left:2px solid #b8954c;padding-left:8px}.gateway-error,.gateway-notice{white-space:pre-wrap;overflow-wrap:anywhere;border-radius:8px;padding:12px;font-size:12px;line-height:1.8}.gateway-error{color:#a5372f;background:#fff0ed}.gateway-notice{color:#375e47;background:#edf5ee}.gateway-save-bar{border-top:1px solid var(--border);color:#748078;background:#fff;justify-content:space-between;align-items:center;gap:12px;margin-top:24px;padding:14px 0 8px;font-size:12px;display:flex;position:sticky;bottom:-24px}.gateway-review{margin-top:24px}.gateway-changes{gap:10px;display:grid}.gateway-changes>div{border:1px solid var(--border);border-radius:9px;gap:8px;padding:14px;font-size:12px;display:grid}.gateway-changes span{color:#66786c}.gateway-json{margin-top:18px;font-size:12px}.gateway-json pre{background:#f7f9f7;max-height:300px;padding:14px;overflow:auto}@media (width<=600px){.gateway-dialog{padding:18px}.gateway-fields{grid-template-columns:minmax(0,1fr)}.gateway-dialog .project-dialog-heading{top:-18px}.gateway-save-bar{bottom:-18px}}.notification-control{border:1px solid var(--border);border-radius:10px;justify-content:space-between;align-items:center;gap:12px;margin-top:20px;padding:14px;display:flex}.notification-control>div{flex-direction:column;gap:5px;min-width:0;font-size:13px;display:flex}.notification-control span{color:#748078;font-size:12px}.notification-control .button{flex-shrink:0}.notification-dialog .notification-help{font-size:12px}.notification-background{border-top:1px solid var(--border);margin-top:22px;padding-top:16px}.notification-background h3{color:#303b35;margin:0;font-size:13px}.notification-background summary{cursor:pointer;color:#405e4c}.notification-background ul{padding-left:20px}.notification-background li+li{margin-top:8px}.notification-background a{color:#337052;margin-left:5px;text-decoration:underline}.privacy-mark:before{content:"";background:#739c82;border-radius:50%;width:5px;height:5px}.sidebar-footer p{color:#a1a6ac;margin:7px 0 0;font-size:10px}.main-panel{flex-direction:column;flex:1;min-width:0;display:flex;position:relative}.topbar{border-bottom:1px solid var(--border);flex-shrink:0;justify-content:space-between;align-items:center;gap:15px;min-height:84px;padding:20px 32px;display:flex}.topbar-title{flex:1;align-items:center;gap:10px;min-width:0;display:flex}.topbar-title>div{flex:1;min-width:0}.breadcrumb{color:#899199;align-items:center;gap:7px;margin-bottom:6px;font-size:10px;display:flex}.breadcrumb span{color:#a5aab0}.topbar h1{white-space:nowrap;text-overflow:ellipsis;max-width:360px;margin:0;font-size:15px;font-weight:550;overflow:hidden}.topbar-status{align-items:center;gap:17px;font-size:11px;display:flex}.thread-title-editor{min-width:0;max-width:480px}.thread-title-editor .thread-title-hint{display:block}.thread-title-editor h1:not(.sr-only){overflow:visible}.thread-title-trigger{max-width:100%;color:inherit;font:inherit;cursor:pointer;background:0 0;border:0;border-radius:4px;align-items:center;gap:8px;padding:3px 0;display:flex}.thread-title-trigger span{text-overflow:ellipsis;overflow:hidden}.thread-title-trigger svg{color:var(--muted);flex-shrink:0}.thread-title-trigger:hover,.thread-title-trigger:focus-visible{color:var(--accent)}.thread-title-trigger[aria-disabled=true]{cursor:default;color:inherit}.thread-title-fields{align-items:center;gap:6px;display:flex}.thread-title-fields input{border:1px solid var(--border);width:100%;min-width:0;color:inherit;font:inherit;background:#fff;border-radius:7px;padding:7px 9px;font-size:15px}.thread-title-fields .button{flex-shrink:0}.thread-title-help,.thread-title-error{overflow-wrap:anywhere;margin:6px 0 0;font-size:11px;line-height:1.5}.thread-title-help{color:var(--muted)}.thread-title-error{color:var(--destructive)}.status{color:#828a90;white-space:nowrap;align-items:center;gap:5px;font-size:11px;display:inline-flex}.status-dot{background:currentColor;border-radius:50%;flex-shrink:0;width:5px;height:5px}.status-running,.status-completed{color:#56866a}.status-waitingApproval,.status-waitingInput,.status-unknown{color:#ad7d26}.status-failed{color:#ac534e}.connection-badge{color:#8b949b;white-space:nowrap;align-items:center;gap:6px;font-size:11px;display:inline-flex}.connection-connected .status-dot{color:#6c997f}.connection-disconnected,.connection-authenticationRequired{color:#ab6c33}.connection-banner,.compatibility-banner,.demo-banner{color:#8a733b;background:#f8f4e9;flex-shrink:0;padding:8px 30px;font-size:12px}.compatibility-notice{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;display:flex}.compatibility-notice>span{flex:1;min-width:180px;line-height:1.65}.compatibility-dialog{color:#42463d;background:#fffefb;border:1px solid #ddd8c8;border-radius:14px;width:min(520px,100vw - 32px);max-height:calc(100dvh - 40px);padding:24px;overflow-y:auto;box-shadow:0 20px 80px #172a2233}.compatibility-dialog::backdrop{background:#172a2255}.compatibility-dialog-heading{color:#8b7037;align-items:center;gap:10px;display:flex}.compatibility-dialog h2{margin:0;font-size:17px;font-weight:600}.compatibility-dialog>p{margin:17px 0;font-size:13px;line-height:1.8}.compatibility-dialog dl{background:#f7f5ed;border-radius:7px;padding:14px;font-size:12px}.compatibility-dialog dt{color:#817d6b}.compatibility-dialog dd{color:#514f43}.compatibility-dialog-actions{flex-wrap:wrap;justify-content:flex-end;gap:10px;margin-top:22px;display:flex}.compatibility-uncertain{background:#fcf8ed;border:1px solid #e6ddc6;border-radius:7px;padding:12px;font-size:12px}.compatibility-uncertain p{margin-bottom:10px}.connection-banner{justify-content:space-between;align-items:center;gap:10px;display:flex}.demo-banner{color:#6476a6;text-align:center;background:#eef1fa;padding:6px;font-size:10px}.error-banner{color:#a75248;overflow-wrap:anywhere;background:#fff5f3;border:1px solid #efd6d3;border-radius:7px;align-items:center;gap:10px;margin:12px 0;padding:11px 13px;font-size:12px;line-height:1.6;display:flex}.error-banner.dismissible{justify-content:space-between;margin:10px 30px 0}.persistent-banner{flex-shrink:0;margin:10px 30px 0}.persistent-banner a{margin-left:auto}.conversation-area{flex-direction:column;flex:1;min-height:100px;display:flex;position:relative}.conversation-viewport{--conversation-sticky-offset:0px;--prompt-sticky-height:40px;flex-direction:column;flex:1;min-height:0;display:flex;position:relative}.conversation-scroll{overscroll-behavior:contain;scroll-behavior:auto;flex:1;min-height:0;overflow-y:auto}.conversation-content,.sticky-prompt-slot{width:min(100%,872px);margin:0 auto}.conversation-content{padding:30px 38px 25px}.conversation-viewport:has(.sticky-prompt){--conversation-sticky-offset:var(--prompt-sticky-height)}.conversation-viewport:has(.sticky-prompt) .conversation-scroll{scroll-padding-top:calc(var(--conversation-sticky-offset) + 8px)}.sticky-prompt-slot{z-index:3;height:0;padding-inline:38px;position:absolute;top:0;left:0;right:0}.sticky-prompt{width:100%;height:var(--prompt-sticky-height);min-height:var(--prompt-sticky-height);background:var(--accent-soft);color:#284d3f;text-align:left;border:1px solid #dce7e0;border-top:0;border-radius:0 0 8px 8px;gap:10px;padding:0 12px;line-height:20px;box-shadow:0 2px 5px #243d2810}.sticky-prompt:hover{background:#e5eee8}.sticky-prompt-label,.sticky-prompt>svg{flex-shrink:0}.sticky-prompt-label{color:var(--accent);font-size:10px;font-weight:600}.sticky-prompt-text{white-space:nowrap;text-overflow:ellipsis;flex:1;min-width:0;font-size:12px;font-weight:400;overflow:hidden}.context-compaction-pinned{flex-shrink:0;width:min(100%,872px);margin:0 auto;padding:14px 38px 0}.context-compaction{color:var(--muted);align-items:flex-start;gap:10px;margin:18px 0;font-size:12px;line-height:1.6;display:flex}.context-compaction>div{min-width:0}.context-compaction strong{font-weight:500}.context-compaction p{overflow-wrap:anywhere;margin:3px 0 0}.compaction-icon{flex-shrink:0;padding-top:1px;display:flex}.context-compaction-inProgress{color:#33665f;background:#f0f7f6;border:1px solid #c9dfdc;border-radius:10px;margin:0;padding:12px 14px}.context-compaction-inProgress .compaction-icon{animation:1.8s ease-in-out infinite compaction-pulse}.context-compaction-failed{color:#a75248}@keyframes compaction-pulse{50%{opacity:.4}}.codex-reconnect-pinned{flex-shrink:0;width:min(100%,872px);margin:0 auto;padding:14px 38px 0}.codex-reconnect{color:#79601f;background:#fff9e9;border:1px solid #eadbb0;border-radius:8px;align-items:flex-start;gap:10px;padding:12px 14px;font-size:12px;line-height:1.6;display:flex}.codex-reconnect>svg{flex-shrink:0;margin-top:2px}.codex-reconnect-content{min-width:0}.codex-reconnect strong{font-weight:600}.codex-reconnect p{margin:4px 0 0}.codex-reconnect details{margin-top:5px;font-size:11px}.codex-reconnect-message{overflow-wrap:anywhere;white-space:pre-wrap;max-height:100px;overflow-y:auto}.codex-reconnect-failed{color:#a75248;background:#fff5f3;border-color:#efd6d3}.turn>.codex-reconnect{margin-bottom:24px}.empty-state{text-align:center;margin:max(4vh,30px) auto 30px;padding:28px 0}.empty-symbol{color:#58715f;background:#f3f5f2;border:1px solid #e9ede7;border-radius:23px;place-items:center;width:76px;height:76px;margin:0 auto 30px;display:grid;transform:rotate(-5deg);box-shadow:0 5px 15px #223b2404}.empty-state .eyebrow{color:#99a09a;margin-bottom:15px;font-size:10px}.empty-state h1{letter-spacing:-.8px;color:#343c35;margin-bottom:15px;font-size:clamp(21px,2.5vw,30px);font-weight:550}.empty-state>p:not(.eyebrow){color:#8d9599;font-size:12px;line-height:1.9}.empty-features{color:#a1a8a3;justify-content:center;gap:25px;padding-top:25px;font-size:10px;display:flex}.empty-features span{align-items:center;gap:6px;display:flex}.turn{padding-bottom:25px}.turn+.turn{border-top:1px solid #f0f1f3;padding-top:23px}.turn-heading{color:#a7adb2;justify-content:space-between;margin:0 0 24px 41px;font-size:10px;display:flex}.turn:has(>.turn-completion){padding-bottom:12px}.turn>:has(+.turn-completion){margin-bottom:0}.turn-completion{color:var(--muted);overflow-wrap:anywhere;margin:8px 0 0;font-size:11px;line-height:1.6}.turn-completion-status{white-space:nowrap}.turn-tps{white-space:nowrap;cursor:help;text-underline-offset:3px;-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.turn-completion-status svg{margin-right:5px}.reply-copy-controls{vertical-align:middle;align-items:center;gap:4px;max-width:100%;margin-left:6px;display:inline-flex}.reply-copy-button{width:28px;height:28px;min-height:28px;color:inherit;padding:5px}.reply-copy-feedback:empty{opacity:0}.reply-copy-failed{color:var(--destructive)}.message{margin-bottom:25px;display:flex}.message-content{flex:1;min-width:0;font-size:13px;line-height:1.9}.user-message{justify-content:flex-end}.user-message .message-content{background:var(--accent-soft);color:#284d3f;border-radius:18px;flex:0 auto;max-width:85%;padding:12px 18px}.user-text{white-space:pre-wrap;overflow-wrap:anywhere;margin-bottom:0}.user-question-reply+.user-question-reply{margin-top:16px}.user-question-reply blockquote{color:#526b5e;white-space:pre-wrap;overflow-wrap:anywhere;border-left:3px solid #b5cfc0;margin:0 0 8px;padding-left:12px}.user-message:focus-visible{outline:none}.user-message:focus-visible .message-content{outline:2px solid var(--accent);outline-offset:3px}.markdown{color:#48515b;overflow-wrap:anywhere;line-height:1.85}.markdown p{margin-bottom:12px}.markdown p:last-child{margin-bottom:0}.markdown h1,.markdown h2,.markdown h3{color:#354139;margin:20px 0 10px;font-size:1.15em;font-weight:600}.markdown ul,.markdown ol{padding-left:23px}.markdown li{padding:3px 0}.markdown code{background:#f0f3f1;border-radius:3px;padding:2px 4px;font-size:11px}.markdown pre{border:1px solid var(--border);background:#f7f8f8;border-radius:7px;padding:13px 15px}.markdown pre code{background:0 0;padding:0}.markdown-code-block{border:1px solid var(--border);background:#f7f8f8;border-radius:7px;min-width:0;max-width:100%;margin:0 0 12px;position:relative}.markdown-code-block:last-child{margin-bottom:0}.markdown-code-toolbar{position:absolute;top:6px;right:6px}.code-copy-feedback{z-index:1;border:1px solid var(--border);width:max-content;max-width:min(260px,100vw - 64px);color:var(--accent);pointer-events:none;background:#fff;border-radius:6px;padding:6px 9px;font-size:12px;line-height:1.5;position:absolute;bottom:calc(100% + 6px);right:0;box-shadow:0 2px 8px #0000000d}.code-copy-feedback:empty{opacity:0}.code-copy-failed{color:#ae3e39}.markdown .markdown-code-block pre{white-space:pre;overflow-wrap:normal;outline-offset:-3px;border:0;margin:0 44px 0 0}.markdown blockquote{color:#7b8780;border-left:3px solid #d4dfd6;margin-left:0;padding-left:15px}.markdown img{max-width:100%}.markdown-table-scroll{outline-offset:-2px;max-width:100%;margin:0 0 12px;overflow-x:auto}.markdown-table-scroll:last-child{margin-bottom:0}.markdown table{border-collapse:collapse;width:100%;min-width:480px}.markdown th,.markdown td{border:1px solid var(--border);vertical-align:top;min-width:6rem;padding:9px 12px}.markdown th{color:#354139;background:#f0f3f1;font-weight:600}.markdown th:not([align]){text-align:left}.markdown td code{white-space:nowrap}.markdown tbody tr:nth-child(2n){background:#fafcfb}.auto-review-card{color:#66756c;overflow-wrap:anywhere;background:#fafcfb;border:1px solid #e2e7e3;border-radius:7px;min-width:0;margin:10px 0 10px 40px;padding:12px 14px;font-size:11px}.auto-review-heading{align-items:center;gap:7px;margin-bottom:10px;display:flex}.auto-review-heading>svg{flex-shrink:0}.auto-review-heading h3{min-width:0;margin:0;font-size:11px;font-weight:600}.auto-review-status{color:#617267;white-space:nowrap;background:#edf1ee;border-radius:4px;flex-shrink:0;margin-left:auto;padding:3px 7px;font-size:10px;font-weight:600}.auto-review-inProgress,.auto-review-timedOut{background:#fdfbf5;border-color:#e8dfc9}.auto-review-inProgress .auto-review-heading,.auto-review-timedOut .auto-review-heading{color:#8f7135}.auto-review-inProgress .auto-review-status,.auto-review-timedOut .auto-review-status{color:#8b6726;background:#f5edd9}.auto-review-approved .auto-review-status{color:#41694c;background:#e9f2eb}.auto-review-denied{background:#fff6f4;border-color:#efd0cc}.auto-review-denied .auto-review-heading{color:#ae4c42}.auto-review-denied .auto-review-status{color:#a13e34;background:#fae5e1}.auto-review-operation{gap:5px;min-width:0;display:grid}.auto-review-operation>span{color:#66746b;font-weight:600}.auto-review-operation>code{color:#4e6154;white-space:pre-wrap;overflow-wrap:anywhere;min-width:0;font-size:11px;line-height:1.6}.auto-review-rationale{margin-top:10px;line-height:1.6}.auto-review-rationale strong{font-weight:600}.auto-review-rationale p{color:#56655c;white-space:pre-wrap;overflow-wrap:anywhere;margin:3px 0 0}.auto-review-details{margin-top:10px;font-size:10px}.auto-review-details>summary{color:#839087}.auto-review-details dl{border-top:1px solid #e4e8e3;grid-template-columns:max-content minmax(0,1fr);gap:6px 12px;margin:10px 0 0;padding-top:10px;line-height:1.5;display:grid}.auto-review-details dt{color:#7c897f}.auto-review-details dd{color:#586b5d;overflow-wrap:anywhere;min-width:0;margin:0}.activity{background:#fbfcfb;border:1px solid #e8ebea;border-radius:7px;margin:10px 0 10px 40px;overflow:clip}.activity>summary{color:#7b8780;align-items:center;gap:8px;padding:11px 12px;font-size:11px;list-style:none;display:flex}.activity>summary::-webkit-details-marker{display:none}.activity-description{align-items:center;gap:8px;min-width:0;display:flex}.activity-label{white-space:nowrap;text-overflow:ellipsis;flex-shrink:0;max-width:100%;overflow:hidden}.command-summary{white-space:nowrap;text-overflow:ellipsis;color:#a0a8a2;min-width:0;font-size:10px;overflow:hidden}.activity-status{color:#9ba79d;white-space:nowrap;flex-shrink:0;margin-left:auto;font-size:10px}.activity-failed{background:#fff5f3;border-color:#efd6d3}.activity-failed>summary,.activity-failed .activity-status{color:var(--destructive)}.activity-failed .activity-status{font-weight:600}.activity[open]>summary>svg:last-child{transform:rotate(90deg)}.activity-body{border-top:1px solid #ebeeeb;padding:13px;font-size:12px}.activity-body>:last-child{margin-bottom:0}.command,.tool-output{color:#506453;background:#f1f4f2;border-radius:5px;margin:8px 0;padding:11px}.tool-output{color:#657068;background:#fff}.truncation{color:#a18145;align-items:center;gap:6px;font-size:11px;display:flex}.file-change-link{text-align:left;gap:8px;width:100%;margin:6px 0;font-size:12px;display:flex}.file-change-link code{overflow-wrap:anywhere;white-space:normal;min-width:0}.file-change-link>span{white-space:nowrap;color:var(--muted);margin-left:auto;font-size:11px}.file-change-link>svg{flex-shrink:0}.turn-diff{border:1px solid var(--border);text-align:left;color:#526458;border-radius:8px;justify-content:flex-start;gap:10px;width:100%;height:auto;margin:18px 0 0;padding:12px 14px;display:flex}.turn-diff>span{flex:1;font-size:12px}.turn-diff small{color:var(--muted);margin-top:3px;font-size:11px;font-weight:400;display:block}.back-to-bottom{position:absolute;bottom:14px;left:50%;transform:translate(-50%);box-shadow:0 3px 15px #18321f12}.bottom-region{flex-shrink:0;width:min(100%,872px);max-height:65%;margin:0 auto;padding:0 38px;overflow-y:auto}.composer-region{padding-bottom:max(12px, env(safe-area-inset-bottom))}.composer-resume-status{color:#65776a;align-items:center;gap:6px;margin:0 0 8px;padding:0 2px;font-size:12px;line-height:1.5;display:flex}.composer-resume-status svg{animation:1.2s linear infinite composer-resume-spin}@keyframes composer-resume-spin{to{transform:rotate(360deg)}}.composer-box{background:#fff;border:1px solid #d9dfda;border-radius:12px;position:relative;overflow:hidden;box-shadow:0 3px 12px #26432705}.composer-box:focus-within{border-color:#96afa0;box-shadow:0 0 0 2px #5e956410}.composer-resize-handle{z-index:1;color:#9baaa0;cursor:ns-resize;touch-action:none;-webkit-user-select:none;user-select:none;background:0 0;border:0;width:32px;height:32px;padding:0;position:absolute;top:0;right:0}.composer-resize-handle svg{pointer-events:none;position:absolute;top:0;right:0}.composer-resize-handle path{stroke:currentColor;stroke-width:3px;stroke-linecap:round}.composer-resize-handle:hover,.composer-resize-handle:focus-visible,.composer-resize-handle:active,.composer-resize-handle[data-resizing=true]{color:var(--accent)}.composer-resize-handle:focus-visible{outline:none}html.composer-resizing,html.composer-resizing *{cursor:ns-resize!important;-webkit-user-select:none!important;user-select:none!important}@media (pointer:coarse){.composer-resize-handle{width:44px;height:44px}}.slash-menu{background:#fafcfb;border-bottom:1px solid #e1e8e3}.slash-menu-heading,.slash-menu-footer{color:#536b5d;justify-content:space-between;gap:8px;padding:9px 14px;font-size:11px;display:flex}.slash-menu-heading>span,.slash-menu-footer{color:#748379}.slash-menu-heading{padding-right:48px}.slash-options{max-height:min(260px,30dvh);padding:0 6px;scroll-padding-block:4px;overflow-y:auto}.slash-option{color:#536359;text-align:left;width:100%;min-height:60px;font:inherit;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:7px;flex-direction:column;gap:4px;padding:10px 9px;font-size:12px;line-height:1.5;display:flex}.slash-option[aria-selected=true]{background:#edf5ef;border-color:#bfd4c5}.slash-option-title{justify-content:space-between;align-items:baseline;gap:12px;display:flex}.slash-option-title strong{color:#244b34;font-size:13px}.slash-option-title>span{color:#77867c;font-size:11px}.slash-unavailable{color:#8b6144}.slash-feedback,.slash-empty{color:#46644e;white-space:pre-wrap;overflow-wrap:anywhere;margin:0;padding:10px 14px;font-size:12px;line-height:1.6}.slash-feedback{background:#f4f8f4;border-bottom:1px solid #e1e8e3;padding-right:48px}.slash-feedback[role=alert]{color:#934922;background:#fdf7f1}.composer-box textarea{--composer-min-height:93px;--composer-max-height:230px;resize:none;width:100%;min-height:var(--composer-min-height);max-height:min(var(--composer-max-height), var(--composer-available-height,230px));color:#45534a;background:0 0;border:0;outline:0;padding:17px 44px 7px 17px;font-size:13px;line-height:1.7}.composer-box textarea::placeholder{color:#a8aeab}.composer-images{flex-wrap:wrap;gap:10px;margin:0;padding:14px 44px 0 14px;list-style:none;display:flex}.composer-images li{background:#f4f7f4;border:1px solid #d9dfda;border-radius:8px;width:104px;position:relative;overflow:hidden}.composer-images img,.composer-images li>span:first-child{object-fit:contain;width:100%;height:72px;display:block}.composer-image-name{text-overflow:ellipsis;white-space:nowrap;padding:4px 6px;font-size:10px;display:block;overflow:hidden}.composer-images button{width:26px;height:26px;padding:0;position:absolute;top:3px;right:3px}.composer-image-error{color:#a33b36;margin:12px 14px 0;font-size:12px}.message-images{flex-wrap:wrap;gap:8px;display:flex}.message-images img{object-fit:contain;border-radius:8px;max-width:min(100%,260px);max-height:200px}.composer-box{container-type:inline-size}.composer-actions{justify-content:space-between;align-items:center;gap:12px;padding:7px 12px 12px;display:flex}.composer-context,.composer-send-controls{align-items:center;gap:7px;min-width:0;display:flex}.composer-context{flex:1 1 0}.composer-send-controls{flex:none;margin-left:auto}.composer-send-controls>:not(.settings-model){flex-shrink:0}.composer-target{color:#8d9b90;flex:0 auto;align-items:center;gap:6px;min-width:0;max-width:180px;font-size:11px;display:flex}.composer-target svg{flex-shrink:0}.composer-target>span{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.control-hint{display:inline-flex}.control-hint>:disabled{pointer-events:none}.tooltip-content{z-index:100;width:max-content;max-width:min(260px, var(--radix-tooltip-content-available-width));max-height:var(--radix-tooltip-content-available-height);color:#fff;white-space:normal;overflow-wrap:anywhere;text-align:left;background:#243d33;border-radius:6px;padding:7px 10px;font-size:11px;line-height:1.5;box-shadow:0 3px 12px #18321f20}.control-hint-content>span,.control-hint-description>span{display:block}.tooltip-arrow{fill:#243d33}.composer-note{text-align:center;color:#a9b1ac;margin:0;padding-top:10px;font-size:9px}.settings-panel{color:#65776a;font-size:12px}.select-trigger{border:1px solid var(--border);color:#314b38;min-width:0;min-height:36px;font:inherit;white-space:nowrap;background:#fff;border-radius:6px;justify-content:space-between;align-items:center;gap:7px;padding:7px 10px;display:inline-flex}.select-chevron{opacity:.65}.select-content{z-index:100;min-width:160px;max-width:min(360px,100vw - 16px);max-height:min(320px, var(--radix-select-content-available-height));color:#314b38;background:#fff;border:1px solid #dce5de;border-radius:8px;font-size:12px;line-height:1.5;overflow:hidden;box-shadow:0 6px 24px #18321f20}.select-viewport{padding:4px}.select-item{cursor:default;-webkit-user-select:none;user-select:none;overflow-wrap:anywhere;border-radius:4px;outline:none;align-items:center;gap:7px;width:100%;padding:7px 30px 7px 8px;display:flex;position:relative}.select-item[data-highlighted]{color:#243d33;background:#edf3ee}.select-item[data-disabled]{opacity:.5;pointer-events:none}.select-item-indicator{justify-content:center;align-items:center;display:flex;position:absolute;right:8px}.select-label{color:#748479;padding:6px 8px;font-size:11px}.select-scroll-button{justify-content:center;align-items:center;padding:4px;display:flex}.settings-choice{background:#f5f8f5;border:0;border-radius:16px;align-items:center;min-width:0;min-height:32px;display:flex;position:relative}.settings-choice:hover:not(:disabled),.settings-choice[data-state=open]{background:#edf3ee}.settings-model{flex:0 160px;width:160px;max-width:160px;padding:6px 9px 6px 10px}.settings-model .select-chevron{flex-shrink:0}.settings-model-value{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.settings-effort{justify-content:center;width:34px;padding:4px}.settings-speed{cursor:pointer;color:#637669;background:0 0;justify-content:center;width:28px;padding:4px}.settings-speed[data-fast=true]{color:#326744}.settings-effort .select-chevron{display:none}.reasoning-tier[data-effort=max]{--effort-color:#a65310;--effort-surface:#fff4e5;--effort-hover:#ffead0;--effort-glow:#e9953340}.reasoning-tier[data-effort=ultra]{--effort-color:#7c3ad9;--effort-surface:#f4edff;--effort-hover:#eadcff;--effort-glow:#aa78ed40}.reasoning-tier:is([data-effort=max],[data-effort=ultra]){color:var(--effort-color)}.settings-effort:is([data-effort=max],[data-effort=ultra]){background:var(--effort-surface);width:80px;padding:4px 8px}.settings-effort:is([data-effort=max],[data-effort=ultra]):is(:hover:not(:disabled),[data-state=open]),.select-item.reasoning-tier:is([data-effort=max],[data-effort=ultra])[data-highlighted]{background:var(--effort-hover)}.reasoning-effort-display{border-radius:inherit;justify-content:center;align-items:center;gap:4px;display:inline-flex}.reasoning-tier-label{font-size:11px;font-weight:650;line-height:20px}.settings-effort[data-effort=max] .reasoning-effort-display{animation:.9s ease-out effort-max-ignite}.settings-effort[data-effort=ultra] .reasoning-effort-display{animation:1.25s ease-out effort-ultra-ignite}@keyframes effort-max-ignite{0%,to{box-shadow:0 0 #0000}35%{box-shadow:0 0 0 5px var(--effort-glow), 0 0 14px var(--effort-glow)}70%{box-shadow:0 0 0 2px var(--effort-glow)}}@keyframes effort-ultra-ignite{0%,to{filter:drop-shadow(0 0 #0000);box-shadow:0 0 #0000}30%,65%{filter:drop-shadow(0 0 4px var(--effort-glow));box-shadow:-5px 0 12px var(--effort-glow), 5px 0 12px var(--effort-glow)}48%{filter:drop-shadow(0 0 1px var(--effort-glow));box-shadow:0 0 4px var(--effort-glow)}}@media (prefers-reduced-motion:reduce){.settings-effort[data-effort] .reasoning-effort-display{animation:none}}.settings-choice:focus-visible{outline-offset:2px;outline:2px solid #6b9674}.settings-choice:disabled{opacity:.6;cursor:default}.settings-policy{cursor:pointer;color:#637669;min-height:32px;font:inherit;white-space:nowrap;background:0 0;border:0;border-radius:16px;flex-shrink:0;align-items:center;gap:5px;padding:5px 7px;font-size:11px;display:flex}.settings-policy:hover,.settings-policy[aria-expanded=true]{background:#edf3ee}.settings-policy{flex-shrink:0;min-width:0;max-width:190px}.permission-mode-label{text-overflow:ellipsis;overflow:hidden}.permission-pending-dot{background:#ac7d2e;border-radius:50%;flex-shrink:0;width:5px;height:5px}.settings-details-toggle{color:#748479;cursor:pointer;background:0 0;border:0;border-radius:6px;flex-shrink:0;place-items:center;width:28px;height:30px;padding:0;display:grid}.settings-details-toggle:hover,.settings-details-toggle[aria-expanded=true]{color:#415e49;background:#edf3ee}.permission-mode-menu{width:min(350px,100vw - 24px);max-height:min(440px, var(--radix-select-content-available-height))}.permission-mode-menu .select-item{flex-direction:column;align-items:flex-start;gap:4px;padding-top:10px;padding-bottom:10px}.permission-mode-menu .select-item-description{color:#6b7c6f;font-size:11px;line-height:1.6}.permission-mode-menu strong{font-size:12px;font-weight:600}.permission-description>span{display:block}.permission-mode-menu .permission-unavailable{color:#85682c}.permission-mode-menu .select-item[data-disabled]{opacity:.7}.permission-values{grid-column:1/-1;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px 20px;margin:0;font-size:11px;line-height:1.6;display:grid}.permission-values>div{min-width:0}.permission-values dt{color:#748479}.permission-values dd{color:#415e49;overflow-wrap:anywhere;margin:2px 0 0}.settings-fields{background:#f8faf8;border:1px solid #e3e9e4;border-radius:10px;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:12px;margin:0 12px 8px;padding:14px;display:grid}.settings-heading{grid-column:1/-1;justify-content:space-between;gap:12px;font-size:11px;display:flex}.settings-heading span{color:#748479}.settings-fields label{flex-direction:column;gap:7px;min-width:0;font-size:11px;display:flex}.settings-fields .select-trigger{color:#415e49;background:#fff;border:1px solid #dee5df;border-radius:5px;width:100%;padding:7px 8px;font-size:11px}.settings-note,.settings-observed{color:#6b7c6f;overflow-wrap:anywhere;grid-column:1/-1;margin:0;font-size:10px;line-height:1.6}.settings-observed{flex-wrap:wrap;gap:4px 18px;display:flex}.settings-pending,.settings-defaults,.settings-error{overflow-wrap:anywhere;color:#85682c;flex-wrap:wrap;align-items:center;gap:4px 12px;margin:4px 14px 10px;font-size:11px;line-height:1.5;display:flex}.settings-pending button,.settings-defaults button,.settings-error button{color:inherit;font:inherit;cursor:pointer;background:0 0;border:0;padding:0;text-decoration:underline}.settings-defaults[data-state=saved]{color:#52735a}.settings-pending>span{min-width:0;max-width:100%}@container (width<=700px){.composer-actions{gap:8px}.composer-action-label{display:none}.composer-send-controls .button{width:32px;height:32px;padding:0}}@container (width<=600px){.composer-actions{gap:4px}.settings-policy>span,.settings-policy>svg:last-child{display:none}.settings-policy{justify-content:center;width:28px;min-height:32px;padding:6px}.settings-details-toggle{width:28px;min-height:32px}.permission-values{grid-template-columns:minmax(0,1fr)}.composer-context,.composer-send-controls{gap:3px}.settings-model{flex-basis:auto;gap:3px;width:clamp(50px,22cqw,160px);padding:6px 5px}.settings-model .select-chevron{flex-shrink:0;width:12px}.settings-choice.settings-effort{width:28px;padding:2px}.reasoning-tier-label{display:none}.settings-speed{width:24px;padding:3px}.settings-fields{grid-template-columns:minmax(0,1fr);padding:12px}}@container (width<=330px){.composer-target{flex:none}.composer-target>span{display:none}.settings-model{width:60px}}.pending-actions{overscroll-behavior:contain;max-height:38vh;margin-bottom:12px;overflow-y:auto}.async-question-card{overflow-wrap:anywhere;background:#f8faf8;border:1px solid #dce5df;border-radius:12px;min-width:0;padding:18px;font-size:12px}.async-question-heading,.async-question-heading>span,.async-question-footer{align-items:center;gap:8px;display:flex}.async-question-heading{color:#415e49;justify-content:space-between;margin-bottom:18px}.async-question-heading small,.async-question-footer>span{color:#748479;font-size:11px}.async-question-card fieldset{border:0;min-width:0;margin:0 0 18px;padding:0}.async-question-card legend{margin-bottom:6px;padding:0;font-weight:600;line-height:1.7}.async-question-card .question-option{background:#fff;border-color:#dce5df}.async-question-card .question-option:has(input:checked){background:#edf4ee;border-color:#8bab95}.async-question-card .text-input{resize:vertical;width:100%;line-height:1.6}.async-question-answer{white-space:pre-wrap;color:#415e49;margin:4px 0 0}.async-question-footer{flex-wrap:wrap;justify-content:space-between}.async-question-footer>button{margin-left:auto}.action-card{overflow-wrap:anywhere;background:#fdfbf5;border:1px solid #eadfc6;border-radius:10px;min-width:0;margin-bottom:10px;padding:16px;font-size:12px}.action-card:last-child{margin-bottom:0}.action-heading{align-items:center;gap:8px;margin-bottom:11px;display:flex}.action-icon{color:#ad955c;flex-shrink:0}.action-heading h3{color:#736343;margin:0;font-size:12px;font-weight:600}.action-state{white-space:nowrap;color:#b5a179;flex-shrink:0;margin-left:auto;font-size:10px}.action-card p{color:#8d826a;font-size:11px}.action-cwd>span{white-space:nowrap}.action-options{flex-wrap:wrap;gap:8px;margin-top:14px;display:flex}.action-card fieldset{border:0;margin:0 0 10px;padding:5px 0 12px}.action-card legend{color:#8e7b4a;font-size:11px;font-weight:600}.question-option{cursor:pointer;background:#fffefa;border:1px solid #eee5d5;border-radius:6px;align-items:center;gap:8px;margin:7px 0;padding:10px 12px;display:flex}.question-option:has(input:checked){background:#faf5e8;border-color:#c2b488}.question-option strong{color:#756a4e;font-size:11px;font-weight:550;display:block}.question-option small{color:#a39b87;margin-top:4px;font-size:10px;display:block}.option-number{color:#c1b69a;margin-left:auto;font-size:9px}input[type=checkbox],input[type=radio]{accent-color:#557963}.text-input{color:#6d6755;background:#fff;border:1px solid #dddccb;border-radius:6px;width:100%;padding:10px;font-size:12px}.action-card-unsupported{background:#fff8f7;border-color:#e4c2bc}.action-card-unsupported .action-state,.action-card-unsupported .action-icon{color:#a84339}.permission-details{color:#665a40;background:#fffefa;border:1px solid #e7decb;border-radius:7px;gap:12px;margin:14px 0;padding:12px;display:grid}.permission-network{flex-wrap:wrap;align-items:center;gap:8px 16px;display:flex}.permission-details h4{margin:0 0 8px;font-size:11px;font-weight:600}.permission-paths{gap:8px;margin:0;padding:0;list-style:none;display:grid}.permission-paths li{align-items:flex-start;gap:10px;min-width:0;display:flex}.permission-paths code{overflow-wrap:anywhere;min-width:0;font-size:11px;line-height:1.6}.permission-access{color:#4c6b52;text-align:center;background:#edf1e9;border-radius:4px;flex-shrink:0;min-width:38px;padding:2px 5px;font-size:10px}.permission-access-write{color:#866123;background:#f5ead2}.permission-access-deny{color:#a84339;background:#fae7e4}.elicitation-source strong{color:#665a40;font-weight:600}.elicitation-fields{gap:16px;margin-top:16px;display:grid}.elicitation-field{min-width:0}.elicitation-field-heading{justify-content:space-between;align-items:center;gap:8px;margin-bottom:7px;display:flex}.elicitation-field-heading label{color:#665a40;font-weight:600}.field-necessity{color:#928367;margin-left:8px;font-size:10px;font-weight:400}.field-unset{color:#6d765f;text-underline-offset:3px;font:inherit;cursor:pointer;background:0 0;border:0;flex-shrink:0;padding:2px 0;text-decoration:underline}.field-unset:disabled{cursor:default;opacity:.5}.elicitation-field .text-input{min-width:0;min-height:39px}.elicitation-field [aria-invalid=true]{border-color:#bd6056}.action-card .field-description,.action-card .field-hint{color:#817456;margin:5px 0 8px;line-height:1.5}.action-card .field-hint{margin-bottom:0;font-size:10px}.action-card .elicitation-error{color:#a23c33;margin:7px 0 0;line-height:1.5}.elicitation-multi-options{border:1px solid #0000;border-radius:6px;flex-wrap:wrap;gap:8px;display:flex}.elicitation-multi-options .question-option{margin:0}.elicitation-url{color:#665a40;background:#fffefa;border:1px solid #e7decb;border-radius:7px;justify-items:start;gap:10px;padding:12px;display:grid}.elicitation-url code{overflow-wrap:anywhere;max-width:100%;font-size:11px}.elicitation-url a{color:#446b55;text-underline-offset:3px}.elicitation-url p{margin:0}.sr-only{clip:rect(0, 0, 0, 0);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.session-resume-notice{color:#917b4e;background:#fdfbf5;border:1px solid #eadfc6;border-radius:8px;margin-bottom:14px;padding:15px;font-size:12px}.session-resume-notice strong{color:#8a7446;font-weight:550}.session-resume-notice p{margin:9px 0;font-size:11px}.session-resume-notice button+button{margin-left:8px}.pending-notice{color:#a18d59;background:#fcf9f0;border:1px solid #eee6d5;border-radius:7px;align-items:center;gap:7px;margin-bottom:12px;padding:8px 10px;font-size:10px;display:flex}.pending-notice .button{flex-shrink:0}.pending-notice>span{margin-right:auto}.subtle{color:#96a097;overflow-wrap:anywhere;font-size:11px}.inline-error{overflow-wrap:anywhere;font-size:11px;color:#b36f63!important}.raw-details{color:#98a097;margin:10px 0;font-size:10px}.raw-details summary{color:#8d978d;font-size:10px}.raw-details pre{background:#ffffff80;border:1px solid #e9ebe4;border-radius:5px;max-height:260px;padding:9px;font-size:10px;overflow:auto}.diagnostics>summary{color:#8f9991;white-space:nowrap;align-items:center;gap:5px;font-size:10px;list-style:none;display:flex}.diagnostics>summary::-webkit-details-marker{display:none}.diagnostics-panel{z-index:5;background:#fff;border:1px solid #e2e8e3;border-radius:12px;width:390px;max-width:calc(100vw - 24px);max-height:calc(100dvh - 100px);padding:20px;position:absolute;top:73px;right:25px;overflow-y:auto;box-shadow:0 12px 50px #1a38241a}.diagnostics-heading{justify-content:space-between;align-items:center;margin-bottom:12px;display:flex}.diagnostics-heading h2{color:#586b5d;margin:0;font-size:13px;font-weight:600}dl{grid-template-columns:90px 1fr;gap:9px 15px;margin:0;font-size:11px;line-height:1.6;display:grid}dt{color:#a0aaa3}dd{color:#6a7b70;overflow-wrap:anywhere;min-width:0;margin:0}.count-badge{text-align:center;color:#a08951;background:#f7efdc;border-radius:5px;min-width:16px;padding:1px 4px;font-size:9px}.operation-section{border-top:1px solid #e9ede9;margin:20px 0;padding-top:16px}.operation-section>h3{color:#7f896b;margin-bottom:12px;font-size:12px}.operation-card{background:#fafbf8;border:1px solid #e7eadf;border-radius:7px;margin-bottom:10px;padding:12px}.operation-title{color:#a59e83;justify-content:space-between;gap:7px;margin-bottom:12px;font-size:9px;display:flex}.operation-title strong{color:#8e865f;font-size:11px}.operation-card dl{grid-template-columns:60px 1fr;font-size:10px}.reconcile p{color:#9d9c88;margin:10px 0;font-size:10px}.reconcile label{color:#8c906e;gap:5px;margin:10px 0;font-size:10px;line-height:1.5;display:flex}.mobile-only,.sidebar-backdrop{display:none}@media (width>=1550px){.sidebar{width:312px}.conversation-content{padding-top:42px}}@media (width<=1150px){.sidebar{width:268px}.topbar{padding:19px 24px}.topbar-status{gap:10px}.topbar-status>.status{display:none}.connection-badge{font-size:10px}}@media (width<=760px){.mobile-only{display:inline-flex}.sidebar{z-index:20;width:min(320px,100vw - 36px);padding:16px 12px;transition:transform .18s;position:fixed;top:0;bottom:0;left:0;transform:translate(-100%)}.sidebar-open{transform:translate(0)}.sidebar-backdrop{z-index:19;background:#18261e44;border:0;display:block;position:fixed;inset:0}.topbar{flex-wrap:wrap;gap:10px;min-height:78px;padding:15px 15px 14px 10px}.topbar h1{max-width:calc(100vw - 220px);font-size:13px}.topbar:has(.thread-title-editing) .topbar-title{flex-basis:100%}.thread-title-fields input{min-height:44px;font-size:16px}.thread-title-fields .button{width:44px;height:44px}.topbar-status{flex-direction:column;align-items:flex-end;gap:7px;margin-left:auto}.breadcrumb{font-size:9px}.diagnostics-panel{padding:15px;top:73px;right:12px}.connection-badge,.diagnostics>summary{font-size:9px}.conversation-content{padding:25px 20px}.sticky-prompt-slot{padding-inline:20px}.context-compaction-pinned,.codex-reconnect-pinned{padding:12px 20px 0}.bottom-region{max-height:65%;padding:0 16px}.empty-state{margin-top:30px;padding:25px 5px}.empty-state h1{font-size:23px}.empty-features{flex-wrap:wrap;gap:16px;font-size:9px}.empty-features span:last-child{display:none}.empty-symbol{width:65px;height:65px;margin-bottom:25px}.message-content{font-size:12px}.user-message .message-content{max-width:90%;padding:11px 15px}.activity,.auto-review-card,.turn-diff,.turn-heading{margin-left:0}.composer-box textarea{--composer-min-height:83px;padding:14px 48px 5px 13px;font-size:13px}.composer-target{text-overflow:ellipsis;white-space:nowrap;max-width:120px;font-size:9px;overflow:hidden}.composer-actions{padding:5px 9px 9px}.composer-note{font-size:8px}.error-banner.dismissible,.persistent-banner{margin:8px 15px 0;font-size:10px}.connection-banner,.compatibility-banner{padding:6px 16px;font-size:10px}.persistent-banner{flex-wrap:wrap}.pending-notice{flex-wrap:wrap;font-size:9px}.action-card{padding:13px}.action-heading{flex-wrap:wrap}.action-state{font-size:9px}.action-card p{font-size:10px}.action-options .button{min-height:38px}}@media (prefers-reduced-motion:reduce){.context-compaction-inProgress .compaction-icon,.composer-resume-status svg{animation:none}*,:before,:after{scroll-behavior:auto!important;transition:none!important}}.archive-switch{gap:4px;display:flex}.thread-row{border-radius:8px;grid-template-columns:minmax(0,1fr) auto;align-items:start;margin-bottom:2px;display:grid;position:relative}.thread-row:has(.thread-selected){background:#ebefec}.thread-row .thread-link{min-width:0;padding-right:4px}.thread-row-actions{align-items:center;gap:0;padding:4px 4px 0 0;display:flex}.thread-status-placeholder,.thread-status-indicator{width:20px;height:28px;color:var(--muted);flex:0 0 20px;justify-content:center;align-items:center;display:inline-flex;position:relative}.thread-status-glyph{justify-content:center;align-items:center;display:inline-flex}.thread-status-dot{border:1px solid;border-radius:50%;width:7px;height:7px}.thread-status-completed,.thread-status-running{color:var(--accent)}.thread-status-completed .thread-status-dot{background:currentColor}.thread-status-waitingApproval,.thread-status-waitingInput,.thread-status-unknown{color:#986414}.thread-status-failed{color:var(--destructive)}.thread-status-notification{border:1px solid var(--sidebar);background:#986414;border-radius:50%;width:6px;height:6px;position:absolute;top:5px;right:0}.thread-status-spinning{animation:1s linear infinite thread-status-spin}@keyframes thread-status-spin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){.thread-status-spinning{animation:none}}.thread-details-trigger,.thread-fork>.button,.thread-archive>button{width:24px;height:28px;min-height:28px;color:var(--muted)}.thread-details-trigger[aria-expanded=true]{color:var(--accent);background:var(--accent-soft)}.thread-archive>button[aria-disabled=true]{cursor:default}.thread-details{border:1px solid var(--border);color:#59636c;overflow-wrap:anywhere;background:#fff;border-radius:8px;grid-column:1/-1;margin:3px 4px 8px;padding:12px;font-size:12px}.thread-details h3{color:#35463e;margin-bottom:10px;font-size:13px;line-height:1.6}.thread-details dl{margin:0 0 10px;display:block}.thread-details dl>div{grid-template-columns:4em minmax(0,1fr);align-items:start;gap:8px;margin-top:6px;display:grid}.thread-details dt{color:var(--muted)}.thread-details dd{margin:0}.thread-details dl>.thread-id-row{grid-template-columns:5em minmax(0,1fr)}.thread-id-value{align-items:flex-start;gap:6px;min-width:0;display:flex}.thread-id-value code{overflow-wrap:anywhere;white-space:normal;-webkit-user-select:text;user-select:text;flex:1;min-width:0}.thread-id-copy{flex:none;width:24px;height:24px;min-height:24px}.thread-id-feedback{color:var(--muted);font-size:11px;display:block}.thread-id-failed{color:var(--destructive)}.thread-details .status{font-size:inherit;background:0 0;padding:0}.thread-details p{margin:8px 0 0}.thread-origin-note{color:var(--muted)}@media (pointer:coarse){.thread-row .thread-link{min-height:44px;padding:12px 4px 12px 10px}.thread-row-actions{gap:0;padding:0}.thread-details-trigger,.thread-fork>.button,.thread-archive>button{width:32px;height:44px;min-height:44px}}.archive-notice{border:1px solid var(--border);background:#fff;border-radius:8px;align-items:center;gap:12px;margin:12px 24px 0;padding:12px 16px;font-size:13px;display:flex}.archive-notice div{flex:1;min-width:0}.archive-notice p{color:var(--muted);margin:3px 0 0;font-size:12px}@media (width<=700px){.archive-notice{flex-wrap:wrap;margin-inline:12px}}.local-image{vertical-align:top;max-width:100%;margin:8px 0;display:inline-block}.local-image-open{border:1px solid var(--border);color:#526458;cursor:zoom-in;text-align:left;background:#f8faf8;border-radius:9px;flex-direction:column;max-width:min(100%,432px);padding:5px;display:flex;overflow:hidden}.markdown .local-image-thumbnail{object-fit:contain;border-radius:5px;width:auto;max-width:min(100%,420px);height:auto;max-height:280px;display:block}.local-image-caption{overflow-wrap:anywhere;max-width:100%;padding:4px 5px 0;font-size:11px}.local-image-link{text-underline-offset:3px;text-decoration-style:dotted}.local-image-loading,.local-image-error{color:#627269;background:#f3f5f3;border-radius:7px;flex-direction:column;align-items:flex-start;gap:7px;max-width:100%;padding:13px;font-size:12px;display:flex}.local-image-error{color:#995338;background:#fff8f4;border:1px solid #e9d6cd}.local-image-error code,.local-image-loading code{overflow-wrap:anywhere;white-space:normal}.image-retry{color:inherit;cursor:pointer;background:0 0;border:0;padding:0;text-decoration:underline}.image-preview-dialog{border:1px solid var(--border);color:#354139;background:#fff;border-radius:12px;width:min(1120px,100vw - 32px);max-width:none;max-height:calc(100dvh - 32px);padding:18px;box-shadow:0 24px 80px #162d2540}.image-preview-dialog::backdrop{background:#14251dd9}.image-preview-heading,.image-preview-toolbar{align-items:center;gap:10px;display:flex}.image-preview-heading{justify-content:space-between}.image-preview-heading h2{overflow-wrap:anywhere;min-width:0;margin:0;font-size:16px}.image-preview-heading>button{flex-shrink:0}.image-preview-toolbar{flex-wrap:wrap;margin:12px 0}.image-preview-toolbar output{text-align:center;font-variant-numeric:tabular-nums;min-width:42px;font-size:12px}.image-preview-shortcuts{color:#76847b;margin-left:auto;font-size:11px}.image-preview-viewport{border:1px solid var(--border);outline-offset:-3px;background:#edf1ee;border-radius:7px;height:min(65dvh,760px);min-height:100px;overflow:auto}.image-preview-canvas{justify-content:center;align-items:center;width:max-content;min-width:100%;min-height:100%;display:flex}.image-preview-canvas img{flex-shrink:0;display:block}.image-preview-path{color:#718077;gap:8px;margin:12px 0 0;font-size:11px;display:flex}.image-preview-path>span{flex-shrink:0}.image-preview-path code{overflow-wrap:anywhere;white-space:normal;min-width:0}@media (width<=600px){.image-preview-dialog{width:calc(100vw - 16px);max-height:calc(100dvh - 16px);padding:12px}.image-preview-viewport{height:58dvh}.image-preview-shortcuts{display:none}}.local-file-link{text-decoration-style:dotted;text-decoration-thickness:1px}.local-file-link:hover{text-decoration-style:solid}.file-preview{border:0;border-left:1px solid var(--border);color:inherit;background:#fff;flex:none;width:clamp(420px,43vw,800px);min-width:0;max-width:none;height:100%;max-height:none;margin:0;padding:0;position:relative;overflow:hidden}.file-preview[open]{flex-direction:column;display:flex}.file-preview-header{border-bottom:1px solid var(--border);flex-shrink:0;align-items:center;gap:12px;padding:18px 20px;display:flex}.file-preview-header>.button,.file-preview-icon{flex-shrink:0}.file-preview-header>.button:first-child{order:4}.file-preview-icon{color:var(--accent)}.file-preview-title{flex:1;min-width:0}.file-preview-title h2{text-overflow:ellipsis;white-space:nowrap;margin:0 0 3px;font-size:14px;font-weight:600;overflow:hidden}.file-preview-title>span{color:var(--muted);font-size:11px}.file-preview-back{display:none}.file-preview-toolbar{color:var(--muted);flex-shrink:0;justify-content:space-between;align-items:center;padding:10px 20px;font-size:11px;display:flex}.file-preview-toolbar>div{gap:4px;display:flex}.file-preview-toolbar [aria-pressed=true]{background:var(--accent-soft);color:var(--accent)}.file-preview-feedback{color:var(--accent);margin:0;padding:0 24px;font-size:12px}.file-preview-feedback:empty{display:none}.file-preview-scroll{overscroll-behavior:contain;flex:1;min-height:0;padding:20px 32px 48px;scroll-padding:24px;overflow:auto}.file-preview-scroll>.markdown{max-width:760px;margin:0 auto;font-size:15px;line-height:1.9}.file-preview-scroll .markdown h1{font-size:1.65em}.file-preview-scroll .markdown h2{font-size:1.3em}.file-preview-scroll .markdown>:first-child{margin-top:0}.file-preview-source{white-space:pre-wrap;overflow-wrap:anywhere;-webkit-user-select:text;user-select:text;background:0 0;border:0;margin:0;padding:0;font-size:13px}.json-preview{tab-size:2;line-height:1.8}.json-key{color:#6f42a1}.json-string{color:#17664b}.json-number{color:#175fa8}.json-boolean,.json-null{color:#a33f21}.json-preview-warning{color:#80501b;background:#fff8ed;border:1px solid #e3c69d;border-radius:8px;margin:0 0 20px;padding:12px 14px;font-size:13px;line-height:1.7}.file-preview-error{text-align:center;padding:40px 0;font-size:14px}.file-preview-error>svg{color:var(--muted);margin-bottom:20px}.file-preview-error h3{font-size:16px}.file-preview-loading{color:var(--muted);font-size:14px}.file-preview-path{border-top:1px solid var(--border);padding:10px 20px max(10px, env(safe-area-inset-bottom));color:var(--muted);text-overflow:ellipsis;white-space:nowrap;flex-shrink:0;font:10px/1.5 SFMono-Regular,Consolas,monospace;overflow:hidden}@media (width<=1279px){.file-preview{border:0;width:100%;height:100dvh;position:fixed;inset:0}.file-preview::backdrop{background:#fff}.file-preview-header{padding:max(12px, env(safe-area-inset-top)) 12px 12px;gap:8px}.file-preview-header>.button:first-child{order:0}.file-preview-header>.button{min-height:44px}.file-preview-back{display:block}.file-preview-close,.file-preview-icon{display:none}.file-preview-toolbar{padding:8px 20px}.file-preview-toolbar .button{min-height:40px;padding-inline:16px}.file-preview-scroll{padding:18px 22px 40px}.file-preview-scroll>.markdown{font-size:16px}}.update-dialog{width:min(540px,100vw - 32px)}.update-version,.update-available{flex-wrap:wrap;align-items:baseline;gap:12px;padding:16px 0;display:flex}.update-version strong{letter-spacing:-.03em;font-size:22px}.update-version code,.update-available code{color:var(--muted);font-size:12px}.update-codex{border:1px solid var(--border);overflow-wrap:anywhere;background:#f7f8fa;border-radius:9px;margin:0 0 16px;padding:12px 14px}.update-codex h3{color:var(--muted);margin:0 0 8px;font-size:12px;font-weight:600}.update-codex>div{flex-wrap:wrap;align-items:center;gap:8px;font-size:13px;display:flex}.update-codex p{margin:8px 0 0;font-size:12px;line-height:1.6}.update-codex-status{color:#4f6658;margin-left:auto}.update-codex[data-state=verified]{background:#f4f8f5;border-color:#c0d6c7}.update-codex[data-state=unverified],.update-codex[data-state=unknown]{background:#fcfaf4;border-color:#dfd4b6}.update-codex[data-state=unsupported]{background:#fcf6f5;border-color:#e2c0be}.update-codex-consent{margin-top:12px}.update-channel{justify-content:space-between;align-items:center;gap:16px;font-weight:600;display:flex}.update-channel select{border:1px solid var(--border);color:#303b35;min-width:148px;font:inherit;background:#f7f8fa;border-radius:8px;padding:8px 12px}.update-control{border-block:1px solid var(--border);justify-content:space-between;align-items:center;gap:20px;margin-top:18px;padding:18px 0;display:flex}.update-control p{margin:5px 0 0}.update-buttons{justify-content:flex-end;gap:10px;margin:18px 0;display:flex}.update-progress{border:1px solid var(--border);background:#f7f8fa;border-radius:10px;gap:7px;margin:18px 0;padding:16px;display:grid}.update-progress>span{color:var(--muted);overflow-wrap:anywhere;font-size:12px}.update-progress p{margin:0;line-height:1.65}.update-progress progress{accent-color:#303b35;width:100%;height:6px;margin-top:8px}.update-progress[data-phase=failed]{border-color:#e5a7a7}.update-progress[data-phase=succeeded]{border-color:#a3c6b0}.update-notice{background:#f7f8fa;border-radius:8px;padding:12px;font-size:13px;line-height:1.6}.update-source{color:var(--muted);flex-wrap:wrap;align-items:center;gap:10px;margin-top:20px;font-size:12px;display:flex}.update-source a{color:inherit;align-items:center;gap:4px;display:inline-flex}.update-downgrade{align-items:flex-start;gap:8px;font-size:12px;line-height:1.5;display:flex}.covro-brand-button{min-height:32px;color:inherit;font:inherit;text-align:left;background:0 0;border:0;align-items:center;gap:5px;padding:0;display:flex}.covro-brand-button svg{opacity:.55}.covro-brand-button[data-update-available=true] svg{color:var(--accent);opacity:1}.history-pagination{min-height:48px;color:var(--muted);flex-wrap:wrap;justify-content:center;align-items:center;gap:8px;font-size:12px;display:flex}.conversation-scroll{overflow-anchor:none}.history-opening{color:var(--muted);padding:48px 16px}.history-skeleton{gap:14px;margin-top:28px;display:grid}.history-skeleton span{background:var(--border);border-radius:6px;width:75%;height:16px}.history-skeleton span:nth-child(2){width:92%}.history-skeleton span:nth-child(3){width:55%}.history-cache-notice{background:var(--surface);color:var(--muted);border-bottom:1px solid var(--border);flex-wrap:wrap;justify-content:center;align-items:center;gap:8px;padding:8px 16px;font-size:12px;display:flex}.diff-scope{color:var(--muted);border-bottom:1px solid var(--border);margin:0;padding:14px 20px;font-size:12px;line-height:1.7}.diff-file-picker{border-bottom:1px solid var(--border);flex-shrink:0;align-items:center;gap:10px;padding:12px 20px;font-size:11px;display:flex}.diff-file-picker label,.diff-file-picker>span{color:var(--muted);white-space:nowrap}.diff-file-picker select{border:1px solid var(--border);min-width:0;max-width:100%;height:36px;color:inherit;font:inherit;background:#fff;border-radius:6px;flex:1;padding:0 8px}.diff-file-heading{align-items:flex-start;gap:9px;padding:16px 20px 8px;font-size:12px;display:flex}.diff-file-heading>code{overflow-wrap:anywhere;white-space:normal;flex:1;min-width:0;line-height:1.7}.diff-kind{color:#476580;background:#edf2f6;border-radius:4px;flex-shrink:0;padding:2px 6px;font-size:10px}.diff-kind-added{color:#257145;background:#e7f4eb}.diff-kind-deleted{color:#a34039;background:#fff0ed}.diff-kind-renamed{color:#865d21;background:#faf0df}.diff-stats{flex-shrink:0;gap:8px;font:11px/1.8 monospace;display:inline-flex}.diff-stats>:first-child{color:#257145}.diff-stats>:last-child{color:#ab453d}.diff-rename{overflow-wrap:anywhere;color:var(--muted);margin:0;padding:0 20px;font-size:11px}.diff-controls{flex-shrink:0;justify-content:space-between;align-items:center;gap:4px;padding:4px 12px 10px;display:flex}.diff-controls [role=group]{color:var(--muted);white-space:nowrap;align-items:center;gap:3px;font-size:11px;display:flex}.diff-warning{color:#865d21;background:#fff7e8;margin:0;padding:8px 20px;font-size:12px;line-height:1.6}.diff-content{overscroll-behavior:contain;border-top:1px solid var(--border);flex:1;min-height:0;scroll-padding-top:28px;overflow:auto}.diff-table{border-collapse:separate;border-spacing:0;tab-size:4;width:100%;font:12px/1.8 SFMono-Regular,Consolas,monospace}.diff-table th{z-index:2;color:var(--muted);text-align:left;white-space:nowrap;border-bottom:1px solid var(--border);background:#f7f9f8;padding:5px 7px;font-size:10px;font-weight:400;position:sticky;top:0}.diff-table th:first-child,.diff-table th:nth-child(2){text-align:right}.diff-hunk td{color:#4b6f85;white-space:pre-wrap;overflow-wrap:anywhere;background:#eef4f8;padding:7px 12px;font-size:11px}.diff-hunk span{margin-right:8px;font-family:inherit;font-weight:600}.diff-line td{vertical-align:top}.diff-line-number{text-align:right;color:#89938d;-webkit-user-select:none;user-select:none;background:#f7f9f8;border-right:1px solid #e9eeeb;width:1%;min-width:38px;padding:0 7px}.diff-marker{-webkit-user-select:none;user-select:none;width:1%;padding:0 6px}.diff-code{white-space:pre;padding:0 16px 0 4px}.diff-code code{font:inherit}.diff-added{color:#245c37;background:#eaf6ee}.diff-removed{color:#983f38;background:#fff0ed}.diff-added .diff-line-number{color:#4f7b5d;background:#dff0e5}.diff-removed .diff-line-number{color:#a66b62;background:#fbe4df}.diff-note{color:var(--muted);font-style:italic}.diff-wrap .diff-table{table-layout:fixed}.diff-wrap .diff-code{white-space:pre-wrap;overflow-wrap:anywhere}.diff-wrap th:first-child,.diff-wrap th:nth-child(2){width:42px}.diff-wrap th:nth-child(3){width:22px}.diff-empty{text-align:center;min-height:180px;color:var(--muted);flex:1;padding:40px 24px;font-size:13px}.diff-empty h3{color:var(--foreground);font-size:15px}.diff-empty p{white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.8}@media (width<=600px){.diff-scope{padding:12px 16px;font-size:11px}.diff-file-picker{gap:6px;padding:10px 12px}.diff-file-picker label{display:none}.diff-file-picker select{height:42px;font-size:12px}.diff-file-heading{flex-wrap:wrap;padding:12px 16px 8px}.diff-controls{padding:4px 8px 8px}.diff-controls .button{min-height:40px}.diff-table{font-size:11px}.diff-warning{padding:8px 16px;font-size:11px}}.diff-loading{flex:1;padding:24px}.diff-inline-change{color:inherit;-webkit-box-decoration-break:clone;box-decoration-break:clone;border-radius:2px;padding:0}.diff-added .diff-inline-change{background:#abdfb8}.diff-removed .diff-inline-change{background:#f6bdb6}
|