You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 74db43e
Browse filesBrowse the repository at this point in the historyBrowse files
fix(console): Home's build chip and /ai read the agent catalog on a deployment without AI (#26716)
<!-- claude-projects-attribution: {"github_login":"zhuangjianguo"} -->
_Requested by **Steedos** · [project
thread](https://claude.ai/code/project/chan_018ETKaNwMZCNRYD7D8Q9Ubb?thread=cmsg_018ETKaNwMZCNRYD7D8Q9UbbDZiPLsrXtX5sZKRTuAwBEC)_Fixes#26614
Clause-②: yes
Metadata-protocol: none
## 维护者速读
- **改了什么**:没有 AI 智能体的部署上(`GET /api/v1/ai/agents`
为空或不可用),首页问候行的「构建应用」改为「在 Studio 中新建」,点开即进入 Studio
首页并直接弹出新建软件包对话框(`/studio?new=package`);没有「管理元数据」权限的会话则不显示这个按钮(「从模板开始」仍带着原因说明)。直接访问
`/_console/ai` 不再静默跳回首页,而是原地显示「AI 助手不可用 · 当前部署未启用 AI
助手」,带「返回首页」按钮,有权编写的管理员还会看到同一个「在 Studio 中新建」链接。有智能体的部署一切照旧。
- **为什么改**:在 HotCRM 本地(18.2.0、无 AI 智能体)上,「构建应用」承诺了一个无法开始的 AI 搭建,而 `/ai`
把人一声不响地送回首页,读起来像坏链接。
- **风险与回滚**:低。没有新端点、没有 spec 改动、没有元数据键;只读已有的智能体目录读数(`useAgents`
的同一份缓存)。按钮会等目录读数返回再画,所以有 AI 的部署上「构建应用」比以前晚一帧出现。新增发布面:i18n 键
`home.build.inStudio`(十个语言包)、`STUDIO_NEW_PACKAGE_PATH`
常量、`AiUnavailable` 抽成独立模块。`RequireAiSurface` 的 `redirectTo` prop
保留原名,改为决定该页面「返回首页」去哪。回滚即 revert 本 PR。
-
**先看**:`ui/packages/app-shell/src/console/home/HomePage.tsx`(`useHomeAiAvailability`
的 `aiResolved`
与两枚构建按钮);`ui/packages/app-shell/src/console/ConsoleShell.tsx`(`RequireAiSurface`
不再重定向);`ui/packages/app-shell/src/views/studio-design/BuilderLanding.tsx`(`?new=package`
深链接)。
- **两分钟验证**:`pnpm --dir ui exec vitest run
packages/app-shell/src/console/home/__tests__/HomePage.noAgentsBuildChip-26614.test.tsx
packages/app-shell/src/console/__tests__/RequireAiSurface.test.tsx
packages/app-shell/src/views/studio-design/BuilderLanding.newPackageDeepLink-26614.test.tsx`,预期全绿;或在没有
AI 的本地运行时打开 Console 首页,看到「在 Studio 中新建」,再打开 `/_console/ai` 看到「当前部署未启用 AI
助手」。
- **需要你做的**:无,席位落地。
## What changes
**Home's build chip reads the agent catalog.** `useHomeAiAvailability`
(the Home's existing `useAgents` read of `GET /api/v1/ai/agents`, no
second fetch path) now also reports `aiResolved`, with
`useAiSurfaceEnabled`'s latch, so the chip waits for the catalog's
answer instead of drawing one form and swapping to the other. For an
admin on a runtime with `features.aiStudio` on:
| catalog | may author | chip |
|---|---|---|
| one or more agents | yes | "Build an app" (「构建应用」) to `/studio`,
unchanged |
| one or more agents | no | "Build an app", dimmed with its reason,
unchanged |
| empty or failed | yes | "New in Studio" (「在 Studio 中新建」) to
`/studio?new=package` |
| empty or failed | no | no build chip; "Start with a template" keeps
the reason |
| not answered yet | any | no build chip |
**`/ai` with no agent.** `RequireAiSurface` (`console/ConsoleShell.tsx`,
the guard on the three `/ai` routes in `apps/console/src/App.tsx`) no
longer redirects home. It renders the AI-unavailable screen in place, in
a full-height frame: the title and description already in every pack
(`console.ai.unavailableTitle`, `console.ai.unavailableDescription`: 「AI
助手不可用」 · 「当前部署未启用 AI 助手。其他功能一切正常。」), "Back to home" to the declared
landing (objectui#7373, unchanged), and, for an admin who may author on
a runtime with `features.aiStudio` on, a "New in Studio" link to
`/studio?new=package`. That screen was `AiChatPage`'s private
`AiUnavailable` (shown when the catalog resolves empty after the gate);
it moves to `console/ai/AiUnavailable.tsx`, and both render it.
`redirectTo` keeps its name (renaming a published prop breaks every host
that passes it) and now sets where the screen's way home leads.
**Studio's new-package flow.** `/studio?new=package` opens the Studio
landing (`BuilderLanding`) with its create-package dialog open, and
drops the param with a replace, so a refresh or Back does not reopen it.
The path's one spelling is `STUDIO_NEW_PACKAGE_PATH` in
`views/studio-design/studioNewPackage.ts`, a module of its own so Home
and the `/ai` gate do not import `BuilderLanding` into the console's
eager closure (`apps/console/src/components/studioBuilder.ts` says why).
`new` is a page-scoped param of the landing, not one of `urlParams.ts`'s
reserved names.
**i18n.** One new key, `home.build.inStudio`, in all ten packs. The
order named two new strings; the second (「此部署未启用 AI 助手」) already exists
as `console.ai.unavailableDescription`, so it is reused, not added.
**Callers of `RequireAiSurface`.** Measured with `git grep`: the only
element callers are the three `/ai` routes in
`apps/console/src/App.tsx`, and they change as described.
`console/AppContent.tsx` and
`apps/console/src/components/StudioRoute.tsx` name it only in comments,
which this PR corrects; neither wraps anything with it.
`ui/e2e/console-boot-indicator.spec.ts` names it in a comment only and
pins no redirect. Five `apps/console` tests stub it as a pass-through,
unchanged.
## Tests
- `console/home/__tests__/HomePage.noAgentsBuildChip-26614.test.tsx`
(new, real `HomePage`, a catalog stand-in that moves as `useAgents`
does: empty first frame, loading, answer): with an agent, "Build an app"
to `/studio` and dimmed for a non-author; with none, "New in Studio" to
`/studio?new=package`; with none and no authoring capability, no build
chip while the template chip keeps the reason; while the catalog is in
flight, neither form.
- `console/__tests__/RequireAiSurface.test.tsx`: the no-agent case now
asserts the screen in place (no redirect, no retry); the Studio link for
an admin who may author, and its absence for a non-admin, a non-author
and a runtime without authoring; the two objectui#7373 cases now click
the screen's "Back to home" and land on the declared landing or the
launcher.
- `views/studio-design/BuilderLanding.newPackageDeepLink-26614.test.tsx`
(new, real `BuilderLanding` under a real router): the dialog opens on
arrival and the param leaves the address; other params stay; the bare
landing and an unknown value open nothing.
- `console/__tests__/bootRedirectCoverage.test.tsx`: the no-agent case
is no longer a redirect; it still asserts the deciding commit covers the
viewport, which the screen's full-height frame does.
- `console/home/__tests__/HomePage.greetingAndApps-12601.test.tsx`: its
catalog stand-in now holds one custom agent, so the builder-chip cases
it pins keep the "Build an app" form they were written for.
## Acceptance notes
- The screenshot of the home on a runtime without AI is not attached:
this container has no HotCRM deployment.
- On a transient `/agents` failure the guard now shows the same "not
enabled" screen it used to redirect away from: `useAiSurfaceEnabled`
reports no error, so the guard cannot tell a failure from an empty
catalog. `AiChatPage`'s own screen, reached when the guard passes, still
tells them apart and offers a retry.
- With agents present, the build chip appears once the catalog answers
rather than on the first frame.
## Verification
All local readings below were taken in a worktree on this branch; heads
named per reading.
<details><summary>Narrowed ui test run, head d566d91: 221 files, 2414
passed, 13 skipped</summary>
`pnpm --dir ui exec vitest run --maxWorkers=2` over every app-shell and
console test file that names `HomePage`, `ConsoleShell`, `AiChatPage`,
`BuilderLanding`, `AiUnavailable` or `studioNewPackage` (132 files, from
`git grep -l`), plus `packages/i18n/` whole: `Test Files 221 passed
(221)`, `Tests 2414 passed | 13 skipped (2427)`, lock VERDICT
command-exit 0. This is a declared narrowing; CI's Test UI shards run
the full suite.
</details>
<details><summary>Final head a967d2f (one commit after the run above,
BuilderLanding only)</summary>
- Every `BuilderLanding.*` test and every `StudioRoute*` test: `Test
Files 14 passed (14)`, `Tests 93 passed (93)`.
- `turbo run type-check --filter=@object-ui/app-shell`: 64 tasks
successful. On d566d91, `--filter=@object-ui/app-shell
--filter=@object-ui/console --filter=@object-ui/i18n`: 72 tasks
successful.
- `pnpm --dir ui exec vitest run scripts/`: 178 passed, 2 skipped files;
5065 tests passed.
- `pnpm check:new-line-citations` (from `ui/`): 0 new citations.
- `eslint --no-inline-config` over the changed ui files: 0 errors
(warnings only, of rules already warned across these files).
</details>
<details><summary>Derived gates: dispatch-gates --commands, 35 families,
all exit 0</summary>
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived 35 commands from the diff; each ran
with its exit code recorded, all 0 (two of them,
`check:query-options-erasure` and `check:type-check-debt`, re-run
without the 300 s cap that first stopped them). `--ran` reconciliation:
"35 derived famil(ies) accounted for — 35 run, 0 NOT-MEASURED". The
derived set reads paths only, and the last commit touched no new path.
Type-check lanes, wide-population families and the always-run tail are
CI's.
</details>
`dogfood_battery`: not run (no `!` in the title, no `(narrowing)` arm).
## Human Minimum
- [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic.
(`packages/spec` untouched.)
- [x] 2. Every name I added uses the casing for its kind.
- [x] 3. No formatter ran; `pnpm lint` passes. (CI's Lint UI is the
authority.)
- [x] 4. One issue, one branch off an up-to-date `main`, one pull
request.
- [x] 5. A change that publishes carries a changeset, and both
declaration lines are filled in here and in the changeset.
- [x] 6. `packages/spec` touched: not touched.
- [x] 7. No hand edits to `content/docs/references/`,
`packages/*/CHANGELOG.md` or `content/docs/releases/`.
- [x] 8. Title, body and comments are in English.
- [x] The *Before Submitting* list in CONTRIBUTING.md is done.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01QsR2jUo2twLdcxA9c695m5)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
fix(app-shell,i18n): on a deployment with no AI agent, Home's build chip opens Studio's new-package flow as "New in Studio", and `/ai` says no assistant is enabled instead of redirecting home
7
+
8
+
Clause-②: yes
9
+
Metadata-protocol: none
10
+
11
+
-**Home's build chip reads the agent catalog.** On a deployment whose catalog (`GET /api/v1/ai/agents`) is empty or absent, the greeting row's "Build an app" (「构建应用」) promised a build nothing there could start. There it now reads "New in Studio" (「在 Studio 中新建」) and opens Studio's new-package flow; a session that may not author gets no build chip at all, while "Start with a template" keeps the reason. The chip waits for the catalog's answer, so neither form flashes first. With an agent in the catalog nothing changes.
12
+
-**`/ai` with no agent.**`RequireAiSurface` used to redirect a visit to `/ai` home with no word of why. It now shows the AI-unavailable screen in place (「AI 助手不可用」 · 「当前部署未启用 AI 助手。其他功能一切正常。」), with the way home and, for an admin who may author on a runtime that offers authoring, the same "New in Studio" link. The screen is the one `AiChatPage` already showed for an empty catalog, now its own module (`console/ai/AiUnavailable.tsx`) shared by both. `RequireAiSurface`'s `redirectTo` prop keeps its name and now sets where that screen's way home leads.
13
+
-**Studio deep link.**`/studio?new=package` opens the Studio landing with the create-package dialog open, and drops the param from the address. `STUDIO_NEW_PACKAGE_PATH` (`views/studio-design/studioNewPackage.ts`) is its one spelling.
14
+
-**i18n.** New key `home.build.inStudio` in all ten packs.
0 commit comments