neko-harness 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/assets/index-6edxlI44.css +2 -0
- package/dist/client/assets/{index-D6NpJLXy.js → index-CZ-wxzM4.js} +26 -26
- package/dist/client/index.html +2 -2
- package/dist/gateway.js +44 -10
- package/dist/neko.js +47 -12
- package/package.json +1 -1
- package/dist/client/assets/index-CxnbrvVk.css +0 -2
package/dist/client/index.html
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' rx='26' fill='%23ffb7c5'/%3E%3Ctext x='50' y='70' font-size='58' text-anchor='middle' fill='%23ffffff' font-family='sans-serif' font-weight='bold'%3En%3C/text%3E%3C/svg%3E"
|
|
10
10
|
/>
|
|
11
11
|
<title>neko harness</title>
|
|
12
|
-
<script type="module" crossorigin src="/assets/index-
|
|
13
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
12
|
+
<script type="module" crossorigin src="/assets/index-CZ-wxzM4.js"></script>
|
|
13
|
+
<link rel="stylesheet" crossorigin href="/assets/index-6edxlI44.css">
|
|
14
14
|
</head>
|
|
15
15
|
<body>
|
|
16
16
|
<div id="root"></div>
|
package/dist/gateway.js
CHANGED
|
@@ -2446,6 +2446,7 @@ async function removeGatewayPortFile(nekoDir, serverId) {
|
|
|
2446
2446
|
// packages/gateway/src/server-services.ts
|
|
2447
2447
|
import {
|
|
2448
2448
|
createRemoteServiceEndpoint,
|
|
2449
|
+
RemoteServiceError,
|
|
2449
2450
|
RemoteServiceProvider,
|
|
2450
2451
|
replicatedState
|
|
2451
2452
|
} from "@earendil-works/chord";
|
|
@@ -2455,6 +2456,13 @@ import { spawn } from "child_process";
|
|
|
2455
2456
|
import { accessSync as accessSync2, constants as constants2 } from "fs";
|
|
2456
2457
|
import { realpath, stat } from "fs/promises";
|
|
2457
2458
|
import { basename as basename2, delimiter, isAbsolute as isAbsolute2, join as join7, relative, resolve as resolve4, sep } from "path";
|
|
2459
|
+
|
|
2460
|
+
class MissingFileSearchDependencyError extends Error {
|
|
2461
|
+
constructor() {
|
|
2462
|
+
super("Install fd (or fdfind) to search workspace files.");
|
|
2463
|
+
this.name = "MissingFileSearchDependencyError";
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2458
2466
|
function findFd() {
|
|
2459
2467
|
for (const name of process.platform === "win32" ? ["fd.exe", "fdfind.exe"] : ["fd", "fdfind"]) {
|
|
2460
2468
|
for (const directory of (process.env.PATH ?? "").split(delimiter)) {
|
|
@@ -2484,7 +2492,7 @@ async function workspaceTarget(root, path) {
|
|
|
2484
2492
|
}
|
|
2485
2493
|
async function searchWorkspaceFiles(root, query, signal, fd = findFd()) {
|
|
2486
2494
|
if (!fd)
|
|
2487
|
-
throw new
|
|
2495
|
+
throw new MissingFileSearchDependencyError;
|
|
2488
2496
|
query = relativeQuery(query);
|
|
2489
2497
|
const slash = query.lastIndexOf("/");
|
|
2490
2498
|
const prefix = slash < 0 ? "" : query.slice(0, slash + 1);
|
|
@@ -2508,6 +2516,8 @@ async function searchWorkspaceFiles(root, query, signal, fd = findFd()) {
|
|
|
2508
2516
|
"--max-results",
|
|
2509
2517
|
"101",
|
|
2510
2518
|
"--print0",
|
|
2519
|
+
"--path-separator",
|
|
2520
|
+
"/",
|
|
2511
2521
|
"--color",
|
|
2512
2522
|
"never"
|
|
2513
2523
|
];
|
|
@@ -2576,6 +2586,26 @@ var NekoWorkspaces = defineService("neko.workspaces");
|
|
|
2576
2586
|
var NekoCredentials = defineService("neko.credentials");
|
|
2577
2587
|
var NekoWorkspaceFiles = defineService("neko.workspace-files");
|
|
2578
2588
|
|
|
2589
|
+
// packages/gateway/src/file-search-help.ts
|
|
2590
|
+
function fileSearchInstallHelp(platform = process.platform) {
|
|
2591
|
+
const docs = "https://github.com/sharkdp/fd#installation";
|
|
2592
|
+
let install;
|
|
2593
|
+
switch (platform) {
|
|
2594
|
+
case "win32":
|
|
2595
|
+
install = "\u8BF7\u6267\u884C\uFF1Awinget install sharkdp.fd\u3002";
|
|
2596
|
+
break;
|
|
2597
|
+
case "darwin":
|
|
2598
|
+
install = "\u8BF7\u6267\u884C\uFF1Abrew install fd\u3002";
|
|
2599
|
+
break;
|
|
2600
|
+
case "linux":
|
|
2601
|
+
install = `Debian/Ubuntu \u8BF7\u6267\u884C\uFF1Asudo apt install fd-find\u3002\u5176\u4ED6\u53D1\u884C\u7248\u8BF7\u53C2\u8003\uFF1A${docs} \u3002`;
|
|
2602
|
+
break;
|
|
2603
|
+
default:
|
|
2604
|
+
install = `\u5B89\u88C5\u65B9\u6CD5\u8BF7\u53C2\u8003\uFF1A${docs} \u3002`;
|
|
2605
|
+
}
|
|
2606
|
+
return `\u672A\u627E\u5230 fd \u6216 fdfind\uFF0C\u6682\u65F6\u65E0\u6CD5\u4F7F\u7528 @ \u6587\u4EF6\u8865\u5168\u3002\u8BF7\u5728\u8FD0\u884C neko \u7684\u7535\u8111\u4E0A\u5B89\u88C5\u3002${install}\u5B89\u88C5\u540E\u91CD\u65B0\u6253\u5F00\u7EC8\u7AEF\u5E76\u91CD\u542F neko\u3002`;
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2579
2609
|
// packages/gateway/src/workspaces.ts
|
|
2580
2610
|
import { constants as constants3 } from "fs";
|
|
2581
2611
|
import { access, readdir as readdir2, stat as stat2 } from "fs/promises";
|
|
@@ -2733,6 +2763,10 @@ async function createNekoServerServices(options) {
|
|
|
2733
2763
|
if (!roots.some((w) => w.path === input.workspaceRoot))
|
|
2734
2764
|
throw new Error("Unknown workspace.");
|
|
2735
2765
|
return await searchWorkspaceFiles(input.workspaceRoot, input.query, AbortSignal.any([controller.signal, ...ctx.abortSignal ? [ctx.abortSignal] : []]));
|
|
2766
|
+
} catch (error) {
|
|
2767
|
+
if (error instanceof MissingFileSearchDependencyError)
|
|
2768
|
+
throw new RemoteServiceError("service_not_allowed", fileSearchInstallHelp());
|
|
2769
|
+
throw error;
|
|
2736
2770
|
} finally {
|
|
2737
2771
|
fileQueries--;
|
|
2738
2772
|
if (fileQuery === controller)
|
|
@@ -2823,7 +2857,7 @@ import { open as open2 } from "fs/promises";
|
|
|
2823
2857
|
import { basename as basename3, extname } from "path";
|
|
2824
2858
|
import {
|
|
2825
2859
|
createRemoteServiceEndpoint as createRemoteServiceEndpoint2,
|
|
2826
|
-
RemoteServiceError,
|
|
2860
|
+
RemoteServiceError as RemoteServiceError2,
|
|
2827
2861
|
RemoteServiceProvider as RemoteServiceProvider2,
|
|
2828
2862
|
replicatedState as replicatedState2
|
|
2829
2863
|
} from "@earendil-works/chord";
|
|
@@ -2991,7 +3025,7 @@ async function openNekoSessionHandle(options) {
|
|
|
2991
3025
|
try {
|
|
2992
3026
|
return action();
|
|
2993
3027
|
} catch (error) {
|
|
2994
|
-
throw new
|
|
3028
|
+
throw new RemoteServiceError2("service_invalid_value", error instanceof Error ? error.message : "Image upload failed");
|
|
2995
3029
|
}
|
|
2996
3030
|
};
|
|
2997
3031
|
const createProvider = () => {
|
|
@@ -3048,7 +3082,7 @@ async function openNekoSessionHandle(options) {
|
|
|
3048
3082
|
try {
|
|
3049
3083
|
await session.compact(instructions);
|
|
3050
3084
|
} catch (error) {
|
|
3051
|
-
throw new
|
|
3085
|
+
throw new RemoteServiceError2("service_invalid_value", error instanceof Error ? error.message : "Cannot compact");
|
|
3052
3086
|
}
|
|
3053
3087
|
},
|
|
3054
3088
|
beginImage: async (input) => safeUpload(() => uploads.begin(input)),
|
|
@@ -3057,15 +3091,15 @@ async function openNekoSessionHandle(options) {
|
|
|
3057
3091
|
releaseImage: async (id) => uploads.release(id),
|
|
3058
3092
|
getImage: async (input) => {
|
|
3059
3093
|
if (!Number.isSafeInteger(input.offset) || input.offset < 0 || !Number.isSafeInteger(input.contentIndex) || input.contentIndex < 0)
|
|
3060
|
-
throw new
|
|
3094
|
+
throw new RemoteServiceError2("service_invalid_value", "Invalid image range");
|
|
3061
3095
|
const entry = history.get(input.entryId);
|
|
3062
3096
|
const content = entry?.model?.[0]?.content;
|
|
3063
3097
|
const image = Array.isArray(content) ? content[input.contentIndex] : undefined;
|
|
3064
3098
|
if (image?.type !== "image")
|
|
3065
|
-
throw new
|
|
3099
|
+
throw new RemoteServiceError2("service_invalid_value", "Image is not part of this conversation");
|
|
3066
3100
|
const bytes = Buffer.from(image.data, "base64");
|
|
3067
3101
|
if (input.offset > bytes.length)
|
|
3068
|
-
throw new
|
|
3102
|
+
throw new RemoteServiceError2("service_invalid_value", "Invalid image range");
|
|
3069
3103
|
return {
|
|
3070
3104
|
data: bytes.subarray(input.offset, input.offset + IMAGE_CHUNK_BYTES).toString("base64"),
|
|
3071
3105
|
total: bytes.length,
|
|
@@ -3085,8 +3119,8 @@ async function openNekoSessionHandle(options) {
|
|
|
3085
3119
|
uploads.release(id);
|
|
3086
3120
|
} catch (error) {
|
|
3087
3121
|
if (error instanceof Error && error.message.startsWith("DEEPSEEK_KEY_REQUIRED:"))
|
|
3088
|
-
throw new
|
|
3089
|
-
throw new
|
|
3122
|
+
throw new RemoteServiceError2("service_invalid_value", "DEEPSEEK_KEY_REQUIRED: Configure DeepSeek in /login or Web settings.");
|
|
3123
|
+
throw new RemoteServiceError2("service_invalid_value", error instanceof Error ? error.message : "Cannot submit message");
|
|
3090
3124
|
}
|
|
3091
3125
|
await onActivity();
|
|
3092
3126
|
},
|
|
@@ -3105,7 +3139,7 @@ async function openNekoSessionHandle(options) {
|
|
|
3105
3139
|
configure: async (change) => {
|
|
3106
3140
|
const applied = await runtime.configureConversation(session.id, change);
|
|
3107
3141
|
if (!applied) {
|
|
3108
|
-
throw new
|
|
3142
|
+
throw new RemoteServiceError2("service_invalid_value", `Session ${String(session.id)} is unavailable or archived`);
|
|
3109
3143
|
}
|
|
3110
3144
|
}
|
|
3111
3145
|
});
|
package/dist/neko.js
CHANGED
|
@@ -3465,7 +3465,7 @@ async function workspaceTarget(root, path) {
|
|
|
3465
3465
|
}
|
|
3466
3466
|
async function searchWorkspaceFiles(root, query, signal, fd = findFd()) {
|
|
3467
3467
|
if (!fd)
|
|
3468
|
-
throw new
|
|
3468
|
+
throw new MissingFileSearchDependencyError;
|
|
3469
3469
|
query = relativeQuery(query);
|
|
3470
3470
|
const slash = query.lastIndexOf("/");
|
|
3471
3471
|
const prefix = slash < 0 ? "" : query.slice(0, slash + 1);
|
|
@@ -3489,6 +3489,8 @@ async function searchWorkspaceFiles(root, query, signal, fd = findFd()) {
|
|
|
3489
3489
|
"--max-results",
|
|
3490
3490
|
"101",
|
|
3491
3491
|
"--print0",
|
|
3492
|
+
"--path-separator",
|
|
3493
|
+
"/",
|
|
3492
3494
|
"--color",
|
|
3493
3495
|
"never"
|
|
3494
3496
|
];
|
|
@@ -3546,7 +3548,15 @@ async function searchWorkspaceFiles(root, query, signal, fd = findFd()) {
|
|
|
3546
3548
|
entries.sort((a, b) => (a.kind === b.kind ? 0 : a.kind === "directory" ? -1 : 1) || a.path.localeCompare(b.path));
|
|
3547
3549
|
return { entries: entries.slice(0, 100), limited: paths.length > 100 };
|
|
3548
3550
|
}
|
|
3549
|
-
var
|
|
3551
|
+
var MissingFileSearchDependencyError;
|
|
3552
|
+
var init_workspace_files = __esm(() => {
|
|
3553
|
+
MissingFileSearchDependencyError = class MissingFileSearchDependencyError extends Error {
|
|
3554
|
+
constructor() {
|
|
3555
|
+
super("Install fd (or fdfind) to search workspace files.");
|
|
3556
|
+
this.name = "MissingFileSearchDependencyError";
|
|
3557
|
+
}
|
|
3558
|
+
};
|
|
3559
|
+
});
|
|
3550
3560
|
|
|
3551
3561
|
// packages/tui/src/file-completion.ts
|
|
3552
3562
|
import { CombinedAutocompleteProvider } from "@earendil-works/pi-tui";
|
|
@@ -3883,6 +3893,26 @@ async function removeGatewayPortFile(nekoDir, serverId) {
|
|
|
3883
3893
|
}
|
|
3884
3894
|
var init_port_file = () => {};
|
|
3885
3895
|
|
|
3896
|
+
// packages/gateway/src/file-search-help.ts
|
|
3897
|
+
function fileSearchInstallHelp(platform = process.platform) {
|
|
3898
|
+
const docs = "https://github.com/sharkdp/fd#installation";
|
|
3899
|
+
let install;
|
|
3900
|
+
switch (platform) {
|
|
3901
|
+
case "win32":
|
|
3902
|
+
install = "\u8BF7\u6267\u884C\uFF1Awinget install sharkdp.fd\u3002";
|
|
3903
|
+
break;
|
|
3904
|
+
case "darwin":
|
|
3905
|
+
install = "\u8BF7\u6267\u884C\uFF1Abrew install fd\u3002";
|
|
3906
|
+
break;
|
|
3907
|
+
case "linux":
|
|
3908
|
+
install = `Debian/Ubuntu \u8BF7\u6267\u884C\uFF1Asudo apt install fd-find\u3002\u5176\u4ED6\u53D1\u884C\u7248\u8BF7\u53C2\u8003\uFF1A${docs} \u3002`;
|
|
3909
|
+
break;
|
|
3910
|
+
default:
|
|
3911
|
+
install = `\u5B89\u88C5\u65B9\u6CD5\u8BF7\u53C2\u8003\uFF1A${docs} \u3002`;
|
|
3912
|
+
}
|
|
3913
|
+
return `\u672A\u627E\u5230 fd \u6216 fdfind\uFF0C\u6682\u65F6\u65E0\u6CD5\u4F7F\u7528 @ \u6587\u4EF6\u8865\u5168\u3002\u8BF7\u5728\u8FD0\u884C neko \u7684\u7535\u8111\u4E0A\u5B89\u88C5\u3002${install}\u5B89\u88C5\u540E\u91CD\u65B0\u6253\u5F00\u7EC8\u7AEF\u5E76\u91CD\u542F neko\u3002`;
|
|
3914
|
+
}
|
|
3915
|
+
|
|
3886
3916
|
// packages/gateway/src/workspaces.ts
|
|
3887
3917
|
import { constants as constants3 } from "fs";
|
|
3888
3918
|
import { access, readdir as readdir2, stat as stat2 } from "fs/promises";
|
|
@@ -3950,6 +3980,7 @@ var init_workspaces = __esm(() => {
|
|
|
3950
3980
|
// packages/gateway/src/server-services.ts
|
|
3951
3981
|
import {
|
|
3952
3982
|
createRemoteServiceEndpoint,
|
|
3983
|
+
RemoteServiceError,
|
|
3953
3984
|
RemoteServiceProvider,
|
|
3954
3985
|
replicatedState
|
|
3955
3986
|
} from "@earendil-works/chord";
|
|
@@ -4048,6 +4079,10 @@ async function createNekoServerServices(options) {
|
|
|
4048
4079
|
if (!roots.some((w) => w.path === input.workspaceRoot))
|
|
4049
4080
|
throw new Error("Unknown workspace.");
|
|
4050
4081
|
return await searchWorkspaceFiles(input.workspaceRoot, input.query, AbortSignal.any([controller.signal, ...ctx.abortSignal ? [ctx.abortSignal] : []]));
|
|
4082
|
+
} catch (error) {
|
|
4083
|
+
if (error instanceof MissingFileSearchDependencyError)
|
|
4084
|
+
throw new RemoteServiceError("service_not_allowed", fileSearchInstallHelp());
|
|
4085
|
+
throw error;
|
|
4051
4086
|
} finally {
|
|
4052
4087
|
fileQueries--;
|
|
4053
4088
|
if (fileQuery === controller)
|
|
@@ -4241,7 +4276,7 @@ import { open as open2 } from "fs/promises";
|
|
|
4241
4276
|
import { basename as basename4, extname } from "path";
|
|
4242
4277
|
import {
|
|
4243
4278
|
createRemoteServiceEndpoint as createRemoteServiceEndpoint2,
|
|
4244
|
-
RemoteServiceError,
|
|
4279
|
+
RemoteServiceError as RemoteServiceError2,
|
|
4245
4280
|
RemoteServiceProvider as RemoteServiceProvider2,
|
|
4246
4281
|
replicatedState as replicatedState2
|
|
4247
4282
|
} from "@earendil-works/chord";
|
|
@@ -4313,7 +4348,7 @@ async function openNekoSessionHandle(options) {
|
|
|
4313
4348
|
try {
|
|
4314
4349
|
return action();
|
|
4315
4350
|
} catch (error) {
|
|
4316
|
-
throw new
|
|
4351
|
+
throw new RemoteServiceError2("service_invalid_value", error instanceof Error ? error.message : "Image upload failed");
|
|
4317
4352
|
}
|
|
4318
4353
|
};
|
|
4319
4354
|
const createProvider = () => {
|
|
@@ -4370,7 +4405,7 @@ async function openNekoSessionHandle(options) {
|
|
|
4370
4405
|
try {
|
|
4371
4406
|
await session.compact(instructions);
|
|
4372
4407
|
} catch (error) {
|
|
4373
|
-
throw new
|
|
4408
|
+
throw new RemoteServiceError2("service_invalid_value", error instanceof Error ? error.message : "Cannot compact");
|
|
4374
4409
|
}
|
|
4375
4410
|
},
|
|
4376
4411
|
beginImage: async (input) => safeUpload(() => uploads.begin(input)),
|
|
@@ -4379,15 +4414,15 @@ async function openNekoSessionHandle(options) {
|
|
|
4379
4414
|
releaseImage: async (id) => uploads.release(id),
|
|
4380
4415
|
getImage: async (input) => {
|
|
4381
4416
|
if (!Number.isSafeInteger(input.offset) || input.offset < 0 || !Number.isSafeInteger(input.contentIndex) || input.contentIndex < 0)
|
|
4382
|
-
throw new
|
|
4417
|
+
throw new RemoteServiceError2("service_invalid_value", "Invalid image range");
|
|
4383
4418
|
const entry = history.get(input.entryId);
|
|
4384
4419
|
const content = entry?.model?.[0]?.content;
|
|
4385
4420
|
const image = Array.isArray(content) ? content[input.contentIndex] : undefined;
|
|
4386
4421
|
if (image?.type !== "image")
|
|
4387
|
-
throw new
|
|
4422
|
+
throw new RemoteServiceError2("service_invalid_value", "Image is not part of this conversation");
|
|
4388
4423
|
const bytes = Buffer.from(image.data, "base64");
|
|
4389
4424
|
if (input.offset > bytes.length)
|
|
4390
|
-
throw new
|
|
4425
|
+
throw new RemoteServiceError2("service_invalid_value", "Invalid image range");
|
|
4391
4426
|
return {
|
|
4392
4427
|
data: bytes.subarray(input.offset, input.offset + IMAGE_CHUNK_BYTES).toString("base64"),
|
|
4393
4428
|
total: bytes.length,
|
|
@@ -4407,8 +4442,8 @@ async function openNekoSessionHandle(options) {
|
|
|
4407
4442
|
uploads.release(id);
|
|
4408
4443
|
} catch (error) {
|
|
4409
4444
|
if (error instanceof Error && error.message.startsWith("DEEPSEEK_KEY_REQUIRED:"))
|
|
4410
|
-
throw new
|
|
4411
|
-
throw new
|
|
4445
|
+
throw new RemoteServiceError2("service_invalid_value", "DEEPSEEK_KEY_REQUIRED: Configure DeepSeek in /login or Web settings.");
|
|
4446
|
+
throw new RemoteServiceError2("service_invalid_value", error instanceof Error ? error.message : "Cannot submit message");
|
|
4412
4447
|
}
|
|
4413
4448
|
await onActivity();
|
|
4414
4449
|
},
|
|
@@ -4427,7 +4462,7 @@ async function openNekoSessionHandle(options) {
|
|
|
4427
4462
|
configure: async (change) => {
|
|
4428
4463
|
const applied = await runtime.configureConversation(session.id, change);
|
|
4429
4464
|
if (!applied) {
|
|
4430
|
-
throw new
|
|
4465
|
+
throw new RemoteServiceError2("service_invalid_value", `Session ${String(session.id)} is unavailable or archived`);
|
|
4431
4466
|
}
|
|
4432
4467
|
}
|
|
4433
4468
|
});
|
|
@@ -6580,7 +6615,7 @@ switch (command2) {
|
|
|
6580
6615
|
}
|
|
6581
6616
|
case "--version":
|
|
6582
6617
|
case "-v":
|
|
6583
|
-
console.log("0.2.
|
|
6618
|
+
console.log("0.2.2");
|
|
6584
6619
|
break;
|
|
6585
6620
|
case undefined:
|
|
6586
6621
|
case "-h":
|
package/package.json
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"packageManager": "bun@1.4.2",
|
|
26
26
|
"trustedDependencies": [],
|
|
27
|
-
"version": "0.2.
|
|
27
|
+
"version": "0.2.2",
|
|
28
28
|
"description": "A local AI coding assistant with terminal and web interfaces, powered by Pi and Bun.",
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"repository": {
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
-
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:"SF Pro Text", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;--font-mono:ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;--spacing:.25rem;--container-sm:24rem;--container-lg:32rem;--text-xs:.75rem;--text-xs--line-height:1.4;--text-sm:.8125rem;--text-sm--line-height:1.5;--text-base:.875rem;--text-lg:1rem;--text-xl:1.25rem;--text-xl--line-height:1.4;--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--tracking-tight:-.025em;--radius-lg:.5rem;--radius-xl:.625rem;--radius-2xl:1rem;--animate-spin:spin 1s linear infinite;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-base:#fefcfe;--color-surface:#fff;--color-sakura-50:#fff1f3;--color-sakura-100:#ffe5ea;--color-sakura-200:#ffd1da;--color-sakura-300:#ffb7c5;--color-sakura-500:#da7f93;--color-sakura-600:#c26279;--color-sakura-700:#a74660;--color-sakura-800:#8b314a;--color-sakura-900:#6e1d36;--color-tianyi-50:#eff8fe;--color-tianyi-100:#dcf3ff;--color-tianyi-200:#b4e6ff;--color-tianyi-300:#6cf;--color-tianyi-500:#059fd7;--color-tianyi-600:#0086bf;--color-tianyi-700:#006ea7;--color-tianyi-800:#00598f;--color-tianyi-900:#004778;--color-ink-50:#f7f4f8;--color-ink-100:#f0ebf1;--color-ink-200:#e2dbe4;--color-ink-400:#9e95a0;--color-ink-500:#7a717c;--color-ink-600:#6a5f6c;--color-ink-700:#554857;--color-ink-800:#443947;--color-ink-900:#322b34;--breakpoint-mobile:48rem;--radius-control:.625rem;--radius-card:1rem;--radius-bubble:1.25rem;--shadow-soft:0 2px 10px 0 oklch(53% .13 6.2/.08);--shadow-bubble-user:0 3px 16px 0 oklch(53% .13 6.2/.16), 0 1px 4px 0 oklch(53% .13 6.2/.1);--shadow-bubble-assistant:0 3px 16px 0 oklch(43% .14 232.7/.12), 0 1px 4px 0 oklch(53% .13 6.2/.06);--shadow-lift:0 10px 32px 0 oklch(53% .13 6.2/.14);--animate-blink:blink 1.2s step-end infinite}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components{.chrome{color:var(--color-ink-900);background:var(--color-base);font-size:var(--text-sm)}.chrome button,.chrome a,.chrome input{border-radius:var(--radius-control)}.chrome button,.chrome a{cursor:pointer}.chrome button:disabled{cursor:default;opacity:.45}.chrome :is(button,a,input){outline:none}.chrome :is(button,a,input):focus-visible{box-shadow:0 0 0 2px var(--color-base), 0 0 0 4px var(--color-sakura-500)}.chrome input:not([type=checkbox]){background:var(--color-surface);border:1px solid var(--color-sakura-200);min-width:0;padding:7px 9px}.chrome svg{flex-shrink:0}.sidebar{--sidebar-width:256px;width:var(--sidebar-width);border-right:1px solid var(--color-sakura-200);flex-direction:column;flex-shrink:0;display:flex}.sidebar-top{padding:12px 10px 6px}.workspace-heading{align-items:center;gap:2px;margin-bottom:14px;display:flex}.workspace-trigger{flex:1;align-items:center;gap:8px;min-width:0;padding:6px 3px;font-weight:600;display:flex}.workspace-mark{background:var(--color-sakura-100);color:var(--color-sakura-800);border-radius:var(--radius-control);padding:5px;display:inline-flex}.icon-btn{width:28px;height:28px;color:var(--color-ink-500);flex-shrink:0;justify-content:center;align-items:center;display:inline-flex}.chrome :is(.chrome-row,.icon-btn,.workspace-trigger,.workspace-option):hover:not(:disabled){background:var(--color-sakura-50)}.chrome-row{text-align:left;align-items:center;gap:8px;width:100%;min-height:32px;padding:5px 8px;text-decoration:none;display:flex}.search-box{color:var(--color-ink-500);align-items:center;gap:7px;margin-top:8px;padding:0 7px;display:flex}.chrome .search-box input{width:100%;font-size:var(--text-xs);background:0 0;border:0;padding:5px 0}.section-label{font-size:var(--text-xs);color:var(--color-ink-500);justify-content:space-between;padding:12px 18px 6px;font-weight:600;display:flex}.session-scroll{flex:1;min-height:0;padding:2px 8px;overflow-y:auto}.session-list{margin:0;padding:0;list-style:none}.session-row{border-radius:var(--radius-control);align-items:center;margin:1px 0;display:flex}.session-row:hover{background:var(--color-sakura-50)}.chrome .is-active{background:var(--color-sakura-100);font-weight:600}.session-select{flex:1;min-width:0}.row-more{opacity:0;margin-right:3px}.session-row:hover .row-more,.session-row:focus-within .row-more{opacity:1}.sidebar-bottom{border-top:1px solid var(--color-sakura-200);padding:10px}.sidebar-bottom .path-text{max-height:44px;padding:0 7px 7px;font-size:10px;display:block;overflow:auto}.path-text{overflow-wrap:anywhere;color:var(--color-ink-500);font-size:var(--text-xs)}.empty-text{color:var(--color-ink-500);text-align:center;font-size:var(--text-xs);padding:24px 12px}.topbar{border-bottom:1px solid var(--color-sakura-200);background:var(--color-surface);align-items:center;gap:10px;min-height:52px;padding:10px 16px;display:flex}.topbar-path{align-items:center;gap:7px;min-width:0;max-width:40%;display:flex}.conn-status{font-size:var(--text-xs);white-space:nowrap;color:var(--color-ink-500);align-items:center;gap:5px;margin-left:auto;display:flex}.conn-status:before{content:"";background:var(--color-ink-400);border-radius:50%;width:5px;height:5px}.conn-status.is-connected:before{background:var(--color-tianyi-600)}.conn-status.is-error:before{background:var(--color-sakura-600)}.popover{z-index:100;border:1px solid var(--color-sakura-200);background:var(--color-surface);border-radius:var(--radius-card);width:280px;max-width:calc(100vw - 16px);max-height:calc(100dvh - 16px);box-shadow:var(--shadow-lift);padding:5px;position:fixed;overflow-y:auto}.popover .section-label{padding:8px}.workspace-options{max-height:45dvh;overflow:auto}.workspace-option{text-align:left;align-items:center;gap:10px;width:100%;padding:9px;display:flex}.workspace-option>span:first-of-type{flex:1;min-width:0}.workspace-option strong,.workspace-option small{overflow-wrap:anywhere;display:block}.workspace-option small{color:var(--color-ink-500);margin-top:2px;font-size:10px;font-weight:400}.popover .add-workspace{border-top:1px solid var(--color-sakura-200);border-radius:0;margin-top:5px}.dialog{border:1px solid var(--color-sakura-200);border-radius:var(--radius-card);background:var(--color-surface);width:min(640px,100vw - 32px);max-height:calc(100dvh - 32px);box-shadow:var(--shadow-lift);margin:auto;padding:0}.dialog[open]{flex-direction:column;display:flex}.dialog::backdrop{background:#322b3454}.dialog-heading{border-bottom:1px solid var(--color-sakura-200);flex-shrink:0;justify-content:space-between;align-items:center;padding:14px 18px;display:flex}.dialog-heading h2{font-weight:600;font-size:var(--text-lg)}.picker-controls{flex-shrink:0;padding:12px 18px}.picker-controls>p{font-size:var(--text-xs);margin-bottom:8px}.breadcrumbs{white-space:nowrap;gap:2px;padding:3px 0 8px;display:flex;overflow-x:auto}.breadcrumbs button{color:var(--color-ink-500);padding:2px 3px}.path-form{gap:6px;display:flex}.path-form input{flex:1}.filter-row{align-items:center;gap:12px;margin-top:10px;display:flex}.filter-row input:not([type=checkbox]){flex:1}.filter-row label{white-space:nowrap;font-size:var(--text-xs);align-items:center;gap:5px;display:flex}.folder-list{border-top:1px solid var(--color-sakura-200);min-inline-size:0;height:300px;min-height:100px;padding:4px 12px;overflow-y:auto}.picker-footer{border-top:1px solid var(--color-sakura-200);flex-shrink:0;padding:14px 18px}.picker-footer .path-text{max-height:50px;margin:3px 0 12px;overflow-y:auto}.actions{justify-content:flex-end;gap:8px;display:flex}.btn-outline{border:1px solid var(--color-sakura-200);background:var(--color-surface);color:var(--color-ink-700);padding:6px 12px;font-weight:500}.btn-outline:hover:not(:disabled){background:var(--color-sakura-50)}.error-text{color:var(--color-sakura-800);overflow-wrap:anywhere;padding:10px 0}.error-text .btn-outline{margin-left:10px}.confirm-body{padding:20px}.confirm-body .actions{margin-top:24px}.drawer{--sidebar-width:min(300px, calc(100vw - 48px));width:var(--sidebar-width);background:var(--color-base);border-radius:0;height:100dvh;max-height:100dvh;margin:0 auto 0 0}@media (hover:none){.row-more{opacity:1}.chrome :is(.icon-btn,.chrome-row,.btn-outline,.workspace-option){min-height:44px}.icon-btn{min-width:44px}}@media (width<=48rem){.topbar{gap:6px;padding:8px}.conn-status{font-size:10px}.dialog:not(.drawer){width:calc(100vw - 16px);max-height:calc(100dvh - 16px)}.picker-controls,.picker-footer{padding:12px}.folder-list{height:min(300px,40dvh)}}.session-select{align-items:flex-start;padding-top:8px;padding-bottom:8px;position:relative}.session-copy{text-align:left;flex-direction:column;flex:1;gap:3px;min-width:0;display:flex}.session-meta{font-size:var(--text-xs);color:var(--color-ink-500);white-space:nowrap;font-weight:400}.session-tooltip{z-index:110;box-sizing:border-box;width:min(calc(var(--sidebar-width,256px) - 24px), calc(100vw - 24px));border:1px solid var(--color-sakura-200);border-radius:var(--radius-control);background:var(--color-surface);color:var(--color-ink-900);font-size:var(--text-xs);white-space:normal;overflow-wrap:anywhere;box-shadow:var(--shadow-soft);pointer-events:none;padding:10px;font-weight:400;display:none;position:fixed;bottom:80px;left:12px}.session-select:hover .session-tooltip,.session-select:focus-visible .session-tooltip{display:block}.session-details{overflow-wrap:anywhere;max-width:280px;padding:8px 10px}.session-details strong,.session-details small{display:block}.session-details small{color:var(--color-ink-500);margin-top:4px}}@layer utilities{.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.relative{position:relative}.top-0{top:0}.right-0{right:0}.z-50{z-index:50}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.mx-auto{margin-inline:auto}.my-2{margin-block:calc(var(--spacing) * 2)}.mt-1{margin-top:var(--spacing)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-\[14vh\]{margin-top:14vh}.mb-1{margin-bottom:var(--spacing)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.hidden{display:none}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.h-10{height:calc(var(--spacing) * 10)}.h-16{height:calc(var(--spacing) * 16)}.h-dvh{height:100dvh}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-\[65dvh\]{max-height:65dvh}.min-h-0{min-height:0}.min-h-4{min-height:calc(var(--spacing) * 4)}.min-h-7{min-height:calc(var(--spacing) * 7)}.min-h-10{min-height:calc(var(--spacing) * 10)}.min-h-dvh{min-height:100dvh}.w-10{width:calc(var(--spacing) * 10)}.w-20{width:calc(var(--spacing) * 20)}.w-28{width:calc(var(--spacing) * 28)}.w-full{width:100%}.max-w-48{max-width:calc(var(--spacing) * 48)}.max-w-64{max-width:calc(var(--spacing) * 64)}.max-w-full{max-width:100%}.max-w-lg{max-width:var(--container-lg)}.max-w-sm{max-width:var(--container-sm)}.min-w-0{min-width:0}.min-w-max{min-width:max-content}.flex-1{flex:1}.shrink-0{flex-shrink:0}.animate-spin{animation:var(--animate-spin)}.resize{resize:both}.resize-none{resize:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 5) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-2{column-gap:calc(var(--spacing) * 2)}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-y-1{row-gap:var(--spacing)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-card{border-radius:var(--radius-card)}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-ink-200{border-color:var(--color-ink-200)}.border-sakura-100{border-color:var(--color-sakura-100)}.border-sakura-200{border-color:var(--color-sakura-200)}.border-sakura-200\/70{border-color:#ffd1dab3}@supports (color:color-mix(in lab, red, red)){.border-sakura-200\/70{border-color:color-mix(in oklab, var(--color-sakura-200) 70%, transparent)}}.border-sakura-300{border-color:var(--color-sakura-300)}.border-sakura-500{border-color:var(--color-sakura-500)}.border-tianyi-100{border-color:var(--color-tianyi-100)}.border-tianyi-200{border-color:var(--color-tianyi-200)}.border-tianyi-300{border-color:var(--color-tianyi-300)}.bg-base{background-color:var(--color-base)}.bg-base\/70{background-color:#fefcfeb3}@supports (color:color-mix(in lab, red, red)){.bg-base\/70{background-color:color-mix(in oklab, var(--color-base) 70%, transparent)}}.bg-ink-50{background-color:var(--color-ink-50)}.bg-ink-100{background-color:var(--color-ink-100)}.bg-sakura-50{background-color:var(--color-sakura-50)}.bg-sakura-50\/70{background-color:#fff1f3b3}@supports (color:color-mix(in lab, red, red)){.bg-sakura-50\/70{background-color:color-mix(in oklab, var(--color-sakura-50) 70%, transparent)}}.bg-sakura-100{background-color:var(--color-sakura-100)}.bg-surface{background-color:var(--color-surface)}.bg-surface\/80{background-color:#fffc}@supports (color:color-mix(in lab, red, red)){.bg-surface\/80{background-color:color-mix(in oklab, var(--color-surface) 80%, transparent)}}.bg-tianyi-50{background-color:var(--color-tianyi-50)}.bg-tianyi-100{background-color:var(--color-tianyi-100)}.object-contain{object-fit:contain}.object-cover{object-fit:cover}.p-1{padding:var(--spacing)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-5{padding:calc(var(--spacing) * 5)}.px-1{padding-inline:var(--spacing)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-8{padding-block:calc(var(--spacing) * 8)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.break-words{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-base{color:var(--color-base)}.text-ink-400{color:var(--color-ink-400)}.text-ink-500{color:var(--color-ink-500)}.text-ink-600{color:var(--color-ink-600)}.text-ink-700{color:var(--color-ink-700)}.text-ink-900{color:var(--color-ink-900)}.text-sakura-700{color:var(--color-sakura-700)}.text-sakura-800{color:var(--color-sakura-800)}.text-sakura-900{color:var(--color-sakura-900)}.text-tianyi-500{color:var(--color-tianyi-500)}.text-tianyi-600{color:var(--color-tianyi-600)}.text-tianyi-700{color:var(--color-tianyi-700)}.text-tianyi-800{color:var(--color-tianyi-800)}.text-tianyi-900{color:var(--color-tianyi-900)}.italic{font-style:italic}.no-underline{text-decoration-line:none}.underline{text-decoration-line:underline}.shadow-soft{--tw-shadow:0 2px 10px 0 var(--tw-shadow-color,oklch(53% .13 6.2/.08));box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-sakura-300{--tw-ring-color:var(--color-sakura-300)}.empty\:mb-0:empty{margin-bottom:0}@media (hover:hover){.hover\:bg-sakura-50:hover{background-color:var(--color-sakura-50)}}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:opacity-50:disabled{opacity:.5}@media (width>=40rem){.sm\:p-4{padding:calc(var(--spacing) * 4)}.sm\:py-12{padding-block:calc(var(--spacing) * 12)}}.\[\&\>button\]\:max-w-full>button{max-width:100%}}:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light}html,body{height:100%}body{background-color:var(--color-base);color:var(--color-ink-900);font-family:var(--font-sans);font-size:var(--text-base);-webkit-font-smoothing:antialiased;background-image:linear-gradient(150deg,#fff 0%,#fff5f8 42%,#eff9ff 100%);background-attachment:fixed}.chat-column{width:100%;max-width:48rem;margin-inline:auto}.chat-bubble{max-width:85%}@media (width>=40rem){.chat-bubble{max-width:75%}}:root{accent-color:var(--color-sakura-600)}::selection{background-color:var(--color-sakura-200);color:var(--color-sakura-900)}*{scrollbar-width:thin;scrollbar-color:var(--color-sakura-200) transparent}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background-color:var(--color-sakura-200);border-radius:8px}::-webkit-scrollbar-thumb:hover{background-color:var(--color-sakura-300)}.focus-neko{outline:none}.focus-neko:focus-visible{box-shadow:0 0 0 2px var(--color-base), 0 0 0 4px var(--color-sakura-500)}@media (forced-colors:active){.focus-neko:focus-visible{box-shadow:none;outline:2px solid highlight}}input,textarea,select,button{font:inherit;color:inherit}.bubble-user{background-image:linear-gradient(135deg, var(--color-sakura-100) 0%, var(--color-sakura-200) 100%);border:1px solid var(--color-sakura-300);color:var(--color-sakura-900);border-radius:var(--radius-bubble);box-shadow:var(--shadow-bubble-user);border-bottom-right-radius:.375rem}.bubble-assistant{background-color:var(--color-surface);border:1px solid var(--color-tianyi-200);color:var(--color-ink-900);border-radius:var(--radius-bubble);box-shadow:var(--shadow-bubble-assistant);border-bottom-left-radius:.375rem}.btn-primary{background-image:linear-gradient(135deg, var(--color-sakura-200) 0%, var(--color-tianyi-200) 100%);border:1px solid #ffd4dc}@supports (color:color-mix(in lab, red, red)){.btn-primary{border:1px solid color-mix(in oklab, var(--color-sakura-300) 60%, white)}}.btn-primary{color:var(--color-sakura-900);box-shadow:inset 0 1px 0 #ffffffbf, var(--shadow-soft)}.btn-primary:hover{filter:brightness(1.05);box-shadow:inset 0 1px 0 #ffffffbf, var(--shadow-lift)}.btn-primary:disabled{opacity:.45;filter:saturate(.5)}.btn-stop{background-color:var(--color-surface);border:1px solid var(--color-sakura-300);color:var(--color-sakura-800)}.btn-stop:hover{background-color:var(--color-sakura-50)}.btn-lift{transition:transform .16s,box-shadow .16s,filter .16s,background-color .16s}.btn-lift:hover{transform:translateY(-1px)}.btn-lift:active{transform:translateY(0)scale(.97)}@keyframes msg-in-right{0%{opacity:0;transform:translate(10px,8px)}to{opacity:1;transform:none}}@keyframes msg-in-left{0%{opacity:0;transform:translate(-10px,8px)}to{opacity:1;transform:none}}.anim-user{animation:.34s cubic-bezier(.2,.8,.3,1) backwards msg-in-right}.anim-other{animation:.34s cubic-bezier(.2,.8,.3,1) backwards msg-in-left}@keyframes stream-in{0%{opacity:0;transform:translateY(10px)scale(.985)}to{opacity:1;transform:none}}.stream-block{animation:.38s ease-out backwards stream-in}@keyframes dot-bounce{0%,60%,to{opacity:.55;transform:translateY(0)}30%{opacity:1;transform:translateY(-2.5px)}}.dots{align-items:center;gap:3px;display:inline-flex}.dots>span{background-color:var(--color-sakura-500);border-radius:9999px;width:5px;height:5px;animation:1.2s ease-in-out infinite dot-bounce}.dots>span:nth-child(2){animation-delay:.15s}.dots>span:nth-child(3){animation-delay:.3s}.logo-gradient{color:#0000;background-image:linear-gradient(115deg,#c26279 0%,#da7f93 35%,#059fd7 100%);-webkit-background-clip:text;background-clip:text}@keyframes cat-float{0%,to{transform:translateY(0)}50%{transform:translateY(-4px)}}.welcome-cat{animation:3.2s ease-in-out infinite cat-float}.discrete-in{opacity:1;transition:opacity .25s ease, transform .25s ease, display .25s ease allow-discrete;transform:none}@starting-style{.discrete-in{opacity:0;transform:translateY(6px)}}.md{overflow-wrap:anywhere;line-height:1.75}.md>:first-child{margin-top:0}.md>:last-child{margin-bottom:0}.md p{margin:.5rem 0}.md h1,.md h2,.md h3,.md h4{color:var(--color-sakura-800);margin:.9rem 0 .4rem;font-weight:700}.md h1{font-size:1.25rem}.md h2{font-size:1.125rem}.md h3,.md h4{font-size:1rem}.md a{color:var(--color-tianyi-800);text-decoration:underline;-webkit-text-decoration-color:var(--color-sakura-300);-webkit-text-decoration-color:var(--color-sakura-300);-webkit-text-decoration-color:var(--color-sakura-300);text-decoration-color:var(--color-sakura-300);text-underline-offset:3px;border-radius:2px}.md a:hover{background-color:var(--color-tianyi-100)}.md ul,.md ol{margin:.5rem 0;padding-left:1.4rem}.md ul{list-style:outside}.md ol{list-style:decimal}.md li{margin:.2rem 0}.md li::marker{color:var(--color-sakura-500)}.md blockquote{border-left:3px solid var(--color-sakura-300);background-color:var(--color-sakura-50);color:var(--color-ink-700);border-radius:0 .625rem .625rem 0;margin:.6rem 0;padding:.2rem .9rem}.md code{font-family:var(--font-mono);background-color:var(--color-ink-100);color:var(--color-ink-800);border-radius:.25rem;padding:.0625rem .25rem;font-size:.85em}.md pre{background-color:var(--color-tianyi-50);color:var(--color-ink-900);border:1px solid var(--color-tianyi-200);border-radius:.75rem;margin:.6rem 0;padding:.75rem .9rem;font-size:.85rem;line-height:1.6;overflow-x:auto}.md pre code{color:inherit;font-size:inherit;background:0 0;padding:0}.hljs{color:var(--color-ink-900);background:0 0}.hljs-comment,.hljs-quote{color:var(--color-ink-600);font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-literal,.hljs-tag,.hljs-name{color:var(--color-sakura-800)}.hljs-string,.hljs-doctag,.hljs-regexp{color:var(--color-tianyi-800)}.hljs-number,.hljs-symbol,.hljs-bullet,.hljs-link{color:var(--color-tianyi-700)}.hljs-title,.hljs-section,.hljs-attr{color:var(--color-sakura-700)}.hljs-built_in,.hljs-type,.hljs-attribute,.hljs-selector-class,.hljs-selector-id,.hljs-meta{color:var(--color-tianyi-700)}.hljs-variable,.hljs-template-variable,.hljs-params,.hljs-subst{color:var(--color-ink-900)}.hljs-addition{color:#117555;background-color:oklch(50% .1 165/.08)}.hljs-deletion{color:var(--color-sakura-800);background-color:oklch(53% .13 6.2/.08)}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.md hr{border:none;border-top:1px dashed var(--color-sakura-300);margin:.9rem 0}.md table{border-collapse:collapse;margin:.6rem 0;font-size:.9rem}.md th,.md td{border:1px solid var(--color-tianyi-200);padding:.3rem .7rem}.md th{background-color:var(--color-tianyi-50);color:var(--color-tianyi-900);font-weight:600}.stream-caret{background-color:var(--color-sakura-500);vertical-align:-.15em;width:.5rem;height:1rem;animation:var(--animate-blink);border-radius:2px;margin-left:2px;display:inline-block}.chat-row{content-visibility:auto;contain-intrinsic-size:auto 120px}.skip-link{z-index:200;border-radius:var(--radius-control);border:1px solid var(--color-sakura-300);background:var(--color-surface);color:var(--color-sakura-800);font-size:var(--text-sm);box-shadow:var(--shadow-soft);padding:8px 12px;font-weight:500;transition:top .15s;position:absolute;top:-48px;left:8px}.skip-link:focus-visible{box-shadow:0 0 0 2px var(--color-base), 0 0 0 4px var(--color-sakura-500);outline:none;top:8px}@media (prefers-reduced-motion:reduce){.anim-user,.anim-other,.stream-block,.welcome-cat{animation:none}.dots>span{opacity:1;animation:none}.stream-caret,.animate-spin{animation:none}.btn-lift,.discrete-in{transition:none}.btn-lift:hover,.btn-lift:active{transform:none}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@keyframes spin{to{transform:rotate(360deg)}}@keyframes blink{0%,to{opacity:1}50%{opacity:0}}
|