diff --git a/.changeset/action-param-visible.md b/.changeset/action-param-visible.md deleted file mode 100644 index 7c61fb6cdf..0000000000 --- a/.changeset/action-param-visible.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -"@object-ui/core": patch -"@object-ui/app-shell": patch ---- - -Action params support a `visible` CEL predicate — the param dialog omits a param -when it evaluates false, against the same scope as action `visible` (features / -user / app / data). Fixes the create-user form offering a **Phone Number** field -the default backend rejects ("Phone numbers require the phoneNumber auth plugin"): -paired with the framework gating that param on `features.phoneNumber`, the form -now follows the plugin — no phone field unless the opt-in phoneNumber auth plugin -is loaded. `filterVisibleParams` is exported + unit-tested (feature-off hides, -feature-on shows, malformed predicate fails open). diff --git a/.changeset/adr-0037-mobile-live-canvas.md b/.changeset/adr-0037-mobile-live-canvas.md deleted file mode 100644 index 188eadf5ab..0000000000 --- a/.changeset/adr-0037-mobile-live-canvas.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -"@object-ui/app-shell": patch -"@object-ui/i18n": patch ---- - -fix(console-ai): Live Canvas is a full-screen, opt-in preview on mobile — not a broken split (#2481) - -On a phone the beside-chat Live Canvas split overflowed the viewport (the chat -column's fixed min-width plus the preview exceeded the screen, and the resize -handle is desktop-only, so it was stuck clipped). Under `md` the canvas is now: - -- **Full-width chat, no split** — the build streams in the chat as before. -- **Opt-in + full-screen** — when the preview is available a floating "Preview - app" pill appears; tapping it (or a Preview button on a draft card) takes the - canvas full-screen over the chat. Closing returns to the chat with the - preview one tap away. The auto-drafted canvas never covers the streaming - chat unprompted. - -Desktop is unchanged (the resizable beside-chat split). Adds the -`console.ai.previewApp` string (en/zh). diff --git a/.changeset/adr-0057-chatdock-default-on.md b/.changeset/adr-0057-chatdock-default-on.md deleted file mode 100644 index c6b25c93c8..0000000000 --- a/.changeset/adr-0057-chatdock-default-on.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -"@object-ui/app-shell": patch ---- - -feat(console-ai): the ChatDock is now DEFAULT ON (ADR-0057 P3 go-live) - -`features.chatDock` flips from opt-in to opt-out: the right-docked chat rail -(FAB as launcher, `/ai` as the panel maximized, Studio right dock with center -`[Canvas | Properties]` tabs) is the console's default chat presentation. The -flag survives only as a server-side kill-switch — an operator sending -`chatDock: false` restores the floating-overlay console until the final -cleanup removes that path (epic #2409). diff --git a/.changeset/adr-0057-dock-polish.md b/.changeset/adr-0057-dock-polish.md deleted file mode 100644 index 8aa61aa1a8..0000000000 --- a/.changeset/adr-0057-dock-polish.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -"@object-ui/app-shell": patch ---- - -polish(console-ai): ease the dock's canvas auto-maximize, and give Studio its own chat width (ADR-0057 UX follow-ups, #2477) - -- **#4** The rail now eases to its new width (200ms) when the Live Canvas opens - (auto-maximize) or closes (tuck), instead of snapping. The transition is - suppressed during a manual resize drag so the width still tracks the pointer - 1:1. -- **#6** The Studio dock persists its width under its own key, separate from the - console dock. A wide console chat no longer squeezes the Studio design canvas - (and vice-versa) — each surface remembers the width that suits it. diff --git a/.changeset/adr-0057-final-cleanup.md b/.changeset/adr-0057-final-cleanup.md deleted file mode 100644 index 1b27b25fc9..0000000000 --- a/.changeset/adr-0057-final-cleanup.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -"@object-ui/app-shell": patch ---- - -refactor(console-ai)!: ADR-0057 final cleanup — remove the chatDock flag, the floating-overlay console chat, and the legacy left Studio copilot - -The docked chat is now the console's ONE chat presentation, unconditionally: - -- `features.chatDock` is removed from the runtime config (it had already - flipped to default-on; the kill-switch is retired with the code path it - guarded). -- `ConsoleFloatingChatbot` (the FAB-armed floating overlay) and its - `agentPicker` helper are deleted; `ConsoleChatbotFab` is now a small - dependency-free launcher (`{ appLabel, onOpenDock }`) that opens the dock — - including on `/home`, where it opens the full-page `/ai` surface (the dock - maximized) since Home has no shell to host a rail. -- The legacy left `StudioAiCopilot` panel is deleted; the Studio copilot's one - home is the right `StudioChatDock`. The ADR-0080 `aiSlot` injection seam is - untouched. -- The runtime SDUI `type: 'chatbot'` bubble (end-user apps) is unchanged - (ADR-0057 §4). -- Fix: the mobile chat sheet no longer shows a "maximize" button. At 85svh the - sheet is already the maximal mobile chat, and navigating to full-page `/ai` - from an OPEN Radix sheet tore it down mid-close (the route change unmounts - the console synchronously, so the scroll-lock/overlay never released and the - destination landed blank-and-frozen — "tap maximize → the chat's just gone"). - Full-page `/ai` stays reachable via normal navigation. diff --git a/.changeset/adr-0057-mobile-fullpage-bridge.md b/.changeset/adr-0057-mobile-fullpage-bridge.md deleted file mode 100644 index a54898a619..0000000000 --- a/.changeset/adr-0057-mobile-fullpage-bridge.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -"@object-ui/app-shell": patch ---- - -feat(console-ai): mobile chat sheet bridges to full-page /ai (conversation history + share) — cleanly (ADR-0057 UX #2477 item 1) - -The mobile chat bottom sheet gets a maximize button back — it opens the -full-page `/ai`, which on mobile already carries the conversation-history -sidebar and share, so the sheet doesn't need a second copy of either. This is -the missing mobile path to switch/resume threads. - -The button navigates **deferred**: an earlier cut jumped straight from the -click and tore the still-open Radix sheet down mid-close (the route change -unmounts the console synchronously, leaking the sheet's scroll-lock/overlay -onto the destination — "tap maximize → the chat's just gone"). Now the click -only closes the sheet; a `useEffect` fires the navigation once `open` has -flipped false — after Radix released the body on that commit and before the -sheet unmounts — so `/ai` lands clean. Applies to both the console sheet -(→ `/ai`) and the Studio copilot sheet (→ `/ai/build?package=…`, same thread). - -Live Canvas on mobile `/ai` (the beside-chat split has no room on a phone) is -tracked separately (#2481). diff --git a/.changeset/adr-0057-p3-followups.md b/.changeset/adr-0057-p3-followups.md deleted file mode 100644 index 29942a0fdd..0000000000 --- a/.changeset/adr-0057-p3-followups.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -"@object-ui/app-shell": patch ---- - -feat(console-ai): ChatDock follow-ups — mobile sheet, wide side-by-side properties, exact collapse landing (ADR-0057 P3) - -- Under `md` the dock presents as a bottom sheet (`ChatDockMobileSheet`) — - console FAB opens it; Studio gets a mobile-visible edge launcher. -- The folded Studio layout keeps canvas AND properties side by side on 2xl+ - viewports; tabs (and their auto-switch) only exist where width forces them. -- Folded tabs mode flattens the source page's nested Source/Props tabs — the - Properties tab body is the code editor directly. -- Maximize remembers its origin, so `/ai`'s collapse-to-dock returns to the - exact page (console or Studio) the user left, immune to history churn. -- The dock's conversation honors `app.defaultAgent` via the one resolver, - matching the FAB's behavior. diff --git a/.changeset/adr-0057-p3a-chatdock.md b/.changeset/adr-0057-p3a-chatdock.md deleted file mode 100644 index 8257c7e4fd..0000000000 --- a/.changeset/adr-0057-p3a-chatdock.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -"@object-ui/app-shell": minor -"@object-ui/layout": minor ---- - -feat(console-ai): ChatDock — right-docked AI rail behind a default-off flag (ADR-0057 P3a) - -Stands up the ADR-0057 P3 docked rail as an ADDITIVE, DEFAULT-OFF shell: until an -operator sets `features.chatDock`, nothing changes and the FAB stays the -canonical entry. - -- `@object-ui/layout`: `AppShell` gains an optional `rightRail` prop, rendered as - a flex sibling of the main content so the rail REFLOWS the content beside it - (VS Code / Cursor idiom), not overlaying it. Absent → unchanged single-pane. -- `@object-ui/app-shell`: new `ChatDock` — a collapsible, resizable right rail - that reuses the shared `ChatPane` engine over the P1 `(user, app, product=ask)` - conversation (the same ambient thread the FAB/`/ai` shows; it's a VIEW, not a - new conversation). Default COLLAPSED (a fixed edge launcher → zero layout cost - until invoked); ⌘/Ctrl+Shift+I toggles it. Gated on `useAiSurfaceEnabled` AND - the flag, so OSS / no-seat runtimes render nothing. -- `runtime-config`: `chatDock?` rollout flag, parsed default-OFF (opt-in only). - -Live-verified with the flag forced on: the launcher expands to a rail rendering -the ask chat, the dashboard content reflows narrower beside it, and collapse -restores the launcher. Unit-tested: width clamp, the composer-safe shortcut -matcher (⌘⇧I, no collision with the ⌘⇧O/S page shortcuts), and the flag's -default-off/opt-in parse. FAB retirement (P3b) and `/ai`-as-maximized-dock + -Studio reflow (P3c) follow. diff --git a/.changeset/adr-0057-p3b-fab-launcher.md b/.changeset/adr-0057-p3b-fab-launcher.md deleted file mode 100644 index 810df07495..0000000000 --- a/.changeset/adr-0057-p3b-fab-launcher.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -"@object-ui/app-shell": patch ---- - -feat(console-ai): the FAB becomes the ChatDock launcher when the dock is on (ADR-0057 P3b) - -When `features.chatDock` is enabled, the console FAB opens the docked rail instead -of the floating overlay — one entry point, the ADR's "FAB → launcher" step. In -dock mode the FAB stays the lightweight button (it never mounts the heavy floating -chatbot; the rail loads the chat on demand), and a designer "Ask AI" open signal -(assistantBus) opens the dock too. With the flag OFF the FAB is unchanged (floating -overlay). Supersedes P3a's edge launcher (the dock is gated on the same -`showChatbot`, so the FAB is always present to launch it). diff --git a/.changeset/adr-0057-p3c-maximized-dock.md b/.changeset/adr-0057-p3c-maximized-dock.md deleted file mode 100644 index b380a31b16..0000000000 --- a/.changeset/adr-0057-p3c-maximized-dock.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -"@object-ui/app-shell": patch ---- - -feat(console-ai): /ai = the ChatDock maximized + Studio right-dock reflow (ADR-0057 P3c) - -The final P3 slice, all behind the default-off `features.chatDock` flag: - -- **/ai ⇄ rail continuity**: the dock header gains a maximize button that opens - the full-page `/ai` surface, and the `/ai` page gains a collapse-to-dock button - that returns to the console with the rail expanded — same thread both ways - (the P1 `(user, app, product)` conversation key). Deep links - (`/ai/:agent/:conversationId`, ADR-0013) are untouched and keep working. -- **Studio reflow** (the ADR's decided grid `[left: nav/tree] [center: canvas + - properties] [right: chat]`): the AI copilot leaves the left `w-96` panel and - renders as the shared right dock (`ChatDockPanel` + `ChatDockLauncher`), same - package-scoped build thread; the Interfaces pillar's right inspector folds - into center `[Canvas | Properties]` tabs with select-a-block auto-switch. An - injected `aiSlot` (cloud seam, ADR-0080) keeps the legacy left panel. -- **Live Canvas** (ADR-0037): in the rail, the dock auto-maximizes while the - canvas is open and tucks back on close (manual resize wins); maximized (`/ai`) - keeps the existing beside-the-chat split. - -With the flag OFF, `/ai` and Studio are pixel-identical to before. diff --git a/.changeset/adr-0057-p4-handoff-context.md b/.changeset/adr-0057-p4-handoff-context.md deleted file mode 100644 index fb8579ddf3..0000000000 --- a/.changeset/adr-0057-p4-handoff-context.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -"@object-ui/plugin-chatbot": minor -"@object-ui/app-shell": minor ---- - -feat(console-ai): ask→build handoff carries conversation context (ADR-0057 P4 / cloud#817) - -The P4 "Open in Builder →" handoff previously carried only the build prompt + an -optional package, so the Builder started cold and the user re-explained -themselves. It now also carries the **source `ask` conversation** as context — -ADR-0057 P4 / cloud#817 — so the build agent's first turn starts with the thread -the user already had. - -- `@object-ui/app-shell`: both handoff sites (the full-page `AiChatPage` and the - console FAB) now append `?parentConversationId=` to the - `/ai/build` URL. The build surface reads it and forwards it to `useObjectChat`; - the existing URL-mirror drops it once the build conversation id is minted, so a - reload never re-carries it. -- `@object-ui/plugin-chatbot`: `useObjectChat` accepts `parentConversationId` and - sends it as `context.parentConversationId` on the **first turn only** (held in a - ref, consumed once) — the backend redeems it into the turn's context and the - client owns history from there. New pure helper `withHandoffContext` (unit - tested) does the non-mutating `context` merge. - -Requires the cloud handoff-context contract (service-ai, cloud#817): the build -agent redeems `context.parentConversationId` into a single system block on its -first turn — ownership-checked, and carrying only the user/assistant text the -user already saw (ADR-0063 governance boundary). Without it the console degrades -cleanly: the id is sent but ignored, and the handoff is a (working) cold start. diff --git a/.changeset/adr-0057-p4-handoff-reliability.md b/.changeset/adr-0057-p4-handoff-reliability.md deleted file mode 100644 index a8ad574819..0000000000 --- a/.changeset/adr-0057-p4-handoff-reliability.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -"@object-ui/plugin-chatbot": patch -"@object-ui/app-shell": patch ---- - -fix(console-ai): reliable ask→build handoff auto-send + second-handoff context re-carry (ADR-0057 P4) - -Two follow-ups to the P4 "Open in Builder →" handoff: - -- **Auto-send swallow.** The handoff's auto-sent first message could be dropped on - a brand-new build conversation: the seed gated on the async-resolved - `activeAgent`, which can settle *after* the conversation id is minted, so the - deferred-send replay ran with an empty pending and never re-fired. The seed now - gates on the **route** (`agentSegment`, synchronous) and bumps a `pendingSignal` - that `useDeferredFirstSend` lists in its replay deps, so the seed always fires — - no more empty build conversation on handoff. - -- **Second-handoff re-carry.** A second "Open in Builder →" into the (singleton) - build conversation now re-carries the latest ask context. The transport re-arms - `parentConversationId` on each falsy→truthy transition of the prop (the ask - thread is a singleton, so the same id repeats — the fresh-arrival signal is the - transition the URL-mirror produces, not a changed value), and the seed re-arms - on each new `handoffPrompt`. - -Unit-tested: deferred-send replays a post-id seed via the signal; the transport -re-carries across a strip→re-supply cycle. diff --git a/.changeset/adr-0057-p4-open-in-builder.md b/.changeset/adr-0057-p4-open-in-builder.md deleted file mode 100644 index 06a06f60fe..0000000000 --- a/.changeset/adr-0057-p4-open-in-builder.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -"@object-ui/plugin-chatbot": minor -"@object-ui/app-shell": minor ---- - -feat(console-ai): explicit "Open in Builder →" ask→build handoff (ADR-0057 P4) - -When the `ask` agent declines an app-authoring request it now calls the cloud -`suggest_builder` tool (structured decline). The console renders that as an -explicit **"Open in Builder →"** action that opens the full-page build surface -seeded with the handoff prompt — ADR-0063 decline-and-redirect: an explicit, -user-initiated switch, never a silent re-route into authoring. - -- `@object-ui/plugin-chatbot`: `detectBuilderHandoff` lifts the - `{ status:'build_handoff', prompt, packageId? }` result onto the tool - invocation; `ChatbotEnhanced` renders the "Open in Builder →" card and calls a - new `onOpenBuilder` prop (disabled when no host wires it). -- `@object-ui/app-shell`: the full-page `AiChatPage` (`ask`) and the console FAB - wire `onOpenBuilder` to navigate to `/ai/build?package=…&handoffPrompt=…`; the - build surface seeds that prompt as its first message (auto-sent once the - conversation is minted), and the URL-mirror strips `?handoffPrompt` so a reload - never re-sends it. Full ask-conversation context transfer is a later upgrade - (cloud#817); v1 carries the build prompt + optional package. - -Requires the cloud `suggest_builder` signal (service-ai-studio) to light up; the -console degrades cleanly (no card) without it. diff --git a/.changeset/adr-0057-studio-dock-ux.md b/.changeset/adr-0057-studio-dock-ux.md deleted file mode 100644 index 97bc878ebb..0000000000 --- a/.changeset/adr-0057-studio-dock-ux.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -"@object-ui/app-shell": patch ---- - -fix(console-ai): Studio dock remembers a collapse; folded canvas+properties go side-by-side at `xl` (ADR-0057 UX follow-ups, #2477) - -- **Studio dock collapse is now remembered** (per-tab). The right copilot still - mounts expanded by default, but collapsing it to get the classic three-zone - canvas no longer re-opens on every pillar / package switch or Studio - re-entry. Backed by an explicit `'0'`/`'1'` stored flag (a default-expanded - surface couldn't remember a collapse when "collapsed" meant "key removed"), - under a Studio-specific key so it never shares state with the console dock. -- **Folded layout shows canvas + properties side by side from `xl`** (1280), - lowered from `2xl`. On the common laptop the folded center used to fall into - tabs, which auto-hide the canvas the moment you select a block — breaking the - WYSIWYG "edit and watch it apply" loop. The side-by-side inspector is slimmer - at `xl` (and grows at `2xl`) so the canvas keeps usable width beside the dock. diff --git a/.changeset/adr-0089-visible-when-renderer.md b/.changeset/adr-0089-visible-when-renderer.md deleted file mode 100644 index d52b324852..0000000000 --- a/.changeset/adr-0089-visible-when-renderer.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"@object-ui/react": minor -"@object-ui/types": minor ---- - -ADR-0089: read the canonical `visibleWhen` conditional-visibility predicate in the form + page renderers. - -`@objectstack/spec` now unifies conditional visibility under a single canonical key, `visibleWhen`, and folds the deprecated `visibleOn` (view form) / `visibility` (page component) aliases into it at parse. This updates ObjectUI to read the canonical key: - -- **Page renderer** (`SchemaRenderer`) — evaluates `visibleWhen` first (show-when-truthy), then the deprecated `visibleOn` / `visibility` as a defensive read for raw / un-normalized metadata. `visibleWhen` is stripped from DOM props. -- **Spec→node bridges** — the page bridge maps a component's `visibleWhen ?? visibility` onto the node's canonical `visibleWhen`; the form-view bridge maps a field's `visibleWhen ?? visibleOn` onto the ObjectForm view-level predicate slot. -- **Form renderers** — the `@object-ui/react` `FormRenderer` prefers `visibleWhen` over the `visibleOn` alias. (`ObjectForm`/`form.tsx` already evaluated `visibleWhen`.) -- **Types** — the component base schema (`BaseSchema` / `base.zod`) gains the canonical `visibleWhen`; `visibleOn` is marked `@deprecated`. - -Fully back-compat: existing `visibleOn` / `visibility` metadata keeps working through the alias reads. diff --git a/.changeset/ask-decline-pending-indicator.md b/.changeset/ask-decline-pending-indicator.md deleted file mode 100644 index d01a112adc..0000000000 --- a/.changeset/ask-decline-pending-indicator.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"@object-ui/plugin-chatbot": patch ---- - -Make the ask-decline wait feel responsive: live thinking indicator + handoff card the moment `suggest_builder` lands (#2458 item 3). - -When the `ask` agent declines a build-shaped request, the ~20s before the "Open in Builder →" card is dominated by the LLM's time-to-tool-call. During that wait the chat could show dead air — a blank bubble, or the static "执行过程" activity note (a hydrated-history affordance) when the backend streamed a `(called …)` tool-call placeholder. - -`ChatbotEnhanced` now shows the existing live thinking indicator (`ThinkingDots`) whenever a streaming assistant turn has nothing visible yet — including whitespace-only content, a mid-stream `(called …)` placeholder, and hidden reasoning in `summary` mode. The static "执行过程" note is reserved for FINISHED (re-hydrated) tool-call-only turns (#772 preserved). The `builderHandoff` card already renders at `output-available` with no gate on the trailing prose, so it surfaces the instant the tool result arrives; the typing cursor now only paints beside real streaming prose (no lone cursor during the tool phase). diff --git a/.changeset/cloud-816-capability-rendering.md b/.changeset/cloud-816-capability-rendering.md deleted file mode 100644 index f50031bb41..0000000000 --- a/.changeset/cloud-816-capability-rendering.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -"@object-ui/plugin-chatbot": minor -"@object-ui/app-shell": patch ---- - -feat(console-ai): render agent behavior by declared capability (cloud#816 / ADR-0057 "B+") - -`GET /api/v1/ai/agents` now serves per-agent `capabilities`; the console -consumes them instead of hard-coding `isBuildAgent(name)`: - -- `@object-ui/plugin-chatbot`: `AgentDescriptor.capabilities` (normalized from - the catalog) + new `agentHasCapability(agents, name, cap)` — declaration wins - when present; falls back to the legacy `isBuildAgent(name)` check when absent - (older server), so shipping order doesn't matter. -- `@object-ui/app-shell`: the build-doctor drawer + `showDebug` key off - `'debug'`, the FAB's resume-vs-fresh keys off `'resume'`, HomePage's - "Build with AI" availability keys off `'authoring'`. The ADR-0063 product-axis - sites (surface→agent resolver, conversation scope keying, picker availability) - intentionally stay name-based — capability describes RENDERED behavior, not - which product an agent is. - -A future skill-driven build variant now needs no console change. diff --git a/.changeset/console-ai-ux-batch.md b/.changeset/console-ai-ux-batch.md deleted file mode 100644 index 4c46ec5cd8..0000000000 --- a/.changeset/console-ai-ux-batch.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -"@object-ui/app-shell": minor -"@object-ui/plugin-chatbot": minor ---- - -feat(console-ai): package binding chip + inert handoff cards + honest send hint (#2458 / ADR-0057 A1.a) - -Three UX improvements from live magic-flow testing: - -- **A1.a — package binding chip** (`app-shell`): the build surface header shows - the package the conversation is bound to (`📦 `), or **"New app"** when - unbound — so the edit blast-radius is always visible (Claude-Code-shows-the-repo - idiom). The magic flow starts unbound and binds the moment its build mints a - package (`deriveBoundPackageId` reads `?package=` else the latest draft/handoff - result; unit-tested). -- **UX#5 — only the latest handoff card is actionable** (`plugin-chatbot`): when - a thread accumulates several "Open in Builder →" cards, only the newest stays - clickable; older (superseded) cards' buttons are disabled — derived from - message order, so it survives the navigation the button triggers and the pane - remount that follows. A stale prompt in an older card can't be re-fired. -- **UX#7 — honest send hint** (`plugin-chatbot`): the composer already sends on - plain Enter (Shift+Enter = newline); dropped the misleading `⌘` glyph from the - hint so it no longer implies Cmd+Enter. diff --git a/.changeset/console-chat-conversation-key.md b/.changeset/console-chat-conversation-key.md deleted file mode 100644 index 9cab4a6fbf..0000000000 --- a/.changeset/console-chat-conversation-key.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -"@object-ui/app-shell": patch ---- - -feat(console-ai): key AI chat conversations on `(user, app, product)`, not on surface (ADR-0057 P1) - -The console rendered AI chat through parallel shells that **forked the -conversation**: the Studio design copilot scoped its thread as -`studio:${packageId}:${agent}` while the full-page `/ai/build` focus view scoped -on the agent alone — so opening the *same app* in both showed an empty "Build -with AI" copilot beside an active full-page build thread (indistinguishable from -data loss). - -Per ADR-0057 (**surface = view · conversation = model · product = binding -axis**), conversations are now keyed on `(user, app, product)`: - -- New pure, unit-tested `chatConversationScope({ appId, product })` + - `chatProductOfAgent(name)` helper (`hooks/chatScope.ts`) is the single place - the scope key is formed. `product` is the ADR-0063 axis (`ask` | `build`), - derived from the resolved agent — never a per-surface choice. -- `StudioAiCopilot` and the full-page `AiChatPage` both resolve - `app:${packageId}:${product}` for a package-scoped surface (the Studio copilot - editing package X and the `/ai/build?package=X` "Edit with AI" focus view now - resume ONE shared thread). The legacy `studio:` surface prefix is dropped. -- A generic `/ai/:agent` visit with no `?package=` degrades to the product alone - (`build` / `ask`) — unchanged behaviour for that surface. - -Enablement stays on the single access-filtered agent-catalog gate -(`useAiSurfaceEnabled`, ADR-0068) — a seat-less user's empty catalog hides the -whole AI surface. No layout change. diff --git a/.changeset/console-surface-agent-resolver.md b/.changeset/console-surface-agent-resolver.md deleted file mode 100644 index 389c1ea43b..0000000000 --- a/.changeset/console-surface-agent-resolver.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -"@object-ui/app-shell": patch ---- - -feat(console-ai): one declarative surface→agent resolver (ADR-0057 P2) - -The console re-implemented the ADR-0063 surface→agent chain in ~5 places, each -spelled slightly differently — and `ConsoleLayout` carried an AI-Studio-off -downgrade special case that existed nowhere else. This collapses them into one -pure, unit-tested resolver so ADR-0063 (exactly two products `ask`/`build`, -bound by surface — no roster, no per-turn classifier) becomes a **structural** -guarantee. - -- New `hooks/surfaceAgent.ts`: `resolveSurfaceAgent(surface, { agents, - appDefaultAgent, aiStudioEnabled })` + `SURFACE_DEFAULT`. `app.defaultAgent` is - **bounded** to ask/build (alias-aware) — a withdrawn tenant custom agent is - rejected, not passed through, so no roster is representable (ADR-0057 open - question #4). The AI-Studio-off `build → ask` downgrade is folded in ONCE. -- `StudioAiCopilot` (studio-build → build) and the console FAB (`default` → ask) - resolve through it. The FAB keeps #771's "prefer build when the catalog unlocks - it and nothing pinned a product" by passing that as its default PRODUCT input — - so the resolver still owns bounding + the downgrade, which now also applies to - the #771 preference (closing the leak where an authoring-disabled deployment - could still open build). -- `ConsoleLayout`'s bespoke `!aiStudioEnabled && isBuildAgent(...)` downgrade is - deleted; it passes the raw `app.defaultAgent` and the resolver downgrades. - -Ships a unit table proving the ADR-0063 rows: Studio→build, other→ask, -AI-Studio-off downgrade, `app.defaultAgent` bounded (valid override wins, roster -rejected), alias-aware catalog resolution, empty catalog → inert (ADR-0025). diff --git a/.changeset/export-filename-and-import-template-i18n.md b/.changeset/export-filename-and-import-template-i18n.md deleted file mode 100644 index 48143296f9..0000000000 --- a/.changeset/export-filename-and-import-template-i18n.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -'@object-ui/core': patch -'@object-ui/plugin-grid': patch -'@object-ui/plugin-list': patch -'@object-ui/plugin-view': patch -'@object-ui/app-shell': patch -'@object-ui/i18n': patch ---- - -导出/导入模板的下载文件名与内容本地化。 - -**导出文件名**:CSV/Excel/JSON 导出下载不再是 `<对象名>.<扩展名>`(如 `contracts.csv`),改为「对象显示名-视图名-时间戳.扩展名」(如 `任务-In Progress-20260714-153045.xlsx`);`exportOptions.fileNamePrefix` 配置仍优先(且作为完整前缀,不再追加视图名)。视图名与对象名重复时自动省略;`@object-ui/core` 新增 `buildExportFileName(ext, { prefix, label, objectName, viewLabel }, now?)` 与 `sanitizeFileNameBase(raw)`,ObjectGrid 与 ListView 的所有导出路径(服务端流式与前端兜底)统一走它。app-shell/plugin-view 的 ObjectView 现将当前视图的显示标签写进传给 ListView 的 schema(`label`),使导出文件名能区分同一对象的不同保存视图。 - -**导入模板**:「下载模板」修复两处英文漏出——示例行的 select/多选取值改为优先取选项**显示标签**(如 `准备中`)而非 ASCII slug(`prepare`,服务端导入两者都接受);模板文件名本地化为 `{{object}}-导入模板.csv`(新增 i18n key `grid.import.templateFileName`,英文回退 `{{object}}-import-template.csv`)。 diff --git a/.changeset/fix-2450-resume-handoff-autosend.md b/.changeset/fix-2450-resume-handoff-autosend.md deleted file mode 100644 index 17ff19d18c..0000000000 --- a/.changeset/fix-2450-resume-handoff-autosend.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -"@object-ui/app-shell": patch ---- - -fix(console-ai): second handoff's auto-send no longer dies in the stale-scope pane (#2450) - -Mid ask→build transition, `useChatConversation` briefly still holds the OLD -scope's conversation id (the same stale window the URL-mirror already guards). -`` was fed that raw id, so a DOOMED pane (build chatApi + stale ask id, -about to remount) could mount — and the deferred first-send replay consumed the -handoff stash into it, where the send died with the unmount before reaching the -wire (observed live as "conversation resumes, zero `…/chat` POST"). - -Two-layer fix: - -- **Scope-gated pane feed (structural):** the page now hands `` a - conversation id/messages ONLY when `conversationScope === chatScope`. During - the stale window the pane mounts as `…:pending`, holds the stash, and replays - exactly once in the correctly-scoped pane — extending the existing URL-mirror - guard to the pane itself. -- **Targeted stash (defense-in-depth):** the handoff seed is stamped - `targetAgentRoute: 'build'`; `useDeferredFirstSend` refuses to consume a - targeted stash in a pane bound to another agent (untargeted user-typed sends - keep the legacy consume-anywhere behavior). - -Per product decision, a second handoff landing on a conversation with a -blueprint still Awaiting Approval just auto-sends — the build agent sees the -pending plan in context and decides merge/supersede itself. diff --git a/.changeset/fix-build-card-mobile-overflow.md b/.changeset/fix-build-card-mobile-overflow.md deleted file mode 100644 index 10027e9712..0000000000 --- a/.changeset/fix-build-card-mobile-overflow.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -"@object-ui/plugin-chatbot": patch ---- - -fix(plugin-chatbot): build-result summary truncates on mobile instead of overflowing (#2493) - -The draft-review card's summary line (`built N artifact(s) — …`) is a nowrap -`truncate` span, but its flex row lacked the `min-w-0` that lets `truncate` -actually bite — so on a phone the long summary expanded the chat column past -the viewport and the whole chat scrolled sideways. The span now gets -`min-w-0 flex-1` (truncating within the row) and the action row is `flex-wrap` -so its buttons drop to a new line on a narrow screen rather than forcing -horizontal scroll. Desktop is unchanged (there's room, so nothing wraps or -truncates). diff --git a/.changeset/form-widget-hint-section-fallback.md b/.changeset/form-widget-hint-section-fallback.md deleted file mode 100644 index 099a5f5478..0000000000 --- a/.changeset/form-widget-hint-section-fallback.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -"@object-ui/components": patch ---- - -Form fields honor their object-schema `widget` render hint on the field-group / -section layout path. `ObjectForm` renders objects that declare field groups -(e.g. `sys_sharing_rule`) via an auto-derived section layout that passed each -field's metadata through without hoisting its `widget` override to the top-level -form-field config, so a field with `widget: 'object-ref'` (or `filter-condition` -/ `recipient-picker`) degraded to its bare `type` input — an admin was asked to -hand-type an object name instead of picking it. The form renderer now falls back -to the field metadata's own `widget` when no top-level override is present, so -the pickers render on sectioned forms just as they do on flat ones. diff --git a/.changeset/gantt-api-data-source.md b/.changeset/gantt-api-data-source.md deleted file mode 100644 index 4b399e8d14..0000000000 --- a/.changeset/gantt-api-data-source.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -"@object-ui/plugin-gantt": patch ---- - -ObjectGantt now supports the `api` data source for **both read and write-back**. -Previously `provider: 'api'` logged "API provider not yet implemented" and rendered -nothing, and every write-back (reschedule, dependency edit, delete, drawer -inline-edit) was hard-wired to the context ObjectQL `dataSource` + `objectName`, -so the api provider's `write` config was never used. - -All reads and writes now flow through a single adapter resolved by -`resolveDataSource(schema.data, dataSource)`: `object` → context DataSource -(unchanged), `api` → `ApiDataSource` (executes the `read`/`write` HttpRequest -config), `value` → in-memory `ValueDataSource`. A pure-api view needs no -`objectName` and no context `dataSource` prop. Object-backed views are behavior- -preserving. Lookup/master_detail quick-filter option domains still resolve from -the context object backend (they degrade to distinct in-row values when absent). diff --git a/.changeset/gantt-border-color-field.md b/.changeset/gantt-border-color-field.md deleted file mode 100644 index 4838fb511b..0000000000 --- a/.changeset/gantt-border-color-field.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"@object-ui/plugin-gantt": patch ---- - -新增逐任务预警描边(#2436 第 3 项):视图配置 `borderColorField` 指向 -记录上的预警颜色字段(常为服务端计算的超期/临期字段),该行条形在保留 -原有填充色的同时,以该颜色描边并加 2px 光晕——任务条、里程碑菱形、 -汇总条均生效。语义色名(red/orange/…)映射为调色板 hex,其余 CSS 颜色 -原样透传;空值不描边。开启关键路径高亮时,关键路径样式在其标记行上优先。 diff --git a/.changeset/gantt-dependency-guards.md b/.changeset/gantt-dependency-guards.md deleted file mode 100644 index d176603c5a..0000000000 --- a/.changeset/gantt-dependency-guards.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"@object-ui/plugin-gantt": patch ---- - -拖拽连线增加内建校验与宿主否决钩子(#2436 第 1、2 项)。落点为锁定行 -(`locked`)或分组行(`type: 'group'`)时,悬停不再高亮、松手不再创建; -成环依赖(直接回边、跨层级传递回边)基于**全量任务集**检测并拒绝——不受 -折叠子树导致可见连线缺边的影响。新增 `onBeforeDependencyCreate(source, -target, type)` 钩子,在内建校验通过后调用,返回 `false` 可否决本次连线 -(即 DHTMLX `onBeforeLinkAdd` / Syncfusion `actionBegin` 惯例)。 -`wouldCreateDependencyCycle` 从 `scheduling` 导出并单测覆盖。 diff --git a/.changeset/gantt-drawer-lock.md b/.changeset/gantt-drawer-lock.md deleted file mode 100644 index 910edc10b1..0000000000 --- a/.changeset/gantt-drawer-lock.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"@object-ui/plugin-detail": patch -"@object-ui/plugin-gantt": patch ---- - -修复记录抽屉绕过甘特图行级锁定的问题(#2436 第 5 项)。 - -- `RecordDetailDrawer` 的编辑/删除能力现在由调用方是否传入 `onFieldSave` / `onDelete` 决定:两者都省略时抽屉严格只读(无内联编辑、无删除入口)。此前抽屉硬编码 `inlineEdit` 与 `showDelete: true`,并无条件向内层 DetailView 传包装函数,导致锁定记录仍可"编辑"(且改动静默丢失)。 -- `ObjectGantt` 对 `lockField` 锁定的行、以及全局 `readOnly` 的甘特图,不再向抽屉传入 `onFieldSave` / `onDelete`,与时间轴上禁止拖拽/调整的行为保持一致。 diff --git a/.changeset/gantt-tree-aware-filter.md b/.changeset/gantt-tree-aware-filter.md deleted file mode 100644 index 36ef9d0e95..0000000000 --- a/.changeset/gantt-tree-aware-filter.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@object-ui/plugin-gantt": patch ---- - -快速筛选改为树感知(#2436 第 4 项):命中任务的**全部祖先链**一并保留。 -此前 `displayTasks` 是平铺过滤,项目/产品等分组行本身没有可筛字段值, -一筛就被丢掉,命中的子任务成孤儿、树结构被打散。现在祖先随命中下级 -自动保留、无命中下级时照常剔除,多分支命中共享祖先不重复。 diff --git a/.changeset/gantt-write-readback-refresh.md b/.changeset/gantt-write-readback-refresh.md deleted file mode 100644 index f8d831f266..0000000000 --- a/.changeset/gantt-write-readback-refresh.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@object-ui/plugin-gantt": patch ---- - -甘特图写后回读 + 工具栏手动刷新按钮(#2436 第 6/7 项)。 - -- 拖拽改期、依赖增删、抽屉内联编辑、删除记录成功后,静默重新读取数据源,让服务端重算的字段(父级汇总、预警颜色、工期重算)刷新到图上;此前乐观补丁只保留客户端写入的字段,派生字段一直陈旧直到整页刷新。静默刷新不闪 loading、不卸载 GanttView(保留滚动/折叠状态),并发请求按序号防乱序覆盖;失败时保留屏上最后一份好数据。 -- GanttView 工具栏新增手动刷新按钮(`onRefresh` / `refreshing` props),object 数据源自动接线;内联 value 数据无可回读来源,不显示按钮。 diff --git a/.changeset/list-search-keyword-chip.md b/.changeset/list-search-keyword-chip.md deleted file mode 100644 index 5bd3223a3d..0000000000 --- a/.changeset/list-search-keyword-chip.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"@object-ui/plugin-list": patch ---- - -The list toolbar search button now shows the active keyword inline (mirroring -the Sort button's count badge). Previously a search term restored from -localStorage after navigating away and back kept filtering the list while the -search popover stayed collapsed — the only cue was a slightly darker magnifier -icon, so users couldn't tell a keyword filter was still active. The keyword is -rendered (truncated at 8rem) next to the magnifier whenever a search is active, -and clicking it opens the popover pre-filled for editing or clearing. diff --git a/.changeset/metadata-client-authenticated-fetch.md b/.changeset/metadata-client-authenticated-fetch.md deleted file mode 100644 index f6e1dedf1b..0000000000 --- a/.changeset/metadata-client-authenticated-fetch.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -"@object-ui/app-shell": patch ---- - -fix(metadata-admin): authenticate console MetadataClient requests (Bearer token) - -Studio / metadata-admin surfaces issued `/api/v1/meta/*` requests (list types, -`?package=…` reads, `_drafts`, the `/meta` root) that came back `401 -unauthenticated` in the token-based console, while the runtime data adapter's -reads (`/meta/object|view|app`) succeeded — so the same page showed some -metadata requests failing and others working. - -Root cause: `useMetadataClient` and `MetadataProvider`'s draft-preview client -constructed `MetadataClient` without a `fetch`, so it fell back to the bare -`globalThis.fetch` and sent no `Authorization` header. The console -authenticates by a Bearer token in localStorage (`auth-session-token`) — there -is no session cookie — so those requests were unauthenticated. A same-origin -cookie deployment masks the bug, which is why it went unnoticed and regressed -twice. - -Both sites (and every future console surface) now construct through a single -`createConsoleMetadataClient` factory that bakes in `createAuthenticatedFetch` -(Bearer token + `X-Tenant-ID` + `Accept-Language`), matching the runtime data -adapter. This is additive for cookie deployments — `credentials` is untouched, -so a same-origin session cookie still flows. A -`metadata-client-auth.ratchet.test.ts` guard forbids a bare -`new MetadataClient(` elsewhere in app-shell so authentication can't silently -regress again. diff --git a/.changeset/permission-set-reset-copy.md b/.changeset/permission-set-reset-copy.md deleted file mode 100644 index 468abdc34b..0000000000 --- a/.changeset/permission-set-reset-copy.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@object-ui/app-shell": patch ---- - -Say "reset to shipped baseline" instead of "delete" when removing a package-owned permission set (ADR-0094). - -Deleting a `sys_permission_set` row whose `managed_by === 'package'` doesn't remove it — the backend drops the environment customization overlay and resets the set to its shipped baseline, so the row stays in the list. The confirmation dialog and success toast now say so (with `resetPackageSetConfirm` / `resetPackageSetSuccess` i18n, en + zh), instead of promising an irreversible delete the user can see doesn't happen. Environment-authored sets keep the plain delete copy. The grid row-delete passes the record through so the check needs no extra fetch; the SDUI header delete falls back to a `findOne` lookup. diff --git a/.changeset/phone-password-login.md b/.changeset/phone-password-login.md deleted file mode 100644 index c619398b70..0000000000 --- a/.changeset/phone-password-login.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -"@object-ui/auth": minor -"@object-ui/console": patch ---- - -feat(auth): phone number + password sign-in on the login page - -The login page's password mode now accepts an **email OR a phone number** as the -identifier and routes by shape — email → `/sign-in/email`, phone → -`/sign-in/phone-number` (better-auth phoneNumber plugin, framework#2780). It -coexists with the existing phone-OTP mode. - -- Gated on `features.phoneNumber` (phoneNumber plugin enabled). Unlike phone-OTP - it needs no SMS service, so it uses that coarser capability flag, not - `features.phoneNumberOtp`. When the flag is off the field stays email-only. -- New `AuthClient.signInWithPhonePassword(phoneNumber, password)` wired through - `AuthContext` / `AuthProvider` / `useAuth`. -- New `normalizePhoneIdentifier` / `looksLikePhoneIdentifier` helpers that mirror - the backend's `normalizePhoneNumber` exactly (strip `[\s\-().]`, validate - `^\+?[0-9]{6,15}$`, **no** forced E.164 / country code — the backend stores the - light-stripped form, so anything heavier would break the lookup). -- SSO stays email-only (a phone-shaped identifier no longer attempts domain - routing). - -Only works for accounts that have both a phone number and a password set; -phone-only accounts set a password on first OTP sign-in. diff --git a/.changeset/plenty-cities-worry.md b/.changeset/plenty-cities-worry.md deleted file mode 100644 index dc50496dbe..0000000000 --- a/.changeset/plenty-cities-worry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@object-ui/console": major ---- - -align with objectstack diff --git a/.changeset/profile-card-i18n.md b/.changeset/profile-card-i18n.md deleted file mode 100644 index c46663cf15..0000000000 --- a/.changeset/profile-card-i18n.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -'@object-ui/console': patch -'@object-ui/i18n': patch -'@object-ui/app-shell': patch -'@object-ui/plugin-detail': patch -'@object-ui/plugin-tree': patch ---- - -i18n: translate the Profile page, honor inline i18n label objects under bare -base-language codes, and localize managed-by badges / record quick actions. - -- `pickLocalized` now upgrades a bare base language (`zh`) to any - region-qualified key sharing the base (`zh-CN`) — runtime language is - normalized to the base code while metadata authors write full BCP-47 tags, - so inline `{ en, 'zh-CN', ... }` label objects previously fell back to - English. -- ProfilePage (`account:profile_card` / `/system/profile`): every hardcoded - string — page title/subtitle, avatar Upload/Replace/Remove, Personal - Information card, Change/Set Password card — now goes through - `useObjectTranslation()` with `profile.*` keys (new namespace in all ten - locale bundles); the lazy-load fallback reuses `common.loading`. -- `ManagedByBadge` chips/tooltips (Config/System/Append-only/Identity) now - resolve through new `managedByBadge.*` keys with `{{provider}}` - interpolation. -- `record:quick_actions` resolves action labels via the - `objects.{object}._actions.{action}.label` convention plus `pickLocalized`, - so object action buttons (Change Password, Enable 2FA, …) localize. -- `record:details` / `record:related_list` / `record:alert` / `ObjectTree` - pass inline label objects through `pickLocalized`. -- Locale bundles: added `managedByBadge` namespace to all ten locales and - backfilled `list.inlineEditShort` / `inlineEditLabel` / - `recordEditingTitle` for ja/es/ko/de/fr/pt/ru/ar. diff --git a/.changeset/resolve-action-param-visible.md b/.changeset/resolve-action-param-visible.md deleted file mode 100644 index 0e29128fed..0000000000 --- a/.changeset/resolve-action-param-visible.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"@object-ui/app-shell": patch ---- - -fix(app-shell): propagate action-param `visible` predicate through resolveActionParams - -The create-user phone fix (#2406) gated the `phoneNumber` param with -`visible: 'features.phoneNumber == true'`, but `resolveActionParam` dropped -`visible` when flattening raw spec params into `ActionParamDef` — so -`ActionParamDialog`'s `filterVisibleParams` never saw the predicate and the -phone field kept rendering even with the phoneNumber auth plugin off. - -Propagate `visible` in all three resolve branches (inline / field-backed / -missing-field), unwrapping the spec's `{ dialect, source }` ExpressionInput -envelope to a plain CEL string. Completes the create-user phone fix end to end. diff --git a/.changeset/sharing-rule-form-pickers.md b/.changeset/sharing-rule-form-pickers.md deleted file mode 100644 index 49bd846ed4..0000000000 --- a/.changeset/sharing-rule-form-pickers.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -"@object-ui/fields": minor -"@object-ui/components": minor -"@object-ui/data-objectstack": minor -"@object-ui/types": minor ---- - -Sharing-rule form: pick, don't type. Three new widget-hint field components make -the generic object form render pickers where an admin previously had to type -machine data (driven by the framework `widget` hints on `sys_sharing_rule`; -generalizes the `capability-multiselect` pattern). All degrade to the underlying -`type` renderer when a widget is unregistered. - -- **`object-ref`** — choose a registered object by name (searchable `Combobox`), - backed by the new `DataSource.getObjects()` (`ObjectStackAdapter` lists code- - and DB-defined objects via `/api/v1/meta/object`), falling back to a - `sys_metadata` query. Stores the object's `name`. -- **`filter-condition`** — a visual criteria builder (`FilterBuilder`) scoped to - the fields of the object chosen in a sibling field (via `getObjectSchema`), - round-tripping the stored **MongoDB-style** FilterCondition JSON. Criteria the - builder can't represent (or invalid JSON) fall back to a raw-JSON editor, with - an always-available "Edit as JSON" toggle — nothing is hidden or lost. -- **`recipient-picker`** — a record picker whose target object follows a sibling - `recipient_type` (`user`→sys_user, `team`→sys_team, `business_unit`/ - `unit_and_subordinates`→sys_business_unit, `position`→sys_position), storing the - value the evaluator matches on (a record id, or the position **name**). Resets - the stored id when the type changes. - -Wiring: the three keys join `DATA_SOURCE_FIELD_TYPES` (form.tsx) so the form -threads `dataSource` + `dependentValues` to them, and `INLINE_EXCLUDED_FIELD_TYPES` -(they're authored in the record form, not a grid cell). `DataSource.getObjects()` -is optional on the interface; the ObjectStack adapter implements it. diff --git a/apps/console/CHANGELOG.md b/apps/console/CHANGELOG.md index 6af37c0a63..fb51c14ca8 100644 --- a/apps/console/CHANGELOG.md +++ b/apps/console/CHANGELOG.md @@ -1,5 +1,62 @@ # @object-ui/console +## 14.0.0 + +### Major Changes + +- 2f3ab55: align with objectstack + +### Patch Changes + +- 94d00d4: feat(auth): phone number + password sign-in on the login page + + The login page's password mode now accepts an **email OR a phone number** as the + identifier and routes by shape — email → `/sign-in/email`, phone → + `/sign-in/phone-number` (better-auth phoneNumber plugin, framework#2780). It + coexists with the existing phone-OTP mode. + + - Gated on `features.phoneNumber` (phoneNumber plugin enabled). Unlike phone-OTP + it needs no SMS service, so it uses that coarser capability flag, not + `features.phoneNumberOtp`. When the flag is off the field stays email-only. + - New `AuthClient.signInWithPhonePassword(phoneNumber, password)` wired through + `AuthContext` / `AuthProvider` / `useAuth`. + - New `normalizePhoneIdentifier` / `looksLikePhoneIdentifier` helpers that mirror + the backend's `normalizePhoneNumber` exactly (strip `[\s\-().]`, validate + `^\+?[0-9]{6,15}$`, **no** forced E.164 / country code — the backend stores the + light-stripped form, so anything heavier would break the lookup). + - SSO stays email-only (a phone-shaped identifier no longer attempts domain + routing). + + Only works for accounts that have both a phone number and a password set; + phone-only accounts set a password on first OTP sign-in. + +- 5971cc4: i18n: translate the Profile page, honor inline i18n label objects under bare + base-language codes, and localize managed-by badges / record quick actions. + + - `pickLocalized` now upgrades a bare base language (`zh`) to any + region-qualified key sharing the base (`zh-CN`) — runtime language is + normalized to the base code while metadata authors write full BCP-47 tags, + so inline `{ en, 'zh-CN', ... }` label objects previously fell back to + English. + - ProfilePage (`account:profile_card` / `/system/profile`): every hardcoded + string — page title/subtitle, avatar Upload/Replace/Remove, Personal + Information card, Change/Set Password card — now goes through + `useObjectTranslation()` with `profile.*` keys (new namespace in all ten + locale bundles); the lazy-load fallback reuses `common.loading`. + - `ManagedByBadge` chips/tooltips (Config/System/Append-only/Identity) now + resolve through new `managedByBadge.*` keys with `{{provider}}` + interpolation. + - `record:quick_actions` resolves action labels via the + `objects.{object}._actions.{action}.label` convention plus `pickLocalized`, + so object action buttons (Change Password, Enable 2FA, …) localize. + - `record:details` / `record:related_list` / `record:alert` / `ObjectTree` + pass inline label objects through `pickLocalized`. + - Locale bundles: added `managedByBadge` namespace to all ten locales and + backfilled `list.inlineEditShort` / `inlineEditLabel` / + `recordEditingTitle` for ja/es/ko/de/fr/pt/ru/ar. + - @object-ui/react-runtime@14.0.0 + - @object-ui/sdui-parser@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/apps/console/package.json b/apps/console/package.json index 11df4dbbc4..fb6513d33c 100644 --- a/apps/console/package.json +++ b/apps/console/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/console", - "version": "13.2.0", + "version": "14.0.0", "description": "ObjectStack Console — opinionated, fork-ready runtime console built on @object-ui/app-shell with the full plugin set wired up. Ships as a Hono UI plugin serving a pre-built SPA.", "license": "MIT", "type": "module", diff --git a/packages/app-shell/CHANGELOG.md b/packages/app-shell/CHANGELOG.md index 9b909f0b77..0a0bc52545 100644 --- a/packages/app-shell/CHANGELOG.md +++ b/packages/app-shell/CHANGELOG.md @@ -1,5 +1,480 @@ # @object-ui/app-shell — Changelog +## 14.0.0 + +### Minor Changes + +- 06e92ac: feat(console-ai): ChatDock — right-docked AI rail behind a default-off flag (ADR-0057 P3a) + + Stands up the ADR-0057 P3 docked rail as an ADDITIVE, DEFAULT-OFF shell: until an + operator sets `features.chatDock`, nothing changes and the FAB stays the + canonical entry. + + - `@object-ui/layout`: `AppShell` gains an optional `rightRail` prop, rendered as + a flex sibling of the main content so the rail REFLOWS the content beside it + (VS Code / Cursor idiom), not overlaying it. Absent → unchanged single-pane. + - `@object-ui/app-shell`: new `ChatDock` — a collapsible, resizable right rail + that reuses the shared `ChatPane` engine over the P1 `(user, app, product=ask)` + conversation (the same ambient thread the FAB/`/ai` shows; it's a VIEW, not a + new conversation). Default COLLAPSED (a fixed edge launcher → zero layout cost + until invoked); ⌘/Ctrl+Shift+I toggles it. Gated on `useAiSurfaceEnabled` AND + the flag, so OSS / no-seat runtimes render nothing. + - `runtime-config`: `chatDock?` rollout flag, parsed default-OFF (opt-in only). + + Live-verified with the flag forced on: the launcher expands to a rail rendering + the ask chat, the dashboard content reflows narrower beside it, and collapse + restores the launcher. Unit-tested: width clamp, the composer-safe shortcut + matcher (⌘⇧I, no collision with the ⌘⇧O/S page shortcuts), and the flag's + default-off/opt-in parse. FAB retirement (P3b) and `/ai`-as-maximized-dock + + Studio reflow (P3c) follow. + +- 7b4fc36: feat(console-ai): ask→build handoff carries conversation context (ADR-0057 P4 / cloud#817) + + The P4 "Open in Builder →" handoff previously carried only the build prompt + an + optional package, so the Builder started cold and the user re-explained + themselves. It now also carries the **source `ask` conversation** as context — + ADR-0057 P4 / cloud#817 — so the build agent's first turn starts with the thread + the user already had. + + - `@object-ui/app-shell`: both handoff sites (the full-page `AiChatPage` and the + console FAB) now append `?parentConversationId=` to the + `/ai/build` URL. The build surface reads it and forwards it to `useObjectChat`; + the existing URL-mirror drops it once the build conversation id is minted, so a + reload never re-carries it. + - `@object-ui/plugin-chatbot`: `useObjectChat` accepts `parentConversationId` and + sends it as `context.parentConversationId` on the **first turn only** (held in a + ref, consumed once) — the backend redeems it into the turn's context and the + client owns history from there. New pure helper `withHandoffContext` (unit + tested) does the non-mutating `context` merge. + + Requires the cloud handoff-context contract (service-ai, cloud#817): the build + agent redeems `context.parentConversationId` into a single system block on its + first turn — ownership-checked, and carrying only the user/assistant text the + user already saw (ADR-0063 governance boundary). Without it the console degrades + cleanly: the id is sent but ignored, and the handoff is a (working) cold start. + +- 7dea792: feat(console-ai): explicit "Open in Builder →" ask→build handoff (ADR-0057 P4) + + When the `ask` agent declines an app-authoring request it now calls the cloud + `suggest_builder` tool (structured decline). The console renders that as an + explicit **"Open in Builder →"** action that opens the full-page build surface + seeded with the handoff prompt — ADR-0063 decline-and-redirect: an explicit, + user-initiated switch, never a silent re-route into authoring. + + - `@object-ui/plugin-chatbot`: `detectBuilderHandoff` lifts the + `{ status:'build_handoff', prompt, packageId? }` result onto the tool + invocation; `ChatbotEnhanced` renders the "Open in Builder →" card and calls a + new `onOpenBuilder` prop (disabled when no host wires it). + - `@object-ui/app-shell`: the full-page `AiChatPage` (`ask`) and the console FAB + wire `onOpenBuilder` to navigate to `/ai/build?package=…&handoffPrompt=…`; the + build surface seeds that prompt as its first message (auto-sent once the + conversation is minted), and the URL-mirror strips `?handoffPrompt` so a reload + never re-sends it. Full ask-conversation context transfer is a later upgrade + (cloud#817); v1 carries the build prompt + optional package. + + Requires the cloud `suggest_builder` signal (service-ai-studio) to light up; the + console degrades cleanly (no card) without it. + +- cd778d4: feat(console-ai): package binding chip + inert handoff cards + honest send hint (#2458 / ADR-0057 A1.a) + + Three UX improvements from live magic-flow testing: + + - **A1.a — package binding chip** (`app-shell`): the build surface header shows + the package the conversation is bound to (`📦 `), or **"New app"** when + unbound — so the edit blast-radius is always visible (Claude-Code-shows-the-repo + idiom). The magic flow starts unbound and binds the moment its build mints a + package (`deriveBoundPackageId` reads `?package=` else the latest draft/handoff + result; unit-tested). + - **UX#5 — only the latest handoff card is actionable** (`plugin-chatbot`): when + a thread accumulates several "Open in Builder →" cards, only the newest stays + clickable; older (superseded) cards' buttons are disabled — derived from + message order, so it survives the navigation the button triggers and the pane + remount that follows. A stale prompt in an older card can't be re-fired. + - **UX#7 — honest send hint** (`plugin-chatbot`): the composer already sends on + plain Enter (Shift+Enter = newline); dropped the misleading `⌘` glyph from the + hint so it no longer implies Cmd+Enter. + +### Patch Changes + +- 443360a: Action params support a `visible` CEL predicate — the param dialog omits a param + when it evaluates false, against the same scope as action `visible` (features / + user / app / data). Fixes the create-user form offering a **Phone Number** field + the default backend rejects ("Phone numbers require the phoneNumber auth plugin"): + paired with the framework gating that param on `features.phoneNumber`, the form + now follows the plugin — no phone field unless the opt-in phoneNumber auth plugin + is loaded. `filterVisibleParams` is exported + unit-tested (feature-off hides, + feature-on shows, malformed predicate fails open). +- c70bca7: fix(console-ai): Live Canvas is a full-screen, opt-in preview on mobile — not a broken split (#2481) + + On a phone the beside-chat Live Canvas split overflowed the viewport (the chat + column's fixed min-width plus the preview exceeded the screen, and the resize + handle is desktop-only, so it was stuck clipped). Under `md` the canvas is now: + + - **Full-width chat, no split** — the build streams in the chat as before. + - **Opt-in + full-screen** — when the preview is available a floating "Preview + app" pill appears; tapping it (or a Preview button on a draft card) takes the + canvas full-screen over the chat. Closing returns to the chat with the + preview one tap away. The auto-drafted canvas never covers the streaming + chat unprompted. + + Desktop is unchanged (the resizable beside-chat split). Adds the + `console.ai.previewApp` string (en/zh). + +- d06de4a: feat(console-ai): the ChatDock is now DEFAULT ON (ADR-0057 P3 go-live) + + `features.chatDock` flips from opt-in to opt-out: the right-docked chat rail + (FAB as launcher, `/ai` as the panel maximized, Studio right dock with center + `[Canvas | Properties]` tabs) is the console's default chat presentation. The + flag survives only as a server-side kill-switch — an operator sending + `chatDock: false` restores the floating-overlay console until the final + cleanup removes that path (epic #2409). + +- 1a12d69: polish(console-ai): ease the dock's canvas auto-maximize, and give Studio its own chat width (ADR-0057 UX follow-ups, #2477) + + - **#4** The rail now eases to its new width (200ms) when the Live Canvas opens + (auto-maximize) or closes (tuck), instead of snapping. The transition is + suppressed during a manual resize drag so the width still tracks the pointer + 1:1. + - **#6** The Studio dock persists its width under its own key, separate from the + console dock. A wide console chat no longer squeezes the Studio design canvas + (and vice-versa) — each surface remembers the width that suits it. + +- b800960: refactor(console-ai)!: ADR-0057 final cleanup — remove the chatDock flag, the floating-overlay console chat, and the legacy left Studio copilot + + The docked chat is now the console's ONE chat presentation, unconditionally: + + - `features.chatDock` is removed from the runtime config (it had already + flipped to default-on; the kill-switch is retired with the code path it + guarded). + - `ConsoleFloatingChatbot` (the FAB-armed floating overlay) and its + `agentPicker` helper are deleted; `ConsoleChatbotFab` is now a small + dependency-free launcher (`{ appLabel, onOpenDock }`) that opens the dock — + including on `/home`, where it opens the full-page `/ai` surface (the dock + maximized) since Home has no shell to host a rail. + - The legacy left `StudioAiCopilot` panel is deleted; the Studio copilot's one + home is the right `StudioChatDock`. The ADR-0080 `aiSlot` injection seam is + untouched. + - The runtime SDUI `type: 'chatbot'` bubble (end-user apps) is unchanged + (ADR-0057 §4). + - Fix: the mobile chat sheet no longer shows a "maximize" button. At 85svh the + sheet is already the maximal mobile chat, and navigating to full-page `/ai` + from an OPEN Radix sheet tore it down mid-close (the route change unmounts + the console synchronously, so the scroll-lock/overlay never released and the + destination landed blank-and-frozen — "tap maximize → the chat's just gone"). + Full-page `/ai` stays reachable via normal navigation. + +- 47b497f: feat(console-ai): mobile chat sheet bridges to full-page /ai (conversation history + share) — cleanly (ADR-0057 UX #2477 item 1) + + The mobile chat bottom sheet gets a maximize button back — it opens the + full-page `/ai`, which on mobile already carries the conversation-history + sidebar and share, so the sheet doesn't need a second copy of either. This is + the missing mobile path to switch/resume threads. + + The button navigates **deferred**: an earlier cut jumped straight from the + click and tore the still-open Radix sheet down mid-close (the route change + unmounts the console synchronously, leaking the sheet's scroll-lock/overlay + onto the destination — "tap maximize → the chat's just gone"). Now the click + only closes the sheet; a `useEffect` fires the navigation once `open` has + flipped false — after Radix released the body on that commit and before the + sheet unmounts — so `/ai` lands clean. Applies to both the console sheet + (→ `/ai`) and the Studio copilot sheet (→ `/ai/build?package=…`, same thread). + + Live Canvas on mobile `/ai` (the beside-chat split has no room on a phone) is + tracked separately (#2481). + +- 804a101: feat(console-ai): ChatDock follow-ups — mobile sheet, wide side-by-side properties, exact collapse landing (ADR-0057 P3) + + - Under `md` the dock presents as a bottom sheet (`ChatDockMobileSheet`) — + console FAB opens it; Studio gets a mobile-visible edge launcher. + - The folded Studio layout keeps canvas AND properties side by side on 2xl+ + viewports; tabs (and their auto-switch) only exist where width forces them. + - Folded tabs mode flattens the source page's nested Source/Props tabs — the + Properties tab body is the code editor directly. + - Maximize remembers its origin, so `/ai`'s collapse-to-dock returns to the + exact page (console or Studio) the user left, immune to history churn. + - The dock's conversation honors `app.defaultAgent` via the one resolver, + matching the FAB's behavior. + +- 3001e20: feat(console-ai): the FAB becomes the ChatDock launcher when the dock is on (ADR-0057 P3b) + + When `features.chatDock` is enabled, the console FAB opens the docked rail instead + of the floating overlay — one entry point, the ADR's "FAB → launcher" step. In + dock mode the FAB stays the lightweight button (it never mounts the heavy floating + chatbot; the rail loads the chat on demand), and a designer "Ask AI" open signal + (assistantBus) opens the dock too. With the flag OFF the FAB is unchanged (floating + overlay). Supersedes P3a's edge launcher (the dock is gated on the same + `showChatbot`, so the FAB is always present to launch it). + +- 159d7db: feat(console-ai): /ai = the ChatDock maximized + Studio right-dock reflow (ADR-0057 P3c) + + The final P3 slice, all behind the default-off `features.chatDock` flag: + + - **/ai ⇄ rail continuity**: the dock header gains a maximize button that opens + the full-page `/ai` surface, and the `/ai` page gains a collapse-to-dock button + that returns to the console with the rail expanded — same thread both ways + (the P1 `(user, app, product)` conversation key). Deep links + (`/ai/:agent/:conversationId`, ADR-0013) are untouched and keep working. + - **Studio reflow** (the ADR's decided grid `[left: nav/tree] [center: canvas + +properties] [right: chat]`): the AI copilot leaves the left `w-96` panel and + renders as the shared right dock (`ChatDockPanel` + `ChatDockLauncher`), same + package-scoped build thread; the Interfaces pillar's right inspector folds + into center `[Canvas | Properties]` tabs with select-a-block auto-switch. An + injected `aiSlot` (cloud seam, ADR-0080) keeps the legacy left panel. + - **Live Canvas** (ADR-0037): in the rail, the dock auto-maximizes while the + canvas is open and tucks back on close (manual resize wins); maximized (`/ai`) + keeps the existing beside-the-chat split. + + With the flag OFF, `/ai` and Studio are pixel-identical to before. + +- 1273f1e: fix(console-ai): reliable ask→build handoff auto-send + second-handoff context re-carry (ADR-0057 P4) + + Two follow-ups to the P4 "Open in Builder →" handoff: + + - **Auto-send swallow.** The handoff's auto-sent first message could be dropped on + a brand-new build conversation: the seed gated on the async-resolved + `activeAgent`, which can settle _after_ the conversation id is minted, so the + deferred-send replay ran with an empty pending and never re-fired. The seed now + gates on the **route** (`agentSegment`, synchronous) and bumps a `pendingSignal` + that `useDeferredFirstSend` lists in its replay deps, so the seed always fires — + no more empty build conversation on handoff. + + - **Second-handoff re-carry.** A second "Open in Builder →" into the (singleton) + build conversation now re-carries the latest ask context. The transport re-arms + `parentConversationId` on each falsy→truthy transition of the prop (the ask + thread is a singleton, so the same id repeats — the fresh-arrival signal is the + transition the URL-mirror produces, not a changed value), and the seed re-arms + on each new `handoffPrompt`. + + Unit-tested: deferred-send replays a post-id seed via the signal; the transport + re-carries across a strip→re-supply cycle. + +- 48d06da: fix(console-ai): Studio dock remembers a collapse; folded canvas+properties go side-by-side at `xl` (ADR-0057 UX follow-ups, #2477) + + - **Studio dock collapse is now remembered** (per-tab). The right copilot still + mounts expanded by default, but collapsing it to get the classic three-zone + canvas no longer re-opens on every pillar / package switch or Studio + re-entry. Backed by an explicit `'0'`/`'1'` stored flag (a default-expanded + surface couldn't remember a collapse when "collapsed" meant "key removed"), + under a Studio-specific key so it never shares state with the console dock. + - **Folded layout shows canvas + properties side by side from `xl`** (1280), + lowered from `2xl`. On the common laptop the folded center used to fall into + tabs, which auto-hide the canvas the moment you select a block — breaking the + WYSIWYG "edit and watch it apply" loop. The side-by-side inspector is slimmer + at `xl` (and grows at `2xl`) so the canvas keeps usable width beside the dock. + +- 9d0fdb1: feat(console-ai): render agent behavior by declared capability (cloud#816 / ADR-0057 "B+") + + `GET /api/v1/ai/agents` now serves per-agent `capabilities`; the console + consumes them instead of hard-coding `isBuildAgent(name)`: + + - `@object-ui/plugin-chatbot`: `AgentDescriptor.capabilities` (normalized from + the catalog) + new `agentHasCapability(agents, name, cap)` — declaration wins + when present; falls back to the legacy `isBuildAgent(name)` check when absent + (older server), so shipping order doesn't matter. + - `@object-ui/app-shell`: the build-doctor drawer + `showDebug` key off + `'debug'`, the FAB's resume-vs-fresh keys off `'resume'`, HomePage's + "Build with AI" availability keys off `'authoring'`. The ADR-0063 product-axis + sites (surface→agent resolver, conversation scope keying, picker availability) + intentionally stay name-based — capability describes RENDERED behavior, not + which product an agent is. + + A future skill-driven build variant now needs no console change. + +- 9442310: feat(console-ai): key AI chat conversations on `(user, app, product)`, not on surface (ADR-0057 P1) + + The console rendered AI chat through parallel shells that **forked the + conversation**: the Studio design copilot scoped its thread as + `studio:${packageId}:${agent}` while the full-page `/ai/build` focus view scoped + on the agent alone — so opening the _same app_ in both showed an empty "Build + with AI" copilot beside an active full-page build thread (indistinguishable from + data loss). + + Per ADR-0057 (**surface = view · conversation = model · product = binding + axis**), conversations are now keyed on `(user, app, product)`: + + - New pure, unit-tested `chatConversationScope({ appId, product })` + + `chatProductOfAgent(name)` helper (`hooks/chatScope.ts`) is the single place + the scope key is formed. `product` is the ADR-0063 axis (`ask` | `build`), + derived from the resolved agent — never a per-surface choice. + - `StudioAiCopilot` and the full-page `AiChatPage` both resolve + `app:${packageId}:${product}` for a package-scoped surface (the Studio copilot + editing package X and the `/ai/build?package=X` "Edit with AI" focus view now + resume ONE shared thread). The legacy `studio:` surface prefix is dropped. + - A generic `/ai/:agent` visit with no `?package=` degrades to the product alone + (`build` / `ask`) — unchanged behaviour for that surface. + + Enablement stays on the single access-filtered agent-catalog gate + (`useAiSurfaceEnabled`, ADR-0068) — a seat-less user's empty catalog hides the + whole AI surface. No layout change. + +- 9442310: feat(console-ai): one declarative surface→agent resolver (ADR-0057 P2) + + The console re-implemented the ADR-0063 surface→agent chain in ~5 places, each + spelled slightly differently — and `ConsoleLayout` carried an AI-Studio-off + downgrade special case that existed nowhere else. This collapses them into one + pure, unit-tested resolver so ADR-0063 (exactly two products `ask`/`build`, + bound by surface — no roster, no per-turn classifier) becomes a **structural** + guarantee. + + - New `hooks/surfaceAgent.ts`: `resolveSurfaceAgent(surface, { agents, +appDefaultAgent, aiStudioEnabled })` + `SURFACE_DEFAULT`. `app.defaultAgent` is + **bounded** to ask/build (alias-aware) — a withdrawn tenant custom agent is + rejected, not passed through, so no roster is representable (ADR-0057 open + question #4). The AI-Studio-off `build → ask` downgrade is folded in ONCE. + - `StudioAiCopilot` (studio-build → build) and the console FAB (`default` → ask) + resolve through it. The FAB keeps #771's "prefer build when the catalog unlocks + it and nothing pinned a product" by passing that as its default PRODUCT input — + so the resolver still owns bounding + the downgrade, which now also applies to + the #771 preference (closing the leak where an authoring-disabled deployment + could still open build). + - `ConsoleLayout`'s bespoke `!aiStudioEnabled && isBuildAgent(...)` downgrade is + deleted; it passes the raw `app.defaultAgent` and the resolver downgrades. + + Ships a unit table proving the ADR-0063 rows: Studio→build, other→ask, + AI-Studio-off downgrade, `app.defaultAgent` bounded (valid override wins, roster + rejected), alias-aware catalog resolution, empty catalog → inert (ADR-0025). + +- 05e56ca: 导出/导入模板的下载文件名与内容本地化。 + + **导出文件名**:CSV/Excel/JSON 导出下载不再是 `<对象名>.<扩展名>`(如 `contracts.csv`),改为「对象显示名-视图名-时间戳.扩展名」(如 `任务-In Progress-20260714-153045.xlsx`);`exportOptions.fileNamePrefix` 配置仍优先(且作为完整前缀,不再追加视图名)。视图名与对象名重复时自动省略;`@object-ui/core` 新增 `buildExportFileName(ext, { prefix, label, objectName, viewLabel }, now?)` 与 `sanitizeFileNameBase(raw)`,ObjectGrid 与 ListView 的所有导出路径(服务端流式与前端兜底)统一走它。app-shell/plugin-view 的 ObjectView 现将当前视图的显示标签写进传给 ListView 的 schema(`label`),使导出文件名能区分同一对象的不同保存视图。 + + **导入模板**:「下载模板」修复两处英文漏出——示例行的 select/多选取值改为优先取选项**显示标签**(如 `准备中`)而非 ASCII slug(`prepare`,服务端导入两者都接受);模板文件名本地化为 `{{object}}-导入模板.csv`(新增 i18n key `grid.import.templateFileName`,英文回退 `{{object}}-import-template.csv`)。 + +- 9d0fdb1: fix(console-ai): second handoff's auto-send no longer dies in the stale-scope pane (#2450) + + Mid ask→build transition, `useChatConversation` briefly still holds the OLD + scope's conversation id (the same stale window the URL-mirror already guards). + `` was fed that raw id, so a DOOMED pane (build chatApi + stale ask id, + about to remount) could mount — and the deferred first-send replay consumed the + handoff stash into it, where the send died with the unmount before reaching the + wire (observed live as "conversation resumes, zero `…/chat` POST"). + + Two-layer fix: + + - **Scope-gated pane feed (structural):** the page now hands `` a + conversation id/messages ONLY when `conversationScope === chatScope`. During + the stale window the pane mounts as `…:pending`, holds the stash, and replays + exactly once in the correctly-scoped pane — extending the existing URL-mirror + guard to the pane itself. + - **Targeted stash (defense-in-depth):** the handoff seed is stamped + `targetAgentRoute: 'build'`; `useDeferredFirstSend` refuses to consume a + targeted stash in a pane bound to another agent (untargeted user-typed sends + keep the legacy consume-anywhere behavior). + + Per product decision, a second handoff landing on a conversation with a + blueprint still Awaiting Approval just auto-sends — the build agent sees the + pending plan in context and decides merge/supersede itself. + +- 9138e68: fix(metadata-admin): authenticate console MetadataClient requests (Bearer token) + + Studio / metadata-admin surfaces issued `/api/v1/meta/*` requests (list types, + `?package=…` reads, `_drafts`, the `/meta` root) that came back `401 +unauthenticated` in the token-based console, while the runtime data adapter's + reads (`/meta/object|view|app`) succeeded — so the same page showed some + metadata requests failing and others working. + + Root cause: `useMetadataClient` and `MetadataProvider`'s draft-preview client + constructed `MetadataClient` without a `fetch`, so it fell back to the bare + `globalThis.fetch` and sent no `Authorization` header. The console + authenticates by a Bearer token in localStorage (`auth-session-token`) — there + is no session cookie — so those requests were unauthenticated. A same-origin + cookie deployment masks the bug, which is why it went unnoticed and regressed + twice. + + Both sites (and every future console surface) now construct through a single + `createConsoleMetadataClient` factory that bakes in `createAuthenticatedFetch` + (Bearer token + `X-Tenant-ID` + `Accept-Language`), matching the runtime data + adapter. This is additive for cookie deployments — `credentials` is untouched, + so a same-origin session cookie still flows. A + `metadata-client-auth.ratchet.test.ts` guard forbids a bare + `new MetadataClient(` elsewhere in app-shell so authentication can't silently + regress again. + +- 780b60a: Say "reset to shipped baseline" instead of "delete" when removing a package-owned permission set (ADR-0094). + + Deleting a `sys_permission_set` row whose `managed_by === 'package'` doesn't remove it — the backend drops the environment customization overlay and resets the set to its shipped baseline, so the row stays in the list. The confirmation dialog and success toast now say so (with `resetPackageSetConfirm` / `resetPackageSetSuccess` i18n, en + zh), instead of promising an irreversible delete the user can see doesn't happen. Environment-authored sets keep the plain delete copy. The grid row-delete passes the record through so the check needs no extra fetch; the SDUI header delete falls back to a `findOne` lookup. + +- 5971cc4: i18n: translate the Profile page, honor inline i18n label objects under bare + base-language codes, and localize managed-by badges / record quick actions. + + - `pickLocalized` now upgrades a bare base language (`zh`) to any + region-qualified key sharing the base (`zh-CN`) — runtime language is + normalized to the base code while metadata authors write full BCP-47 tags, + so inline `{ en, 'zh-CN', ... }` label objects previously fell back to + English. + - ProfilePage (`account:profile_card` / `/system/profile`): every hardcoded + string — page title/subtitle, avatar Upload/Replace/Remove, Personal + Information card, Change/Set Password card — now goes through + `useObjectTranslation()` with `profile.*` keys (new namespace in all ten + locale bundles); the lazy-load fallback reuses `common.loading`. + - `ManagedByBadge` chips/tooltips (Config/System/Append-only/Identity) now + resolve through new `managedByBadge.*` keys with `{{provider}}` + interpolation. + - `record:quick_actions` resolves action labels via the + `objects.{object}._actions.{action}.label` convention plus `pickLocalized`, + so object action buttons (Change Password, Enable 2FA, …) localize. + - `record:details` / `record:related_list` / `record:alert` / `ObjectTree` + pass inline label objects through `pickLocalized`. + - Locale bundles: added `managedByBadge` namespace to all ten locales and + backfilled `list.inlineEditShort` / `inlineEditLabel` / + `recordEditingTitle` for ja/es/ko/de/fr/pt/ru/ar. + +- 2fb38ed: fix(app-shell): propagate action-param `visible` predicate through resolveActionParams + + The create-user phone fix (#2406) gated the `phoneNumber` param with + `visible: 'features.phoneNumber == true'`, but `resolveActionParam` dropped + `visible` when flattening raw spec params into `ActionParamDef` — so + `ActionParamDialog`'s `filterVisibleParams` never saw the predicate and the + phone field kept rendering even with the phoneNumber auth plugin off. + + Propagate `visible` in all three resolve branches (inline / field-backed / + missing-field), unwrapping the spec's `{ dialect, source }` ExpressionInput + envelope to a plain CEL string. Completes the create-user phone fix end to end. + +- Updated dependencies [443360a] +- Updated dependencies [c70bca7] +- Updated dependencies [06e92ac] +- Updated dependencies [7b4fc36] +- Updated dependencies [1273f1e] +- Updated dependencies [7dea792] +- Updated dependencies [86c69c3] +- Updated dependencies [bfea27f] +- Updated dependencies [9d0fdb1] +- Updated dependencies [cd778d4] +- Updated dependencies [05e56ca] +- Updated dependencies [408f4ba] +- Updated dependencies [a44e7b6] +- Updated dependencies [eef832b] +- Updated dependencies [b66d8ee] +- Updated dependencies [94d00d4] +- Updated dependencies [5971cc4] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/i18n@14.0.0 + - @object-ui/layout@14.0.0 + - @object-ui/plugin-chatbot@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/plugin-grid@14.0.0 + - @object-ui/plugin-list@14.0.0 + - @object-ui/plugin-view@14.0.0 + - @object-ui/components@14.0.0 + - @object-ui/plugin-detail@14.0.0 + - @object-ui/auth@14.0.0 + - @object-ui/fields@14.0.0 + - @object-ui/data-objectstack@14.0.0 + - @object-ui/plugin-calendar@14.0.0 + - @object-ui/plugin-charts@14.0.0 + - @object-ui/plugin-dashboard@14.0.0 + - @object-ui/plugin-designer@14.0.0 + - @object-ui/plugin-editor@14.0.0 + - @object-ui/plugin-form@14.0.0 + - @object-ui/plugin-kanban@14.0.0 + - @object-ui/plugin-report@14.0.0 + - @object-ui/collaboration@14.0.0 + - @object-ui/permissions@14.0.0 + - @object-ui/providers@14.0.0 + ## 13.2.0 ### Minor Changes diff --git a/packages/app-shell/package.json b/packages/app-shell/package.json index 1fa1a2f436..3e13275c6c 100644 --- a/packages/app-shell/package.json +++ b/packages/app-shell/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/app-shell", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Minimal application shell for ObjectUI - framework-agnostic rendering engine", diff --git a/packages/auth/CHANGELOG.md b/packages/auth/CHANGELOG.md index abafff3602..770aa1923d 100644 --- a/packages/auth/CHANGELOG.md +++ b/packages/auth/CHANGELOG.md @@ -1,5 +1,37 @@ # @object-ui/auth +## 14.0.0 + +### Minor Changes + +- 94d00d4: feat(auth): phone number + password sign-in on the login page + + The login page's password mode now accepts an **email OR a phone number** as the + identifier and routes by shape — email → `/sign-in/email`, phone → + `/sign-in/phone-number` (better-auth phoneNumber plugin, framework#2780). It + coexists with the existing phone-OTP mode. + + - Gated on `features.phoneNumber` (phoneNumber plugin enabled). Unlike phone-OTP + it needs no SMS service, so it uses that coarser capability flag, not + `features.phoneNumberOtp`. When the flag is off the field stays email-only. + - New `AuthClient.signInWithPhonePassword(phoneNumber, password)` wired through + `AuthContext` / `AuthProvider` / `useAuth`. + - New `normalizePhoneIdentifier` / `looksLikePhoneIdentifier` helpers that mirror + the backend's `normalizePhoneNumber` exactly (strip `[\s\-().]`, validate + `^\+?[0-9]{6,15}$`, **no** forced E.164 / country code — the backend stores the + light-stripped form, so anything heavier would break the lookup). + - SSO stays email-only (a phone-shaped identifier no longer attempts domain + routing). + + Only works for accounts that have both a phone number and a password set; + phone-only accounts set a password on first OTP sign-in. + +### Patch Changes + +- Updated dependencies [86c69c3] +- Updated dependencies [6a74160] + - @object-ui/types@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/auth/package.json b/packages/auth/package.json index 24a29d72a3..594b9ce595 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/auth", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Authentication system for Object UI with AuthProvider, useAuth hook, AuthGuard, and form components.", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 7b8fda3d85..b347187fc3 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,16 @@ # @object-ui/cli +## 14.0.0 + +### Patch Changes + +- Updated dependencies [86c69c3] +- Updated dependencies [a44e7b6] +- Updated dependencies [6a74160] + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 6b2aa4ebf3..c307105379 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/cli", - "version": "13.2.0", + "version": "14.0.0", "description": "Standalone CLI for Object UI — scaffold, develop, build and validate JSON/YAML schema-driven applications.", "type": "module", "homepage": "https://www.objectui.org/docs/utilities/cli", diff --git a/packages/collaboration/CHANGELOG.md b/packages/collaboration/CHANGELOG.md index c9cd1a4f02..6941fb9e47 100644 --- a/packages/collaboration/CHANGELOG.md +++ b/packages/collaboration/CHANGELOG.md @@ -1,5 +1,13 @@ # @object-ui/collaboration +## 14.0.0 + +### Patch Changes + +- Updated dependencies [86c69c3] +- Updated dependencies [6a74160] + - @object-ui/types@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/collaboration/package.json b/packages/collaboration/package.json index 45b8ac96a4..8cac326d75 100644 --- a/packages/collaboration/package.json +++ b/packages/collaboration/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/collaboration", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Real-time collaboration for Object UI with presence tracking, live cursors, conflict resolution, and comment threads.", diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 79878b6a6d..b6e3d41b0f 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -1,5 +1,59 @@ # @object-ui/components +## 14.0.0 + +### Minor Changes + +- 6a74160: Sharing-rule form: pick, don't type. Three new widget-hint field components make + the generic object form render pickers where an admin previously had to type + machine data (driven by the framework `widget` hints on `sys_sharing_rule`; + generalizes the `capability-multiselect` pattern). All degrade to the underlying + `type` renderer when a widget is unregistered. + + - **`object-ref`** — choose a registered object by name (searchable `Combobox`), + backed by the new `DataSource.getObjects()` (`ObjectStackAdapter` lists code- + and DB-defined objects via `/api/v1/meta/object`), falling back to a + `sys_metadata` query. Stores the object's `name`. + - **`filter-condition`** — a visual criteria builder (`FilterBuilder`) scoped to + the fields of the object chosen in a sibling field (via `getObjectSchema`), + round-tripping the stored **MongoDB-style** FilterCondition JSON. Criteria the + builder can't represent (or invalid JSON) fall back to a raw-JSON editor, with + an always-available "Edit as JSON" toggle — nothing is hidden or lost. + - **`recipient-picker`** — a record picker whose target object follows a sibling + `recipient_type` (`user`→sys_user, `team`→sys_team, `business_unit`/ + `unit_and_subordinates`→sys_business_unit, `position`→sys_position), storing the + value the evaluator matches on (a record id, or the position **name**). Resets + the stored id when the type changes. + + Wiring: the three keys join `DATA_SOURCE_FIELD_TYPES` (form.tsx) so the form + threads `dataSource` + `dependentValues` to them, and `INLINE_EXCLUDED_FIELD_TYPES` + (they're authored in the record form, not a grid cell). `DataSource.getObjects()` + is optional on the interface; the ObjectStack adapter implements it. + +### Patch Changes + +- a44e7b6: Form fields honor their object-schema `widget` render hint on the field-group / + section layout path. `ObjectForm` renders objects that declare field groups + (e.g. `sys_sharing_rule`) via an auto-derived section layout that passed each + field's metadata through without hoisting its `widget` override to the top-level + form-field config, so a field with `widget: 'object-ref'` (or `filter-condition` + / `recipient-picker`) degraded to its bare `type` input — an admin was asked to + hand-type an object name instead of picking it. The form renderer now falls back + to the field metadata's own `widget` when no top-level override is present, so + the pickers render on sectioned forms just as they do on flat ones. +- Updated dependencies [443360a] +- Updated dependencies [c70bca7] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [5971cc4] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/i18n@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/react-runtime@14.0.0 + - @object-ui/sdui-parser@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/components/package.json b/packages/components/package.json index db85668135..7b49603e45 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/components", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Standard UI component library for Object UI, built with Shadcn UI + Tailwind CSS", diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index eb73089dcd..615b1e98b6 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,27 @@ # @object-ui/core +## 14.0.0 + +### Patch Changes + +- 443360a: Action params support a `visible` CEL predicate — the param dialog omits a param + when it evaluates false, against the same scope as action `visible` (features / + user / app / data). Fixes the create-user form offering a **Phone Number** field + the default backend rejects ("Phone numbers require the phoneNumber auth plugin"): + paired with the framework gating that param on `features.phoneNumber`, the form + now follows the plugin — no phone field unless the opt-in phoneNumber auth plugin + is loaded. `filterVisibleParams` is exported + unit-tested (feature-off hides, + feature-on shows, malformed predicate fails open). +- 05e56ca: 导出/导入模板的下载文件名与内容本地化。 + + **导出文件名**:CSV/Excel/JSON 导出下载不再是 `<对象名>.<扩展名>`(如 `contracts.csv`),改为「对象显示名-视图名-时间戳.扩展名」(如 `任务-In Progress-20260714-153045.xlsx`);`exportOptions.fileNamePrefix` 配置仍优先(且作为完整前缀,不再追加视图名)。视图名与对象名重复时自动省略;`@object-ui/core` 新增 `buildExportFileName(ext, { prefix, label, objectName, viewLabel }, now?)` 与 `sanitizeFileNameBase(raw)`,ObjectGrid 与 ListView 的所有导出路径(服务端流式与前端兜底)统一走它。app-shell/plugin-view 的 ObjectView 现将当前视图的显示标签写进传给 ListView 的 schema(`label`),使导出文件名能区分同一对象的不同保存视图。 + + **导入模板**:「下载模板」修复两处英文漏出——示例行的 select/多选取值改为优先取选项**显示标签**(如 `准备中`)而非 ASCII slug(`prepare`,服务端导入两者都接受);模板文件名本地化为 `{{object}}-导入模板.csv`(新增 i18n key `grid.import.templateFileName`,英文回退 `{{object}}-import-template.csv`)。 + +- Updated dependencies [86c69c3] +- Updated dependencies [6a74160] + - @object-ui/types@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/core/package.json b/packages/core/package.json index 56d3322571..66f71ec05a 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/core", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "sideEffects": false, "license": "MIT", diff --git a/packages/create-plugin/CHANGELOG.md b/packages/create-plugin/CHANGELOG.md index 40a92ec713..4abec72e7d 100644 --- a/packages/create-plugin/CHANGELOG.md +++ b/packages/create-plugin/CHANGELOG.md @@ -1,5 +1,7 @@ # @object-ui/create-plugin +## 14.0.0 + ## 13.2.0 ## 13.1.0 diff --git a/packages/create-plugin/package.json b/packages/create-plugin/package.json index 81a47ae846..c3247b21a9 100644 --- a/packages/create-plugin/package.json +++ b/packages/create-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/create-plugin", - "version": "13.2.0", + "version": "14.0.0", "description": "CLI tool to scaffold ObjectUI plugins", "type": "module", "license": "MIT", diff --git a/packages/data-objectstack/CHANGELOG.md b/packages/data-objectstack/CHANGELOG.md index 8b47e5a9a7..e0920d8a71 100644 --- a/packages/data-objectstack/CHANGELOG.md +++ b/packages/data-objectstack/CHANGELOG.md @@ -1,5 +1,44 @@ # @object-ui/data-objectstack +## 14.0.0 + +### Minor Changes + +- 6a74160: Sharing-rule form: pick, don't type. Three new widget-hint field components make + the generic object form render pickers where an admin previously had to type + machine data (driven by the framework `widget` hints on `sys_sharing_rule`; + generalizes the `capability-multiselect` pattern). All degrade to the underlying + `type` renderer when a widget is unregistered. + + - **`object-ref`** — choose a registered object by name (searchable `Combobox`), + backed by the new `DataSource.getObjects()` (`ObjectStackAdapter` lists code- + and DB-defined objects via `/api/v1/meta/object`), falling back to a + `sys_metadata` query. Stores the object's `name`. + - **`filter-condition`** — a visual criteria builder (`FilterBuilder`) scoped to + the fields of the object chosen in a sibling field (via `getObjectSchema`), + round-tripping the stored **MongoDB-style** FilterCondition JSON. Criteria the + builder can't represent (or invalid JSON) fall back to a raw-JSON editor, with + an always-available "Edit as JSON" toggle — nothing is hidden or lost. + - **`recipient-picker`** — a record picker whose target object follows a sibling + `recipient_type` (`user`→sys_user, `team`→sys_team, `business_unit`/ + `unit_and_subordinates`→sys_business_unit, `position`→sys_position), storing the + value the evaluator matches on (a record id, or the position **name**). Resets + the stored id when the type changes. + + Wiring: the three keys join `DATA_SOURCE_FIELD_TYPES` (form.tsx) so the form + threads `dataSource` + `dependentValues` to them, and `INLINE_EXCLUDED_FIELD_TYPES` + (they're authored in the record form, not a grid cell). `DataSource.getObjects()` + is optional on the interface; the ObjectStack adapter implements it. + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/types@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/data-objectstack/package.json b/packages/data-objectstack/package.json index 54b8336659..0cd02e5295 100644 --- a/packages/data-objectstack/package.json +++ b/packages/data-objectstack/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/data-objectstack", - "version": "13.2.0", + "version": "14.0.0", "description": "ObjectStack Data Adapter for Object UI", "license": "MIT", "type": "module", diff --git a/packages/fields/CHANGELOG.md b/packages/fields/CHANGELOG.md index 3cc33de369..425f8b34e1 100644 --- a/packages/fields/CHANGELOG.md +++ b/packages/fields/CHANGELOG.md @@ -1,5 +1,51 @@ # @object-ui/fields +## 14.0.0 + +### Minor Changes + +- 6a74160: Sharing-rule form: pick, don't type. Three new widget-hint field components make + the generic object form render pickers where an admin previously had to type + machine data (driven by the framework `widget` hints on `sys_sharing_rule`; + generalizes the `capability-multiselect` pattern). All degrade to the underlying + `type` renderer when a widget is unregistered. + + - **`object-ref`** — choose a registered object by name (searchable `Combobox`), + backed by the new `DataSource.getObjects()` (`ObjectStackAdapter` lists code- + and DB-defined objects via `/api/v1/meta/object`), falling back to a + `sys_metadata` query. Stores the object's `name`. + - **`filter-condition`** — a visual criteria builder (`FilterBuilder`) scoped to + the fields of the object chosen in a sibling field (via `getObjectSchema`), + round-tripping the stored **MongoDB-style** FilterCondition JSON. Criteria the + builder can't represent (or invalid JSON) fall back to a raw-JSON editor, with + an always-available "Edit as JSON" toggle — nothing is hidden or lost. + - **`recipient-picker`** — a record picker whose target object follows a sibling + `recipient_type` (`user`→sys_user, `team`→sys_team, `business_unit`/ + `unit_and_subordinates`→sys_business_unit, `position`→sys_position), storing the + value the evaluator matches on (a record id, or the position **name**). Resets + the stored id when the type changes. + + Wiring: the three keys join `DATA_SOURCE_FIELD_TYPES` (form.tsx) so the form + threads `dataSource` + `dependentValues` to them, and `INLINE_EXCLUDED_FIELD_TYPES` + (they're authored in the record form, not a grid cell). `DataSource.getObjects()` + is optional on the interface; the ObjectStack adapter implements it. + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [c70bca7] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [5971cc4] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/i18n@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + - @object-ui/providers@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/fields/package.json b/packages/fields/package.json index c3f87b8adb..bbc3926f51 100644 --- a/packages/fields/package.json +++ b/packages/fields/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/fields", - "version": "13.2.0", + "version": "14.0.0", "description": "Field renderers and registry for Object UI", "license": "MIT", "type": "module", diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index 26e15b989e..12e4280787 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -1,5 +1,56 @@ # @object-ui/i18n +## 14.0.0 + +### Patch Changes + +- c70bca7: fix(console-ai): Live Canvas is a full-screen, opt-in preview on mobile — not a broken split (#2481) + + On a phone the beside-chat Live Canvas split overflowed the viewport (the chat + column's fixed min-width plus the preview exceeded the screen, and the resize + handle is desktop-only, so it was stuck clipped). Under `md` the canvas is now: + + - **Full-width chat, no split** — the build streams in the chat as before. + - **Opt-in + full-screen** — when the preview is available a floating "Preview + app" pill appears; tapping it (or a Preview button on a draft card) takes the + canvas full-screen over the chat. Closing returns to the chat with the + preview one tap away. The auto-drafted canvas never covers the streaming + chat unprompted. + + Desktop is unchanged (the resizable beside-chat split). Adds the + `console.ai.previewApp` string (en/zh). + +- 05e56ca: 导出/导入模板的下载文件名与内容本地化。 + + **导出文件名**:CSV/Excel/JSON 导出下载不再是 `<对象名>.<扩展名>`(如 `contracts.csv`),改为「对象显示名-视图名-时间戳.扩展名」(如 `任务-In Progress-20260714-153045.xlsx`);`exportOptions.fileNamePrefix` 配置仍优先(且作为完整前缀,不再追加视图名)。视图名与对象名重复时自动省略;`@object-ui/core` 新增 `buildExportFileName(ext, { prefix, label, objectName, viewLabel }, now?)` 与 `sanitizeFileNameBase(raw)`,ObjectGrid 与 ListView 的所有导出路径(服务端流式与前端兜底)统一走它。app-shell/plugin-view 的 ObjectView 现将当前视图的显示标签写进传给 ListView 的 schema(`label`),使导出文件名能区分同一对象的不同保存视图。 + + **导入模板**:「下载模板」修复两处英文漏出——示例行的 select/多选取值改为优先取选项**显示标签**(如 `准备中`)而非 ASCII slug(`prepare`,服务端导入两者都接受);模板文件名本地化为 `{{object}}-导入模板.csv`(新增 i18n key `grid.import.templateFileName`,英文回退 `{{object}}-import-template.csv`)。 + +- 5971cc4: i18n: translate the Profile page, honor inline i18n label objects under bare + base-language codes, and localize managed-by badges / record quick actions. + + - `pickLocalized` now upgrades a bare base language (`zh`) to any + region-qualified key sharing the base (`zh-CN`) — runtime language is + normalized to the base code while metadata authors write full BCP-47 tags, + so inline `{ en, 'zh-CN', ... }` label objects previously fell back to + English. + - ProfilePage (`account:profile_card` / `/system/profile`): every hardcoded + string — page title/subtitle, avatar Upload/Replace/Remove, Personal + Information card, Change/Set Password card — now goes through + `useObjectTranslation()` with `profile.*` keys (new namespace in all ten + locale bundles); the lazy-load fallback reuses `common.loading`. + - `ManagedByBadge` chips/tooltips (Config/System/Append-only/Identity) now + resolve through new `managedByBadge.*` keys with `{{provider}}` + interpolation. + - `record:quick_actions` resolves action labels via the + `objects.{object}._actions.{action}.label` convention plus `pickLocalized`, + so object action buttons (Change Password, Enable 2FA, …) localize. + - `record:details` / `record:related_list` / `record:alert` / `ObjectTree` + pass inline label objects through `pickLocalized`. + - Locale bundles: added `managedByBadge` namespace to all ten locales and + backfilled `list.inlineEditShort` / `inlineEditLabel` / + `recordEditingTitle` for ja/es/ko/de/fr/pt/ru/ar. + ## 13.2.0 ### Patch Changes diff --git a/packages/i18n/package.json b/packages/i18n/package.json index de3b45d678..155420d136 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/i18n", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "sideEffects": false, "license": "MIT", diff --git a/packages/layout/CHANGELOG.md b/packages/layout/CHANGELOG.md index e4f61419a3..d869616483 100644 --- a/packages/layout/CHANGELOG.md +++ b/packages/layout/CHANGELOG.md @@ -1,5 +1,45 @@ # @object-ui/layout +## 14.0.0 + +### Minor Changes + +- 06e92ac: feat(console-ai): ChatDock — right-docked AI rail behind a default-off flag (ADR-0057 P3a) + + Stands up the ADR-0057 P3 docked rail as an ADDITIVE, DEFAULT-OFF shell: until an + operator sets `features.chatDock`, nothing changes and the FAB stays the + canonical entry. + + - `@object-ui/layout`: `AppShell` gains an optional `rightRail` prop, rendered as + a flex sibling of the main content so the rail REFLOWS the content beside it + (VS Code / Cursor idiom), not overlaying it. Absent → unchanged single-pane. + - `@object-ui/app-shell`: new `ChatDock` — a collapsible, resizable right rail + that reuses the shared `ChatPane` engine over the P1 `(user, app, product=ask)` + conversation (the same ambient thread the FAB/`/ai` shows; it's a VIEW, not a + new conversation). Default COLLAPSED (a fixed edge launcher → zero layout cost + until invoked); ⌘/Ctrl+Shift+I toggles it. Gated on `useAiSurfaceEnabled` AND + the flag, so OSS / no-seat runtimes render nothing. + - `runtime-config`: `chatDock?` rollout flag, parsed default-OFF (opt-in only). + + Live-verified with the flag forced on: the launcher expands to a rail rendering + the ask chat, the dashboard content reflows narrower beside it, and collapse + restores the launcher. Unit-tested: width clamp, the composer-safe shortcut + matcher (⌘⇧I, no collision with the ⌘⇧O/S page shortcuts), and the flag's + default-off/opt-in parse. FAB retirement (P3b) and `/ai`-as-maximized-dock + + Studio reflow (P3c) follow. + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/layout/package.json b/packages/layout/package.json index 5e0cfc1ef4..d1f127ac86 100644 --- a/packages/layout/package.json +++ b/packages/layout/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/layout", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "sideEffects": false, "main": "dist/index.umd.cjs", diff --git a/packages/mobile/CHANGELOG.md b/packages/mobile/CHANGELOG.md index 054d566f03..87c24b33f5 100644 --- a/packages/mobile/CHANGELOG.md +++ b/packages/mobile/CHANGELOG.md @@ -1,5 +1,13 @@ # @object-ui/mobile +## 14.0.0 + +### Patch Changes + +- Updated dependencies [86c69c3] +- Updated dependencies [6a74160] + - @object-ui/types@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/mobile/package.json b/packages/mobile/package.json index c0148e07cb..7e16f4bf36 100644 --- a/packages/mobile/package.json +++ b/packages/mobile/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/mobile", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Mobile optimization for Object UI with responsive components, PWA support, and touch gesture handling.", diff --git a/packages/permissions/CHANGELOG.md b/packages/permissions/CHANGELOG.md index 1208c98d03..1523c0401c 100644 --- a/packages/permissions/CHANGELOG.md +++ b/packages/permissions/CHANGELOG.md @@ -1,5 +1,13 @@ # @object-ui/permissions +## 14.0.0 + +### Patch Changes + +- Updated dependencies [86c69c3] +- Updated dependencies [6a74160] + - @object-ui/types@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/permissions/package.json b/packages/permissions/package.json index b94c463366..2e27f49d7e 100644 --- a/packages/permissions/package.json +++ b/packages/permissions/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/permissions", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "RBAC permission system for Object UI with object/field/row-level access control, permission guards, and hooks.", diff --git a/packages/plugin-ai/CHANGELOG.md b/packages/plugin-ai/CHANGELOG.md index a7917160cc..50fe0a99e9 100644 --- a/packages/plugin-ai/CHANGELOG.md +++ b/packages/plugin-ai/CHANGELOG.md @@ -1,5 +1,19 @@ # @object-ui/plugin-ai +## 14.0.0 + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-ai/package.json b/packages/plugin-ai/package.json index 1ebea676b9..eecde772c1 100644 --- a/packages/plugin-ai/package.json +++ b/packages/plugin-ai/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-ai", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "main": "dist/index.umd.cjs", "module": "dist/index.js", diff --git a/packages/plugin-calendar/CHANGELOG.md b/packages/plugin-calendar/CHANGELOG.md index 1a39766c46..95dd284f8f 100644 --- a/packages/plugin-calendar/CHANGELOG.md +++ b/packages/plugin-calendar/CHANGELOG.md @@ -1,5 +1,26 @@ # @object-ui/plugin-calendar +## 14.0.0 + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [c70bca7] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [eef832b] +- Updated dependencies [5971cc4] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/i18n@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + - @object-ui/plugin-detail@14.0.0 + - @object-ui/fields@14.0.0 + - @object-ui/mobile@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-calendar/package.json b/packages/plugin-calendar/package.json index bbe05b6ed2..6249794bba 100644 --- a/packages/plugin-calendar/package.json +++ b/packages/plugin-calendar/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-calendar", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Calendar view plugins for Object UI - includes both ObjectQL-integrated and standalone calendar components", diff --git a/packages/plugin-charts/CHANGELOG.md b/packages/plugin-charts/CHANGELOG.md index bf996f30fa..1af2a795d4 100644 --- a/packages/plugin-charts/CHANGELOG.md +++ b/packages/plugin-charts/CHANGELOG.md @@ -1,5 +1,22 @@ # @object-ui/plugin-charts +## 14.0.0 + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [c70bca7] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [5971cc4] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/i18n@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-charts/package.json b/packages/plugin-charts/package.json index 38c2b3f60f..061a9b6bc1 100644 --- a/packages/plugin-charts/package.json +++ b/packages/plugin-charts/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-charts", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Chart components plugin for Object UI, powered by Recharts", diff --git a/packages/plugin-chatbot/CHANGELOG.md b/packages/plugin-chatbot/CHANGELOG.md index 961ea7c663..c05c44e0a8 100644 --- a/packages/plugin-chatbot/CHANGELOG.md +++ b/packages/plugin-chatbot/CHANGELOG.md @@ -1,5 +1,144 @@ # @object-ui/plugin-chatbot +## 14.0.0 + +### Minor Changes + +- 7b4fc36: feat(console-ai): ask→build handoff carries conversation context (ADR-0057 P4 / cloud#817) + + The P4 "Open in Builder →" handoff previously carried only the build prompt + an + optional package, so the Builder started cold and the user re-explained + themselves. It now also carries the **source `ask` conversation** as context — + ADR-0057 P4 / cloud#817 — so the build agent's first turn starts with the thread + the user already had. + + - `@object-ui/app-shell`: both handoff sites (the full-page `AiChatPage` and the + console FAB) now append `?parentConversationId=` to the + `/ai/build` URL. The build surface reads it and forwards it to `useObjectChat`; + the existing URL-mirror drops it once the build conversation id is minted, so a + reload never re-carries it. + - `@object-ui/plugin-chatbot`: `useObjectChat` accepts `parentConversationId` and + sends it as `context.parentConversationId` on the **first turn only** (held in a + ref, consumed once) — the backend redeems it into the turn's context and the + client owns history from there. New pure helper `withHandoffContext` (unit + tested) does the non-mutating `context` merge. + + Requires the cloud handoff-context contract (service-ai, cloud#817): the build + agent redeems `context.parentConversationId` into a single system block on its + first turn — ownership-checked, and carrying only the user/assistant text the + user already saw (ADR-0063 governance boundary). Without it the console degrades + cleanly: the id is sent but ignored, and the handoff is a (working) cold start. + +- 7dea792: feat(console-ai): explicit "Open in Builder →" ask→build handoff (ADR-0057 P4) + + When the `ask` agent declines an app-authoring request it now calls the cloud + `suggest_builder` tool (structured decline). The console renders that as an + explicit **"Open in Builder →"** action that opens the full-page build surface + seeded with the handoff prompt — ADR-0063 decline-and-redirect: an explicit, + user-initiated switch, never a silent re-route into authoring. + + - `@object-ui/plugin-chatbot`: `detectBuilderHandoff` lifts the + `{ status:'build_handoff', prompt, packageId? }` result onto the tool + invocation; `ChatbotEnhanced` renders the "Open in Builder →" card and calls a + new `onOpenBuilder` prop (disabled when no host wires it). + - `@object-ui/app-shell`: the full-page `AiChatPage` (`ask`) and the console FAB + wire `onOpenBuilder` to navigate to `/ai/build?package=…&handoffPrompt=…`; the + build surface seeds that prompt as its first message (auto-sent once the + conversation is minted), and the URL-mirror strips `?handoffPrompt` so a reload + never re-sends it. Full ask-conversation context transfer is a later upgrade + (cloud#817); v1 carries the build prompt + optional package. + + Requires the cloud `suggest_builder` signal (service-ai-studio) to light up; the + console degrades cleanly (no card) without it. + +- 9d0fdb1: feat(console-ai): render agent behavior by declared capability (cloud#816 / ADR-0057 "B+") + + `GET /api/v1/ai/agents` now serves per-agent `capabilities`; the console + consumes them instead of hard-coding `isBuildAgent(name)`: + + - `@object-ui/plugin-chatbot`: `AgentDescriptor.capabilities` (normalized from + the catalog) + new `agentHasCapability(agents, name, cap)` — declaration wins + when present; falls back to the legacy `isBuildAgent(name)` check when absent + (older server), so shipping order doesn't matter. + - `@object-ui/app-shell`: the build-doctor drawer + `showDebug` key off + `'debug'`, the FAB's resume-vs-fresh keys off `'resume'`, HomePage's + "Build with AI" availability keys off `'authoring'`. The ADR-0063 product-axis + sites (surface→agent resolver, conversation scope keying, picker availability) + intentionally stay name-based — capability describes RENDERED behavior, not + which product an agent is. + + A future skill-driven build variant now needs no console change. + +- cd778d4: feat(console-ai): package binding chip + inert handoff cards + honest send hint (#2458 / ADR-0057 A1.a) + + Three UX improvements from live magic-flow testing: + + - **A1.a — package binding chip** (`app-shell`): the build surface header shows + the package the conversation is bound to (`📦 `), or **"New app"** when + unbound — so the edit blast-radius is always visible (Claude-Code-shows-the-repo + idiom). The magic flow starts unbound and binds the moment its build mints a + package (`deriveBoundPackageId` reads `?package=` else the latest draft/handoff + result; unit-tested). + - **UX#5 — only the latest handoff card is actionable** (`plugin-chatbot`): when + a thread accumulates several "Open in Builder →" cards, only the newest stays + clickable; older (superseded) cards' buttons are disabled — derived from + message order, so it survives the navigation the button triggers and the pane + remount that follows. A stale prompt in an older card can't be re-fired. + - **UX#7 — honest send hint** (`plugin-chatbot`): the composer already sends on + plain Enter (Shift+Enter = newline); dropped the misleading `⌘` glyph from the + hint so it no longer implies Cmd+Enter. + +### Patch Changes + +- 1273f1e: fix(console-ai): reliable ask→build handoff auto-send + second-handoff context re-carry (ADR-0057 P4) + + Two follow-ups to the P4 "Open in Builder →" handoff: + + - **Auto-send swallow.** The handoff's auto-sent first message could be dropped on + a brand-new build conversation: the seed gated on the async-resolved + `activeAgent`, which can settle _after_ the conversation id is minted, so the + deferred-send replay ran with an empty pending and never re-fired. The seed now + gates on the **route** (`agentSegment`, synchronous) and bumps a `pendingSignal` + that `useDeferredFirstSend` lists in its replay deps, so the seed always fires — + no more empty build conversation on handoff. + + - **Second-handoff re-carry.** A second "Open in Builder →" into the (singleton) + build conversation now re-carries the latest ask context. The transport re-arms + `parentConversationId` on each falsy→truthy transition of the prop (the ask + thread is a singleton, so the same id repeats — the fresh-arrival signal is the + transition the URL-mirror produces, not a changed value), and the seed re-arms + on each new `handoffPrompt`. + + Unit-tested: deferred-send replays a post-id seed via the signal; the transport + re-carries across a strip→re-supply cycle. + +- bfea27f: Make the ask-decline wait feel responsive: live thinking indicator + handoff card the moment `suggest_builder` lands (#2458 item 3). + + When the `ask` agent declines a build-shaped request, the ~20s before the "Open in Builder →" card is dominated by the LLM's time-to-tool-call. During that wait the chat could show dead air — a blank bubble, or the static "执行过程" activity note (a hydrated-history affordance) when the backend streamed a `(called …)` tool-call placeholder. + + `ChatbotEnhanced` now shows the existing live thinking indicator (`ThinkingDots`) whenever a streaming assistant turn has nothing visible yet — including whitespace-only content, a mid-stream `(called …)` placeholder, and hidden reasoning in `summary` mode. The static "执行过程" note is reserved for FINISHED (re-hydrated) tool-call-only turns (#772 preserved). The `builderHandoff` card already renders at `output-available` with no gate on the trailing prose, so it surfaces the instant the tool result arrives; the typing cursor now only paints beside real streaming prose (no lone cursor during the tool phase). + +- 408f4ba: fix(plugin-chatbot): build-result summary truncates on mobile instead of overflowing (#2493) + + The draft-review card's summary line (`built N artifact(s) — …`) is a nowrap + `truncate` span, but its flex row lacked the `min-w-0` that lets `truncate` + actually bite — so on a phone the long summary expanded the chat column past + the viewport and the whole chat scrolled sideways. The span now gets + `min-w-0 flex-1` (truncating within the row) and the action row is `flex-wrap` + so its buttons drop to a new line on a narrow screen rather than forcing + horizontal scroll. Desktop is unchanged (there's room, so nothing wraps or + truncates). + +- Updated dependencies [443360a] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-chatbot/package.json b/packages/plugin-chatbot/package.json index 43e2b14628..c74d14151d 100644 --- a/packages/plugin-chatbot/package.json +++ b/packages/plugin-chatbot/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-chatbot", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Chatbot interface plugin for Object UI", diff --git a/packages/plugin-dashboard/CHANGELOG.md b/packages/plugin-dashboard/CHANGELOG.md index fb8faa2e1a..73a813a35f 100644 --- a/packages/plugin-dashboard/CHANGELOG.md +++ b/packages/plugin-dashboard/CHANGELOG.md @@ -1,5 +1,23 @@ # @object-ui/plugin-dashboard +## 14.0.0 + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [c70bca7] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [5971cc4] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/i18n@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + - @object-ui/fields@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-dashboard/package.json b/packages/plugin-dashboard/package.json index a87595d045..c8a3aefae9 100644 --- a/packages/plugin-dashboard/package.json +++ b/packages/plugin-dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-dashboard", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Dashboard plugin for Object UI", diff --git a/packages/plugin-designer/CHANGELOG.md b/packages/plugin-designer/CHANGELOG.md index 85faacc0d5..a29ac218fd 100644 --- a/packages/plugin-designer/CHANGELOG.md +++ b/packages/plugin-designer/CHANGELOG.md @@ -1,5 +1,26 @@ # @object-ui/plugin-designer +## 14.0.0 + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [c70bca7] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [5971cc4] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/i18n@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/plugin-grid@14.0.0 + - @object-ui/components@14.0.0 + - @object-ui/fields@14.0.0 + - @object-ui/data-objectstack@14.0.0 + - @object-ui/plugin-form@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-designer/package.json b/packages/plugin-designer/package.json index 20794a6799..87168cacb8 100644 --- a/packages/plugin-designer/package.json +++ b/packages/plugin-designer/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-designer", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Visual designer plugin for Object UI with page, data model, process, and report designers plus collaborative editing.", diff --git a/packages/plugin-detail/CHANGELOG.md b/packages/plugin-detail/CHANGELOG.md index 91118a89ea..0197bf4e94 100644 --- a/packages/plugin-detail/CHANGELOG.md +++ b/packages/plugin-detail/CHANGELOG.md @@ -1,5 +1,54 @@ # @object-ui/plugin-detail +## 14.0.0 + +### Patch Changes + +- eef832b: 修复记录抽屉绕过甘特图行级锁定的问题(#2436 第 5 项)。 + + - `RecordDetailDrawer` 的编辑/删除能力现在由调用方是否传入 `onFieldSave` / `onDelete` 决定:两者都省略时抽屉严格只读(无内联编辑、无删除入口)。此前抽屉硬编码 `inlineEdit` 与 `showDelete: true`,并无条件向内层 DetailView 传包装函数,导致锁定记录仍可"编辑"(且改动静默丢失)。 + - `ObjectGantt` 对 `lockField` 锁定的行、以及全局 `readOnly` 的甘特图,不再向抽屉传入 `onFieldSave` / `onDelete`,与时间轴上禁止拖拽/调整的行为保持一致。 + +- 5971cc4: i18n: translate the Profile page, honor inline i18n label objects under bare + base-language codes, and localize managed-by badges / record quick actions. + + - `pickLocalized` now upgrades a bare base language (`zh`) to any + region-qualified key sharing the base (`zh-CN`) — runtime language is + normalized to the base code while metadata authors write full BCP-47 tags, + so inline `{ en, 'zh-CN', ... }` label objects previously fell back to + English. + - ProfilePage (`account:profile_card` / `/system/profile`): every hardcoded + string — page title/subtitle, avatar Upload/Replace/Remove, Personal + Information card, Change/Set Password card — now goes through + `useObjectTranslation()` with `profile.*` keys (new namespace in all ten + locale bundles); the lazy-load fallback reuses `common.loading`. + - `ManagedByBadge` chips/tooltips (Config/System/Append-only/Identity) now + resolve through new `managedByBadge.*` keys with `{{provider}}` + interpolation. + - `record:quick_actions` resolves action labels via the + `objects.{object}._actions.{action}.label` convention plus `pickLocalized`, + so object action buttons (Change Password, Enable 2FA, …) localize. + - `record:details` / `record:related_list` / `record:alert` / `ObjectTree` + pass inline label objects through `pickLocalized`. + - Locale bundles: added `managedByBadge` namespace to all ten locales and + backfilled `list.inlineEditShort` / `inlineEditLabel` / + `recordEditingTitle` for ja/es/ko/de/fr/pt/ru/ar. + +- Updated dependencies [443360a] +- Updated dependencies [c70bca7] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [5971cc4] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/i18n@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + - @object-ui/fields@14.0.0 + - @object-ui/permissions@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-detail/package.json b/packages/plugin-detail/package.json index 0b6fdf2abe..0a88f1f6a5 100644 --- a/packages/plugin-detail/package.json +++ b/packages/plugin-detail/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-detail", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "DetailView plugin for Object UI - comprehensive detail page with sections, tabs, and related lists", diff --git a/packages/plugin-editor/CHANGELOG.md b/packages/plugin-editor/CHANGELOG.md index b928bd6225..ba34b57143 100644 --- a/packages/plugin-editor/CHANGELOG.md +++ b/packages/plugin-editor/CHANGELOG.md @@ -1,5 +1,19 @@ # @object-ui/plugin-editor +## 14.0.0 + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-editor/package.json b/packages/plugin-editor/package.json index 17e5e5e291..e3ca411c16 100644 --- a/packages/plugin-editor/package.json +++ b/packages/plugin-editor/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-editor", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Rich text editor plugin for Object UI, powered by Monaco Editor", diff --git a/packages/plugin-form/CHANGELOG.md b/packages/plugin-form/CHANGELOG.md index 2963f7bc08..fcacd3da74 100644 --- a/packages/plugin-form/CHANGELOG.md +++ b/packages/plugin-form/CHANGELOG.md @@ -1,5 +1,24 @@ # @object-ui/plugin-form +## 14.0.0 + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [c70bca7] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [5971cc4] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/i18n@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + - @object-ui/fields@14.0.0 + - @object-ui/permissions@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-form/package.json b/packages/plugin-form/package.json index 4b9f683b15..e20a698dba 100644 --- a/packages/plugin-form/package.json +++ b/packages/plugin-form/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-form", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Form plugin for Object UI", diff --git a/packages/plugin-gantt/CHANGELOG.md b/packages/plugin-gantt/CHANGELOG.md index 25fe5b3762..fb83781e61 100644 --- a/packages/plugin-gantt/CHANGELOG.md +++ b/packages/plugin-gantt/CHANGELOG.md @@ -1,5 +1,65 @@ # @object-ui/plugin-gantt +## 14.0.0 + +### Patch Changes + +- a506e6d: ObjectGantt now supports the `api` data source for **both read and write-back**. + Previously `provider: 'api'` logged "API provider not yet implemented" and rendered + nothing, and every write-back (reschedule, dependency edit, delete, drawer + inline-edit) was hard-wired to the context ObjectQL `dataSource` + `objectName`, + so the api provider's `write` config was never used. + + All reads and writes now flow through a single adapter resolved by + `resolveDataSource(schema.data, dataSource)`: `object` → context DataSource + (unchanged), `api` → `ApiDataSource` (executes the `read`/`write` HttpRequest + config), `value` → in-memory `ValueDataSource`. A pure-api view needs no + `objectName` and no context `dataSource` prop. Object-backed views are behavior- + preserving. Lookup/master_detail quick-filter option domains still resolve from + the context object backend (they degrade to distinct in-row values when absent). + +- 42b36c4: 新增逐任务预警描边(#2436 第 3 项):视图配置 `borderColorField` 指向 + 记录上的预警颜色字段(常为服务端计算的超期/临期字段),该行条形在保留 + 原有填充色的同时,以该颜色描边并加 2px 光晕——任务条、里程碑菱形、 + 汇总条均生效。语义色名(red/orange/…)映射为调色板 hex,其余 CSS 颜色 + 原样透传;空值不描边。开启关键路径高亮时,关键路径样式在其标记行上优先。 +- 8a7d5af: 拖拽连线增加内建校验与宿主否决钩子(#2436 第 1、2 项)。落点为锁定行 + (`locked`)或分组行(`type: 'group'`)时,悬停不再高亮、松手不再创建; + 成环依赖(直接回边、跨层级传递回边)基于**全量任务集**检测并拒绝——不受 + 折叠子树导致可见连线缺边的影响。新增 `onBeforeDependencyCreate(source, +target, type)` 钩子,在内建校验通过后调用,返回 `false` 可否决本次连线 + (即 DHTMLX `onBeforeLinkAdd` / Syncfusion `actionBegin` 惯例)。 + `wouldCreateDependencyCycle` 从 `scheduling` 导出并单测覆盖。 +- eef832b: 修复记录抽屉绕过甘特图行级锁定的问题(#2436 第 5 项)。 + + - `RecordDetailDrawer` 的编辑/删除能力现在由调用方是否传入 `onFieldSave` / `onDelete` 决定:两者都省略时抽屉严格只读(无内联编辑、无删除入口)。此前抽屉硬编码 `inlineEdit` 与 `showDelete: true`,并无条件向内层 DetailView 传包装函数,导致锁定记录仍可"编辑"(且改动静默丢失)。 + - `ObjectGantt` 对 `lockField` 锁定的行、以及全局 `readOnly` 的甘特图,不再向抽屉传入 `onFieldSave` / `onDelete`,与时间轴上禁止拖拽/调整的行为保持一致。 + +- 0b03b34: 快速筛选改为树感知(#2436 第 4 项):命中任务的**全部祖先链**一并保留。 + 此前 `displayTasks` 是平铺过滤,项目/产品等分组行本身没有可筛字段值, + 一筛就被丢掉,命中的子任务成孤儿、树结构被打散。现在祖先随命中下级 + 自动保留、无命中下级时照常剔除,多分支命中共享祖先不重复。 +- 07b2cda: 甘特图写后回读 + 工具栏手动刷新按钮(#2436 第 6/7 项)。 + + - 拖拽改期、依赖增删、抽屉内联编辑、删除记录成功后,静默重新读取数据源,让服务端重算的字段(父级汇总、预警颜色、工期重算)刷新到图上;此前乐观补丁只保留客户端写入的字段,派生字段一直陈旧直到整页刷新。静默刷新不闪 loading、不卸载 GanttView(保留滚动/折叠状态),并发请求按序号防乱序覆盖;失败时保留屏上最后一份好数据。 + - GanttView 工具栏新增手动刷新按钮(`onRefresh` / `refreshing` props),object 数据源自动接线;内联 value 数据无可回读来源,不显示按钮。 + +- Updated dependencies [443360a] +- Updated dependencies [c70bca7] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [eef832b] +- Updated dependencies [5971cc4] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/i18n@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + - @object-ui/plugin-detail@14.0.0 + - @object-ui/fields@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-gantt/package.json b/packages/plugin-gantt/package.json index 78d3dec5b5..243511db03 100644 --- a/packages/plugin-gantt/package.json +++ b/packages/plugin-gantt/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-gantt", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Gantt chart plugin for Object UI", diff --git a/packages/plugin-grid/CHANGELOG.md b/packages/plugin-grid/CHANGELOG.md index 205b1032e8..e54e65c846 100644 --- a/packages/plugin-grid/CHANGELOG.md +++ b/packages/plugin-grid/CHANGELOG.md @@ -1,5 +1,30 @@ # @object-ui/plugin-grid +## 14.0.0 + +### Patch Changes + +- 05e56ca: 导出/导入模板的下载文件名与内容本地化。 + + **导出文件名**:CSV/Excel/JSON 导出下载不再是 `<对象名>.<扩展名>`(如 `contracts.csv`),改为「对象显示名-视图名-时间戳.扩展名」(如 `任务-In Progress-20260714-153045.xlsx`);`exportOptions.fileNamePrefix` 配置仍优先(且作为完整前缀,不再追加视图名)。视图名与对象名重复时自动省略;`@object-ui/core` 新增 `buildExportFileName(ext, { prefix, label, objectName, viewLabel }, now?)` 与 `sanitizeFileNameBase(raw)`,ObjectGrid 与 ListView 的所有导出路径(服务端流式与前端兜底)统一走它。app-shell/plugin-view 的 ObjectView 现将当前视图的显示标签写进传给 ListView 的 schema(`label`),使导出文件名能区分同一对象的不同保存视图。 + + **导入模板**:「下载模板」修复两处英文漏出——示例行的 select/多选取值改为优先取选项**显示标签**(如 `准备中`)而非 ASCII slug(`prepare`,服务端导入两者都接受);模板文件名本地化为 `{{object}}-导入模板.csv`(新增 i18n key `grid.import.templateFileName`,英文回退 `{{object}}-import-template.csv`)。 + +- Updated dependencies [443360a] +- Updated dependencies [c70bca7] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [5971cc4] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/i18n@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + - @object-ui/fields@14.0.0 + - @object-ui/mobile@14.0.0 + ## 13.2.0 ### Minor Changes diff --git a/packages/plugin-grid/package.json b/packages/plugin-grid/package.json index 2688e3edff..b62610414f 100644 --- a/packages/plugin-grid/package.json +++ b/packages/plugin-grid/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-grid", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Grid plugin for Object UI", diff --git a/packages/plugin-kanban/CHANGELOG.md b/packages/plugin-kanban/CHANGELOG.md index 2ef31253d1..95c4168119 100644 --- a/packages/plugin-kanban/CHANGELOG.md +++ b/packages/plugin-kanban/CHANGELOG.md @@ -1,5 +1,25 @@ # @object-ui/plugin-kanban +## 14.0.0 + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [c70bca7] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [eef832b] +- Updated dependencies [5971cc4] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/i18n@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + - @object-ui/plugin-detail@14.0.0 + - @object-ui/fields@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-kanban/package.json b/packages/plugin-kanban/package.json index c1992ee45a..e41c793041 100644 --- a/packages/plugin-kanban/package.json +++ b/packages/plugin-kanban/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-kanban", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Kanban board plugin for Object UI, powered by dnd-kit", diff --git a/packages/plugin-list/CHANGELOG.md b/packages/plugin-list/CHANGELOG.md index 57a5b63102..eaa50cf13b 100644 --- a/packages/plugin-list/CHANGELOG.md +++ b/packages/plugin-list/CHANGELOG.md @@ -1,5 +1,38 @@ # @object-ui/plugin-list +## 14.0.0 + +### Patch Changes + +- 05e56ca: 导出/导入模板的下载文件名与内容本地化。 + + **导出文件名**:CSV/Excel/JSON 导出下载不再是 `<对象名>.<扩展名>`(如 `contracts.csv`),改为「对象显示名-视图名-时间戳.扩展名」(如 `任务-In Progress-20260714-153045.xlsx`);`exportOptions.fileNamePrefix` 配置仍优先(且作为完整前缀,不再追加视图名)。视图名与对象名重复时自动省略;`@object-ui/core` 新增 `buildExportFileName(ext, { prefix, label, objectName, viewLabel }, now?)` 与 `sanitizeFileNameBase(raw)`,ObjectGrid 与 ListView 的所有导出路径(服务端流式与前端兜底)统一走它。app-shell/plugin-view 的 ObjectView 现将当前视图的显示标签写进传给 ListView 的 schema(`label`),使导出文件名能区分同一对象的不同保存视图。 + + **导入模板**:「下载模板」修复两处英文漏出——示例行的 select/多选取值改为优先取选项**显示标签**(如 `准备中`)而非 ASCII slug(`prepare`,服务端导入两者都接受);模板文件名本地化为 `{{object}}-导入模板.csv`(新增 i18n key `grid.import.templateFileName`,英文回退 `{{object}}-import-template.csv`)。 + +- b66d8ee: The list toolbar search button now shows the active keyword inline (mirroring + the Sort button's count badge). Previously a search term restored from + localStorage after navigating away and back kept filtering the list while the + search popover stayed collapsed — the only cue was a slightly darker magnifier + icon, so users couldn't tell a keyword filter was still active. The keyword is + rendered (truncated at 8rem) next to the magnifier whenever a search is active, + and clicking it opens the popover pre-filled for editing or clearing. +- Updated dependencies [443360a] +- Updated dependencies [c70bca7] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [5971cc4] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/i18n@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + - @object-ui/fields@14.0.0 + - @object-ui/mobile@14.0.0 + - @object-ui/permissions@14.0.0 + ## 13.2.0 ## 13.1.0 diff --git a/packages/plugin-list/package.json b/packages/plugin-list/package.json index d8f8024ef3..d63b2e7ed9 100644 --- a/packages/plugin-list/package.json +++ b/packages/plugin-list/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-list", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "ListView plugin for Object UI - unified view component with view type switching", diff --git a/packages/plugin-map/CHANGELOG.md b/packages/plugin-map/CHANGELOG.md index 2e17a071c6..92e9682b14 100644 --- a/packages/plugin-map/CHANGELOG.md +++ b/packages/plugin-map/CHANGELOG.md @@ -1,5 +1,19 @@ # @object-ui/plugin-map +## 14.0.0 + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-map/package.json b/packages/plugin-map/package.json index 0a644b9eaf..cb90eb3df2 100644 --- a/packages/plugin-map/package.json +++ b/packages/plugin-map/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-map", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Map visualization plugin for Object UI", diff --git a/packages/plugin-markdown/CHANGELOG.md b/packages/plugin-markdown/CHANGELOG.md index 0cfebdb227..62717d6b23 100644 --- a/packages/plugin-markdown/CHANGELOG.md +++ b/packages/plugin-markdown/CHANGELOG.md @@ -1,5 +1,19 @@ # @object-ui/plugin-markdown +## 14.0.0 + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-markdown/package.json b/packages/plugin-markdown/package.json index 44d68c3a7d..f52002b574 100644 --- a/packages/plugin-markdown/package.json +++ b/packages/plugin-markdown/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-markdown", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Markdown rendering plugin for Object UI, powered by react-markdown", diff --git a/packages/plugin-report/CHANGELOG.md b/packages/plugin-report/CHANGELOG.md index e23c1cbe9d..933e0a8845 100644 --- a/packages/plugin-report/CHANGELOG.md +++ b/packages/plugin-report/CHANGELOG.md @@ -1,5 +1,24 @@ # @object-ui/plugin-report +## 14.0.0 + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [c70bca7] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [5971cc4] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/i18n@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/plugin-grid@14.0.0 + - @object-ui/components@14.0.0 + - @object-ui/fields@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-report/package.json b/packages/plugin-report/package.json index ff2c5cc686..772ddf9722 100644 --- a/packages/plugin-report/package.json +++ b/packages/plugin-report/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-report", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "main": "dist/index.umd.cjs", "module": "dist/index.js", diff --git a/packages/plugin-timeline/CHANGELOG.md b/packages/plugin-timeline/CHANGELOG.md index 8f8fe3b49b..cd3ed697cf 100644 --- a/packages/plugin-timeline/CHANGELOG.md +++ b/packages/plugin-timeline/CHANGELOG.md @@ -1,5 +1,20 @@ # @object-ui/plugin-timeline +## 14.0.0 + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + - @object-ui/mobile@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-timeline/package.json b/packages/plugin-timeline/package.json index 14cb4afe9f..7294865c47 100644 --- a/packages/plugin-timeline/package.json +++ b/packages/plugin-timeline/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-timeline", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Timeline component plugin for Object UI", diff --git a/packages/plugin-tree/CHANGELOG.md b/packages/plugin-tree/CHANGELOG.md index 02ac04cc1a..9cd96ce3be 100644 --- a/packages/plugin-tree/CHANGELOG.md +++ b/packages/plugin-tree/CHANGELOG.md @@ -1,5 +1,44 @@ # @object-ui/plugin-tree +## 14.0.0 + +### Patch Changes + +- 5971cc4: i18n: translate the Profile page, honor inline i18n label objects under bare + base-language codes, and localize managed-by badges / record quick actions. + + - `pickLocalized` now upgrades a bare base language (`zh`) to any + region-qualified key sharing the base (`zh-CN`) — runtime language is + normalized to the base code while metadata authors write full BCP-47 tags, + so inline `{ en, 'zh-CN', ... }` label objects previously fell back to + English. + - ProfilePage (`account:profile_card` / `/system/profile`): every hardcoded + string — page title/subtitle, avatar Upload/Replace/Remove, Personal + Information card, Change/Set Password card — now goes through + `useObjectTranslation()` with `profile.*` keys (new namespace in all ten + locale bundles); the lazy-load fallback reuses `common.loading`. + - `ManagedByBadge` chips/tooltips (Config/System/Append-only/Identity) now + resolve through new `managedByBadge.*` keys with `{{provider}}` + interpolation. + - `record:quick_actions` resolves action labels via the + `objects.{object}._actions.{action}.label` convention plus `pickLocalized`, + so object action buttons (Change Password, Enable 2FA, …) localize. + - `record:details` / `record:related_list` / `record:alert` / `ObjectTree` + pass inline label objects through `pickLocalized`. + - Locale bundles: added `managedByBadge` namespace to all ten locales and + backfilled `list.inlineEditShort` / `inlineEditLabel` / + `recordEditingTitle` for ja/es/ko/de/fr/pt/ru/ar. + +- Updated dependencies [443360a] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-tree/package.json b/packages/plugin-tree/package.json index 67259fa24a..47b813bb7c 100644 --- a/packages/plugin-tree/package.json +++ b/packages/plugin-tree/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-tree", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Tree / tree-grid visualization plugin for Object UI", diff --git a/packages/plugin-view/CHANGELOG.md b/packages/plugin-view/CHANGELOG.md index 1d2450a009..d9385e35e0 100644 --- a/packages/plugin-view/CHANGELOG.md +++ b/packages/plugin-view/CHANGELOG.md @@ -1,5 +1,30 @@ # @object-ui/plugin-view +## 14.0.0 + +### Patch Changes + +- 05e56ca: 导出/导入模板的下载文件名与内容本地化。 + + **导出文件名**:CSV/Excel/JSON 导出下载不再是 `<对象名>.<扩展名>`(如 `contracts.csv`),改为「对象显示名-视图名-时间戳.扩展名」(如 `任务-In Progress-20260714-153045.xlsx`);`exportOptions.fileNamePrefix` 配置仍优先(且作为完整前缀,不再追加视图名)。视图名与对象名重复时自动省略;`@object-ui/core` 新增 `buildExportFileName(ext, { prefix, label, objectName, viewLabel }, now?)` 与 `sanitizeFileNameBase(raw)`,ObjectGrid 与 ListView 的所有导出路径(服务端流式与前端兜底)统一走它。app-shell/plugin-view 的 ObjectView 现将当前视图的显示标签写进传给 ListView 的 schema(`label`),使导出文件名能区分同一对象的不同保存视图。 + + **导入模板**:「下载模板」修复两处英文漏出——示例行的 select/多选取值改为优先取选项**显示标签**(如 `准备中`)而非 ASCII slug(`prepare`,服务端导入两者都接受);模板文件名本地化为 `{{object}}-导入模板.csv`(新增 i18n key `grid.import.templateFileName`,英文回退 `{{object}}-import-template.csv`)。 + +- Updated dependencies [443360a] +- Updated dependencies [c70bca7] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [5971cc4] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/i18n@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/plugin-grid@14.0.0 + - @object-ui/components@14.0.0 + - @object-ui/plugin-form@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/plugin-view/package.json b/packages/plugin-view/package.json index 7cfdb890c2..cbe0cefb72 100644 --- a/packages/plugin-view/package.json +++ b/packages/plugin-view/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/plugin-view", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Object View plugin for Object UI", diff --git a/packages/providers/CHANGELOG.md b/packages/providers/CHANGELOG.md index bb57cebffb..cd3760ad1c 100644 --- a/packages/providers/CHANGELOG.md +++ b/packages/providers/CHANGELOG.md @@ -1,5 +1,13 @@ # @object-ui/providers — Changelog +## 14.0.0 + +### Patch Changes + +- Updated dependencies [86c69c3] +- Updated dependencies [6a74160] + - @object-ui/types@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/providers/package.json b/packages/providers/package.json index 7240968267..788548a7ec 100644 --- a/packages/providers/package.json +++ b/packages/providers/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/providers", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Reusable context providers for ObjectUI applications", diff --git a/packages/react-runtime/CHANGELOG.md b/packages/react-runtime/CHANGELOG.md index a384b08dc8..47c6df0400 100644 --- a/packages/react-runtime/CHANGELOG.md +++ b/packages/react-runtime/CHANGELOG.md @@ -1,5 +1,7 @@ # @object-ui/react-runtime +## 14.0.0 + ## 13.2.0 ## 13.1.0 diff --git a/packages/react-runtime/package.json b/packages/react-runtime/package.json index 5493a39d75..1132a8ebc4 100644 --- a/packages/react-runtime/package.json +++ b/packages/react-runtime/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/react-runtime", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "sideEffects": false, "license": "MIT", diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index 8e032e6487..748a68b5a7 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,33 @@ # @object-ui/react +## 14.0.0 + +### Minor Changes + +- 86c69c3: ADR-0089: read the canonical `visibleWhen` conditional-visibility predicate in the form + page renderers. + + `@objectstack/spec` now unifies conditional visibility under a single canonical key, `visibleWhen`, and folds the deprecated `visibleOn` (view form) / `visibility` (page component) aliases into it at parse. This updates ObjectUI to read the canonical key: + + - **Page renderer** (`SchemaRenderer`) — evaluates `visibleWhen` first (show-when-truthy), then the deprecated `visibleOn` / `visibility` as a defensive read for raw / un-normalized metadata. `visibleWhen` is stripped from DOM props. + - **Spec→node bridges** — the page bridge maps a component's `visibleWhen ?? visibility` onto the node's canonical `visibleWhen`; the form-view bridge maps a field's `visibleWhen ?? visibleOn` onto the ObjectForm view-level predicate slot. + - **Form renderers** — the `@object-ui/react` `FormRenderer` prefers `visibleWhen` over the `visibleOn` alias. (`ObjectForm`/`form.tsx` already evaluated `visibleWhen`.) + - **Types** — the component base schema (`BaseSchema` / `base.zod`) gains the canonical `visibleWhen`; `visibleOn` is marked `@deprecated`. + + Fully back-compat: existing `visibleOn` / `visibility` metadata keeps working through the alias reads. + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [c70bca7] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [5971cc4] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/i18n@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/data-objectstack@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/react/package.json b/packages/react/package.json index 0bd67854da..884992e0df 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/react", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "React bindings and SchemaRenderer component for Object UI", diff --git a/packages/runner/CHANGELOG.md b/packages/runner/CHANGELOG.md index 8b480e9835..5861fbbc19 100644 --- a/packages/runner/CHANGELOG.md +++ b/packages/runner/CHANGELOG.md @@ -1,5 +1,21 @@ # @object-ui/runner +## 14.0.0 + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [a44e7b6] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/react@14.0.0 + - @object-ui/types@14.0.0 + - @object-ui/components@14.0.0 + - @object-ui/plugin-charts@14.0.0 + - @object-ui/plugin-kanban@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/runner/package.json b/packages/runner/package.json index cb5a24ff5e..0c9dd43505 100644 --- a/packages/runner/package.json +++ b/packages/runner/package.json @@ -1,7 +1,7 @@ { "name": "@object-ui/runner", "private": false, - "version": "13.2.0", + "version": "14.0.0", "description": "Universal Object UI Application Runner", "type": "module", "homepage": "https://www.objectui.org/docs/utilities/runner", diff --git a/packages/sdui-parser/CHANGELOG.md b/packages/sdui-parser/CHANGELOG.md index 9921f04a91..01711e8452 100644 --- a/packages/sdui-parser/CHANGELOG.md +++ b/packages/sdui-parser/CHANGELOG.md @@ -1,5 +1,7 @@ # @object-ui/sdui-parser +## 14.0.0 + ## 13.2.0 ## 13.1.0 diff --git a/packages/sdui-parser/package.json b/packages/sdui-parser/package.json index 94a76a5909..3570187951 100644 --- a/packages/sdui-parser/package.json +++ b/packages/sdui-parser/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/sdui-parser", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "sideEffects": false, "license": "MIT", diff --git a/packages/tenant/CHANGELOG.md b/packages/tenant/CHANGELOG.md index df079aafd1..2a8bacacf5 100644 --- a/packages/tenant/CHANGELOG.md +++ b/packages/tenant/CHANGELOG.md @@ -1,5 +1,13 @@ # @object-ui/tenant +## 14.0.0 + +### Patch Changes + +- Updated dependencies [86c69c3] +- Updated dependencies [6a74160] + - @object-ui/types@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/tenant/package.json b/packages/tenant/package.json index addd7cfd05..10bf75156c 100644 --- a/packages/tenant/package.json +++ b/packages/tenant/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/tenant", - "version": "13.2.0", + "version": "14.0.0", "type": "module", "license": "MIT", "description": "Multi-tenancy support for Object UI with tenant isolation, scoped queries, and custom branding.", diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md index 1b5db87b84..faa8a1891f 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/CHANGELOG.md @@ -1,5 +1,46 @@ # @object-ui/types +## 14.0.0 + +### Minor Changes + +- 86c69c3: ADR-0089: read the canonical `visibleWhen` conditional-visibility predicate in the form + page renderers. + + `@objectstack/spec` now unifies conditional visibility under a single canonical key, `visibleWhen`, and folds the deprecated `visibleOn` (view form) / `visibility` (page component) aliases into it at parse. This updates ObjectUI to read the canonical key: + + - **Page renderer** (`SchemaRenderer`) — evaluates `visibleWhen` first (show-when-truthy), then the deprecated `visibleOn` / `visibility` as a defensive read for raw / un-normalized metadata. `visibleWhen` is stripped from DOM props. + - **Spec→node bridges** — the page bridge maps a component's `visibleWhen ?? visibility` onto the node's canonical `visibleWhen`; the form-view bridge maps a field's `visibleWhen ?? visibleOn` onto the ObjectForm view-level predicate slot. + - **Form renderers** — the `@object-ui/react` `FormRenderer` prefers `visibleWhen` over the `visibleOn` alias. (`ObjectForm`/`form.tsx` already evaluated `visibleWhen`.) + - **Types** — the component base schema (`BaseSchema` / `base.zod`) gains the canonical `visibleWhen`; `visibleOn` is marked `@deprecated`. + + Fully back-compat: existing `visibleOn` / `visibility` metadata keeps working through the alias reads. + +- 6a74160: Sharing-rule form: pick, don't type. Three new widget-hint field components make + the generic object form render pickers where an admin previously had to type + machine data (driven by the framework `widget` hints on `sys_sharing_rule`; + generalizes the `capability-multiselect` pattern). All degrade to the underlying + `type` renderer when a widget is unregistered. + + - **`object-ref`** — choose a registered object by name (searchable `Combobox`), + backed by the new `DataSource.getObjects()` (`ObjectStackAdapter` lists code- + and DB-defined objects via `/api/v1/meta/object`), falling back to a + `sys_metadata` query. Stores the object's `name`. + - **`filter-condition`** — a visual criteria builder (`FilterBuilder`) scoped to + the fields of the object chosen in a sibling field (via `getObjectSchema`), + round-tripping the stored **MongoDB-style** FilterCondition JSON. Criteria the + builder can't represent (or invalid JSON) fall back to a raw-JSON editor, with + an always-available "Edit as JSON" toggle — nothing is hidden or lost. + - **`recipient-picker`** — a record picker whose target object follows a sibling + `recipient_type` (`user`→sys_user, `team`→sys_team, `business_unit`/ + `unit_and_subordinates`→sys_business_unit, `position`→sys_position), storing the + value the evaluator matches on (a record id, or the position **name**). Resets + the stored id when the type changes. + + Wiring: the three keys join `DATA_SOURCE_FIELD_TYPES` (form.tsx) so the form + threads `dataSource` + `dependentValues` to them, and `INLINE_EXCLUDED_FIELD_TYPES` + (they're authored in the record form, not a grid cell). `DataSource.getObjects()` + is optional on the interface; the ObjectStack adapter implements it. + ## 13.2.0 ## 13.1.0 diff --git a/packages/types/package.json b/packages/types/package.json index 7d318aa782..01cb2816ec 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@object-ui/types", - "version": "13.2.0", + "version": "14.0.0", "description": "Pure TypeScript type definitions for Object UI - The Protocol Layer", "type": "module", "sideEffects": false, diff --git a/packages/vscode-extension/CHANGELOG.md b/packages/vscode-extension/CHANGELOG.md index 5b2e7b24c8..ff38299be0 100644 --- a/packages/vscode-extension/CHANGELOG.md +++ b/packages/vscode-extension/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## 14.0.0 + +### Patch Changes + +- Updated dependencies [443360a] +- Updated dependencies [86c69c3] +- Updated dependencies [05e56ca] +- Updated dependencies [6a74160] + - @object-ui/core@14.0.0 + - @object-ui/types@14.0.0 + ## 13.2.0 ### Patch Changes diff --git a/packages/vscode-extension/package.json b/packages/vscode-extension/package.json index adc195867e..f179de64ef 100644 --- a/packages/vscode-extension/package.json +++ b/packages/vscode-extension/package.json @@ -2,7 +2,7 @@ "name": "object-ui", "displayName": "Object UI", "description": "VSCode extension for Object UI - Schema-driven UI development with IntelliSense, validation, and live preview", - "version": "13.2.0", + "version": "14.0.0", "publisher": "objectui", "private": true, "icon": "icon.svg",