@rexvane/piweb 0.3.24 → 0.3.26
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 +11 -11
- package/.next/build-manifest.json +3 -3
- package/.next/prerender-manifest.json +5 -5
- package/.next/react-loadable-manifest.json +13 -20
- package/.next/required-server-files.js +2 -1
- package/.next/required-server-files.json +2 -1
- package/.next/routes-manifest.json +6 -8
- 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 +2 -2
- package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -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/agent/resources/route.js +1 -0
- package/.next/server/app/api/agent/resources/route.js.nft.json +1 -0
- package/.next/server/app/api/agent/resources/route_client-reference-manifest.js +1 -0
- 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/fs/route.js +1 -1
- package/.next/server/app/api/fs/route.js.nft.json +1 -1
- package/.next/server/app/api/git/route.js +4 -4
- package/.next/server/app/api/git/route.js.nft.json +1 -1
- package/.next/server/app/api/github/route.js +4 -4
- package/.next/server/app/api/github/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/defaults/route.js +1 -1
- package/.next/server/app/api/models/defaults/route.js.nft.json +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/remote/route.js +4 -3
- 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 +2 -2
- 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/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 +2 -2
- 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 +6 -7
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +6 -7
- package/.next/server/app/index.segments/_full.segment.rsc +6 -7
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -3
- 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 +3 -3
- package/.next/server/app/login.segments/_full.segment.rsc +3 -3
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/page.js +1 -1
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +11 -11
- package/.next/server/chunks/3924.js +3 -3
- package/.next/server/chunks/538.js +1 -1
- package/.next/server/chunks/620.js +1 -0
- package/.next/server/chunks/6229.js +1 -1
- package/.next/server/chunks/7496.js +1 -1
- package/.next/server/chunks/7662.js +2 -2
- package/.next/server/chunks/8686.js +1 -1
- package/.next/server/functions-config-manifest.json +1 -2
- package/.next/server/instrumentation.js.nft.json +1 -1
- 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/preview-props.json +3 -3
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/QJCtqgDKzGS2BdKABd9ch/_buildManifest.js +1 -0
- package/.next/static/chunks/2577.86c8538fbf05a8b2.js +1 -0
- package/.next/static/chunks/2716.fa561519675a3ff1.js +1 -0
- package/.next/static/chunks/2906.8a0e09bb47605cf1.js +1 -0
- package/.next/static/chunks/4673.ea36e55005c0f82f.js +1 -0
- package/.next/static/chunks/4686-4dc565817a160351.js +1 -0
- package/.next/static/chunks/4778.0d2c5d75b791d352.js +1 -0
- package/.next/static/chunks/{618.949981da99be7182.js → 618.9a22656b863f242b.js} +2 -2
- package/.next/static/chunks/app/_global-error/page-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/events/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/tree/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/agent/new/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/agent/resources/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/config/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/files/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/fs/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/git/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/github/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/growth/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/health/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/models/defaults/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/models/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/pi-settings/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/plugins/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/prompts/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/remote/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/security/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/export/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/sessions/import/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/sessions/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/skills/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/update/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/version/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/web-auth/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/api/workspaces/route-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/app/page-71f2d3b3ed864b3d.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-f2d93969c0bcf406.js +1 -0
- package/.next/static/chunks/webpack-ffc09b5fcc8aaa6d.js +1 -0
- package/.next/static/css/014eb1f21414e615.css +1 -0
- package/.next/static/css/56b129a13637fcfd.css +1 -0
- package/.next/static/css/7e3caf797e4cb19a.css +1 -0
- package/.next/types/app/api/agent/{[id]/side-chat → resources}/route.ts +3 -3
- package/.next/types/routes.d.ts +2 -2
- package/.next/types/validator.ts +9 -9
- package/README.md +1 -1
- package/next.config.ts +1 -1
- package/package.json +9 -9
- package/scripts/apply-global.mjs +87 -0
- package/scripts/launcher.mjs +21 -0
- package/scripts/testing/prepare-sdk-tools.mjs +19 -0
- package/src/app/api/agent/new/route.ts +2 -1
- package/src/app/api/agent/resources/route.ts +18 -0
- package/src/app/api/models/route.ts +22 -1
- package/src/app/api/plugins/route.ts +3 -2
- package/src/app/api/prompts/route.ts +3 -2
- package/src/app/api/remote/route.ts +22 -4
- package/src/app/api/sessions/[id]/export/route.ts +3 -1
- package/src/app/api/skills/route.ts +3 -2
- package/src/app/globals.css +1002 -1765
- package/src/components/AppShell.tsx +128 -93
- package/src/components/ChatInput.tsx +177 -98
- package/src/components/ChatWindow.tsx +189 -56
- package/src/components/ContextMeter.tsx +33 -9
- package/src/components/CustomSelect.module.css +142 -0
- package/src/components/CustomSelect.tsx +157 -0
- package/src/components/DrawerPanel.tsx +1 -1
- package/src/components/ExtensionUI.tsx +9 -3
- package/src/components/FileViewer.tsx +24 -21
- package/src/components/GitPanel.tsx +35 -13
- package/src/components/GrowthTree.tsx +6 -2
- package/src/components/ImageViewer.tsx +72 -0
- package/src/components/MarkdownBlock.tsx +67 -96
- package/src/components/ModelSelector.tsx +36 -39
- package/src/components/PiMark.tsx +76 -41
- package/src/components/PreviewImage.tsx +33 -0
- package/src/components/ProjectPanel.tsx +8 -5
- package/src/components/PromptPanel.tsx +85 -20
- package/src/components/ProviderSetupModal.module.css +12 -11
- package/src/components/ProviderSetupModal.tsx +107 -36
- package/src/components/RemoteSection.tsx +53 -2
- package/src/components/SessionImportSection.tsx +30 -15
- package/src/components/SessionSidebar.tsx +72 -62
- package/src/components/SettingsPanel.tsx +49 -151
- package/src/components/TrajectoryAnalyzer.module.css +26 -11
- package/src/components/TrajectoryView.tsx +11 -3
- package/src/components/chat/markdown-actions.tsx +23 -0
- package/src/components/composer/ComposerFiles.tsx +224 -0
- package/src/components/composer/ComposerImages.tsx +59 -127
- package/src/hooks/usePiWeb.ts +47 -2
- package/src/i18n.tsx +62 -80
- package/src/lib/agent-manager.ts +365 -33
- package/src/lib/chat/file-path.ts +54 -0
- package/src/lib/chat/skill-expansion.ts +51 -0
- package/src/lib/extension-ui.ts +25 -1
- package/src/lib/font.ts +37 -39
- package/src/lib/git-service.ts +4 -2
- package/src/lib/growth-turns.ts +3 -1
- package/src/lib/model-draft.ts +69 -2
- package/src/lib/models-service.ts +53 -3
- package/src/lib/pi.ts +2 -2
- package/src/lib/remote/assets.json +1 -1
- package/src/lib/remote/supervisor.ts +48 -5
- package/src/lib/security-service.ts +2 -1
- package/src/lib/session-reader.ts +25 -13
- package/src/lib/session-retention.ts +11 -8
- package/src/lib/skills-service.ts +2 -1
- package/src/lib/slash-command-token.ts +14 -0
- package/src/lib/trajectory.ts +111 -15
- package/src/lib/types.ts +28 -3
- package/src/lib/update-service.ts +29 -9
- package/src/lib/workspace-store.ts +36 -1
- package/.next/server/app/api/agent/[id]/side-chat/route.js +0 -5
- package/.next/server/app/api/agent/[id]/side-chat/route.js.nft.json +0 -1
- package/.next/server/app/api/agent/[id]/side-chat/route_client-reference-manifest.js +0 -1
- package/.next/server/chunks/3421.js +0 -1
- package/.next/static/chunks/2716.44fdf1b21454b961.js +0 -1
- package/.next/static/chunks/4673.e261707dce391be7.js +0 -1
- package/.next/static/chunks/4686-0cd87513f9ea3538.js +0 -1
- package/.next/static/chunks/4778.eddd3a5813f85824.js +0 -1
- package/.next/static/chunks/7411.5f79671208209b13.js +0 -1
- package/.next/static/chunks/8552.25c39ef4c995eba0.js +0 -1
- package/.next/static/chunks/app/_global-error/page-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/events/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/side-chat/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/tree/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/agent/new/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/config/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/files/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/fs/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/git/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/github/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/growth/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/health/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/models/defaults/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/models/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/pi-settings/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/plugins/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/prompts/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/remote/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/security/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/export/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/sessions/import/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/sessions/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/skills/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/update/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/version/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/web-auth/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/api/workspaces/route-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/app/page-dc3cb41d91c7432e.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-cbaaee0d7aacb85a.js +0 -1
- package/.next/static/chunks/webpack-2ac3d76b81895f5b.js +0 -1
- package/.next/static/css/08815507594e8b8d.css +0 -1
- package/.next/static/css/9fc559c2c4ad1d0f.css +0 -1
- package/.next/static/css/c6e2227c36ec2fd6.css +0 -1
- package/.next/static/css/f15a853af8b5127f.css +0 -1
- package/.next/static/lvKCJmjFj8LuqSojRVLRF/_buildManifest.js +0 -1
- package/src/app/api/agent/[id]/side-chat/route.ts +0 -77
- package/src/components/side-chat/SideChatPanel.module.css +0 -131
- package/src/components/side-chat/SideChatPanel.tsx +0 -189
- package/src/components/side-chat/icons.tsx +0 -8
- package/src/components/side-chat/request-history.ts +0 -29
- package/src/components/side-chat/store.ts +0 -248
- package/src/lib/chat/stream-settings.ts +0 -192
- package/src/lib/side-chat/context.ts +0 -123
- package/src/lib/side-chat/service.ts +0 -191
- package/src/lib/side-chat/types.ts +0 -61
- /package/.next/static/{lvKCJmjFj8LuqSojRVLRF → QJCtqgDKzGS2BdKABd9ch}/_ssgManifest.js +0 -0
|
@@ -39,16 +39,6 @@ import { useI18n } from "@/i18n";
|
|
|
39
39
|
import { fmtTokens } from "@/lib/format";
|
|
40
40
|
import { applyPebrelTheme, loadPebrelTheme, loadThemeMode, type PebrelTheme, type ThemeMode } from "@/lib/theme";
|
|
41
41
|
import { applyFontChoice, CUSTOM_PREFIX, FONT_PRESETS, loadFontChoice } from "@/lib/font";
|
|
42
|
-
import {
|
|
43
|
-
DEFAULT_STREAM_SETTINGS,
|
|
44
|
-
getStreamSettings,
|
|
45
|
-
setStreamSettings,
|
|
46
|
-
STREAM_SPEED_MAX,
|
|
47
|
-
STREAM_SPEED_MIN,
|
|
48
|
-
STREAM_STYLES,
|
|
49
|
-
type StreamSettings,
|
|
50
|
-
type StreamStyle,
|
|
51
|
-
} from "@/lib/chat/stream-settings";
|
|
52
42
|
import {
|
|
53
43
|
customModelGaps,
|
|
54
44
|
fillModelFields,
|
|
@@ -134,32 +124,26 @@ export function SettingsPanel({
|
|
|
134
124
|
boxShadow: "var(--dsw-elevation-prominent)",
|
|
135
125
|
}}
|
|
136
126
|
>
|
|
137
|
-
{/* 左导航(
|
|
138
|
-
<div className="settings-nav flex w-52 flex-none flex-col gap-
|
|
127
|
+
{/* 左导航(Iconsax .isx-menu-item:h42 r12,悬停/激活高对比反转 + 文字右移 + 右侧短竖条) */}
|
|
128
|
+
<div className="settings-nav flex w-52 flex-none flex-col gap-1 py-4 pl-4 pr-3">
|
|
139
129
|
<div className="settings-title px-2 pb-3" style={{ fontSize: 16, fontWeight: 500 }}>
|
|
140
130
|
{t.settings}
|
|
141
131
|
</div>
|
|
142
132
|
{navItems.map((n) => (
|
|
143
133
|
<button
|
|
144
134
|
key={n.id}
|
|
145
|
-
|
|
135
|
+
data-active={section === n.id ? "true" : undefined}
|
|
136
|
+
className="isx-menu-item flex h-[42px] items-center gap-2.5 rounded-xl px-3 text-left"
|
|
146
137
|
style={{
|
|
147
|
-
paddingLeft:
|
|
148
|
-
paddingRight:
|
|
138
|
+
paddingLeft: 10,
|
|
139
|
+
paddingRight: 14,
|
|
149
140
|
fontSize: 14,
|
|
150
|
-
|
|
151
|
-
color: section === n.id ? "var(--dsw-label-primary)" : "var(--dsw-label-secondary)",
|
|
152
|
-
}}
|
|
153
|
-
onMouseEnter={(e) => {
|
|
154
|
-
if (section !== n.id) e.currentTarget.style.background = "var(--dsw-hover)";
|
|
155
|
-
}}
|
|
156
|
-
onMouseLeave={(e) => {
|
|
157
|
-
if (section !== n.id) e.currentTarget.style.background = "transparent";
|
|
141
|
+
color: section === n.id ? "var(--dsw-bg-base)" : "var(--dsw-label-secondary)",
|
|
158
142
|
}}
|
|
159
143
|
onClick={() => setSection(n.id)}
|
|
160
144
|
>
|
|
161
|
-
|
|
162
|
-
{n.label}
|
|
145
|
+
<span className="isx-menu-icon" style={{ display: "inline-flex" }}>{n.icon}</span>
|
|
146
|
+
<span className="isx-menu-shift">{n.label}</span>
|
|
163
147
|
</button>
|
|
164
148
|
))}
|
|
165
149
|
</div>
|
|
@@ -203,15 +187,14 @@ function GeneralSection({
|
|
|
203
187
|
const [themeMode, setThemeMode] = useState<ThemeMode>("system");
|
|
204
188
|
const [fontSize, setFontSize] = useState(14);
|
|
205
189
|
const [chatFontSize, setChatFontSize] = useState(14);
|
|
206
|
-
const [stream, setStream] = useState<StreamSettings>(DEFAULT_STREAM_SETTINGS);
|
|
207
190
|
const [enterBehavior, setEnterBehavior] = useState<EnterBehavior>("steer");
|
|
208
|
-
const [piSettings, setPiSettings] = useState<{ compaction: { enabled: boolean; reserveTokens: number
|
|
191
|
+
const [piSettings, setPiSettings] = useState<{ compaction: { enabled: boolean; reserveTokens: number }; retry: { enabled: boolean; maxRetries: number } } | null>(null);
|
|
209
192
|
const [versions, setVersions] = useState<{ piWeb: string; piEngine: string } | null>(null);
|
|
210
193
|
const [webAuth, setWebAuth] = useState<{ enabled: boolean; authenticated: boolean } | null>(null);
|
|
211
194
|
const [settingsLoading, setSettingsLoading] = useState(true);
|
|
212
195
|
const [settingsSaving, setSettingsSaving] = useState(false);
|
|
213
196
|
const [settingsError, setSettingsError] = useState<"load" | "save" | null>(null);
|
|
214
|
-
const [numberDrafts, setNumberDrafts] = useState({ reserveTokens: "",
|
|
197
|
+
const [numberDrafts, setNumberDrafts] = useState({ reserveTokens: "", maxRetries: "" });
|
|
215
198
|
|
|
216
199
|
const loadRemoteSettings = async () => {
|
|
217
200
|
setSettingsLoading(true);
|
|
@@ -232,9 +215,7 @@ function GeneralSection({
|
|
|
232
215
|
setPiSettings(ps.value);
|
|
233
216
|
setNumberDrafts({
|
|
234
217
|
reserveTokens: String(ps.value.compaction.reserveTokens),
|
|
235
|
-
keepRecentTokens: String(ps.value.compaction.keepRecentTokens),
|
|
236
218
|
maxRetries: String(ps.value.retry.maxRetries),
|
|
237
|
-
baseDelayMs: String(ps.value.retry.baseDelayMs),
|
|
238
219
|
});
|
|
239
220
|
} else setPiSettings(null);
|
|
240
221
|
if (health.status === "fulfilled" && health.value?.piWeb) setVersions({ piWeb: health.value.piWeb, piEngine: health.value.piEngine });
|
|
@@ -252,8 +233,6 @@ function GeneralSection({
|
|
|
252
233
|
if (!Number.isNaN(fs)) setFontSize(fs);
|
|
253
234
|
const chatFs = parseInt(localStorage.getItem("piweb.chatFontSize") ?? "14", 10);
|
|
254
235
|
if (!Number.isNaN(chatFs)) setChatFontSize(chatFs);
|
|
255
|
-
// 流式输出偏好与主题/字体同源(localStorage),同样等挂载后再读,避免水合不一致
|
|
256
|
-
setStream(getStreamSettings());
|
|
257
236
|
setEnterBehavior(getEnterBehavior());
|
|
258
237
|
void loadRemoteSettings();
|
|
259
238
|
}, []);
|
|
@@ -286,9 +265,6 @@ function GeneralSection({
|
|
|
286
265
|
document.documentElement.style.setProperty("--piweb-chat-font-size", `${v}px`);
|
|
287
266
|
};
|
|
288
267
|
|
|
289
|
-
/** 流式输出:样式 / 速度 / 光标。改完即持久化,正在流出的回答下一帧就换(订阅在 MarkdownBlock 里) */
|
|
290
|
-
const pickStream = (patch: Partial<StreamSettings>) => setStream(setStreamSettings(patch));
|
|
291
|
-
|
|
292
268
|
const pickEnter = (v: EnterBehavior) => {
|
|
293
269
|
setEnterBehavior(v);
|
|
294
270
|
saveEnterBehavior(v);
|
|
@@ -316,7 +292,7 @@ function GeneralSection({
|
|
|
316
292
|
}
|
|
317
293
|
};
|
|
318
294
|
|
|
319
|
-
const commitNumber = async (section: "compaction" | "retry", field: "reserveTokens" | "
|
|
295
|
+
const commitNumber = async (section: "compaction" | "retry", field: "reserveTokens" | "maxRetries") => {
|
|
320
296
|
if (!piSettings) return;
|
|
321
297
|
const raw = numberDrafts[field].trim();
|
|
322
298
|
const value = Number(raw);
|
|
@@ -327,7 +303,7 @@ function GeneralSection({
|
|
|
327
303
|
if (value === (piSettings[section] as unknown as Record<string, number>)[field]) return;
|
|
328
304
|
await patchPiSettings({ [section]: { [field]: value } });
|
|
329
305
|
};
|
|
330
|
-
const numberInput = (section: "compaction" | "retry", field: "reserveTokens" | "
|
|
306
|
+
const numberInput = (section: "compaction" | "retry", field: "reserveTokens" | "maxRetries", title: string) => (
|
|
331
307
|
<input
|
|
332
308
|
type="number"
|
|
333
309
|
min={0}
|
|
@@ -343,7 +319,7 @@ function GeneralSection({
|
|
|
343
319
|
);
|
|
344
320
|
|
|
345
321
|
const themes: { id: PebrelTheme; label: string; light: string; dark: string; accent: string }[] = [
|
|
346
|
-
{ id: "dsh", label: t.themeDsh, light: "#
|
|
322
|
+
{ id: "dsh", label: t.themeDsh, light: "#FFFFFF", dark: "#040405", accent: "#02DEFC" },
|
|
347
323
|
{ id: "silver-steel", label: t.themeSilverSteel, light: "#F3F4F6", dark: "#1A1C24", accent: "#94A3B8" },
|
|
348
324
|
{ id: "limestone-coal", label: t.themeLimestoneCoal, light: "#F0EFEB", dark: "#171717", accent: "#CEB27E" },
|
|
349
325
|
{ id: "linen-moss", label: t.themeLinenMoss, light: "#F2F2EC", dark: "#1E211E", accent: "#A3B3A3" },
|
|
@@ -351,20 +327,6 @@ function GeneralSection({
|
|
|
351
327
|
{ id: "pebrel", label: t.themePebrel, light: "#F3F4F6", dark: "#0F111A", accent: "#52A8FF" },
|
|
352
328
|
];
|
|
353
329
|
|
|
354
|
-
const streamStyleText: Record<StreamStyle, { label: string; desc: string }> = {
|
|
355
|
-
smooth: { label: t.streamStyleSmooth, desc: t.streamStyleSmoothDesc },
|
|
356
|
-
typewriter: { label: t.streamStyleTypewriter, desc: t.streamStyleTypewriterDesc },
|
|
357
|
-
fade: { label: t.streamStyleFade, desc: t.streamStyleFadeDesc },
|
|
358
|
-
instant: { label: t.streamStyleInstant, desc: t.streamStyleInstantDesc },
|
|
359
|
-
};
|
|
360
|
-
const streamSpeedText: Record<number, string> = {
|
|
361
|
-
1: t.streamSpeed1,
|
|
362
|
-
2: t.streamSpeed2,
|
|
363
|
-
3: t.streamSpeed3,
|
|
364
|
-
4: t.streamSpeed4,
|
|
365
|
-
5: t.streamSpeed5,
|
|
366
|
-
};
|
|
367
|
-
|
|
368
330
|
return (
|
|
369
331
|
<div className="flex flex-col gap-6">
|
|
370
332
|
{(settingsLoading || settingsError) && (
|
|
@@ -388,13 +350,12 @@ function GeneralSection({
|
|
|
388
350
|
{themes.map((th) => (
|
|
389
351
|
<button
|
|
390
352
|
key={th.id}
|
|
391
|
-
className="flex flex-col items-center justify-center gap-1
|
|
353
|
+
className="isx-card flex flex-col items-center justify-center gap-1"
|
|
392
354
|
style={{
|
|
393
355
|
flex: "1 1 150px",
|
|
394
356
|
padding: "20px 32px",
|
|
395
357
|
borderRadius: 20,
|
|
396
|
-
|
|
397
|
-
background: theme === th.id ? "var(--dsw-module-platform)" : "transparent",
|
|
358
|
+
background: theme === th.id ? "var(--dsw-module-platform)" : "var(--dsw-bg-elevated)",
|
|
398
359
|
color: "var(--dsw-label-primary)",
|
|
399
360
|
fontSize: 14,
|
|
400
361
|
lineHeight: "22px",
|
|
@@ -402,7 +363,7 @@ function GeneralSection({
|
|
|
402
363
|
aria-pressed={theme === th.id}
|
|
403
364
|
onClick={() => pickTheme(th.id)}
|
|
404
365
|
>
|
|
405
|
-
<span className="flex items-center overflow-hidden rounded-md" style={{ border: "
|
|
366
|
+
<span className="flex items-center overflow-hidden rounded-md" style={{ border: "1px solid var(--dsw-border-l3)", width: 42, height: 20 }}>
|
|
406
367
|
<span style={{ background: th.light, flex: 1, height: "100%" }} />
|
|
407
368
|
<span style={{ background: th.dark, flex: 1, height: "100%" }} />
|
|
408
369
|
</span>
|
|
@@ -423,13 +384,12 @@ function GeneralSection({
|
|
|
423
384
|
] as { id: ThemeMode; label: string }[]).map((mode) => (
|
|
424
385
|
<button
|
|
425
386
|
key={mode.id}
|
|
426
|
-
className="flex flex-col items-center justify-center gap-1
|
|
387
|
+
className="isx-card flex flex-col items-center justify-center gap-1"
|
|
427
388
|
style={{
|
|
428
389
|
flex: "1 1 120px",
|
|
429
390
|
padding: "16px 24px",
|
|
430
391
|
borderRadius: 20,
|
|
431
|
-
|
|
432
|
-
background: themeMode === mode.id ? "var(--dsw-module-platform)" : "transparent",
|
|
392
|
+
background: themeMode === mode.id ? "var(--dsw-module-platform)" : "var(--dsw-bg-elevated)",
|
|
433
393
|
color: "var(--dsw-label-primary)",
|
|
434
394
|
fontSize: 14,
|
|
435
395
|
lineHeight: "22px",
|
|
@@ -449,83 +409,7 @@ function GeneralSection({
|
|
|
449
409
|
<FontSizeStepper value={chatFontSize} onChange={pickChatFont} max={20} />
|
|
450
410
|
</Row>
|
|
451
411
|
<Row title={t.fontUiFamily} desc={t.fontUiFamilyDesc}>
|
|
452
|
-
<FontFamilyPicker
|
|
453
|
-
</Row>
|
|
454
|
-
<Row title={t.fontMonoFamily} desc={t.fontMonoFamilyDesc}>
|
|
455
|
-
<FontFamilyPicker scope="mono" />
|
|
456
|
-
</Row>
|
|
457
|
-
<RowColumn title={t.streamStyleTitle} desc={t.streamStyleDesc}>
|
|
458
|
-
<div className="flex w-full flex-wrap gap-2">
|
|
459
|
-
{STREAM_STYLES.map((id) => {
|
|
460
|
-
const active = stream.style === id;
|
|
461
|
-
return (
|
|
462
|
-
<button
|
|
463
|
-
key={id}
|
|
464
|
-
type="button"
|
|
465
|
-
className="flex flex-col items-start gap-1 text-left transition-colors"
|
|
466
|
-
style={{
|
|
467
|
-
flex: "1 1 150px",
|
|
468
|
-
padding: "12px 16px",
|
|
469
|
-
borderRadius: 14,
|
|
470
|
-
border: `0.5px solid ${active ? "var(--dsw-border-strong)" : "var(--dsw-border-l4)"}`,
|
|
471
|
-
background: active ? "var(--dsw-module-platform)" : "transparent",
|
|
472
|
-
color: "var(--dsw-label-primary)",
|
|
473
|
-
lineHeight: "18px",
|
|
474
|
-
}}
|
|
475
|
-
aria-pressed={active}
|
|
476
|
-
onClick={() => pickStream({ style: id })}
|
|
477
|
-
>
|
|
478
|
-
<span className="flex items-center gap-1.5" style={{ fontSize: 14 }}>
|
|
479
|
-
{active ? <IconCheckOutline14 size={13} /> : null}
|
|
480
|
-
{streamStyleText[id].label}
|
|
481
|
-
</span>
|
|
482
|
-
<span style={{ fontSize: 11.5, color: "var(--dsw-label-caption)" }}>{streamStyleText[id].desc}</span>
|
|
483
|
-
</button>
|
|
484
|
-
);
|
|
485
|
-
})}
|
|
486
|
-
</div>
|
|
487
|
-
</RowColumn>
|
|
488
|
-
<RowColumn title={t.streamSpeedTitle} desc={t.streamSpeedDesc}>
|
|
489
|
-
<div className="flex w-full flex-wrap gap-2">
|
|
490
|
-
{Array.from({ length: STREAM_SPEED_MAX - STREAM_SPEED_MIN + 1 }, (_, i) => STREAM_SPEED_MIN + i).map((level) => {
|
|
491
|
-
const active = stream.speed === level;
|
|
492
|
-
return (
|
|
493
|
-
<button
|
|
494
|
-
key={level}
|
|
495
|
-
type="button"
|
|
496
|
-
className="transition-colors disabled:opacity-50"
|
|
497
|
-
// 即时样式不排队,速度对它没有意义:置灰,免得以为调了没反应
|
|
498
|
-
disabled={stream.style === "instant"}
|
|
499
|
-
style={{
|
|
500
|
-
flex: "1 1 84px",
|
|
501
|
-
padding: "10px 8px",
|
|
502
|
-
borderRadius: 12,
|
|
503
|
-
border: `0.5px solid ${active ? "var(--dsw-border-strong)" : "var(--dsw-border-l4)"}`,
|
|
504
|
-
background: active ? "var(--dsw-module-platform)" : "transparent",
|
|
505
|
-
color: active ? "var(--dsw-label-primary)" : "var(--dsw-label-secondary)",
|
|
506
|
-
fontSize: 13,
|
|
507
|
-
}}
|
|
508
|
-
aria-pressed={active}
|
|
509
|
-
onClick={() => pickStream({ speed: level })}
|
|
510
|
-
>
|
|
511
|
-
{streamSpeedText[level]}
|
|
512
|
-
</button>
|
|
513
|
-
);
|
|
514
|
-
})}
|
|
515
|
-
</div>
|
|
516
|
-
</RowColumn>
|
|
517
|
-
<Row title={t.streamCaretTitle} desc={t.streamCaretDesc}>
|
|
518
|
-
<button
|
|
519
|
-
type="button"
|
|
520
|
-
className="relative h-5 w-9 flex-none rounded-full transition-colors"
|
|
521
|
-
style={{ background: stream.caret ? "var(--dsw-accent)" : "var(--dsw-border-l3)" }}
|
|
522
|
-
role="switch"
|
|
523
|
-
aria-checked={stream.caret}
|
|
524
|
-
aria-label={t.streamCaretTitle}
|
|
525
|
-
onClick={() => pickStream({ caret: !stream.caret })}
|
|
526
|
-
>
|
|
527
|
-
<span className="absolute top-0.5 h-4 w-4 rounded-full bg-white transition-all" style={{ left: stream.caret ? 18 : 2 }} />
|
|
528
|
-
</button>
|
|
412
|
+
<FontFamilyPicker />
|
|
529
413
|
</Row>
|
|
530
414
|
<Row title={t.enterBehavior} desc={t.enterBehaviorDesc}>
|
|
531
415
|
<SelectOption
|
|
@@ -543,7 +427,6 @@ function GeneralSection({
|
|
|
543
427
|
<span className="absolute top-0.5 h-4 w-4 rounded-full bg-white transition-all" style={{ left: piSettings?.compaction.enabled ? 18 : 2 }} />
|
|
544
428
|
</button>
|
|
545
429
|
{numberInput("compaction", "reserveTokens", t.reserveTokens)}
|
|
546
|
-
{numberInput("compaction", "keepRecentTokens", t.keepRecentTokens)}
|
|
547
430
|
</div>
|
|
548
431
|
</Row>
|
|
549
432
|
<Row title={t.autoRetry} desc={t.autoRetryDesc}>
|
|
@@ -552,7 +435,6 @@ function GeneralSection({
|
|
|
552
435
|
<span className="absolute top-0.5 h-4 w-4 rounded-full bg-white transition-all" style={{ left: piSettings?.retry.enabled ? 18 : 2 }} />
|
|
553
436
|
</button>
|
|
554
437
|
{numberInput("retry", "maxRetries", t.maxRetries)}
|
|
555
|
-
{numberInput("retry", "baseDelayMs", t.baseDelayMs)}
|
|
556
438
|
</div>
|
|
557
439
|
</Row>
|
|
558
440
|
<Row title={t.versionPiweb} desc={t.versionPiwebDesc}>
|
|
@@ -662,7 +544,7 @@ function UpdateControl({ target }: { target: UpdateTarget }) {
|
|
|
662
544
|
}
|
|
663
545
|
|
|
664
546
|
/** 通用下选芯片:自定义深色圆角浮层,替代原生 select */
|
|
665
|
-
function SelectOption({
|
|
547
|
+
export function SelectOption({
|
|
666
548
|
value,
|
|
667
549
|
options,
|
|
668
550
|
onChange,
|
|
@@ -694,6 +576,18 @@ function SelectOption({
|
|
|
694
576
|
if (disabled) setOpen(false);
|
|
695
577
|
}, [disabled]);
|
|
696
578
|
const current = options.find((o) => o.value === value);
|
|
579
|
+
// 下方放不下(按每项约 37px 估高,封顶 280)且上方更宽裕时向上翻转,并把高度限制在可用空间内。
|
|
580
|
+
// 以前只把 top 钳到窗口底部上方 40px,靠近底部时只露出第一项,其余落到屏幕外
|
|
581
|
+
const placement = (() => {
|
|
582
|
+
if (!rect || typeof window === "undefined") return null;
|
|
583
|
+
const margin = 8;
|
|
584
|
+
const wanted = Math.min(280, options.length * 37 + 12);
|
|
585
|
+
const below = window.innerHeight - rect.top - margin;
|
|
586
|
+
const above = rect.bottom - margin;
|
|
587
|
+
return below < wanted && above > below
|
|
588
|
+
? { bottom: window.innerHeight - rect.bottom, maxHeight: Math.min(280, above) }
|
|
589
|
+
: { top: rect.top, maxHeight: Math.min(280, Math.max(below, 80)) };
|
|
590
|
+
})();
|
|
697
591
|
return (
|
|
698
592
|
<div className="relative">
|
|
699
593
|
<button ref={anchorRef} className="select-chip" data-open={open} disabled={disabled} onClick={() => setOpen((o) => !o)}>
|
|
@@ -702,12 +596,13 @@ function SelectOption({
|
|
|
702
596
|
<IconChevronDown14 size={14} />
|
|
703
597
|
</span>
|
|
704
598
|
</button>
|
|
705
|
-
{open && !disabled && rect && createPortal(
|
|
599
|
+
{open && !disabled && rect && placement && createPortal(
|
|
706
600
|
<div
|
|
707
601
|
ref={popRef}
|
|
708
602
|
className="popover fixed z-[130] p-1.5 shadow-xl"
|
|
709
|
-
|
|
710
|
-
|
|
603
|
+
data-placement={"bottom" in placement ? "top" : "bottom"}
|
|
604
|
+
// 左右都对齐 chip 左缘
|
|
605
|
+
style={{ left: rect.left, ...placement, minWidth: width ?? 140, width: "max-content", overflowY: "auto" }}
|
|
711
606
|
>
|
|
712
607
|
{options.map((o) => {
|
|
713
608
|
const selected = o.value === value;
|
|
@@ -813,8 +708,9 @@ function FontSizeStepper({ value, onChange, max }: { value: number; onChange: (v
|
|
|
813
708
|
);
|
|
814
709
|
}
|
|
815
710
|
|
|
816
|
-
/**
|
|
817
|
-
|
|
711
|
+
/** 界面字体族选择:预设下拉 + 「自定义」文本框。改动即生效并持久化。
|
|
712
|
+
* 代码字体已固定为系统等宽、不再可配(见 lib/font.ts)。 */
|
|
713
|
+
function FontFamilyPicker() {
|
|
818
714
|
const { t, lang } = useI18n();
|
|
819
715
|
const [stored, setStored] = useState<string | null>(null);
|
|
820
716
|
const [custom, setCustom] = useState("");
|
|
@@ -823,18 +719,18 @@ function FontFamilyPicker({ scope }: { scope: "ui" | "mono" }) {
|
|
|
823
719
|
const [customMode, setCustomMode] = useState(false);
|
|
824
720
|
|
|
825
721
|
useEffect(() => {
|
|
826
|
-
const saved = loadFontChoice(
|
|
722
|
+
const saved = loadFontChoice();
|
|
827
723
|
const savedCustom = saved?.startsWith(CUSTOM_PREFIX) ? saved.slice(CUSTOM_PREFIX.length) : null;
|
|
828
724
|
setStored(saved);
|
|
829
725
|
setCustomMode(savedCustom !== null);
|
|
830
726
|
setCustom(savedCustom ?? "");
|
|
831
|
-
}, [
|
|
727
|
+
}, []);
|
|
832
728
|
|
|
833
729
|
const applyCustom = (v: string) => {
|
|
834
730
|
setCustom(v);
|
|
835
731
|
const next = v.trim() ? CUSTOM_PREFIX + v.trim() : null;
|
|
836
732
|
setStored(next);
|
|
837
|
-
applyFontChoice(
|
|
733
|
+
applyFontChoice(next);
|
|
838
734
|
};
|
|
839
735
|
|
|
840
736
|
const pick = (v: string) => {
|
|
@@ -846,10 +742,10 @@ function FontFamilyPicker({ scope }: { scope: "ui" | "mono" }) {
|
|
|
846
742
|
}
|
|
847
743
|
setCustomMode(false);
|
|
848
744
|
setStored(v);
|
|
849
|
-
applyFontChoice(
|
|
745
|
+
applyFontChoice(v);
|
|
850
746
|
};
|
|
851
747
|
|
|
852
|
-
const selectValue = customMode ? CUSTOM_PREFIX : stored ?? FONT_PRESETS[
|
|
748
|
+
const selectValue = customMode ? CUSTOM_PREFIX : stored ?? FONT_PRESETS[0].id;
|
|
853
749
|
|
|
854
750
|
return (
|
|
855
751
|
<div className="flex flex-col items-end gap-2">
|
|
@@ -857,7 +753,7 @@ function FontFamilyPicker({ scope }: { scope: "ui" | "mono" }) {
|
|
|
857
753
|
value={selectValue}
|
|
858
754
|
width={220}
|
|
859
755
|
options={[
|
|
860
|
-
...FONT_PRESETS
|
|
756
|
+
...FONT_PRESETS.map((p) => ({
|
|
861
757
|
value: p.id,
|
|
862
758
|
label: lang === "zh" ? p.label.zh : p.label.en,
|
|
863
759
|
})),
|
|
@@ -2628,7 +2524,9 @@ export function PluginsSection({ cwd }: { cwd: string }) {
|
|
|
2628
2524
|
role="menuitem"
|
|
2629
2525
|
className="flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs transition-colors hover:bg-[var(--dsw-hover)] cursor-pointer disabled:opacity-50"
|
|
2630
2526
|
style={{ color: "var(--dsw-label-secondary)" }}
|
|
2631
|
-
|
|
2527
|
+
// 停用的包挪到了 PiWeb 私有的 disabledPackages,SDK 的 update 只认 packages,点了只会报「找不到包」
|
|
2528
|
+
disabled={busy || isDisabled}
|
|
2529
|
+
title={isDisabled ? t.updateNeedsEnable : undefined}
|
|
2632
2530
|
onClick={() => {
|
|
2633
2531
|
setMenuKey(null);
|
|
2634
2532
|
void act(
|
|
@@ -59,23 +59,30 @@
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
.toolbarButton:hover,
|
|
62
|
-
.toolbarButton[aria-pressed="true"] {
|
|
62
|
+
.toolbarButton[aria-pressed="true"] {
|
|
63
|
+
color: var(--dsw-label-primary);
|
|
64
|
+
background: var(--dsw-hover);
|
|
65
|
+
transform: translateY(-0.5px);
|
|
66
|
+
}
|
|
63
67
|
|
|
64
68
|
.searchBox {
|
|
65
69
|
display: flex;
|
|
66
70
|
width: min(230px, 30vw);
|
|
67
|
-
height:
|
|
71
|
+
height: 26px;
|
|
68
72
|
align-items: center;
|
|
69
73
|
gap: 5px;
|
|
70
74
|
margin-left: auto;
|
|
71
|
-
padding: 0
|
|
72
|
-
border:
|
|
73
|
-
border-radius:
|
|
74
|
-
color: var(--dsw-label-
|
|
75
|
+
padding: 0 8px;
|
|
76
|
+
border: 1.5px solid var(--dsw-border-l2);
|
|
77
|
+
border-radius: 12px;
|
|
78
|
+
color: var(--dsw-label-secondary);
|
|
75
79
|
background: var(--dsw-layer-2);
|
|
80
|
+
transition: border-color 0.22s var(--isx-ease);
|
|
76
81
|
}
|
|
77
82
|
|
|
78
|
-
.searchBox:focus-within {
|
|
83
|
+
.searchBox:focus-within {
|
|
84
|
+
border-color: var(--dsw-label-primary);
|
|
85
|
+
}
|
|
79
86
|
.searchBox input { width: 100%; min-width: 0; font-size: 12px; }
|
|
80
87
|
|
|
81
88
|
.timeline {
|
|
@@ -145,10 +152,17 @@
|
|
|
145
152
|
border-bottom: 0.5px solid var(--dsw-border-l1);
|
|
146
153
|
background: var(--dsw-bg-base);
|
|
147
154
|
text-align: left;
|
|
155
|
+
transition: background 0.2s var(--isx-ease), transform 0.2s var(--isx-ease);
|
|
148
156
|
}
|
|
149
157
|
|
|
150
|
-
.row:hover {
|
|
151
|
-
|
|
158
|
+
.row:hover {
|
|
159
|
+
background: var(--dsw-hover);
|
|
160
|
+
transform: translateX(2px);
|
|
161
|
+
}
|
|
162
|
+
.row[data-selected="true"] {
|
|
163
|
+
background: var(--dsw-hover);
|
|
164
|
+
box-shadow: inset 3px 0 0 var(--dsw-label-primary);
|
|
165
|
+
}
|
|
152
166
|
.row[data-environment="true"] { background: var(--dsw-bg-elevated); }
|
|
153
167
|
.row[data-environment="true"]:hover,
|
|
154
168
|
.row[data-environment="true"][data-selected="true"] { background: var(--dsw-hover); }
|
|
@@ -161,9 +175,10 @@
|
|
|
161
175
|
max-width: 100%;
|
|
162
176
|
height: 22px;
|
|
163
177
|
align-items: center;
|
|
164
|
-
padding: 0
|
|
178
|
+
padding: 0 8px;
|
|
165
179
|
overflow: hidden;
|
|
166
|
-
border-radius:
|
|
180
|
+
border-radius: 999px;
|
|
181
|
+
border: 1px solid var(--dsw-border-l1);
|
|
167
182
|
color: var(--dsw-label-secondary);
|
|
168
183
|
background: var(--dsw-module-platform);
|
|
169
184
|
font-family: var(--font-mono);
|
|
@@ -236,12 +236,20 @@ export function TrajectoryView({ entries, selected, onSelect }: {
|
|
|
236
236
|
);
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
-
|
|
239
|
+
/**
|
|
240
|
+
* context 条目的全文回退:轨迹里的 detail 只有头部(快照不再与 contextResources 双份带全文),
|
|
241
|
+
* inspector 展开时按路径回快照资源表里取。
|
|
242
|
+
*/
|
|
243
|
+
type ContextLookup = (path: string) => string | undefined;
|
|
244
|
+
|
|
245
|
+
export function TrajInspector({ entry, onClose, contextLookup }: { entry: TrajEntry; onClose: () => void; contextLookup?: ContextLookup }) {
|
|
240
246
|
const { t } = useI18n();
|
|
241
247
|
const [tab, setTab] = useState<DetailTab>("summary");
|
|
242
248
|
const kind = entry.toolName || KIND_NAME[entry.kind];
|
|
243
249
|
const position = entry.kind === "system" ? t.trajSystem : entry.turn ? `${t.trajTurn} ${entry.turn}` : t.trajSession;
|
|
244
|
-
const
|
|
250
|
+
const fullText = entry.kind === "context" && entry.title ? contextLookup?.(entry.title) : undefined;
|
|
251
|
+
const body = fullText ?? entry.detail;
|
|
252
|
+
const preview = body || entry.preview || entry.thinking || "";
|
|
245
253
|
const tabs: Array<{ id: DetailTab; label: string }> = [
|
|
246
254
|
{ id: "summary", label: t.trajSummary },
|
|
247
255
|
{ id: "preview", label: t.trajPreview },
|
|
@@ -274,7 +282,7 @@ export function TrajInspector({ entry, onClose }: { entry: TrajEntry; onClose: (
|
|
|
274
282
|
</dl>
|
|
275
283
|
{preview && <InspectorPayload title={t.trajPreview} value={preview} />}
|
|
276
284
|
</>}
|
|
277
|
-
{tab === "preview" && <InspectorPayload title={entry.thinking ? t.trajThink : t.trajPreview} value={[entry.thinking,
|
|
285
|
+
{tab === "preview" && <InspectorPayload title={entry.thinking ? t.trajThink : t.trajPreview} value={[entry.thinking, body || entry.preview].filter(Boolean).join("\n\n")} empty={t.trajNoContent} />}
|
|
278
286
|
{tab === "raw" && <InspectorPayload title="JSON" value={JSON.stringify(entry, null, 2)} mono />}
|
|
279
287
|
{tab === "source" && <InspectorPayload title={t.trajSource} value={`${sourceOf(entry)}\n\nseq: ${entry.seq}\ntimestamp: ${new Date(entry.ts).toISOString()}`} mono />}
|
|
280
288
|
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 正文(Markdown)里可交互元素的接线。
|
|
5
|
+
*
|
|
6
|
+
* 用 context 而不是逐层传 props:MarkdownBlock 在对话正文、轨迹详情、提示词面板等处复用,
|
|
7
|
+
* 中间隔着好几层,逐层透传会把签名污染到与之无关的组件上。
|
|
8
|
+
* 没有 Provider 时(例如文件查看器里渲染 Markdown)这些交互自然不生效,正文照常显示。
|
|
9
|
+
*/
|
|
10
|
+
import { createContext, useContext } from "react";
|
|
11
|
+
|
|
12
|
+
export interface MarkdownActions {
|
|
13
|
+
/** 用文件查看器打开项目内路径;没有工作区时不给(此时路径只作展示) */
|
|
14
|
+
openFile?: (path: string) => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const MarkdownActionsContext = createContext<MarkdownActions>({});
|
|
18
|
+
|
|
19
|
+
export const MarkdownActionsProvider = MarkdownActionsContext.Provider;
|
|
20
|
+
|
|
21
|
+
export function useMarkdownActions(): MarkdownActions {
|
|
22
|
+
return useContext(MarkdownActionsContext);
|
|
23
|
+
}
|