Skip to content

Commit 4cc6068

Browse files
authored
Merge branch 'main' into copilot/update-ai-chat-api-protocol
2 parents aff2159 + b25943b commit 4cc6068

26 files changed

Lines changed: 1093 additions & 29 deletions

CHANGELOG.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
- **Discovery Schema — `ServiceStatus` enum & `handlerReady` field** — Added `'registered'`
12+
status to `ServiceInfoSchema` to distinguish routes that are declared in the dispatcher
13+
table but whose HTTP handler has not been verified. Added optional `handlerReady` boolean
14+
field (omitted = unverified/unknown) so clients can filter handler-ready services before
15+
displaying endpoints when the value is explicitly `true`.
16+
- **Discovery Schema — `RouteHealthReportSchema`** — New schema for automated route/handler
17+
coverage reporting at startup. Includes per-route health entries (`pass`, `fail`, `missing`,
18+
`skip`) and summary counters.
19+
- **Dispatcher Schema — `DispatcherErrorCode` & `DispatcherErrorResponseSchema`** — Semantic
20+
error codes (`404`/`405`/`501`/`503`) with machine-readable `type` field
21+
(`ROUTE_NOT_FOUND`, `METHOD_NOT_ALLOWED`, `NOT_IMPLEMENTED`, `SERVICE_UNAVAILABLE`) and
22+
developer-facing `hint` strings.
23+
- **Dispatcher Schema — `/health` route** — Added health endpoint to `DEFAULT_DISPATCHER_ROUTES`.
24+
- **REST API Plugin — `handlerStatus` field** — Added `handlerStatus` (`implemented`, `stub`,
25+
`planned`) to `RestApiEndpointSchema` to track handler implementation readiness.
26+
- **REST API Plugin — `RouteCoverageReportSchema`** — Schema for adapter-generated coverage
27+
reports listing every declared endpoint and its implementation status.
28+
- `ai` v6 as a dependency of `@objectstack/spec` for type re-exports
29+
30+
### Removed
31+
- **Removed `value` field from data API responses** — The `findData` protocol
32+
implementation no longer returns the deprecated `value` field alongside `records`.
33+
Only `records` is returned, matching the `FindDataResponseSchema` spec. All
34+
downstream consumers (Studio, app-host example, tests) updated to use `records`
35+
exclusively. OData-specific responses (`ODataResponseSchema`) retain `value` per
36+
the OData v4 standard — protocol-to-OData adaptation is handled in the HTTP
37+
dispatch layer.
38+
1039
### Changed
1140
- **AI Chat Protocol Aligned with Vercel AI SDK** — Removed custom AI chat protocol
1241
types and Zod schemas (`AIMessage`, `AIToolCall`, `AIStreamEvent`,
@@ -32,6 +61,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3261
- Conversation services serialize/deserialize `ModelMessage` union to flat DB columns
3362
- All 158 service-ai tests updated and passing
3463

64+
### Fixed
65+
- **Runtime Dispatcher — semantic error differentiation**`HttpDispatcher.dispatch()` now
66+
returns typed 404 (`ROUTE_NOT_FOUND`) with diagnostic info instead of bare `{ handled: false }`.
67+
Added `routeNotFound()` (404) helper method.
68+
- **Runtime Dispatcher — `/health` handler** — Added health endpoint returning `status`,
69+
`timestamp`, `version`, and `uptime`.
70+
- **Runtime Dispatcher — `handlerReady` in discovery**`getDiscoveryInfo()` now emits
71+
`handlerReady: true` for services with confirmed handlers and `handlerReady: false` for
72+
unavailable services.
73+
- **Dispatcher Plugin — semantic 404**`sendResult()` now returns `ROUTE_NOT_FOUND` error
74+
type with a hint pointing to the discovery endpoint. Added `/health` handler registration.
75+
- **Studio — handler-ready filtering**`useApiDiscovery()` now checks both `enabled` and
76+
`handlerReady` (or `status === 'available' | 'degraded'` for backward compatibility) before
77+
displaying service endpoints in the UI.
78+
3579
### Removed
3680
- `AiChatRequestSchema` / `AiChatResponseSchema` Zod schemas from
3781
`@objectstack/spec/api` — the AI chat wire protocol now uses Vercel AI SDK's

apps/studio/CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
# @objectstack/studio
22

3+
## Unreleased
4+
5+
### Minor Changes
6+
7+
- Add collapsible right-side AI Chat floating panel (VS Code Copilot Chat style).
8+
9+
- New `AiChatPanel` component: fixed right-side panel with 48px collapsed edge
10+
button and 380px expanded view. Supports stream chat via Vercel AI SDK
11+
`useChat` hook connected to `/api/v1/ai/chat`.
12+
- New `use-ai-chat-panel` hook: manages panel visibility toggle, keyboard
13+
shortcut (`Ctrl+Shift+I` / `Cmd+Shift+I`), and message history persistence
14+
to localStorage.
15+
- Added `ai` and `@ai-sdk/react` dependencies for Vercel Data Stream Protocol
16+
integration.
17+
318
## 4.0.0
419

520
### Patch Changes
@@ -48,6 +63,15 @@
4863

4964
### Fixes
5065

66+
- **Vercel deployment: Fix `functions` pattern validation error**
67+
- The `functions` key in `vercel.json` referenced `api/index.js` — a build artifact created by
68+
`bundle-api.mjs` — which does not exist in the source tree. Vercel CLI validates patterns against
69+
source files before the build runs, producing the error:
70+
`The pattern "api/index.js" defined in "functions" doesn't match any Serverless Functions`.
71+
- Removed `functions` from `vercel.json` and moved the memory/maxDuration settings to an inline
72+
`export const config` in `server/index.ts`. This is the standard Vercel per-function configuration
73+
mechanism and is bundled into `api/index.js` by esbuild.
74+
5175
- **Vercel deployment: Fix `@vercel/node@3` runtime error**
5276
- Removed the `functions.runtime` config from `vercel.json` — the `runtime` field is only for custom/community runtimes, not Node.js. Vercel auto-detects the pre-bundled `api/index.js` as a Node.js serverless function.
5377

apps/studio/ROADMAP.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
| # | Task | Details |
5959
|---|------|---------|
6060
| 0.1 | **Add URL Router** | Integrate TanStack Router or React Router. Map views to URL paths: `/:package/objects/:name`, `/:package/metadata/:type/:name`, `/packages`, `/settings`. Enable browser back/forward and deep linking. |
61-
| 0.2 | **Centralize response normalization** | Create `src/lib/api-utils.ts` with `normalizeRecords()`, `normalizeMetadata()`. Remove inline `.records || .value || .data` from all components. |
61+
| 0.2 | **~~Centralize response normalization~~** | ✅ Done — `value` field removed from protocol implementation. All components now use `records` directly (spec-compliant). |
6262
| 0.3 | **Wire plugin sidebar groups** | Replace hardcoded `PROTOCOL_GROUPS` in `app-sidebar.tsx` with plugin-contributed `useSidebarGroups()`. |
6363
| 0.4 | **Clean dead code** | Remove stale `types.ts`, empty `app/dashboard/` directory. |
6464
| 0.5 | **Add React Testing Library** | Set up component test infrastructure. Write baseline tests for `ObjectDataTable`, `ObjectDataForm`, `AppSidebar`, Plugin system. Target: 50% component coverage. |

apps/studio/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"preview": "vite preview"
1818
},
1919
"dependencies": {
20+
"@ai-sdk/react": "^3.0.144",
2021
"@hono/node-server": "^1.19.11",
2122
"@objectstack/client": "workspace:*",
2223
"@objectstack/client-react": "workspace:*",
@@ -47,6 +48,7 @@
4748
"@radix-ui/react-tabs": "^1.1.13",
4849
"@radix-ui/react-toast": "^1.2.15",
4950
"@radix-ui/react-tooltip": "^1.2.8",
51+
"ai": "^6.0.142",
5052
"class-variance-authority": "^0.7.1",
5153
"clsx": "^2.1.1",
5254
"hono": "^4.12.9",

apps/studio/scripts/bundle-api.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ await build({
3737
platform: 'node',
3838
format: 'esm',
3939
target: 'es2020',
40-
outfile: 'api/index.js',
40+
outfile: 'dist/api/index.js',
4141
sourcemap: true,
4242
external: EXTERNAL,
4343
// Silence warnings about optional/unused require() calls in knex drivers
4444
logOverride: { 'require-resolve-not-external': 'silent' },
4545
});
4646

47-
console.log('[bundle-api] Bundled server/index.ts → api/index.js');
47+
console.log('[bundle-api] Bundled server/index.ts → dist/api/index.js');

apps/studio/server/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,3 +235,15 @@ app.all('*', async (c) => {
235235
});
236236

237237
export default handle(app);
238+
239+
/**
240+
* Vercel per-function configuration.
241+
*
242+
* Picked up by the @vercel/node runtime from the deployed api/index.js bundle.
243+
* Replaces the top-level "functions" key in vercel.json so there is no
244+
* pre-build file-pattern validation against a not-yet-bundled artifact.
245+
*/
246+
export const config = {
247+
memory: 1024,
248+
maxDuration: 60,
249+
};

apps/studio/src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { DeveloperOverview } from './components/DeveloperOverview';
1111
import { PackageManager } from './components/PackageManager';
1212
import { ApiConsolePage } from './components/ApiConsolePage';
1313
import { Toaster } from "@/components/ui/toaster"
14+
import { AiChatPanel } from "@/components/AiChatPanel"
1415
import { getApiBaseUrl, config } from './lib/config';
1516
import { PluginRegistryProvider, PluginHost } from './plugins';
1617
import { builtInPlugins } from './plugins/built-in';
@@ -142,6 +143,7 @@ export default function App() {
142143
</div>
143144
</main>
144145
<Toaster />
146+
<AiChatPanel />
145147
</SidebarProvider>
146148
</ErrorBoundary>
147149
</PluginRegistryProvider>

0 commit comments

Comments
 (0)