@lobehub/chat 1.81.9 → 1.82.1

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.
Files changed (115) hide show
  1. package/.cursor/rules/desktop-local-tools-implement.mdc +80 -0
  2. package/.env.desktop +2 -1
  3. package/.github/scripts/pr-comment.js +4 -9
  4. package/CHANGELOG.md +50 -0
  5. package/changelog/v1.json +18 -0
  6. package/locales/ar/electron.json +38 -2
  7. package/locales/ar/plugin.json +33 -2
  8. package/locales/bg-BG/electron.json +38 -2
  9. package/locales/bg-BG/plugin.json +33 -2
  10. package/locales/de-DE/electron.json +38 -2
  11. package/locales/de-DE/plugin.json +28 -2
  12. package/locales/en-US/electron.json +38 -2
  13. package/locales/en-US/plugin.json +28 -2
  14. package/locales/es-ES/electron.json +38 -2
  15. package/locales/es-ES/plugin.json +33 -2
  16. package/locales/fa-IR/electron.json +38 -2
  17. package/locales/fa-IR/plugin.json +33 -2
  18. package/locales/fr-FR/electron.json +38 -2
  19. package/locales/fr-FR/plugin.json +33 -2
  20. package/locales/it-IT/electron.json +38 -2
  21. package/locales/it-IT/plugin.json +33 -2
  22. package/locales/ja-JP/electron.json +38 -2
  23. package/locales/ja-JP/plugin.json +33 -2
  24. package/locales/ko-KR/electron.json +38 -2
  25. package/locales/ko-KR/plugin.json +28 -2
  26. package/locales/nl-NL/electron.json +38 -2
  27. package/locales/nl-NL/plugin.json +33 -2
  28. package/locales/pl-PL/electron.json +38 -2
  29. package/locales/pl-PL/plugin.json +28 -2
  30. package/locales/pt-BR/electron.json +38 -2
  31. package/locales/pt-BR/plugin.json +33 -2
  32. package/locales/ru-RU/electron.json +38 -2
  33. package/locales/ru-RU/plugin.json +33 -2
  34. package/locales/tr-TR/electron.json +38 -2
  35. package/locales/tr-TR/plugin.json +33 -2
  36. package/locales/vi-VN/electron.json +38 -2
  37. package/locales/vi-VN/plugin.json +28 -2
  38. package/locales/zh-CN/electron.json +38 -2
  39. package/locales/zh-CN/plugin.json +38 -2
  40. package/locales/zh-TW/electron.json +38 -2
  41. package/locales/zh-TW/plugin.json +33 -2
  42. package/package.json +1 -1
  43. package/packages/electron-client-ipc/src/events/update.ts +3 -3
  44. package/src/app/[variants]/(main)/_layout/Desktop/ElectronTitlebar/Connection/Mode.tsx +222 -0
  45. package/src/app/[variants]/(main)/_layout/Desktop/ElectronTitlebar/Connection/Option.tsx +104 -0
  46. package/src/app/[variants]/(main)/_layout/Desktop/ElectronTitlebar/Connection/Sync.tsx +42 -0
  47. package/src/app/[variants]/(main)/_layout/Desktop/ElectronTitlebar/Connection/Waiting.tsx +203 -0
  48. package/src/app/[variants]/(main)/_layout/Desktop/ElectronTitlebar/Connection/index.tsx +57 -0
  49. package/src/app/[variants]/(main)/_layout/Desktop/ElectronTitlebar/UpdateModal.tsx +242 -0
  50. package/src/app/[variants]/(main)/_layout/Desktop/ElectronTitlebar/UpdateNotification.tsx +193 -0
  51. package/src/app/[variants]/(main)/_layout/Desktop/{Titlebar.tsx → ElectronTitlebar/index.tsx} +15 -1
  52. package/src/app/[variants]/(main)/_layout/Desktop/SideBar/BottomActions.tsx +3 -2
  53. package/src/app/[variants]/(main)/_layout/Desktop/index.tsx +1 -1
  54. package/src/app/[variants]/layout.tsx +2 -1
  55. package/src/components/ManifestPreviewer/index.tsx +4 -1
  56. package/src/features/ChatInput/ActionBar/Tools/Dropdown.tsx +2 -1
  57. package/src/features/Conversation/Extras/Usage/index.tsx +7 -1
  58. package/src/features/Conversation/Messages/Assistant/Tool/Render/CustomRender.tsx +1 -1
  59. package/src/features/Conversation/components/MarkdownElements/LocalFile/Render/LocalFile.tsx +65 -0
  60. package/src/features/Conversation/components/MarkdownElements/LocalFile/Render/index.tsx +29 -0
  61. package/src/features/Conversation/components/MarkdownElements/LocalFile/index.ts +16 -0
  62. package/src/features/Conversation/components/MarkdownElements/index.ts +7 -1
  63. package/src/features/Conversation/components/MarkdownElements/remarkPlugins/__snapshots__/createRemarkSelfClosingTagPlugin.test.ts.snap +260 -0
  64. package/src/features/Conversation/components/MarkdownElements/remarkPlugins/createRemarkSelfClosingTagPlugin.test.ts +204 -0
  65. package/src/features/Conversation/components/MarkdownElements/remarkPlugins/createRemarkSelfClosingTagPlugin.ts +133 -0
  66. package/src/features/Conversation/components/MarkdownElements/type.ts +5 -1
  67. package/src/features/PluginAvatar/index.tsx +2 -1
  68. package/src/features/PluginDevModal/MCPManifestForm/ArgsInput.tsx +20 -0
  69. package/src/features/PluginDevModal/MCPManifestForm/MCPTypeSelect.tsx +176 -0
  70. package/src/features/PluginDevModal/MCPManifestForm/index.tsx +226 -0
  71. package/src/features/PluginDevModal/PluginPreview.tsx +4 -3
  72. package/src/features/PluginDevModal/index.tsx +43 -34
  73. package/src/features/PluginStore/AddPluginButton.tsx +3 -1
  74. package/src/features/PluginStore/PluginItem/Action.tsx +5 -2
  75. package/src/features/PluginStore/PluginItem/PluginAvatar.tsx +25 -0
  76. package/src/features/PluginStore/PluginItem/index.tsx +4 -3
  77. package/src/features/PluginTag/index.tsx +8 -2
  78. package/src/{server/modules/MCPClient → libs/mcp}/__tests__/__snapshots__/index.test.ts.snap +0 -56
  79. package/src/{server/modules/MCPClient → libs/mcp}/__tests__/index.test.ts +2 -2
  80. package/src/{server/modules/MCPClient/index.ts → libs/mcp/client.ts} +29 -33
  81. package/src/libs/mcp/index.ts +2 -0
  82. package/src/libs/mcp/types.ts +27 -0
  83. package/src/locales/default/electron.ts +38 -2
  84. package/src/locales/default/plugin.ts +41 -3
  85. package/src/server/modules/ElectronIPCClient/index.ts +36 -0
  86. package/src/server/routers/lambda/session.ts +2 -6
  87. package/src/server/routers/tools/index.ts +2 -0
  88. package/src/server/routers/tools/mcp.ts +85 -0
  89. package/src/server/services/file/impls/index.ts +9 -1
  90. package/src/server/services/file/impls/local.test.ts +299 -0
  91. package/src/server/services/file/impls/local.ts +183 -0
  92. package/src/server/services/mcp/index.ts +176 -0
  93. package/src/services/aiModel/index.ts +5 -1
  94. package/src/services/aiProvider/index.ts +5 -1
  95. package/src/services/electron/autoUpdate.ts +4 -0
  96. package/src/services/file/index.ts +5 -1
  97. package/src/services/mcp.ts +36 -0
  98. package/src/services/message/index.ts +5 -1
  99. package/src/services/plugin/index.ts +5 -1
  100. package/src/services/session/index.ts +5 -1
  101. package/src/services/tableViewer/desktop.ts +15 -0
  102. package/src/services/tableViewer/index.ts +4 -1
  103. package/src/services/thread/index.ts +5 -1
  104. package/src/services/topic/index.ts +5 -1
  105. package/src/services/user/index.ts +5 -1
  106. package/src/store/chat/slices/plugin/action.ts +46 -2
  107. package/src/store/electron/actions/app.ts +59 -0
  108. package/src/store/electron/actions/sync.ts +5 -1
  109. package/src/store/electron/initialState.ts +3 -1
  110. package/src/store/electron/store.ts +6 -1
  111. package/src/store/tool/slices/customPlugin/action.ts +16 -4
  112. package/src/types/tool/plugin.ts +9 -0
  113. package/src/utils/client/GlobalAgentContextManager.ts +85 -0
  114. package/src/utils/promptTemplate.test.ts +78 -0
  115. package/src/utils/promptTemplate.ts +17 -0
