@lobehub/lobehub 2.0.0-next.239 → 2.0.0-next.240

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 (69) hide show
  1. package/.cursor/rules/typescript.mdc +1 -0
  2. package/CHANGELOG.md +33 -0
  3. package/changelog/v1.json +5 -0
  4. package/locales/en-US/plugin.json +9 -0
  5. package/locales/zh-CN/plugin.json +9 -0
  6. package/package.json +1 -1
  7. package/packages/builtin-tool-gtd/src/client/Streaming/CreatePlan/index.tsx +4 -19
  8. package/packages/builtin-tool-notebook/src/client/Inspector/CreateDocument/index.tsx +51 -0
  9. package/packages/builtin-tool-notebook/src/client/Inspector/index.ts +14 -0
  10. package/packages/builtin-tool-notebook/src/client/Placeholder/CreateDocument.tsx +101 -0
  11. package/packages/builtin-tool-notebook/src/client/Placeholder/index.ts +10 -0
  12. package/packages/builtin-tool-notebook/src/client/Render/CreateDocument/DocumentCard.tsx +63 -33
  13. package/packages/builtin-tool-notebook/src/client/Streaming/CreateDocument/index.tsx +75 -0
  14. package/packages/builtin-tool-notebook/src/client/Streaming/index.ts +14 -0
  15. package/packages/builtin-tool-notebook/src/client/components/AnimatedNumber.tsx +57 -0
  16. package/packages/builtin-tool-notebook/src/client/index.ts +12 -0
  17. package/packages/builtin-tool-notebook/src/systemRole.ts +2 -1
  18. package/packages/memory-user-memory/src/extractors/base.ts +8 -13
  19. package/packages/memory-user-memory/src/extractors/context.test.ts +2 -7
  20. package/packages/memory-user-memory/src/extractors/context.ts +7 -2
  21. package/packages/memory-user-memory/src/extractors/experience.test.ts +2 -10
  22. package/packages/memory-user-memory/src/extractors/experience.ts +7 -2
  23. package/packages/memory-user-memory/src/extractors/gatekeeper.test.ts +2 -7
  24. package/packages/memory-user-memory/src/extractors/gatekeeper.ts +3 -2
  25. package/packages/memory-user-memory/src/extractors/identity.test.ts +2 -7
  26. package/packages/memory-user-memory/src/extractors/identity.ts +7 -2
  27. package/packages/memory-user-memory/src/extractors/preference.test.ts +2 -10
  28. package/packages/memory-user-memory/src/extractors/preference.ts +7 -2
  29. package/packages/memory-user-memory/src/prompts/gatekeeper.ts +127 -0
  30. package/packages/memory-user-memory/src/prompts/index.ts +2 -0
  31. package/packages/memory-user-memory/src/prompts/layers/context.ts +155 -0
  32. package/packages/memory-user-memory/src/prompts/layers/experience.ts +162 -0
  33. package/packages/memory-user-memory/src/prompts/layers/identity.ts +219 -0
  34. package/packages/memory-user-memory/src/prompts/layers/index.ts +4 -0
  35. package/packages/memory-user-memory/src/prompts/layers/preference.ts +164 -0
  36. package/packages/memory-user-memory/src/services/extractExecutor.ts +0 -7
  37. package/packages/memory-user-memory/src/types.ts +0 -1
  38. package/src/app/[variants]/(main)/image/features/GenerationFeed/index.tsx +2 -2
  39. package/src/app/[variants]/(main)/image/features/ImageWorkspace/Content.tsx +1 -11
  40. package/src/app/[variants]/(main)/image/features/PromptInput/index.tsx +1 -7
  41. package/src/app/[variants]/(main)/image/index.tsx +2 -5
  42. package/src/components/Loading/BrandTextLoading/index.module.css +0 -1
  43. package/src/components/StreamingMarkdown/index.tsx +88 -0
  44. package/src/features/Conversation/Messages/AssistantGroup/Tool/Render/index.tsx +3 -5
  45. package/src/features/Conversation/Messages/AssistantGroup/Tool/index.tsx +14 -0
  46. package/src/features/PluginDevModal/PluginPreview/EmptyState.tsx +1 -1
  47. package/src/locales/default/plugin.ts +9 -0
  48. package/src/server/routers/async/image.ts +1 -1
  49. package/src/server/routers/lambda/image/index.test.ts +491 -0
  50. package/src/server/routers/lambda/{image.ts → image/index.ts} +57 -41
  51. package/src/server/routers/lambda/{__tests__/image.test.ts → image/utils.test.ts} +1 -21
  52. package/src/server/routers/lambda/image/utils.ts +24 -0
  53. package/src/server/services/file/__tests__/index.test.ts +3 -3
  54. package/src/server/services/file/impls/index.ts +4 -4
  55. package/src/server/services/file/impls/s3.test.ts +57 -39
  56. package/src/server/services/file/impls/s3.ts +29 -21
  57. package/src/server/services/file/impls/type.ts +1 -2
  58. package/src/server/services/file/index.ts +5 -3
  59. package/src/tools/inspectors.ts +2 -0
  60. package/src/tools/placeholders.ts +5 -0
  61. package/src/tools/streamings.ts +2 -0
  62. package/packages/memory-user-memory/src/prompts/gatekeeper.md +0 -125
  63. package/packages/memory-user-memory/src/prompts/layers/context.md +0 -153
  64. package/packages/memory-user-memory/src/prompts/layers/experience.md +0 -160
  65. package/packages/memory-user-memory/src/prompts/layers/identity.md +0 -217
  66. package/packages/memory-user-memory/src/prompts/layers/preference.md +0 -162
  67. package/packages/memory-user-memory/src/utils/path.ts +0 -5
  68. package/src/server/services/file/impls/utils.test.ts +0 -154
  69. package/src/server/services/file/impls/utils.ts +0 -17
