pi-web-ui 0.48.1 → 0.48.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/server/agent-service.js +5 -16
- package/dist/server/model-admin.js +2 -0
- package/package.json +110 -110
- package/themes/md-preview.css +42 -85
- package/themes/white.css +42 -85
- package/web/dist/assets/{TerminalPanel-zmg6ssVv.js → TerminalPanel-m1Uq9P_a.js} +1 -1
- package/web/dist/assets/{index-B22rO2Ct.css → index-B8YOHfUN.css} +1 -1
- package/web/dist/assets/{index-ChxqCQTs.js → index-Dg-bQ98a.js} +2 -2
- package/web/dist/index.html +2 -2
|
@@ -1332,28 +1332,17 @@ export class ClientSession {
|
|
|
1332
1332
|
this.webUi.resolveDialog(id, value);
|
|
1333
1333
|
}
|
|
1334
1334
|
/**
|
|
1335
|
-
* Whether the pi agent
|
|
1336
|
-
*
|
|
1335
|
+
* Whether the pi agent has at least one usable model. ModelRuntime's
|
|
1336
|
+
* available snapshot already accounts for models.json, auth.json, env-var
|
|
1337
|
+
* credentials, OAuth, and runtime API-key overrides. Cached for 2s because
|
|
1338
|
+
* this is called while building frequent snapshots.
|
|
1337
1339
|
*/
|
|
1338
1340
|
isPiConfigured() {
|
|
1339
1341
|
const now = Date.now();
|
|
1340
1342
|
const cached = this.piCheckCache;
|
|
1341
1343
|
if (cached && now - cached.at < 2000)
|
|
1342
1344
|
return cached.configured;
|
|
1343
|
-
|
|
1344
|
-
try {
|
|
1345
|
-
const authPath = join(this.agentDir, "auth.json");
|
|
1346
|
-
if (existsSync(authPath)) {
|
|
1347
|
-
const data = JSON.parse(readFileSync(authPath, "utf8"));
|
|
1348
|
-
configured =
|
|
1349
|
-
typeof data === "object" &&
|
|
1350
|
-
data !== null &&
|
|
1351
|
-
Object.keys(data).length > 0;
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
catch {
|
|
1355
|
-
configured = false;
|
|
1356
|
-
}
|
|
1345
|
+
const configured = (this.sharedModelRuntime?.getAvailableSnapshot().length ?? 0) > 0;
|
|
1357
1346
|
this.piCheckCache = { at: now, configured };
|
|
1358
1347
|
return configured;
|
|
1359
1348
|
}
|
|
@@ -769,6 +769,7 @@ export class ModelAdminService {
|
|
|
769
769
|
// auth.json is optional; models.json can still use its own apiKey.
|
|
770
770
|
}
|
|
771
771
|
await this.host.modelRuntime().refresh();
|
|
772
|
+
this.host.invalidatePiConfig();
|
|
772
773
|
await this.listModelsConfig();
|
|
773
774
|
await this.host.pushModels();
|
|
774
775
|
this.host.emit({
|
|
@@ -801,6 +802,7 @@ export class ModelAdminService {
|
|
|
801
802
|
delete providers[providerId];
|
|
802
803
|
writeFileSync(this.modelsConfigPath(), JSON.stringify({ providers }, null, 2) + "\n");
|
|
803
804
|
await this.host.modelRuntime().refresh();
|
|
805
|
+
this.host.invalidatePiConfig();
|
|
804
806
|
await this.listModelsConfig();
|
|
805
807
|
await this.host.pushModels();
|
|
806
808
|
this.host.emit({
|
package/package.json
CHANGED
|
@@ -1,110 +1,110 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "pi-web-ui",
|
|
3
|
-
"version": "0.48.
|
|
4
|
-
"description": "Web chat interface for the pi coding agent, powered by the pi SDK (@earendil-works/pi-coding-agent) — one-command run, Docker/systemd/launchd deployable",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"author": {
|
|
7
|
-
"name": "xingshuyin",
|
|
8
|
-
"email": "xingshuyin@users.noreply.github.com"
|
|
9
|
-
},
|
|
10
|
-
"type": "module",
|
|
11
|
-
"bin": {
|
|
12
|
-
"pi-web-ui": "bin/pi-web-ui.mjs"
|
|
13
|
-
},
|
|
14
|
-
"main": "electron/main.mjs",
|
|
15
|
-
"files": [
|
|
16
|
-
"bin/",
|
|
17
|
-
"dist/",
|
|
18
|
-
"web/dist/",
|
|
19
|
-
"web/public/",
|
|
20
|
-
"themes/",
|
|
21
|
-
"deploy/",
|
|
22
|
-
"extensions/",
|
|
23
|
-
"README.md",
|
|
24
|
-
"LICENSE"
|
|
25
|
-
],
|
|
26
|
-
"keywords": [
|
|
27
|
-
"pi",
|
|
28
|
-
"pi-package",
|
|
29
|
-
"coding-agent",
|
|
30
|
-
"ai",
|
|
31
|
-
"chat",
|
|
32
|
-
"web-ui",
|
|
33
|
-
"terminal",
|
|
34
|
-
"llm"
|
|
35
|
-
],
|
|
36
|
-
"repository": {
|
|
37
|
-
"type": "git",
|
|
38
|
-
"url": "git+https://github.com/xing-shuyin/pi-web-ui.git"
|
|
39
|
-
},
|
|
40
|
-
"pi": {
|
|
41
|
-
"extensions": [
|
|
42
|
-
"./extensions"
|
|
43
|
-
]
|
|
44
|
-
},
|
|
45
|
-
"engines": {
|
|
46
|
-
"node": ">=22.19.0"
|
|
47
|
-
},
|
|
48
|
-
"scripts": {
|
|
49
|
-
"prepublishOnly": "npm run build",
|
|
50
|
-
"dev": "concurrently -k -n server,web -c blue,green \"npm:dev:server\" \"npm:dev:web\"",
|
|
51
|
-
"dev:server": "cross-env PORT=8788 PI_WEB_ALLOW_ORIGINS=http://localhost:5173,http://127.0.0.1:5173 node --watch --import tsx server/index.ts",
|
|
52
|
-
"dev:web": "vite --config web/vite.config.ts",
|
|
53
|
-
"build": "npm run build:web && npm run build:server",
|
|
54
|
-
"build:web": "vite build --config web/vite.config.ts",
|
|
55
|
-
"build:server": "tsc -p tsconfig.server.json",
|
|
56
|
-
"typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p web/tsconfig.json --noEmit && tsc -p tsconfig.tests.json --noEmit",
|
|
57
|
-
"test": "vitest run",
|
|
58
|
-
"test:unit": "vitest run",
|
|
59
|
-
"test:smoke": "node tests/run-smoke.mjs",
|
|
60
|
-
"check:protocol": "node scripts/check-protocol-sync.mjs",
|
|
61
|
-
"test:freeze": "node tests/freeze-test.mjs",
|
|
62
|
-
"start": "node dist/server/index.js",
|
|
63
|
-
"start:electron": "electron .",
|
|
64
|
-
"build:electron": "electron-builder build",
|
|
65
|
-
"build:electron:mac": "electron-builder build --mac",
|
|
66
|
-
"build:electron:win": "electron-builder build --win",
|
|
67
|
-
"build:electron:linux": "electron-builder build --linux",
|
|
68
|
-
"publish:electron": "electron-builder build --publish always"
|
|
69
|
-
},
|
|
70
|
-
"dependencies": {
|
|
71
|
-
"@earendil-works/pi-coding-agent": "^0.84.2",
|
|
72
|
-
"@xterm/addon-fit": "^0.11.0",
|
|
73
|
-
"@xterm/xterm": "^6.0.0",
|
|
74
|
-
"compression": "^1.8.1",
|
|
75
|
-
"express": "^4.21.2",
|
|
76
|
-
"highlight.js": "^11.10.0",
|
|
77
|
-
"node-pty": "^1.1.0",
|
|
78
|
-
"react": "^18.3.1",
|
|
79
|
-
"react-dom": "^18.3.1",
|
|
80
|
-
"react-icons": "^5.7.0",
|
|
81
|
-
"react-markdown": "^9.0.1",
|
|
82
|
-
"rehype-highlight": "^7.0.1",
|
|
83
|
-
"remark-gfm": "^4.0.0",
|
|
84
|
-
"typebox": "^1.3.14",
|
|
85
|
-
"ws": "^8.18.0"
|
|
86
|
-
},
|
|
87
|
-
"devDependencies": {
|
|
88
|
-
"@types/compression": "^1.8.1",
|
|
89
|
-
"@types/express": "^4.17.21",
|
|
90
|
-
"@types/node": "^22.10.0",
|
|
91
|
-
"@types/react": "^18.3.12",
|
|
92
|
-
"@types/react-dom": "^18.3.1",
|
|
93
|
-
"@types/ws": "^8.5.13",
|
|
94
|
-
"@vitejs/plugin-react": "^4.3.4",
|
|
95
|
-
"concurrently": "^9.1.0",
|
|
96
|
-
"cross-env": "^10.1.0",
|
|
97
|
-
"playwright-core": "^1.62.1",
|
|
98
|
-
"tsx": "^4.19.2",
|
|
99
|
-
"typescript": "^5.7.2",
|
|
100
|
-
"vite": "^6.0.3",
|
|
101
|
-
"vitest": "^4.1.11",
|
|
102
|
-
"electron": "^41.0.0",
|
|
103
|
-
"electron-builder": "^25.0.0",
|
|
104
|
-
"electron-updater": "^6.0.0"
|
|
105
|
-
},
|
|
106
|
-
"allowScripts": {
|
|
107
|
-
"node-pty@1.1.0": true,
|
|
108
|
-
"electron@41.10.7": true
|
|
109
|
-
}
|
|
110
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-web-ui",
|
|
3
|
+
"version": "0.48.2",
|
|
4
|
+
"description": "Web chat interface for the pi coding agent, powered by the pi SDK (@earendil-works/pi-coding-agent) — one-command run, Docker/systemd/launchd deployable",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "xingshuyin",
|
|
8
|
+
"email": "xingshuyin@users.noreply.github.com"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"bin": {
|
|
12
|
+
"pi-web-ui": "bin/pi-web-ui.mjs"
|
|
13
|
+
},
|
|
14
|
+
"main": "electron/main.mjs",
|
|
15
|
+
"files": [
|
|
16
|
+
"bin/",
|
|
17
|
+
"dist/",
|
|
18
|
+
"web/dist/",
|
|
19
|
+
"web/public/",
|
|
20
|
+
"themes/",
|
|
21
|
+
"deploy/",
|
|
22
|
+
"extensions/",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"keywords": [
|
|
27
|
+
"pi",
|
|
28
|
+
"pi-package",
|
|
29
|
+
"coding-agent",
|
|
30
|
+
"ai",
|
|
31
|
+
"chat",
|
|
32
|
+
"web-ui",
|
|
33
|
+
"terminal",
|
|
34
|
+
"llm"
|
|
35
|
+
],
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/xing-shuyin/pi-web-ui.git"
|
|
39
|
+
},
|
|
40
|
+
"pi": {
|
|
41
|
+
"extensions": [
|
|
42
|
+
"./extensions"
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=22.19.0"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"prepublishOnly": "npm run build",
|
|
50
|
+
"dev": "concurrently -k -n server,web -c blue,green \"npm:dev:server\" \"npm:dev:web\"",
|
|
51
|
+
"dev:server": "cross-env PORT=8788 PI_WEB_ALLOW_ORIGINS=http://localhost:5173,http://127.0.0.1:5173 node --watch --import tsx server/index.ts",
|
|
52
|
+
"dev:web": "vite --config web/vite.config.ts",
|
|
53
|
+
"build": "npm run build:web && npm run build:server",
|
|
54
|
+
"build:web": "vite build --config web/vite.config.ts",
|
|
55
|
+
"build:server": "tsc -p tsconfig.server.json",
|
|
56
|
+
"typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p web/tsconfig.json --noEmit && tsc -p tsconfig.tests.json --noEmit",
|
|
57
|
+
"test": "vitest run",
|
|
58
|
+
"test:unit": "vitest run",
|
|
59
|
+
"test:smoke": "node tests/run-smoke.mjs",
|
|
60
|
+
"check:protocol": "node scripts/check-protocol-sync.mjs",
|
|
61
|
+
"test:freeze": "node tests/freeze-test.mjs",
|
|
62
|
+
"start": "node dist/server/index.js",
|
|
63
|
+
"start:electron": "electron .",
|
|
64
|
+
"build:electron": "electron-builder build",
|
|
65
|
+
"build:electron:mac": "electron-builder build --mac",
|
|
66
|
+
"build:electron:win": "electron-builder build --win",
|
|
67
|
+
"build:electron:linux": "electron-builder build --linux",
|
|
68
|
+
"publish:electron": "electron-builder build --publish always"
|
|
69
|
+
},
|
|
70
|
+
"dependencies": {
|
|
71
|
+
"@earendil-works/pi-coding-agent": "^0.84.2",
|
|
72
|
+
"@xterm/addon-fit": "^0.11.0",
|
|
73
|
+
"@xterm/xterm": "^6.0.0",
|
|
74
|
+
"compression": "^1.8.1",
|
|
75
|
+
"express": "^4.21.2",
|
|
76
|
+
"highlight.js": "^11.10.0",
|
|
77
|
+
"node-pty": "^1.1.0",
|
|
78
|
+
"react": "^18.3.1",
|
|
79
|
+
"react-dom": "^18.3.1",
|
|
80
|
+
"react-icons": "^5.7.0",
|
|
81
|
+
"react-markdown": "^9.0.1",
|
|
82
|
+
"rehype-highlight": "^7.0.1",
|
|
83
|
+
"remark-gfm": "^4.0.0",
|
|
84
|
+
"typebox": "^1.3.14",
|
|
85
|
+
"ws": "^8.18.0"
|
|
86
|
+
},
|
|
87
|
+
"devDependencies": {
|
|
88
|
+
"@types/compression": "^1.8.1",
|
|
89
|
+
"@types/express": "^4.17.21",
|
|
90
|
+
"@types/node": "^22.10.0",
|
|
91
|
+
"@types/react": "^18.3.12",
|
|
92
|
+
"@types/react-dom": "^18.3.1",
|
|
93
|
+
"@types/ws": "^8.5.13",
|
|
94
|
+
"@vitejs/plugin-react": "^4.3.4",
|
|
95
|
+
"concurrently": "^9.1.0",
|
|
96
|
+
"cross-env": "^10.1.0",
|
|
97
|
+
"playwright-core": "^1.62.1",
|
|
98
|
+
"tsx": "^4.19.2",
|
|
99
|
+
"typescript": "^5.7.2",
|
|
100
|
+
"vite": "^6.0.3",
|
|
101
|
+
"vitest": "^4.1.11",
|
|
102
|
+
"electron": "^41.0.0",
|
|
103
|
+
"electron-builder": "^25.0.0",
|
|
104
|
+
"electron-updater": "^6.0.0"
|
|
105
|
+
},
|
|
106
|
+
"allowScripts": {
|
|
107
|
+
"node-pty@1.1.0": true,
|
|
108
|
+
"electron@41.10.7": true
|
|
109
|
+
}
|
|
110
|
+
}
|
package/themes/md-preview.css
CHANGED
|
@@ -2903,7 +2903,9 @@ body.panel-resizing {
|
|
|
2903
2903
|
color: var(--text-faint);
|
|
2904
2904
|
}
|
|
2905
2905
|
flex: none;
|
|
2906
|
-
width:
|
|
2906
|
+
width: max-content; /* 按最宽服务商名自适应(上限 280px),名字完整显示 */
|
|
2907
|
+
min-width: 150px;
|
|
2908
|
+
max-width: 280px;
|
|
2907
2909
|
overflow-y: auto;
|
|
2908
2910
|
border-right: 1px solid var(--border-soft);
|
|
2909
2911
|
margin: 2px 4px 2px 0;
|
|
@@ -2959,14 +2961,24 @@ body.panel-resizing {
|
|
|
2959
2961
|
display: flex;
|
|
2960
2962
|
flex-direction: column;
|
|
2961
2963
|
overflow-y: hidden;
|
|
2962
|
-
/*
|
|
2963
|
-
|
|
2964
|
-
|
|
2964
|
+
/* 宽度:由 JS 打开时测量内容自然宽度并锁定(自适应最宽需要、不来回变化);
|
|
2965
|
+
min/max 只是兜底。 */
|
|
2966
|
+
min-width: 440px;
|
|
2967
|
+
max-width: 620px;
|
|
2968
|
+
}
|
|
2969
|
+
/* 模型弹窗高度固定(按最高来):不再随筛选/搜索内容变短而回缩。
|
|
2970
|
+
底部输入栏最高约 300px,预留 320px 保证任何输入框高度都不溢出视口。 */
|
|
2971
|
+
@media (min-width: 769px) {
|
|
2972
|
+
.dropdown.dd-up .dd-menu.dd-menu-model {
|
|
2973
|
+
max-height: none; /* 去掉 dd-up 的 360px 上限,改用固定高度 */
|
|
2974
|
+
height: min(600px, calc(100vh - 320px));
|
|
2975
|
+
}
|
|
2965
2976
|
}
|
|
2966
2977
|
.dd-menu.dd-menu-model .dd-model-scroll {
|
|
2967
2978
|
flex: 1 1 auto;
|
|
2968
2979
|
min-height: 0;
|
|
2969
|
-
|
|
2980
|
+
min-width: 0; /* 模型列可收缩:宽度由固定服务商栏/内容最宽项决定,不被行内长内容撑开 */
|
|
2981
|
+
max-height: none; /* 由外层固定 height 约束,列表吃掉剩余空间后内部滚动 */
|
|
2970
2982
|
}
|
|
2971
2983
|
.dd-menu.dd-menu-model .dd-footer {
|
|
2972
2984
|
flex-shrink: 0;
|
|
@@ -3062,7 +3074,11 @@ body.panel-resizing {
|
|
|
3062
3074
|
white-space: nowrap;
|
|
3063
3075
|
}
|
|
3064
3076
|
.dd-model-provider {
|
|
3065
|
-
flex-shrink:
|
|
3077
|
+
flex-shrink: 1;
|
|
3078
|
+
min-width: 0;
|
|
3079
|
+
overflow: hidden;
|
|
3080
|
+
text-overflow: ellipsis;
|
|
3081
|
+
white-space: nowrap;
|
|
3066
3082
|
font-size: 11px;
|
|
3067
3083
|
color: var(--text-faint);
|
|
3068
3084
|
font-family: var(--mono);
|
|
@@ -3083,6 +3099,18 @@ body.panel-resizing {
|
|
|
3083
3099
|
white-space: nowrap;
|
|
3084
3100
|
}
|
|
3085
3101
|
|
|
3102
|
+
/* 使用次数徽标(突出显示,区别于推理/识图等普通徽标)。 */
|
|
3103
|
+
.dd-model-usage {
|
|
3104
|
+
font-size: 10.5px;
|
|
3105
|
+
line-height: 1.5;
|
|
3106
|
+
color: var(--accent);
|
|
3107
|
+
background: var(--accent-soft);
|
|
3108
|
+
border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--border));
|
|
3109
|
+
border-radius: 4px;
|
|
3110
|
+
padding: 0 6px;
|
|
3111
|
+
white-space: nowrap;
|
|
3112
|
+
}
|
|
3113
|
+
|
|
3086
3114
|
.dd-refresh {
|
|
3087
3115
|
width: 100%;
|
|
3088
3116
|
margin-top: 4px;
|
|
@@ -4306,87 +4334,13 @@ span.msg-editor-hint svg {
|
|
|
4306
4334
|
flex-direction: column;
|
|
4307
4335
|
align-items: center;
|
|
4308
4336
|
text-align: center;
|
|
4309
|
-
padding:
|
|
4310
|
-
color: var(--text-dim);
|
|
4311
|
-
}
|
|
4312
|
-
|
|
4313
|
-
.empty-logo-wrap {
|
|
4314
|
-
position: relative;
|
|
4315
|
-
margin-bottom: 20px;
|
|
4316
|
-
}
|
|
4317
|
-
|
|
4318
|
-
.empty-logo {
|
|
4319
|
-
width: 68px;
|
|
4320
|
-
height: 68px;
|
|
4321
|
-
display: flex;
|
|
4322
|
-
align-items: center;
|
|
4323
|
-
justify-content: center;
|
|
4324
|
-
font-size: 40px;
|
|
4325
|
-
font-weight: 700;
|
|
4326
|
-
color: #fff;
|
|
4327
|
-
background: linear-gradient(135deg, #8b5cf6 0%, #6366f1 60%, #4f46e5 100%);
|
|
4328
|
-
border-radius: 20px;
|
|
4329
|
-
box-shadow:
|
|
4330
|
-
0 16px 44px rgba(139, 92, 246, 0.38),
|
|
4331
|
-
inset 0 1px 0 rgba(255, 255, 255, 0.22);
|
|
4332
|
-
}
|
|
4333
|
-
|
|
4334
|
-
/* soft glow behind the logo */
|
|
4335
|
-
.empty-logo-wrap::before {
|
|
4336
|
-
content: "";
|
|
4337
|
-
position: absolute;
|
|
4338
|
-
inset: -18px;
|
|
4339
|
-
border-radius: 32px;
|
|
4340
|
-
background: radial-gradient(
|
|
4341
|
-
ellipse at center,
|
|
4342
|
-
rgba(139, 92, 246, 0.28),
|
|
4343
|
-
transparent 70%
|
|
4344
|
-
);
|
|
4345
|
-
z-index: -1;
|
|
4346
|
-
}
|
|
4347
|
-
|
|
4348
|
-
.empty-title {
|
|
4349
|
-
margin: 0 0 6px;
|
|
4350
|
-
color: var(--text);
|
|
4351
|
-
font-size: 22px;
|
|
4352
|
-
font-weight: 650;
|
|
4353
|
-
letter-spacing: 0.3px;
|
|
4354
|
-
}
|
|
4355
|
-
|
|
4356
|
-
.empty-sub {
|
|
4357
|
-
margin: 0 0 16px;
|
|
4358
|
-
font-size: 13px;
|
|
4359
|
-
color: var(--text-faint);
|
|
4360
|
-
}
|
|
4361
|
-
|
|
4362
|
-
.empty-cwd {
|
|
4363
|
-
display: inline-flex;
|
|
4364
|
-
align-items: center;
|
|
4365
|
-
gap: 7px;
|
|
4366
|
-
max-width: min(560px, 80vw);
|
|
4367
|
-
padding: 4px 12px;
|
|
4368
|
-
border: 1px solid var(--border-soft);
|
|
4369
|
-
border-radius: 999px;
|
|
4370
|
-
background: var(--bg-elev);
|
|
4371
|
-
font-size: 11.5px;
|
|
4372
|
-
}
|
|
4373
|
-
|
|
4374
|
-
.empty-cwd-label {
|
|
4375
|
-
color: var(--text-faint);
|
|
4376
|
-
flex-shrink: 0;
|
|
4377
|
-
}
|
|
4378
|
-
|
|
4379
|
-
.empty-cwd-path {
|
|
4337
|
+
padding: 40px 20px 30px;
|
|
4380
4338
|
color: var(--text-dim);
|
|
4381
|
-
font-family: var(--mono);
|
|
4382
|
-
overflow: hidden;
|
|
4383
|
-
text-overflow: ellipsis;
|
|
4384
|
-
white-space: nowrap;
|
|
4385
4339
|
}
|
|
4386
4340
|
|
|
4387
4341
|
/* ---- 提示词模板(空态推荐卡片) ---- */
|
|
4388
4342
|
.empty-templates {
|
|
4389
|
-
margin-top:
|
|
4343
|
+
margin-top: 0;
|
|
4390
4344
|
width: min(720px, 92vw);
|
|
4391
4345
|
}
|
|
4392
4346
|
|
|
@@ -4538,9 +4492,12 @@ span.msg-editor-hint svg {
|
|
|
4538
4492
|
max-width: 620px;
|
|
4539
4493
|
}
|
|
4540
4494
|
|
|
4541
|
-
/*
|
|
4542
|
-
|
|
4543
|
-
|
|
4495
|
+
/* 模板库(选择器)弹窗:列所有模板卡片。用复合选择器保证覆盖更靠后的
|
|
4496
|
+
* `.modal { max-width: 460px }` 基类——同优先级的选择器会被后面的规则覆盖,
|
|
4497
|
+
* 单类选择器 `.template-picker` 之前一直没生效。 */
|
|
4498
|
+
.modal.template-picker {
|
|
4499
|
+
/* 两倍宽度:原设计 720px → 1440px,模板卡片多列铺开。 */
|
|
4500
|
+
max-width: 1440px;
|
|
4544
4501
|
}
|
|
4545
4502
|
|
|
4546
4503
|
.template-picker-head {
|
package/themes/white.css
CHANGED
|
@@ -2902,7 +2902,9 @@ body.panel-resizing {
|
|
|
2902
2902
|
color: var(--text-faint);
|
|
2903
2903
|
}
|
|
2904
2904
|
flex: none;
|
|
2905
|
-
width:
|
|
2905
|
+
width: max-content; /* 按最宽服务商名自适应(上限 280px),名字完整显示 */
|
|
2906
|
+
min-width: 150px;
|
|
2907
|
+
max-width: 280px;
|
|
2906
2908
|
overflow-y: auto;
|
|
2907
2909
|
border-right: 1px solid var(--border-soft);
|
|
2908
2910
|
margin: 2px 4px 2px 0;
|
|
@@ -2958,14 +2960,24 @@ body.panel-resizing {
|
|
|
2958
2960
|
display: flex;
|
|
2959
2961
|
flex-direction: column;
|
|
2960
2962
|
overflow-y: hidden;
|
|
2961
|
-
/*
|
|
2962
|
-
|
|
2963
|
-
|
|
2963
|
+
/* 宽度:由 JS 打开时测量内容自然宽度并锁定(自适应最宽需要、不来回变化);
|
|
2964
|
+
min/max 只是兜底。 */
|
|
2965
|
+
min-width: 440px;
|
|
2966
|
+
max-width: 620px;
|
|
2967
|
+
}
|
|
2968
|
+
/* 模型弹窗高度固定(按最高来):不再随筛选/搜索内容变短而回缩。
|
|
2969
|
+
底部输入栏最高约 300px,预留 320px 保证任何输入框高度都不溢出视口。 */
|
|
2970
|
+
@media (min-width: 769px) {
|
|
2971
|
+
.dropdown.dd-up .dd-menu.dd-menu-model {
|
|
2972
|
+
max-height: none; /* 去掉 dd-up 的 360px 上限,改用固定高度 */
|
|
2973
|
+
height: min(600px, calc(100vh - 320px));
|
|
2974
|
+
}
|
|
2964
2975
|
}
|
|
2965
2976
|
.dd-menu.dd-menu-model .dd-model-scroll {
|
|
2966
2977
|
flex: 1 1 auto;
|
|
2967
2978
|
min-height: 0;
|
|
2968
|
-
|
|
2979
|
+
min-width: 0; /* 模型列可收缩:宽度由固定服务商栏/内容最宽项决定,不被行内长内容撑开 */
|
|
2980
|
+
max-height: none; /* 由外层固定 height 约束,列表吃掉剩余空间后内部滚动 */
|
|
2969
2981
|
}
|
|
2970
2982
|
.dd-menu.dd-menu-model .dd-footer {
|
|
2971
2983
|
flex-shrink: 0;
|
|
@@ -3061,7 +3073,11 @@ body.panel-resizing {
|
|
|
3061
3073
|
white-space: nowrap;
|
|
3062
3074
|
}
|
|
3063
3075
|
.dd-model-provider {
|
|
3064
|
-
flex-shrink:
|
|
3076
|
+
flex-shrink: 1;
|
|
3077
|
+
min-width: 0;
|
|
3078
|
+
overflow: hidden;
|
|
3079
|
+
text-overflow: ellipsis;
|
|
3080
|
+
white-space: nowrap;
|
|
3065
3081
|
font-size: 11px;
|
|
3066
3082
|
color: var(--text-faint);
|
|
3067
3083
|
font-family: var(--mono);
|
|
@@ -3082,6 +3098,18 @@ body.panel-resizing {
|
|
|
3082
3098
|
white-space: nowrap;
|
|
3083
3099
|
}
|
|
3084
3100
|
|
|
3101
|
+
/* 使用次数徽标(突出显示,区别于推理/识图等普通徽标)。 */
|
|
3102
|
+
.dd-model-usage {
|
|
3103
|
+
font-size: 10.5px;
|
|
3104
|
+
line-height: 1.5;
|
|
3105
|
+
color: var(--accent);
|
|
3106
|
+
background: var(--accent-soft);
|
|
3107
|
+
border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--border));
|
|
3108
|
+
border-radius: 4px;
|
|
3109
|
+
padding: 0 6px;
|
|
3110
|
+
white-space: nowrap;
|
|
3111
|
+
}
|
|
3112
|
+
|
|
3085
3113
|
.dd-refresh {
|
|
3086
3114
|
width: 100%;
|
|
3087
3115
|
margin-top: 4px;
|
|
@@ -4305,87 +4333,13 @@ span.msg-editor-hint svg {
|
|
|
4305
4333
|
flex-direction: column;
|
|
4306
4334
|
align-items: center;
|
|
4307
4335
|
text-align: center;
|
|
4308
|
-
padding:
|
|
4309
|
-
color: var(--text-dim);
|
|
4310
|
-
}
|
|
4311
|
-
|
|
4312
|
-
.empty-logo-wrap {
|
|
4313
|
-
position: relative;
|
|
4314
|
-
margin-bottom: 20px;
|
|
4315
|
-
}
|
|
4316
|
-
|
|
4317
|
-
.empty-logo {
|
|
4318
|
-
width: 68px;
|
|
4319
|
-
height: 68px;
|
|
4320
|
-
display: flex;
|
|
4321
|
-
align-items: center;
|
|
4322
|
-
justify-content: center;
|
|
4323
|
-
font-size: 40px;
|
|
4324
|
-
font-weight: 700;
|
|
4325
|
-
color: #fff;
|
|
4326
|
-
background: linear-gradient(135deg, #8b5cf6 0%, #6366f1 60%, #4f46e5 100%);
|
|
4327
|
-
border-radius: 20px;
|
|
4328
|
-
box-shadow:
|
|
4329
|
-
0 16px 44px rgba(139, 92, 246, 0.38),
|
|
4330
|
-
inset 0 1px 0 rgba(255, 255, 255, 0.22);
|
|
4331
|
-
}
|
|
4332
|
-
|
|
4333
|
-
/* soft glow behind the logo */
|
|
4334
|
-
.empty-logo-wrap::before {
|
|
4335
|
-
content: "";
|
|
4336
|
-
position: absolute;
|
|
4337
|
-
inset: -18px;
|
|
4338
|
-
border-radius: 32px;
|
|
4339
|
-
background: radial-gradient(
|
|
4340
|
-
ellipse at center,
|
|
4341
|
-
rgba(139, 92, 246, 0.28),
|
|
4342
|
-
transparent 70%
|
|
4343
|
-
);
|
|
4344
|
-
z-index: -1;
|
|
4345
|
-
}
|
|
4346
|
-
|
|
4347
|
-
.empty-title {
|
|
4348
|
-
margin: 0 0 6px;
|
|
4349
|
-
color: var(--text);
|
|
4350
|
-
font-size: 22px;
|
|
4351
|
-
font-weight: 650;
|
|
4352
|
-
letter-spacing: 0.3px;
|
|
4353
|
-
}
|
|
4354
|
-
|
|
4355
|
-
.empty-sub {
|
|
4356
|
-
margin: 0 0 16px;
|
|
4357
|
-
font-size: 13px;
|
|
4358
|
-
color: var(--text-faint);
|
|
4359
|
-
}
|
|
4360
|
-
|
|
4361
|
-
.empty-cwd {
|
|
4362
|
-
display: inline-flex;
|
|
4363
|
-
align-items: center;
|
|
4364
|
-
gap: 7px;
|
|
4365
|
-
max-width: min(560px, 80vw);
|
|
4366
|
-
padding: 4px 12px;
|
|
4367
|
-
border: 1px solid var(--border-soft);
|
|
4368
|
-
border-radius: 999px;
|
|
4369
|
-
background: var(--bg-elev);
|
|
4370
|
-
font-size: 11.5px;
|
|
4371
|
-
}
|
|
4372
|
-
|
|
4373
|
-
.empty-cwd-label {
|
|
4374
|
-
color: var(--text-faint);
|
|
4375
|
-
flex-shrink: 0;
|
|
4376
|
-
}
|
|
4377
|
-
|
|
4378
|
-
.empty-cwd-path {
|
|
4336
|
+
padding: 40px 20px 30px;
|
|
4379
4337
|
color: var(--text-dim);
|
|
4380
|
-
font-family: var(--mono);
|
|
4381
|
-
overflow: hidden;
|
|
4382
|
-
text-overflow: ellipsis;
|
|
4383
|
-
white-space: nowrap;
|
|
4384
4338
|
}
|
|
4385
4339
|
|
|
4386
4340
|
/* ---- 提示词模板(空态推荐卡片) ---- */
|
|
4387
4341
|
.empty-templates {
|
|
4388
|
-
margin-top:
|
|
4342
|
+
margin-top: 0;
|
|
4389
4343
|
width: min(720px, 92vw);
|
|
4390
4344
|
}
|
|
4391
4345
|
|
|
@@ -4537,9 +4491,12 @@ span.msg-editor-hint svg {
|
|
|
4537
4491
|
max-width: 620px;
|
|
4538
4492
|
}
|
|
4539
4493
|
|
|
4540
|
-
/*
|
|
4541
|
-
|
|
4542
|
-
|
|
4494
|
+
/* 模板库(选择器)弹窗:列所有模板卡片。用复合选择器保证覆盖更靠后的
|
|
4495
|
+
* `.modal { max-width: 460px }` 基类——同优先级的选择器会被后面的规则覆盖,
|
|
4496
|
+
* 单类选择器 `.template-picker` 之前一直没生效。 */
|
|
4497
|
+
.modal.template-picker {
|
|
4498
|
+
/* 两倍宽度:原设计 720px → 1440px,模板卡片多列铺开。 */
|
|
4499
|
+
max-width: 1440px;
|
|
4543
4500
|
}
|
|
4544
4501
|
|
|
4545
4502
|
.template-picker-head {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as d,j as n}from"./markdown-DRBrS2Nf.js";import{b as $,T as R,u as O,F as P,a as K,c as q,d as L,e as B,f as J,g as X,h as G,r as Q}from"./index-
|
|
1
|
+
import{a as d,j as n}from"./markdown-DRBrS2Nf.js";import{b as $,T as R,u as O,F as P,a as K,c as q,d as L,e as B,f as J,g as X,h as G,r as Q}from"./index-Dg-bQ98a.js";import{D as U,o as V}from"./xterm-D1D2FVe3.js";import"./react-C9ovnpIm.js";function W({conversationId:s,terminalId:r,command:x,cwd:a,active:f,send:m,register:v}){const w=d.useRef(null),N=d.useRef(null),b=x?JSON.stringify(x):"";return d.useEffect(()=>{const p=w.current;if(!p)return;const t=new U({theme:$(),fontFamily:'"SF Mono", "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace',fontSize:13,cursorBlink:!0,scrollback:8e3}),c=new V;t.loadAddon(c),t.open(p),N.current={term:t,fit:c},f&&t.focus();const h=()=>{t.options.theme=$()};window.addEventListener(R,h),t.attachCustomKeyEventHandler(o=>{var F;if(o.type!=="keydown")return!0;const E=(F=o.key)==null?void 0:F.toLowerCase();if((o.ctrlKey||o.metaKey)&&E==="v")return!1;if(o.ctrlKey&&!o.shiftKey&&!o.altKey&&E==="c"&&t.hasSelection()){const T=t.textarea;return T&&(T.value=t.getSelection(),T.select()),!1}return!0});const g=v(s,r,{write:o=>t.write(o),dispose:()=>t.dispose()}),C=()=>{try{c.fit(),m({type:"terminal_resize",terminalId:r,conversationId:s,cols:t.cols,rows:t.rows})}catch{}},j=requestAnimationFrame(()=>{try{c.fit()}catch{}m(x?{type:"run_command",terminalId:r,conversationId:s,command:x,cols:t.cols,rows:t.rows}:{type:"terminal_create",terminalId:r,conversationId:s,cwd:a,cols:t.cols,rows:t.rows})}),k=t.onData(o=>{m({type:"terminal_input",terminalId:r,conversationId:s,data:o})});let y=null;return typeof ResizeObserver<"u"&&(y=new ResizeObserver(()=>{p.offsetWidth>0&&p.offsetHeight>0&&C()}),y.observe(p)),()=>{cancelAnimationFrame(j),k.dispose(),window.removeEventListener(R,h),y==null||y.disconnect(),g(),t.dispose(),N.current=null}},[s,r,b,m,v]),d.useEffect(()=>{if(!f)return;const p=requestAnimationFrame(()=>{const t=N.current;if(t){try{t.fit.fit(),m({type:"terminal_resize",terminalId:r,conversationId:s,cols:t.term.cols,rows:t.term.rows})}catch{}t.term.focus()}});return()=>cancelAnimationFrame(p)},[f]),n.jsx("div",{ref:w,className:`term-xterm ${f?"":"hidden"}`})}const A={name:"",command:"",cwd:"${pwd}"};function se({chat:s,send:r,terminal:x}){const a=O(),[f,m]=d.useState(null),[v,w]=d.useState(!1),[N,b]=d.useState(!1),[p,t]=d.useState(null),[c,h]=d.useState(A),[g,C]=d.useState(null),j=d.useRef(null);d.useEffect(()=>{s.terminals.length===0?m(null):s.terminals.some(e=>e.id===f)||m(s.terminals[s.terminals.length-1].id)},[s.terminals,f]),d.useEffect(()=>()=>{j.current&&clearTimeout(j.current)},[]);const k=e=>{var u;if(!s.ready)return;const i=Q(),l=s.activeConversationId||((u=s.state)==null?void 0:u.conversationId)||"";x.create({...e,id:i,conversationId:l,cols:e.cols??80,rows:e.rows??24,running:!0,exitCode:null}),m(i),w(!1)},y=()=>{var e;return k({title:a("terminalTitle",{n:s.terminals.length+1}),cwd:((e=s.state)==null?void 0:e.cwd)??""})},o=e=>{var u;const i=e.name||e.command,l=s.terminals.find(_=>_.title===i);if(l){x.restart(l.id),m(l.id),r({type:"run_command",terminalId:l.id,conversationId:l.conversationId,command:e,cols:80,rows:24});return}k({title:i,cwd:((u=s.state)==null?void 0:u.cwd)??"",command:e})},E=e=>{const i=s.terminals.find(l=>l.id===e);if(i&&r({type:"terminal_kill",terminalId:e,conversationId:i.conversationId}),x.close(e),f===e){const l=s.terminals.filter(u=>u.id!==e);m(l.length>0?l[l.length-1].id:null)}},F=()=>{b(!0),t(null),h(A)},T=e=>{const i=s.commands[e];i&&(b(!1),t(e),h({name:i.name,command:i.command,cwd:i.cwd??""}))},D=()=>{b(!1),t(null)},S=()=>{const e=c.name.trim(),i=c.command.trim();if(!e||!i)return;const l=c.cwd.trim(),u={name:e,command:i,cwd:l||void 0},_=N?[...s.commands,u]:p!==null?s.commands.map((z,H)=>H===p?u:z):s.commands;r({type:"save_commands",commands:_}),D()},I=e=>{if(g===e){const i=s.commands.filter((l,u)=>u!==e);r({type:"save_commands",commands:i}),C(null),j.current&&clearTimeout(j.current)}else C(e),j.current&&clearTimeout(j.current),j.current=setTimeout(()=>C(null),2500)},M=N||p!==null;return n.jsxs("div",{className:"terminal-view",children:[n.jsxs("aside",{className:`term-side term-commands ${v?"open":""}`,children:[n.jsxs("div",{className:"panel-header",children:[n.jsx("span",{className:"panel-title",children:a("commands")}),n.jsxs("div",{className:"panel-header-actions",children:[n.jsx("button",{type:"button",className:"panel-refresh",title:a("rerun"),onClick:()=>r({type:"list_commands"}),children:n.jsx(P,{})}),n.jsx("button",{type:"button",className:"panel-new",title:a("newCommand"),onClick:F,children:n.jsx(K,{})})]})]}),n.jsx("div",{className:"panel-body",children:M?n.jsxs("div",{className:"cmd-form",children:[n.jsx("label",{htmlFor:"cmd-name",children:a("name")}),n.jsx("input",{id:"cmd-name",className:"cmd-input",value:c.name,placeholder:a("exampleName"),autoFocus:!0,onChange:e=>h({...c,name:e.target.value})}),n.jsx("label",{htmlFor:"cmd-command",children:a("command")}),n.jsx("input",{id:"cmd-command",className:"cmd-input",value:c.command,placeholder:a("exampleCommand"),onChange:e=>h({...c,command:e.target.value}),onKeyDown:e=>{e.key==="Enter"&&!e.nativeEvent.isComposing&&S()}}),n.jsxs("label",{htmlFor:"cmd-cwd",children:[a("directory")," ",n.jsx("span",{className:"cmd-hint",children:a("cwdHint")})]}),n.jsx("input",{id:"cmd-cwd",className:"cmd-input",value:c.cwd,placeholder:"${pwd}",onChange:e=>h({...c,cwd:e.target.value}),onKeyDown:e=>{e.key==="Enter"&&!e.nativeEvent.isComposing&&S()}}),n.jsxs("div",{className:"cmd-form-actions",children:[n.jsx("button",{type:"button",className:"btn",onClick:D,children:a("cancel")}),n.jsx("button",{type:"button",className:"btn primary",disabled:!c.name.trim()||!c.command.trim(),onClick:S,children:a("save")})]})]}):n.jsxs(n.Fragment,{children:[s.commands.length===0&&n.jsx("div",{className:"panel-empty",children:a("noCommands")}),s.commands.map((e,i)=>n.jsxs("div",{className:"cmd-item",children:[n.jsx("button",{type:"button",className:"cmd-run",title:a("clickToRun"),onClick:()=>o(e),children:n.jsx(q,{})}),n.jsxs("button",{type:"button",className:"cmd-main",title:a("clickToRun"),onClick:()=>o(e),children:[n.jsx("span",{className:"cmd-name",children:e.name}),n.jsx("span",{className:"cmd-command",children:e.command}),e.cwd&&n.jsx("span",{className:"cmd-cwd",children:e.cwd})]}),n.jsx("button",{type:"button",className:"cmd-act",title:a("edit"),onClick:()=>T(i),children:n.jsx(L,{})}),n.jsx("button",{type:"button",className:`cmd-act del ${g===i?"confirm":""}`,title:a("delete"),onClick:()=>I(i),children:g===i?a("confirmQ"):n.jsx(B,{})})]},i))]})}),n.jsxs("div",{className:"term-tabs-block",children:[n.jsxs("div",{className:"panel-header",children:[n.jsx("span",{className:"panel-title",children:a("terminal")}),n.jsx("button",{type:"button",className:"panel-new",title:a("newTerminal"),onClick:y,children:n.jsx(K,{})})]}),n.jsxs("div",{className:"panel-body",children:[s.terminals.length===0&&n.jsx("div",{className:"panel-empty",children:a("noTerminal")}),s.terminals.map(e=>n.jsxs("div",{className:`term-tab ${e.id===f?"active":""}`,children:[n.jsxs("button",{type:"button",className:"term-tab-main",title:`${e.cwd}${e.command?`
|
|
2
2
|
> ${e.command.command}`:""}`,onClick:()=>{m(e.id),w(!1)},children:[n.jsx("span",{className:`term-tab-dot ${e.running?"run":"exit"}`}),n.jsxs("span",{className:"term-tab-title",children:[e.title,!e.running&&n.jsx("span",{className:"term-tab-exit",children:a("exited",{code:e.exitCode===null?"":` ${e.exitCode}`})})]})]}),n.jsx("button",{type:"button",className:"term-tab-close",title:a("closeTerminal"),onClick:()=>E(e.id),children:n.jsx(J,{})})]},e.id))]})]})]}),n.jsxs("div",{className:"term-main",children:[v&&n.jsx("div",{className:"drawer-backdrop",onClick:()=>w(!1)}),n.jsx("button",{type:"button",className:"term-side-toggle",title:a("commands"),onClick:()=>w(e=>!e),children:n.jsx(X,{})}),s.terminals.length===0?n.jsxs("div",{className:"term-empty",children:[n.jsx(G,{className:"term-empty-icon"}),n.jsx("div",{className:"term-empty-title",children:a("builtinTerminal")}),n.jsx("div",{className:"term-empty-sub",children:a("termEmptySub")})]}):s.terminals.map(e=>n.jsx(W,{conversationId:e.conversationId,terminalId:e.id,command:e.command,cwd:e.cwd,active:e.id===f,send:r,register:x.register},`${e.conversationId}:${e.id}`))]})]})}export{se as TerminalPanel};
|