@oversk7/pi-web-dsh-style 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/THIRD_PARTY_NOTICES.md +4 -0
- package/attachment-parser.ts +210 -0
- package/attachment-store.ts +67 -24
- package/background-jobs.ts +52 -0
- package/extension-settings.ts +50 -0
- package/file-preview.ts +7 -1
- package/package.json +13 -3
- package/pi-rpc.ts +7 -5
- package/server.ts +206 -49
- package/terminal-proxy.ts +50 -0
- package/transcript.ts +13 -0
- package/web/app.css +187 -55
- package/web/app.js +5097 -4619
- package/web/assets/markdown.LICENSE.txt +200 -0
- package/web/assets/markdown.js +25 -0
- package/web/assets/themes/sakura.webp +0 -0
- package/web/assets/themes/starlight.webp +0 -0
- package/web/index.html +5 -1
- package/web/markdown.ts +118 -0
- package/web/slash-commands.d.ts +11 -0
- package/web/slash-commands.js +46 -0
- package/web/themes.css +158 -0
|
Binary file
|
|
Binary file
|
package/web/index.html
CHANGED
|
@@ -8,11 +8,15 @@
|
|
|
8
8
|
<link rel="manifest" href="/manifest.webmanifest" />
|
|
9
9
|
<title>Pi Web</title>
|
|
10
10
|
<link rel="stylesheet" href="/app.css" />
|
|
11
|
+
<link rel="stylesheet" href="/themes.css" />
|
|
11
12
|
</head>
|
|
12
13
|
<body>
|
|
13
14
|
<script>
|
|
14
15
|
(() => {
|
|
15
|
-
const
|
|
16
|
+
const saved = localStorage.getItem("pi-web-theme");
|
|
17
|
+
const preference = ["light", "dark", "system"].includes(saved) ? saved : "system";
|
|
18
|
+
const style = localStorage.getItem("pi-web-theme-style");
|
|
19
|
+
document.body.dataset.themeStyle = ["classic", "sakura", "starlight"].includes(style) ? style : "classic";
|
|
16
20
|
const systemDark = preference === "system" && matchMedia("(prefers-color-scheme: dark)").matches;
|
|
17
21
|
const dark = preference === "dark" || systemDark;
|
|
18
22
|
document.documentElement.style.colorScheme = dark ? "dark" : "light";
|
package/web/markdown.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import MarkdownIt from "markdown-it";
|
|
2
|
+
import hljs from "highlight.js/lib/common";
|
|
3
|
+
import dockerfile from "highlight.js/lib/languages/dockerfile";
|
|
4
|
+
import powershell from "highlight.js/lib/languages/powershell";
|
|
5
|
+
|
|
6
|
+
hljs.registerLanguage("dockerfile", dockerfile);
|
|
7
|
+
hljs.registerLanguage("powershell", powershell);
|
|
8
|
+
|
|
9
|
+
function localFileLink(target: string) {
|
|
10
|
+
let value = target.trim();
|
|
11
|
+
let line: number | null = null;
|
|
12
|
+
const location = /#L(\d+)(?:C\d+)?$/i.exec(value) || /:(\d+)(?::\d+)?$/.exec(value);
|
|
13
|
+
if (location) {
|
|
14
|
+
line = Number(location[1]);
|
|
15
|
+
value = value.slice(0, location.index);
|
|
16
|
+
}
|
|
17
|
+
if (/^file:\/\/\//i.test(value)) {
|
|
18
|
+
try {
|
|
19
|
+
value = decodeURIComponent(new URL(value).pathname).replace(/^\/([A-Za-z]:[\\/])/, "$1");
|
|
20
|
+
} catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
value = value.replace(/^\/([A-Za-z]:[\\/])/, "$1");
|
|
25
|
+
if (!/^[A-Za-z]:[\\/]/.test(value) && !/^\\\\[^\\]+\\[^\\]+/.test(value)) return null;
|
|
26
|
+
const href = `/api/fs/view?path=${encodeURIComponent(value)}${line ? `#L${line}` : ""}`;
|
|
27
|
+
return { path: value, line, href };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const parser = new MarkdownIt({ html: false, breaks: false, linkify: true });
|
|
31
|
+
const InlineState = parser.inline.State;
|
|
32
|
+
parser.inline.State = class extends InlineState {
|
|
33
|
+
scanDelims(start: number, canSplitWord: boolean) {
|
|
34
|
+
const scanned = super.scanDelims(start, canSplitWord);
|
|
35
|
+
if (this.src[start] !== "*" || scanned.length < 2) return scanned;
|
|
36
|
+
const before = this.src.slice(Math.max(0, start - 2), start);
|
|
37
|
+
const end = start + scanned.length;
|
|
38
|
+
const after = end < this.posMax ? String.fromCodePoint(this.src.codePointAt(end)!) : "";
|
|
39
|
+
// Chinese punctuation can border emphasis even beside Latin text or numbers.
|
|
40
|
+
const cjkPunctuation = /[\u2000-\u206f\u3000-\u303f\uff00-\uffef]/u;
|
|
41
|
+
if (/^\p{P}/u.test(after) && (cjkPunctuation.test(after) || /\p{Script=Han}$/u.test(before))) scanned.can_open = true;
|
|
42
|
+
if (/\p{P}$/u.test(before) && (cjkPunctuation.test(before.slice(-1)) || /^\p{Script=Han}/u.test(after))) scanned.can_close = true;
|
|
43
|
+
return scanned;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const escape = parser.utils.escapeHtml;
|
|
47
|
+
const normalizeLink = parser.normalizeLink;
|
|
48
|
+
const validateLink = parser.validateLink;
|
|
49
|
+
parser.normalizeLink = (target) => localFileLink(target) ? target : normalizeLink(target);
|
|
50
|
+
parser.validateLink = (target) => Boolean(localFileLink(target)) || validateLink(target);
|
|
51
|
+
|
|
52
|
+
parser.renderer.rules.link_open = (tokens, index, options, env, renderer) => {
|
|
53
|
+
const token = tokens[index];
|
|
54
|
+
const target = String(token.attrGet("href") || "");
|
|
55
|
+
const local = localFileLink(target);
|
|
56
|
+
if (local) {
|
|
57
|
+
token.attrSet("href", local.href);
|
|
58
|
+
token.attrJoin("class", "md-local-file");
|
|
59
|
+
token.attrSet("data-file-path", local.path);
|
|
60
|
+
token.attrSet("data-file-line", local.line ? String(local.line) : "");
|
|
61
|
+
token.attrSet("title", `${local.path}${local.line ? `:${local.line}` : ""}`);
|
|
62
|
+
} else if (/^https?:\/\//i.test(target)) {
|
|
63
|
+
token.attrSet("target", "_blank");
|
|
64
|
+
token.attrSet("rel", "noopener noreferrer");
|
|
65
|
+
}
|
|
66
|
+
return renderer.renderToken(tokens, index, options);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const renderImage = parser.renderer.rules.image!;
|
|
70
|
+
parser.renderer.rules.image = (tokens, index, options, env, renderer) => {
|
|
71
|
+
const local = localFileLink(String(tokens[index].attrGet("src") || ""));
|
|
72
|
+
if (local) tokens[index].attrSet("src", `/api/fs/view?path=${encodeURIComponent(local.path)}&format=image`);
|
|
73
|
+
tokens[index].attrSet("loading", "lazy");
|
|
74
|
+
tokens[index].attrSet("decoding", "async");
|
|
75
|
+
tokens[index].attrSet("referrerpolicy", "no-referrer");
|
|
76
|
+
return renderImage(tokens, index, options, env, renderer);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
parser.renderer.rules.fence = (tokens, index) => {
|
|
80
|
+
const token = tokens[index];
|
|
81
|
+
const language = token.info.trim().split(/\s+/)[0];
|
|
82
|
+
let code = escape(token.content);
|
|
83
|
+
// Bound synchronous highlighting work while streaming large tool-generated snippets.
|
|
84
|
+
if (language && hljs.getLanguage(language) && token.content.length <= 32 * 1024) {
|
|
85
|
+
code = hljs.highlight(token.content, { language, ignoreIllegals: true }).value;
|
|
86
|
+
}
|
|
87
|
+
const label = language ? `<div class="md-code-language">${escape(language)}</div>` : "";
|
|
88
|
+
return `<div class="md-code-container">${label}<pre class="md-code-block"><code class="hljs">${code}</code></pre></div>\n`;
|
|
89
|
+
};
|
|
90
|
+
parser.renderer.rules.code_block = (tokens, index) => `<pre class="md-code-block"><code>${escape(tokens[index].content)}</code></pre>\n`;
|
|
91
|
+
parser.renderer.rules.table_open = () => '<div class="md-table-wrap"><table>\n';
|
|
92
|
+
parser.renderer.rules.table_close = () => '</table></div>\n';
|
|
93
|
+
|
|
94
|
+
parser.core.ruler.after("inline", "task_lists", (state) => {
|
|
95
|
+
for (let i = 2; i < state.tokens.length; i += 1) {
|
|
96
|
+
const token = state.tokens[i];
|
|
97
|
+
const paragraph = state.tokens[i - 1];
|
|
98
|
+
const item = state.tokens[i - 2];
|
|
99
|
+
if (token.type !== "inline" || paragraph.type !== "paragraph_open" || item.type !== "list_item_open") continue;
|
|
100
|
+
const first = token.children?.[0];
|
|
101
|
+
if (first?.type !== "text") continue;
|
|
102
|
+
const match = /^\[([ xX])\](?:\s+|$)/.exec(first.content);
|
|
103
|
+
if (!match) continue;
|
|
104
|
+
first.content = first.content.slice(match[0].length);
|
|
105
|
+
const checkbox = new state.Token("task_checkbox", "input", 0);
|
|
106
|
+
checkbox.meta = { checked: match[1].toLowerCase() === "x" };
|
|
107
|
+
token.children!.unshift(checkbox);
|
|
108
|
+
item.attrJoin("class", "md-task-item");
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
parser.renderer.rules.task_checkbox = (tokens, index) => {
|
|
112
|
+
const checked = tokens[index].meta!.checked;
|
|
113
|
+
return `<input type="checkbox" disabled${checked ? " checked" : ""} aria-label="${checked ? "已完成" : "未完成"}"/> `;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export function markdown(src: unknown): string {
|
|
117
|
+
return parser.render(String(src ?? ""));
|
|
118
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface WebSlashCommand {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
acceptsArgs?: boolean;
|
|
5
|
+
source: string;
|
|
6
|
+
local: boolean;
|
|
7
|
+
}
|
|
8
|
+
export const webSlashCommands: WebSlashCommand[];
|
|
9
|
+
export const unsupportedSlashCommands: Record<string, string>;
|
|
10
|
+
export function parseSlashCommand(text: string): { name: string; args: string } | null;
|
|
11
|
+
export function builtinCommandError(name: string): string | null;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Shared by the browser and server so built-in commands never fall through to RPC prompts.
|
|
2
|
+
export const webSlashCommands = [
|
|
3
|
+
{ name: "settings", description: "打开界面与运行时设置" },
|
|
4
|
+
{ name: "model", description: "选择当前模型", acceptsArgs: true },
|
|
5
|
+
{ name: "thinking", description: "选择思考强度", acceptsArgs: true },
|
|
6
|
+
{ name: "export", description: "将当前会话下载为 HTML" },
|
|
7
|
+
{ name: "copy", description: "复制最后一条助手回复" },
|
|
8
|
+
{ name: "name", description: "设置当前会话名称", acceptsArgs: true },
|
|
9
|
+
{ name: "session", description: "显示会话统计信息" },
|
|
10
|
+
{ name: "new", description: "在当前工作区创建新会话" },
|
|
11
|
+
{ name: "resume", description: "打开侧栏搜索并切换会话" },
|
|
12
|
+
{ name: "rewind", description: "回溯对话,可选择同步恢复文件" },
|
|
13
|
+
{ name: "tree", description: "打开当前会话的分支树" },
|
|
14
|
+
{ name: "compact", description: "压缩当前会话,可附加压缩要求", acceptsArgs: true },
|
|
15
|
+
{ name: "reload", description: "重新加载当前会话的扩展与配置" },
|
|
16
|
+
].map((command) => ({ ...command, source: "builtin", local: true }));
|
|
17
|
+
|
|
18
|
+
export const unsupportedSlashCommands = {
|
|
19
|
+
"scoped-models": "Web 暂不支持终端模型轮换范围,请使用 /model 选择模型。",
|
|
20
|
+
import: "Web 暂不支持从命令导入 JSONL 文件,请在 Pi 终端执行 /import。",
|
|
21
|
+
share: "Web 暂不支持发布 GitHub gist,请使用 /export 下载会话,或在 Pi 终端执行 /share。",
|
|
22
|
+
fork: "Web 暂不支持创建分叉副本,请在 Pi 终端执行 /fork;同一会话内切换分支可使用 /tree。",
|
|
23
|
+
clone: "Web 暂不支持复制整个会话,请在 Pi 终端执行 /clone。",
|
|
24
|
+
trust: "项目信任设置需要在 Pi 终端中通过 /trust 管理。",
|
|
25
|
+
changelog: "Web 暂不展示 Pi 更新日志,请在 Pi 终端执行 /changelog。",
|
|
26
|
+
hotkeys: "终端快捷键不适用于网页。网页输入框支持 Enter 发送、Shift+Enter 换行,命令菜单支持方向键选择和 Tab 补全。",
|
|
27
|
+
debug: "此调试命令仅支持 Pi 终端。",
|
|
28
|
+
arminsayshi: "此彩蛋命令仅支持 Pi 终端。",
|
|
29
|
+
dementedelves: "此彩蛋命令仅支持 Pi 终端。",
|
|
30
|
+
login: "Web 暂不支持登录流程,请在启动 Pi 的终端执行 /login。",
|
|
31
|
+
logout: "Web 暂不支持注销流程,请在启动 Pi 的终端执行 /logout。",
|
|
32
|
+
quit: "请关闭网页标签页;如需退出 Pi,请在启动 Pi 的终端执行 /quit。",
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export function parseSlashCommand(text) {
|
|
36
|
+
const match = /^\/([^\s]+)(?:\s+([\s\S]*))?$/.exec(text.trim());
|
|
37
|
+
return match ? { name: match[1], args: (match[2] || "").trim() } : null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function builtinCommandError(name) {
|
|
41
|
+
if (Object.hasOwn(unsupportedSlashCommands, name)) return unsupportedSlashCommands[name];
|
|
42
|
+
if (webSlashCommands.some((command) => command.name === name)) {
|
|
43
|
+
return `/${name} 需要由 Web 命令入口执行,请刷新网页后重试。`;
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
package/web/themes.css
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
body[data-theme-style=classic][data-custom-background]{
|
|
2
|
+
--pi-base:#f9fafb;--pi-surface:#fff;--pi-raised:#fff;--pi-soft:#f1f3f5;--pi-sidebar:#f5f6f7;
|
|
3
|
+
--pi-text:#0f1115;--pi-secondary:#50555e;--pi-muted:#656b76;--pi-accent:#416ee5;--pi-on-accent:#fff;
|
|
4
|
+
--pi-tint:#e4edfd;--pi-border:#dbe0e9;--pi-code:#f5f6f8;--pi-code-banner:#eceff4;
|
|
5
|
+
--pi-art:none;--pi-scene-wash:rgba(249,250,251,.12);--pi-shadow:0 12px 40px rgb(30 40 60 / .12);
|
|
6
|
+
}
|
|
7
|
+
body[data-theme-style=classic][data-custom-background][data-ds-dark-theme]{
|
|
8
|
+
--pi-base:#151517;--pi-surface:#232324;--pi-raised:#353638;--pi-soft:#2c2c2e;--pi-sidebar:#1b1b1c;
|
|
9
|
+
--pi-text:#f5f6f7;--pi-secondary:#cfd3d6;--pi-muted:#adb2b8;--pi-accent:#a5bbff;--pi-on-accent:#182344;
|
|
10
|
+
--pi-tint:#30394e;--pi-border:#454850;--pi-code:#1b1b1c;--pi-code-banner:#2c2c2e;
|
|
11
|
+
--pi-scene-wash:rgba(21,21,23,.2);--pi-shadow:0 12px 40px rgb(0 0 0 / .22);
|
|
12
|
+
}
|
|
13
|
+
body[data-theme-style=sakura]{
|
|
14
|
+
--pi-base:#fff9fb;--pi-surface:#fffdfd;--pi-raised:#fff;--pi-soft:#f8edf3;--pi-sidebar:#f8eef3;
|
|
15
|
+
--pi-text:#382d3b;--pi-secondary:#6c5366;--pi-muted:#876779;--pi-accent:#ac406e;--pi-on-accent:#fff;
|
|
16
|
+
--pi-tint:#f5dfeb;--pi-border:#e9d6e1;--pi-code:#f8f1f6;--pi-code-banner:#f1e7ef;
|
|
17
|
+
--pi-art:url('/assets/themes/sakura.webp');--pi-scene-wash:rgba(255,249,251,.12);
|
|
18
|
+
--pi-shadow:0 12px 40px rgb(114 54 88 / .09);
|
|
19
|
+
}
|
|
20
|
+
body[data-theme-style=sakura][data-ds-dark-theme]{
|
|
21
|
+
--pi-base:#211c28;--pi-surface:#2b2432;--pi-raised:#352c3e;--pi-soft:#342a3b;--pi-sidebar:#251e2e;
|
|
22
|
+
--pi-text:#f3e7f0;--pi-secondary:#cfbace;--pi-muted:#b99eb4;--pi-accent:#efa7c8;--pi-on-accent:#362032;
|
|
23
|
+
--pi-tint:#4c3149;--pi-border:#4d3b51;--pi-code:#241e2d;--pi-code-banner:#312738;
|
|
24
|
+
--pi-scene-wash:rgba(33,28,40,.46);--pi-shadow:0 12px 40px rgb(0 0 0 / .18);
|
|
25
|
+
}
|
|
26
|
+
body[data-theme-style=starlight]{
|
|
27
|
+
--pi-base:#f6f8ff;--pi-surface:#fcfcff;--pi-raised:#fff;--pi-soft:#eaf0fb;--pi-sidebar:#eaf0fb;
|
|
28
|
+
--pi-text:#263252;--pi-secondary:#506084;--pi-muted:#657398;--pi-accent:#5553b6;--pi-on-accent:#fff;
|
|
29
|
+
--pi-tint:#e3e4fb;--pi-border:#d5def0;--pi-code:#eef1fa;--pi-code-banner:#e5e9f5;
|
|
30
|
+
--pi-art:url('/assets/themes/starlight.webp');--pi-scene-wash:rgba(246,248,255,.16);
|
|
31
|
+
--pi-shadow:0 12px 40px rgb(61 79 131 / .1);
|
|
32
|
+
}
|
|
33
|
+
body[data-theme-style=starlight][data-ds-dark-theme]{
|
|
34
|
+
--pi-base:#141b2e;--pi-surface:#1c253c;--pi-raised:#28324f;--pi-soft:#242f49;--pi-sidebar:#172037;
|
|
35
|
+
--pi-text:#e6edff;--pi-secondary:#b8c7e8;--pi-muted:#9aaccf;--pi-accent:#b6afff;--pi-on-accent:#222040;
|
|
36
|
+
--pi-tint:#35345a;--pi-border:#394563;--pi-code:#151e32;--pi-code-banner:#202a42;
|
|
37
|
+
--pi-scene-wash:rgba(20,27,46,.08);--pi-shadow:0 12px 40px rgb(0 0 0 / .22);
|
|
38
|
+
}
|
|
39
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]){
|
|
40
|
+
--dsw-alias-bg-base:var(--pi-base);
|
|
41
|
+
--dsw-alias-bg-layer-1:var(--pi-surface);--dsw-alias-bg-layer-2:var(--pi-surface);--dsw-alias-bg-layer-3:var(--pi-raised);
|
|
42
|
+
--dsw-alias-bg-module-platform:var(--pi-soft);--dsw-alias-bg-multi-select:var(--pi-soft);--dsw-alias-bg-overlay:var(--pi-tint);
|
|
43
|
+
--dsw-alias-label-primary:var(--pi-text);--dsw-alias-label-primary-dimmed:var(--pi-text);--dsw-alias-label-primary-bluish:var(--pi-accent);
|
|
44
|
+
--dsw-alias-label-secondary:var(--pi-secondary);--dsw-alias-label-tertiary:var(--pi-muted);--dsw-alias-label-caption:var(--pi-muted);
|
|
45
|
+
--dsw-alias-label-primary-foreground:var(--pi-on-accent);--dsw-alias-label-primary-inverted:var(--pi-on-accent);
|
|
46
|
+
--dsw-alias-brand-primary:var(--pi-accent);--dsw-alias-brand-primary-invert:var(--pi-accent);--dsw-alias-brand-text:var(--pi-text);
|
|
47
|
+
--dsw-alias-state-business-primary:var(--pi-accent);--dsw-alias-state-business-tertiary:var(--pi-tint);
|
|
48
|
+
--dsw-alias-border-l1:color-mix(in srgb,var(--pi-border) 65%,transparent);
|
|
49
|
+
--dsw-alias-border-l2:var(--pi-border);--dsw-alias-border-l2-darkmode-thin:var(--pi-border);
|
|
50
|
+
--dsw-alias-border-l3:color-mix(in srgb,var(--pi-border) 65%,var(--pi-muted));--dsw-alias-border-l4:var(--pi-muted);
|
|
51
|
+
--dsw-alias-button-primary-fill:var(--pi-accent);--dsw-alias-button-primary-hover:color-mix(in srgb,var(--pi-accent) 85%,var(--pi-text));
|
|
52
|
+
--dsw-alias-button-info-fill:var(--pi-accent);--dsw-alias-button-info-hover:color-mix(in srgb,var(--pi-accent) 85%,var(--pi-text));
|
|
53
|
+
--dsw-alias-button-primary-dimmed:var(--pi-border);--dsw-alias-button-elevated-fill:var(--pi-surface);
|
|
54
|
+
--dsw-alias-button-floating-fill:var(--pi-raised);--dsw-alias-button-floating-hover:var(--pi-soft);
|
|
55
|
+
--dsw-alias-button-ghost-active-fill:var(--pi-tint);--dsw-alias-button-ghost-active-hover:var(--pi-soft);
|
|
56
|
+
--dsw-alias-interactive-bg-hover:color-mix(in srgb,var(--pi-accent) 8%,transparent);
|
|
57
|
+
--dsw-alias-interactive-bg-hover-accent:color-mix(in srgb,var(--pi-accent) 16%,transparent);
|
|
58
|
+
--dsw-alias-interactive-bg-active:var(--pi-tint);--dsw-alias-interactive-bg-hover-solid:var(--pi-soft);
|
|
59
|
+
--dsw-alias-markdown-code-block:var(--pi-code);--dsw-alias-markdown-code-block-banner:var(--pi-code-banner);
|
|
60
|
+
--dsw-alias-markdown-inline-code:var(--pi-soft);--dsw-alias-markdown-citation:var(--pi-tint);
|
|
61
|
+
--dsw-alias-markdown-code-segment-selected:var(--pi-raised);--dsw-alias-markdown-code-segment-unselected:var(--pi-code);
|
|
62
|
+
--dsw-alias-markdown-placeholder:var(--pi-soft);--dsw-alias-markdown-tag:var(--pi-soft);
|
|
63
|
+
--dsw-specific-bubble:var(--pi-tint);--dsw-specific-bubble-highlight:var(--pi-border);
|
|
64
|
+
--dsw-specific-input-major:var(--pi-surface);--dsw-specific-selector:var(--pi-soft);--dsw-specific-tip:var(--pi-soft);
|
|
65
|
+
--dsw-specific-sidebar-fill:var(--pi-sidebar);--dsw-specific-sidebar-nav-item-active:var(--pi-tint);
|
|
66
|
+
--dsw-specific-sidebar-nav-item-active-accent:var(--pi-tint);--dsw-specific-sidebar-nav-item-hover:var(--pi-soft);
|
|
67
|
+
--dsw-alias-scrollbar-bg-l1:var(--pi-border);--dsw-alias-scrollbar-bg-l2:var(--pi-border);
|
|
68
|
+
--dsw-alias-scrollbar-hover-l1:var(--pi-muted);--dsw-alias-scrollbar-hover-l2:var(--pi-muted);
|
|
69
|
+
--dsw-linear-gradient-think:linear-gradient(180deg,var(--pi-base) 20%,transparent);
|
|
70
|
+
--dsw-linear-think-select:linear-gradient(180deg,var(--pi-soft) 20%,transparent);
|
|
71
|
+
}
|
|
72
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .pI_x6G_frame{
|
|
73
|
+
background-image:linear-gradient(var(--pi-scene-wash),var(--pi-scene-wash)),var(--pi-background-image,var(--pi-art));
|
|
74
|
+
background-size:cover;background-position:center;background-repeat:no-repeat;
|
|
75
|
+
}
|
|
76
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) :is(.hHd-Xa_root,.wSkVaW_root){background:transparent}
|
|
77
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .pI_x6G_sidebarCol{
|
|
78
|
+
background:color-mix(in srgb,var(--pi-sidebar) 62%,transparent);
|
|
79
|
+
backdrop-filter:blur(12px);border-right-color:color-mix(in srgb,var(--pi-raised) 45%,transparent);
|
|
80
|
+
}
|
|
81
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .wSkVaW_header{
|
|
82
|
+
background:color-mix(in srgb,var(--pi-surface) 72%,transparent);backdrop-filter:blur(12px);
|
|
83
|
+
}
|
|
84
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .wSkVaW_root[data-phase=active] .wSkVaW_composerSeat{background:transparent}
|
|
85
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) :is(.uV2eYG_card,.pi-settingsPanel){
|
|
86
|
+
background:color-mix(in srgb,var(--pi-surface) 72%,transparent);
|
|
87
|
+
backdrop-filter:blur(16px);border-color:color-mix(in srgb,var(--pi-raised) 55%,var(--pi-border));
|
|
88
|
+
}
|
|
89
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) [data-chat-flow-kind=assistant-text]{
|
|
90
|
+
box-sizing:border-box;padding:18px 22px;border:1px solid color-mix(in srgb,var(--pi-raised) 50%,var(--pi-border));border-radius:20px;
|
|
91
|
+
background:color-mix(in srgb,var(--pi-surface) 78%,transparent);backdrop-filter:blur(8px);box-shadow:var(--pi-shadow);
|
|
92
|
+
}
|
|
93
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) :is(.gdEzaW_bubble,.oRe1gG_bubble){
|
|
94
|
+
background:color-mix(in srgb,var(--pi-tint) 74%,transparent);backdrop-filter:blur(8px);
|
|
95
|
+
border:1px solid color-mix(in srgb,var(--pi-raised) 50%,var(--pi-border));box-shadow:var(--pi-shadow);
|
|
96
|
+
}
|
|
97
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .pi-compactionCard{
|
|
98
|
+
background:color-mix(in srgb,var(--pi-surface) 84%,transparent);backdrop-filter:blur(8px);
|
|
99
|
+
}
|
|
100
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .CY-8Ka_card{
|
|
101
|
+
background:color-mix(in srgb,var(--pi-surface) 48%,transparent);backdrop-filter:blur(8px);border-radius:8px;
|
|
102
|
+
}
|
|
103
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .CY-8Ka_root{background:transparent}
|
|
104
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .CY-8Ka_card :is(.Sxvs8a_root,.Sxvs8a_body,.Y0dWHa_payload){background:transparent}
|
|
105
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .CY-8Ka_card .Y0dWHa_payload{color:var(--pi-text)}
|
|
106
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) :is(.pXSMma_headline,.wSkVaW_heroWorkspaceRow){
|
|
107
|
+
align-self:center;max-width:calc(100% - 32px);padding:10px 16px;border:1px solid var(--dsw-alias-border-l2);border-radius:18px;
|
|
108
|
+
background:color-mix(in srgb,var(--pi-surface) 72%,transparent);backdrop-filter:blur(12px);
|
|
109
|
+
}
|
|
110
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .wSkVaW_heroWorkspaceRow{align-self:flex-start;margin-left:16px;padding:6px 12px}
|
|
111
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .p-xYUq_action{background:color-mix(in srgb,var(--pi-surface) 80%,transparent)}
|
|
112
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .pi-filePreview{
|
|
113
|
+
background:color-mix(in srgb,var(--pi-surface) 86%,transparent);backdrop-filter:blur(16px);
|
|
114
|
+
}
|
|
115
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .pi-filePreviewScroll{background:transparent}
|
|
116
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .pi-settingsSidebar{background:color-mix(in srgb,var(--pi-sidebar) 40%,transparent)}
|
|
117
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .pi-settingsBackdrop{background:rgb(15 20 30 / .18);backdrop-filter:blur(3px)}
|
|
118
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .wSkVaW_heroGlow{display:none}
|
|
119
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .pXSMma_headlineText{font-weight:600;letter-spacing:.04em;text-shadow:0 2px 18px var(--pi-base)}
|
|
120
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) :is(.pi-settingsActionPrimary,.uV2eYG_primary){color:var(--pi-on-accent)}
|
|
121
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .cubgiG_seatIcon text{fill:var(--pi-on-accent)}
|
|
122
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .uV2eYG_card{box-shadow:var(--pi-shadow)}
|
|
123
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .pi-settingsPanel{box-shadow:var(--pi-shadow)}
|
|
124
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .hHd-Xa_newSession{border-radius:14px;box-shadow:0 3px 12px color-mix(in srgb,var(--pi-accent) 7%,transparent)}
|
|
125
|
+
.pi-backgroundCard{display:grid;grid-template-columns:96px minmax(0,1fr);gap:14px;padding:14px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px}
|
|
126
|
+
.pi-backgroundPreview{height:72px;overflow:hidden;border-radius:8px;background-color:var(--dsw-alias-bg-module-platform);background-image:var(--pi-art,none);background-size:cover;background-position:center}
|
|
127
|
+
.pi-backgroundPreview img{width:100%;height:100%;object-fit:cover}
|
|
128
|
+
.pi-backgroundCopy{min-width:0;align-self:center}
|
|
129
|
+
.pi-backgroundCopy strong{display:block;font-size:12px;line-height:20px;overflow-wrap:anywhere}
|
|
130
|
+
.pi-backgroundCopy p{margin:4px 0 0;font-size:11px;line-height:18px;color:var(--dsw-alias-label-secondary)}
|
|
131
|
+
.pi-backgroundActions{grid-column:1/-1;display:flex;flex-wrap:wrap;gap:10px}
|
|
132
|
+
.pi-backgroundError{grid-column:1/-1;margin:0;font-size:12px;line-height:20px;color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere}
|
|
133
|
+
.pi-themeModeHeading{margin-top:28px}
|
|
134
|
+
.pi-settingsStyles button{text-align:left}
|
|
135
|
+
.pi-stylePreview{position:relative;display:flex;align-items:end;justify-content:center;height:104px;border-radius:7px;overflow:hidden;background-color:#eef1f6;background-size:cover;background-position:center}
|
|
136
|
+
.pi-stylePreview-classic{background-image:linear-gradient(145deg,#f1f3f9,#dce3f1)}
|
|
137
|
+
.pi-stylePreview-sakura{background-image:url('/assets/themes/sakura.webp')}
|
|
138
|
+
.pi-stylePreview-starlight{background-image:url('/assets/themes/starlight.webp')}
|
|
139
|
+
.pi-stylePreviewWindow{display:flex;flex-direction:column;gap:5px;width:68%;height:42px;padding:10px;margin-bottom:10px;border:1px solid rgb(255 255 255 / .7);border-radius:7px;background:rgb(255 255 255 / .85);box-shadow:0 4px 16px rgb(25 30 60 / .1)}
|
|
140
|
+
.pi-stylePreviewWindow i{display:block;width:68%;height:3px;border-radius:3px;background:#b5bdd2}
|
|
141
|
+
.pi-stylePreviewWindow i:first-child{align-self:end;width:48%;height:10px;background:#d9def0}
|
|
142
|
+
.pi-stylePreviewWindow i:last-child{width:45%}
|
|
143
|
+
.pi-stylePreview-sakura .pi-stylePreviewWindow i{background:#c6a0b8}
|
|
144
|
+
.pi-stylePreview-sakura .pi-stylePreviewWindow i:first-child{background:#f0d1e2}
|
|
145
|
+
.pi-stylePreview-starlight .pi-stylePreviewWindow{background:rgb(24 33 56 / .9);border-color:rgb(184 195 238 / .35)}
|
|
146
|
+
.pi-stylePreview-starlight .pi-stylePreviewWindow i{background:#7f91b5}
|
|
147
|
+
.pi-stylePreview-starlight .pi-stylePreviewWindow i:first-child{background:#66659a}
|
|
148
|
+
.pi-styleDescription{display:block;padding:0 3px 4px;color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:18px}
|
|
149
|
+
@media(max-width:640px){
|
|
150
|
+
.pi-stylePreview{height:84px}
|
|
151
|
+
.pi-stylePreviewWindow{width:72%;height:34px;padding:7px;margin-bottom:7px}
|
|
152
|
+
.pi-styleDescription{padding:2px 1px;font-size:10px}
|
|
153
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .pXSMma_headline{grid-template-columns:30px minmax(0,auto);row-gap:8px;margin:0 16px;font-size:22px;line-height:30px}
|
|
154
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .pXSMma_headlineText{letter-spacing:.02em}
|
|
155
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .pXSMma_previewBadge{grid-area:2/2;justify-self:start;margin:0}
|
|
156
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) [data-chat-flow-kind=assistant-text]{padding:14px;border-radius:16px}
|
|
157
|
+
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .pXSMma_headline{padding:10px 12px;margin:0;box-sizing:border-box}
|
|
158
|
+
}
|