@jetcrab/pi-desk 1.1.16 → 1.1.20-dev
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/docs/plugins.md +3 -1
- package/next.config.ts +1 -0
- package/package.json +4 -3
- package/src/client/l2_biz/workbench/file-workspace/l2-file-workspace-runtime.ts +1 -1
- package/src/client/l2_biz/workbench/hooks/l2-workbench-chat-reload.ts +42 -0
- package/src/client/l2_biz/workbench/l2-work-session-sidebar.tsx +19 -1
- package/src/client/l2_biz/workbench/l2-workbench-chat.ts +45 -0
- package/src/client/l2_biz/workbench/l2-workbench.tsx +4 -0
- package/src/client/l3_modules/conversation/l3-conversation-markdown.module.css +1 -0
- package/src/client/l3_modules/conversation/l3-conversation-markdown.tsx +10 -1
- package/src/client/l3_modules/project-files/l3-markdown-preview.tsx +10 -1
- package/src/client/l3_modules/project-files/l3-project-document-view.tsx +2 -0
- package/src/client/l3_modules/project-files/l3-project-file-browser.tsx +171 -229
- package/src/client/l3_modules/project-files/l3-project-file-runtime.ts +133 -70
- package/src/client/l3_modules/project-files/l3-project-reader.ts +4 -3
- package/src/client/l3_modules/project-files/views/l3-project-search-controls.tsx +201 -0
- package/src/client/l3_modules/project-files/views/l3-project-search-results.tsx +333 -0
- package/src/client/l4_foundation/ui/code/l4-code-preview.tsx +47 -3
- package/src/client/l4_foundation/ui/markdown/l4-markdown-remark.ts +89 -0
- package/src/client/l4_foundation/ui/markdown/l4-markdown.module.css +58 -0
- package/src/client/l4_foundation/ui/markdown/l4-markdown.tsx +108 -0
- package/src/common/l2_biz/work-session/l2-work-session-file-contract.ts +4 -3
- package/src/common/l2_biz/workbench/l2-workbench-locale-messages.ts +6 -0
- package/src/common/l3_modules/project-files/l3-project-files-contract.ts +2 -3
- package/src/common/l3_modules/project-files/l3-project-files-locale-messages.ts +56 -10
- package/src/common/l4_foundation/file/l4-project-file-contract.ts +51 -1
- package/src/common/l4_foundation/locale/l4-host-error-messages.ts +11 -0
- package/src/common/l4_foundation/locale/l4-locale-messages.ts +16 -0
- package/src/instrumentation.ts +0 -2
- package/src/server/l1_entry/api/l1-project-read-routes.ts +6 -4
- package/src/server/l1_entry/api/l1-project-route.ts +9 -8
- package/src/server/l1_entry/api/l1-work-session-file-error.ts +23 -0
- package/src/server/l2_biz/plugin-management/l2-plugin-management.ts +0 -3
- package/src/server/l2_biz/work-session/l2-work-session-chat-runtime.ts +30 -58
- package/src/server/l2_biz/work-session/l2-work-session-manage.ts +0 -4
- package/src/server/l4_foundation/file/l4-project-file-index.ts +276 -0
- package/src/server/l4_foundation/file/l4-project-search.ts +399 -0
- package/src/server/l4_foundation/file/l4-ripgrep-search.ts +192 -0
- package/src/server/l4_foundation/file/l4-work-session-project-file.ts +8 -332
- package/src/server/l4_foundation/pi/l4-pi-package-maintenance.ts +0 -6
- package/src/server/l4_foundation/pi/l4-pi-plugin-capability-probe.ts +1 -3
- package/src/server/l4_foundation/pi/l4-pi-plugin-probe.ts +1 -3
- package/src/server/l4_foundation/pi/l4-pi-runner-process.ts +3 -15
- package/src/server/l4_foundation/process/l4-process-tree.js +31 -5
- package/temp/build/pi-desk/release/.next/BUILD_ID +1 -1
- package/temp/build/pi-desk/release/.next/build-manifest.json +3 -3
- package/temp/build/pi-desk/release/.next/prerender-manifest.json +3 -3
- package/temp/build/pi-desk/release/.next/react-loadable-manifest.json +1 -1
- package/temp/build/pi-desk/release/.next/required-server-files.js +4 -3
- package/temp/build/pi-desk/release/.next/required-server-files.json +4 -3
- package/temp/build/pi-desk/release/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.html +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.rsc +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_not-found/page.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/health/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-files/get/route.js +2 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-files/list/route.js +2 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-files/reveal/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-files/search/route.js +2 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-git/get/route.js +2 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-git-branches/list/route.js +2 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-git-changes/list/route.js +2 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-git-diff/get/route.js +2 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-git-heads/get/route.js +2 -1
- package/temp/build/pi-desk/release/.next/server/app/api/project-git-log/list/route.js +2 -1
- package/temp/build/pi-desk/release/.next/server/app/login/page.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/page.js +77 -77
- package/temp/build/pi-desk/release/.next/server/app/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/{33658.js → 10881.js} +8 -8
- package/temp/build/pi-desk/release/.next/server/chunks/23054.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/25406.js +3 -3
- package/temp/build/pi-desk/release/.next/server/chunks/35985.js +5 -5
- package/temp/build/pi-desk/release/.next/server/chunks/50520.js +2 -4
- package/temp/build/pi-desk/release/.next/server/chunks/6917.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/70780.js +1 -0
- package/temp/build/pi-desk/release/.next/server/chunks/74528.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/92386.js +1 -1
- package/temp/build/pi-desk/release/.next/server/instrumentation.js +1 -1
- package/temp/build/pi-desk/release/.next/server/middleware-build-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/pages/500.html +1 -1
- package/temp/build/pi-desk/release/.next/server/server-reference-manifest.json +1 -1
- package/temp/build/pi-desk/release/.next/static/chunks/27611-0890482fe76bd9d6.js +238 -0
- package/temp/build/pi-desk/release/.next/static/chunks/{31087-ba426d09d6f68bfd.js → 31087-d8e5765d541d5c26.js} +1 -1
- package/temp/build/pi-desk/release/.next/static/chunks/{49516-cc4dcd84d64ab4fe.js → 51474-8dc714cb76b2e60a.js} +2 -2
- package/temp/build/pi-desk/release/.next/static/chunks/77592-5bef6acb8e7c4b96.js +13 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/layout-a50c456648537afb.js +3 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/{page-0069319a4fb97211.js → page-0789c43551b29dd2.js} +4 -4
- package/temp/build/pi-desk/release/.next/static/chunks/{webpack-40a782fc8a3535b9.js → webpack-d7248206b7fc7ba8.js} +1 -1
- package/temp/build/pi-desk/release/.next/static/css/250a6b93cc2222d1.css +1 -0
- package/temp/build/pi-desk/release/.next/static/css/6dbae2922f88ca31.css +1 -0
- package/temp/build/pi-desk/release/.next/static/css/a4cf28fd76c70165.css +1 -0
- package/temp/build/pi-desk/release/.next/trace-build +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/8584.js +0 -2
- package/temp/build/pi-desk/release/.next/static/chunks/39654-b5fedd762ea0312e.js +0 -238
- package/temp/build/pi-desk/release/.next/static/chunks/75130-d2ca74894aff8085.js +0 -13
- package/temp/build/pi-desk/release/.next/static/chunks/app/layout-c0e1c5cef8620cf8.js +0 -3
- package/temp/build/pi-desk/release/.next/static/css/6427d02b6edf406f.css +0 -1
- package/temp/build/pi-desk/release/.next/static/css/949d0d1a99d5de92.css +0 -1
- /package/temp/build/pi-desk/release/.next/static/{DqamF28k0ShQLbNVzXDIj → RLKcK-RQF5FvEeDmS9uih}/_buildManifest.js +0 -0
- /package/temp/build/pi-desk/release/.next/static/{DqamF28k0ShQLbNVzXDIj → RLKcK-RQF5FvEeDmS9uih}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
CheckIcon,
|
|
5
|
+
InfoIcon,
|
|
6
|
+
LightbulbIcon,
|
|
7
|
+
MessageSquareWarningIcon,
|
|
8
|
+
MinusIcon,
|
|
9
|
+
OctagonAlertIcon,
|
|
10
|
+
TriangleAlertIcon
|
|
11
|
+
} from 'lucide-react'
|
|
12
|
+
import type { ComponentProps } from 'react'
|
|
13
|
+
import { useTranslation } from 'react-i18next'
|
|
14
|
+
import { defaultRemarkPlugins, type Components, type StreamdownProps } from 'streamdown'
|
|
15
|
+
import { cn } from '@client/l4_foundation/lib/l4-utils'
|
|
16
|
+
import { remarkL4Markdown } from './l4-markdown-remark'
|
|
17
|
+
import styles from './l4-markdown.module.css'
|
|
18
|
+
|
|
19
|
+
export { L4_MARKDOWN_ALLOWED_TAGS } from './l4-markdown-remark'
|
|
20
|
+
|
|
21
|
+
export const L4_MARKDOWN_REMARK_PLUGINS: NonNullable<StreamdownProps['remarkPlugins']> = [
|
|
22
|
+
...Object.values(defaultRemarkPlugins),
|
|
23
|
+
remarkL4Markdown
|
|
24
|
+
]
|
|
25
|
+
export const L4_MARKDOWN_CLASS_NAME = styles.markdown
|
|
26
|
+
|
|
27
|
+
const alerts = {
|
|
28
|
+
note: { icon: InfoIcon, label: 'markdownNote' },
|
|
29
|
+
tip: { icon: LightbulbIcon, label: 'markdownTip' },
|
|
30
|
+
important: { icon: MessageSquareWarningIcon, label: 'markdownImportant' },
|
|
31
|
+
warning: { icon: TriangleAlertIcon, label: 'markdownWarning' },
|
|
32
|
+
caution: { icon: OctagonAlertIcon, label: 'markdownCaution' }
|
|
33
|
+
} as const
|
|
34
|
+
|
|
35
|
+
function MarkdownStatus({
|
|
36
|
+
'data-pi-markdown-progress': progress,
|
|
37
|
+
...props
|
|
38
|
+
}: ComponentProps<'input'> & {
|
|
39
|
+
node?: unknown
|
|
40
|
+
'data-pi-markdown-progress'?: string
|
|
41
|
+
}): React.JSX.Element {
|
|
42
|
+
const { t } = useTranslation('common')
|
|
43
|
+
delete props.node
|
|
44
|
+
if (props.type !== 'checkbox') return <input {...props} />
|
|
45
|
+
const state = progress ? 'progress' : props.checked ? 'completed' : 'pending'
|
|
46
|
+
const marker = progress ? '[-]' : props.checked ? '[x]' : '[ ]'
|
|
47
|
+
const label = t(
|
|
48
|
+
progress ? 'markdownProgress' : props.checked ? 'markdownCompleted' : 'markdownPending'
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<span className={styles.status} data-state={state} role="img" aria-label={label} title={label}>
|
|
53
|
+
{progress ? (
|
|
54
|
+
<MinusIcon aria-hidden="true" />
|
|
55
|
+
) : props.checked ? (
|
|
56
|
+
<CheckIcon aria-hidden="true" />
|
|
57
|
+
) : null}
|
|
58
|
+
<span className="sr-only" aria-hidden="true">
|
|
59
|
+
{marker}
|
|
60
|
+
</span>
|
|
61
|
+
</span>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function MarkdownBlockquote({
|
|
66
|
+
'data-pi-markdown-alert': kind,
|
|
67
|
+
className,
|
|
68
|
+
children,
|
|
69
|
+
...props
|
|
70
|
+
}: ComponentProps<'blockquote'> & {
|
|
71
|
+
node?: unknown
|
|
72
|
+
'data-pi-markdown-alert'?: string
|
|
73
|
+
}): React.JSX.Element {
|
|
74
|
+
const { t } = useTranslation('common')
|
|
75
|
+
delete props.node
|
|
76
|
+
const alert = Object.entries(alerts).find(([name]) => name === kind)?.[1]
|
|
77
|
+
|
|
78
|
+
if (!alert) {
|
|
79
|
+
return (
|
|
80
|
+
<blockquote
|
|
81
|
+
{...props}
|
|
82
|
+
data-streamdown="blockquote"
|
|
83
|
+
className={cn(
|
|
84
|
+
'my-4 border-muted-foreground/30 border-l-4 pl-4 text-muted-foreground italic',
|
|
85
|
+
className
|
|
86
|
+
)}
|
|
87
|
+
>
|
|
88
|
+
{children}
|
|
89
|
+
</blockquote>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const Icon = alert.icon
|
|
94
|
+
return (
|
|
95
|
+
<aside className={styles.alert} role="note" aria-label={t(alert.label)}>
|
|
96
|
+
<div className={styles.alertTitle}>
|
|
97
|
+
<Icon aria-hidden="true" />
|
|
98
|
+
{t(alert.label)}
|
|
99
|
+
</div>
|
|
100
|
+
<div className={styles.alertBody}>{children}</div>
|
|
101
|
+
</aside>
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export const L4_MARKDOWN_COMPONENTS: Components = {
|
|
106
|
+
input: MarkdownStatus,
|
|
107
|
+
blockquote: MarkdownBlockquote
|
|
108
|
+
}
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
L4ProjectFileEntrySchema,
|
|
11
11
|
L4ProjectFileListSchema,
|
|
12
12
|
L4ProjectFileSearchSchema,
|
|
13
|
+
L4ProjectSearchInputSchema,
|
|
13
14
|
L4ProjectFileContentSchema,
|
|
14
15
|
L4ProjectDirectoryPathSchema,
|
|
15
16
|
L4ProjectFileImageMimeTypeSchema,
|
|
@@ -47,9 +48,9 @@ export const L2WorkSessionFileListRequestSchema = L2WorkSessionFileProjectRefSch
|
|
|
47
48
|
|
|
48
49
|
export const L2WorkSessionFileListResponseSchema = L4ProjectFileListSchema
|
|
49
50
|
|
|
50
|
-
export const L2WorkSessionFileSearchRequestSchema = L2WorkSessionFileProjectRefSchema.extend(
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
export const L2WorkSessionFileSearchRequestSchema = L2WorkSessionFileProjectRefSchema.extend(
|
|
52
|
+
L4ProjectSearchInputSchema.shape
|
|
53
|
+
).strict()
|
|
53
54
|
|
|
54
55
|
export const L2WorkSessionFileSearchResponseSchema = L4ProjectFileSearchSchema
|
|
55
56
|
|
|
@@ -202,6 +202,9 @@ export const L2_WORKBENCH_LOCALE_MESSAGES = {
|
|
|
202
202
|
deleteSessionTitle: 'Delete work session',
|
|
203
203
|
copyProjectPath: 'Copy project path',
|
|
204
204
|
renameSessionTitle: 'Edit title',
|
|
205
|
+
reloadChatData: 'Reload chat data',
|
|
206
|
+
reloadChatDataFailed: 'Could not reload chat data',
|
|
207
|
+
reloadChatSourceChanged: 'The session has changed. Select it again.',
|
|
205
208
|
sessionTitleLabel: 'Session title',
|
|
206
209
|
renameSessionFailed: 'Could not save the session title',
|
|
207
210
|
sidebarSessions: 'Work sessions',
|
|
@@ -645,6 +648,9 @@ export const L2_WORKBENCH_LOCALE_MESSAGES = {
|
|
|
645
648
|
deleteSessionTitle: '删除工作会话',
|
|
646
649
|
copyProjectPath: '复制项目路径',
|
|
647
650
|
renameSessionTitle: '修改标题',
|
|
651
|
+
reloadChatData: '重新加载聊天数据',
|
|
652
|
+
reloadChatDataFailed: '重新加载聊天数据失败',
|
|
653
|
+
reloadChatSourceChanged: '会话已变化,请重新选择会话',
|
|
648
654
|
sessionTitleLabel: '会话标题',
|
|
649
655
|
renameSessionFailed: '保存会话标题失败',
|
|
650
656
|
sidebarSessions: '工作会话',
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
L4ProjectFileImagePreviewModeSchema,
|
|
7
7
|
L4ProjectFileListSchema,
|
|
8
8
|
L4ProjectFileSearchSchema,
|
|
9
|
+
L4ProjectSearchInputSchema,
|
|
9
10
|
L4ProjectFileContentSchema
|
|
10
11
|
} from '@common/l4_foundation/file/l4-project-file-contract'
|
|
11
12
|
import {
|
|
@@ -67,9 +68,7 @@ export const L3ProjectFileList = {
|
|
|
67
68
|
} as const
|
|
68
69
|
export const L3ProjectFileSearch = {
|
|
69
70
|
path: '/api/project-files/search',
|
|
70
|
-
request: L3ProjectReadContextSchema.extend(
|
|
71
|
-
query: z.string().trim().min(1).max(200)
|
|
72
|
-
}).strict(),
|
|
71
|
+
request: L3ProjectReadContextSchema.extend(L4ProjectSearchInputSchema.shape).strict(),
|
|
73
72
|
response: L4ProjectFileSearchSchema
|
|
74
73
|
} as const
|
|
75
74
|
export const L3ProjectFileGet = {
|
|
@@ -19,16 +19,39 @@ export const L3_PROJECT_FILES_LOCALE_MESSAGES = {
|
|
|
19
19
|
sessionDirectory: 'Original folder',
|
|
20
20
|
unavailable: 'Unavailable',
|
|
21
21
|
projectFiles: '{{name}} project files',
|
|
22
|
-
searchFiles: 'Search filenames',
|
|
23
|
-
|
|
22
|
+
searchFiles: 'Search filenames or paths',
|
|
23
|
+
searchAll: 'Search files or content',
|
|
24
|
+
searchContent: 'Search file content',
|
|
25
|
+
searchScope: 'Search scope',
|
|
26
|
+
searchScopeAll: 'All',
|
|
27
|
+
searchScopeFiles: 'Files',
|
|
28
|
+
searchScopeContent: 'Content',
|
|
29
|
+
searchCaseSensitive: 'Match case',
|
|
30
|
+
searchWholeWord: 'Match whole word',
|
|
31
|
+
searchRegex: 'Use regular expression',
|
|
32
|
+
searchResults: 'Search results',
|
|
33
|
+
searchStart: 'Search this project',
|
|
34
|
+
searchTryOptions: 'Try another query or adjust the search options.',
|
|
35
|
+
searchFailed: 'Could not search the project. Please try again.',
|
|
36
|
+
searchCounts: '{{files}} files · {{lines}} matching lines',
|
|
37
|
+
searchShownCounts: 'Shown: {{counts}}',
|
|
38
|
+
searchFileHeading: 'Filenames',
|
|
39
|
+
searchContentHeading: 'Content',
|
|
40
|
+
searchContentCounts: '{{lines}} matching lines · {{files}} files',
|
|
41
|
+
searchProjectRoot: 'Project root',
|
|
42
|
+
searchExpandFiles: 'Show {{count}} more files',
|
|
43
|
+
searchOpenLine: 'Open {{path}}, line {{line}}',
|
|
44
|
+
searchLineUnavailable: 'The file content has changed and the matching line no longer exists.',
|
|
45
|
+
searchTextLimit: 'Content search: previewable UTF-8 text up to 5 MiB.',
|
|
46
|
+
closeSearch: 'Exit search',
|
|
24
47
|
layout: 'File organization',
|
|
25
48
|
directory: 'Folders',
|
|
26
49
|
repository: 'Repositories',
|
|
27
50
|
changesOnly: 'Changes only',
|
|
28
|
-
searchProject: 'Search project
|
|
29
|
-
noMatches: 'No matching
|
|
51
|
+
searchProject: 'Search project',
|
|
52
|
+
noMatches: 'No matching results',
|
|
30
53
|
searching: 'Searching…',
|
|
31
|
-
resultLimit: '
|
|
54
|
+
resultLimit: 'Results are limited. Refine your query or narrow the search scope.',
|
|
32
55
|
copied: 'Copied.',
|
|
33
56
|
copyFailed: 'Could not copy. Please try again.',
|
|
34
57
|
revealRequested: 'Opened the system file manager.',
|
|
@@ -119,16 +142,39 @@ export const L3_PROJECT_FILES_LOCALE_MESSAGES = {
|
|
|
119
142
|
sessionDirectory: '原目录',
|
|
120
143
|
unavailable: '不可用',
|
|
121
144
|
projectFiles: '{{name}} 项目文件',
|
|
122
|
-
searchFiles: '
|
|
123
|
-
|
|
145
|
+
searchFiles: '搜索文件名或路径',
|
|
146
|
+
searchAll: '搜索文件或内容',
|
|
147
|
+
searchContent: '搜索文件内容',
|
|
148
|
+
searchScope: '搜索范围',
|
|
149
|
+
searchScopeAll: '全部',
|
|
150
|
+
searchScopeFiles: '文件',
|
|
151
|
+
searchScopeContent: '内容',
|
|
152
|
+
searchCaseSensitive: '区分大小写',
|
|
153
|
+
searchWholeWord: '全词匹配',
|
|
154
|
+
searchRegex: '使用正则表达式',
|
|
155
|
+
searchResults: '搜索结果',
|
|
156
|
+
searchStart: '搜索这个项目',
|
|
157
|
+
searchTryOptions: '试试其他关键词,或调整搜索选项。',
|
|
158
|
+
searchFailed: '项目搜索失败,请重试。',
|
|
159
|
+
searchCounts: '{{files}} 个文件 · {{lines}} 个命中行',
|
|
160
|
+
searchShownCounts: '已显示:{{counts}}',
|
|
161
|
+
searchFileHeading: '文件名',
|
|
162
|
+
searchContentHeading: '内容',
|
|
163
|
+
searchContentCounts: '{{lines}} 个命中行 · {{files}} 个文件',
|
|
164
|
+
searchProjectRoot: '项目根目录',
|
|
165
|
+
searchExpandFiles: '展开其余 {{count}} 个文件',
|
|
166
|
+
searchOpenLine: '打开 {{path}} 第 {{line}} 行',
|
|
167
|
+
searchLineUnavailable: '文件内容已变化,搜索命中行已不存在',
|
|
168
|
+
searchTextLimit: '正文搜索:可预览的 UTF-8 文本,不超过 5 MiB。',
|
|
169
|
+
closeSearch: '退出搜索',
|
|
124
170
|
layout: '文件组织方式',
|
|
125
171
|
directory: '目录',
|
|
126
172
|
repository: '仓库',
|
|
127
173
|
changesOnly: '只看变更',
|
|
128
|
-
searchProject: '
|
|
129
|
-
noMatches: '
|
|
174
|
+
searchProject: '搜索项目',
|
|
175
|
+
noMatches: '没有匹配结果',
|
|
130
176
|
searching: '正在搜索…',
|
|
131
|
-
resultLimit: '
|
|
177
|
+
resultLimit: '结果较多,已截断显示。请细化关键词或缩小搜索范围。',
|
|
132
178
|
copied: '已复制。',
|
|
133
179
|
copyFailed: '复制失败,请重试。',
|
|
134
180
|
revealRequested: '已请求运行端文件管理器定位。',
|
|
@@ -3,6 +3,8 @@ import { z } from 'zod'
|
|
|
3
3
|
export const L4_PROJECT_FILE_PATH_MAX_LENGTH = 4096
|
|
4
4
|
export const L4_PROJECT_FILE_LIST_MAX_ENTRIES = 5000
|
|
5
5
|
export const L4_PROJECT_FILE_SEARCH_MAX_RESULTS = 100
|
|
6
|
+
export const L4_PROJECT_CONTENT_SEARCH_MAX_RESULTS = 200
|
|
7
|
+
export const L4_PROJECT_SEARCH_TEXT_MAX_LENGTH = 1000
|
|
6
8
|
export const L4_PROJECT_TEXT_FILE_MAX_BYTES = 5 * 1024 * 1024
|
|
7
9
|
export const L4_PROJECT_CODE_PARSE_MAX_BYTES = 1024 * 1024
|
|
8
10
|
export const L4_PROJECT_IMAGE_FILE_MAX_BYTES = 10 * 1024 * 1024
|
|
@@ -76,9 +78,53 @@ export const L4ProjectFileListSchema = z
|
|
|
76
78
|
})
|
|
77
79
|
.strict()
|
|
78
80
|
|
|
81
|
+
export const L4ProjectSearchInputSchema = z
|
|
82
|
+
.object({
|
|
83
|
+
query: z
|
|
84
|
+
.string()
|
|
85
|
+
.min(1)
|
|
86
|
+
.max(200)
|
|
87
|
+
.refine(
|
|
88
|
+
(value) => value.trim().length > 0 && !/[\0\r\n]/.test(value),
|
|
89
|
+
'搜索词必须是非空单行文本'
|
|
90
|
+
),
|
|
91
|
+
scope: z.enum(['all', 'files', 'content']).default('all'),
|
|
92
|
+
caseSensitive: z.boolean().default(false),
|
|
93
|
+
wholeWord: z.boolean().default(false),
|
|
94
|
+
regex: z.boolean().default(false)
|
|
95
|
+
})
|
|
96
|
+
.strict()
|
|
97
|
+
|
|
98
|
+
export const L4ProjectSearchRangeSchema = z
|
|
99
|
+
.object({ start: z.number().int().nonnegative(), end: z.number().int().nonnegative() })
|
|
100
|
+
.strict()
|
|
101
|
+
.refine((range) => range.start <= range.end, '搜索命中区间无效')
|
|
102
|
+
|
|
103
|
+
export const L4ProjectFileMatchSchema = z
|
|
104
|
+
.object({ path: L4ProjectFilePathSchema, ranges: z.array(L4ProjectSearchRangeSchema) })
|
|
105
|
+
.strict()
|
|
106
|
+
.refine(
|
|
107
|
+
(match) => match.ranges.every((range) => range.end <= match.path.length),
|
|
108
|
+
'文件名命中区间越界'
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
export const L4ProjectContentMatchSchema = z
|
|
112
|
+
.object({
|
|
113
|
+
path: L4ProjectFilePathSchema,
|
|
114
|
+
line: z.number().int().positive(),
|
|
115
|
+
text: z.string().max(L4_PROJECT_SEARCH_TEXT_MAX_LENGTH),
|
|
116
|
+
ranges: z.array(L4ProjectSearchRangeSchema)
|
|
117
|
+
})
|
|
118
|
+
.strict()
|
|
119
|
+
.refine(
|
|
120
|
+
(match) => match.ranges.every((range) => range.end <= match.text.length),
|
|
121
|
+
'正文命中区间越界'
|
|
122
|
+
)
|
|
123
|
+
|
|
79
124
|
export const L4ProjectFileSearchSchema = z
|
|
80
125
|
.object({
|
|
81
|
-
|
|
126
|
+
fileMatches: z.array(L4ProjectFileMatchSchema).max(L4_PROJECT_FILE_SEARCH_MAX_RESULTS),
|
|
127
|
+
contentMatches: z.array(L4ProjectContentMatchSchema).max(L4_PROJECT_CONTENT_SEARCH_MAX_RESULTS),
|
|
82
128
|
truncated: z.boolean()
|
|
83
129
|
})
|
|
84
130
|
.strict()
|
|
@@ -103,6 +149,10 @@ export const L4ProjectFileContentSchema = z.discriminatedUnion('kind', [
|
|
|
103
149
|
|
|
104
150
|
export type L4ProjectFileEntry = z.infer<typeof L4ProjectFileEntrySchema>
|
|
105
151
|
export type L4ProjectFileList = z.infer<typeof L4ProjectFileListSchema>
|
|
152
|
+
export type L4ProjectSearchInput = z.infer<typeof L4ProjectSearchInputSchema>
|
|
153
|
+
export type L4ProjectSearchRange = z.infer<typeof L4ProjectSearchRangeSchema>
|
|
154
|
+
export type L4ProjectFileMatch = z.infer<typeof L4ProjectFileMatchSchema>
|
|
155
|
+
export type L4ProjectContentMatch = z.infer<typeof L4ProjectContentMatchSchema>
|
|
106
156
|
export type L4ProjectFileSearch = z.infer<typeof L4ProjectFileSearchSchema>
|
|
107
157
|
export type L4ProjectFileContent = z.infer<typeof L4ProjectFileContentSchema>
|
|
108
158
|
export type L4ProjectFileImagePreviewMode = z.infer<typeof L4ProjectFileImagePreviewModeSchema>
|
|
@@ -15,6 +15,12 @@ export const L4_HOST_ERROR_MESSAGES = {
|
|
|
15
15
|
imageTooLarge: 'This image is too large for online preview',
|
|
16
16
|
previewUnsupported: 'This file type cannot be previewed online',
|
|
17
17
|
fileReadFailed: 'Could not read the project file',
|
|
18
|
+
projectSearchPatternInvalid: 'The search expression is invalid or uses unsupported syntax',
|
|
19
|
+
projectSearchUnavailable:
|
|
20
|
+
'The project search engine is unavailable. Reinstall the complete runtime dependencies',
|
|
21
|
+
projectSearchTimeout: 'Project search timed out. Narrow the search scope and try again',
|
|
22
|
+
projectSearchReadFailed: 'Could not read project search files or results',
|
|
23
|
+
projectSearchCancelled: 'Project search was cancelled',
|
|
18
24
|
revealFailed: 'Could not open the file location',
|
|
19
25
|
repositoryMissing: 'Git repository not found',
|
|
20
26
|
gitOutsideProject: 'The Git target is outside the current project',
|
|
@@ -169,6 +175,11 @@ export const L4_HOST_ERROR_MESSAGES = {
|
|
|
169
175
|
imageTooLarge: '图片过大,暂不支持在线预览',
|
|
170
176
|
previewUnsupported: '当前文件类型不支持在线预览',
|
|
171
177
|
fileReadFailed: '读取项目文件失败',
|
|
178
|
+
projectSearchPatternInvalid: '搜索表达式无效或包含不支持的语法',
|
|
179
|
+
projectSearchUnavailable: '项目搜索引擎不可用,请重新安装完整运行依赖',
|
|
180
|
+
projectSearchTimeout: '项目搜索超时,请缩小搜索范围后重试',
|
|
181
|
+
projectSearchReadFailed: '无法读取项目搜索文件或结果',
|
|
182
|
+
projectSearchCancelled: '项目搜索已取消',
|
|
172
183
|
revealFailed: '打开所在文件夹失败',
|
|
173
184
|
repositoryMissing: 'Git 仓库不存在',
|
|
174
185
|
gitOutsideProject: 'Git 目标不在当前项目目录内',
|
|
@@ -40,6 +40,14 @@ export const L4_LOCALE_MESSAGES = {
|
|
|
40
40
|
authenticationRequired: 'Please sign in',
|
|
41
41
|
authUnavailable: 'Sign-in service is not ready',
|
|
42
42
|
shuttingDown: 'The service is shutting down',
|
|
43
|
+
markdownPending: 'Not completed',
|
|
44
|
+
markdownCompleted: 'Completed',
|
|
45
|
+
markdownProgress: 'In progress',
|
|
46
|
+
markdownNote: 'Note',
|
|
47
|
+
markdownTip: 'Tip',
|
|
48
|
+
markdownImportant: 'Important',
|
|
49
|
+
markdownWarning: 'Warning',
|
|
50
|
+
markdownCaution: 'Caution',
|
|
43
51
|
codeReadOnly: 'Read-only code file',
|
|
44
52
|
codeLoading: 'Loading code viewer…',
|
|
45
53
|
codeFailed: 'Could not load code viewer. Reopen the file.',
|
|
@@ -118,6 +126,14 @@ export const L4_LOCALE_MESSAGES = {
|
|
|
118
126
|
authenticationRequired: '请先登录',
|
|
119
127
|
authUnavailable: '登录认证尚未就绪',
|
|
120
128
|
shuttingDown: '服务正在关闭',
|
|
129
|
+
markdownPending: '未完成',
|
|
130
|
+
markdownCompleted: '已完成',
|
|
131
|
+
markdownProgress: '进行中',
|
|
132
|
+
markdownNote: '说明',
|
|
133
|
+
markdownTip: '提示',
|
|
134
|
+
markdownImportant: '重要',
|
|
135
|
+
markdownWarning: '警告',
|
|
136
|
+
markdownCaution: '注意',
|
|
121
137
|
codeReadOnly: '只读代码文件',
|
|
122
138
|
codeLoading: '正在加载代码查看器…',
|
|
123
139
|
codeFailed: '代码查看器加载失败,请重新打开文件。',
|
package/src/instrumentation.ts
CHANGED
|
@@ -33,7 +33,6 @@ export async function register(): Promise<void> {
|
|
|
33
33
|
})
|
|
34
34
|
const manage = getL2WorkSessionManage()
|
|
35
35
|
initializeL2PluginManagement({
|
|
36
|
-
refreshPluginMessages: () => manage.refreshPluginMessages(),
|
|
37
36
|
runPluginRestart: (operation) => manage.runPluginRestart(operation)
|
|
38
37
|
})
|
|
39
38
|
registerL1WebAuthRuntime(getL1WebAuthRuntime())
|
|
@@ -70,7 +69,6 @@ export async function register(): Promise<void> {
|
|
|
70
69
|
setTimeout(() => {
|
|
71
70
|
void pluginRuntime.initialize().then(
|
|
72
71
|
() => {
|
|
73
|
-
manage.refreshPluginMessages()
|
|
74
72
|
console.info('[Pi Desk][Instrumentation] 插件加载尝试完成,基础聊天不依赖插件就绪')
|
|
75
73
|
},
|
|
76
74
|
(error: unknown) => {
|
|
@@ -2,9 +2,9 @@ import 'server-only'
|
|
|
2
2
|
import * as contracts from '@common/l3_modules/project-files/l3-project-files-contract'
|
|
3
3
|
import {
|
|
4
4
|
getL4WorkSessionProjectFile,
|
|
5
|
-
listL4WorkSessionProjectFiles
|
|
6
|
-
searchL4WorkSessionProjectFiles
|
|
5
|
+
listL4WorkSessionProjectFiles
|
|
7
6
|
} from '@server/l4_foundation/file/l4-work-session-project-file'
|
|
7
|
+
import { searchL4ProjectFiles } from '@server/l4_foundation/file/l4-project-search'
|
|
8
8
|
import {
|
|
9
9
|
getL4WorkSessionGitHeads,
|
|
10
10
|
getL4WorkSessionGitSnapshot
|
|
@@ -20,8 +20,10 @@ import { createL1ProjectRoute } from './l1-project-route'
|
|
|
20
20
|
export const projectFileList = createL1ProjectRoute(contracts.L3ProjectFileList, (input) =>
|
|
21
21
|
listL4WorkSessionProjectFiles(input.cwd, input.path)
|
|
22
22
|
)
|
|
23
|
-
export const projectFileSearch = createL1ProjectRoute(
|
|
24
|
-
|
|
23
|
+
export const projectFileSearch = createL1ProjectRoute(
|
|
24
|
+
contracts.L3ProjectFileSearch,
|
|
25
|
+
({ cwd, query, scope, caseSensitive, wholeWord, regex }, signal) =>
|
|
26
|
+
searchL4ProjectFiles(cwd, { query, scope, caseSensitive, wholeWord, regex }, signal)
|
|
25
27
|
)
|
|
26
28
|
export const projectFileGet = createL1ProjectRoute(contracts.L3ProjectFileGet, (input) =>
|
|
27
29
|
getL4WorkSessionProjectFile(input.cwd, input.path, input.imagePreviewMode)
|
|
@@ -13,7 +13,7 @@ import { createL1WorkSessionGitErrorResponse } from './l1-work-session-git-error
|
|
|
13
13
|
|
|
14
14
|
export function createL1ProjectRoute<I extends contracts.L3ProjectReadContext, O>(
|
|
15
15
|
contract: { path: string; request: z.ZodType<I>; response: z.ZodType<O> },
|
|
16
|
-
execute: (input: I) => Promise<O>
|
|
16
|
+
execute: (input: I, signal: AbortSignal) => Promise<O>
|
|
17
17
|
): (request: Request) => Promise<Response> {
|
|
18
18
|
return async (request: Request): Promise<Response> => {
|
|
19
19
|
let payload: unknown
|
|
@@ -49,19 +49,20 @@ export function createL1ProjectRoute<I extends contracts.L3ProjectReadContext, O
|
|
|
49
49
|
input.cwd = context.cwd
|
|
50
50
|
isCurrent = context.isCurrent
|
|
51
51
|
}
|
|
52
|
-
const result = await execute(input)
|
|
52
|
+
const result = await execute(input, request.signal)
|
|
53
53
|
if (isCurrent && !isCurrent())
|
|
54
54
|
return createL4ApiErrorResponse(409, '工作会话项目已变化', {
|
|
55
55
|
key: 'errors:projectChanged'
|
|
56
56
|
})
|
|
57
57
|
return createL4ApiSuccessResponse(contract.response.parse(result))
|
|
58
58
|
} catch (error) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
if (!request.signal.aborted)
|
|
60
|
+
console.warn('[Pi Desk][Project] 项目请求失败', {
|
|
61
|
+
path: contract.path,
|
|
62
|
+
cwd: input.cwd,
|
|
63
|
+
workId: input.workId,
|
|
64
|
+
error: error instanceof Error ? error.message : String(error)
|
|
65
|
+
})
|
|
65
66
|
if (getL4WorkSessionGitErrorKind(error) === 'read-failed') {
|
|
66
67
|
return createL4ApiErrorResponse(
|
|
67
68
|
500,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import 'server-only'
|
|
2
2
|
|
|
3
3
|
import { getL4WorkSessionProjectFileErrorKind } from '@server/l4_foundation/file/l4-work-session-project-file'
|
|
4
|
+
import { L4ProjectSearchError } from '@server/l4_foundation/file/l4-project-search'
|
|
4
5
|
import { createL4ApiErrorResponse } from '@server/l4_foundation/http/l4-api-response'
|
|
5
6
|
|
|
6
7
|
export function createL1WorkSessionFileErrorResponse(error: unknown): Response | null {
|
|
@@ -11,6 +12,28 @@ export function createL1WorkSessionFileErrorResponse(error: unknown): Response |
|
|
|
11
12
|
return createL4ApiErrorResponse(409, '工作会话项目已变化', { key: 'errors:projectChanged' })
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
16
|
+
return createL4ApiErrorResponse(499, '项目搜索已取消', { key: 'errors:projectSearchCancelled' })
|
|
17
|
+
}
|
|
18
|
+
if (error instanceof L4ProjectSearchError) {
|
|
19
|
+
switch (error.kind) {
|
|
20
|
+
case 'invalid-pattern':
|
|
21
|
+
return createL4ApiErrorResponse(400, error.message, {
|
|
22
|
+
key: 'errors:projectSearchPatternInvalid'
|
|
23
|
+
})
|
|
24
|
+
case 'unavailable':
|
|
25
|
+
return createL4ApiErrorResponse(503, error.message, {
|
|
26
|
+
key: 'errors:projectSearchUnavailable'
|
|
27
|
+
})
|
|
28
|
+
case 'timeout':
|
|
29
|
+
return createL4ApiErrorResponse(504, error.message, { key: 'errors:projectSearchTimeout' })
|
|
30
|
+
case 'read-failed':
|
|
31
|
+
return createL4ApiErrorResponse(500, error.message, {
|
|
32
|
+
key: 'errors:projectSearchReadFailed'
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
14
37
|
switch (getL4WorkSessionProjectFileErrorKind(error)) {
|
|
15
38
|
case 'not-found':
|
|
16
39
|
return createL4ApiErrorResponse(404, '文件或目录不存在', { key: 'errors:fileMissing' })
|
|
@@ -112,7 +112,6 @@ interface L2PluginPreparedMutation {
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
export interface L2PluginManagementWorkSessions {
|
|
115
|
-
refreshPluginMessages: () => void
|
|
116
115
|
runPluginRestart: <T>(operation: () => Promise<T>) => Promise<T>
|
|
117
116
|
}
|
|
118
117
|
|
|
@@ -621,7 +620,6 @@ export class L2PluginManagement {
|
|
|
621
620
|
if (change.current?.path) clearL4PiPluginNativeDiagnostics(change.current.path)
|
|
622
621
|
if (change.previous?.path) clearL4PiPluginNativeDiagnostics(change.previous.path)
|
|
623
622
|
this.capabilityCache = null
|
|
624
|
-
this.workSessions.refreshPluginMessages()
|
|
625
623
|
this.operations.delete(change.source)
|
|
626
624
|
} catch (error) {
|
|
627
625
|
this.setOperation(change.source, 'failed', errorMessage(error))
|
|
@@ -981,7 +979,6 @@ export class L2PluginManagement {
|
|
|
981
979
|
this.updates.clear(operationSource)
|
|
982
980
|
this.updates.clear(source)
|
|
983
981
|
this.capabilityCache = null
|
|
984
|
-
this.workSessions.refreshPluginMessages()
|
|
985
982
|
},
|
|
986
983
|
this.lifetime.signal,
|
|
987
984
|
waiting
|