@@ -1,11 +1,20 @@
1
1
  import { memo } from 'react';
2
2
  import { Flexbox } from 'react-layout-kit';
3
3
 
4
+ import { useElectronStore } from '@/store/electron';
4
5
  import { electronStylish } from '@/styles/electron';
5
6
 
7
+ import Connection from './Connection';
8
+ import { UpdateModal } from './UpdateModal';
9
+ import { UpdateNotification } from './UpdateNotification';
10
+
6
11
  export const TITLE_BAR_HEIGHT = 36;
7
12
 
8
13
  const TitleBar = memo(() => {
14
+ const initElectronAppState = useElectronStore((s) => s.useInitElectronAppState);
15
+
16
+ initElectronAppState();
17
+
9
18
  return (
10
19
  <Flexbox
11
20
  align={'center'}
@@ -19,7 +28,12 @@ const TitleBar = memo(() => {
19
28
  >
20
29
  <div />
21
30
  <div>{/* TODO */}</div>
22
- <div>{/* TODO */}</div>
31
+
32
+ <Flexbox className={electronStylish.nodrag} gap={8} horizontal>
33
+ <UpdateNotification />
34
+ <Connection />
35
+ </Flexbox>
36
+ <UpdateModal />
23
37
  </Flexbox>
24
38
  );
25
39
  });
@@ -3,6 +3,7 @@ import { Book, Github } from 'lucide-react';
3
3
  import Link from 'next/link';
4
4
  import { memo } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
+ import { Flexbox } from 'react-layout-kit';
6
7
 
7
8
  import { DOCUMENTS_REFER_URL, GITHUB } from '@/const/url';
8
9
  import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
@@ -12,7 +13,7 @@ const BottomActions = memo(() => {
12
13
  const { hideGitHub, hideDocs } = useServerConfigStore(featureFlagsSelectors);
13
14
 
14
15
  return (
15
- <>
16
+ <Flexbox gap={8}>
16
17
  {!hideGitHub && (
17
18
  <Link aria-label={'GitHub'} href={GITHUB} target={'_blank'}>
18
19
  <ActionIcon icon={Github} placement={'right'} title={'GitHub'} />
@@ -23,7 +24,7 @@ const BottomActions = memo(() => {
23
24
  <ActionIcon icon={Book} placement={'right'} title={t('document')} />
24
25
  </Link>
25
26
  )}
26
- </>
27
+ </Flexbox>
27
28
  );
28
29
  });
29
30
 
@@ -14,9 +14,9 @@ import { usePlatform } from '@/hooks/usePlatform';
14
14
  import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
15
15
  import { HotkeyScopeEnum } from '@/types/hotkey';
16
16
 
17
+ import TitleBar, { TITLE_BAR_HEIGHT } from './ElectronTitlebar';
17
18
  import RegisterHotkeys from './RegisterHotkeys';
18
19
  import SideBar from './SideBar';
19
- import TitleBar, { TITLE_BAR_HEIGHT } from './Titlebar';
20
20
 
21
21
  const CloudBanner = dynamic(() => import('@/features/AlertBanner/CloudBanner'));
22
22
 
@@ -7,6 +7,7 @@ import { isRtlLang } from 'rtl-detect';
7
7
 
8
8
  import Analytics from '@/components/Analytics';
9
9
  import { DEFAULT_LANG } from '@/const/locale';
10
+ import { isDesktop } from '@/const/version';
10
11
  import PWAInstall from '@/features/PWAInstall';
11
12
  import AuthProvider from '@/layout/AuthProvider';
12
13
  import GlobalProvider from '@/layout/GlobalProvider';
@@ -78,7 +79,7 @@ export const generateViewport = async (props: DynamicLayoutProps): ResolvingView
78
79
 
79
80
  export const generateStaticParams = () => {
80
81
  const themes: ThemeAppearance[] = ['dark', 'light'];
81
- const mobileOptions = [true, false];
82
+ const mobileOptions = isDesktop ? [false] : [true, false];
82
83
  // only static for serveral page, other go to dynamtic
83
84
  const staticLocales: Locales[] = [DEFAULT_LANG, 'zh-CN'];
84
85
 
@@ -13,7 +13,10 @@ const ManifestPreviewer = memo<PluginManifestPreviewerProps>(
13
13
  <Popover
14
14
  arrow={false}
15
15
  content={
16
- <Highlighter language={'json'} style={{ maxHeight: 600, maxWidth: 400 }}>
16
+ <Highlighter
17
+ language={'json'}
18
+ style={{ maxHeight: 600, maxWidth: 400, overflow: 'scroll' }}
19
+ >
17
20
  {JSON.stringify(manifest, null, 2)}
18
21
  </Highlighter>
19
22
  }
@@ -9,6 +9,7 @@ import { useTranslation } from 'react-i18next';
9
9
  import { Flexbox } from 'react-layout-kit';
10
10
 
11
11
  import PluginStore from '@/features/PluginStore';
12
+ import PluginAvatar from '@/features/PluginStore/PluginItem/PluginAvatar';
12
13
  import { useCheckPluginsIsInstalled } from '@/hooks/useCheckPluginsIsInstalled';
13
14
  import { useFetchInstalledPlugins } from '@/hooks/useFetchInstalledPlugins';
14
15
  import { useWorkspaceModal } from '@/hooks/useWorkspaceModal';
@@ -67,7 +68,7 @@ const DropdownMenu = memo<PropsWithChildren>(({ children }) => {
67
68
  children: [
68
69
  ...list.map((item) => ({
69
70
  icon: item.meta?.avatar ? (
70
- <Avatar avatar={pluginHelpers.getPluginAvatar(item.meta)} size={24} />
71
+ <PluginAvatar avatar={pluginHelpers.getPluginAvatar(item.meta)} size={24} />
71
72
  ) : (
72
73
  <Icon icon={ToyBrick} size={{ fontSize: 16 }} style={{ padding: 4 }} />
73
74
  ),
@@ -24,7 +24,13 @@ const Usage = memo<UsageProps>(({ model, metadata, provider }) => {
24
24
  const { styles } = useStyles();
25
25
 
26
26
  return (
27
- <Flexbox align={'center'} className={styles.container} horizontal justify={'space-between'}>
27
+ <Flexbox
28
+ align={'center'}
29
+ className={styles.container}
30
+ gap={12}
31
+ horizontal
32
+ justify={'space-between'}
33
+ >
28
34
  <Center gap={4} horizontal style={{ fontSize: 12 }}>
29
35
  <ModelIcon model={model as string} type={'mono'} />
30
36
  {model}
@@ -75,7 +75,7 @@ const CustomRender = memo<CustomRenderProps>(
75
75
  useEffect(() => {
76
76
  if (!plugin?.type || loading) return;
77
77
 
78
- setShowPluginRender(plugin?.type !== 'default');
78
+ setShowPluginRender(!['default', 'mcp'].includes(plugin?.type));
79
79
  }, [plugin?.type, loading]);
80
80
 
81
81
  if (loading) return <Arguments arguments={requestArgs} shine />;
@@ -0,0 +1,65 @@
1
+ import { createStyles } from 'antd-style';
2
+ import React from 'react';
3
+ import { Flexbox } from 'react-layout-kit';
4
+
5
+ import FileIcon from '@/components/FileIcon';
6
+ import { localFileService } from '@/services/electron/localFileService';
7
+
8
+ const useStyles = createStyles(({ css, token }) => ({
9
+ container: css`
10
+ cursor: pointer;
11
+
12
+ padding-block: 2px;
13
+ padding-inline: 4px 8px;
14
+ border-radius: 4px;
15
+
16
+ color: ${token.colorTextSecondary};
17
+
18
+ :hover {
19
+ color: ${token.colorText};
20
+ background: ${token.colorFillTertiary};
21
+ }
22
+ `,
23
+ title: css`
24
+ overflow: hidden;
25
+ display: block;
26
+
27
+ line-height: 20px;
28
+ color: inherit;
29
+ text-overflow: ellipsis;
30
+ white-space: nowrap;
31
+ `,
32
+ }));
33
+
34
+ const LocalFile = ({
35
+ name,
36
+ path,
37
+ isDirectory,
38
+ }: {
39
+ isDirectory: boolean;
40
+ name: string;
41
+ path: string;
42
+ }) => {
43
+ const { styles } = useStyles();
44
+ const handleClick = () => {
45
+ localFileService.openLocalFileOrFolder(path, isDirectory);
46
+ };
47
+
48
+ return (
49
+ <Flexbox
50
+ align={'center'}
51
+ className={styles.container}
52
+ gap={4}
53
+ horizontal
54
+ onClick={handleClick}
55
+ style={{ display: 'inline-flex', verticalAlign: 'middle' }}
56
+ >
57
+ <FileIcon fileName={name} isDirectory={isDirectory} size={22} variant={'pure'} />
58
+ <Flexbox align={'baseline'} gap={4} horizontal style={{ overflow: 'hidden', width: '100%' }}>
59
+ <div className={styles.title}>{name}</div>
60
+ </Flexbox>
61
+ </Flexbox>
62
+ );
63
+ };
64
+
65
+ export default LocalFile;
@@ -0,0 +1,29 @@
1
+ import isEqual from 'fast-deep-equal';
2
+ import React, { memo } from 'react';
3
+
4
+ import { MarkdownElementProps } from '../../type';
5
+ import LocalFile from './LocalFile';
6
+
7
+ interface LocalFileProps {
8
+ isDirectory: boolean;
9
+ name: string;
10
+ path: string;
11
+ }
12
+
13
+ const Render = memo<MarkdownElementProps<LocalFileProps>>(({ node }) => {
14
+ // 从 node.properties 中提取属性
15
+ const { name, path, isDirectory } = node?.properties || {};
16
+
17
+ if (!name || !path) {
18
+ // 如果缺少必要属性,可以选择渲染错误提示或 null
19
+ console.error('LocalFile Render component missing required properties:', node?.properties);
20
+ return null; // 或者返回一个错误占位符
21
+ }
22
+
23
+ // isDirectory 属性可能为 true (来自插件) 或 undefined,我们需要确保它是 boolean
24
+ const isDir = isDirectory === true;
25
+
26
+ return <LocalFile isDirectory={isDir} name={name} path={path} />;
27
+ }, isEqual);
28
+
29
+ export default Render;
@@ -0,0 +1,16 @@
1
+ import { FC } from 'react';
2
+
3
+ import { createRemarkSelfClosingTagPlugin } from '../remarkPlugins/createRemarkSelfClosingTagPlugin';
4
+ import { MarkdownElement, MarkdownElementProps } from '../type';
5
+ import RenderComponent from './Render';
6
+
7
+ // 定义此元素的标签名
8
+ const tag = 'localFile';
9
+
10
+ const LocalFileElement: MarkdownElement = {
11
+ Component: RenderComponent as FC<MarkdownElementProps>,
12
+ remarkPlugin: createRemarkSelfClosingTagPlugin(tag),
13
+ tag,
14
+ };
15
+
16
+ export default LocalFileElement;
@@ -1,6 +1,12 @@
1
1
  import LobeArtifact from './LobeArtifact';
2
2
  import LobeThinking from './LobeThinking';
3
+ import LocalFile from './LocalFile';
3
4
  import Thinking from './Thinking';
4
5
  import { MarkdownElement } from './type';
5
6
 
6
- export const markdownElements: MarkdownElement[] = [Thinking, LobeArtifact, LobeThinking];
7
+ export const markdownElements: MarkdownElement[] = [
8
+ Thinking,
9
+ LobeArtifact,
10
+ LobeThinking,
11
+ LocalFile,
12
+ ];
@@ -0,0 +1,260 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`createRemarkSelfClosingTagPlugin > should handle tag within a list item and generate snapshot 1`] = `
4
+ {
5
+ "children": [
6
+ {
7
+ "children": [
8
+ {
9
+ "checked": null,
10
+ "children": [
11
+ {
12
+ "children": [
13
+ {
14
+ "position": {
15
+ "end": {
16
+ "column": 26,
17
+ "line": 2,
18
+ "offset": 26,
19
+ },
20
+ "start": {
21
+ "column": 4,
22
+ "line": 2,
23
+ "offset": 4,
24
+ },
25
+ },
26
+ "type": "text",
27
+ "value": "文件名:飞机全书 一部明晰可见的历史.pdf",
28
+ },
29
+ ],
30
+ "position": {
31
+ "end": {
32
+ "column": 26,
33
+ "line": 2,
34
+ "offset": 26,
35
+ },
36
+ "start": {
37
+ "column": 4,
38
+ "line": 2,
39
+ "offset": 4,
40
+ },
41
+ },
42
+ "type": "paragraph",
43
+ },
44
+ {
45
+ "children": [
46
+ {
47
+ "checked": null,
48
+ "children": [
49
+ {
50
+ "children": [
51
+ {
52
+ "position": {
53
+ "end": {
54
+ "column": 10,
55
+ "line": 3,
56
+ "offset": 36,
57
+ },
58
+ "start": {
59
+ "column": 6,
60
+ "line": 3,
61
+ "offset": 32,
62
+ },
63
+ },
64
+ "type": "text",
65
+ "value": "路径1:",
66
+ },
67
+ {
68
+ "data": {
69
+ "hName": "localFile",
70
+ "hProperties": {
71
+ "name": "飞机全书 一部明晰可见的历史.pdf",
72
+ "path": "/Users/abc/Zotero/storage/ASBMAURK/飞机全书 一部明晰可见的历史.pdf",
73
+ },
74
+ },
75
+ "type": "localFile",
76
+ },
77
+ ],
78
+ "position": {
79
+ "end": {
80
+ "column": 110,
81
+ "line": 3,
82
+ "offset": 136,
83
+ },
84
+ "start": {
85
+ "column": 6,
86
+ "line": 3,
87
+ "offset": 32,
88
+ },
89
+ },
90
+ "type": "paragraph",
91
+ },
92
+ ],
93
+ "position": {
94
+ "end": {
95
+ "column": 110,
96
+ "line": 3,
97
+ "offset": 136,
98
+ },
99
+ "start": {
100
+ "column": 4,
101
+ "line": 3,
102
+ "offset": 30,
103
+ },
104
+ },
105
+ "spread": false,
106
+ "type": "listItem",
107
+ },
108
+ {
109
+ "checked": null,
110
+ "children": [
111
+ {
112
+ "children": [
113
+ {
114
+ "position": {
115
+ "end": {
116
+ "column": 56,
117
+ "line": 4,
118
+ "offset": 192,
119
+ },
120
+ "start": {
121
+ "column": 6,
122
+ "line": 4,
123
+ "offset": 142,
124
+ },
125
+ },
126
+ "type": "text",
127
+ "value": "路径2:/Users/abc/Downloads/测试 PDF/飞机全书 一部明晰可见的历史.pdf",
128
+ },
129
+ ],
130
+ "position": {
131
+ "end": {
132
+ "column": 56,
133
+ "line": 4,
134
+ "offset": 192,
135
+ },
136
+ "start": {
137
+ "column": 6,
138
+ "line": 4,
139
+ "offset": 142,
140
+ },
141
+ },
142
+ "type": "paragraph",
143
+ },
144
+ ],
145
+ "position": {
146
+ "end": {
147
+ "column": 56,
148
+ "line": 4,
149
+ "offset": 192,
150
+ },
151
+ "start": {
152
+ "column": 4,
153
+ "line": 4,
154
+ "offset": 140,
155
+ },
156
+ },
157
+ "spread": false,
158
+ "type": "listItem",
159
+ },
160
+ ],
161
+ "ordered": false,
162
+ "position": {
163
+ "end": {
164
+ "column": 56,
165
+ "line": 4,
166
+ "offset": 192,
167
+ },
168
+ "start": {
169
+ "column": 4,
170
+ "line": 3,
171
+ "offset": 30,
172
+ },
173
+ },
174
+ "spread": false,
175
+ "start": null,
176
+ "type": "list",
177
+ },
178
+ ],
179
+ "position": {
180
+ "end": {
181
+ "column": 56,
182
+ "line": 4,
183
+ "offset": 192,
184
+ },
185
+ "start": {
186
+ "column": 1,
187
+ "line": 2,
188
+ "offset": 1,
189
+ },
190
+ },
191
+ "spread": false,
192
+ "type": "listItem",
193
+ },
194
+ ],
195
+ "ordered": true,
196
+ "position": {
197
+ "end": {
198
+ "column": 56,
199
+ "line": 4,
200
+ "offset": 192,
201
+ },
202
+ "start": {
203
+ "column": 1,
204
+ "line": 2,
205
+ "offset": 1,
206
+ },
207
+ },
208
+ "spread": false,
209
+ "start": 1,
210
+ "type": "list",
211
+ },
212
+ {
213
+ "children": [
214
+ {
215
+ "position": {
216
+ "end": {
217
+ "column": 75,
218
+ "line": 6,
219
+ "offset": 268,
220
+ },
221
+ "start": {
222
+ "column": 1,
223
+ "line": 6,
224
+ "offset": 194,
225
+ },
226
+ },
227
+ "type": "text",
228
+ "value": "这是一本 PDF 格式的书,并且在你的 Zotero 和 Downloads 文件夹里都能找到。如果需要进一步操作,比如阅读或者提取内容,可以告诉我",
229
+ },
230
+ ],
231
+ "position": {
232
+ "end": {
233
+ "column": 75,
234
+ "line": 6,
235
+ "offset": 268,
236
+ },
237
+ "start": {
238
+ "column": 1,
239
+ "line": 6,
240
+ "offset": 194,
241
+ },
242
+ },
243
+ "type": "paragraph",
244
+ },
245
+ ],
246
+ "position": {
247
+ "end": {
248
+ "column": 1,
249
+ "line": 7,
250
+ "offset": 269,
251
+ },
252
+ "start": {
253
+ "column": 1,
254
+ "line": 1,
255
+ "offset": 0,
256
+ },
257
+ },
258
+ "type": "root",
259
+ }
260
+ `;