@rexvane/piweb 0.3.15 → 0.3.16
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/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +9 -6
- package/.next/build-manifest.json +3 -3
- package/.next/prerender-manifest.json +6 -6
- package/.next/react-loadable-manifest.json +16 -4
- package/.next/routes-manifest.json +20 -0
- package/.next/server/app/_global-error/page.js +2 -2
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page.js +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +7 -4
- package/.next/server/app/_not-found.segments/_full.segment.rsc +7 -4
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +5 -2
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +5 -2
- package/.next/server/app/api/agent/[id]/events/route.js +2 -2
- package/.next/server/app/api/agent/[id]/events/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/[id]/route.js +1 -1
- package/.next/server/app/api/agent/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/[id]/tree/route.js +1 -1
- package/.next/server/app/api/agent/[id]/tree/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/new/route.js +1 -1
- package/.next/server/app/api/agent/new/route.js.nft.json +1 -1
- package/.next/server/app/api/config/route.js +1 -1
- package/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/server/app/api/files/route.js +1 -1
- package/.next/server/app/api/files/route.js.nft.json +1 -1
- package/.next/server/app/api/git/route.js +2 -2
- package/.next/server/app/api/git/route.js.nft.json +1 -1
- package/.next/server/app/api/growth/route.js +1 -1
- package/.next/server/app/api/growth/route.js.nft.json +1 -1
- package/.next/server/app/api/health/route.js +1 -1
- package/.next/server/app/api/models/route.js +1 -1
- package/.next/server/app/api/models/route.js.nft.json +1 -1
- package/.next/server/app/api/pi-settings/route.js +1 -1
- package/.next/server/app/api/pi-settings/route.js.nft.json +1 -1
- package/.next/server/app/api/plugins/route.js +1 -1
- package/.next/server/app/api/plugins/route.js.nft.json +1 -1
- package/.next/server/app/api/prompts/route.js +1 -1
- package/.next/server/app/api/prompts/route.js.nft.json +1 -1
- package/.next/server/app/api/security/route.js +1 -1
- package/.next/server/app/api/security/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/export/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/export/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/import/route.js +3 -3
- package/.next/server/app/api/sessions/import/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/route.js +1 -1
- package/.next/server/app/api/sessions/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/route.js +2 -2
- package/.next/server/app/api/skills/route.js.nft.json +1 -1
- package/.next/server/app/api/swarm/[id]/route.js +1 -0
- package/.next/server/app/api/swarm/[id]/route.js.nft.json +1 -0
- package/.next/server/app/api/swarm/[id]/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/swarm/route.js +1 -0
- package/.next/server/app/api/swarm/route.js.nft.json +1 -0
- package/.next/server/app/api/swarm/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/tests/route.js +2 -0
- package/.next/server/app/api/tests/route.js.nft.json +1 -0
- package/.next/server/app/api/tests/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/update/route.js +2 -2
- package/.next/server/app/api/update/route.js.nft.json +1 -1
- package/.next/server/app/api/version/route.js +1 -1
- package/.next/server/app/api/version/route.js.nft.json +1 -1
- package/.next/server/app/api/web-auth/route.js +1 -1
- package/.next/server/app/api/workspaces/route.js +1 -1
- package/.next/server/app/api/workspaces/route.js.nft.json +1 -1
- package/.next/server/app/icon.svg/route.js +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +9 -6
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +7 -4
- package/.next/server/app/index.segments/_full.segment.rsc +9 -6
- package/.next/server/app/index.segments/_tree.segment.rsc +5 -2
- package/.next/server/app/login/page.js +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +1 -1
- package/.next/server/app/login.rsc +8 -5
- package/.next/server/app/login.segments/_full.segment.rsc +8 -5
- package/.next/server/app/login.segments/_tree.segment.rsc +5 -2
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +6 -3
- package/.next/server/app/page.js +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +9 -6
- package/.next/server/chunks/496.js +1 -1
- package/.next/server/chunks/532.js +1 -1
- package/.next/server/chunks/686.js +6 -2
- package/.next/server/chunks/757.js +1 -0
- package/.next/server/chunks/775.js +3 -0
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/0t1jBUAuVaTFTXxRyIo3q/_buildManifest.js +1 -0
- package/.next/static/chunks/2608.43c58236c9cce8e6.js +1 -0
- package/.next/static/chunks/{2716.a9e808190a4e2424.js → 2716.4ec42df1d51354c9.js} +1 -1
- package/.next/static/chunks/4632.62139b565b657aac.js +1 -0
- package/.next/static/chunks/{4673.d3d0a7f2599080fb.js → 4673.7796104395deb8d7.js} +1 -1
- package/.next/static/chunks/4686-17f21a006739a596.js +1 -0
- package/.next/static/chunks/7577.10af9bb661652da8.js +1 -0
- package/.next/static/chunks/8866.38ec4ac4ee5a1b74.js +1 -0
- package/.next/static/chunks/app/_global-error/page-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/events/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/tree/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/agent/new/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/config/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/files/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/git/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/growth/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/health/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/models/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/pi-settings/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/plugins/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/prompts/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/security/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/export/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/sessions/import/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/sessions/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/skills/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/swarm/[id]/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/swarm/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/tests/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/update/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/version/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/web-auth/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/api/workspaces/route-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/app/page-14379b8060d5cf07.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-5148173b3f55e415.js +1 -0
- package/.next/static/chunks/webpack-d1a69ad9edb38b11.js +1 -0
- package/.next/static/css/d0a0162cb481abe8.css +1 -0
- package/.next/types/app/api/swarm/[id]/route.ts +353 -0
- package/.next/types/app/api/swarm/route.ts +353 -0
- package/.next/types/app/api/tests/route.ts +353 -0
- package/.next/types/routes.d.ts +4 -1
- package/.next/types/validator.ts +27 -0
- package/README.md +10 -0
- package/package.json +4 -3
- package/scripts/pick-folder.ps1 +11 -2
- package/scripts/release.mjs +11 -31
- package/scripts/run-test-file.mjs +34 -0
- package/scripts/verify-release-config.mjs +24 -0
- package/src/app/api/config/route.ts +4 -1
- package/src/app/api/security/route.ts +8 -3
- package/src/app/api/swarm/[id]/route.ts +28 -0
- package/src/app/api/swarm/route.ts +24 -0
- package/src/app/api/tests/route.ts +27 -0
- package/src/app/api/update/route.ts +8 -2
- package/src/app/globals.css +777 -0
- package/src/app/layout.tsx +13 -6
- package/src/components/AppShell.tsx +505 -199
- package/src/components/ChatInput.tsx +153 -26
- package/src/components/ChatWindow.tsx +46 -40
- package/src/components/ContextMeter.tsx +11 -17
- package/src/components/FileViewer.tsx +1 -1
- package/src/components/GitPanel.tsx +13 -11
- package/src/components/ModelSelector.tsx +19 -6
- package/src/components/PiMark.tsx +5 -38
- package/src/components/ProjectPanel.tsx +1 -0
- package/src/components/PromptPanel.tsx +132 -51
- package/src/components/SessionImportSection.tsx +17 -17
- package/src/components/SessionSidebar.tsx +159 -57
- package/src/components/SettingsPanel.tsx +330 -193
- package/src/components/SwarmCoordinatorPod.tsx +1021 -0
- package/src/components/TestInspectorPod.tsx +549 -0
- package/src/components/icons.tsx +23 -0
- package/src/hooks/usePiWeb.ts +112 -8
- package/src/i18n.tsx +59 -3
- package/src/lib/agent-manager.ts +180 -12
- package/src/lib/command-validation.ts +9 -1
- package/src/lib/delegation.ts +93 -0
- package/src/lib/managed-niubash.ts +8 -4
- package/src/lib/pi.ts +3 -2
- package/src/lib/runtime-activity.ts +27 -0
- package/src/lib/session-import/index.ts +5 -0
- package/src/lib/session-import/lock.ts +25 -0
- package/src/lib/session-import/writer.ts +8 -3
- package/src/lib/skills-service.ts +16 -9
- package/src/lib/swarm-service.ts +371 -0
- package/src/lib/test-run-service.ts +122 -0
- package/src/lib/theme.ts +68 -1
- package/src/lib/trajectory.ts +1 -0
- package/src/lib/types.ts +14 -0
- package/src/lib/workflow.ts +55 -0
- package/.next/static/DdBwPYoHBKtaJ97QIr6Co/_buildManifest.js +0 -1
- package/.next/static/chunks/2608.ec8ff1f5767c9056.js +0 -1
- package/.next/static/chunks/4632.0ed92ae42905ce40.js +0 -1
- package/.next/static/chunks/4686-7d694def920ff093.js +0 -1
- package/.next/static/chunks/app/_global-error/page-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/events/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/tree/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/agent/new/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/config/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/files/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/git/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/growth/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/health/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/models/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/pi-settings/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/plugins/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/prompts/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/security/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/export/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/sessions/import/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/sessions/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/skills/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/update/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/version/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/web-auth/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/api/workspaces/route-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/app/page-9a5440047c5a415c.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-f77e9ede9808b18e.js +0 -1
- package/.next/static/chunks/webpack-42c5aae79b0e5d8c.js +0 -1
- package/.next/static/css/b2d35abc828d4713.css +0 -1
- /package/.next/static/{DdBwPYoHBKtaJ97QIr6Co → 0t1jBUAuVaTFTXxRyIo3q}/_ssgManifest.js +0 -0
|
@@ -30,6 +30,8 @@ import {
|
|
|
30
30
|
IconSettingsOutline16,
|
|
31
31
|
IconTrashOutline16,
|
|
32
32
|
IconTriangleRightFill14,
|
|
33
|
+
IconAgentPresetOutline16,
|
|
34
|
+
IconWorkflowAgent16,
|
|
33
35
|
} from "@/components/icons";
|
|
34
36
|
import { useI18n } from "@/i18n";
|
|
35
37
|
import type { SessionListItem } from "@/hooks/usePiWeb";
|
|
@@ -97,6 +99,12 @@ export function SessionSidebar({
|
|
|
97
99
|
onOpenSettings,
|
|
98
100
|
onAddWorkspace,
|
|
99
101
|
draftCwd,
|
|
102
|
+
gitBranch = "—",
|
|
103
|
+
gitStatus = "未选择",
|
|
104
|
+
canAskCommit = false,
|
|
105
|
+
onAskCommit,
|
|
106
|
+
activeTopView = "workbench",
|
|
107
|
+
onSelectTopView,
|
|
100
108
|
}: {
|
|
101
109
|
sessions: SessionListItem[];
|
|
102
110
|
sessionListError?: string | null;
|
|
@@ -129,6 +137,12 @@ export function SessionSidebar({
|
|
|
129
137
|
onAddWorkspace: () => void;
|
|
130
138
|
/** 新会话草稿所在的工作区:条目显示在该分组内,发送第一条消息才真正创建 */
|
|
131
139
|
draftCwd?: string | null;
|
|
140
|
+
gitBranch?: string;
|
|
141
|
+
gitStatus?: string;
|
|
142
|
+
canAskCommit?: boolean;
|
|
143
|
+
onAskCommit?: () => void;
|
|
144
|
+
activeTopView?: "workbench" | "diff" | "tests" | "swarm" | "archive";
|
|
145
|
+
onSelectTopView?: (view: "workbench" | "diff" | "tests" | "swarm" | "archive") => void;
|
|
132
146
|
}) {
|
|
133
147
|
const { t, lang } = useI18n();
|
|
134
148
|
const [q, setQ] = useState("");
|
|
@@ -392,9 +406,6 @@ export function SessionSidebar({
|
|
|
392
406
|
<IconSearchOutline16 size={17} />
|
|
393
407
|
</button>
|
|
394
408
|
<div className="flex-1" />
|
|
395
|
-
<button className="rail-btn" title={t.settings} onClick={onOpenSettings}>
|
|
396
|
-
<IconSettingsOutline16 size={17} />
|
|
397
|
-
</button>
|
|
398
409
|
</div>
|
|
399
410
|
);
|
|
400
411
|
}
|
|
@@ -406,16 +417,11 @@ export function SessionSidebar({
|
|
|
406
417
|
return (
|
|
407
418
|
<div
|
|
408
419
|
key={s.path}
|
|
409
|
-
className="group relative flex items-center
|
|
420
|
+
className="pw-session-row group relative flex items-center transition-colors"
|
|
421
|
+
data-selected={selected || undefined}
|
|
410
422
|
style={{
|
|
411
423
|
background: selected ? "var(--dsw-active)" : "transparent",
|
|
412
|
-
paddingLeft: indented ?
|
|
413
|
-
paddingRight: 8,
|
|
414
|
-
paddingTop: 6,
|
|
415
|
-
paddingBottom: 6,
|
|
416
|
-
// 选中/悬停框之间留缝,不互相粘连
|
|
417
|
-
marginTop: 2,
|
|
418
|
-
marginBottom: 2,
|
|
424
|
+
paddingLeft: indented ? 32 : s.streaming ? 16 : 8,
|
|
419
425
|
}}
|
|
420
426
|
onMouseEnter={(e) => {
|
|
421
427
|
if (!selected) e.currentTarget.style.background = "var(--dsw-hover)";
|
|
@@ -448,8 +454,8 @@ export function SessionSidebar({
|
|
|
448
454
|
<button
|
|
449
455
|
className="icon-btn"
|
|
450
456
|
style={{ width: 22, height: 22 }}
|
|
451
|
-
title=
|
|
452
|
-
aria-label=
|
|
457
|
+
title={t.sessionActions}
|
|
458
|
+
aria-label={t.sessionActions}
|
|
453
459
|
onClick={(e) => {
|
|
454
460
|
e.stopPropagation();
|
|
455
461
|
setSessionMenu(sessionMenu === s.path ? null : s.path);
|
|
@@ -525,16 +531,12 @@ export function SessionSidebar({
|
|
|
525
531
|
return (
|
|
526
532
|
<div key={g.cwd}>
|
|
527
533
|
<div
|
|
528
|
-
className="group relative flex items-center
|
|
534
|
+
className="pw-workspace-row group relative flex items-center transition-colors"
|
|
535
|
+
data-current={isCurrent || undefined}
|
|
536
|
+
data-open={open || undefined}
|
|
529
537
|
style={{
|
|
530
538
|
background: open || isCurrent ? "var(--dsw-hover)" : "transparent",
|
|
531
|
-
paddingLeft:
|
|
532
|
-
paddingRight: 6,
|
|
533
|
-
paddingTop: 7,
|
|
534
|
-
paddingBottom: 7,
|
|
535
|
-
// 悬停/展开框之间留缝,不互相粘连(与会话行一致)
|
|
536
|
-
marginTop: 2,
|
|
537
|
-
marginBottom: 2,
|
|
539
|
+
paddingLeft: 8,
|
|
538
540
|
}}
|
|
539
541
|
onMouseEnter={(e) => {
|
|
540
542
|
if (!(open || isCurrent)) e.currentTarget.style.background = "var(--dsw-hover)";
|
|
@@ -570,8 +572,8 @@ export function SessionSidebar({
|
|
|
570
572
|
<button
|
|
571
573
|
className="icon-btn"
|
|
572
574
|
style={{ width: 22, height: 22 }}
|
|
573
|
-
title=
|
|
574
|
-
aria-label=
|
|
575
|
+
title={t.workspaceActions}
|
|
576
|
+
aria-label={t.workspaceActions}
|
|
575
577
|
onClick={() => {
|
|
576
578
|
setRowMenu(rowMenu === g.cwd ? null : g.cwd);
|
|
577
579
|
setSessionMenu(null);
|
|
@@ -651,9 +653,9 @@ export function SessionSidebar({
|
|
|
651
653
|
};
|
|
652
654
|
|
|
653
655
|
return (
|
|
654
|
-
<div className="flex h-full min-h-0 flex-col">
|
|
656
|
+
<div className="pw-sidebar flex h-full min-h-0 flex-col">
|
|
655
657
|
{/* 品牌行 */}
|
|
656
|
-
<div className="flex items-center gap-1 px-4 pb-2 pt-4">
|
|
658
|
+
<div className="pw-sidebar-head flex items-center gap-1 px-4 pb-2 pt-4">
|
|
657
659
|
<BrandPi />
|
|
658
660
|
<div className="flex-1" />
|
|
659
661
|
<button className="icon-btn" onClick={onToggleCollapse} title="«">
|
|
@@ -661,14 +663,116 @@ export function SessionSidebar({
|
|
|
661
663
|
</button>
|
|
662
664
|
</div>
|
|
663
665
|
|
|
664
|
-
{/*
|
|
665
|
-
<div className="px-3 pt-1">
|
|
666
|
-
<button className="btn-
|
|
666
|
+
{/* 新会话(柔和粘土拟物风格) */}
|
|
667
|
+
<div className="pw-sidebar-new px-3 pt-1">
|
|
668
|
+
<button className="clay-btn clay-btn-mint w-full py-2.5 px-4 text-xs font-semibold tracking-wide flex items-center justify-center gap-2 text-white shadow-md rounded-2xl transition-all" onClick={onNew}>
|
|
667
669
|
<IconNewChatOutline16 size={14} />
|
|
668
670
|
{t.newChat}
|
|
669
671
|
</button>
|
|
670
672
|
</div>
|
|
671
673
|
|
|
674
|
+
{/* Git 状态卡片 (Screen 1 & 2) */}
|
|
675
|
+
<div className="px-3 pt-2">
|
|
676
|
+
<div className="clay-card p-2.5 rounded-2xl border border-slate-200/50 dark:border-slate-800/50 bg-white/70 dark:bg-slate-900/70">
|
|
677
|
+
<div className="flex items-center justify-between text-xs font-medium text-slate-700 dark:text-slate-200">
|
|
678
|
+
<div className="flex items-center gap-1.5">
|
|
679
|
+
<IconBranchOutline16 size={13} className="text-emerald-500" />
|
|
680
|
+
<span className="font-mono truncate max-w-[90px]" title={gitBranch}>{gitBranch}</span>
|
|
681
|
+
</div>
|
|
682
|
+
<span className={`text-[10px] font-mono font-semibold px-1.5 py-0.5 rounded ${gitStatus === "干净" ? "text-emerald-600 dark:text-emerald-400 bg-emerald-50 dark:bg-emerald-950/60" : "text-amber-700 dark:text-amber-300 bg-amber-50 dark:bg-amber-950/60"}`}>
|
|
683
|
+
{gitStatus}
|
|
684
|
+
</span>
|
|
685
|
+
</div>
|
|
686
|
+
<div className="flex items-center justify-between pt-2">
|
|
687
|
+
<span className="text-[11px] text-slate-400">就绪待审查</span>
|
|
688
|
+
<button
|
|
689
|
+
type="button"
|
|
690
|
+
className="px-2.5 py-1 text-[11px] font-medium text-emerald-700 dark:text-emerald-300 rounded-xl clay-btn clay-btn-soft transition-colors flex items-center gap-1 disabled:opacity-50 disabled:cursor-not-allowed"
|
|
691
|
+
disabled={!canAskCommit}
|
|
692
|
+
onClick={onAskCommit}
|
|
693
|
+
>
|
|
694
|
+
<span>让 pi 提交</span>
|
|
695
|
+
</button>
|
|
696
|
+
</div>
|
|
697
|
+
</div>
|
|
698
|
+
</div>
|
|
699
|
+
|
|
700
|
+
{/* 快速视图切换导航 (Screen 1 & 3 & 4) */}
|
|
701
|
+
<div className="px-3 pt-2">
|
|
702
|
+
<nav className="flex flex-col gap-1">
|
|
703
|
+
<button
|
|
704
|
+
type="button"
|
|
705
|
+
className={`flex items-center justify-between px-3 py-1.5 rounded-xl transition-all text-xs font-medium ${
|
|
706
|
+
activeTopView === "workbench"
|
|
707
|
+
? "clay-card text-emerald-700 dark:text-emerald-300 font-bold bg-white dark:bg-slate-800 shadow-sm"
|
|
708
|
+
: "text-slate-600 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800/60"
|
|
709
|
+
}`}
|
|
710
|
+
onClick={() => onSelectTopView?.("workbench")}
|
|
711
|
+
>
|
|
712
|
+
<span className="flex items-center gap-2">
|
|
713
|
+
<IconFolderOpenOutline16 size={14} className={activeTopView === "workbench" ? "text-emerald-500" : "text-slate-400"} />
|
|
714
|
+
<span>工作区文件</span>
|
|
715
|
+
</span>
|
|
716
|
+
</button>
|
|
717
|
+
<button
|
|
718
|
+
type="button"
|
|
719
|
+
className={`flex items-center justify-between px-3 py-1.5 rounded-xl transition-all text-xs font-medium ${
|
|
720
|
+
activeTopView === "diff"
|
|
721
|
+
? "clay-card text-emerald-700 dark:text-emerald-300 font-bold bg-white dark:bg-slate-800 shadow-sm"
|
|
722
|
+
: "text-slate-600 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800/60"
|
|
723
|
+
}`}
|
|
724
|
+
onClick={() => onSelectTopView?.("diff")}
|
|
725
|
+
>
|
|
726
|
+
<span className="flex items-center gap-2">
|
|
727
|
+
<IconEditOutline16 size={14} className={activeTopView === "diff" ? "text-emerald-500" : "text-slate-400"} />
|
|
728
|
+
<span>改动检查器</span>
|
|
729
|
+
</span>
|
|
730
|
+
</button>
|
|
731
|
+
<button
|
|
732
|
+
type="button"
|
|
733
|
+
className={`flex items-center justify-between px-3 py-1.5 rounded-xl transition-all text-xs font-medium ${
|
|
734
|
+
activeTopView === "tests"
|
|
735
|
+
? "clay-card text-emerald-700 dark:text-emerald-300 font-bold bg-white dark:bg-slate-800 shadow-sm"
|
|
736
|
+
: "text-slate-600 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800/60"
|
|
737
|
+
}`}
|
|
738
|
+
onClick={() => onSelectTopView?.("tests")}
|
|
739
|
+
>
|
|
740
|
+
<span className="flex items-center gap-2">
|
|
741
|
+
<IconWorkflowAgent16 size={14} className={activeTopView === "tests" ? "text-emerald-500" : "text-slate-400"} />
|
|
742
|
+
<span>测试套件</span>
|
|
743
|
+
</span>
|
|
744
|
+
</button>
|
|
745
|
+
<button
|
|
746
|
+
type="button"
|
|
747
|
+
className={`flex items-center justify-between px-3 py-1.5 rounded-xl transition-all text-xs font-medium ${
|
|
748
|
+
activeTopView === "swarm"
|
|
749
|
+
? "clay-card text-emerald-700 dark:text-emerald-300 font-bold bg-white dark:bg-slate-800 shadow-sm"
|
|
750
|
+
: "text-slate-600 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800/60"
|
|
751
|
+
}`}
|
|
752
|
+
onClick={() => onSelectTopView?.("swarm")}
|
|
753
|
+
>
|
|
754
|
+
<span className="flex items-center gap-2">
|
|
755
|
+
<IconAgentPresetOutline16 size={14} className={activeTopView === "swarm" ? "text-emerald-500" : "text-slate-400"} />
|
|
756
|
+
<span>智能体群组</span>
|
|
757
|
+
</span>
|
|
758
|
+
</button>
|
|
759
|
+
<button
|
|
760
|
+
type="button"
|
|
761
|
+
className={`flex items-center justify-between px-3 py-1.5 rounded-xl transition-all text-xs font-medium ${
|
|
762
|
+
activeTopView === "archive"
|
|
763
|
+
? "clay-card text-emerald-700 dark:text-emerald-300 font-bold bg-white dark:bg-slate-800 shadow-sm"
|
|
764
|
+
: "text-slate-600 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800/60"
|
|
765
|
+
}`}
|
|
766
|
+
onClick={() => onSelectTopView?.("archive")}
|
|
767
|
+
>
|
|
768
|
+
<span className="flex items-center gap-2">
|
|
769
|
+
<IconArchiveOutline20 size={14} className={activeTopView === "archive" ? "text-emerald-500" : "text-slate-400"} />
|
|
770
|
+
<span>归档</span>
|
|
771
|
+
</span>
|
|
772
|
+
</button>
|
|
773
|
+
</nav>
|
|
774
|
+
</div>
|
|
775
|
+
|
|
672
776
|
{/* 工作区标题行 / 搜索框(互替,照 dsh) */}
|
|
673
777
|
{searchOpen ? (
|
|
674
778
|
<div className="px-3 pb-1 pt-3">
|
|
@@ -676,6 +780,7 @@ export function SessionSidebar({
|
|
|
676
780
|
<IconSearchOutline16 size={14} style={{ color: "var(--dsw-label-caption)" }} />
|
|
677
781
|
<input
|
|
678
782
|
autoFocus
|
|
783
|
+
aria-label={t.searchSessions}
|
|
679
784
|
value={q}
|
|
680
785
|
onChange={(e) => setQ(e.target.value)}
|
|
681
786
|
placeholder={t.searchSessions}
|
|
@@ -685,6 +790,7 @@ export function SessionSidebar({
|
|
|
685
790
|
<button
|
|
686
791
|
className="icon-btn"
|
|
687
792
|
style={{ width: 20, height: 20 }}
|
|
793
|
+
aria-label={t.close}
|
|
688
794
|
onClick={() => {
|
|
689
795
|
setQ("");
|
|
690
796
|
setSearchOpen(false);
|
|
@@ -695,7 +801,7 @@ export function SessionSidebar({
|
|
|
695
801
|
</div>
|
|
696
802
|
</div>
|
|
697
803
|
) : (
|
|
698
|
-
<div className="flex items-center gap-0.5 px-4 pb-1 pt-3">
|
|
804
|
+
<div className="pw-sidebar-section-head flex items-center gap-0.5 px-4 pb-1 pt-3">
|
|
699
805
|
<span style={{ fontSize: 13, color: "var(--dsw-label-primary)" }}>{t.workspaces}</span>
|
|
700
806
|
<div className="flex-1" />
|
|
701
807
|
<button className="icon-btn" style={{ width: 26, height: 26 }} title={t.search} onClick={() => setSearchOpen(true)}>
|
|
@@ -733,7 +839,7 @@ export function SessionSidebar({
|
|
|
733
839
|
)}
|
|
734
840
|
|
|
735
841
|
{/* 列表区 */}
|
|
736
|
-
<div className="min-h-0 flex-1 overflow-y-auto px-3 pb-3">
|
|
842
|
+
<div className="pw-sidebar-list min-h-0 flex-1 overflow-y-auto px-3 pb-3">
|
|
737
843
|
{sessionListError && (
|
|
738
844
|
<div role="alert" className="mb-2 rounded-xl px-3 py-2" style={{ background: "var(--dsw-hover)", color: "var(--dsw-danger)", fontSize: 12 }}>
|
|
739
845
|
<div>{t.sessionListLoadFailed}: {sessionListError}</div>
|
|
@@ -864,28 +970,20 @@ export function SessionSidebar({
|
|
|
864
970
|
)}
|
|
865
971
|
</div>
|
|
866
972
|
|
|
867
|
-
{/*
|
|
868
|
-
<div className="px-3 py-2
|
|
869
|
-
<
|
|
870
|
-
className="flex w-full items-center gap-2.5 rounded-xl px-4 py-2 text-left transition-colors"
|
|
871
|
-
style={{ color: "var(--dsw-label-secondary)" }}
|
|
872
|
-
onMouseEnter={(e) => (e.currentTarget.style.background = "var(--dsw-hover)")}
|
|
873
|
-
onMouseLeave={(e) => (e.currentTarget.style.background = "transparent")}
|
|
874
|
-
onClick={onOpenSettings}
|
|
875
|
-
>
|
|
876
|
-
<IconSettingsOutline16 size={16} />
|
|
877
|
-
<span style={{ fontSize: "var(--dsh-content-font-size)" }}>{t.settings}</span>
|
|
878
|
-
</button>
|
|
973
|
+
{/* 底部版本号 */}
|
|
974
|
+
<div className="pw-sidebar-footer px-3 py-2 border-t border-slate-200/60 dark:border-slate-800/60 flex items-center justify-center text-xs text-slate-400 font-mono text-[11px] shrink-0">
|
|
975
|
+
<span>PiWeb v0.3.15</span>
|
|
879
976
|
</div>
|
|
880
977
|
|
|
881
978
|
{/* 重命名弹窗(照用户截图 media_1788745548711.png,通过 createPortal 挂载到 document.body 确保浏览器正居中) */}
|
|
882
979
|
{mounted && renameTarget && createPortal(
|
|
883
980
|
<div
|
|
884
|
-
className="fixed inset-0 z-[9999] flex items-center justify-center
|
|
981
|
+
className="modal-mask fixed inset-0 z-[9999] flex items-center justify-center p-4 animate-in fade-in duration-150"
|
|
885
982
|
onClick={closeRename}
|
|
886
983
|
>
|
|
887
984
|
<div
|
|
888
|
-
className="relative w-full max-w-[420px] rounded-[24px]
|
|
985
|
+
className="glass-modal relative w-full max-w-[420px] rounded-[24px] p-6 shadow-2xl"
|
|
986
|
+
style={{ color: "var(--dsw-label-primary)", border: "0.5px solid var(--dsw-border-l2)" }}
|
|
889
987
|
onClick={(e) => e.stopPropagation()}
|
|
890
988
|
role="dialog"
|
|
891
989
|
aria-modal="true"
|
|
@@ -896,14 +994,14 @@ export function SessionSidebar({
|
|
|
896
994
|
type="button"
|
|
897
995
|
onClick={closeRename}
|
|
898
996
|
disabled={renamePending}
|
|
899
|
-
className="absolute right-5 top-5 rounded-full p-1
|
|
997
|
+
className="icon-btn absolute right-5 top-5 rounded-full p-1"
|
|
900
998
|
aria-label={t.close}
|
|
901
999
|
>
|
|
902
1000
|
<IconCloseOutline14 size={16} />
|
|
903
1001
|
</button>
|
|
904
1002
|
|
|
905
1003
|
{/* 标题 */}
|
|
906
|
-
<h3 id="rename-dialog-title" className="text-lg font-medium
|
|
1004
|
+
<h3 id="rename-dialog-title" className="pr-8 text-lg font-medium">
|
|
907
1005
|
{renameTarget.type === "session"
|
|
908
1006
|
? (t.renameSession || "重命名会话")
|
|
909
1007
|
: (t.renameWorkspace || "重命名工作区")}
|
|
@@ -914,6 +1012,7 @@ export function SessionSidebar({
|
|
|
914
1012
|
<input
|
|
915
1013
|
ref={renameInputRef}
|
|
916
1014
|
type="text"
|
|
1015
|
+
aria-label={renameTarget.type === "session" ? t.renameSession : t.renameWorkspace}
|
|
917
1016
|
value={renameValue}
|
|
918
1017
|
disabled={renamePending}
|
|
919
1018
|
onChange={(e) => {
|
|
@@ -924,7 +1023,8 @@ export function SessionSidebar({
|
|
|
924
1023
|
if (e.key === "Enter") void handleConfirmRename();
|
|
925
1024
|
if (e.key === "Escape") closeRename();
|
|
926
1025
|
}}
|
|
927
|
-
className="w-full rounded-full
|
|
1026
|
+
className="w-full rounded-full px-4 py-2.5 text-[14.5px] outline-none transition"
|
|
1027
|
+
style={{ background: "var(--dsw-hover)", border: "1px solid var(--dsw-border-l2)", color: "var(--dsw-label-primary)" }}
|
|
928
1028
|
/>
|
|
929
1029
|
</div>
|
|
930
1030
|
{renameError && (
|
|
@@ -937,7 +1037,7 @@ export function SessionSidebar({
|
|
|
937
1037
|
type="button"
|
|
938
1038
|
onClick={closeRename}
|
|
939
1039
|
disabled={renamePending}
|
|
940
|
-
className="
|
|
1040
|
+
className="btn-outline"
|
|
941
1041
|
>
|
|
942
1042
|
{t.cancel}
|
|
943
1043
|
</button>
|
|
@@ -945,7 +1045,7 @@ export function SessionSidebar({
|
|
|
945
1045
|
type="button"
|
|
946
1046
|
onClick={() => void handleConfirmRename()}
|
|
947
1047
|
disabled={renamePending || !renameValue.trim() || (renameTarget.type === "workspace" && (renameValue.trim() === renameTarget.name || renameWorkspaceConflict))}
|
|
948
|
-
className="
|
|
1048
|
+
className="btn-primary-white"
|
|
949
1049
|
>
|
|
950
1050
|
{t.rename}
|
|
951
1051
|
</button>
|
|
@@ -958,11 +1058,12 @@ export function SessionSidebar({
|
|
|
958
1058
|
{/* 删除工作区确认弹窗(照用户截图 media_1788745235179.png 与 media_1788746156687.png,通过 createPortal 挂载到 document.body 确保浏览器正居中) */}
|
|
959
1059
|
{mounted && deleteWorkspaceTarget && createPortal(
|
|
960
1060
|
<div
|
|
961
|
-
className="fixed inset-0 z-[9999] flex items-center justify-center
|
|
1061
|
+
className="modal-mask fixed inset-0 z-[9999] flex items-center justify-center p-4 animate-in fade-in duration-150"
|
|
962
1062
|
onClick={() => !deleteWorkspacePending && setDeleteWorkspaceTarget(null)}
|
|
963
1063
|
>
|
|
964
1064
|
<div
|
|
965
|
-
className="relative w-full max-w-[420px] rounded-[24px]
|
|
1065
|
+
className="glass-modal relative w-full max-w-[420px] rounded-[24px] p-6 shadow-2xl"
|
|
1066
|
+
style={{ color: "var(--dsw-label-primary)", border: "0.5px solid var(--dsw-border-l2)" }}
|
|
966
1067
|
onClick={(e) => e.stopPropagation()}
|
|
967
1068
|
role="dialog"
|
|
968
1069
|
aria-modal="true"
|
|
@@ -973,26 +1074,26 @@ export function SessionSidebar({
|
|
|
973
1074
|
type="button"
|
|
974
1075
|
onClick={() => setDeleteWorkspaceTarget(null)}
|
|
975
1076
|
disabled={deleteWorkspacePending}
|
|
976
|
-
className="absolute right-5 top-5 rounded-full p-1
|
|
1077
|
+
className="icon-btn absolute right-5 top-5 rounded-full p-1"
|
|
977
1078
|
aria-label={t.close}
|
|
978
1079
|
>
|
|
979
1080
|
<IconCloseOutline14 size={16} />
|
|
980
1081
|
</button>
|
|
981
1082
|
|
|
982
1083
|
{/* 标题 */}
|
|
983
|
-
<h3 id="delete-workspace-dialog-title" className="text-lg font-medium
|
|
1084
|
+
<h3 id="delete-workspace-dialog-title" className="pr-8 text-lg font-medium">
|
|
984
1085
|
{t.deleteWorkspace}
|
|
985
1086
|
</h3>
|
|
986
1087
|
|
|
987
1088
|
{/* 描述文本 */}
|
|
988
|
-
<p className="mt-3 text-[14.5px] leading-relaxed
|
|
1089
|
+
<p className="mt-3 text-[14.5px] leading-relaxed" style={{ color: "var(--dsw-label-secondary)" }}>
|
|
989
1090
|
{(t.deleteWorkspaceConfirm || "将把“{name}”从工作区列表中移除。文件夹与会话记录会保留,其会话将显示在“未分组”下。").replace(
|
|
990
1091
|
"{name}",
|
|
991
1092
|
deleteWorkspaceTarget.name,
|
|
992
1093
|
)}
|
|
993
1094
|
</p>
|
|
994
1095
|
{deleteWorkspacePending && (
|
|
995
|
-
<p className="mt-4 text-sm
|
|
1096
|
+
<p className="mt-4 text-sm" style={{ color: "var(--dsw-label-caption)" }} role="status">{t.deleteWorkspacePending}</p>
|
|
996
1097
|
)}
|
|
997
1098
|
{deleteWorkspaceError && (
|
|
998
1099
|
<p className="mt-4 text-sm" style={{ color: "var(--dsw-danger)" }} role="alert">{deleteWorkspaceError}</p>
|
|
@@ -1004,7 +1105,7 @@ export function SessionSidebar({
|
|
|
1004
1105
|
type="button"
|
|
1005
1106
|
onClick={() => setDeleteWorkspaceTarget(null)}
|
|
1006
1107
|
disabled={deleteWorkspacePending}
|
|
1007
|
-
className="
|
|
1108
|
+
className="btn-outline"
|
|
1008
1109
|
>
|
|
1009
1110
|
{t.cancel}
|
|
1010
1111
|
</button>
|
|
@@ -1012,7 +1113,8 @@ export function SessionSidebar({
|
|
|
1012
1113
|
type="button"
|
|
1013
1114
|
onClick={() => void handleConfirmDeleteWorkspace()}
|
|
1014
1115
|
disabled={deleteWorkspacePending}
|
|
1015
|
-
className="
|
|
1116
|
+
className="btn-outline"
|
|
1117
|
+
style={{ color: "var(--dsw-danger)" }}
|
|
1016
1118
|
>
|
|
1017
1119
|
{t.deleteWorkspace}
|
|
1018
1120
|
</button>
|