feat(cli): make the AI service opt-in via a declared dependency (Community-Edition support)#2311
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 3 package(s): 100 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
…nor config.tiers)
The CLI auto-registered the headless AIServicePlugin whenever the `ai` tier was
enabled (default) and @objectstack/service-ai was merely *resolvable*. In a
workspace/monorepo the package is hoist-resolvable even when an app doesn't
declare it, so every app got the AI service — discovery reported services.ai
available and the agent runtime served any metadata-defined agents — including
Community-Edition apps that ship no AI.
Make the DECLARED dependency the AI edition boundary: auto-register AIService
only when the host app declares @objectstack/service-ai OR
@objectstack/service-ai-studio (Studio attaches its personas via the base
service's `ai:ready` hook, so declaring Studio implies the base — load it even
when only Studio is in the deps). A CE app that declares neither gets no AI
service, no agents, and services.ai { enabled:false, status:'unavailable' } in
discovery — so the MIT console hides its AI surface — while MCP and every other
capability are unaffected.
Also honor `config.tiers`: ObjectStackDefinitionSchema gains a `tiers` field so
defineStack stops stripping it. `config.tiers` (e.g. a list without `ai`) now
actually overrides the `--preset` default — previously silently dropped by schema
validation, which made the `--preset` help text inaccurate. A second, in-place
lever to disable AI without touching dependencies.
Declare @objectstack/service-ai in the showcase and crm examples (they ship AI
agents) so they keep AI.
Verified e2e in an isolated build:
- app WITHOUT service-ai/studio → discovery AI unavailable, /api/v1/ai/agents
404, AIService not loaded; MCP server still starts + serves (401 auth-gate).
- app declaring service-ai (or studio-only) → services.ai available + agents served.
- config.tiers without `ai` → AIService not loaded even when service-ai IS declared.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
os-zhuang
force-pushed
the
feat/ce-ai-opt-in
branch
from
June 25, 2026 02:00
766452a to
91f6252
Compare
runtime/security/api-key.ts re-exports @objectstack/core's extractApiKey, which accepts a Bearer token carrying the `osk_` api-key prefix (for remote MCP clients — core's own test covers this). This duplicate test in runtime predated that behavior and asserted the old "Bearer is never an api-key" rule, so it failed whenever runtime's tests run. It was latent on main: turbo only runs runtime's tests when runtime or a dependency changes, and main's recent commits didn't. This PR's @objectstack/spec change makes spec "changed", so every spec-dependent package's tests now run — surfacing the pre-existing failure. Align the assertion with core + the implementation (extractApiKey is re-exported, so they must agree). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
os-zhuang
added a commit
to objectstack-ai/objectui
that referenced
this pull request
Jun 25, 2026
…he agent catalog (#1992) useAiSurfaceEnabled now keys off discovery's `services.ai` (isAiEnabled) — i.e. whether the enterprise @objectstack/service-ai capability is present — instead of a non-empty agent catalog. service-ai is an enterprise capability; a Community-Edition runtime doesn't ship it, so the framework doesn't register the AI service and discovery reports services.ai unavailable → the whole AI surface hides. An install that has service-ai reports it available → AI shows. The presence of the CAPABILITY gates, not whether a specific agent is configured yet. The earlier catalog-based gating was a workaround for the headless service-ai reporting itself available in CE. The framework now only registers the AI service when the host app declares @objectstack/service-ai (objectstack-ai/framework#2311), so discovery is an honest edition signal and the catalog detour is gone. Everything else from the original gating stays: the centralized hook, the RequireAiSurface /ai route guard, the gated top-bar link + designer "Ask AI" buttons, and AiChatPage's graceful empty state. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
os-zhuang
added a commit
that referenced
this pull request
Jun 25, 2026
…ability) (#2317) * chore: bump objectui to 8a3b351a5a32 fix(console): gate the AI surface on the service-ai capability, not the agent catalog (#1992) objectui@8a3b351a5a320e6769a1616e85a6fd05aabd3279 * chore(showcase): remove the AI agent — service-ai is an enterprise capability The showcase defined a `showcase_assistant` agent + a skill + two tools, all of which need the enterprise `@objectstack/service-ai` runtime to be served. The open-source showcase shouldn't require an enterprise capability, so drop the AI block entirely: - delete `src/agents/index.ts` (agent + skill + tools) and its config wiring (`agents` / `skills` / `tools`); - remove the `@objectstack/service-ai` dependency (added in #2311 to back the agent — no longer needed); - drop the descriptive `ai` entry from the coverage map and update the seed test (`agents.length` 1 → 0). The showcase now boots as a Community-Edition shape: no AI service is registered, discovery reports `services.ai` unavailable, and `/api/v1/ai/agents` 404s — so the console hides its AI surface. `tsc --noEmit` + all 39 showcase tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
os-zhuang
added a commit
that referenced
this pull request
Jun 25, 2026
…ity (#2319) Mirror the showcase change (#2317): the open-source CRM example shouldn't define an AI agent that requires the enterprise @objectstack/service-ai runtime. - delete src/agents/ (SalesAssistantAgent + DealManagementSkill + LookupContactTool) and its config wiring (agents / skills) plus the unused referenceMetadata export; - remove the @objectstack/service-ai dependency (added in #2311 to back the agent). crm now boots as a Community-Edition shape: no AI service registered, discovery reports services.ai unavailable, /api/v1/ai/agents 404. tsc --noEmit + all 29 crm tests pass. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
os-zhuang
added a commit
that referenced
this pull request
Jul 6, 2026
fix(components): also toast form submit errors so they're visible past the fold (#2311) objectui@ffad2a13790c589de88323b932617a2cba93129c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A self-host Community Edition runtime (framework + the MIT console, without the cloud AI package) should serve no AI but still support MCP. Today it can't: the CLI auto-registers the headless
AIServicePluginwhenever theaitier is enabled (default) and@objectstack/service-aiis merely resolvable. In a workspace/monorepo the package is hoist-resolvable even when an app doesn't declare it, so every app gets the AI service — discovery reportsservices.ai: availableand the agent runtime serves any metadata-defined agents — even CE apps that ship no AI.(Surfaced from the objectui side: the console gates its AI UI on the live agent catalog, but a CE runtime still reported
services.aiavailable with agents served, so the AI surface didn't hide.)What
1. AI is opt-in via a declared dependency (
packages/cli/src/commands/serve.ts). Auto-register the AI service only when the host app declares@objectstack/service-aior@objectstack/service-ai-studio— gating on a declared dep, not mere resolvability, so it's reliable in a monorepo.services.ai: { enabled:false, status:'unavailable' }→ the console hides its AI surface.requires: ['mcp']), noservice-aidependency, bridges data/metadata regardless; only optionally bridges the AI tool registry when theaiservice is present.ai:readyhook, so declaring Studio now implies (and loads) the base service. Previously a Studio-only app would have loaded neither.app-showcase/app-crmnow declare@objectstack/service-ai(they ship AI agents).For real standalone apps (outside this monorepo) this is a no-op — they already had to declare deps to resolve them. Only in-monorepo apps relying on hoisting were affected (the two examples, now fixed).
2.
config.tiersis now honored (packages/spec/src/stack.zod.ts).ObjectStackDefinitionSchemagains atiersfield, sodefineStackno longer strips it.config.tiers(e.g. a list withoutai) now actually overrides the--presetdefault — previously silently dropped by schema validation, which made the--presethelp text ("overridden by config.tiers if set") inaccurate. A second, in-place way to disable AI without touching dependencies.Verified end-to-end (isolated build, fresh runtime)
services.ai/api/v1/ai/agentsenabled:false, "unavailable"404OS_MCP_SERVER_ENABLED=true→401auth-gate = live)service-aienabled:true, "available"showcase_assistantservice-ai-studioenabled:true, "available"200ai:ready)config.tierswithoutai(service-ai declared)enabled:false, "unavailable"404@objectstack/cli+@objectstack/specbuild clean (tsc). Changeset included (bothminor).🤖 Generated with Claude Code