Skip to content

feat: add serving type generator, Vite plugin, and UI hooks#240

Merged
pkosiec merged 10 commits intomainfrom
pkosiec/serving-2-types-hooks
Apr 10, 2026
Merged

feat: add serving type generator, Vite plugin, and UI hooks#240
pkosiec merged 10 commits intomainfrom
pkosiec/serving-2-types-hooks

Conversation

@pkosiec
Copy link
Copy Markdown
Member

@pkosiec pkosiec commented Apr 3, 2026

Summary

  • Add Vite plugin that auto-generates TypeScript types from serving endpoint OpenAPI schemas
  • Add AST-based server file extraction (@ast-grep/napi) for automatic endpoint discovery
  • Add schema-to-TypeScript conversion with OpenAI-compatible streaming chunk inference
  • Add useServingInvoke and useServingStream React hooks with type-safe registry support

Demo

model-serving-demo-compressed.mp4

PR Stack — Model Serving

# PR Description
1 #239 Serving connector & plugin
2 this PR Type generator, Vite plugin & UI hooks
3 #241 Dev-playground, template & docs

@pkosiec pkosiec force-pushed the pkosiec/serving-1-core branch from 83dab4c to 76a2618 Compare April 3, 2026 10:04
@pkosiec pkosiec force-pushed the pkosiec/serving-2-types-hooks branch from 735aa72 to 9b7bcc1 Compare April 3, 2026 10:06
@pkosiec pkosiec force-pushed the pkosiec/serving-1-core branch from 76a2618 to 41a0074 Compare April 3, 2026 10:14
@pkosiec pkosiec force-pushed the pkosiec/serving-2-types-hooks branch 2 times, most recently from 2657962 to 8687067 Compare April 3, 2026 12:25
@pkosiec pkosiec force-pushed the pkosiec/serving-1-core branch from 218f9b5 to cab05df Compare April 9, 2026 14:14
@pkosiec pkosiec force-pushed the pkosiec/serving-2-types-hooks branch 2 times, most recently from a8ebf5e to cccf049 Compare April 9, 2026 14:46
@pkosiec pkosiec force-pushed the pkosiec/serving-1-core branch from 2080612 to 1996ad6 Compare April 9, 2026 17:40
@pkosiec pkosiec force-pushed the pkosiec/serving-2-types-hooks branch 2 times, most recently from ac0a669 to 10204a8 Compare April 10, 2026 08:13
@pkosiec pkosiec force-pushed the pkosiec/serving-1-core branch from 22df022 to ac93525 Compare April 10, 2026 08:22
@pkosiec pkosiec force-pushed the pkosiec/serving-2-types-hooks branch from 10204a8 to 6c85231 Compare April 10, 2026 08:22
@pkosiec pkosiec force-pushed the pkosiec/serving-1-core branch from ac93525 to 99bbfad Compare April 10, 2026 08:25
@pkosiec pkosiec force-pushed the pkosiec/serving-2-types-hooks branch from 6c85231 to e1068f6 Compare April 10, 2026 08:25
Base automatically changed from pkosiec/serving-1-core to main April 10, 2026 13:23
pkosiec added 7 commits April 10, 2026 15:25
Add Vite plugin that auto-generates TypeScript types from serving
endpoint OpenAPI schemas. Includes AST-based server file extraction
(@ast-grep/napi), schema-to-TypeScript conversion, and caching.
Also adds useServingInvoke and useServingStream React hooks in
appkit-ui with full type-safe registry support.

Signed-off-by: Pawel Kosiec <pawel.kosiec@databricks.com>
- Store requestKeys[] in serving cache instead of regex-parsing
  TypeScript type strings in schema-filter (fragile indentation dependency)
- Add overrideBody parameter to useServingStream's stream() to allow
  callers to pass fresh body without waiting for useMemo recomputation
- Lazy-init WorkspaceClient in type generator (skip when no endpoints resolve)

