u1s1-cli 0.10.0 → 0.11.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/dist/agent-setup.d.ts +32 -0
- package/dist/agent-setup.js +27 -0
- package/dist/api.d.ts +51 -0
- package/dist/brand.d.ts +13 -0
- package/dist/config.d.ts +77 -0
- package/dist/deploy.d.ts +2 -0
- package/dist/embed.d.ts +11 -0
- package/dist/embed.js +11 -0
- package/dist/import/claude.d.ts +3 -0
- package/dist/import/codex.d.ts +3 -0
- package/dist/import/index.d.ts +1 -0
- package/dist/import/types.d.ts +104 -0
- package/dist/import/util.d.ts +26 -0
- package/dist/import/write.d.ts +4 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/login.d.ts +16 -0
- package/dist/login.js +3 -3
- package/dist/model.d.ts +1 -0
- package/dist/shortcut.d.ts +1 -0
- package/dist/style.d.ts +7 -0
- package/dist/templates.d.ts +2 -0
- package/dist/templates.js +48 -0
- package/dist/tools.d.ts +18 -0
- package/dist/update.d.ts +8 -0
- package/dist/usage.d.ts +1 -0
- package/dist/web.d.ts +13 -0
- package/dist/web.js +45 -32
- package/dist/webui-brand.d.ts +9 -0
- package/dist/webui-brand.js +155 -10
- package/package.json +4 -3
- package/webui-dist/assets/index-Cz5vuDzv.js +128 -0
- package/webui-dist/assets/index-DICLz-bf.css +41 -0
- package/webui-dist/favicon.svg +4 -0
- package/webui-dist/icon.ico +0 -0
- package/webui-dist/index.html +15 -0
package/dist/web.js
CHANGED
|
@@ -2,9 +2,9 @@ import { spawn, spawnSync } from "node:child_process";
|
|
|
2
2
|
import { mkdirSync } from "node:fs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
|
-
import { cleanupBrandThemes, ensureBrandPrompt, ensureDefaultSettings, ensureProviderModels, writeWebToolsExtension, } from "./agent-setup.js";
|
|
5
|
+
import { cleanupBrandThemes, ensureAuthCredential, ensureBrandPrompt, ensureDefaultSettings, ensureProviderModels, writeWebToolsExtension, } from "./agent-setup.js";
|
|
6
6
|
import { agentDir, apiModelToDef, resolvePreferredModel, setModelsFromApi, u1s1Dir, writeAgentDefaultModel, } from "./config.js";
|
|
7
|
-
import { applyWebUiBranding } from "./webui-brand.js";
|
|
7
|
+
import { applyWebUiBranding, applyWebUiFrontend } from "./webui-brand.js";
|
|
8
8
|
import { fetchModels } from "./api.js";
|
|
9
9
|
const require = createRequire(import.meta.url);
|
|
10
10
|
/**
|
|
@@ -12,6 +12,43 @@ const require = createRequire(import.meta.url);
|
|
|
12
12
|
* (品牌 prompt / models.json / 会话与 TUI 共享)和登录 key,其余原样透传
|
|
13
13
|
* (--port / --cwd / --no-browser)。
|
|
14
14
|
*/
|
|
15
|
+
/**
|
|
16
|
+
* 启动 pi-web-ui 服务器前的公共准备:品牌 prompt、模型列表、auth.json 凭据、
|
|
17
|
+
* 联网工具扩展、默认模型,并返回子进程需要的环境变量。CLI(`u1s1 web`)和
|
|
18
|
+
* 桌面版 App(packages/app,经 "u1s1-cli/embed" 引入)共用这一份逻辑。
|
|
19
|
+
*/
|
|
20
|
+
export async function prepareWebEnv(cfg) {
|
|
21
|
+
cleanupBrandThemes();
|
|
22
|
+
ensureBrandPrompt();
|
|
23
|
+
ensureDefaultSettings();
|
|
24
|
+
// Fetch model list from server; fall back to built-in MODELS on error.
|
|
25
|
+
// 服务端没开搜索(或老网关没有 features 字段)时不注册 web_search
|
|
26
|
+
let webSearchEnabled = true;
|
|
27
|
+
try {
|
|
28
|
+
const { models, features } = await fetchModels(cfg);
|
|
29
|
+
setModelsFromApi(models.map(apiModelToDef));
|
|
30
|
+
webSearchEnabled = features.web_search !== false;
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
console.error(" 获取模型列表失败,使用内置列表:", e.message);
|
|
34
|
+
}
|
|
35
|
+
ensureProviderModels(cfg);
|
|
36
|
+
// pi-web-ui 靠 auth.json 判断「已配置」,否则网页会弹 pi 安装引导
|
|
37
|
+
ensureAuthCredential();
|
|
38
|
+
// 联网工具经 agentDir/extensions 投影,和 TUI 共用一份注册
|
|
39
|
+
writeWebToolsExtension(cfg, webSearchEnabled);
|
|
40
|
+
// 网页版新会话从 settings.json 的 defaultModel 取模型(TUI 是每次传 --model),
|
|
41
|
+
// 确保它有值;resolvePreferredModel 优先尊重已有的 in-session 选择,不会回退覆盖。
|
|
42
|
+
writeAgentDefaultModel(resolvePreferredModel(cfg.model));
|
|
43
|
+
const dataDir = join(u1s1Dir, "web");
|
|
44
|
+
mkdirSync(dataDir, { recursive: true });
|
|
45
|
+
return {
|
|
46
|
+
PI_CODING_AGENT_DIR: agentDir,
|
|
47
|
+
U1S1_API_KEY: cfg.apiKey,
|
|
48
|
+
U1S1_TOOLS_VIA_EXTENSION: "1",
|
|
49
|
+
PI_WEB_DATA_DIR: dataDir,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
15
52
|
export async function webCommand(cfg, args) {
|
|
16
53
|
// pi-web-ui 的 server install/shortcut 生成的服务定义只固化 PORT/CWD,不带
|
|
17
54
|
// PI_CODING_AGENT_DIR 和 U1S1_API_KEY —— 装出来的自启服务是坏的(丢登录态、
|
|
@@ -24,6 +61,7 @@ export async function webCommand(cfg, args) {
|
|
|
24
61
|
}
|
|
25
62
|
// pi-web-ui 是 optionalDependency:装 CLI 时它编译/下载失败不会拖垮整个安装,
|
|
26
63
|
// 代价是这里可能不存在 —— 给出人话指引而不是 Cannot find module。
|
|
64
|
+
// (桌面版 App 上线后这里的兜底会改为指向 App 下载,CLI 届时不再携带 pi-web-ui。)
|
|
27
65
|
let bin;
|
|
28
66
|
try {
|
|
29
67
|
bin = require.resolve("pi-web-ui/bin/pi-web-ui.mjs");
|
|
@@ -45,39 +83,14 @@ export async function webCommand(cfg, args) {
|
|
|
45
83
|
process.exitCode = 1;
|
|
46
84
|
return;
|
|
47
85
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// 服务端没开搜索(或老网关没有 features 字段)时不注册 web_search
|
|
53
|
-
let webSearchEnabled = true;
|
|
54
|
-
try {
|
|
55
|
-
const { models, features } = await fetchModels(cfg);
|
|
56
|
-
setModelsFromApi(models.map(apiModelToDef));
|
|
57
|
-
webSearchEnabled = features.web_search !== false;
|
|
58
|
-
}
|
|
59
|
-
catch (e) {
|
|
60
|
-
console.error(" 获取模型列表失败,使用内置列表:", e.message);
|
|
61
|
-
}
|
|
62
|
-
ensureProviderModels(cfg);
|
|
63
|
-
// 联网工具经 agentDir/extensions 投影,和 TUI 共用一份注册
|
|
64
|
-
writeWebToolsExtension(cfg, webSearchEnabled);
|
|
65
|
-
// 网页版新会话从 settings.json 的 defaultModel 取模型(TUI 是每次传 --model),
|
|
66
|
-
// 确保它有值;resolvePreferredModel 优先尊重已有的 in-session 选择,不会回退覆盖。
|
|
67
|
-
writeAgentDefaultModel(resolvePreferredModel(cfg.model));
|
|
68
|
-
const dataDir = join(u1s1Dir, "web");
|
|
69
|
-
mkdirSync(dataDir, { recursive: true });
|
|
70
|
-
applyWebUiBranding(bin);
|
|
86
|
+
const webEnv = await prepareWebEnv(cfg);
|
|
87
|
+
// 首选 u1s1 自有前端(Codex 布局);产物缺失时回退为上游界面 + 品牌补丁
|
|
88
|
+
if (!applyWebUiFrontend(bin))
|
|
89
|
+
applyWebUiBranding(bin);
|
|
71
90
|
console.log("u1s1 网页版启动中… 浏览器会自动打开;关闭请回到这里按 Ctrl+C。");
|
|
72
91
|
const child = spawn(process.execPath, [bin, ...args], {
|
|
73
92
|
stdio: "inherit",
|
|
74
|
-
env: {
|
|
75
|
-
...process.env,
|
|
76
|
-
PI_CODING_AGENT_DIR: agentDir,
|
|
77
|
-
U1S1_API_KEY: cfg.apiKey,
|
|
78
|
-
U1S1_TOOLS_VIA_EXTENSION: "1",
|
|
79
|
-
PI_WEB_DATA_DIR: dataDir,
|
|
80
|
-
},
|
|
93
|
+
env: { ...process.env, ...webEnv },
|
|
81
94
|
});
|
|
82
95
|
// Ctrl+C 由子进程负责优雅停机(同进程组,信号会直达);父进程只等退出码,
|
|
83
96
|
// 避免父进程先死导致孤儿服务器。
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* u1s1 自有前端(packages/webui,Codex 布局复刻)整体替换 pi-web-ui 的
|
|
3
|
+
* web/dist。产物随 CLI 包发布在 <cliPkg>/webui-dist;index.html 内容一致
|
|
4
|
+
* 说明已同步过,跳过。目标目录先整体删除再拷贝 —— 断开 pnpm 硬链接,
|
|
5
|
+
* 也顺带清掉上游的旧 assets。返回 false 表示产物缺失(回退到品牌补丁)。
|
|
6
|
+
*/
|
|
7
|
+
export declare function applyWebUiFrontend(binPath: string): boolean;
|
|
8
|
+
/** binPath = <pkg>/bin/pi-web-ui.mjs → 前端产物在 <pkg>/web/dist。 */
|
|
9
|
+
export declare function applyWebUiBranding(binPath: string): void;
|
package/dist/webui-brand.js
CHANGED
|
@@ -1,15 +1,45 @@
|
|
|
1
|
-
import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { cpSync, existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
3
4
|
/**
|
|
4
|
-
* pi-web-ui
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* u1s1 自有前端(packages/webui,Codex 布局复刻)整体替换 pi-web-ui 的
|
|
6
|
+
* web/dist。产物随 CLI 包发布在 <cliPkg>/webui-dist;index.html 内容一致
|
|
7
|
+
* 说明已同步过,跳过。目标目录先整体删除再拷贝 —— 断开 pnpm 硬链接,
|
|
8
|
+
* 也顺带清掉上游的旧 assets。返回 false 表示产物缺失(回退到品牌补丁)。
|
|
9
|
+
*/
|
|
10
|
+
export function applyWebUiFrontend(binPath) {
|
|
11
|
+
const src = fileURLToPath(new URL("../webui-dist/", import.meta.url));
|
|
12
|
+
const srcIndex = join(src, "index.html");
|
|
13
|
+
if (!existsSync(srcIndex))
|
|
14
|
+
return false;
|
|
15
|
+
const dist = join(dirname(binPath), "..", "web", "dist");
|
|
16
|
+
const distIndex = join(dist, "index.html");
|
|
17
|
+
try {
|
|
18
|
+
if (existsSync(distIndex) &&
|
|
19
|
+
readFileSync(distIndex, "utf8") === readFileSync(srcIndex, "utf8")) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
rmSync(dist, { recursive: true, force: true });
|
|
23
|
+
cpSync(src, dist, { recursive: true });
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
console.error(" 前端替换失败,退回默认界面:", e.message);
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* pi-web-ui 前端产物的启动时品牌补丁。不 fork 上游,只在每次 `u1s1 web` /
|
|
33
|
+
* 桌面版启动前改它 web/dist 里的静态文件:重写 <title>、换 favicon、注入
|
|
34
|
+
* 品牌脚本和一份 Codex 风格的主题 CSS(u1s1-theme.css),把整个界面换成
|
|
35
|
+
* u1s1 的视觉:石墨底色、品牌蓝 #4ea1ff、幽灵化顶栏、居中内容列。
|
|
7
36
|
*
|
|
8
|
-
* -
|
|
37
|
+
* - 幂等 + 可升级:index.html 里有当前版本标记则跳过;版本变了先剥掉旧注入
|
|
38
|
+
* 再打新的;pi-web-ui 升级后文件是全新的,自动重打。
|
|
9
39
|
* - 写文件前先 rmSync 断开硬链接 —— pnpm 的 node_modules 是全局 store 的硬链接,
|
|
10
40
|
* 原地写会污染 store;unlink 后新写的是独立 inode,npm 平铺安装则无所谓。
|
|
11
41
|
*/
|
|
12
|
-
const PATCH_MARK = "u1s1-brand-
|
|
42
|
+
const PATCH_MARK = "u1s1-brand-v2";
|
|
13
43
|
const PAGE_TITLE = "u1s1 网页版 — 有一说一";
|
|
14
44
|
const FAVICON_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
|
15
45
|
<rect width="64" height="64" rx="14" fill="#101418"/>
|
|
@@ -25,11 +55,116 @@ const BRAND_JS = `(function(){
|
|
|
25
55
|
if (logo && logo.textContent !== LOGO) logo.textContent = LOGO;
|
|
26
56
|
var name = document.querySelector(".brand-name");
|
|
27
57
|
if (name && name.textContent !== NAME) name.textContent = NAME;
|
|
58
|
+
// 输入框占位符里的 pi 字样换成 u1s1(React 重渲染会改回去,观察到就再改)
|
|
59
|
+
var box = document.querySelector(".inputbox textarea");
|
|
60
|
+
if (box && box.placeholder && box.placeholder.indexOf("pi ") !== -1) {
|
|
61
|
+
box.placeholder = box.placeholder.replace(/pi /g, "u1s1 ");
|
|
62
|
+
}
|
|
63
|
+
// 消息里的助手角色标签 pi → u1s1(大写 PI 是 CSS text-transform 渲染的)
|
|
64
|
+
var roles = document.querySelectorAll(".msg-role, .msg-collapsed-role");
|
|
65
|
+
for (var i = 0; i < roles.length; i++) {
|
|
66
|
+
if (roles[i].textContent.trim().toLowerCase() === "pi") roles[i].textContent = NAME;
|
|
67
|
+
}
|
|
28
68
|
}
|
|
29
69
|
apply();
|
|
30
|
-
new MutationObserver(apply).observe(document.documentElement, { childList: true, subtree: true });
|
|
70
|
+
new MutationObserver(apply).observe(document.documentElement, { childList: true, subtree: true, attributes: true, attributeFilter: ["placeholder"] });
|
|
31
71
|
})();
|
|
32
72
|
`;
|
|
73
|
+
/**
|
|
74
|
+
* Codex mac app 风格的亮色主题覆盖层:暖白底、深灰字、浅灰气泡、极简边框,
|
|
75
|
+
* 视觉锚点只留品牌、模型和「新对话」。全部通过变量覆盖 + 定向规则实现,
|
|
76
|
+
* 上游 DOM/类名不动;上游写死的暗色(代码块 #0b0d12!important、hljs 深色
|
|
77
|
+
* token、黑色重阴影)逐条压回亮色。终端面板(xterm)保持深色不动。
|
|
78
|
+
*/
|
|
79
|
+
const THEME_CSS = `/* ${PATCH_MARK} — u1s1 light theme overlay (Codex mac style) */
|
|
80
|
+
:root{
|
|
81
|
+
--bg:#faf9f7;
|
|
82
|
+
--bg-elev:#f2f0ec;
|
|
83
|
+
--bg-elev1:#f4f2ef;
|
|
84
|
+
--bg-elev2:#ecebe6;
|
|
85
|
+
--border:#dcd8d0;
|
|
86
|
+
--border-soft:#e8e5df;
|
|
87
|
+
--text:#1f1e1b;
|
|
88
|
+
--text-dim:#57534c;
|
|
89
|
+
--text-faint:#8a857c;
|
|
90
|
+
--accent:#2f6fe0;
|
|
91
|
+
--accent-soft:rgba(47,111,224,.10);
|
|
92
|
+
--green:#1a7f37;
|
|
93
|
+
--green-soft:rgba(26,127,55,.12);
|
|
94
|
+
--red:#cf222e;
|
|
95
|
+
--red-soft:rgba(207,34,46,.10);
|
|
96
|
+
--amber:#9a6700;
|
|
97
|
+
}
|
|
98
|
+
html,body{background:var(--bg);color-scheme:light}
|
|
99
|
+
|
|
100
|
+
/* ---- 顶栏:去底色去边框,低频控件幽灵化,悬停才现形 ---- */
|
|
101
|
+
.topbar{background:transparent;border-bottom:1px solid var(--border-soft);padding:10px 18px}
|
|
102
|
+
.topbar-desktop .dropdown .chip{background:transparent;border-color:transparent;color:var(--text-dim)}
|
|
103
|
+
.topbar-desktop .dropdown .chip:hover{background:var(--bg-elev2);border-color:var(--border);color:var(--text)}
|
|
104
|
+
/* 模型选择是高频锚点,保留药丸形态 */
|
|
105
|
+
.topbar-desktop .dropdown:first-child .chip{background:#fff;border-color:var(--border);color:var(--text)}
|
|
106
|
+
.chip{background:#fff}
|
|
107
|
+
.chip.github{display:none}
|
|
108
|
+
.chip.newchat{background:var(--accent);border-color:transparent;color:#fff;font-weight:600}
|
|
109
|
+
.chip.newchat:hover{background:#2a63c8;border-color:transparent}
|
|
110
|
+
.view-switch{background:transparent;border-color:transparent;gap:2px}
|
|
111
|
+
.view-switch button{color:var(--text-dim)}
|
|
112
|
+
.view-switch button.active{background:var(--bg-elev2);border-radius:999px;color:var(--text)}
|
|
113
|
+
|
|
114
|
+
/* ---- 侧栏:层级靠底色深浅,不靠描边 ---- */
|
|
115
|
+
.panel{border-right:none;background:var(--bg-elev)}
|
|
116
|
+
.panel-right{border-left:1px solid var(--border-soft);background:var(--bg);width:216px}
|
|
117
|
+
.panel .panel-title,.panel .panel-section-title,.panel-header .panel-title{font-size:11px;letter-spacing:.8px;text-transform:uppercase;color:var(--text-faint)}
|
|
118
|
+
.session-item.active,.project-item.active{background:#fff;border-color:var(--border);box-shadow:0 1px 3px rgba(0,0,0,.06)}
|
|
119
|
+
.panel-crumbs .crumb{color:var(--text-faint)}
|
|
120
|
+
.panel-crumbs .crumb.active{color:var(--text-dim)}
|
|
121
|
+
|
|
122
|
+
/* ---- 对话流:收窄到 780px,和 composer 对齐 ---- */
|
|
123
|
+
.msg,.goalbar,.inputbox{max-width:780px}
|
|
124
|
+
.msg-text{line-height:1.75}
|
|
125
|
+
.messages{padding-top:28px}
|
|
126
|
+
/* markdown 表格降噪:去竖线只留横向分隔,表头不抢戏 */
|
|
127
|
+
.msg-text th,.msg-text td{border:none;border-bottom:1px solid var(--border-soft);padding:6px 12px}
|
|
128
|
+
.msg-text thead th{border-bottom:1px solid var(--border);background:transparent;color:var(--text-dim);font-weight:600;text-align:left}
|
|
129
|
+
.msg-text table{margin:10px 0;width:100%}
|
|
130
|
+
.msg-text hr{border-color:var(--border-soft)}
|
|
131
|
+
/* 用户消息:浅灰气泡靠右(Codex 同款),替换上游的紫色调 */
|
|
132
|
+
.msg-user .msg-body{background:var(--bg-elev2);border:1px solid transparent;border-radius:14px;margin-left:auto;width:fit-content;max-width:min(85%,620px)}
|
|
133
|
+
|
|
134
|
+
/* ---- 代码:亮色卡片 + GitHub-Light 配色(压过上游写死的 #0b0d12) ---- */
|
|
135
|
+
.codeblock pre{background:#f6f5f1!important;border:1px solid var(--border-soft)}
|
|
136
|
+
.termline{background:#f6f5f1;border-color:var(--border-soft)}
|
|
137
|
+
.toolcall-output pre{background:#f6f5f1;border-color:var(--border-soft);color:var(--text-dim)}
|
|
138
|
+
.fp-code{background:#f6f5f1}
|
|
139
|
+
.fp-code.dragging .fp-line.sel{background:var(--accent-soft)}
|
|
140
|
+
.thinking{background:#f7f5f1}
|
|
141
|
+
.hljs{color:#24292f;background:transparent}
|
|
142
|
+
.hljs-comment,.hljs-quote{color:#6e7781}
|
|
143
|
+
.hljs-keyword,.hljs-doctag,.hljs-template-tag,.hljs-template-variable,.hljs-type{color:#cf222e}
|
|
144
|
+
.hljs-title,.hljs-title.class_,.hljs-title.function_{color:#8250df}
|
|
145
|
+
.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#0550ae}
|
|
146
|
+
.hljs-string,.hljs-regexp{color:#0a3069}
|
|
147
|
+
.hljs-built_in,.hljs-symbol{color:#953800}
|
|
148
|
+
.hljs-name,.hljs-selector-tag,.hljs-selector-pseudo{color:#116329}
|
|
149
|
+
.hljs-section{color:#0550ae;font-weight:700}
|
|
150
|
+
.hljs-bullet{color:#953800}
|
|
151
|
+
.hljs-emphasis{font-style:italic}
|
|
152
|
+
.hljs-strong{font-weight:700}
|
|
153
|
+
.hljs-addition{color:#116329;background:#dafbe1}
|
|
154
|
+
.hljs-deletion{color:#82071e;background:#ffebe9}
|
|
155
|
+
|
|
156
|
+
/* ---- Composer:白色主舞台,轻投影 ---- */
|
|
157
|
+
.inputbar{padding:10px 24px 26px}
|
|
158
|
+
.inputbox{background:#fff;border-color:var(--border);border-radius:18px;box-shadow:0 1px 2px rgba(0,0,0,.04),0 6px 24px rgba(0,0,0,.07)}
|
|
159
|
+
.inputbox:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft),0 6px 24px rgba(0,0,0,.07)}
|
|
160
|
+
|
|
161
|
+
/* ---- 状态栏与滚动条:退到最底的音量 ---- */
|
|
162
|
+
.statusbar{background:transparent;border-top:1px solid var(--border-soft)}
|
|
163
|
+
::-webkit-scrollbar{width:10px;height:10px}
|
|
164
|
+
::-webkit-scrollbar-thumb{background:#00000024;border-radius:5px;border:2px solid transparent;background-clip:content-box}
|
|
165
|
+
::-webkit-scrollbar-thumb:hover{background:#0000003d;border-radius:5px;border:2px solid transparent;background-clip:content-box}
|
|
166
|
+
::-webkit-scrollbar-track{background:transparent}
|
|
167
|
+
`;
|
|
33
168
|
function replaceFile(path, content) {
|
|
34
169
|
rmSync(path, { force: true });
|
|
35
170
|
writeFileSync(path, content);
|
|
@@ -40,13 +175,23 @@ export function applyWebUiBranding(binPath) {
|
|
|
40
175
|
const indexHtml = join(dist, "index.html");
|
|
41
176
|
if (!existsSync(indexHtml))
|
|
42
177
|
return; // 上游布局变了就跳过,页面保持原样也能用
|
|
178
|
+
// 资产文件每次启动重写:内容随 CLI 版本走,不依赖 html 的版本标记
|
|
179
|
+
replaceFile(join(dist, "u1s1-brand.js"), BRAND_JS);
|
|
180
|
+
replaceFile(join(dist, "u1s1-theme.css"), THEME_CSS);
|
|
181
|
+
replaceFile(join(dist, "favicon.svg"), FAVICON_SVG);
|
|
43
182
|
let html = readFileSync(indexHtml, "utf8");
|
|
44
183
|
if (html.includes(PATCH_MARK))
|
|
45
184
|
return;
|
|
46
|
-
|
|
47
|
-
|
|
185
|
+
// 老版本补丁(u1s1-brand-v1 等)的注入行先剥掉,避免升级后重复注入
|
|
186
|
+
html = html
|
|
187
|
+
.replace(/[ \t]*<!-- u1s1-brand-[^>]*-->\n?/g, "")
|
|
188
|
+
.replace(/[ \t]*<script defer src="\/u1s1-brand\.js"><\/script>\n?/g, "")
|
|
189
|
+
.replace(/[ \t]*<link rel="stylesheet" href="\/u1s1-theme\.css"\s*\/?>\n?/g, "");
|
|
48
190
|
html = html
|
|
49
191
|
.replace(/<title>[^<]*<\/title>/, `<title>${PAGE_TITLE}</title>`)
|
|
50
|
-
.replace("</head>", ` <!-- ${PATCH_MARK} -->\n
|
|
192
|
+
.replace("</head>", ` <!-- ${PATCH_MARK} -->\n` +
|
|
193
|
+
` <link rel="stylesheet" href="/u1s1-theme.css" />\n` +
|
|
194
|
+
` <script defer src="/u1s1-brand.js"></script>\n` +
|
|
195
|
+
` </head>`);
|
|
51
196
|
replaceFile(indexHtml, html);
|
|
52
197
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "u1s1-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "u1s1 — 有一说一,最省心的 AI 编程搭子。终端里用中文说需求,AI 帮你读文件、改代码、跑命令。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"./package.json": "./package.json"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
|
-
"dist"
|
|
17
|
+
"dist",
|
|
18
|
+
"webui-dist"
|
|
18
19
|
],
|
|
19
20
|
"engines": {
|
|
20
21
|
"node": ">=22.19.0"
|
|
@@ -43,7 +44,7 @@
|
|
|
43
44
|
"typebox": "1.3.7"
|
|
44
45
|
},
|
|
45
46
|
"optionalDependencies": {
|
|
46
|
-
"pi-web-ui": "0.
|
|
47
|
+
"pi-web-ui": "0.26.0"
|
|
47
48
|
},
|
|
48
49
|
"devDependencies": {
|
|
49
50
|
"@types/node": "^22.15.0",
|