@@ -1,14 +1,13 @@
1
1
  'use client';
2
2
 
3
3
  import { Flexbox } from '@lobehub/ui';
4
- import { Suspense, memo } from 'react';
4
+ import { memo } from 'react';
5
5
 
6
6
  import NavHeader from '@/features/NavHeader';
7
7
  import WideScreenContainer from '@/features/WideScreenContainer';
8
8
  import WideScreenButton from '@/features/WideScreenContainer/WideScreenButton';
9
9
 
10
10
  import ImageWorkspace from './features/ImageWorkspace';
11
- import SkeletonList from './features/ImageWorkspace/SkeletonList';
12
11
 
13
12
  const DesktopImagePage = memo(() => {
14
13
  return (
@@ -16,9 +15,7 @@ const DesktopImagePage = memo(() => {
16
15
  <NavHeader right={<WideScreenButton />} />
17
16
  <Flexbox height={'100%'} style={{ overflowY: 'auto', position: 'relative' }} width={'100%'}>
18
17
  <WideScreenContainer height={'100%'} wrapperStyle={{ height: '100%' }}>
19
- <Suspense fallback={<SkeletonList />}>
20
- <ImageWorkspace />
21
- </Suspense>
18
+ <ImageWorkspace />
22
19
  </WideScreenContainer>
23
20
  </Flexbox>
24
21
  </>
@@ -65,7 +65,6 @@
65
65
  align-items: center;
66
66
 
67
67
  padding: 2px 8px;
68
- border: 1px solid var(--brand-border-color);
69
68
  border-radius: 6px;
70
69
 
71
70
  background: var(--brand-tag-bg);
@@ -0,0 +1,88 @@
1
+ 'use client';
2
+
3
+ import { Markdown, ScrollShadow } from '@lobehub/ui';
4
+ import { createStaticStyles } from 'antd-style';
5
+ import { memo, useCallback, useEffect, useRef, useState } from 'react';
6
+
7
+ const styles = createStaticStyles(({ css }) => ({
8
+ container: css`
9
+ padding-block: 12px;
10
+ padding-inline: 16px;
11
+ border-radius: 8px;
12
+ font-size: 14px;
13
+ `,
14
+ }));
15
+
16
+ interface StreamingMarkdownProps {
17
+ children?: string;
18
+ maxHeight?: number;
19
+ }
20
+
21
+ const StreamingMarkdown = memo<StreamingMarkdownProps>(({ children, maxHeight = 400 }) => {
22
+ const containerRef = useRef<HTMLDivElement>(null);
23
+ const [userHasScrolled, setUserHasScrolled] = useState(false);
24
+ const isAutoScrollingRef = useRef(false);
25
+
26
+ // Handle user scroll detection
27
+ const handleScroll = useCallback(() => {
28
+ // Ignore scroll events triggered by auto-scroll
29
+ if (isAutoScrollingRef.current) return;
30
+
31
+ const container = containerRef.current;
32
+ if (!container) return;
33
+
34
+ // Check if user scrolled away from bottom
35
+ const distanceToBottom = container.scrollHeight - container.scrollTop - container.clientHeight;
36
+ const isAtBottom = distanceToBottom < 20;
37
+
38
+ // If user scrolled up, stop auto-scrolling
39
+ if (!isAtBottom) {
40
+ setUserHasScrolled(true);
41
+ }
42
+ }, []);
43
+
44
+ // Auto scroll to bottom when content changes (unless user has scrolled)
45
+ useEffect(() => {
46
+ if (userHasScrolled) return;
47
+
48
+ const container = containerRef.current;
49
+ if (!container) return;
50
+
51
+ isAutoScrollingRef.current = true;
52
+ requestAnimationFrame(() => {
53
+ container.scrollTop = container.scrollHeight;
54
+ // Reset the flag after scroll completes
55
+ requestAnimationFrame(() => {
56
+ isAutoScrollingRef.current = false;
57
+ });
58
+ });
59
+ }, [children, userHasScrolled]);
60
+
61
+ // Reset userHasScrolled when content is cleared (new stream starts)
62
+ useEffect(() => {
63
+ if (!children) {
64
+ setUserHasScrolled(false);
65
+ }
66
+ }, [children]);
67
+
68
+ if (!children) return null;
69
+
70
+ return (
71
+ <ScrollShadow
72
+ className={styles.container}
73
+ offset={12}
74
+ onScroll={handleScroll}
75
+ ref={containerRef}
76
+ size={12}
77
+ style={{ maxHeight }}
78
+ >
79
+ <Markdown animated style={{ overflow: 'unset' }} variant={'chat'}>
80
+ {children}
81
+ </Markdown>
82
+ </ScrollShadow>
83
+ );
84
+ });
85
+
86
+ StreamingMarkdown.displayName = 'StreamingMarkdown';
87
+
88
+ export default StreamingMarkdown;
@@ -1,4 +1,3 @@
1
- import { LOADING_FLAT } from '@lobechat/const';
2
1
  import { type ChatToolResult, type ToolIntervention } from '@lobechat/types';
3
2
  import { safeParsePartialJSON } from '@lobechat/utils';
4
3
  import { Flexbox } from '@lobehub/ui';
@@ -20,6 +19,7 @@ interface RenderProps {
20
19
  identifier: string;
21
20
  intervention?: ToolIntervention;
22
21
  isArgumentsStreaming?: boolean;
22
+ isToolCalling?: boolean;
23
23
  /**
24
24
  * ContentBlock ID (not the group message ID)
25
25
  */
@@ -52,6 +52,7 @@ const Render = memo<RenderProps>(
52
52
  intervention,
53
53
  toolMessageId,
54
54
  isArgumentsStreaming,
55
+ isToolCalling,
55
56
  }) => {
56
57
  if (toolMessageId && intervention?.status === 'pending') {
57
58
  return (
@@ -125,10 +126,7 @@ const Render = memo<RenderProps>(
125
126
  />
126
127
  );
127
128
 
128
- // Standalone plugins always have LOADING_FLAT as content
129
- const inPlaceholder = result.content === LOADING_FLAT && type !== 'standalone';
130
-
131
- if (inPlaceholder) return placeholder;
129
+ if (isToolCalling) return placeholder;
132
130
 
133
131
  return (
134
132
  <Suspense fallback={placeholder}>
@@ -1,9 +1,12 @@
1
+ import { LOADING_FLAT } from '@lobechat/const';
1
2
  import { type ChatToolResult, type ToolIntervention } from '@lobechat/types';
2
3
  import { AccordionItem, Flexbox, Skeleton } from '@lobehub/ui';
3
4
  import { Divider } from 'antd';
4
5
  import dynamic from 'next/dynamic';
5
6
  import { memo, useEffect, useState } from 'react';
6
7
 
8
+ import { useChatStore } from '@/store/chat';
9
+ import { operationSelectors } from '@/store/chat/slices/operation/selectors';
7
10
  import { useToolStore } from '@/store/tool';
8
11
  import { toolSelectors } from '@/store/tool/selectors';
9
12
  import { getBuiltinRender } from '@/tools/renders';
@@ -71,6 +74,16 @@ const Tool = memo<GroupToolProps>(
71
74
  const hasStreamingRenderer = !!getBuiltinStreaming(identifier, apiName);
72
75
  const forceShowStreamingRender = isArgumentsStreaming && hasStreamingRenderer;
73
76
 
77
+ // Get precise tool calling state from operation
78
+ const isToolCallingFromOperation = useChatStore(
79
+ operationSelectors.isMessageInToolCalling(assistantMessageId),
80
+ );
81
+
82
+ // Fallback: arguments completed but no final result yet
83
+ const isToolCallingFallback =
84
+ !isArgumentsStreaming && (!result || result.content === LOADING_FLAT || !result.content);
85
+ const isToolCalling = isToolCallingFromOperation || isToolCallingFallback;
86
+
74
87
  const hasCustomRender = !!getBuiltinRender(identifier, apiName);
75
88
 
76
89
  // Handle expand state changes with showPluginRender
@@ -138,6 +151,7 @@ const Tool = memo<GroupToolProps>(
138
151
  identifier={identifier}
139
152
  intervention={intervention}
140
153
  isArgumentsStreaming={isArgumentsStreaming}
154
+ isToolCalling={isToolCalling}
141
155
  messageId={assistantMessageId}
142
156
  result={result}
143
157
  setShowPluginRender={setShowPluginRender}
@@ -64,7 +64,7 @@ export default function PluginEmptyState() {
64
64
  {t('dev.preview.empty.title')}
65
65
  </Text>
66
66
  <Text className={styles.description}>{t('dev.preview.empty.desc')}</Text>
67
- <Space align="center" direction="vertical">
67
+ <Space align="center" orientation="vertical">
68
68
  <div className={styles.line} style={{ width: 128 }} />
69
69
  <div className={styles.line} style={{ width: 96 }} />
70
70
  <div className={styles.line} style={{ width: 48 }} />
@@ -93,6 +93,15 @@ export default {
93
93
  'builtins.lobe-local-system.inspector.rename.result':
94
94
  '<old>{{oldName}}</old> → <new>{{newName}}</new>',
95
95
  'builtins.lobe-local-system.title': 'Local System',
96
+ 'builtins.lobe-notebook.actions.copy': 'Copy',
97
+ 'builtins.lobe-notebook.actions.creating': 'Creating document...',
98
+ 'builtins.lobe-notebook.actions.edit': 'Edit',
99
+ 'builtins.lobe-notebook.actions.expand': 'Expand',
100
+ 'builtins.lobe-notebook.apiName.createDocument': 'Create document',
101
+ 'builtins.lobe-notebook.apiName.deleteDocument': 'Delete document',
102
+ 'builtins.lobe-notebook.apiName.getDocument': 'Get document',
103
+ 'builtins.lobe-notebook.apiName.updateDocument': 'Update document',
104
+ 'builtins.lobe-notebook.title': 'Notebook',
96
105
  'builtins.lobe-page-agent.apiName.batchUpdate': 'Batch update nodes',
97
106
  'builtins.lobe-page-agent.apiName.compareSnapshots': 'Compare snapshots',
98
107
  'builtins.lobe-page-agent.apiName.convertToList': 'Convert to list',
@@ -185,7 +185,7 @@ const categorizeError = (
185
185
  }
186
186
 
187
187
  return {
188
- errorMessage: error.message || AsyncTaskErrorType.ServerError,
188
+ errorMessage: error.message || error.error?.message || AsyncTaskErrorType.ServerError,
189
189
  errorType: AsyncTaskErrorType.ServerError,
190
190
  };
191
191
  };