Signed-off-by: Pawel Kosiec <pawel.kosiec@databricks.com>
Chunks persisted after onComplete, causing the streaming bubble to
remain visible alongside the committed message (duplicate response).
Now chunks are cleared atomically with setStreaming(false) so React
batches all state updates in one render.

Signed-off-by: Pawel Kosiec <pawel.kosiec@databricks.com>
Clearing chunks in the hook's .then() handler caused a race with React
batching — chunks were empty before the component could commit them.
Let consumers decide when to clear via reset() instead.

Signed-off-by: Pawel Kosiec <pawel.kosiec@databricks.com>
Without a .catch(), if connectSSE rejects the promise is unhandled and
setStreaming(false) never fires, leaving the hook in a broken state.
This matches the pattern used by the genie chat hook.

Signed-off-by: Pawel Kosiec <pawel.kosiec@databricks.com>
The invoke callback is recreated whenever body changes (via useCallback
deps), which triggers the useEffect cleanup that aborts in-flight
requests. Adding overrideBody allows callers to use a stable body while
passing the real payload per-invocation, matching useServingStream.

Signed-off-by: Pawel Kosiec <pawel.kosiec@databricks.com>
…T_NAME in type generator

Signed-off-by: Pawel Kosiec <pawel.kosiec@databricks.com>
@pkosiec pkosiec force-pushed the pkosiec/serving-2-types-hooks branch from e1068f6 to c428977 Compare April 10, 2026 13:26
@MarioCadenas
Copy link
Copy Markdown
Collaborator

also almost forgot, this should be hooked into the packages/shared/src/cli/commands/generate-types.ts command too

- Add appKitServingTypesPlugin to vite-dev-server (auto-included)
- Use SDK getOpenApi method instead of manual fetch in fetcher
- Extract helpers from generateServingTypes for readability
- Add clientConfig to ServingPlugin, use in hooks for URL construction
- Export type-generator/serving entry point for CLI generate-types
- Hook serving type generation into generate-types CLI command

Signed-off-by: Pawel Kosiec <pawel.kosiec@databricks.com>
- Replace manual getPluginClientConfig + useMemo with usePluginClientConfig hook
- Move generateServingTypes to explicit import + export in type-generator index
- Remove unnecessary typeof guard in generate-types CLI command
- Update test mocks to mock use-plugin-config instead of @/js

Signed-off-by: Pawel Kosiec <pawel.kosiec@databricks.com>
Copy link
Copy Markdown
Collaborator

@MarioCadenas MarioCadenas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

once the artifact ci is fixed it LGTM, as a followup, I would add a system that allows us to write all the types in client/src/appKitTypes.d.ts or another cleaner approach, I would like to avoid populating with multiple d.ts files. Maybe to make it look cleaner and not having to have a full lock mechanism we could simply change the appKitTypes.d.ts to a file that simply references others in a folder, and the folder contains one file per plugin that needs it? something like this

appKitTypes.d.ts
|- appkit-types
   |- analytics.d.ts
   |- serving.d.ts

having appKitTypes.d.ts as something like this

/// <reference path="./appkit-types/analytics.d.ts" />
/// <reference path="./appkit-types/serving.d.ts" />

but just an idea!

Rolldown tree-shaking only preserves "own exports" (locally defined)
— not re-exports. Use a local binding instead of a re-export so the
serving vite plugin's import keeps it in the dependency graph.

Also remove gitignore comment for type generator caches.

Signed-off-by: Pawel Kosiec <pawel.kosiec@databricks.com>
@pkosiec pkosiec force-pushed the pkosiec/serving-2-types-hooks branch from 2dbaf25 to 09ec8f3 Compare April 10, 2026 15:37
@pkosiec pkosiec merged commit c4285af into main Apr 10, 2026
7 checks passed
@pkosiec pkosiec deleted the pkosiec/serving-2-types-hooks branch April 10, 2026 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants