| ๐ fix(agent-document): propagate sourceType and dedupe web crawls (#15088) | 2 ๅคฉๅ |
| ๐ fix(desktop): remote re-auth for batched tRPC and clean OIDC on disconnect (#13614)
* ๐ fix(desktop): remote re-auth for batched tRPC and clean OIDC on disconnect
- Notify authorization required when X-Auth-Required is set, not only on HTTP 401 (207 batch)
- Show AuthRequiredModal after remote config init; do not gate on dataSyncConfig.active
- Desktop: market 401 only silent refresh; avoid community sign-in UI (AuthRequiredModal handles cloud)
- Disconnect: clearRemoteServerConfig to wipe encrypted OIDC tokens
Made-with: Cursor
* ๐ Reset user-data Zustand stores on remote disconnect and sync refresh
- Add ResetableStoreAction helper and batched reset via userDataStores
- Wire reset into Electron remote disconnect and refreshUserData
- Handle refreshUserData failures in data sync SWR onSuccess
Made-with: Cursor
* ๐ fix(useUserAvatar): refactor desktop environment checks to use mockConstEnv
- Replace direct manipulation of mockIsDesktop with mockConstEnv.isDesktop for better encapsulation.
- Update all relevant test cases to utilize the new mock structure, ensuring consistent behavior across tests.
This change improves the clarity and maintainability of the test code.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ test: update mocks for ShikiLobeTheme and refactor session/agent mocks
- Added ShikiLobeTheme mock to ComfyUIForm and AddFilesToKnowledgeBase tests for consistent theming.
- Refactored session and agent mocks to use async imports, improving test isolation and performance.
This enhances the clarity and maintainability of the test suite.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com> | 1 ไธชๆๅ |
| โป๏ธ refactor: load models through model bank slot (#14877)
* โป๏ธ refactor: load models through model bank slot
* โป๏ธ refactor: remove static LobeHub model cards
* โป๏ธ refactor: share OpenAI image parameters
* ๐ fix: load async LobeHub model config in server paths
* ๐ fix: repair model bank CI follow-ups
* ๐ fix: avoid repeated model bank fallback loads
* ๐ fix: resolve business model config import in browser
* ๐ fix: align Nano Banana 2 resolution default
* โป๏ธ refactor: move model loader slot under client
* โ
test: move model bank aiModels spec out of build entries
* ๐ fix: use business model config for mixed provider parsing
* โป๏ธ refactor: consolidate model bank provider utilities
* ๐ fix: preserve Nano Banana 2 raw resolution
* ๐ fix: avoid generated locale sync for raw resolution
* ๐ style: add Nano Banana 2 resolution locales
* ๐ style: add online LobeHub model locales
* ๐ fix: guard optional model provider loaders
* ๐ fix: prevent sitemap build from hanging
* ๐ fix: clear sitemap timeout after model load | 3 ๅคฉๅ |
| ๐ style(brief-card): mute icon for resolved briefs on home page (#14452)
* ๐ style(brief-card): mute brief icon when brief is resolved
Resolved briefs now render the leading icon with muted gray colors instead
of the type's accent color, matching the existing "ๅทฒๆ ่ฎฐไธบๅทฒ่งฃๅณ" pill so the
card visually reads as inactive at a glance.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* โจ feat(page-agent): add custom Render for modifyNodes tool
Wires page-agent renders into the central registry and adds a per-operation
list view for modifyNodes (action icon, position chip, litexml preview, and
per-op success/error from pluginState.results), replacing the JSON fallback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* โจ feat(brief): set trigger='task' on briefs created from task lifecycle
Populate the existing `trigger` column on briefs emitted by the task
lifecycle (error, synthesized topic, auto-review pass/retry/force-pass)
and the heartbeat watchdog (workflow + tRPC), so consumers can filter
briefs by source module.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ๐ style(brief-card): show only the producing agent avatar
Stop fetching every agent in the task tree for brief cards. The stacked
Avatar.Group looked noisy for tasks with multiple subagents and didn't
convey ownership; render a single avatar for the agent that produced
the brief instead (`brief.agentId`).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> | 18 ๅคฉๅ |
| chore: clean up LOBE-XXX code annotations (#15135)
* chore: clean up LOBE-XXX annotations from codebase comments
- Remove ใLOBE-XXXใ bracket markers
- Remove LOBE-XXXX references from inline comments
- Clean up test descriptions containing LOBE identifiers
- Preserve linear.app URLs and code-level regex patterns
- Generated: 2026-05-23 02:30:09
* ๐ fix(tests): restore () in arrow callbacks broken by annotation cleanup
The LOBE-XXX annotation cleanup script over-matched `(LOBE-XXXX', () =>`
and stripped the callback `()`, leaving invalid syntax like
`describe(..., => {` and `it(..., async => {` across 24 test files.
This caused parse failures in Test Packages, Test Desktop App, Test
Database lint, and Test App shard runs. Restoring `()` / `async ()`
unblocks the suites while keeping the ticket-text cleanup intact.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ๐ fix(hintFormat-test): restore label + ellipsis in stripMarkdownLinks fixture
The annotation cleanup stripped `LOBE-8516` from a markdown-link's
*label* (`[LOBE-8516](/task/T-1)` โ `[](/task/T-1)`), which then survived
`stripMarkdownLinks` because the pattern requires non-empty link text โ
the test expected the link to disappear and asserted equality on a
LOBE-free output. The same line also lost a `.` from the trailing
`...` indicator in both input and expected strings.
Substitute a neutral Chinese label (`ๅๅธ่ฎกๅ`) so the link continues
to exercise the multi-link substitution path, and restore the full
`...` ellipsis.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Arvin Xu <arvinxx@lobehub.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> | 20 ๅฐๆถๅ |
| ๐ fix(desktop): remote re-auth for batched tRPC and clean OIDC on disconnect (#13614)
* ๐ fix(desktop): remote re-auth for batched tRPC and clean OIDC on disconnect
- Notify authorization required when X-Auth-Required is set, not only on HTTP 401 (207 batch)
- Show AuthRequiredModal after remote config init; do not gate on dataSyncConfig.active
- Desktop: market 401 only silent refresh; avoid community sign-in UI (AuthRequiredModal handles cloud)
- Disconnect: clearRemoteServerConfig to wipe encrypted OIDC tokens
Made-with: Cursor
* ๐ Reset user-data Zustand stores on remote disconnect and sync refresh
- Add ResetableStoreAction helper and batched reset via userDataStores
- Wire reset into Electron remote disconnect and refreshUserData
- Handle refreshUserData failures in data sync SWR onSuccess
Made-with: Cursor
* ๐ fix(useUserAvatar): refactor desktop environment checks to use mockConstEnv
- Replace direct manipulation of mockIsDesktop with mockConstEnv.isDesktop for better encapsulation.
- Update all relevant test cases to utilize the new mock structure, ensuring consistent behavior across tests.
This change improves the clarity and maintainability of the test code.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ test: update mocks for ShikiLobeTheme and refactor session/agent mocks
- Added ShikiLobeTheme mock to ComfyUIForm and AddFilesToKnowledgeBase tests for consistent theming.
- Refactored session and agent mocks to use async imports, improving test isolation and performance.
This enhances the clarity and maintainability of the test suite.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com> | 1 ไธชๆๅ |
| ๐ ๏ธ fix: unify SKILL.md frontmatter parsing and edit validation in agent documents (#14566) | 14 ๅคฉๅ |
| โป๏ธ refactor(desktop): unify TabBar registration into a cross-platform route-meta layer (#14995)
* โป๏ธ refactor(desktop): unify TabBar registration into a cross-platform route-meta layer
Replace the desktop TabBar plugin registry with route-co-located metadata.
Previously four parallel registries (the RecentlyViewed plugin registry,
routeMetadata.ts, getRouteById icons, and the router config) had to be kept
in sync by hand; forgetting to register a page made its tab silently break.
Now every route declares its metadata once via `handle.meta`:
- New `routeMeta.ts` declaration types + a cross-platform `<RouteMetaBridge>`
that resolves the active route's meta and drives `document.title`.
- Tab identity moves from semantic ids to normalized URLs (`TabItem`).
- Background-tab titles fall back through a guarded snapshot so cold-start
store-data gaps never blank or clobber a tab.
- Deletes the 11 plugins, the registry, usePluginContext, routeMetadata.ts
and cachedData.ts; `<PageTitle>` is removed from the (main) route tree.
* โจ feat(desktop): define route-meta title for task workspace routes
* โป๏ธ refactor(settings): create settingsRouteMeta for dynamic tab titles in settings
Signed-off-by: Innei <tukon479@gmail.com>
* โป๏ธ refactor(RouteMetaBridge): enhance dynamic route meta handling and state management
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ fix: scope route meta to tab url
* โป๏ธ refactor(PopupLayout): remove unused RouteMetaBridge component
Signed-off-by: Innei <tukon479@gmail.com>
* โป๏ธ refactor(route-meta): centralize web title updates
---------
Signed-off-by: Innei <tukon479@gmail.com> | 3 ๅคฉๅ |
| ๐ fix(desktop): remote re-auth for batched tRPC and clean OIDC on disconnect (#13614)
* ๐ fix(desktop): remote re-auth for batched tRPC and clean OIDC on disconnect
- Notify authorization required when X-Auth-Required is set, not only on HTTP 401 (207 batch)
- Show AuthRequiredModal after remote config init; do not gate on dataSyncConfig.active
- Desktop: market 401 only silent refresh; avoid community sign-in UI (AuthRequiredModal handles cloud)
- Disconnect: clearRemoteServerConfig to wipe encrypted OIDC tokens
Made-with: Cursor
* ๐ Reset user-data Zustand stores on remote disconnect and sync refresh
- Add ResetableStoreAction helper and batched reset via userDataStores
- Wire reset into Electron remote disconnect and refreshUserData
- Handle refreshUserData failures in data sync SWR onSuccess
Made-with: Cursor
* ๐ fix(useUserAvatar): refactor desktop environment checks to use mockConstEnv
- Replace direct manipulation of mockIsDesktop with mockConstEnv.isDesktop for better encapsulation.
- Update all relevant test cases to utilize the new mock structure, ensuring consistent behavior across tests.
This change improves the clarity and maintainability of the test code.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ test: update mocks for ShikiLobeTheme and refactor session/agent mocks
- Added ShikiLobeTheme mock to ComfyUIForm and AddFilesToKnowledgeBase tests for consistent theming.
- Refactored session and agent mocks to use async imports, improving test isolation and performance.
This enhances the clarity and maintainability of the test suite.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com> | 1 ไธชๆๅ |
| ๐ fix(document): reject unsupported file parser types (#14966) | 4 ๅคฉๅ |
| โจ feat(follow-up): extend follow-up chip suggestions to general chat (#15101)
* โจ feat(follow-up): add foundation types for chat follow-up chips
- FollowUpExtractInput.threadId for portal thread isolation
- UserSystemAgentConfig.followUpAction (global enable + model)
- LobeAgentChatConfig.enableFollowUpChips (per-agent opt-in)
- ConversationHooks.onAssistantTurnSettled first-class member
- Remove dead onGenerationStart/Complete/Cancelled hooks
- DEFAULT_SYSTEM_AGENT_CONFIG.followUpAction off by default
- DEFAULT_AGENT_CHAT_CONFIG.enableFollowUpChips false default
* โป๏ธ refactor(follow-up): key follow-up store by conversation for concurrency
- Convert useFollowUpActionStore from single-slot to slots map
- conversationKey = messageMapKey(agentId, topicId, threadId?) for parity with chat store
- contextSelectors.conversationKey exposes the key from ConversationProvider
- FollowUpChips and ChatItem consume conversationKey
- Onboarding hook adopts the new keyed API
- Pass threadId through to extract (server filter lands in T3)
* ๐ fix(follow-up): address T2 code review feedback
- Restore design-intent comments for 20s timeout and race guard
- Remove dead pendingMessageId field from FollowUpActionSlot
- Remove unused slotFor selector
- Trim chipsFor / FollowUpActionSlot JSDoc to design intent only
- Gate useOnboardingFollowUp against missing onboardingAgentId
- removeSlot uses destructure; slotStatus uses ?? for falsy safety
* โจ feat(follow-up): filter extract by threadId for portal thread isolation
- FollowUpActionService.extract honours optional threadId
- threadId provided โ eq(messages.threadId, threadId)
- threadId absent โ isNull(messages.threadId) so main topic never surfaces thread replies
- Tests cover both branches
* โจ feat(conversation): emit onAssistantTurnSettled hook from provider
- AssistantTurnSettledWatcher fires hooks.onAssistantTurnSettled(messageId, { reason }) once per turn
- Reason derived from the most recent terminal Operation for the message id
- Reason mapping: cancelled โ stopped, type=regenerate โ regenerated, type=continue โ continued, else โ completed
- Settlement gated on idle + no pending tool intervention (mirrors Onboarding's logic)
- Tests cover all four reason branches + intervention gating + no double-fire + fallback log
- Onboarding bespoke prop untouched (migrates in T6)
* ๐ fix(conversation): scope settlement reason to turn-level operations
- TURN_LEVEL_TYPES filter excludes child sub-ops (callLLM, executeToolCall, etc.) before sorting by endTime
- Prevents successful regenerate/continue being misreported as 'completed' when a child finishes after the parent
- Tests cover parent/child ordering for all reason branches
* โจ feat(follow-up): add useChatFollowUp hook and wire chat mount sites
- New mergeConversationHooks composes multiple hooks with boolean short-circuit
- useChatFollowUp computes effective enable (global ร per-agent ร valid model)
- Registers onBeforeSendMessage/Continue/Regenerate to clear slot and onAssistantTurnSettled to extract
- Mount sites: agent route ConversationArea, FloatingChatPanel, Portal Thread Chat (last in chain per ยง4.6)
- Skips on reason='stopped'; skips when effective is false
- Group chat intentionally not mounted
* โป๏ธ refactor(onboarding): migrate settlement to ConversationHooks first-class
- Drop bespoke onAssistantTurnSettled prop and duplicate useEffect from AgentOnboardingConversation
- useOnboardingFollowUp returns ConversationHooks { onBeforeSendMessage, onAssistantTurnSettled }
- Split settlement work: context-sync + builtin refresh runs first, chip extract runs after
- Phase snapshot captured at memoize time preserves original prevPhase semantics
- Settlement detection now lives solely in AssistantTurnSettledWatcher
* โจ feat(settings): add Follow-up suggestions controls (global + per-agent)
- Global System Agent page: new Follow-up Suggestions panel (model picker + enable toggle)
- Per-agent chat controls: enableFollowUpChips toggle with hint when global not configured
- i18n keys: setting.systemAgent.followUpAction.*, setting.settingChat.enableFollowUpChips.*
- Hint surfaces when user toggles per-agent ON but global is disabled/unmodeled
* ๐ง chore(follow-up): T8 โ scoped lint cleanup and comment discipline pass
* ๐ fix(follow-up): align conversationKey selector with callsite + wrap single hook
- contextSelectors.conversationKey forwards full context (scope/isNew/groupId/subAgentId) so portal-thread NEW state matches callsite-computed keys
- ConversationArea wraps chat-follow-up via mergeConversationHooks for spec ยง4.6 ordering robustness
- Both per final-review Important concerns
* โ
test(settings): update follow-up defaults snapshots
* โจ feat(follow-up): surface model in service-model page + default to mini
- Add followUpAction to /service-model OPTIONAL_FEATURE_ITEMS so model/provider and enable Switch render alongside inputCompletion and promptRewrite
- Seed DEFAULT_FOLLOW_UP_ACTION_SYSTEM_AGENT_ITEM with DEFAULT_MINI model/provider so out-of-box config has a valid model; users only need to flip enabled
- Sync settings selector snapshot | 1 ๅคฉๅ |
| โป๏ธ refactor(agent-settings): consolidate Chat tab into Params popover, drop dead auto-topic feature (#14885)
* ๐ฅ chore(agent-config): drop dead enableAutoCreateTopic feature
Drop enableAutoCreateTopic + autoCreateTopicThreshold end-to-end. No
business code consumed these fields anymore โ only types, defaults,
locale copy, UI form items, agent-builder LLM prompts, and test
fixtures kept the dead config alive.
Sweep:
- types & zod schema (LobeAgentChatConfig, AgentChatConfigSchema, openapi)
- DEFAULT_AGENT_CHAT_CONFIG constant
- locale keys in default + 18 translations
- agent-builder system prompts & tool manifests
- AgentChat form items (auto-topic switch + threshold slider)
- test fixtures & integration tests (replaced sample boolean key in
parser tests with enableHistoryCount)
- docs/self-hosting env-var examples
- settings.test snapshot
dataImporter JSON fixtures keep the legacy keys on purpose โ they
simulate historical user exports and the zod schema strips unknowns.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* โจ feat(chat-input): move inputTemplate + autoScroll into Params popover
Surface the User Input Preprocessing template (inputTemplate) and
Auto-scroll During AI Response toggle (enableAutoScrollOnStreaming) in
the chat-input Params popover, alongside compression / history /
max_tokens. Drop the matching form items from AgentChat โ the popover
is now the single entry point for these two agent-level preferences.
ControlRow's action prop becomes optional so inputTemplate can render
as a label + TextArea without a Switch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ๐ฅ refactor(agent-settings): drop AgentChat tab in favor of Params popover
Remove the now-redundant Chat Preferences tab from agent settings:
- delete src/features/AgentSetting/AgentChat/
- drop ChatSettingsTabs.Chat enum and its three registrations
(useCategory, AgentSettingsContent, profile Content)
- drop agentTab.chat locale key in default + 18 translations
- drop MessagesSquare / MessagesSquareIcon imports that became unused
History/compression/auto-scroll/inputTemplate already live in the
chat-input Params popover, so this tab carried no unique
functionality.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* โจ feat(chat-input): surface enableStreaming + reasoning_effort + disabledParams in Params popover
Bring the Model tab's controls into the chat-input Params popover so the
popover can become the single entry point for agent-level params.
- enableStreaming Switch at the top of Advanced (treats undefined as on,
matching `chatConfig.enableStreaming !== false` in chat service)
- reasoning_effort row after max_tokens (Select tied to
chatConfig.enableReasoningEffort / params.reasoning_effort, matching
the agentConfigResolver gating)
- per-model disabledParams filter on the 4 sampling sliders (e.g. Claude
Opus 4.7 hides temperature/top_p), via aiModelSelectors.modelDisabledParams
- max_tokens defaults to 4096 on toggle-on (parity with AgentModal),
matching the AgentModal UX
- drop the !enableAgentMode gate on Advanced so agent-mode users still
reach the model params once the Model tab is gone
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ๐ฅ refactor(agent-settings): drop AgentModal tab in favor of Params popover
Now that the chat-input Params popover surfaces enableStreaming,
reasoning_effort, the 4 sampling params (model-aware via
disabledParams), and max_tokens, the Model Settings tab carries no
unique behavior. Remove it:
- delete src/features/AgentSetting/AgentModal/ (index + ModelSelect)
- drop ChatSettingsTabs.Modal enum and its three registrations
(useCategory, AgentSettingsContent, profile Content)
- drop agentTab.modal locale key in default + 18 translations
- drop BrainCog / BrainIcon imports that became unused
- simplify the profile Content inbox-default fallback to Opening
(Content menu no longer carried Modal at all)
settingModel.* locale keys are kept โ Controls still reads them.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ๐ fix(chat-input): keep !enableAgentMode gate on Advanced sampling params
Walk back the gate removal from the prior commit. Agent mode is meant
to manage temperature / top_p / penalties / reasoning_effort itself;
exposing user overrides there contradicts the design.
- Move enableStreaming out of Advanced into the common section so it
stays visible in both modes (streaming is a UI behavior, not a
sampling param).
- Re-wrap the SectionHeader + sampling sliders + max_tokens +
reasoning_effort with `{!enableAgentMode && (...)}`, restoring the
prior visibility rule.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> | 4 ๅคฉๅ |
| โป๏ธ refactor(store): class-based Zustand actions with flattenActions (#13383)
โป๏ธ refactor(store): migrate slices to class actions with flattenActions
- Video store: generationConfig/Topic/Batch/createVideo as *ActionImpl; aggregate with flattenActions
- Eval store: benchmark/dataset/run/testCase as classes; top-level flattenActions
- Tool agentSkills: AgentSkillsActionImpl + Pick typing
- groupProfile: flattenActions around ActionImpl instead of spreading instance
- agentGroup: wrap chatGroupAction with flattenActions for consistent aggregation
Made-with: Cursor | 1 ไธชๆๅ |
| ๐ fix(agent-builder): open builder panel after prompt creation (#14978) | 4 ๅคฉๅ |
| ๐ fix: preserve Gemini image diagnostics (#15120) | 1 ๅคฉๅ |
| ๐ fix(desktop): remote re-auth for batched tRPC and clean OIDC on disconnect (#13614)
* ๐ fix(desktop): remote re-auth for batched tRPC and clean OIDC on disconnect
- Notify authorization required when X-Auth-Required is set, not only on HTTP 401 (207 batch)
- Show AuthRequiredModal after remote config init; do not gate on dataSyncConfig.active
- Desktop: market 401 only silent refresh; avoid community sign-in UI (AuthRequiredModal handles cloud)
- Disconnect: clearRemoteServerConfig to wipe encrypted OIDC tokens
Made-with: Cursor
* ๐ Reset user-data Zustand stores on remote disconnect and sync refresh
- Add ResetableStoreAction helper and batched reset via userDataStores
- Wire reset into Electron remote disconnect and refreshUserData
- Handle refreshUserData failures in data sync SWR onSuccess
Made-with: Cursor
* ๐ fix(useUserAvatar): refactor desktop environment checks to use mockConstEnv
- Replace direct manipulation of mockIsDesktop with mockConstEnv.isDesktop for better encapsulation.
- Update all relevant test cases to utilize the new mock structure, ensuring consistent behavior across tests.
This change improves the clarity and maintainability of the test code.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ test: update mocks for ShikiLobeTheme and refactor session/agent mocks
- Added ShikiLobeTheme mock to ComfyUIForm and AddFilesToKnowledgeBase tests for consistent theming.
- Refactored session and agent mocks to use async imports, improving test isolation and performance.
This enhances the clarity and maintainability of the test suite.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com> | 1 ไธชๆๅ |
| ๐ fix(desktop): remote re-auth for batched tRPC and clean OIDC on disconnect (#13614)
* ๐ fix(desktop): remote re-auth for batched tRPC and clean OIDC on disconnect
- Notify authorization required when X-Auth-Required is set, not only on HTTP 401 (207 batch)
- Show AuthRequiredModal after remote config init; do not gate on dataSyncConfig.active
- Desktop: market 401 only silent refresh; avoid community sign-in UI (AuthRequiredModal handles cloud)
- Disconnect: clearRemoteServerConfig to wipe encrypted OIDC tokens
Made-with: Cursor
* ๐ Reset user-data Zustand stores on remote disconnect and sync refresh
- Add ResetableStoreAction helper and batched reset via userDataStores
- Wire reset into Electron remote disconnect and refreshUserData
- Handle refreshUserData failures in data sync SWR onSuccess
Made-with: Cursor
* ๐ fix(useUserAvatar): refactor desktop environment checks to use mockConstEnv
- Replace direct manipulation of mockIsDesktop with mockConstEnv.isDesktop for better encapsulation.
- Update all relevant test cases to utilize the new mock structure, ensuring consistent behavior across tests.
This change improves the clarity and maintainability of the test code.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ test: update mocks for ShikiLobeTheme and refactor session/agent mocks
- Added ShikiLobeTheme mock to ComfyUIForm and AddFilesToKnowledgeBase tests for consistent theming.
- Refactored session and agent mocks to use async imports, improving test isolation and performance.
This enhances the clarity and maintainability of the test suite.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com> | 1 ไธชๆๅ |
| ๐ fix(conversation): preserve mention runtime context (#13223)
* ๐ fix(conversation): preserve mention context on retry
* ๐ fix(runtime): preserve initial payload for mention context
* โจ feat(store): expose Zustand stores on window.__LOBE_STORES in dev
Made-with: Cursor | 1 ไธชๆๅ |
| โจ feat(agent): add floating chat panel and workspace improvements (#13887)
* โจ feat(FloatingChatPanel): add single-instance mount guard
* โจ feat(FloatingChatPanel): add inner ChatBody layout
* โจ feat(FloatingChatPanel): add reusable floating conversation panel
* โ
test(FloatingChatPanel): add props wiring smoke tests
* Refactor agent topic and page routes
* Restore topic page routing for floating chat panel
* โจ feat(FloatingChatPanel): enhance ChatBody and TopicItem for improved routing and styling
- Updated ChatBody to maintain scroll ownership while hiding overflow.
- Refactored TopicItem to correctly highlight active topics based on routing context.
- Added tests for TopicItem to ensure correct active state behavior.
- Introduced static styles for FloatingChatPanel to manage layout overflow.
Signed-off-by: Innei <tukon479@gmail.com>
* chore: help to merge & rebase
* chore: align merge with canary โ drop pkg.pr.new ui, adopt canary useMenu, remove NotebookButton
* โจ feat: add ViewSwitcher component and update localization for chat views
- Introduced a new ViewSwitcher component to toggle between chat, page, and task views in the conversation header.
- Updated English and Chinese localization files to include new labels for the view switcher options.
- Refactored the conversation header to integrate the ViewSwitcher, enhancing the user interface for better navigation.
Signed-off-by: Innei <tukon479@gmail.com>
* fix: update @lobehub/ui to version 5.9.1 and refactor FloatingChatPanel to use FloatingSheet component
- Updated the @lobehub/ui dependency in package.json to version 5.9.1.
- Refactored FloatingChatPanel to utilize the new FloatingSheet component, enhancing its layout and state management.
- Introduced a new ChatLayout component for better organization of chat-related UI elements.
- Adjusted routing configuration to incorporate the new ChatLayout for agent chat pages.
Signed-off-by: Innei <tukon479@gmail.com>
* feat: add TopicCanvas and TitleSection components for topic management
- Introduced TopicCanvas component to serve as a document canvas for topics, integrating an editor and title section.
- Added TitleSection component for managing topic titles and emojis, enhancing user interaction with a dedicated UI.
- Updated FloatingChatPanel to accommodate the new TopicCanvas, ensuring a cohesive layout in the topic page.
- Enhanced tests to verify the integration of TopicCanvas within the topic page route.
Signed-off-by: Innei <tukon479@gmail.com>
* โจ feat(agent-page): bind documentId to URL and introduce HeaderSlot
- Add nested /agent/:aid/:topicId/page/:docId route with PageRedirect for bare /page
- Introduce useAutoCreateTopicDocument with module-level inflight de-dup
- Lift Portal + WorkingSidebar to (chat) layout; keep ChatHeader in left column
- Sidebar document clicks on page route navigate to /page/:docId instead of opening Portal
- Add HeaderSlot (context + createPortal) as a reusable header injection point
- Mount AutoSaveHint via HeaderSlot; register Files hotkey scope in TopicCanvas so Cmd+S triggers manual save
- Sync desktopRouter.config.tsx and desktopRouter.config.desktop.tsx
- Extend RecentlyViewed plugin to round-trip optional docId segment
* Use topic titles for auto-created page documents
* Add page-agent init gating and runtime diagnostics
* Support current-topic agent documents
* Implement Active Topic Document and Disabled Tool Call Filtering
- Introduced ActiveTopicDocumentContextInjector to inject context for active topic documents into user messages.
- Added DisabledToolCallFilter to remove historical tool calls for disabled tools in the current runtime scope.
- Updated MessagesEngine to utilize the new context injectors and filters.
- Enhanced tests to verify the correct injection of active topic document context and filtering of disabled tool calls.
This update improves the handling of document editing contexts and tool management in the conversation flow.
Signed-off-by: Innei <tukon479@gmail.com>
* feat: enhance agent document management with LiteXML operations
- Updated API names for clarity, changing 'patchDocument' to 'modifyNodes'.
- Introduced LiteXML operation schema for document modifications.
- Implemented new mutation for modifying document nodes via LiteXML.
- Enhanced document retrieval methods to support format options (XML, Markdown, Both).
- Added support for editor data snapshots and normalization of diff nodes.
- Improved document history management to handle editor data with diff nodes.
- Created tests for new features and ensured existing functionality remains intact.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ fix: apply agent document xml edits directly
* Refine document cache invalidation and editor hydration
* ๐ fix: stabilize agent topic hydration
* fix: update @lobehub/editor dependency version and clean up test mocks
Signed-off-by: Innei <tukon479@gmail.com>
* Potential fix for pull request finding 'Useless assignment to local variable'
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
* ๐ fix(document): preserve pending diff nodes through save path
Skip normalizeEditorDataDiffNodes on every autosave so diff nodes awaiting
user review survive persistence. Normalization now runs only on explicit
Accept/Reject via DiffAllToolbar. Also flip headless litexml ops to delay:true
to match the new review flow.
* ๐ fix(agent): detect agent sub-route from URL params not cached topic
isInAgentSubRoute used routeTopicId (with activeTopicId fallback) as its
base path. On /agent/:aid/profile with a cached activeTopicId, the base
became /agent/:aid/:cachedTopicId which pathname cannot startsWith, so
sub-route detection returned false and sidebar topic clicks only called
switchTopic without routing back to chat โ users stayed stuck on profile.
Derive the sub-route base from params.topicId directly so stale store
state cannot mask the check. routeTopicId export keeps the fallback for
sidebar highlighting.
* ๐ fix(page): repair topic page document recovery
* ๐ fix(page-agent): block tool calls when page editor is not mounted
scope is topic-bound not route-bound, so navigating from /agent/.../Page
to /agent/... keeps scope==='page' and PageAgentIdentifier stayed in the
injected plugin list. The LLM could still call initPage / modifyNodes /
etc. against a stale editor reference, returning misleading success
(e.g. nodeCount=0).
Two layers of guard:
- PageAgentExecutor wraps `invoke` and returns a structured
PAGE_EDITOR_NOT_MOUNTED / kind: 'replan' result when the runtime
editor is not mounted, pointing the LLM at lobe-agent-documents.
- streamingExecutor drops PageAgentIdentifier from the tool set via
the new `composeEnabledTools` pipeline when scope==='page' and
the page-agent runtime is not ready.
Also extract the tool-set composition (inject merge + runtime drops)
out of the ~320-line internal_createAgentState into
`mecha/toolSetComposer`, with unit tests.
* ๐ fix(chat): unify message stream for /agent/:topicId and /page/:docId
Before this change a page-scoped conversation (FloatingChatPanel with
scope='page' in the /Page route) partitioned the client message store by
scope, so /agent/:topicId and /agent/:topicId/page/:docId each built their
own messagesMap slot and SWR cache โ but the TRPC getMessages endpoint
ignores scope and returned the same messages for both, producing duplicate
fetches and a visible message-history split between the two surfaces.
Fixes by keeping scope='page' as a capability/surfacing marker only:
- messageMapKey: collapse 'page' to the default scope early in
toMessageMapContext, so threadId/groupId still win and only the
main/page pair actually unifies.
- useFetchMessages: build the SWR key from identity fields
(agentId, groupId, threadId, topicId) instead of the full
ConversationContext, so scope no longer partitions the cache.
agentConfigResolver/streamingExecutor/composeEnabledTools still read
scope='page' from operation.context for PageAgent injection and
initialContext.pageEditor wiring โ the capability layer is unchanged.
Also fix two pre-existing test regressions surfaced by re-running the
impacted suites:
- streamingExecutor page-editor initialContext test now mocks
pageAgentRuntime.isReady() (required since the PageAgent editor-ready
guard landed).
- FloatingChatPanel default shell props test updated to match the
[180,320,520,800] snap points introduced in 62dc91e444.
* โป๏ธ refactor(FloatingChatPanel): read main slot without changing scope
Revert the global messageMapKey/SWR-key changes from b650cdc9d7 โ the
global collapse over-reached and coupled message routing to scope in
ways other surfaces don't want. Instead, specialize only the place that
actually has the dual-role problem.
`scope` should be a capability marker (PageAgent tool + pageEditor
initialContext injection), not a message-list partition. Floating panel
on /agent/:topicId/page is the only caller that sets scope='page', and
its message list should mirror /agent/:topicId โ the surfaces share a
topic.
Local collapse in FloatingChatPanel: compute chatKey with
`scope === 'page' ? 'main' : scope`, so messagesMap is read from the
main slot. The downstream ConversationContext keeps scope='page' for
the capability layer; only the slot lookup is specialized.
Kept from b650cdc9d7 (unrelated to the revert):
- streamingExecutor test mocks pageAgentRuntime.isReady() โ required
by the PageAgent editor-ready guard in 01ef7bc142.
- FloatingChatPanel snap-points test matches [180,320,520,800] from
62dc91e444.
* ๐ fix(FloatingChatPanel): simplify chat key computation for message retrieval
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ fix(index.desktop.test): update LocationProbe to reflect route changes and improve test accuracy
Signed-off-by: Innei <tukon479@gmail.com>
* Constrain agent header title under centered switcher
* ๐ Fix conversation header view switcher layout
* ๐ Fix agent topic path links and cmdk context
* ๐ fix(test): align document history fixtures and layout ui mock
* ๐ fix(e2e): support dialog-based topic rename
* โป๏ธ refactor(debug): use scoped debuggers for PR logging
---------
Signed-off-by: Innei <tukon479@gmail.com>
Co-authored-by: Neko Ayaka <neko@ayaka.moe>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> | 29 ๅคฉๅ |
| ๐ fix(editor-runtime): add mutation handlers for post-save synchronization (#14469)
* ๐ fix(editor-runtime): add afterMutateHandler for post-mutation synchronization
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ fix(editor-runtime): enhance beforeMutateHandler with context and add meaningful content check
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ fix(editor-runtime): improve data source validation and streamline command dispatch logic
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ fix(editor-runtime): add test for Page Agent editTitle behavior without sending content or editorData
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ fix(editor-runtime): update LiteXML node extraction to include attributes and improve error logging
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ fix: use namespace import for GeneralChatAgent to fix vi.spyOn in tests
vi.spyOn on a module namespace object requires the production code to
access the class through the same namespace. Destructured imports capture
a direct binding that bypasses the spy, causing "Class constructor
GeneralChatAgent cannot be invoked without 'new'" in tests.
* ๐ fix: replace vi.spyOn on class constructor with vi.mock for GeneralChatAgent
vi.spyOn wraps a class with a plain function that loses [[Construct]]
semantics in ESM, causing "Class constructor GeneralChatAgent cannot be
invoked without 'new'". Replace with vi.mock + hoisted mock constructor
that properly tracks calls while preserving new-ability.
---------
Signed-off-by: Innei <tukon479@gmail.com> | 17 ๅคฉๅ |
| โจ feat(devtools): add dev-only feature flag override panel (#14565)
Add a client-side feature flag override panel that lives behind a
floating button in dev builds. Overrides are persisted to localStorage
and merged into useServerConfigStore.featureFlags so existing flag
consumers see the toggled value without any callsite changes.
The panel is gated by NODE_ENV plus a localStorage opt-in
(LOBE_DEV_FEATURE_FLAG_PANEL_ENABLED = "1"); prod builds tree-shake
the entire feature. | 11 ๅคฉๅ |
| โป๏ธ refactor: createAgent uses `agentModel.create` directly (#13871)
* โป๏ธ refactor: createAgent uses agentModel.create directly
The createAgent router was still going through sessionModel.create,
which is a legacy path that doesn't pass all agent fields (like
agencyConfig) to the agents table. Switch to agentModel.create
which directly inserts into the agents table with full field support.
- Add CreateAgentSchema in types package for proper input validation
- Remove dependency on insertAgentSchema from database package
- Remove sessionId from CreateAgentResult
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ๐ท๏ธ chore: mark session-based agent creation as deprecated
Add @deprecated JSDoc tags to the legacy session-based agent creation
path (session router, SessionService, SessionModel.create, session store,
insertAgentSchema). New code should use agent.createAgent / agentModel.create
directly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ๐ fix: honor groupId when creating agents
Pass input.groupId as sessionGroupId to agentModel.create so that
agents created from a sidebar folder are correctly assigned to that group.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ๐ fix: resolve type errors from createAgent refactor
- Remove sessionId fallback in AddAgent.tsx and ForkAndChat.tsx
- Use z.custom<T>() for agencyConfig and tts in CreateAgentSchema
to match agentModel.create parameter types
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> | 1 ไธชๆๅ |
| chore: clean up LOBE-XXX code annotations (#15135)
* chore: clean up LOBE-XXX annotations from codebase comments
- Remove ใLOBE-XXXใ bracket markers
- Remove LOBE-XXXX references from inline comments
- Clean up test descriptions containing LOBE identifiers
- Preserve linear.app URLs and code-level regex patterns
- Generated: 2026-05-23 02:30:09
* ๐ fix(tests): restore () in arrow callbacks broken by annotation cleanup
The LOBE-XXX annotation cleanup script over-matched `(LOBE-XXXX', () =>`
and stripped the callback `()`, leaving invalid syntax like
`describe(..., => {` and `it(..., async => {` across 24 test files.
This caused parse failures in Test Packages, Test Desktop App, Test
Database lint, and Test App shard runs. Restoring `()` / `async ()`
unblocks the suites while keeping the ticket-text cleanup intact.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ๐ fix(hintFormat-test): restore label + ellipsis in stripMarkdownLinks fixture
The annotation cleanup stripped `LOBE-8516` from a markdown-link's
*label* (`[LOBE-8516](/task/T-1)` โ `[](/task/T-1)`), which then survived
`stripMarkdownLinks` because the pattern requires non-empty link text โ
the test expected the link to disappear and asserted equality on a
LOBE-free output. The same line also lost a `.` from the trailing
`...` indicator in both input and expected strings.
Substitute a neutral Chinese label (`ๅๅธ่ฎกๅ`) so the link continues
to exercise the multi-link substitution path, and restore the full
`...` ellipsis.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Arvin Xu <arvinxx@lobehub.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> | 20 ๅฐๆถๅ |
| ๐ chore: translate non-English comments to English in agent-skills-identifiers (#15137)
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> | 1 ๅคฉๅ |
| โป๏ธ refactor(resource): tree store for library hierarchy and move sync (#13640)
* โจ feat(ResourceManager): integrate tree store for folder management and enhance file operations
- Added `useTreeStore` to manage folder structure and state, replacing previous file store dependencies.
- Updated `EmptyPlaceholder` to utilize `currentFolderId` for file uploads.
- Refactored `MoveToFolderModal` to use tree store for moving items, improving folder navigation.
- Enhanced drag-and-drop functionality in `DndContextWrapper` to support moving items between folders.
- Removed obsolete `LibraryHierarchy` state management, streamlining folder operations.
- Improved file renaming and deletion processes to ensure tree state consistency.
This update enhances the overall file management experience by leveraging a dedicated tree store for better performance and maintainability.
Signed-off-by: Innei <tukon479@gmail.com>
* โจ feat(TreeAction): enhance resource movement and update handling
- Updated mutation logic for moving resources to differentiate between items visible in the Explorer and those not visible, improving performance and user experience.
- Added refresh functionality for the file list after resource updates (move, update, delete) to ensure the Explorer reflects the latest state.
- Refactored mutation methods to use async/await for better readability and error handling.
This update streamlines resource management within the tree structure, ensuring a more responsive and consistent user interface.
Signed-off-by: Innei <tukon479@gmail.com>
* Fix file updates and tree move fallback regressions
---------
Signed-off-by: Innei <tukon479@gmail.com> | 1 ไธชๆๅ |
| โจ feat(follow-up): extend follow-up chip suggestions to general chat (#15101)
* โจ feat(follow-up): add foundation types for chat follow-up chips
- FollowUpExtractInput.threadId for portal thread isolation
- UserSystemAgentConfig.followUpAction (global enable + model)
- LobeAgentChatConfig.enableFollowUpChips (per-agent opt-in)
- ConversationHooks.onAssistantTurnSettled first-class member
- Remove dead onGenerationStart/Complete/Cancelled hooks
- DEFAULT_SYSTEM_AGENT_CONFIG.followUpAction off by default
- DEFAULT_AGENT_CHAT_CONFIG.enableFollowUpChips false default
* โป๏ธ refactor(follow-up): key follow-up store by conversation for concurrency
- Convert useFollowUpActionStore from single-slot to slots map
- conversationKey = messageMapKey(agentId, topicId, threadId?) for parity with chat store
- contextSelectors.conversationKey exposes the key from ConversationProvider
- FollowUpChips and ChatItem consume conversationKey
- Onboarding hook adopts the new keyed API
- Pass threadId through to extract (server filter lands in T3)
* ๐ fix(follow-up): address T2 code review feedback
- Restore design-intent comments for 20s timeout and race guard
- Remove dead pendingMessageId field from FollowUpActionSlot
- Remove unused slotFor selector
- Trim chipsFor / FollowUpActionSlot JSDoc to design intent only
- Gate useOnboardingFollowUp against missing onboardingAgentId
- removeSlot uses destructure; slotStatus uses ?? for falsy safety
* โจ feat(follow-up): filter extract by threadId for portal thread isolation
- FollowUpActionService.extract honours optional threadId
- threadId provided โ eq(messages.threadId, threadId)
- threadId absent โ isNull(messages.threadId) so main topic never surfaces thread replies
- Tests cover both branches
* โจ feat(conversation): emit onAssistantTurnSettled hook from provider
- AssistantTurnSettledWatcher fires hooks.onAssistantTurnSettled(messageId, { reason }) once per turn
- Reason derived from the most recent terminal Operation for the message id
- Reason mapping: cancelled โ stopped, type=regenerate โ regenerated, type=continue โ continued, else โ completed
- Settlement gated on idle + no pending tool intervention (mirrors Onboarding's logic)
- Tests cover all four reason branches + intervention gating + no double-fire + fallback log
- Onboarding bespoke prop untouched (migrates in T6)
* ๐ fix(conversation): scope settlement reason to turn-level operations
- TURN_LEVEL_TYPES filter excludes child sub-ops (callLLM, executeToolCall, etc.) before sorting by endTime
- Prevents successful regenerate/continue being misreported as 'completed' when a child finishes after the parent
- Tests cover parent/child ordering for all reason branches
* โจ feat(follow-up): add useChatFollowUp hook and wire chat mount sites
- New mergeConversationHooks composes multiple hooks with boolean short-circuit
- useChatFollowUp computes effective enable (global ร per-agent ร valid model)
- Registers onBeforeSendMessage/Continue/Regenerate to clear slot and onAssistantTurnSettled to extract
- Mount sites: agent route ConversationArea, FloatingChatPanel, Portal Thread Chat (last in chain per ยง4.6)
- Skips on reason='stopped'; skips when effective is false
- Group chat intentionally not mounted
* โป๏ธ refactor(onboarding): migrate settlement to ConversationHooks first-class
- Drop bespoke onAssistantTurnSettled prop and duplicate useEffect from AgentOnboardingConversation
- useOnboardingFollowUp returns ConversationHooks { onBeforeSendMessage, onAssistantTurnSettled }
- Split settlement work: context-sync + builtin refresh runs first, chip extract runs after
- Phase snapshot captured at memoize time preserves original prevPhase semantics
- Settlement detection now lives solely in AssistantTurnSettledWatcher
* โจ feat(settings): add Follow-up suggestions controls (global + per-agent)
- Global System Agent page: new Follow-up Suggestions panel (model picker + enable toggle)
- Per-agent chat controls: enableFollowUpChips toggle with hint when global not configured
- i18n keys: setting.systemAgent.followUpAction.*, setting.settingChat.enableFollowUpChips.*
- Hint surfaces when user toggles per-agent ON but global is disabled/unmodeled
* ๐ง chore(follow-up): T8 โ scoped lint cleanup and comment discipline pass
* ๐ fix(follow-up): align conversationKey selector with callsite + wrap single hook
- contextSelectors.conversationKey forwards full context (scope/isNew/groupId/subAgentId) so portal-thread NEW state matches callsite-computed keys
- ConversationArea wraps chat-follow-up via mergeConversationHooks for spec ยง4.6 ordering robustness
- Both per final-review Important concerns
* โ
test(settings): update follow-up defaults snapshots
* โจ feat(follow-up): surface model in service-model page + default to mini
- Add followUpAction to /service-model OPTIONAL_FEATURE_ITEMS so model/provider and enable Switch render alongside inputCompletion and promptRewrite
- Seed DEFAULT_FOLLOW_UP_ACTION_SYSTEM_AGENT_ITEM with DEFAULT_MINI model/provider so out-of-box config has a valid model; users only need to flip enabled
- Sync settings selector snapshot | 1 ๅคฉๅ |
| ๐ fix(desktop): remote re-auth for batched tRPC and clean OIDC on disconnect (#13614)
* ๐ fix(desktop): remote re-auth for batched tRPC and clean OIDC on disconnect
- Notify authorization required when X-Auth-Required is set, not only on HTTP 401 (207 batch)
- Show AuthRequiredModal after remote config init; do not gate on dataSyncConfig.active
- Desktop: market 401 only silent refresh; avoid community sign-in UI (AuthRequiredModal handles cloud)
- Disconnect: clearRemoteServerConfig to wipe encrypted OIDC tokens
Made-with: Cursor
* ๐ Reset user-data Zustand stores on remote disconnect and sync refresh
- Add ResetableStoreAction helper and batched reset via userDataStores
- Wire reset into Electron remote disconnect and refreshUserData
- Handle refreshUserData failures in data sync SWR onSuccess
Made-with: Cursor
* ๐ fix(useUserAvatar): refactor desktop environment checks to use mockConstEnv
- Replace direct manipulation of mockIsDesktop with mockConstEnv.isDesktop for better encapsulation.
- Update all relevant test cases to utilize the new mock structure, ensuring consistent behavior across tests.
This change improves the clarity and maintainability of the test code.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ test: update mocks for ShikiLobeTheme and refactor session/agent mocks
- Added ShikiLobeTheme mock to ComfyUIForm and AddFilesToKnowledgeBase tests for consistent theming.
- Refactored session and agent mocks to use async imports, improving test isolation and performance.
This enhances the clarity and maintainability of the test suite.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com> | 1 ไธชๆๅ |
| โจ chore(heterogeneous-agent): integrate heterogeneous agents with claude code (#13754)
* โป๏ธ refactor(acp): move agent provider to agencyConfig + restore creation entry
- Move AgentProviderConfig from chatConfig to agencyConfig.heterogeneousProvider
- Rename type from 'acp' to 'claudecode' for clarity
- Restore Claude Code agent creation entry in sidebar + menu
- Prioritize heterogeneousProvider check over gateway mode in execution flow
- Remove ACP settings from AgentChat form (provider is set at creation time)
- Add getAgencyConfigById selector for cleaner access
- Use existing agent workingDirectory instead of duplicating in provider config
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
โจ feat(acp): defer terminal events + extract model/usage per turn
Three improvements to ACP stream handling:
1. Defer agent_runtime_end/error: Previously the adapter emitted terminal
events from result.type directly into the Gateway handler. The handler
immediately fires fetchAndReplaceMessages which reads stale DB state
(before we persist final content/tools). Fix: intercept terminal events
in the executor's event loop and forward them only AFTER content +
metadata has been written to DB.
2. Extract model/usage per assistant event: Claude Code sets model name
and token usage on every assistant event. Adapter now emits a
'step_complete' event with phase='turn_metadata' carrying these.
Executor accumulates input/output/cache tokens across turns and
persists them onto the assistant message (model + metadata.totalTokens).
3. Missing final text fix: The accumulated assistant text was being
written AFTER agent_runtime_end triggered fetchAndReplaceMessages,
so the UI rendered stale (empty) content. Deferred terminals solve this.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
๐ fix(acp): eliminate orphan-tool warning flicker during streaming
Root cause:
LobeHub's conversation-flow parser (collectToolMessages) filters tool
messages by matching `tool_call_id` against `assistant.tools[].id`. The
previous flow created tool messages FIRST, then updated assistant.tools[],
which opened a brief window where the UI saw tool messages that had no
matching entry in the parent's tools array โ rendering them as "orphan"
with a scary "่ฏทๅ ้ค" warning to the user.
Fix:
Reorder persistNewToolCalls into three phases:
1. Pre-register tool entries in assistant.tools[] (id only, no result_msg_id)
2. Create the tool messages in DB (tool_call_id matches pre-registered ids)
3. Back-fill result_msg_id and re-write assistant.tools[]
Between phase 1 and phase 3 the UI always sees consistent state: every
tool message in DB has a matching entry in the parent's tools array.
Verified: orphan count stays at 0 across all sampled timepoints during
streaming (vs 1+ before fix).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
๐ fix(acp): dedupe tool_use + capture tool_result + persist result_msg_id
Three critical fixes to ACP tool-call handling, discovered via live testing:
1. **tool_use dedupe** โ Claude Code stream-json previously produced 15+
duplicate tool messages per tool_call_id. The adapter now tracks emitted
ids so each tool_use โ exactly one tool message.
2. **tool_result content capture** โ tool_result blocks live in
`type: 'user'` events in Claude Code's stream-json, not in assistant
events. The adapter now handles the 'user' event type and emits a new
`tool_result` HeterogeneousAgentEvent which the executor consumes to
call messageService.updateToolMessage() with the actual result content.
Previously all tool messages had empty content.
3. **result_msg_id on assistant.tools[]** โ LobeHub's parse() step links
tool messages to their parent assistant turn via tools[].result_msg_id.
Without it, the UI renders orphan-message warnings. The executor now
captures the tool message id returned by messageService.createMessage
and writes it back into the assistant.tools[] JSONB.
Also adds vitest config + 9 unit tests for the adapter covering lifecycle,
content mapping, and tool_result handling.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
โจ feat(acp): integrate external AI agents via ACP protocol
Adds support for connecting external AI agents (Claude Code and future
agents like Codex, Kimi CLI) into LobeHub Desktop via a new heterogeneous
agent layer that adapts agent-specific protocols to the unified Gateway
event stream.
Architecture:
- New @lobechat/heterogeneous-agents package: pluggable adapters that
convert agent-specific outputs to AgentStreamEvent
- AcpCtr (Electron main): agent-agnostic process manager with CLI
presets registry, broadcasts raw stdout lines to renderer
- acpExecutor (renderer): subscribes to broadcasts, runs events through
adapter, feeds into existing createGatewayEventHandler
- Tool call persistence: creates role='tool' messages via messageService
before emitting tool_start/tool_end to the handler
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* โป๏ธ refactor: rename acpExecutor to heterogeneousAgentExecutor
- Rename file acpExecutor.ts โ heterogeneousAgentExecutor.ts
- Rename ACPExecutorParams โ HeterogeneousAgentExecutorParams
- Rename executeACPAgent โ executeHeterogeneousAgent
- Change operation type from execAgentRuntime to execHeterogeneousAgent
- Change operation label to "Heterogeneous Agent Execution"
- Change error type from ACPError to HeterogeneousAgentError
- Rename acpData/acpContext variables to heteroData/heteroContext
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* โป๏ธ refactor: rename AcpCtr and acp service to heterogeneousAgent
Desktop side:
- AcpCtr.ts โ HeterogeneousAgentCtr.ts
- groupName 'acp' โ 'heterogeneousAgent'
- IPC channels: acpRawLine โ heteroAgentRawLine, etc.
Renderer side:
- services/electron/acp.ts โ heterogeneousAgent.ts
- ACPService โ HeterogeneousAgentService
- acpService โ heterogeneousAgentService
- Update all IPC channel references in executor
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ๐ง chore: switch CC permission mode to bypassPermissions
Use bypassPermissions to allow Bash and other tool execution.
Previously acceptEdits only allowed file edits, causing Bash tool
calls to fail during CC execution.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ๐ fix: don't fallback activeAgentId to empty string in AgentIdSync
Empty string '' causes chat store to have a truthy but invalid
activeAgentId, breaking message routing. Pass undefined instead.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ๐ fix: use AI_RUNTIME_OPERATION_TYPES for loading and cancel states
stopGenerateMessage and cancelOperation were hardcoding
['execAgentRuntime', 'execServerAgentRuntime'], missing
execHeterogeneousAgent. This caused:
- CC execution couldn't be cancelled via stop button
- isAborting flag wasn't set for heterogeneous agent operations
Now uses AI_RUNTIME_OPERATION_TYPES constant everywhere to ensure
all AI runtime operation types are handled consistently.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* โจ feat: split multi-step CC execution into separate assistant messages
Claude Code's multi-turn execution (thinking โ tool โ final text) was
accumulating everything onto a single assistant message, causing the
final text response to appear inside the tool call message.
Changes:
- ClaudeCodeAdapter: detect message.id changes and emit stream_end +
stream_start with newStep flag at step boundaries
- heterogeneousAgentExecutor: on newStep stream_start, persist previous
step's content, create a new assistant message, reset accumulators,
and forward the new message ID to the gateway handler
This ensures each LLM turn gets its own assistant message, matching
how Gateway mode handles multi-step agent execution.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ๐ fix: fix multi-step CC execution and add DB persistence tests
Adapter fixes:
- Fix false step boundary on first assistant after init (ghost empty message)
Executor fixes:
- Fix parentId chain: new-step assistant points to last tool message
- Fix content contamination: sync snapshot of content accumulators on step boundary
- Fix type errors (import path, ChatToolPayload casts, sessionId guard)
Tests:
- Add ClaudeCodeAdapter unit tests (multi-step, usage, flush, edge cases)
- Add ClaudeCodeAdapter E2E test (full multi-step session simulation)
- Add registry tests
- Add executor DB persistence tests covering:
- Tool 3-phase write (pre-register โ create โ backfill)
- Tool result content + error persistence
- Multi-step parentId chain (assistant โ tool โ assistant)
- Final content/reasoning/model/usage writes
- Sync snapshot preventing cross-step contamination
- Error handling with partial content persistence
- Full multi-step E2E (Read โ Write โ text)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ๐ง chore: add orphan tool regression tests and debug trace
- Add orphan tool regression tests for multi-turn tool execution
- Add __HETERO_AGENT_TRACE debug instrumentation for event flow capture
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* โจ feat: support image attachments in CC via stream-json stdin
- Main process downloads files by ID from cloud (GET {domain}/f/{fileId})
- Local disk cache at lobehub-storage/heteroAgent/files/ (by fileId)
- When fileIds present, switches to --input-format stream-json + stdin pipe
- Constructs user message with text + image content blocks (base64)
- Pass fileIds through executor โ service โ IPC โ controller
Closes LOBE-7254
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* โป๏ธ refactor: pass imageList instead of fileIds for CC vision support
- Use imageList (with url) instead of fileIds โ Main downloads from URL directly
- Cache by image id at lobehub-storage/heteroAgent/files/
- Only images (not arbitrary files) are sent to CC via stream-json stdin
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ๐ fix: read imageList from persisted DB message instead of chatUploadFileList
chatUploadFileList is cleared after sendMessageInServer, so tempImages
was empty by the time the executor ran. Now reads imageList from the
persisted user message in heteroData.messages instead.
Also removes debug console.log/console.error statements.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* update i18n
* ๐ fix: prevent orphan tool UI by deferring handler events during step transition
Root cause: when a CC step boundary occurs, the adapter produces
[stream_end, stream_start(newStep), stream_chunk(tools_calling)] in one batch.
The executor deferred stream_start via persistQueue but forwarded stream_chunk
synchronously โ handler received tools_calling BEFORE stream_start, dispatching
tools to the OLD assistant message โ UI showed orphan tool warning.
Fix: add pendingStepTransition flag that defers ALL handler-bound events through
persistQueue until stream_start is forwarded, guaranteeing correct event ordering.
Also adds:
- Minimal regression test in gatewayEventHandler confirming correct ordering
- Multi-tool per turn regression test from real LOBE-7240 trace
- Data-driven regression replaying 133 real CC events from regression.json
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* โจ feat: add lab toggle for heterogeneous agent (Claude Code)
- Add enableHeterogeneousAgent to UserLabSchema + defaults (off by default)
- Add selector + settings UI toggle (desktop only)
- Gate "Claude Code Agent" sidebar menu item behind the lab setting
- Remove regression.json (no longer needed)
- Add i18n keys for the lab feature
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ๐ fix: gate heterogeneous agent execution behind isDesktop check
Without this, web users with an agent that has heterogeneousProvider
config would hit the CC execution path and fail (no Electron IPC).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* โป๏ธ refactor: rename tool identifier from acp-agent to claude-code
Also update operation label to "External agent running".
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* โจ feat: add CLI agent detectors for system tools settings
Detect agentic coding CLIs installed on the system:
- Claude Code, Codex, Gemini CLI, Qwen Code, Kimi CLI, Aider
- Uses validated detection (which + --version keyword matching)
- New "CLI Agents" category in System Tools settings
- i18n for en-US and zh-CN
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ๐ fix: fix token usage over-counting in CC execution
Two bugs fixed:
1. Adapter: same message.id emitted duplicate step_complete(turn_metadata)
for each content block (thinking/text/tool_use) โ all carry identical
usage. Now deduped by message.id, only emits once per turn.
2. Executor: CC result event contains authoritative session-wide usage
totals but was ignored. Now adapter emits step_complete(result_usage)
from the result event, executor uses it to override accumulated values.
Fixes LOBE-7261
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ๐ง chore: gitignore cc-stream.json and .heterogeneous-tracing/
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ๐ง chore: untrack .heerogeneous-tracing/
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* โจ feat: wire CC session resume for multi-turn conversations
Reads `ccSessionId` from topic metadata and passes it as `resumeSessionId`
into the heterogeneous-agent executor, which forwards it into the Electron
main-process controller. `sendPrompt` then appends `--resume <id>` so the
next turn continues the same Claude Code session instead of starting fresh.
After each run, the CC init-event session_id (captured by the adapter) is
persisted back onto the topic so the chain survives page reloads.
Also stops killing the session in `finally` โ it needs to stay alive for
subsequent turns; cleanup happens on topic deletion or app quit.
* ๐ fix: record cache token breakdown in CC execution metadata
The prior token-usage fix only wrote totals โ `inputCachedTokens`,
`inputWriteCacheTokens` and `inputCacheMissTokens` were dropped, so the
pricing card rendered zero cached/write-cache tokens even though CC had
reported them. Map the accumulated Anthropic-shape usage to the same
breakdown the anthropic usage converter emits, so CC turns display
consistently with Gateway turns.
Refs LOBE-7261
* โป๏ธ refactor: write CC usage under metadata.usage instead of flat fields
Flat `inputCachedTokens / totalInputTokens / ...` on `MessageMetadata` are
the legacy shape; new code should put usage under `metadata.usage`. Move
the CC executor to the nested shape so it matches the convention the rest
of the runtime is migrating to.
Refs LOBE-7261
* โป๏ธ refactor(types): mark flat usage fields on MessageMetadata as deprecated
Stop extending `ModelUsage` and redeclare each token field inline with a
`@deprecated` JSDoc pointing to `metadata.usage` (nested). Existing readers
still type-check, but IDEs now surface the deprecation so writers migrate
to the nested shape.
* โป๏ธ refactor(types): mark flat performance fields on MessageMetadata as deprecated
Stop extending `ModelPerformance` and redeclare `duration` / `latency` /
`tps` / `ttft` inline with `@deprecated`, pointing at `metadata.performance`.
Mirrors the same treatment just done for the token usage fields.
* โจ feat: CC agent gets claude avatar + lands on chat page directly
Skip the shared createAgent hook's /profile redirect for the Claude Code
variant โ its config is fixed so the profile editor would be noise โ and
preseed the Claude avatar from @lobehub/icons-static-avatar so new CC
agents aren't blank.
* ๐ fix(conversation-flow): read usage/performance from nested metadata
`splitMetadata` only scraped the legacy flat token/perf fields, so messages
written under the new canonical shape (`metadata.usage`, `metadata.performance`)
never populated `UIChatMessage.usage` and the Extras panel rendered blank.
- Prefer nested `metadata.usage` / `metadata.performance` when present; keep
flat scraping as fallback for pre-migration rows.
- Add `usage` / `performance` to FlatListBuilder's filter sets so the nested
blobs don't leak into `otherMetadata`.
- Drop the stale `usage! || metadata` fallback in the Assistant / CouncilMember
Extra renders โ with splitMetadata fixed, `item.usage` is always populated
when usage data exists, and passing raw metadata as ModelUsage is wrong now
that the flat fields are gone.
* ๐ fix: skip stores.reset on initial dataSyncConfig hydration
`useDataSyncConfig`'s SWR onSuccess called `refreshUserData` (which runs
`stores.reset()`) whenever the freshly-fetched config didn't deep-equal the
hard-coded initial `{ storageMode: 'cloud' }` โ which happens on every
first load. The reset would wipe `chat.activeAgentId` just after
`AgentIdSync` set it from the URL, and because `AgentIdSync`'s sync
effects are keyed on `params.aid` (which hasn't changed), they never re-fire
to restore it. Result: topic SWR saw `activeAgentId === ''`, treated the
container as invalid, and left the sidebar stuck on the loading skeleton.
Gate the reset on `isInitRemoteServerConfig` so it only runs when the user
actually switches sync modes, not on the first hydration.
* โจ feat(claude-code): wire Inspector layer for CC tool calls
Mirrors local-system: each CC tool now has an inspector rendered above the
tool-call output instead of an opaque default row.
- `Inspector.tsx` โ registry that passes the CC tool name itself as the
shared factories' `translationKey`. react-i18next's missing-key fallback
surfaces the literal name (Bash / Edit / Glob / Grep / Read / Write), so
we don't add CC-specific entries to the plugin locale.
- `ReadInspector.tsx` / `WriteInspector.tsx` โ thin adapters that map
Anthropic-native args (`file_path` / `offset` / `limit`) onto the shared
inspectors' shape (`path` / `startLine` / `endLine`), so shared stays
pure. Bash / Edit / Glob / Grep reuse shared factories directly.
- Register `ClaudeCodeInspectors` under `claude-code` in the builtin-tools
inspector dispatch.
Also drops the redundant `Render/Bash/index.tsx` wrapper and pipes the
shared `RunCommandRender` straight into the registry.
* โป๏ธ refactor: use agentSelectors.isCurrentAgentHeterogeneous
Two callsites (ConversationArea / useActionsBarConfig) were reaching into
`currentAgentConfig(...)?.agencyConfig?.heterogeneousProvider` inline.
Switch them to the existing `isCurrentAgentHeterogeneous` selector so the
predicate lives in one place.
* update
* โป๏ธ refactor: drop no-op useCallback wrapper in AgentChat form
`handleFinish` just called `updateConfig(values)` with no extra logic; the
zustand action is already a stable reference so the wrapper added no
memoization value. Leftover from the ACP refactor (930ba41fe3) where the
handler once did more work โ hand the action straight to `onFinish`.
* update
* โช revert: roll back conversation-flow nested-shape reads
Unwind the `splitMetadata` nested-preference + `FlatListBuilder` filter
additions from 306fd6561f. The nested `metadata.usage` / `metadata.performance`
promotion now happens in `parse.ts` (and a `?? metadata?.usage` fallback at
the UI callsites), so conversation-flow's transformer layer goes back to
its original flat-field-only behavior.
* update
* ๐ fix(cc): wire Stop to cancel the external Claude Code process
Previously hitting Stop only flipped the `execHeterogeneousAgent` operation
to `cancelled` in the store โ the spawned `claude -p` process kept
running and kept streaming/persisting output for the user. The op's abort
signal had no listeners and no `onCancelHandler` was registered.
- On session start, register an `onCancelHandler` that calls
`heterogeneousAgentService.cancelSession(sessionId)` (SIGINT to the CLI).
- Read the op's `abortController.signal` and short-circuit `onRawLine` so
late events the CLI emits between SIGINT and exit don't leak into DB
writes.
- Skip the error-event forward in `onError` / the outer catch when the
abort came from the user, so the UI doesn't surface a misleading error
toast on top of the already-cancelled operation.
Verified end-to-end: prompt that runs a long sequence of Reads โ click
Stop โ `claude -p` process is gone within 2s, op status = cancelled, no
error message written to the conversation.
* โจ feat(sidebar): mark heterogeneous agents with an "External" tag
Pipes the agent's `agencyConfig.heterogeneousProvider.type` through the
sidebar data flow and renders a `<Tag>` next to the title for any agent
driven by an external CLI runtime (Claude Code today, more later). Mirrors
the group-member External pattern so future provider types just need a
label swap โ the field is a string, not a boolean.
- `SidebarAgentItem.heterogeneousType?: string | null` on the shared type
- `HomeRepository.getSidebarAgentList` selects `agents.agencyConfig` and
derives the field via `cleanObject`
- `AgentItem` shows `<Tag>{t('group.profile.external')}</Tag>` when the
field is present
Verified client-side by injecting `heterogeneousType: 'claudecode'` into
a sidebar item at runtime โ the "ๅค้จ" tag renders next to the title in
the zh-CN locale.
* โป๏ธ refactor(i18n): dedicated key for the sidebar external-agent tag
Instead of reusing `group.profile.external` (which is about group members
that are user-linked rather than virtual), add `agentSidebar.externalTag`
specifically for the heterogeneous-runtime tag. Keeps the two concepts
separate so we can swap this one to "Claude Code" / provider-specific
labels later without touching the group UI copy.
Remember to run `pnpm i18n` before the PR so the remaining locales pick
up the new key.
* ๐ fix: clear remaining CI type errors
Three small fixes so `tsgo --noEmit` exits clean:
- `AgentIdSync`: `useChatStoreUpdater` is typed off the chat-store key, whose
`activeAgentId` is `string` (initial ''). Coerce the optional URL param to
`''` so the store key type matches; `createStoreUpdater` still skips the
setState when the value is undefined-ish.
- `heterogeneousAgentExecutor.test.ts`: `scope: 'session'` isn't a valid
`MessageMapScope` (the union dropped that variant); switch the fixture to
`'main'`, which is the correct scope for agent main conversations.
- Same test file: `Array.at(-1)` is `T | undefined`; non-null assert since
the preceding calls guarantee the slot is populated.
* ๐ fix: loosen createStoreUpdater signature to accept nullable values
Upstream `createStoreUpdater` types `value` as exactly `T[Key]`, so any
call site feeding an optional source (URL param, selector that may return
undefined) fails type-check โ even though the runtime already guards
`typeof value !== 'undefined'` and no-ops in that case.
Wrap it once in `store/utils/createStoreUpdater.ts` with a `T[Key] | null
| undefined` value type so callers can pass `params.aid` directly, instead
of the lossy `?? ''` fallback the previous commit used (which would have
written an empty-string sentinel into the chat store).
Swap the import in `AgentIdSync.tsx`.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> | 1 ไธชๆๅ |
| โป๏ธ refactor: load models through model bank slot (#14877)
* โป๏ธ refactor: load models through model bank slot
* โป๏ธ refactor: remove static LobeHub model cards
* โป๏ธ refactor: share OpenAI image parameters
* ๐ fix: load async LobeHub model config in server paths
* ๐ fix: repair model bank CI follow-ups
* ๐ fix: avoid repeated model bank fallback loads
* ๐ fix: resolve business model config import in browser
* ๐ fix: align Nano Banana 2 resolution default
* โป๏ธ refactor: move model loader slot under client
* โ
test: move model bank aiModels spec out of build entries
* ๐ fix: use business model config for mixed provider parsing
* โป๏ธ refactor: consolidate model bank provider utilities
* ๐ fix: preserve Nano Banana 2 raw resolution
* ๐ fix: avoid generated locale sync for raw resolution
* ๐ style: add Nano Banana 2 resolution locales
* ๐ style: add online LobeHub model locales
* ๐ fix: guard optional model provider loaders
* ๐ fix: prevent sitemap build from hanging
* ๐ fix: clear sitemap timeout after model load | 3 ๅคฉๅ |
| โป๏ธ refactor: migrate AI Rules to Claude Code Skills (#11737)
โป๏ธ refactor: migrate AI Rules to Claude Code Skills system
Migrate all AI Rules from .cursor/rules/ to .agents/skills/ directory:
- Move 23 skills to .agents/skills/ (main directory)
- Update symlinks: .claude/skills, .cursor/skills, .codex/skills
- Create project-overview skill from project documentation
- Add references/ subdirectories for complex skills
- Remove LobeChat references from skill descriptions
- Delete obsolete .cursor/rules/ and .claude/commands/prompts/ directories
Skills structure enables better portability and maintainability across AI tools. | 3 ไธชๆๅ |
| โป๏ธ refactor(store): migrate to class-based actions with flattenActions (#12081)
* โจ feat(store): introduce StoreSetter interface and refactor agent group actions
- Added StoreSetter interface to manage state updates in a more flexible manner.
- Refactored ChatGroupInternalAction, ChatGroupCurdAction, and ChatGroupMemberAction to utilize the new StoreSetter for state management.
- Enhanced action methods to improve clarity and maintainability.
- Introduced createActionProxy utility to streamline action handling across slices.
- Updated lifecycle and member slices to align with the new structure, ensuring consistent state management practices.
Signed-off-by: Innei <tukon479@gmail.com>
* refactor squash
refactor: replace createActionProxy with flattenActions for action handling
- Updated multiple store files to utilize flattenActions instead of createActionProxy, improving the handling of action methods and ensuring proper prototype method binding.
- Removed createActionProxy utility as it is no longer needed, streamlining the action management process across the application.
This change enhances maintainability and consistency in state management practices.
Signed-off-by: Innei <tukon479@gmail.com>
chore: format code
Signed-off-by: Innei <tukon479@gmail.com>
fix: correct assignment syntax in GroupChatSupervisor and ResourceSyncEngine
- Updated assignment syntax from object-like notation to standard assignment for error handling and state updates in GroupChatSupervisor and ResourceSyncEngine classes.
- Ensured proper variable assignments for error handling and state management, enhancing code clarity and functionality.
Signed-off-by: Innei <tukon479@gmail.com>
fix: update transformApiArgumentsToAiState return type and logic
- Changed the return type of transformApiArgumentsToAiState from Promise<string> to Promise<string | undefined> to better reflect possible outcomes.
- Modified the return statement to return undefined instead of an empty string when the builtinToolLoading for the given key is true, improving clarity in the function's behavior.
Signed-off-by: Innei <tukon479@gmail.com>
* feat(upload): enhance uploadBase64FileWithProgress return type and add dimensions
- Introduced a new interface, UploadWithProgressResult, to define the structure of the result returned by uploadBase64FileWithProgress.
- Updated the return type of uploadBase64FileWithProgress and uploadFileWithProgress methods to reflect the new interface, improving type safety and clarity.
- This change allows for better handling of image dimensions and file metadata during the upload process.
Signed-off-by: Innei <tukon479@gmail.com>
* refactor(zustand): migrate to class-based actions and enhance action composition
- Updated the implementation of actions from plain StateCreator objects to class-based actions, improving encapsulation and maintainability.
- Introduced a new pattern for defining actions using private fields to prevent internal state leakage.
- Replaced createActionProxy with flattenActions for better method binding and prototype support in action handling.
- Enhanced the structure for multi-class slices, allowing for cleaner composition of actions within store files.
This refactor streamlines state management practices and improves code clarity across the application.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
| 3 ไธชๆๅ |