文件最后提交记录最后更新时间
🐛 fix: return bad request for malformed auth JSON (#15038)3 天前
🐛 fix: hetero agent cloud credential alert flash and width misalignment (#15056) 🐛 fix: hetero agent alert flash and width misalignment - Treat `isCredsLoading` as configured in `useHeteroAgentCloudConfig` so the "cloud credentials required" alert is hidden during the initial query, preventing the flash-then-disappear effect when credentials are already set up. - Wrap the alert in `WideScreenContainer` in `HeterogeneousChatInput` so its width and centering match the chat input below it. Co-authored-by: LobeHub Bot <bot@lobehub.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>2 天前
✨ feat(analytics): track onboarding step events (#15133)1 天前
✨ feat: Agent Task System available (#14540) * 🔥 chore: remove agent_task feature flag and graduate task feature Drop the agent_task / enableAgentTask gate that was guarding the agent task rollout. The feature is now permanently enabled, so all flag checks, disabled-state redirects, and disabled-only fallback UI (SuggestQuestions, CommunityAgents) are removed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🐛 fix(brief): create regular task instead of cron job from template card The "Add task" button on DailyBrief recommendation cards was creating an agentCronJob (scheduled recurring job). Switch to taskService.create via the createTask store action so it creates a one-off inbox task and refreshes the task list, matching user expectation that the click adds a task rather than a schedule. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat(task): support schedule fields on task.create The brief recommendation card needs to create a recurring scheduled task in one shot (template carries `cronPattern`). Extend `task.create` to accept `automationMode`, `schedulePattern`, `scheduleTimezone`, and thread them through the service + store action. The model already accepts these via NewTask, and the central schedule-dispatch sweep picks the task up once status is dispatchable. TaskTemplateCard now creates a schedule-mode task with the template's cron pattern and the user's local timezone, restoring the recurring behavior previously provided by AgentCronJob. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 i18n(home): shorten brief.title from "Daily brief" to "Brief" Daily-frequency tasks are no longer the only source feeding the section (scheduled, manual, and on-demand briefs all flow through it now), so the more general label fits better. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style(task-list): show skeleton instead of blank while task list loads Both the list view (TaskList) and kanban view (KanbanBoard / KanbanColumn) returned null until isInit, leaving the page empty during the first SWR fetch. Render a TaskItemSkeleton (default + compact variants) to keep the layout stable and signal that data is loading. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style(git-status): toggle review panel on diff-stat click Clicking the diff-stat chip used to always open the review panel — if the panel was already showing review, the click was a no-op. Switch to a toggle: clicking again with the review tab active closes the panel, matching the implicit expectation that the chip is the entry/exit control for that view. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✅ test(brief): update TaskTemplateCard test for createTask flow Card now calls useTaskStore.createTask with schedule fields instead of agentCronJobService.create. Replace the agentCronJob service mock with a useTaskStore mock exposing createTask, and assert the schedule-mode payload (automationMode + schedulePattern + scheduleTimezone) on the success path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style(brief): jump to task detail after creating from template The success toast asked users to look in the inbox agent for the new scheduled task; navigating directly to the task detail is a clearer landing for what they just confirmed. Drop the toast and route to `/task/<identifier>` once createTask resolves. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>14 天前
✨ feat: set OSS default model to DeepSeek V4 Pro (#14555)14 天前
🐛 fix(web-crawler): support Jina CN domains (#14916) Co-authored-by: AnotiaWang <AnotiaWang@users.noreply.github.com>1 天前
✨ feat: per-call llm_generation_tracing observability (#15124) * ✨ feat(database): add llm_generation_tracing schema + tracing package (LOBE-9462) Foundation layer for per-call observability of `generateObject` calls. - New Drizzle table `llm_generation_tracing` with identity / context / model / result / usage / storage / feedback / audit columns and full single-column index coverage (Postgres bitmap-scan friendly). Migration 0103 is idempotent (CREATE TABLE/INDEX IF NOT EXISTS) for safe re-runs. - `LlmGenerationTracingModel` with `record` / `updateFeedback` / `findById` / `listRecent`, all userId-scoped to prevent cross-user leaks. - New package `@lobechat/llm-generation-tracing` mirroring agent-tracing's shape: `ITracingStore` interface, `FileTracingStore` (local/dev, scenario subfolders + latest.json symlink), `computePromptHash` (6-char sha256 of systemPrompt + schema), and `TRACING_SCENARIO_REGISTRY` + `resolveScenario` with explicit scenario override. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ✨ feat(model-runtime): wire llm_generation_tracing into ModelRuntime.generateObject (LOBE-9462) Per-call interception layer — one hook covers all generateObject callers. - New `onGenerateObjectComplete` hook on `ModelRuntimeHooks`: always fires (success or failure) with latency, usage, output/error. Fixes the gap where `onGenerateObjectFinal` only fires when the runtime invokes `onUsage`. - `S3TracingStore` (zstd level 3, key `llm-generation-tracing/{scenario}/{v}-{hash}/{date}/{id}.json.zst`) and `LLMGenerationTracingService` that does DB insert → store.save → patch storage_key. Store failures preserve the row with `metadata.store_error`. - `createLLMGenerationTracingHook` + `mergeModelRuntimeHooks` wired into `initModelRuntimeFromDB`; tracing runs alongside business (billing) hooks via `next/server.after()` when available, microtask fallback otherwise. Unknown metadata keys (e.g. `parent_memory_trace_key`) pass through. - Memory extractor accepts `parentMemoryTraceKey` option for the job-level backlink. Follow-up-action caller given an explicit `scenario: 'follow_up'` metadata override — it was the only OSS caller missing trigger metadata. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ✅ test(llm-generation-tracing): type vi.fn mocks so tsgo accepts mock.calls indexing The hook + service tests destructured `mock.calls[0][0]` and accessed nested fields, which tsgo flagged as TS2493 / TS18046 because `vi.fn()` defaults to a zero-arg signature. Add explicit type parameters to the mocks so tsgo can infer the call tuple, and cast `call.payload` at the access point. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ♻️ refactor(model-runtime): move mergeModelRuntimeHooks into the package It's a generic utility for composing `ModelRuntimeHooks` instances — same import surface as `ModelRuntime` and the hooks interface — so it belongs alongside them rather than tucked under a server-side consumer. - New `packages/model-runtime/src/core/mergeHooks.ts` exports `mergeModelRuntimeHooks` and is re-exported from the package index. - Move the unit tests to `packages/model-runtime/src/core/mergeHooks.test.ts`, including a new case covering the "a throws → b is skipped" load-bearing semantics. - `src/server/services/llmGenerationTracing/hook.ts` drops the local copy and the consumer (`src/server/modules/ModelRuntime/index.ts`) imports from `@lobechat/model-runtime`. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ♻️ refactor(llm-generation-tracing): version lives with the prompt, not in a central table `promptVersion` was baked into `TRACING_SCENARIO_REGISTRY`, far from any prompt definition — editing a prompt + forgetting to bump the entry in a completely different file was an obvious foot-gun. - Registry is now `Record<string, string>` mapping trigger → scenario only; it's the stable concern that rarely changes. - `resolveScenario` always passes `promptVersion` through from the caller, defaulting to `UNKNOWN_PROMPT_VERSION` ('v0') when absent. - Each call site declares its own `*_PROMPT_VERSION` constant next to the prompt it describes. `followUpAction` ships the first one: `FOLLOW_UP_PROMPT_VERSION` in `prompts/index.ts`, threaded through `metadata.promptVersion` at the `generateObject` call. Other callers can add the same constant when they next touch their prompts. The 6-char prompt hash on the row still catches forgotten bumps. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ✨ feat(input-completion): wire prompt-version metadata at the auto-complete call site Aligns input auto-complete with the FOLLOW_UP_PROMPT_VERSION convention so each prompt iteration is recordable as the chat-side tracing lands. - `INPUT_COMPLETION_PROMPT_VERSION = 'v1.0'` declared next to `chainInputCompletion` — bump together with the prompt body. - `fetchPresetTaskResult` accepts optional `metadata` and forwards it to `getChatCompletion`; the existing chat path already plumbs metadata to `ModelRuntime.chat` options. - `InputEditor` call site passes `{ scenario: 'input_completion', promptVersion }`. Note: `llm_generation_tracing` currently only fires from `onGenerateObjectComplete`. Input completion is a `chat` call, so this metadata is forward-looking until a chat-side tracing hook lands. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * 🐛 fix(llm-generation-tracing): collapse bucketDir path.join args to silence turbopack glob warning Turbopack's static analyzer treats `path.join(root, dyn1, dyn2)` as a multi-segment glob pattern and warned that it could match ~12k files in the project. Compose the relative subdir as a single string first, so `path.join` only sees one dynamic segment. Behavior unchanged — the resulting path is identical. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ✨ feat(input-completion): route auto-complete through generateObject for tracing Auto-complete is the first preset-task caller migrated to the structured- output path so it lands in `llm_generation_tracing` via the existing `onGenerateObjectComplete` hook. No new server hook, no global chat-side tracing. - `chainInputCompletion` now returns `{ messages, schema }` with a minimal `{ completion: string }` schema and a stable `INPUT_COMPLETION_SCHEMA_NAME` constant. JSON wrapping costs ~15-30 tokens against a 100-token completion budget — negligible for the observability win. - `StructureOutputSchema` / `StructureOutputParams` accept optional `metadata`; `aiChatRouter.outputJSON` merges caller metadata over the default trigger so `{ scenario, promptVersion, schemaName }` reach `ModelRuntime.generateObject` options unchanged. - `IStructureSchema.description` is now optional to match the zod schema — previously the TS type was stricter than runtime validation accepted. - `InputEditor` switches from `chatService.fetchPresetTaskResult` to `aiChatService.generateJSON`, reading `response.completion`. Streaming is dropped because auto-complete already buffers the full result before inserting; no UX change. - Reverts the unused `metadata` field that was added to `fetchPresetTaskResult` in the previous commit — no current caller needs it now that input completion uses the generateObject path. Bumps `INPUT_COMPLETION_PROMPT_VERSION` to v2.0 because the system prompt gained an "output the completion field" instruction. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ♻️ refactor(aiGeneration): extract the runtime-init + generateObject dance into a service Every server-side caller that produces structured output was repeating the same two-step ritual: `initModelRuntimeFromDB(...)` → `runtime.generateObject(payload, { metadata })`. `AiGenerationService` collapses it into one call so future cross-cutting concerns (default metadata, retry, observability hooks) have one place to land. - New `src/server/services/aiGeneration/index.ts` exposes `generateObject<T>(input, options)` and is unit-tested for provider resolution + payload/metadata pass-through. - `aiChatRouter.outputJSON` and `FollowUpActionService.extract` migrated to the service (other callers move organically when next touched). - Drops the unused `keyVaultsPayload` field from `StructureOutputParams` and the placeholder at the InputEditor call site — key vaults are server-resolved from DB, the client never supplies them. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ♻️ refactor(tracing): centralize TRACING_SCENARIOS const + inject AiGenerationService via trpc ctx - New `packages/const/src/llmGenerationTracing.ts` exports `TRACING_SCENARIOS` + `TracingScenario` type — the single directory where every known scenario name lives. Adds `@lobechat/const` as a workspace dep on llm-generation- tracing so `TRACING_SCENARIO_REGISTRY` can reference the same literals. - Callers (FollowUpActionService, InputEditor) replace `'follow_up'` / `'input_completion'` string literals with `TRACING_SCENARIOS.FollowUp` / `.InputCompletion`, so a typo or a rename fails the type-check instead of silently drifting on the row. - `AiGenerationService` is now injected into the `aiChatProcedure` ctx middleware alongside `aiChatService`; `outputJSON` consumes it via `ctx.aiGenerationService` instead of new-ing it inside the handler. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ✨ feat(llm-generation-tracing): add lt/llm-tracing CLI + drop local-only storage_key - Add `lt` / `llm-tracing` CLI under @lobechat/llm-generation-tracing with `list` (recent records, --scenario filter, --json) and `inspect` (by tracing_id prefix or latest, --full, --json). - `FileTracingStore.save` now returns `{ key: null }` so dev DB rows leave `storage_key` empty instead of recording a non-resolvable local path; S3 store remains the source of truth for the real key. Add helpers `findByTracingId` / `getLatest` used by the CLI. - Wire `agentId` and `topicId` into `input_completion` tracing metadata from the chat input auto-complete call site. - Default `FileTracingStore` whenever NODE_ENV=development (drop the ENABLE_LLM_GENERATION_TRACING_LOCAL opt-in env var). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * 💄 style(llm-generation-tracing): prettier CLI output (tree + colors) Mirror the @lobechat/agent-tracing viewer style: - Inline ANSI color helpers (dim/bold/cyan/magenta/green/yellow/red). - Compact single-line header with id, scenario, version, model, status, time — replaces the multi-line bullet list. - Tree structure with `├─`/`└─` connectors instead of `── section ──` banners. - input arrays render per-message (role + char count + preview) rather than dumping raw JSON. - Small single-key outputs (e.g. `{ completion: "怎么样" }`) collapse to inline `key: "value"`. - `lt list` switches to a colored, properly padded table. Default view stays compact; --full expands system_prompt / input / schema bodies. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ♻️ refactor(llm-generation-tracing): split `tracing` config out of `metadata` `options.metadata` was overloaded — half tracing-specific structured fields (scenario / promptVersion / schemaName / agentId / topicId / ...), half free-form jsonb passthrough. Callers couldn't tell which was which, and the inputHint was always auto-extracted (useless when the prompt wraps the user's text in a template). This commit introduces a dedicated `tracing` option: - Add `TracingOptions` to @lobechat/llm-generation-tracing — the typed shape callers import (agentId / topicId / inputHint / scenario / promptVersion / schemaName / systemPrompt / parentTracingId / metadata). - Add loose `tracing?: Record<string, unknown>` to GenerateObjectOptions and StructureOutputParams / StructureOutputSchema so the field flows through the runtime + TRPC. - Tracing hook now reads `context.options.tracing` for structured fields; it still falls back to `metadata.trigger` for the cross-cutting trigger string (ModelRuntime itself uses metadata.trigger for timing logs, so trigger stays on metadata). - Service `record()` accepts an explicit `inputHint`; otherwise falls back to auto-extraction from the first user message. Always truncated. - Free-form jsonb fields move to `tracing.metadata` (was unknown-key passthrough on `metadata`). - Call sites updated: - FollowUpAction now passes `tracing: { scenario, promptVersion, schemaName, topicId }` (previously `metadata`). - InputCompletion now passes `tracing: { agentId, topicId, inputHint: input, scenario, promptVersion, schemaName }` — `inputHint` is the user's actual typed text, not the wrapper prompt's first user message. - `aiChat.outputJSON` router forwards both metadata and tracing. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * Update inputCompletion.ts * 🐛 fix(llm-generation-tracing): stop duplicating provider into the row's metadata jsonb `provider` is already a first-class column on the `llm_generation_tracing` row, so auto-stamping it into the `metadata` jsonb column on every call was pure noise. The hook now writes the caller-supplied `tracing.metadata` verbatim — empty/undefined when the caller had nothing to add. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>17 小时前
✨ feat: support chat mode and redesign chat input action bar (#14774) * Refine chat parameter controls and working sidebar * 💄 style: refine chat parameter controls * 💄 style: refine chat input action affordances * 💄 style: refine chat input control menus * 💄 style: refine chat input skills menu * 🐛 fix: replace skills policy dropdown with popover * fix: base-ui dropdown * fix: base-ui dropdown * 💄 style: fix popover conflict and refine skills menu layout - Extract PopoverLabel component with controlled open state to prevent conflict when skill policy menu opens - Dispatch custom close event so detail popovers close before policy popover opens - Add divider between pinned and auto skill groups - Refine sticky search/footer padding via CSS attribute selectors - Remove stray console.log from ActionDropdown Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * 💄 style: refine skills policy menu and chat input UI - Skills policy menu: change active icon color to blue, add divider + uninstall action for Klavis/MCP/agent-skill items, suppress detail popover when the "..." policy menu is open - Minor refinements across ChatInput, Conversation Error/ContentLoading, and HeterogeneousAgent StatusGuide components Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat: add custom MCP tag and configure action to skills menu - Show orange "Custom" tag next to custom MCP plugin entries - Add Configure action above Uninstall in the policy popover that opens the PluginDevModal drawer for editing the custom plugin Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat: default agent mode to true and gate chat mode at the tools engine - Move `enableAgentMode` from `LobeAgentConfig` to `LobeAgentChatConfig` so it persists via the existing `chat_config` jsonb column and is readable on the server (the top-level field was silently dropped by drizzle). - Default to agent mode for all agents — selectors treat `undefined` as `true`; only an explicit `false` collapses to chat mode. - Introduce `chatModeAllowedToolIds = [knowledge-base, memory, web-browsing]`. Both `createServerAgentToolsEngine` and the frontend `createAgentToolsEngine` now switch on this whitelist in chat mode: skip user plugins, skip `alwaysOnToolIds`, narrow `defaultToolIds`, and turn off `allowExplicitActivation` so the activator can't smuggle other tools in. - `useToggleAgentMode` is the single mode-switch entry; `plugins[]` is left alone — chat mode is enforced at runtime, not by mutating saved config. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat: extend topic status with running/paused/failed Widen `ChatTopicStatus` enum (DB schema, types, TRPC validation) to cover the in-flight lifecycle that gateway and heterogeneous executor runs report. Add a `updateTopicStatus` store action and have both runtime paths write `running` on start and `active` on completion (or `failed` on terminal error). Sidebar topic items render a spinner while `status === 'running'`. Note: drizzle migration for the widened enum needs to be generated separately. * 💄 style: polish skills menu — official tag, tooltip on settings button Add a LobeHub "official" badge to builtin tools and agent skills surfaced in the Skills menu. Wrap the menu's settings button in a Tooltip. Scope the group-header padding reset to the skill-activation group only so the Knowledge submenu keeps its native section padding. * ✨ feat: mark topic as paused while awaiting human tool approval Extend the heterogeneous-agent topic status machine (c0170d032f) with a paused state. The gateway event handler writes topic.status = 'paused' on step_start { phase: 'human_approval' } — one hook covers both Gateway and desktop heterogeneous paths since they share the same handler. Resume back to 'running' is free: approve / reject_continue both spawn a fresh op via the executor entries, which already persist 'running'. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat: gate skills and agent-document injectors at the context engine in chat mode Thread `enableAgentMode` into `MessagesEngine`. When it is explicitly `false`, the engine forces `enabled: false` on: - SkillContextProvider — drops the <available_skills> block - All AgentDocument injectors (BeforeSystem / SystemAppend / SystemReplace / Context / Message) — drops every agent-document position The frontend (`src/services/chat/mecha/contextEngineering.ts`) and server (`src/server/modules/AgentRuntime/RuntimeExecutors.ts` → `serverMessagesEngine`) read `chatConfig.enableAgentMode` from agent config and pass it through; no caller needs to know which injectors to skip. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat: also gate agent-management context in chat mode `agentManagementContext` (the `<current_agent>` + `<available_agents>` block) was leaking into chat-mode prompts whenever the agent was in auto-skill mode, because its caller-side guard (`isInAutoSkillMode || isAgentManagementEnabled`) is orthogonal to `enableAgentMode`. Fold the gate into the same `isAgentMode` switch already covering skills + agent documents in `MessagesEngine` so the injector goes off in chat mode regardless of how the caller populates the context. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🐛 fix: drop orphan rebase marker in OperationTraceRecorder Leftover `<<<<<<< HEAD` from an earlier rebase that was only half cleaned — the HEAD-side content is the one we want; just delete the marker line so the file type-checks again. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style: cursor-style action bar on home input Rework the home ChatInput footer to read like Cursor's composer while keeping the model picker on the right: - Replace the `agentMode` icon-only button with a pill trigger (icon + label + chevron) carrying a persistent fill, dropping a `bottomLeft` mode popover. Reuses the `RuntimeConfig/ModeSelector` design in place so any other action bar consumer picks it up automatically. - Introduce a `modelLabel` action that shows the resolved model display name + chevron, opening `ModelSwitchPanel`. The original `model` icon stays untouched for callers that prefer the compact form. - Wire the home input to use ['agentMode','plus'] on the left and ['modelLabel'] on the right; bump `SendArea` gap to 12 and add `paddingLeft={6}` to the action bar so the pill aligns with the input placeholder. - Localize `chatMode.chat` to "对话" in zh-CN (default English stays "Chat"). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style: surface params panel toggle and hide it for heterogeneous agents - Drop the developer-mode gate on the conversation header params toggle so it ships by default; popup routes remain excluded. - Hide both the header toggle and the right sidebar `Params` tab for heterogeneous agents (Claude Code / Codex etc.), since their model params panel doesn't apply. The active-tab resolver also falls back away from `params` when it isn't available. - Strengthen the Tools popover divider to `colorFill` so the header / footer separators stay visible against the elevated dark-mode surface. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🚑 fix: address type errors surfaced on the new-input branch - Move the `border` from the removed `overlayInnerStyle` onto `styles.content` so the AgentMode / ModeSelector popovers compile against the base-ui `PopoverProps` shape. - Pass `paddingLeft: 6` through `style` on `ChatInputActions` since the underlying Flexbox only accepts `padding` / `paddingBlock` / `paddingInline`. - Tighten skill / market menu items: drop the unsupported `closeOnClick` from the group item, fallback the uninstall display name to `identifier`, swap the antd-style `type: 'warning'` confirm option for `okButtonProps.danger`, and assert the conditionally-spread market items as `ItemType` so the inferred union no longer contains `undefined`. - Annotate `resolveMark` in `LevelSlider` so the fallback branch returns a `ReactNode` label, fixing the `MarkObj` mismatch on `LevelOption`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Innei <tukon479@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>9 天前
✨ feat(platform-agent): openclaw/hermes agent creation UI, device guard, and remote dispatch backend (#15065) * ♻️ refactor(agent-invocation): add AgentInvocationIntent + unified non-hetero dispatcher (LOBE-8927/8928) Introduce a shared invocation contract and unified dispatcher for the non-hetero, non-group agent call paths (callAgent speak mode and @agent direct mentions). Removes the implicit client-only fallback that existed in both entry points. Changes: - agentDispatcher.ts: add AgentInvocationIntent interface as the unified intent type for callSubAgent / callAgent / @agent invocations - nonHeteroSubAgentDispatcher.ts (new): dispatchNonHeteroSubAgent() resolves child runtime via selectRuntimeType and routes to executeClientAgent (client) or executeGatewayAgent (gateway); throws for hetero (out of scope per LOBE-8926) - conversationLifecycle.ts #executeDirectMentionRoute: replace hardcoded executeClientAgent + TODO fallback with dispatchNonHeteroSubAgent call - builtin-tool-agent-management executor.ts callAgent speak mode: replace hardcoded executeClientAgent + TODO fallback with dispatchNonHeteroSubAgent call Fixes LOBE-8927 Fixes LOBE-8928 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ✨ feat(platform-agent): openclaw/hermes agent creation UI, device guard, and remote dispatch backend - Add CreatePlatformAgent 3-step creation modal (type select → config → bind device) - Add RemoteAgentConfigCard to agent profile editor for openclaw/hermes config - Add device guard banner in HeterogeneousChatInput for offline/unavailable devices - Add useRemoteAgentDeviceGuard hook for real-time device status polling - Fix backend dispatch: openclaw/hermes now use executeToolCall(runHeteroTask) instead of dispatchAgentRun (lh connect only handles tool_call_request) - Add agentNotify router for lh notify → DB write + gateway stream event - Add device.checkCapability endpoint for platform availability probe - Add notify_update event type to gateway stream and event handler - Add sendDoneSignal in heteroTask.ts for clean openclaw exit signaling - Unify non-hetero sub-agent dispatch via dispatchNonHeteroSubAgent (LOBE-8927) - Route openclaw/hermes to gateway runtime; keep claude-code/codex on hetero/client paths - Add i18n keys for platform agent UI and device guard banners Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * 🐛 fix(agentNotify): reuse execAgent placeholder message on first lh notify call Instead of creating a second empty bubble, the first assistant notify without a messageId now updates the placeholder assistantMessageId that execAgent already seeded in runningOperation.assistantMessageId. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ✨ feat(agentNotify): cancel openclaw/hermes process on interruptTask - Store deviceId + heteroType in topic.metadata.runningOperation at dispatch time - interruptTask now dispatches cancelHeteroTask tool call to the bound device when topicId reveals a remote hetero operation, sending SIGINT to the process - Pass topicId from gateway cancel callback to interruptTask - Add topicId to InterruptTaskSchema and InterruptTaskParams Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ♻️ refactor(hetero-agent): consolidate remote/local type classification into heterogeneous-agents package - Add RemoteHeterogeneousAgentConfig, REMOTE_HETEROGENEOUS_AGENT_CONFIGS, isRemoteHeterogeneousType, and derived type aliases (HeterogeneousAgentType, LocalHeterogeneousAgentType, RemoteHeterogeneousAgentType) to packages/heterogeneous-agents/src/config.ts - Extend HETEROGENEOUS_TYPE_LABELS to cover remote platform types (openclaw, hermes) via REMOTE_HETEROGENEOUS_AGENT_CONFIGS - Replace all inline `=== 'openclaw' || === 'hermes'` checks and local Sets/type aliases across aiAgent service, ProfileEditor, HeterogeneousChatInput, useRemoteAgentDeviceGuard, CreatePlatformAgent, RemoteAgentConfigCard, and deviceProxy with the shared utility - Show OpenClaw/Hermes display name in assistant message model tag (Usage component) by setting provider=heteroType on placeholder message and using HETEROGENEOUS_TYPE_LABELS for rendering - Fix ReferenceError: move remoteDeviceId declaration before updateMetadata call Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: add the platform agents get profiles * 🐛 fix(platform-agent): routing, security, and i18n issues from review - Route openclaw/hermes to gateway on desktop (P1): add isRemoteHeterogeneousType check in selectRuntimeType before desktop hetero branch — remote agents never use local desktop IPC, no special-casing needed - Fix race in heteroTask: sendAutoNotify → sendDoneSignal now sequential via .finally() so error message is written before agent_runtime_end is published - Security: validate messageId belongs to topicId in agentNotify before MessageModel.update to prevent cross-conversation data corruption - Clear capability/device/profile state on platform change in creation modal (P2) - Derive PLATFORM_DEFS from REMOTE_HETEROGENEOUS_AGENT_CONFIGS — new platforms automatically appear in the modal without code changes - Use HETEROGENEOUS_TYPE_LABELS for platform names in HeterogeneousChatInput and RemoteAgentConfigCard (remove hardcoded PLATFORM_NAMES map) - i18n: platform card descs, 'online'/'offline' tags, 'Select a device' placeholder, checkFailed error — all now use i18n keys Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ♻️ refactor(platform-agent): derive remote platform enum from config + fix test - device.ts: replace hardcoded z.enum(['hermes','openclaw']) with a zod enum derived from REMOTE_HETEROGENEOUS_AGENT_CONFIGS so new platforms are automatically covered without touching this file - heteroTask.ts / getAgentProfile.ts: use RemoteHeterogeneousAgentType instead of literal 'hermes' | 'openclaw' union for the same reason - gateway.test.ts: update cancel-handler assertion to include topicId which was added to the interruptTask call in the previous commit Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ✨ feat(platform-agent): gate creation entry behind labs flag + expand dispatcher tests - Add enablePlatformAgent lab preference (default false) — the "Add Platform Agent" menu item is hidden until the user opts in via Settings → Advanced → Labs - Wire toggle in settings/advanced with labs i18n key (en/zh) - createPlatformAgentMenuItem returns null when flag is off - agentDispatcher.test: add remote hetero cases (openclaw/hermes → gateway on both web and desktop) to cover the routing fix added earlier Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * 🐛 fix(lint): merge duplicate import + sort interface props in nonHeteroSubAgentDispatcher Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * 💄 feat(platform-agent): disable Hermes option in creation modal (coming soon) Hermes is not yet ready for production. Mark it as coming-soon in the platform selection step: grayed-out card, not clickable, "Coming Soon" tag next to the name. To enable Hermes when ready: remove 'hermes' from COMING_SOON_PLATFORMS in CreatePlatformAgent/index.tsx. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ✅ fix(test): mock CreatePlatformAgentModal in ModalProvider.test The modal always mounts (open=false) and calls lambdaQuery.useQuery which requires a tRPC context not present in the test environment. Mock it out the same way as ChatGroupWizard and EditingPopover. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ✅ fix(test): mock useUserStore + labPreferSelectors in useCreateMenuItems.test Adding useUserStore to useCreateMenuItems triggered user store initialization in tests, which pulled in @lobechat/const and failed because the existing mock only exports isDesktop. Mock the store and selectors directly instead. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * 🐛 fix(platform-agent): hide divider when platform agent entry is disabled The divider before 'Add Platform Agent' was unconditional — it showed even when the labs flag was off. Conditionally include both the divider and the menu item together so no orphaned separator appears. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <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>18 小时前
♻️ refactor: add shared guard helpers (#15122)1 天前
✨ feat(review-panel): group review changes by submodule (#15148) * 🐛 fix(claude-code): show task subject in TaskUpdate inspector & header A TaskUpdate that only sets `subject` (no status flip) was falling through to the aggregate `Todos: x/y` chip and burying the per-call signal. Surface the new subject like the status branch already does: "Task updated: <subject>". Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ✨ feat(review-panel): group changes by submodule with per-group collapse Surface dirty submodules as their own groups in the agent Review panel so users working in a parent repo with submodules see each repo's changes clustered together (mirrors WebStorm's per-repo commit grouping). Both Unstaged and Branch modes apply the same grouping — submodules with internal working-tree changes (unstaged) or branch diffs against their own origin/HEAD (branch) surface as separate groups, each tagged with its own branch label and file/diff totals. Backend (`GitCtr`): - `getGitWorkingTreePatches` and `getGitBranchDiff` extracted into private recursive helpers that detect submodules via `git submodule status`, partition pointer-bump entries out of the parent's flat patches, and recurse one level for each dirty submodule's own patches + branch info. - Nested submodules are not traversed (phase 1); revert routes through each group's absolute path so submodule files revert inside the submodule. Renderer: - New `GroupHeader` and `FileRow` subcomponents split out of `Review`. `GroupHeader` is sticky with a chevron + name + file count + diff totals + branch; clicking collapses the group's rows. A hover-revealed `ActionIcon` on the right expands/collapses all file diffs in that group (`e.stopPropagation` keeps it from also collapsing the surrounding header). - Fixed `block-size: 32px` on the header so toggling the fold button on/off doesn't jitter the sticky height. - Single-repo working trees keep the previous flat layout when no submodule groups exist. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ✨ feat(review-panel): scan all submodules in branch mode Previously branch mode only surfaced a submodule group when the parent's diff against base ref contained a `Subproject commit` pointer bump for it. This missed the common case where the user has committed work in a submodule on a feature branch but the parent's pointer hasn't yet moved relative to its base — the submodule's own branch differences stayed invisible in the Review panel. `collectBranchDiff` now recurses into every registered submodule (single level, in parallel) and keeps a group when EITHER its pointer differs in the parent OR its own branch diverges from its own origin/HEAD. Clean-on- both-axes submodules are dropped so the panel stays quiet for repos where the submodule isn't actively being worked on. Submodule count is small in practice (single digits), so the extra per-submodule fetch + diff in parallel is an acceptable cost. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ✨ feat(agent-documents): hide .tool-results archive from user-facing lists Auto-created tool-result archive folder and its children are now filtered out of getAgentDocuments. Agents still discover them via the tool-oriented listDocuments paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style(review-panel): drop "file not found in project index" toast Reveal-in-tree now silently no-ops when the path isn't indexed (e.g. submodule files) instead of nagging the user with a warning toast. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * 🐛 fix(review-panel): keep submodule groups visible on pointer-only bumps `isEmpty` was derived solely from `totalEntryCount`, which counts file patches across groups. A pointer-only submodule bump (parent patch filtered out, submodule group present but internally clean) produced `totalEntryCount === 0`, so the panel rendered the global empty state and silently skipped the submoduleClean group rendering — even though git was dirty. Now `isEmpty` also requires zero submodule groups, so pointer-only bumps keep their GroupHeader + "submodule clean" line. The fold-all button visibility switches to `totalEntryCount > 0` so it stays hidden when there's nothing foldable. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>11 小时前
✨ feat(review-panel): group review changes by submodule (#15148) * 🐛 fix(claude-code): show task subject in TaskUpdate inspector & header A TaskUpdate that only sets `subject` (no status flip) was falling through to the aggregate `Todos: x/y` chip and burying the per-call signal. Surface the new subject like the status branch already does: "Task updated: <subject>". Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ✨ feat(review-panel): group changes by submodule with per-group collapse Surface dirty submodules as their own groups in the agent Review panel so users working in a parent repo with submodules see each repo's changes clustered together (mirrors WebStorm's per-repo commit grouping). Both Unstaged and Branch modes apply the same grouping — submodules with internal working-tree changes (unstaged) or branch diffs against their own origin/HEAD (branch) surface as separate groups, each tagged with its own branch label and file/diff totals. Backend (`GitCtr`): - `getGitWorkingTreePatches` and `getGitBranchDiff` extracted into private recursive helpers that detect submodules via `git submodule status`, partition pointer-bump entries out of the parent's flat patches, and recurse one level for each dirty submodule's own patches + branch info. - Nested submodules are not traversed (phase 1); revert routes through each group's absolute path so submodule files revert inside the submodule. Renderer: - New `GroupHeader` and `FileRow` subcomponents split out of `Review`. `GroupHeader` is sticky with a chevron + name + file count + diff totals + branch; clicking collapses the group's rows. A hover-revealed `ActionIcon` on the right expands/collapses all file diffs in that group (`e.stopPropagation` keeps it from also collapsing the surrounding header). - Fixed `block-size: 32px` on the header so toggling the fold button on/off doesn't jitter the sticky height. - Single-repo working trees keep the previous flat layout when no submodule groups exist. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ✨ feat(review-panel): scan all submodules in branch mode Previously branch mode only surfaced a submodule group when the parent's diff against base ref contained a `Subproject commit` pointer bump for it. This missed the common case where the user has committed work in a submodule on a feature branch but the parent's pointer hasn't yet moved relative to its base — the submodule's own branch differences stayed invisible in the Review panel. `collectBranchDiff` now recurses into every registered submodule (single level, in parallel) and keeps a group when EITHER its pointer differs in the parent OR its own branch diverges from its own origin/HEAD. Clean-on- both-axes submodules are dropped so the panel stays quiet for repos where the submodule isn't actively being worked on. Submodule count is small in practice (single digits), so the extra per-submodule fetch + diff in parallel is an acceptable cost. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ✨ feat(agent-documents): hide .tool-results archive from user-facing lists Auto-created tool-result archive folder and its children are now filtered out of getAgentDocuments. Agents still discover them via the tool-oriented listDocuments paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style(review-panel): drop "file not found in project index" toast Reveal-in-tree now silently no-ops when the path isn't indexed (e.g. submodule files) instead of nagging the user with a warning toast. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * 🐛 fix(review-panel): keep submodule groups visible on pointer-only bumps `isEmpty` was derived solely from `totalEntryCount`, which counts file patches across groups. A pointer-only submodule bump (parent patch filtered out, submodule group present but internally clean) produced `totalEntryCount === 0`, so the panel rendered the global empty state and silently skipped the submoduleClean group rendering — even though git was dirty. Now `isEmpty` also requires zero submodule groups, so pointer-only bumps keep their GroupHeader + "submodule clean" line. The fold-all button visibility switches to `totalEntryCount > 0` so it stays hidden when there's nothing foldable. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>11 小时前
🐛 fix(agent-runtime): route context engine payload out of the events stream (#15151) * 🐛 fix(agent-runtime): route context engine payload out of the events stream `call_llm` previously pushed a `context_engine_result` event carrying the full `contextEngineInput` (agentDocuments, systemRole, knowledge, …) into the per-step events array. That array is the same one persisted into Redis `agent_runtime_events`, so every step shipped the heavy CE payload into the state pipeline even though the only consumer was the trace recorder, which extracted CE into the typed `contextEngine` snapshot field and immediately filtered the event back out. Wire a typed `recordContextEngine` callback through `RuntimeExecutorContext` instead. `AgentRuntimeService.executeStep` buffers the call per step and hands it to `OperationTraceRecorder.appendStep` via a new `contextEngine` param. Trace snapshots are byte-identical; the events stream — and therefore the Redis state blob — no longer carries CE. Step toward LOBE-9110 (split state vs trace pipeline). Viewer keeps the legacy `context_engine_result` reader for back-compat with older on-disk snapshots. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * 🎨 refactor(agent-runtime): rename recordContextEngine to tracingContextEngine The callback name now signals its role as the trace-pipeline channel, matching the `tracing` prefix used elsewhere for non-state observability wiring. Pure rename, no behavior change. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>10 小时前
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>18 小时前
♻️ 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 天前
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>18 小时前
💄 style: AnalyzeVisualMedia inspector, Portal HTML preview refactor & CE trace dedup (#14777) * ✨ feat: add AnalyzeVisualMedia inspector, Portal HTML preview refactor, and CE trace dedup - Add AnalyzeVisualMedia inspector and state types to builtin-tool-lobe-agent - Refactor Portal HTML renderer to use @lobehub/ui built-in HtmlPreview - Add portal artifact type selector and portal selectors to distinguish HTML/other artifacts - Dedup context_engine_result events in OperationTraceRecorder; add resolveCeEvent in viewer - Update .agents/skills/builtin-tool/references/ui.md with Tool Render design principles - Bump @lobehub/ui to 5.12.0 for HtmlPreview support Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * 🧪 test(trace-recorder): add deduplicateCeEvent tests for context_engine_result dedup Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * 🐛 fix(agent-tracing): wire resolveCeEvent into all CE reader paths All render functions and CLI inspect paths now call resolveCeEvent(step, allSteps) instead of reading step.events?.find(...) directly, so deduplicated steps correctly reconstruct their context_engine_result input/output by walking back through previous steps. Affected: renderSystemRole, renderEnvContext, renderPayloadTools, renderPayload, renderMemory, renderMessageDetail, renderStepDetail, and all --system-role / --env / --payload-tools / --payload / --memory CLI branches (both text and --json). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ♻️ refactor(conversation): pass onRegenerate through ErrorMessageExtra and fix error guard order Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ♻️ refactor(agent-tracing): lift context_engine_result out of events into typed contextEngine field Replace ad-hoc CE event dedup (mutating input/output inside events[]) with a dedicated `contextEngine` field on StepSnapshot that uses the same delta pattern as messagesBaseline/messagesDelta. CE data is structural state, not a streaming event — keeping it in events[] was a semantic mismatch. - Add `StepSnapshot.contextEngine?: { input?, output? }` with full delta semantics - OperationTraceRecorder: extract CE from events before building snapshotEvents, store in contextEngine, deduplicate via deduplicateCeSnapshot (no more mutations) - viewer: add resolveCeSnapshot (reads contextEngine first, falls back to legacy events format for old snapshots); deprecate resolveCeEvent alias - inspect CLI: update all call sites to resolveCeSnapshot - tests: rewrite deduplicateCeEvent suite → contextEngine dedup suite Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * 💄 style(loading): use colorTextTertiary for elapsed time display Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>9 天前
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>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>18 小时前
🔨 chore: project structure businessify (#10930) 4 个月前
⚡️ perf: warm route chunks after idle (#15109) * ⚡️ perf: warm route chunks after idle * 🐛 fix: normalize platform route chunk ids * ⚡️ perf: refine route chunk preloading * 🔧 chore: keep desktop renderer preload unchanged * ⚡️ perf: skip renderer chunks in route warmup * ⚡️ perf: preload agent route dynamic chunks * ⚡️ perf: align route preload deployment urls * ⚡️ perf: coalesce stable vendor chunks * ⚡️ perf: group shared data runtime chunks * ⚡️ perf: group model runtime chunks * ⚡️ perf: trim initial route preloads * ⚡️ perf: limit idle route micro preloads * ⚡️ perf: strip tiny html modulepreloads * ⚡️ perf: prune redundant route chunk imports * ⚡️ perf: enable rolldown devtools * ⚡️ perf: gate vite devtools output * ⚡️ perf: optimize react-scan integration and update global types Signed-off-by: Innei <tukon479@gmail.com> * ⚡️ perf: support cloud route chunk preload --------- Signed-off-by: Innei <tukon479@gmail.com>1 天前
✨ feat:support LobeHub MarketPlace (#8841) * feat: 链接market 做基本的市场接驳功能 * feat: 重写分享助手的页面 * feat: 新增market-auth 的 oidc 方案 * feat: 增加初次agent发布链路和更agent逻辑 * feat: 增加二次添加助手时候的提示 * feat: 重新授权时候唤起新的重新授权而不是自动 token 换取 * feat: 添加market-auth-callback的 layout * feat: 调整env 中的market 引用 * fix: 解决url 双/导致的路径请求问题 * fix: fix build error * feat: 更新sitemap 的生成逻辑 * feat: 更新pglite的session meta 定义,增加 marketIdentifier * feat: 增加个人信息存储的逻辑 & 整理发布 agent 时候按钮的整体逻辑 * fix: delete 0030 * feat: add search myown in discover * feat: clean cthe code & refactor agents showpannel * feat: support assistant detail pages have unpublish & achiave hint * feat: change text render type * feat: add submit mode style fixed * fix: fixed migrations * feat: update agent publish version modal * feat: update market publish button * feat: update exmaple &summary show case * feat: add token show in publish modal * feat: add verison show tags antd version? params search * feat: add desktop market auth request way * feat: delete market-oidc second path,change all to base url * feat: change sdk & api into url const & change market api into servers * feat: change all api into /market server path * feat: change the migrations insert position * feat: support assistant origin checkout feature * feat: change the item show place * feat: add market source switch components * feat: add 'force-dynamic' in discord/detail page * feat: change the describe name * feat: styles & locals add * feat: add locals * feat: fixed market update locals * feat: update market-oidc layout * feat: delete some types * feat: support leacgcy params change * feat: change the oidc url * feat: agent detial page should have status show page * feat: add db migrations * test: update test * feat: delete database change & update i18n * fix: rollback mirgration * fix: change mirgration * fix: back snapshot * Update print statement from 'Hello' to 'Goodbye'6 个月前
✨ feat: support messager (#14442) * feat: support messagers * chore: refactor lobeai to messager prefix * feat: reigister messager platforms * feat: support slack messager * fix: verify im route redirect * fix: link page style * chore: optimize agent select and /agents commands * feat:support lab switch * feat: use same agent select * chore: add runtime error info * chore: optimize error text * feat: add slack messagger installation implementation * chore: add more scope * feat: add slack messager account link * fix: open slack in a new link * feat: optimze messager link page * feat: optimize messager locales and bot options * chore: optimize messager * fix: slack integration detail * fix: avoid taking over and fix slash commands * chore: optimize slack app setup * chore: update slack manifest and setup * feat: support discrod platform * feat: discord messger slash commands and agent picker * chore: update discord messager * feat: support db bot provider credentials * chore: remove message router ensure connected * chore: remove notes field * chore: add applicationId and credentails * chore: squash db migations * chore: remove installedAt and linkedAt field * chore: remove messager releated env variables * chore: remove old skill bot skill * feat: add operationId when throwing error * chore: abstract platform clients and registery * chore: fix link modal message i18n and add platform definition name field * feat: add integration detail * feat: add platfom definition i18n files * chore: abstract messenger router platform branches Collapse parallel Slack/Discord slash & action paths in MessengerRouter into a single command registry + binder hooks (replyPrivately, extractActionFromEvent, acknowledgeCallback). Wire Discord /start by resolving DM via openDM(authorUserId) so a public-channel slash invocation posts the link privately. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: update installation and oauth process for discord and slack * fix: telegram local button * chore: remove messager docs * feat: add discord installation process * chore: remove discord bot username * chore: adjust discord integration detail * feat: extract platfom specific implementation * chore: handle connection flow and redirect * feat: add platform router for messager * chore: move messager to agents group * chore: update i18n files * chore: update messager table sql * chore: update messager sql * fix: link with tenantId * chore: move messger verify page to features/Messager * chore: refactor messager verify page * Potential fix for pull request finding 'Property access on null or undefined' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> * fix: Rebind by platform user when confirming messenger link * chore: remove unnecessary journals * chore: update i18n files * fix: lint error and i18n * fix: test cases * chore: add lost test cases * chore: try cpus 2 * chore: try remove optimize package import * chore: fallback define config * chore: try to reduce OOM * chore: fallback --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>15 天前
💄 style(task): activity card stop run + register /tasks in SPA proxy (#14559) * ✨ feat(task): add stop run action to activity card menu Surface the existing cancelTopic flow in the task detail activity card so users can interrupt a running topic without opening the chat drawer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat(task): confirm before stopping a running topic Wrap the new Stop run action in a confirmModal so an accidental click can't silently abort an in-flight run. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🐛 fix(spa): register /tasks and /task in SPA proxy matcher Without these matcher entries, the Next.js middleware never rewrote /tasks and /task/:taskId to the SPA catch-all, so the activity feed entries 404'd in production builds even though the routes were wired in the SPA router. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>14 天前
🔨 chore(vite): support direct markdown imports (#13216) ✨ feat(vite): support markdown imports1 个月前