mirror of
https://github.com/lobehub/lobe-chat.git
synced 2026-06-14 03:30:19 +00:00
canary
172 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
365dd1ff64 |
⚡️ perf(build): remove sitemap generation to cut static export time (#15702)
* ⚡️ perf(build): remove sitemap generation to cut static export time
The sitemap accounted for 772 of 827 prerendered pages, each fetching
marketplace data at build time. Static generation drops from 28.2s to
0.3s and total next build from ~59s to ~32s.
* Redirect legacy sitemap URLs to the landing site
* Redirect sitemap index to landing sitemap
|
||
|
|
ccb33fa48c |
✨ feat: workspace backend service slice (#15560)
Backend-only slice of the workspace feature (server routers/services, database models with workspaceId threading, openapi middleware, business/server stubs, const/types). Excludes all UI (features/routes/store/hooks). Deploys dark behind the workspace feature flag. Includes open-source stub fixes: workspaceCreds router stub, ChargeParams workspaceId, usage.ts null-coalesce, DBMessageItem.workspaceId. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
dbf743cc12 |
✨ feat(verify): Agent Run delivery checker system (#15489)
* 🗃️ feat(database): add verify system tables for agent run delivery checker Implement the database layer for the Agent Run delivery checker (Verify System). Reuse / definition layer: - verify_criteria: a single reusable pass/fail standard (atomic unit), carrying its verifier config + onFail default and bound to a document for judging guidance (iteration history reuses document_history; no version columns) - verify_rubrics: a named group that aggregates criteria — the reusable unit - verify_rubric_criteria: junction, which criteria a rubric aggregates (criteria are reusable across rubrics) Mounted onto an agent via the existing agency config jsonb: - agencyConfig.verifyRubricId: a reusable rubric (criteria template) - agencyConfig.verifyCriteriaIds: ad-hoc one-off criteria A run's plan instantiates the union of both. No dedicated bindings table. Snapshot + result layer: - agent_operations.verify_plan (jsonb) + verify_plan_confirmed_at: the per-run immutable check-item snapshot lives ON the operation (1:1 — auto-repair spawns a new operation), instead of a separate plans table - agent_operations.verify_status: denormalized rollup for list-page badges - verify_check_results: per-criterion result with the Toulmin model (verdict/confidence as columns, narrative in a typed toulmin jsonb), N:1 verifier_tracing_id for batch judging, FP/FN flags for the data flywheel; relates to the plan via operation_id + stable check_item_id Ref: LOBE-10019 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ✨ feat(verify): add Agent Run delivery checker backend + frontend module Implements the verify system on top of the schema (PR #15480): - models: verifyCriterion / verifyRubric (+junction) / verifyCheckResult; agentOperation verify plan/status methods - services/verify: AI plan generation (auto-create criteria), executor with LLM Toulmin judge (per-criterion + batch), program placeholder, agent & auto-repair spawner seams, rollup chokepoint, feedback fp/fn, completion lifecycle bridge - lambda verify router (criteria/rubric CRUD, plan, results, feedback) - frontend feature module: service, SWR hooks, CheckerDock state machine, RunArtifact, verify i18n namespace - tracing scenarios: VerifyPlanGen / VerifyJudge Live UI mount (dock/artifact into chat) pending server operationId source. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * 🐛 fix(verify): persist delivery-checker verdicts via async tracing backfill The LLM judge produced valid verdicts but they were never persisted, leaving every run stuck at `verifying`. Two root causes: 1. FK ordering: `writeVerdict` stamped `verifier_tracing_id` synchronously, but the `llm_generation_tracing` row is written asynchronously (best-effort, after the response) — so the hard FK was violated every time and the verdict write was rolled back. Now the verdict is written with a null link, and the tracing id is backfilled by an `onPersisted` callback that fires only after the tracing row commits (still non-blocking). If tracing is disabled the link simply stays null. 2. Verdict parse: the judge JSON schema is non-strict, so the provider returns optional Toulmin fields as explicit `null`. The Zod validator used `.optional()` (accepts undefined, not null), so any null failed the whole `safeParse` and discarded the batch. Switched to `.nullish()`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ✨ feat(cli): add `verify` command for the delivery checker Adds `lh verify` covering the full delivery-checker chain — criteria & rubric CRUD, per-run plan (generate/state/confirm/skip), execute (LLM judge), results, and feedback — calling the `verify` lambda router. Enables end-to-end backend testing of the verify system. Also adds the missing `tool-runtime` / `prompts` / `const` workspace entries to the CLI's `pnpm-workspace.yaml` so the standalone package installs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * 💄 feat(verify): add verify message role + delivery-checker card UI Make the delivery-checker renderable in chat: - Fix the `features/Verify` components so they compile: flatten the `verify` locale to the repo's flat-dotted-key convention (keySeparator: false), import `Flexbox`/`TextArea` from `@lobehub/ui` (react-layout-kit is no longer a dep), and the token cast. - Add a `verify` UI message role + a `VerifyMessage` card that renders the Run Artifact + checker dock from `metadata.verifyOperationId`, wired into the message renderer switch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ✨ feat(verify): add lobe-agent `generateVerifyPlan` tool (server runtime) Lets an agent set up the delivery checker for its run: the agent calls `generateVerifyPlan` early (per the new `<delivery_checker>` system-role guidance), which instantiates the rubric / ad-hoc criteria into a frozen plan on the current `agent_operations` row. Executed server-side only — the executor is dispatched via `runtime[apiName]` with `operationId` threaded through the tool execution context; the client `BaseExecutor` gracefully no-ops it. Also registers the metadata fields (`verifyOperationId`/`verifyRound`) on the message metadata zod schema so the role='verify' card can carry its operation id. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ✨ feat(verify): surface role=verify card on run completion (LOBE-10051) Connect the delivery checker to the conversation: when an Agent Run with a verify plan completes, `CompletionLifecycle` inserts a persisted `role='verify'` message (parented to the assistant, carrying `metadata.verifyOperationId`) that renders the checker card. Self-guarded — no plan → no card, failures never affect the run. `role='verify'` behaves like a `user` leaf message everywhere it flows (persistence + conversation-flow pass it through unchanged); only the context-engine treats it specially: a new `VerifyMessageProcessor` drops it from the model context (UI-only card, not a valid model role). Adds `verify` to `CreateMessageRoleType`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * 💄 feat(verify): merge run-artifact + checker into one card The role=verify message rendered two stacked cards (Run Artifact summary + Delivery Checker) that duplicated the check-item list. Merge into a single card: the `Run Artifact · Round N` header, then the checker results + actions, then the snapshot note. RunArtifact/CheckerDock gain an `embedded` prop (header-only / body-only, no card chrome) and VerifyMessage composes them under one border. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ✨ feat(verify): derive generateVerifyPlan rubric from agencyConfig A real agent calls `generateVerifyPlan` with just a `goal` and doesn't know rubric ids. When `rubricId`/`criteriaIds` params are absent, derive the mounted rubric + ad-hoc criteria from the executing agent's `agencyConfig.verifyRubricId / verifyCriteriaIds`. Params still win when given. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * 🐛 fix(cli): surface agent gateway WebSocket close code + reason The `onclose` handler logged `String(event)` → the useless "[object CloseEvent]". Surface `event.code` (+ `event.reason` when present) so a gateway disconnect before completion is actually diagnosable. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * 💄 fix(verify): rename "Run Artifact" → "Verification", drop failed red border - The kicker said "Run Artifact" — it's automated verification, not an artifact. Renamed to "Verification · Round N". - Removed the red error border on a failed check — a normal card reads better. - Fixes a render crash (`useVerifyState is not defined`): the border removal left a dangling reference after the import was dropped. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ✨ feat(cli): poll run status when the agent stream drops When the live stream (gateway WebSocket / SSE) closes before the run finishes, the run is still executing server-side — so instead of hard-exiting, fall back to polling `aiAgent.getOperationStatus` every 10s until the run reaches a terminal state (or is no longer tracked). Pairs with surfacing the WS close code/reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * 💄 feat(verify): add Render for generateVerifyPlan tool call The generateVerifyPlan tool call rendered as the default param/result dump. Add a Render that lists the generated delivery checks (title + gate/auto-fill tag), and surface the items on the tool state so the Render can read them. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ✨ feat(verify): auto-confirm generated plan so checks run on completion The agent generated a plan but it stayed `planned`/unconfirmed, so the completion hook (which gates on a confirmed plan) never ran the checks — the card was stuck at "awaiting confirmation" with no pass/fail. In the headless agent flow there's no one to click Confirm, so `generateVerifyPlan` now auto-confirms the plan it generates; the checks then run automatically on completion. (An interactive "review before run" gate is a future enhancement.) Also: the verify card header disappeared in the draft/planned phase (`phaseToArtifact.draft` was null). Give it a header so the card always shows its "Verification · Round N" heading. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * 🐛 fix(agent-tracing): only count opaque/presentational attrs as structural noise The first structuralNoiseRatio charged ALL markup (every <...> tag) as noise, which over-penalized legitimately structured results 3x. Grounding against real web-search output (`<item title="…" url="…">snippet</item>`) showed the tags and the title=/url= attributes ARE the signal the model reads. Now only opaque/presentational attribute names (id, class, style, data-*, aria-*, role, on*) count as noise; semantic element tags and content-bearing attributes (title, url, href, name…) are kept. On a 57-op user-interrupted sample this drops web-search noise 42%→0% and overall estimated waste 16%→5%, leaving large-payload (readDocument) and high error-rate tools as the real signal. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ✨ feat(verify): model-authored criteria with name/description/instruction-in-document + agent verifier Restructure the generateVerifyPlan tool to a createDocument-style full-create flow and wire up the agent verifier path: - criteria now = title + description (required one-liner) + instruction (required detailed rubric); instruction lives in a linked document (verify_criteria.documentId), description is a new verify_criteria column (migration 0111). verifierConfig no longer holds description/instruction. - generateVerifyPlan creates verify_criteria + a rubric, snapshots the plan onto the operation and confirms it; judge resolves the instruction from the document. - agent-type checks run as verifier sub-agents (execAgent + isolated thread) whose onComplete hook parses a VERDICT and writes it back to verify_check_results (renamed AgentVerifierSpawner → VerifierAgentRunner). - UI: custom Inspector for the tool header; check list shows per-verifier-type icons (llm/agent/program) + description + required/optional tag; i18n en/zh. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ⚡️ perf(verify): run program/llm/agent checks concurrently on completion The three verifier kinds are independent; previously the agent spawn waited for the batched LLM judge to finish. Run them via Promise.all so agent sub-agents start immediately alongside the LLM batch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ✨ feat(verify): dedicated builtin verify-agent + writeback tool, role=verify message, portal check editor - Add `@lobechat/builtin-tool-verify` (submitVerifyResult) + builtin `verify-agent`; agent-type checks now run as the dedicated verify agent (not the user's agent), which investigates and writes its verdict back via the tool during its run. - Verifier inherits the parent run's model/provider (builtin default may be unconfigured locally). - role=verify completion message no longer requires an assistantMessageId, so the delivery-checker card always surfaces when a plan exists. - Portal editor for verify checks (title/description/instruction/verifier/onFail). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * 🐛 fix(verify): restrict verify-agent to its writeback tool; fix running loader icon Root cause of stuck `running` agent checks: the verify-agent ran in agent mode and inherited all default tools (web-browsing, cloud-sandbox, skills, activator), so it went off web-searching/crawling to "investigate" and never called submitVerifyResult. - Run the verify-agent in chat mode (enableAgentMode: false, searchMode: off) — the strict whitelist — and whitelist `lobe-verify` for chat mode so the verifier gets ONLY its writeback tool. - Sharpen the verify systemRole: judge from the provided deliverable/instruction (no external tools), always reach a verdict, and always call submitVerifyResult. - CheckerDock: running check now uses the standard RingLoadingIcon (warning ring), matching the app's loader instead of a blue spinner. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ✨ feat(verify): auto-repair loop — re-run the agent with failure feedback on failed checks When required checks fail with onFail=auto_repair, automatically run a second iteration instead of ending at `failed`: - createRepairRunner: re-runs the SAME agent in the same topic with the failure feedback as the prompt, re-snapshots the plan onto the repair operation and confirms it so it re-verifies on completion (the next round). Capped at MAX_REPAIR_ROUNDS via parent-chain depth to prevent runaway loops. - maybeAutoRepair: fires only once every required check has a terminal result, so it works for inline LLM checks (triggered from lifecycle) and async agent checks (triggered from the verify tool's writeback path). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ✨ feat(verify): open check result detail in portal & rename artifact→result - add a VerifyResult portal view: clicking any check row opens that result's detail (verdict, confidence, Toulmin sections, suggestion) on the right; agent checks expose their execution trace from inside the panel - CheckerDock rows are all clickable now (chevron affordance), status shown by icon only; verify card uses colorBgElevated - rename the run-result surface from "artifact" to "result" everywhere: RunArtifact → RunResult, phaseToArtifact → phaseToResult, and all `artifact.*` i18n keys → `result.*` - ship verify namespace zh-CN / en-US locales Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ✨ feat(verify): enrich check result portal — criterion stepper, richer detail view Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ✨ feat(verify): rubric run-policy config + repair feedback on the verify card Auto-repair feedback now lives on the failed round's role=verify message (content), and the VerifyMessageProcessor surfaces it into the repair run's context as a tagged user turn — so the repair op runs off history via a new execAgent `suppressUserMessage` path instead of injecting a synthetic user message. createVerifyMessage is awaited before verification to avoid a race. maxRepairRounds becomes a rubric-level config: new `verify_rubrics.config` jsonb column, read live at repair time via the plan's sourceRubricId. Adds a RubricConfig portal panel (reachable from the plan card's settings affordance) to view/edit it, wired through the verify store + TRPC. Verify domain types/vocab/config are extracted from the DB schema into @lobechat/types as the single source of truth; schema and consumers import from there. Tests: VerifyMessageProcessor dual behavior; VerifyRubricModel config round-trip; MessageModel.findVerifyMessageByOperationId. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * 🗃️ refactor(verify): squash the 3 verify migrations into one Collapse 0110 (tables) + 0111 (criteria.description) + 0112 (rubrics.config) into a single regenerated 0110_add_verify_tables so the PR ships one clean, idempotent migration. No schema change vs the three combined. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ✨ feat(cli): verify rubric run-policy config commands + shrink judging-rule editor font CLI: `verify rubric create --max-repair-rounds`, `verify rubric view`, and `verify rubric update` exercise the rubric config endpoints end-to-end; adds a mocked command test. UI: judging-rule editor font 16px → 14px. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ✨ feat(verify): editable rubric name in the config panel + default 3 repair rounds Add a name (title) field to the RubricConfig portal, persisted via a new updateRubricTitle store action + service (optimistic + debounced, alongside the config write-back). Bump DEFAULT_MAX_REPAIR_ROUNDS 2 → 3. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ♻️ refactor(verify): extract generateVerifyPlan into installable lobe-delivery-checker tool Move the delivery-checker plan-creation flow out of the always-on lobe-agent tool into a new standalone, installable builtin tool `lobe-delivery-checker` (Skill Store, opt-in per agent — not loaded by default). lobe-agent no longer ships generateVerifyPlan. - new packages/builtin-tool-lobe-delivery-checker (manifest/types/systemRole + client Render/Inspector/Portal moved wholesale from lobe-agent) - new serverRuntimes/lobeDeliveryChecker.ts (generateVerifyPlan moved out of lobeAgent.ts), registered alongside verifyResult - registered installable in builtin-tools (no hidden/discoverable:false, not in defaultToolIds/alwaysOnToolIds/runtimeManagedToolIds); renders/inspectors/ portals/identifiers wired; lobe-agent portal entries removed - i18n keys moved builtins.lobe-agent.verifyPlan.* → builtins.lobe-delivery-checker.* Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ✨ feat(agent): add `custom` tool mode; verify agent uses it instead of chat-mode Chat mode's contract is to strip ALL user/agent plugins (strict KB/memory/web allow-list) — so the verify sub-agent couldn't get its writeback tool without a leaky blanket rule. Introduce a third tool mode `custom` where the toolset is EXACTLY the agent's declared plugins (no always-on, no defaults, no activator), for focused builtin sub-agents. - chatConfig.toolMode: 'agent' | 'chat' | 'custom' (overrides enableAgentMode) - AgentToolsEngine: custom branch (defaultToolIds = plugins, rules = plugins-on, allowExplicitActivation only in agent mode); chatModeRules restored to strict - verify agent → toolMode: 'custom'; lobe-verify dropped from chatModeAllowedToolIds - test: custom mode enables exactly the declared plugin, no always-on / defaults Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e855fcc0b8 |
♻️ refactor(desktop): move backend URL rewrite into main process (#15304)
* ♻️ refactor(desktop): move backend URL rewrite into main process Renderer code no longer needs `withElectronProtocolIfElectron` to rewrite backend URLs to `lobe-backend://`. The Electron main process now diverts backend-prefixed paths (`/trpc`, `/webapi`, `/api/auth`, `/market`) to the remote LobeHub server in two places: - prod: `RendererProtocolManager` (`app://` handler) delegates to `BackendProxyProtocolManager.proxy(request, session)` after the existing hostname guard. - dev: `Browser.setupRemoteServerRequestHook` registers a `webRequest.onBeforeRequest` listener that redirects `http://localhost(:*)/<backend-prefix>...` to `lobe-backend://lobe<path>`. `BackendProxyProtocolManager` keeps a per-session `WeakMap<Session, Context>` and exposes `proxy(request, session)` so the same OIDC token / Vercel cookie / 401 debounce / `X-Auth-Required` pipeline serves both entry points. The helper and ~35 call sites in `src/services/_url.ts` and the three tRPC clients are removed. `ELECTRON_BE_PROTOCOL_SCHEME` stays for the main process; new `BACKEND_PATH_PREFIXES` + `isBackendPath` predicate live in `apps/desktop/src/main/const/protocol.ts`. * ♻️ refactor(desktop): decouple renderer protocol from backend proxy via interceptor pipeline `RendererProtocolManager` no longer imports `BackendProxyProtocolManager` or `isBackendPath`. It exposes a generic `addRequestInterceptor(fn)` hook and runs interceptors in order inside the `app://` handler — first non-null Response short-circuits the file pipeline. `BackendProxyProtocolManager.createAppRequestInterceptor()` owns the "what counts as a backend path" knowledge and returns a 502 for backend prefixes when no proxy context is wired up (must not fall through to SPA HTML). Wiring happens in `App.ts` after `RendererUrlManager` construction — composition root knows both modules so neither has to know the other. * ♻️ refactor(desktop): unify dev/prod renderer under app:// and drop lobe-backend:// Dev mode no longer uses `http://localhost:<port>` as the renderer origin; the BrowserWindow now loads `app://renderer/` in both dev and prod. Non-backend requests fall through to a strategy: - prod: `StaticRendererFallback` serves the static export from `rendererDir` (Range support, SPA HTML fallback, 404 handling) - dev: `ViteRendererFallback` proxies to the electron-vite dev server via `net.fetch('http://localhost:5173/<path>')`; HMR WebSocket connects directly (configured via `server.hmr.{host,clientPort}` + `strictPort`) `lobe-backend://` is gone — the scheme, its privileged registration, the `session.protocol.handle('lobe-backend', ...)` call, and the dev `webRequest.onBeforeRequest` trampoline are all removed. `BackendProxyProtocolManager` now only stores per-session context and exposes `createAppRequestInterceptor()` for the `app://` pipeline. Dev userData is pinned to `<appData>/lobehub-desktop-dev` via a new `pre-app-init.ts` that runs before `@/const/dir` captures `app.getPath('userData')` — necessary because dev and prod now share the `app://renderer` origin and would otherwise collide on localStorage / cookies / IndexedDB. Also adds `stream: true` to the `app` scheme privilege so dev media Range requests survive forwarding. |
||
|
|
65ba086685 |
🐛 fix(agent-documents): render system docs in editor (#15462)
* 🐛 fix(agent-documents): render system docs in editor * ✨ feat(agent-documents): autosave highlight editor with safe unmount flush Add debounced autosave to the non-markdown highlight editor and a StrictMode-safe unmount flush via queueMicrotask, plus a beforeunload guard against dirty buffers. * ✅ test: fix agent document PR type checks |
||
|
|
1ce4e026a7 | 🐛 fix(const): point CHANGELOG_URL to /changelog (#15428) | ||
|
|
e1d6b30127 |
🐛 fix(desktop): relocate visual-ref helpers to @lobechat/const to fix renderer crash (#15369)
🐛 fix(desktop): relocate visual-ref helpers to @lobechat/const PR #15114 added @lobechat/prompts + @lobechat/tool-runtime to the desktop nested pnpm workspace. pnpm then linked their @lobechat/types dependency to the desktop type-only stub (apps/desktop/stubs/types) inside the SHARED packages/*/node_modules, which the renderer/web build also consumes. The runtime value import `createVisualFileRef` (in prompts/files/{image,video}.ts) resolved to the stub — which only surfaces types — so the renderer crashed on boot with `SyntaxError: ... does not provide an export named createVisualFileRef`. The stub is load-bearing: pointing the desktop workspace at the real @lobechat/types fails install (model-bank@workspace:* dependency cascade), so the stub must stay. Fix the contract instead: visual-ref helpers are runtime logic, not types, so they don't belong in @lobechat/types. Move the zero-dependency helpers to @lobechat/const/visualRef (already a real desktop member, no cascade) and import them via the narrow subpath. prompts/tool-runtime now only `import type` from @lobechat/types, so the stub link is harmless. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
c8ff3ac43d | ✨ feat: gate agent document floating chat panel (#15260) | ||
|
|
82cc885394 |
🐛 fix(llm-generation-tracing): backfill task_brief / task_brief_judge scenario (#15198)
🐛 fix(llm-generation-tracing): backfill task_brief/task_brief_judge scenario
Brief generation and judge call sites only set `metadata.trigger`, so the
tracing hook fell back to `scenario='unknown'` for every row. Surfaced via
the unknown-scenario cleanup pass: 433 task-brief + 26 task-brief-judge
rows landed in unknown, alongside 434 task-handoff rows that still used
the dashed trigger string.
- Add `task_brief` and `task_brief_judge` to `TRACING_SCENARIOS`
- Add `_PROMPT_VERSION` + `_SCHEMA_NAME` constants for both brief chains,
matching the existing `TASK_TOPIC_HANDOFF_*` convention
- Wire explicit `tracing: { promptVersion, scenario, schemaName }` at all
three task-lifecycle generateObject call sites
- Normalize `metadata.trigger` to underscored ids
(`task_handoff` / `task_brief` / `task_brief_judge`) to match the
`RequestTrigger` enum convention
|
||
|
|
46f884d5ed |
chore(llm-generation-tracing): pre-allocate tracingId + recordFeedback router (#15146)
* ✨ feat(llm-generation-tracing): pre-allocate tracingId + recordFeedback router Wire up the per-call feedback loop foundation. 1. **Pre-allocate tracingId (plan A2)** - `TracingOptions.tracingId?: string` — optional caller-supplied UUID. - `LLMGenerationTracingService.record` generates one via `randomUUID()` when the caller doesn't supply one, so the id is always known before DB insert. - `LlmGenerationTracingModel.record` accepts an optional `id` and forwards it to the insert (Drizzle still autogens when omitted). - `aiChat.outputJSON` allocates the id up-front, threads it through `tracing.tracingId`, and returns `{ data, tracingId }` so the client can wire feedback against the id even though `service.record` runs inside Next's `after()`. - `aiChatService.generateJSON` consumers (InputEditor, supervisor) unwrap the envelope. 2. **New `llmGenerationTracingRouter.recordFeedback`** - Scenario-agnostic feedback endpoint at `lambda.llmGenerationTracing`. - Validates `{ tracingId (uuid), signal (positive|negative|neutral), source, score?, data? }` and forwards to `LLMGenerationTracingService.recordFeedback`. Follow-up issues already filed: - LOBE-9488 — `@lobehub/editor` AutoCompletePlugin needs `onAccept`/`onReject`/`onCancel` callbacks before the client side can capture Tab/Esc/keep-typing signals against the returned tracingId. - LOBE-9489 — session-level signal modeling (multi-suggestion typing sessions) — deferred until per-row feedback data lands. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * 🐛 fix(llm-generation-tracing): surface feedback write failures instead of silent ok The recordFeedback mutation used to always return `{ ok: true }` even when the underlying write was silently dropped — `LLMGenerationTracingService` swallowed both DB-init/update throws and the no-op case where the WHERE clause (id + userId) matched zero rows. Callers couldn't tell "persisted" from "lost", which would skew tracing-feedback metrics and prevent reasoned retry/error handling. Fix: - `LlmGenerationTracingModel.updateFeedback` now returns `{ updated: boolean }` (via `.returning({ id })`), so the caller knows whether the WHERE clause actually matched a row. - `LLMGenerationTracingService.recordFeedback` throws a typed `LLMGenerationFeedbackError` with `kind: 'not_found' | 'db_failure'` instead of swallowing — stops logging-only behaviour for DB errors and promotes the 0-rows case to an explicit signal. - `llmGenerationTracingRouter.recordFeedback` catches that error and translates to `TRPCError({ code: 'NOT_FOUND' })` for stale-id and `INTERNAL_SERVER_ERROR` for DB outages — `{ ok: true }` only flows back when a row was actually patched. Tests: - Model: assert `{ updated: true/false }` for happy / cross-user / missing-id - Service: assert throws on both not_found scenarios - Router: assert TRPCError code translation for both error kinds Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ✨ feat(input-completion): wire Tab/Esc/typing feedback to recordFeedback - bump @lobehub/editor to ^4.12.0 for AutoComplete onSuggestion{Accepted,Rejected} - add llmGenerationTracingService wrapping lambda.llmGenerationTracing.recordFeedback - InputEditor: map suggestionId→tracingId, fire positive on accept, negative on esc, neutral on typing/cursor-move/blur/other; recode IME-driven escape as neutral/autocomplete_ime so CJK input doesn't poison the signal Closes LOBE-9488 * ♻️ refactor(input-completion): fold recordTracingFeedback into aiChatService Single trpc mutation didn't warrant a dedicated service file; aiChatService already owns the paired `outputJSON` call that mints the tracingId, so recordTracingFeedback belongs alongside it. * 💄 style(llm-generation-tracing): tag task-handoff scenario + prompt version (#15191) * 💄 style(QueueTray): use borderless variant for queued file preview Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat(llm-generation-tracing): tag task-handoff scenario + prompt version Task topic handoff was tracing as scenario=unknown / promptVersion=v0 because the generateObject call only set metadata.trigger and that trigger isn't in the registry. Add a TaskHandoff scenario const, version the prompt next to its definition, and pass tracing options explicitly at the call site (mirroring followUpAction). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🐛 fix(llm-generation-tracing): validate caller-supplied tracingId as UUID The `outputJSON` route echoed `tracing.tracingId` back to clients without checking the shape. Because the surrounding `tracing` record is free-form, a malformed value passed request validation, then failed DB insertion on the uuid PK and was later rejected by `recordFeedback` (`z.string().uuid()`), so callers could receive a tracingId unusable for the feedback flow. Tighten `StructureOutputSchema.tracing` to a `z.object({ tracingId: uuid }).catchall(unknown)` so the validation happens at the request boundary; the route can then drop the redundant `typeof === 'string'` guard. --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
f3d5d03cf5 |
♻️ refactor(userMemories): support resolving agent config from ServiceModel (#15138)
* ♻️ refactor(userMemories): support resolving agent config from ServiceModel * ♻️ refactor(userMemories): share memory analysis service model |
||
|
|
775be47513 | 🐛 fix(agent): align settings defaults and locale state (#15163) | ||
|
|
cce14911d1 |
✨ 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> |
||
|
|
f685d5c217 |
✨ feat(agent-explorer): support multi-select delete in document tree (#15125)
* ✨ feat(agent-explorer): support multi-select delete in document tree - Right-click on a multi-selected row deletes the whole selection; dedupe descendants when an ancestor folder is also selected - Reserve chevron slot in SkillsList rows so atomic and bundled skills align - Centralize EMPTY_ARRAY (typed `never[]`, frozen) in @lobechat/const * ♻️ refactor: migrate delete confirm dialog from antd modal to confirmModal * ✅ test: stabilize bun vitest environment * 🔧 ci: avoid authenticated checkout for PR tests |
||
|
|
7eee016abe |
🌐 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> |
||
|
|
de9f7e092a |
✨ 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 |
||
|
|
a41fd95eb5 |
✨ feat(skills): drag skill chips + register agent-document skills (#15095)
* ✨ feat(skills): drag skill chips from the working sidebar into the chat input Pick a project skill from the right Skills panel and drop it onto the chat input to insert a `/<skill-name>` action tag — the same end state as picking it from the `/` slash menu. - `SKILL_DRAG_MIME` lives in `@lobechat/const` so both the producer (sidebar) and the consumer (input drop handler) share one source of truth. - `skillDragData.ts` owns the drag payload and a custom drag image: a themed "icon + name" chip centered above the cursor. The native drag image is suppressed by an invisible 1×1 ghost — the OS bakes its own drop shadow into it which no CSS can remove. Token values are resolved via `getComputedStyle` against the dragged row so the chip stays themed even though it mounts on `document.body`. - `useSkillDrop` listens on the input container and only reacts to the `application/x-lobe-skill` MIME, so it never interferes with the file-upload drop zone (which keys off `Files`). - `ProjectLevelSkills` and `SkillsGroup` wire drag-start with the `projectSkill` category, matching the existing slash-menu behaviour (markdown serializes to `/<skill-name>`). Agent-document skills (the 智能体 Skills group) are not wired here — they need to be registered as first-class skills in the runtime registry first; that work is tracked separately. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * 💄 style(i18n): localize Skills label to 技能 across working sidebar and mention menu - zh-CN: workingPanel.skills.* and resources.filter.skills now use 技能 (covers the Space tab pill plus the agent/project skill section headers) - Wire SkillStore tab and ChatInput mention categories through t() instead of hardcoded English labels; add mention.category.* keys for the five @-menu groups (Agents / Members / Topics / Skills / Tools) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ✨ feat(skills): register agent-document skill bundles in the skill registry Agent-document skill bundles (the "智能体 Skills" panel group, stored as isSkillBundle documents in agent_document) become first-class runtime skills end-to-end, so the slash menu / drag chip / model activation all share one source of truth. Identifier convention: `agent-document:<filename>` (where `<filename>` is the bundle's slug — `validateSkillName`-validated on the server). The prefix prevents collisions with builtin / DB skill names; mirrors the `project:<name>` convention used for filesystem project skills. Server: - `aiAgent/index.ts` SkillEngine assembly: query `agentDocumentsService.getAgentDocuments(resolvedAgentId)`, filter `isSkillBundle`, and merge into the skills array so the model sees them in `<available_skills>`. - `toolExecution/serverRuntimes/skills.ts` factory: when an `agentId` is in the request context, load the bundles + their SKILL.md index children and shape them as `BuiltinSkill` entries, then concat with `filterBuiltinSkills(builtinSkills)` before constructing `SkillsExecutionRuntime`. The runtime resolves builtins by `name` with no DB lookup — so `activateSkill('agent-document:<filename>')` now returns the SKILL.md content for free, no `SkillRuntimeService` extension needed. `source: 'builtin'` on these entries is a type-system carrier shape, not a claim that they're real builtins. Client: - New tool-store slice `agentDocumentSkills` (per-agent scoped, cleared on agent switch). `useFetchAgentDocumentSkills(agentId)` is the SWR hook that keeps the registry hydrated; shares the SWR key with the working-sidebar panel so we never double-fetch. - `useInstalledSkillsAndTools` now reads from the new slice and triggers the SWR hook with the active agent's id, so the `/` menu and any consumer that goes through that hook see agent-doc skills alongside builtin / lobehub / market / user skills. - `AgentDocumentsGroup` wires `onSkillDragStart` on its SkillsList: the payload uses the runtime identifier (`agent-document:<filename>`), while the chip label keeps the human-readable title. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ♻️ refactor(skills): rename agent-doc skill prefix to agent-skills + render <skill> tags Three intertwined fixes around the agent-document skill registry that the earlier commit ( |
||
|
|
6953f188c1 |
✨ 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> |
||
|
|
3bcf6a8d72 |
♻️ 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> |
||
|
|
d3973a5cc0 | ✨ feat: add chat cost estimate support (#14876) | ||
|
|
469a8e6661 |
🐛 fix(conversation): animate only the last markdown block + drop clearMessages hotkey (#14906)
* 🐛 fix(conversation): animate only the last assistant block markdown streaming Switch `withMarkdownStreamingState` from disabling the first block to disabling every block except the last one. The previous logic let middle blocks keep `animated=true` during generation, so any remount mid-stream replayed the typewriter from scratch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🔥 chore(hotkey): remove clearCurrentMessages shortcut Drop the Alt+Shift+Backspace binding from the chat scope. The eraser button in ActionBar still works; only the keyboard shortcut, registry entry, hotkey i18n and docs row are gone. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
e0d20e86fc |
✨ 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> |
||
|
|
875c9b49eb |
🐛 fix: reduce task template skeleton CLS (#14788)
* 🐛 fix: reduce task template skeleton CLS * 🐛 fix: align recommendation skeleton count * 🐛 fix: derive recommendation skeleton count * ✅ test: cover recommendation count without rendering * ✅ test: move recommendation count coverage to const * ♻️ refactor: simplify task template recommendation count * ♻️ refactor: remove task template recommendation aliases * 🐛 fix: use task template count constant in router * ♻️ refactor: remove task template count max |
||
|
|
1914ae6d43 |
🐛 fix(desktop): restrict local file previews (#14789)
* 🐛 fix(desktop): restrict local file previews * 🐛 fix(desktop): close TOCTOU in localfile protocol handler * 🐛 fix(desktop): guard approveWorkspaceRoots against undefined input App.test.ts StoreManager mock returned undefined for unknown keys, causing TypeError when approveWorkspaceRoots tried to call .map(). Added default parameter and updated mock to return defaultValue. * ✅ test: stabilize ci dependency resolution |
||
|
|
5b7611615e |
🐛 fix: system bot error (#14784)
* chore: add start link short cut * chore: update qq zh files * fix: add messenger block message alert * chore: update i18n files * fix: messenger router bridge * fix: dm thread create problem * chore: remove lab prefer for messenger * chore: update i18n files * fix: e2e test |
||
|
|
9075d5dfd3 |
refactor: merge agent marketplace into web onboarding
* ✨ feat(desktop): open-in-app + agent files tab + localfile protocol Bundle three related desktop features: - Open-in-app: IPC contract, main-process detector/launcher/icon-extractor, renderer service, OpenInAppButton + hook, agent header / portal / files-tab integration, user preference (defaultOpenInApp). - Agent files tab: working sidebar files tab with file tracking, store wiring, i18n, reveal-in-tree action in Review/FileItem. - LocalFile protocol: serve binary images via localfile:// for inline preview in the review panel. * 🐛 fix: add explicit type annotation for ref parameter in Files test Fix TS7031: Binding element 'ref' implicitly has an 'any' type. This error was caught by tsgo type-check in CI. * 🐛 fix: address codex review feedback (P1 reveal retry + P2 WebStorm Windows detection) * 🐛 fix(open-in-app): avoid process.platform reference in renderer The Electron renderer sandbox does not expose `process`, so reading `process.platform` in the useOpenInApp hook crashes with a ReferenceError on app launch. Use the `window.lobeEnv.platform` value already exposed via preload contextBridge instead. * 🐛 fix(conversation): keep assistant runtime errors outside workflow collapse When an assistant block carries a runtime error, render the error in the answer segment instead of letting it fold into the workflow collapse with the surrounding tool calls. * ✨ feat(portal): add file viewer tab strip and local file protocol improvements - Add tabbed interface for local file portal viewer - Extend LocalFileProtocolManager with audio MIME type support - Add portal actions for file navigation and tab management - Improve OpenInAppButton and conversation header integration - Update working sidebar resources section - Add comprehensive portal action tests * ✨ feat(agent-sidebar): redesign Review panel and refine Files explorer - Review: drop antd Collapse, replace with a linear disclosure list (hairline dividers, no rounded cards, chevron-left, role=button rows). Add motion height/opacity expand animation. Compact row spacing. Move hover-revealed copy/reveal/revert into an absolute Flexbox with a gradient mask so they overlay the right edge without taking layout. - Files: extract useGitWorkingTreeFiles hook + tests; surface git status entries in the working tree explorer. - ExplorerTree: share folder icon style; minor type tweak. - Locales: new chat strings for the above. * 🐛 fix(test): add missing chatConfigByIdSelectors mock to WorkingSidebar test |
||
|
|
1c429f8d28 |
✨ feat(chat): add Onboarding request trigger and pass via metadata (#14770)
* ✨ feat(chat): add Onboarding request trigger and pass via metadata - Add RequestTrigger.Onboarding for onboarding chat requests - Replace requestTrigger option with metadata.trigger across chat service / executors - Tag onboarding agent send-message with metadata.trigger = Onboarding - Persist trigger on message metadata for billing & logs * 🔨 chore(chat): share request context header constants * 🐛 fix(chat): preserve trigger on tool resumes * 🔧 chore(builtin-agents): expose package entry types * ✅ test(types): preserve request trigger metadata * 🐛 fix(chat): scope resumed trigger metadata to message chain |
||
|
|
ac250b9897 | ♻️ refactor(agent-signal,server,app,database,locales): self iteration exits lab (#14769) | ||
|
|
ccddbaa25d |
♻️ refactor(builtin-tool): move sub-agent dispatch from lobe-gtd to lobe-agent (#14715)
* ♻️ refactor(builtin-tool): move sub-agent dispatch from lobe-gtd to lobe-agent
Move the `execTask` / `execTasks` capability out of `packages/builtin-tool-gtd/`
and into `packages/builtin-tool-lobe-agent/`, renaming the public APIs to
`callSubAgent` / `callSubAgents`. The "subtask" naming inside GTD overlapped
with the new lobe-task tool's task model and conflated planning with
sub-agent dispatch.
- API names: `execTask` → `callSubAgent`, `execTasks` → `callSubAgents`
- TS types: `ExecTaskParams` → `CallSubAgentParams`, etc.; introduce
`SubAgentTask` to replace `ExecTaskItem`
- Client UI (Inspector / Render / Streaming) ported under
`packages/builtin-tool-lobe-agent/src/client/`
- Central registries (`packages/builtin-tools/src/{inspectors,renders,streamings}.ts`)
updated to register lobe-agent
- GTD `meta.description` and system role no longer mention async tasks;
they point to lobe-agent for sub-agent dispatch
- `isSubTask` filtering in `agentConfigResolver` now excludes `lobe-agent`
(new owner of sub-agent dispatch) instead of `lobe-gtd`
- i18n: new `builtins.lobe-agent.apiName.callSubAgent*` and
`workflow.toolDisplayName.callSubAgent*` keys in default/zh-CN/en-US
Kept the executor's emitted `state.type` values (`execTask` / `execTasks` /
`execClientTask` / `execClientTasks`) unchanged so the agent-runtime
instruction layer (`exec_task` / `exec_tasks` / `exec_client_task*`) and all
downstream tests / heterogeneous executors (`builtin-tool-agent-management`,
server `agentManagement` runtime) continue to work without modification.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ♻️ refactor(chat): rename isSubTask flag to isSubAgent
After moving sub-agent dispatch from lobe-gtd to lobe-agent, the flag name
no longer matches what it controls. Rename `isSubTask` → `isSubAgent` across
the chat / agent runtime layer and update related comments and test labels.
- `agentConfigResolver` context field + filter helper
- `streamingExecutor.internal_createAgentState` + `executeClientAgent`
signatures and call sites
- `createAgentExecutors` (exec_task / exec_client_task handlers) and
`GroupOrchestrationExecutors` (batch_exec_async_tasks)
- `chatService.createAssistantMessageStream` `resolvedAgentConfig` docs
- Test descriptions and assertions in `agentConfigResolver.test.ts` and
`streamingExecutor.test.ts`
No behavior change — the flag's filter target (`lobe-agent` identifier) is
unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ♻️ refactor(agent-runtime): rename exec_task wire identifiers to exec_sub_agent
Bring the agent-runtime "wire" naming in line with the lobe-agent
callSubAgent / callSubAgents API rename. Three layers are renamed in lockstep
to keep the bridge between tool executors and the runtime consistent:
1. Tool-emitted state.type discriminators
- 'execTask' → 'execSubAgent'
- 'execTasks' → 'execSubAgents'
- 'execClientTask' → 'execClientSubAgent'
- 'execClientTasks' → 'execClientSubAgents'
2. AgentInstruction.type and matching TS interfaces
- 'exec_task' / 'exec_tasks' / 'exec_client_task' / 'exec_client_tasks'
→ 'exec_sub_agent' / 'exec_sub_agents' / 'exec_client_sub_agent' /
'exec_client_sub_agents'
- AgentInstructionExecTask → AgentInstructionExecSubAgent (and the three
siblings)
- ExecTaskItem → SubAgentTask
3. AgentRuntimeContext.phase + matching payload types
- 'task_result' → 'sub_agent_result'
- 'tasks_batch_result' → 'sub_agents_batch_result'
- TaskResultPayload → SubAgentResultPayload
- TasksBatchResultPayload → SubAgentsBatchResultPayload
Also renames the operation-type discriminator 'execClientTask' /
'execClientTasks' to 'execClientSubAgent' / 'execClientSubAgents' and updates
its locale string in default / zh-CN / en-US.
Tests / fixtures / mocks updated in lockstep:
- packages/agent-runtime/src/agents/{GeneralChatAgent.ts,__tests__/...}
- packages/builtin-tool-{lobe-agent,agent-management}/src/...
- src/server/services/toolExecution/serverRuntimes/agentManagement.ts
- packages/agent-mock/src/cases/builtins/todo-write-stress.ts (helper renamed
to callSubAgent)
- src/store/chat/agents/createAgentExecutors.ts + exec-task / exec-tasks tests
+ fixtures/mockInstructions.ts (createExecSubAgent[s]Instruction)
- src/store/chat/slices/aiChat/actions/streamingExecutor.ts (phase check)
- packages/conversation-flow/src/__tests__/fixtures/**/*.json (8 fixtures
retargeted from lobe-gtd/execTask[s] to lobe-agent/callSubAgent[s] with the
new state.type wire values)
No behavior change — the agent runtime, executors and tests all go through
the same code paths; only the strings on the wire change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ♻️ refactor(builtin-tool): absorb GTD tool (plan + todo) into lobe-agent
Delete `packages/builtin-tool-gtd/` and fold its full surface — plan, todo,
ExecutionRuntime, all client UI (Inspector / Render / Streaming /
Intervention / SortableTodoList) and the system role — into
`packages/builtin-tool-lobe-agent/`. Single `lobe-agent` identifier now
owns: plan + todo management, sub-agent dispatch, and visual media analysis.
Also restructures the lobe-agent package so the executor lives under
`./client/` alongside the UI it ships with, and drops the dedicated
`./executor` export — consumers go through `./client` for everything
client-side.
Package-level changes:
- DELETE `packages/builtin-tool-gtd/` entirely.
- `packages/builtin-tool-lobe-agent/`
- Move `src/executor/` → `src/client/executor/`. Drop `./executor` from
`package.json` exports; expose `lobeAgentExecutor` via `./client` only.
- Rename `GTDExecutionRuntime` → `PlanExecutionRuntime` and place under
`src/client/executor/PlanRuntime/`. Re-export from package root so the
server runtime can consume it without pulling in client UI deps.
- Extend `LobeAgentExecutor` with `createPlan` / `updatePlan` /
`createTodos` / `updateTodos` / `clearTodos`, all delegated to the
shared runtime.
- Add Plan + Todo API entries to the manifest (with their original
descriptions, humanIntervention, renderDisplayControl).
- Move all GTD client UI verbatim:
`Inspector/{ClearTodos,CreatePlan,CreateTodos,UpdatePlan,UpdateTodos}`,
`Render/{CreatePlan,TodoList}`, `Streaming/CreatePlan`,
`Intervention/{AddTodo,ClearTodos,CreatePlan}`,
`components/SortableTodoList`. Register them in
`LobeAgentInspectors / Renders / Streamings`, add new
`LobeAgentInterventions`.
- Merge GTD system role into lobe-agent's (`<plan_and_todos>` plus the
existing `<sub_agents>` and `<run_in_client>` sections).
- `package.json`: pick up `@lobechat/prompts` dep and `@lobehub/editor` +
`antd` + `lucide-react` peer-deps inherited from GTD.
Central registries (`packages/builtin-tools/src/*`) and consumers:
- Remove every `GTDManifest / Inspectors / Renders / Streamings /
Interventions` import + registration; existing `LobeAgent*` registrations
now cover them.
- Replace `[GTDManifest.identifier]: GTDInterventions` with
`[LobeAgentManifest.identifier]: LobeAgentInterventions`.
- Drop `@lobechat/builtin-tool-gtd` workspace dep from
`packages/builtin-tools/package.json`, `packages/builtin-agents/package.json`
and root `package.json`.
- Remove `gtdExecutor` from `src/store/tool/slices/builtin/executors/index.ts`;
switch `lobeAgentExecutor` import to `/client`.
- Replace `serverRuntimes/gtd.ts` with a service factory
`serverRuntimes/lobeAgentPlan.ts` (`createServerPlanRuntimeService`).
`serverRuntimes/lobeAgent.ts` instantiates `PlanExecutionRuntime` with
that service so the registry exposes one runtime per `lobe-agent`
identifier covering both visual analysis and plan/todo.
- `services/chat/mecha/contextEngineering.ts`: gate plan/todo injection on
`LobeAgentIdentifier` instead of `GTDIdentifier`.
- `agentConfigResolver.test.ts`: switch fixture plugin IDs to
`LobeAgentIdentifier`.
- `packages/const/src/recommendedSkill.ts`: drop the standalone `lobe-gtd`
recommendation — `lobe-agent` already covers it via `defaultToolIds`.
i18n migration (default + zh-CN + en-US; other locales regenerate on
`pnpm i18n`):
- `builtins.lobe-gtd.*` → `builtins.lobe-agent.*` in `plugin.ts/json`.
- `lobe-gtd.*` (tool namespace) → `lobe-agent.*` in `tool.ts/json`.
- Remove `tools.builtins.lobe-gtd.{description,readme,title}` from
`setting.ts/json` (lobe-agent has its own meta now).
- Update all client component `t(...)` keys to the new namespace.
Mocks / fixtures / tests:
- `packages/agent-mock/src/cases/builtins/todo-write-stress.ts`: all
`identifier: 'lobe-gtd'` → `'lobe-agent'`; helper comments updated.
- `packages/types/src/stepContext.ts`: comment refers to
`builtin-tool-lobe-agent` (the only consumer of `StepContextTodoItem`).
- `packages/model-runtime/src/core/streams/google/google-ai.test.ts`:
function-call names from `lobe-gtd____createPlan` etc. → `lobe-agent____*`.
- `src/store/chat/slices/message/selectors/dbMessage.test.ts`: same.
- `src/features/DevPanel/RenderGallery/fixtures/lobe-gtd.ts` deleted; its
plan/todo fixtures are folded into `fixtures/lobe-agent.ts` alongside the
existing `callSubAgent[s]` ones.
- Replace `console.log` → `console.info` in moved client components to
satisfy lobe-agent's stricter ESLint rules (GTD package allowed
`console.log`; lobe-agent inherits the repo-wide `no-console` rule).
No behavior change for end users: `lobe-agent` now owns all the APIs,
identifiers, and UI that previously lived in `lobe-gtd`, but as a single
consolidated package under a single tool identifier.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ♻️ refactor(context-engine): drop residual GTD naming, rename to PlanInjector / TodoInjector
Follow-up to
|
||
|
|
dfb5e0176e |
✨ feat(markdown): user_feedback card + task card polish + Run now context menu (#14727)
* ✨ feat(markdown): render <user_feedback> task prompt blocks as a card `buildTaskRunPrompt` wraps the user's pre-run comments in a `<user_feedback>` block alongside `<task>`. The Task plugin captured `<task>` into a card, but `<user_feedback>` had no plugin and leaked into the chat as raw XML. Because CommonMark only treats tag names matching `[a-zA-Z][a-zA-Z0-9-]*` as html, the underscore in `user_feedback` puts the opening/closing tags inside a `paragraph` as plain text — so the new remark plugin walks paragraph children rather than html nodes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style(task-card): drop standalone status row + Agent/Parent/Topics, inline semantic status badge The status/Priority row, Agent, Parent and Topics fields aren't useful when the task card is rendered inside the topic chat drawer (the drawer already exposes that context). Move the task status to a compact badge beside the identifier and reuse `taskDetail.status.*` for the label so "scheduled" reads as "Scheduled" / "已排期". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style(user-feedback): compact one-line header + left-border quote-style card Slims the card down to a single 12px header line ("User feedback · N comments") with a small 12px icon, and wraps the whole block in a subtle fill + 2px left-border accent so it reads as a quoted aside and visually separates from the task card that follows in the same user message body. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style(user-feedback): drop fill + radius, render as plain left-rail blockquote The filled card competed visually with the unstyled task block that sits beside it in the same message body. Reducing to a 2px left-rail quote without background or border-radius lets both blocks read as parts of the same user message. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style(user-feedback): collapsible card with task-style head + bottom divider Default-collapsed `<details>` whose summary mirrors the task title row (32px icon + bold label + small count badge), with a bottom split-line that doubles as a divider between the user feedback head and the task card that follows in the same message body. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style(user-feedback): strip default markdown details card chrome @lobehub/ui Markdown applies bg + padding (0.75em 1em) + box-shadow + border-radius to every nested <details>, which made the user_feedback head read as a wide standalone card sitting awkwardly on top of the inline task title. Override the chrome (with !important — the lib selector wins on specificity otherwise) so the head sits flat in the message body, with only the bottom split line separating it from the task that follows. The lib's right-side disclosure chevron is kept. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style(user-feedback): match task card's 12px symmetric divider spacing Add a 12px margin-bottom so the gap below the user_feedback bottom rule mirrors the 12px above it, matching the symmetric 12px the task card already uses around its own internal divider. Without this, the user_feedback rule sat flush against the T-31 row while the next rule below T-31 had a 12px gap on both sides — visually uneven. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style(task-card): drop status badge from task title row The task drawer header and the schedule strip on the task detail page already convey status; surfacing it again on the task card inside the chat body just added noise. Drop the badge along with the now-unused KNOWN_STATUSES / isKnownStatus / TaskStatusIcon / useTranslation plumbing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat(tasks): add "Run now" item to task card context menu Available only for backlog and completed tasks; mirrors the inbox-agent fallback used by the detail-page Run Now action. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🐛 fix(topic-list): preserve `#` icon placeholder for heterogeneous agents Returning null for the icon slot collapsed the row layout, so titles on heterogeneous-agent topics (Claude Code, Codex, …) no longer aligned with sibling rows. Render the same HashIcon with visibility:hidden so the box is preserved without showing the glyph. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
5d6d01601d |
🐛 fix(builtin-tool-task): expose lobe-task and add setTaskSchedule (#14713)
* ✨ feat(builtin-tool-task): expose lobe-task to users and add schedule config The task tool is now generally available — flip it from a scenario-only internal tool to a user-toggleable recommended skill, and let the LLM configure recurring execution (cron or heartbeat) via createTask / editTask. - Drop `discoverable: false` + `hidden: true` from TaskManifest registration - Add `lobe-task` to RECOMMENDED_SKILLS so it stays installed by default - Remove the USER_HIDDEN_BUILTIN_TOOL_IDS allowlist (only contained lobe-task); update selectors and AgentTool to stop filtering it out - Extend createTask / createTasks / editTask with `automationMode`, `schedulePattern`, `scheduleTimezone`, `heartbeatInterval`; editTask also accepts `maxExecutions` - Route schedule columns through taskService.update and maxExecutions through taskService.updateConfig (server merges into tasks.config.schedule); refresh detail once at the end of editTask Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ♻️ refactor(builtin-tool-task): split schedule config into dedicated setTaskSchedule tool editTask was the wrong place for schedule fields — schedule needs its own verb so the LLM (and any future human-in-the-loop review) can audit cron / heartbeat changes separately from generic field edits, and createTask should stay a pure "make a task" verb without automation knobs. - Drop automationMode / schedulePattern / scheduleTimezone / heartbeatInterval from createTask + createTasks, and drop them plus maxExecutions from editTask - Add new `setTaskSchedule(identifier, automationMode?, schedulePattern?, scheduleTimezone?, heartbeatInterval?, maxExecutions?)` API with its own manifest entry, executor method, types, i18n key, and inspector - Schedule columns still route through taskService.update; maxExecutions still routes through taskService.updateConfig (server merges into tasks.config.schedule) — same wiring, just moved into the dedicated tool - Update systemRole to advertise setTaskSchedule + keep editTask description clean of schedule mentions Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
6a66901b12 |
🔥 chore: drop task template tracking (#14666)
* 🔥 chore: drop task template tracking The recommendation surface is about to be redesigned, so the analytics funnel added in #14517 is being removed up front. A fresh tracking schema will land alongside the redesigned UI. - Delete `analytics.ts` plus its test and the tracking-focused `TaskTemplateCard.test.tsx`. - Drop `RecommendedTaskTemplate` / `TaskTemplateRecommendationSource` / `TaskTemplateFallbackPool` and revert the service to plain `TaskTemplate[]`. - Strip impression, dismiss, create-clicked/result and skill-connect-clicked/result calls from `TaskTemplateCard.tsx`, while keeping the createTask + navigate-to-task flow from #14540. - Remove `recommendationBatchId` / `userInterestCount` / `onCreated` plumbing from `useDailyBriefRecommendationsUI`, `DailyBriefRecommendationsView`, and the card props. - Revert `useSkillConnection` to the pre-tracking variant (no onConnectResult / SkillConnectionResult). * 🐛 fix: remove created template from recommendation cache After #14540 changed the create-task flow to auto-navigate to `/task/{id}`, removing the `onCreated` plumbing from #14517 in the same sweep meant the SWR recommendation cache was never mutated on success. Combined with the server-side `recordCreated` being a no-op and `listDailyRecommend` not excluding created IDs, returning to Home showed the same recommendation as actionable again — letting users trigger duplicate scheduled tasks from the same template. Re-add the minimal cache-eviction plumbing (no analytics): - TaskTemplateCard exposes `onCreated` and calls it on success - useDailyBriefRecommendationsUI shares `removeTemplateFromList` for both dismiss and created flows - DailyBriefRecommendationsView passes `onCreated` through |
||
|
|
58318e97df | 🐛 fix: store onboarding interests as keys (#14624) | ||
|
|
b180c03e04 |
✨ feat: migrate Notion to LobeHub Market (#14578)
Migrate Notion to LobeHub Market |
||
|
|
83bc73c2ae | ✨ feat: add task template tracking (#14517) | ||
|
|
a372acd50d |
✨ feat: add lobeAgents markdown tag for inline agent card rendering (#14495)
* ✨ feat: add lobeAgents markdown tag for inline agent card rendering Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * 📝 docs(agent-management): instruct LLM to render lobeAgents card after agent operations Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * 🐛 fix(lobe-agents): support single-quoted attrs and preserve trailing paragraph siblings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
43b064f803 | ✨ feat: add RecommendTaskTemplates UI and default noop router (#14488) | ||
|
|
e6d49fdb76 | 🐛 fix: track visual analysis trigger (#14399) | ||
|
|
df32dd4966 | ✨ feat: support model defaults and DeepSeek pricing (#14379) | ||
|
|
990942fb45 |
✨ feat(agent-marketplace): fetch onboarding templates from market API (#14286)
* ✨ feat(agent-marketplace): implement onboarding agent marketplace picker Adds a new builtin tool `@lobechat/builtin-tool-agent-marketplace` that opens a categorized agent picker UI during web onboarding. The picker fetches the live curated catalog from the marketplace API (`/api/v1/agents/onboarding-full`) via a TRPC procedure that injects the trust-token, and lets the user select template agents to install. Highlights: - Self-contained marketplace package with manifest, system role, executor, and ExecutionRuntime - React intervention component with category sidebar, skeleton loading state, and avatar/empty/error UI; all user-visible strings i18n-driven - Dependency-inverted fetcher: package exports `setAgentTemplatesFetcher`, app registers a TRPC-backed implementation in AgentOnboardingPage - New TRPC `market.agent.getOnboardingFull` proxies the upstream API with trust-token authentication; client never sees secrets - Splits the existing `saveUserQuestion` intervention into agent identity and user profile cards for clearer onboarding approval UX - Wires marketplace into `builtin-tools` registry, executor map, and onboarding metrics; web-onboarding agent system prompt updated to reference the picker Closes LOBE-7801 * ✨ feat(onboarding): enhance early exit handling and marketplace integration in onboarding flow Signed-off-by: Innei <tukon479@gmail.com> * 🐛 fix(agent-marketplace): register server runtime, scope picks per-topic, and harden onboarding handoff prompts The summary phase silently skipped the marketplace handoff because the server toolExecution registry had no runtime for `lobe-agent-marketplace`, so every `showAgentMarketplace` call returned "not implemented" and the agent fell through to `finishOnboarding`. The runtime-injected phase guidance and action hints also instructed the agent to call finishOnboarding directly after the summary, contradicting the new system role. - Register `agentMarketplaceRuntime` in `src/server/services/toolExecution/serverRuntimes` so the executor can actually run. - Scope the in-memory `picks` map by `topicId` and reject a second `showAgentMarketplace` call in the same conversation with a clear "already opened, finish on next turn" message. - Tighten the success content to instruct the model to STOP the current turn after opening the picker and run closing + finishOnboarding on the FOLLOWING user turn. - Update `OnboardingActionHintInjector`, `PHASE_GUIDANCE.summary`, `toolSystemRole` and `web-onboarding/systemRole` so all four prompt layers agree: open the picker exactly once during summary, do not call finishOnboarding in the same turn, and do not call the submit/skip/cancel APIs ourselves. - Stop treating short affirmations like "好的" / "行" / "ok" as early-exit signals; they are confirmation of the summary and should let the picker handoff proceed normally. Verified end-to-end with `bun run agent-evals run onboarding/web-onboarding-v3 --case-id fe-intj-crud-v1 --model deepseek-v4-pro`: hard assertions all pass, judge moves from 7/10 (premature finishOnboarding in same turn) to 8/10 with picker opened once and finishOnboarding deferred to the next turn. * fix(ci): attempt 1 for PR #14286 Auto-generated by pr-dispatcher (task: 01KQBY8GAC1MNQCJ6T6X5DEP2F, attempt: 1). Co-Authored-By: Claude <noreply@anthropic.com> * 🐛 fix(agent-marketplace): wire picker submit + fix marketplace-already-opened detection The marketplace picker confirm flow was sending the user's selection back as a synthetic user message, and the action hint kept telling the model to open the marketplace again — leading to a death loop where the agent re-opened the picker instead of summarizing + persisting + finishing onboarding. Two issues: 1. Pick confirm forwarded the selection as a user message instead of forking the agents and resuming from the tool result. Wire `prepareCustomInteractionSubmit` into the intervention's submit branch so it runs `installMarketplaceAgents` client-side and returns a descriptive `toolResultContent`. Plumb a `createUserMessage: false` + `toolResultContent` option through `submitToolInteraction` (slice + chat store): when set, skip the synthetic user message, override the tool message content, and resume runtime from the tool message (`parentMessageType: 'tool'`) so the LLM sees the install result and continues from there. 2. `OnboardingActionHintInjector.marketplaceAlreadyOpened` read `msg.tool_calls`, but this provider runs in pipeline phase 4.5 (virtual tail guidance) BEFORE `ToolCallProcessor` (phase 5) converts DB-shape `tools` → OpenAI-shape `tool_calls`. Detection always returned false → the hint kept saying "call showAgentMarketplace" → death loop. Fix: match on `tools[].apiName` (with `tool_calls` kept as a fallback). Also rewrote the Summary-phase hints to reflect the new flow (picker resolves directly via tool result, no synthetic user reply needed). Includes intervention bar portal-target plumbing for approval actions. * ✨ feat(onboarding): wire marketplace picker analytics on agent onboarding page Mount AnalyticsBridge under AgentOnboardingPage to inject useAnalytics() into setOnboardingAnalyticsClient, so onboarding_marketplace_shown/picked events emit through PostHog instead of being silently dropped. Adds spm fields to align with onboardingFeedback's telemetry shape. * ♻️ refactor: move DEFAULT_ONBOARDING_MODEL to business-const Made-with: Cursor * ✨ test(customInteractionHandlers): add tests for persisting marketplace picks and resolutions Signed-off-by: Innei <tukon479@gmail.com> * ✨ feat(onboarding): enhance agent marketplace integration with metadata persistence Signed-off-by: Innei <tukon479@gmail.com> * ✨ feat(agent): add web onboarding agent selectors and integrate into Actions and Usage components Signed-off-by: Innei <tukon479@gmail.com> --------- Signed-off-by: Innei <tukon479@gmail.com> Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
a099749b41 | ♻️ refactor(taskTemplate): use string icon identifiers (#14302) | ||
|
|
9555e4fda3 |
✨ feat: task card, agent profile nav, CC streaming, view switcher polish (#14277)
* 💄 style(home): collapse empty suggest questions wrapper on default home Why: when enableAgentTask is on, SuggestQuestions and CommunityRecommend both render null on the default home view, but the AnimatePresence wrapper still mounted with marginTop:24 and produced a large empty gap between StarterList and DailyBrief. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat(task): add cron-based task schedule dispatcher Wires up backend execution for task-level cron schedules. Adds two QStash workflows-hono routes: - POST /api/workflows/task/schedule-dispatch — central sweep, point a QStash Schedule (e.g. */30 * * * *) here. Loads all schedule-mode tasks, filters by cron pattern + timezone + lastHeartbeatAt dedup, and fans out per-task messages. - POST /api/workflows/task/schedule-execute — internal per-task handler that re-validates DB state and runs the task via TaskRunnerService. Reuses existing schedulePattern / scheduleTimezone columns and lastHeartbeatAt for dedup — no migration needed. Failure paths fall through to the existing onTopicComplete error handling (urgent brief + paused). * 💄 style(task): collapse resolved brief card on detail by default Why: resolved briefs on the detail page rarely need re-reading; matching home's collapse-when-resolved behavior keeps the activity feed compact. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat(agent-profile): make popup header navigate to agent profile Click on the avatar/title in AgentProfilePopup now closes the popup and routes to /agent/:id/profile. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat(task): render task XML as a card in topic chat drawer Why: the topic drawer's first user message is the task run prompt — a `<task>...</task>` XML blob (identifier, status, instruction, agent, …). Rendering it as raw XML buries the structure the user actually cares about. - Add a `Task` markdown plugin (scope: user) that parses the `<task>` payload and renders an Artifacts-style card. - Use a custom remark plugin so the block survives mdast splitting it across html + paragraph nodes. - Gate the card UI behind a `TaskCardScope` React Context so it only activates inside `TopicChatDrawer`; everywhere else falls back to a plain `<pre>`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat(claude-code): reuse result renders during streaming via wrapRender Why: while a CC tool is still executing, the detail view fell back to a generic argument table for everything except `Agent`. Read/Write/Edit/Glob/Grep/Skill/Bash/TodoWrite already gracefully degrade their result Render when `content`/`pluginState` are absent, so the same component works for the live phase too. - Add `wrapRender` helper that adapts a `BuiltinRender` into a `BuiltinStreaming` by passing `content: null`. - Register Bash/Edit/Glob/Grep/Read/Skill/TodoWrite/Write streaming entries through `wrapRender`. `Agent` keeps its bespoke streaming view. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ♻️ refactor(task-subtasks): drop legacy blockedBy flattening branch Why: subtasks now always arrive as a real tree from the upstream service, so the fallback that re-built the tree from a flat list via `blockedBy` is dead code. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🐛 fix(view-switcher): hide chat/task switcher for heterogeneous agents Why: the chat/task view switcher in the agent header doesn't apply when the agent is heterogeneous (Claude Code / Codex / etc.) — those agents don't share the task topic flow, so showing the switch surfaces a non-functional control. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat(task-topic): show elapsed duration on completed topic runs Mirror task_topics terminal transitions (completed / failed / canceled / timeout) onto topics.completedAt so the activity feed can render elapsed time for finished runs, not just for the live one. Thread completedAt through findWithHandoff and the TaskDetailActivity payload, then extend TopicCard to render formatDuration(completedAt - createdAt) for non-running statuses. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🐛 fix(task-trigger-tag): respect automationMode when rendering schedule label Heartbeat tasks were displaying cron schedule text when the DB still carried a schedulePattern from a previous mode. Switch to automationMode as the source of truth in TaskTriggerTag and pass it from all three call sites. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
19643ba662 | ✨ feat(task-template): add home recommendation system with skill connect (#14214) | ||
|
|
a176288670 |
💄 style(conversation): persist per-topic chat scroll position (#14191)
* ✨ feat(conversation): persist per-topic chat scroll position to localStorage Restores scroll position when switching back to a topic, keyed by messageMapKey(context). Falls back to scroll-to-bottom for new topics or when the user was already at the bottom. Storage is capped at 500 entries with 30-day expiry and silent fallback on quota errors. Fixes LOBE-8251 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🔨 chore(conversation): rename scroll snapshot storage prefix to LOBEHUB Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🔨 chore(conversation): use LOBEHUB_SCROLL as scroll snapshot key prefix Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🐛 fix(conversation): preserve scroll across draft-to-topic key transition When a draft conversation (`*_new` key) gets promoted to a real topic via onTopicCreated, the contextKey changes mid-stream for the same logical conversation. Treating it as a topic switch loaded a missing snapshot and fell back to scrollToIndex(end), yanking users away from content they were reading. Now we detect the draft-promotion shape, migrate the snapshot to the new key, and skip the restore pass while data is already on screen. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🔥 chore(settings): remove queryRewrite system agent Removes the unused knowledge-base query rewrite system agent: settings UI in agent/service-model pages, type definition, default config, store selector, server env parser, locale strings across 18 languages, env-variable docs, and the now-orphan chainRewriteQuery prompt chain. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
56bc216c5e | ✨ feat(agent-signal,app,const,types): added self interation into lab, and feature flag (#14169) | ||
|
|
01f6858cc1 |
🔥 feat(heterogeneous-agent): remove lab flag for GA rollout (#14162)
* 🧹 chore: remove unused desktop upload IPC * 🔥 feat(heterogeneous-agent): remove lab flag for GA rollout External CLI agents (Claude Code, Codex) are now always available on desktop without the lab toggle. Drops the `enableHeterogeneousAgent` preference, selector, settings switch, locale strings, and menu-item gating. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ⬆️ chore(deps): bump @lobehub/ui to ^5.9.6 and @lobehub/editor to ^4.9.3 Unpin from exact versions so future patch/minor releases roll in automatically. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
043d2a81fb |
✨ 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 |
||
|
|
9b6a60339f | 🐛 fix: default DeepSeek V4 reasoning control (#14131) | ||
|
|
82ba3706a7 |
✨ feat(desktop): screen capture overlay, Quick Chat tray, and upload pipeline improvements (#13818)
* feat: add screen capture functionality with overlay support - Implemented ScreenCaptureManager to handle screen capture sessions. - Added ScreenCaptureCtr for IPC methods related to screen capture. - Created overlay.html and ScreenCaptureOverlay component for user interaction. - Integrated window enumeration and capture logic using node-screenshots and get-windows. - Updated menu options to include screen capture actions. - Enhanced RendererUrlManager to support overlay routing. - Introduced drag selection for capturing specific screen areas. - Added necessary types and events for screen capture in electron-client-ipc. Signed-off-by: Innei <tukon479@gmail.com> * ✨ feat(desktop): refine screen capture overlay flow * ✨ feat(desktop): refine screen capture overlay flow * ⚡ feat(desktop): optimize screen capture overlay flow * Delete apps/desktop/mockup/screen-capture-overlay.html * ✨ feat(desktop): open mini toolbar via double Option * 🐛 fix(desktop): separate quick composer hotkey * 💄 fix(desktop): remove stale quick composer accelerator * 🐛 fix(desktop): stabilize double option monitor * 🐛 fix(desktop): read hardware option key state * 🐛 fix(desktop): standardize path imports and improve error handling - Replaced `join` imports with `path` imports for consistency across files. - Enhanced error handling in various modules to include error causes for better debugging. - Updated test files to reflect changes in variable naming and mock implementations. Signed-off-by: Innei <tukon479@gmail.com> * 🔥 chore(hotkey): drop orphan renderer quickComposer i18n entries The `quickComposer` hotkey is registered only on the Electron side (DESKTOP_GLOBAL_SHORTCUT_DEFAULTS + BrowserWindowsCtr.openQuickComposer); the renderer never referenced these i18n keys, so the entries were dead. `desktop.quickComposer` covers the app-level trigger. * ⚡️ perf(screen-capture): parallelize overlay upload with route navigation Overlay submit used to await screenshot upload before router.push, blocking the main window for several seconds when the user was on an unrelated page (e.g. /settings). Now we navigate immediately and run upload in a background IIFE; MessageFromUrl waits on a new `uploadStatus` field before calling sendMessage, so the chat page mount and the upload proceed in parallel. - Add `uploadStatus: 'uploading' | 'ready' | 'failed'` to PendingOverlayDispatch; canConsumePendingOverlayDispatch blocks while `'uploading'`. - Store gains `markDispatchUploadComplete`; on failure it clears screenshotFileNames so the prompt still delivers. - Dispatcher drops stale prev search params on push to prevent MessageFromUrl's message-param effect from double-firing. * ⚡️ perf(screen-capture): pre-upload captures in overlay preview + per-thumbnail status Move uploads from post-submit to preview time, bypassing dataUrl round-trips: - Main process assigns captureId at preview time and ships the PNG bytes as ArrayBuffer to the main renderer via `overlayUploadRequest`. - Main renderer uploads through a dedicated pool (uploadWithProgress, no chatUploadFileList pollution); reports status back to the overlay through `overlayCaptureUploadStatus`. - Overlay thumbnails render a spinner / error badge based on status; the send button stays grey until every capture resolves to `ready`. - Submit now carries only captureIds; MessageFromUrl awaits the pool promises before sendMessage, removing the second upload pass. - Carry overlay-selected modelId/provider into the agent config so the first message actually uses the user-chosen model (fixes the bug where switching the model on the overlay had no effect). * update * ✨ feat(popup): add Quick Chat tray entry backed by Inbox agent Tray menu now exposes a "Quick Chat" action that opens (or focuses) a single-instance popup window at `/popup/agent/inbox`. Each fresh open starts with no active topic; the first message creates one through the normal agent flow. - New `PopupAgentQuickPage` resolves the inbox slug via `builtinAgentSelectors.inboxAgentId` so `activeAgentId` points at the real entity in `agentMap` (fixes the stuck-loading / skeleton state from using the literal `'inbox'` slug). - `BrowserManager.openQuickChatPopup` wraps `createMultiInstanceWindow` with a fixed `topicPopup_quick_inbox` uniqueId so repeat clicks focus rather than spawn. - Wire the action into macOS / Windows / Linux tray menus and add the `tray.quickChat` i18n key. * Add quick chat shortcut and desktop hotkey support * ✨ feat(screen-capture): enhance window enumeration with scale factor support - Updated `enumerateWindows` to accept an optional `displayScaleFactor` parameter for improved window geometry normalization on high-DPI displays. - Refactored `normalizeWindowBounds` to handle scaling based on the provided scale factor, ensuring accurate window dimensions across different platforms. - Adjusted tests in `WindowSourceService.test.ts` to validate the new scaling behavior for both Windows and macOS environments. - Minor adjustments in `ScreenCaptureManager` to accommodate the updated window enumeration logic. --------- Signed-off-by: Innei <tukon479@gmail.com> |
||
|
|
b8cd21a257 | chore: add Twitter to recommended skills (#14037) |