Add IBackendsTransport interface for provider packages#526
Conversation
@workglow/cli
@workglow/ai
@workglow/browser-control
@workglow/indexeddb
@workglow/javascript
@workglow/job-queue
@workglow/knowledge-base
@workglow/mcp
@workglow/storage
@workglow/task-graph
@workglow/tasks
@workglow/util
workglow
@workglow/anthropic
@workglow/bun-webview
@workglow/cactus
@workglow/chrome-ai
@workglow/electron
@workglow/google-gemini
@workglow/huggingface-inference
@workglow/huggingface-transformers
@workglow/llamacpp-server
@workglow/mlx
@workglow/node-llama-cpp
@workglow/ollama
@workglow/openai
@workglow/playwright
@workglow/postgres
@workglow/sqlite
@workglow/stable-diffusion-server
@workglow/supabase
@workglow/tf-mediapipe
commit: |
…s, tighten JSDoc (PR #526 follow-up) (#527) * feat(ai): finalize IBackendsTransport — add list/uninstall, widen opts, tighten JSDoc Adds list() and uninstall(backend) to IBackendsTransport so the libs interface matches what builder's MessagePortBackendsTransport already implements and the renderer UI requires. Widens IEnsureRunningRequest.opts from { ctx: number } to Readonly<Record<string, unknown>> so non-llamacpp backends (sd-cpp, future MLX/whisper) don't have to lie with ctx: 0. Updates StableDiffusionCppProvider to pass opts: {} accordingly. Tightens JSDoc on release() (resolves on post, not broker-ack) and subscribeStatus() (idempotent unsubscribe, dedup of double-subscribe). * docs(IBackendsTransport): clarify opts JSDoc for sd-cpp * test(IBackendsTransport): move type test under packages/test for CI discovery The repo's test runner (scripts/test.ts) only collects Vitest files from packages/test/src/test, so this file was never executed in CI. Removing the old location; the file is recreated under packages/test/src/test/ai in the following commit (also strengthens the structural conformance assertion with explicit parameter signatures). * test(IBackendsTransport): strengthen conformance with explicit signatures Recreates the type-conformance test at packages/test/src/test/ai/ (the location scripts/test.ts discovers) and replaces the zero-arg dummy implementations with explicit parameter signatures drawn from the interface. TypeScript happily assigns `() => X` to `(arg) => X`, so the previous form did not catch parameter-list drift; the new form fails typecheck on any rename, type change, or return-type change to a method of `IBackendsTransport`. Imports come from `@workglow/ai/provider-utils` (the public subpath export) instead of the previous relative path into packages/ai/src.
Coverage Report
File CoverageNo changed files found. |
There was a problem hiding this comment.
Pull request overview
Introduces a renderer-side IBackendsTransport abstraction in @workglow/ai/provider-utils so provider packages can acquire/install local backends without depending on any desktop/builder/Electron implementation details. The PR also adds three new provider packages (llamacpp-server, stable-diffusion-cpp, and an mlx stub) that consume this transport interface.
Changes:
- Added
IBackendsTransport(+ related request/handle/status types) and exported it via@workglow/ai/provider-utils. - Added compile-time conformance tests for the
IBackendsTransportsurface. - Added new provider packages for local backends (llama-server, stable-diffusion.cpp HTTP) and an MLX stub, plus workspace lockfile updates.
Reviewed changes
Copilot reviewed 30 out of 31 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| providers/stable-diffusion-cpp/tsconfig.json | New TS project config for the stable-diffusion.cpp provider package. |
| providers/stable-diffusion-cpp/src/ai/StableDiffusionCppProvider.ts | Implements a text-to-image provider that uses IBackendsTransport.ensureRunning() or an external URL. |
| providers/stable-diffusion-cpp/src/ai/runtime.ts | Runtime entry re-export for registration. |
| providers/stable-diffusion-cpp/src/ai/registerStableDiffusionCpp.ts | Provider registration helper (injects transport/external URL). |
| providers/stable-diffusion-cpp/src/ai/index.ts | Public AI entry exports for the provider. |
| providers/stable-diffusion-cpp/src/ai/common/StableDiffusionCpp_Constants.ts | Defines the provider name constant. |
| providers/stable-diffusion-cpp/src/ai.ts | Package ./ai entrypoint barrel. |
| providers/stable-diffusion-cpp/src/ai-runtime.ts | Package ./ai-runtime entrypoint barrel. |
| providers/stable-diffusion-cpp/package.json | New provider package manifest/exports/scripts. |
| providers/mlx/tsconfig.json | New TS project config for the MLX provider stub package. |
| providers/mlx/src/ai/runtime.ts | Runtime entry re-export for registration. |
| providers/mlx/src/ai/registerMlx.ts | Provider registration helper for the stub provider. |
| providers/mlx/src/ai/MlxProvider.ts | Stub provider that registers but throws on inference (v1 limitation). |
| providers/mlx/src/ai/index.ts | Public AI entry exports for the provider. |
| providers/mlx/src/ai/common/Mlx_Constants.ts | Defines the provider name constant. |
| providers/mlx/src/ai.ts | Package ./ai entrypoint barrel. |
| providers/mlx/src/ai-runtime.ts | Package ./ai-runtime entrypoint barrel. |
| providers/mlx/package.json | New provider package manifest/exports/scripts. |
| providers/llamacpp-server/tsconfig.json | New TS project config for the llama-server provider package. |
| providers/llamacpp-server/src/ai/runtime.ts | Runtime entry re-export for registration. |
| providers/llamacpp-server/src/ai/registerLlamaCppServer.ts | Provider registration helper (injects transport/external URL). |
| providers/llamacpp-server/src/ai/LlamaCppServerProvider.ts | OpenAI-compatible streaming chat-completions client for llama-server using IBackendsTransport. |
| providers/llamacpp-server/src/ai/index.ts | Public AI entry exports for the provider. |
| providers/llamacpp-server/src/ai/common/LlamaCppServer_Constants.ts | Defines the provider name constant. |
| providers/llamacpp-server/src/ai.ts | Package ./ai entrypoint barrel. |
| providers/llamacpp-server/src/ai-runtime.ts | Package ./ai-runtime entrypoint barrel. |
| providers/llamacpp-server/package.json | New provider package manifest/exports/scripts. |
| packages/test/src/test/ai/IBackendsTransport.types.test.ts | Adds compile-time conformance checks for IBackendsTransport. |
| packages/ai/src/provider-utils/IBackendsTransport.ts | Defines the new transport interface/types for provider packages. |
| packages/ai/src/provider-utils.ts | Re-exports IBackendsTransport from the provider-utils entrypoint. |
| bun.lock | Adds the new provider workspaces and adjusts trustedDependencies ordering. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "png" | ||
| ); | ||
|
|
||
| emit({ type: "finish", data: { image } }); |
| for (const line of lines) { | ||
| const trimmed = line.trim(); | ||
| if (!trimmed.startsWith("data:")) continue; | ||
| const data = trimmed.slice(5).trim(); | ||
| if (data === "[DONE]") break; | ||
| if (!data) continue; |
| * Mirrors `IBackendStatus` from `packages/electron/src/backends-util/types.ts` | ||
| * without importing from the builder package. |
| * The concrete implementation (`MessagePortBackendsTransport`, in builder) uses | ||
| * `window.desktop.backends.openChannel()` to obtain a `MessagePort` and speaks | ||
| * the protocol defined in `packages/electron/src/backends-util/protocol.ts`. |
| export * from "./provider-utils/BaseCloudProvider"; | ||
| export * from "./provider-utils/CloudProviderClient"; | ||
| export * from "./provider-utils/OpenAIShapedChat"; | ||
| export * from "./provider-utils/IBackendsTransport"; |
| "peerDependencies": { | ||
| "@workglow/ai": "workspace:*", | ||
| "@workglow/util": "workspace:*" | ||
| }, | ||
| "peerDependenciesMeta": { | ||
| "@workglow/ai": { | ||
| "optional": false | ||
| }, | ||
| "@workglow/util": { | ||
| "optional": false | ||
| } | ||
| }, |
| "peerDependencies": { | ||
| "@workglow/ai": "workspace:*", | ||
| "@workglow/util": "workspace:*" | ||
| }, | ||
| "peerDependenciesMeta": { | ||
| "@workglow/ai": { | ||
| "optional": false | ||
| }, | ||
| "@workglow/util": { | ||
| "optional": false | ||
| } | ||
| }, |
| "@workglow/ai": "workspace:*", | ||
| "@workglow/util": "workspace:*" | ||
| }, | ||
| "peerDependenciesMeta": { | ||
| "@workglow/ai": { | ||
| "optional": false | ||
| }, | ||
| "@workglow/util": { | ||
| "optional": false | ||
| } | ||
| }, | ||
| "devDependencies": { | ||
| "@workglow/ai": "workspace:*", |
…s, tighten JSDoc (PR #526 follow-up) (#527) * feat(ai): finalize IBackendsTransport — add list/uninstall, widen opts, tighten JSDoc Adds list() and uninstall(backend) to IBackendsTransport so the libs interface matches what builder's MessagePortBackendsTransport already implements and the renderer UI requires. Widens IEnsureRunningRequest.opts from { ctx: number } to Readonly<Record<string, unknown>> so non-llamacpp backends (sd-cpp, future MLX/whisper) don't have to lie with ctx: 0. Updates StableDiffusionCppProvider to pass opts: {} accordingly. Tightens JSDoc on release() (resolves on post, not broker-ack) and subscribeStatus() (idempotent unsubscribe, dedup of double-subscribe). * docs(IBackendsTransport): clarify opts JSDoc for sd-cpp * test(IBackendsTransport): move type test under packages/test for CI discovery The repo's test runner (scripts/test.ts) only collects Vitest files from packages/test/src/test, so this file was never executed in CI. Removing the old location; the file is recreated under packages/test/src/test/ai in the following commit (also strengthens the structural conformance assertion with explicit parameter signatures). * test(IBackendsTransport): strengthen conformance with explicit signatures Recreates the type-conformance test at packages/test/src/test/ai/ (the location scripts/test.ts discovers) and replaces the zero-arg dummy implementations with explicit parameter signatures drawn from the interface. TypeScript happily assigns `() => X` to `(arg) => X`, so the previous form did not catch parameter-list drift; the new form fails typecheck on any rename, type change, or return-type change to a method of `IBackendsTransport`. Imports come from `@workglow/ai/provider-utils` (the public subpath export) instead of the previous relative path into packages/ai/src.
54cbafd to
60723b7
Compare
Review notes (process, not blocking)Thanks for the work here! Two process-level suggestions before merge — both about keeping the historical record clean, not about the code itself. H1 — Unrelated deletion of
|
…sports Adds a renderer-side abstraction at packages/ai/src/transport/IBackendsTransport.ts that provider packages (in libs) consume to talk to electron's backends-util utility process without importing electron. The concrete MessagePort-based implementation lives in builder; this is the public surface. Exposed via the @workglow/ai/backends-transport subpath export. Used by the upcoming llamacpp-server and stable-diffusion-cpp provider packages.
… (v1 chat-completion) Adds the minimum-viable `libs/providers/llamacpp-server` package that POSTs to an OpenAI-compatible `/v1/chat/completions` endpoint. Acquires a backend URL via `IBackendsTransport.ensureRunning` (with proper `release()` in finally) or bypasses transport when `externalUrl` is set. Exports `registerLlamaCppServer` from both `./ai` and `./ai-runtime` subpaths. https://claude.ai/code/session_01Avr2i3ryqAUJUFRRZZ3Mf3
The previous \`./backends-transport\` subpath export had only a
\`types\` field pointing at a raw \`.ts\` source file and no \`import\`
field, which is non-idiomatic and likely the cause of the
\`test-vitest-ai-provider-api\` job failing on this PR (the bad
export disrupts the @workglow/ai package build/types pipeline that
the api-provider tests indirectly depend on).
Moving the interface alongside the other shared provider helpers
(\`packages/ai/src/provider-utils/IBackendsTransport.ts\`) lets it
ride the existing barrel: consumers now \`import type { ... } from
\"@workglow/ai/provider-utils\"\` just like every other vendor
package, and the bespoke subpath export is gone.
The three downstream providers (\`@workglow/llamacpp-server\`,
\`@workglow/stable-diffusion-cpp\`, \`@workglow/mlx\`) are updated to
the new import path.
https://claude.ai/code/session_01Avr2i3ryqAUJUFRRZZ3Mf3
LlamaCppServerProvider and StableDiffusionCppProvider stored
\`options.transport\` and \`options.externalUrl\` on the instance via
\`#transport\` / \`#externalUrl\` but never read them — the run-fn
closures capture them directly from \`options\`. With strict
\`noUnusedLocals\` these unused private fields broke
\`bun run build\` in libs CI (build-types step).
Also typed the local \`handle\` variable as \`IRunningHandle\` instead
of the partial \`{ release }\` shape — the run-fn reads \`handle.url\`,
which is part of \`IRunningHandle\`.
\`bun run build\` now succeeds for all 71 turbo tasks locally.
https://claude.ai/code/session_01Avr2i3ryqAUJUFRRZZ3Mf3
…s, tighten JSDoc (PR #526 follow-up) (#527) * feat(ai): finalize IBackendsTransport — add list/uninstall, widen opts, tighten JSDoc Adds list() and uninstall(backend) to IBackendsTransport so the libs interface matches what builder's MessagePortBackendsTransport already implements and the renderer UI requires. Widens IEnsureRunningRequest.opts from { ctx: number } to Readonly<Record<string, unknown>> so non-llamacpp backends (sd-cpp, future MLX/whisper) don't have to lie with ctx: 0. Updates StableDiffusionCppProvider to pass opts: {} accordingly. Tightens JSDoc on release() (resolves on post, not broker-ack) and subscribeStatus() (idempotent unsubscribe, dedup of double-subscribe). * docs(IBackendsTransport): clarify opts JSDoc for sd-cpp * test(IBackendsTransport): move type test under packages/test for CI discovery The repo's test runner (scripts/test.ts) only collects Vitest files from packages/test/src/test, so this file was never executed in CI. Removing the old location; the file is recreated under packages/test/src/test/ai in the following commit (also strengthens the structural conformance assertion with explicit parameter signatures). * test(IBackendsTransport): strengthen conformance with explicit signatures Recreates the type-conformance test at packages/test/src/test/ai/ (the location scripts/test.ts discovers) and replaces the zero-arg dummy implementations with explicit parameter signatures drawn from the interface. TypeScript happily assigns `() => X` to `(arg) => X`, so the previous form did not catch parameter-list drift; the new form fails typecheck on any rename, type change, or return-type change to a method of `IBackendsTransport`. Imports come from `@workglow/ai/provider-utils` (the public subpath export) instead of the previous relative path into packages/ai/src.
Agent-Logs-Url: https://github.com/workglow-dev/libs/sessions/dcbb8be4-0aa3-4632-9caf-7120a026d8c2 Co-authored-by: sroussey <127349+sroussey@users.noreply.github.com>
Introduces the `@workglow/stable-diffusion-server` package, which serves as a local HTTP client for stable-diffusion.cpp servers. This package includes the `StableDiffusionCppProvider` for image generation tasks and provides registration functionality through `registerStableDiffusionCpp`. Additionally, updates to the `bun.lock` and `package.json` files reflect the new dependencies and workspace configurations for the added provider. - Added `StableDiffusionCppProvider` for handling image generation requests. - Implemented `registerStableDiffusionCpp` for provider registration. - Updated `bun.lock` and `package.json` to include new dependencies and workspace references.
2cc8663 to
231f21f
Compare
…uery filter Also fix description text so it does not pollute case-insensitive query filtering (every loaded model previously matched 'llama' because the static description was 'llama-server loaded model').
…, browser/worker constraints
…path + ModelUtil helpers
…e64 PNG round-trip)
… [] in transport mode)
…rovider (main-thread) shells
…sport + externalUrl)
…pp using QueuedProvider proxy
…to new register API + model_path schema
… request shape + errors
…h externalUrl/query
…ty table, browser note
| } | ||
|
|
||
| function stripTrailingSlash(url: string): string { | ||
| return url.replace(/\/+$/, ""); |
| try { | ||
| const { baseUrl, release } = await acquire(model, opts); | ||
| try { | ||
| const res = await fetch(`${baseUrl}/props`, { signal }); |
| try { | ||
| const { baseUrl, release } = await acquire(model, opts); | ||
| try { | ||
| const res = await fetch(`${baseUrl}/v1/models`, { signal }); |
| emit({ type: "finish", data: { results: [] } }); | ||
| return; | ||
| } | ||
| const baseUrl = opts.externalUrl.replace(/\/+$/, ""); |
| } | ||
| const baseUrl = opts.externalUrl.replace(/\/+$/, ""); | ||
| try { | ||
| const res = await fetch(`${baseUrl}/v1/models`, { signal }); |
| const response = await fetch(`${baseUrl}/v1/chat/completions`, { | ||
| method: "POST", | ||
| headers: { "Content-Type": "application/json" }, | ||
| body, | ||
| signal, | ||
| }); |
| } | ||
|
|
||
| function stripTrailingSlash(url: string): string { | ||
| return url.replace(/\/+$/, ""); |
| const response = await fetch(`${baseUrl}${endpoint}`, { | ||
| method: "POST", | ||
| headers: { "Content-Type": "application/json" }, | ||
| body, | ||
| signal, | ||
| }); |
| emit({ type: "finish", data: { results: [] } }); | ||
| return; | ||
| } | ||
| const baseUrl = opts.externalUrl.replace(/\/+$/, ""); |
| } | ||
| const baseUrl = opts.externalUrl.replace(/\/+$/, ""); | ||
| try { | ||
| const res = await fetch(`${baseUrl}/v1/models`, { signal }); |
Summary
Introduces
IBackendsTransport, a renderer-side abstraction interface for the backends broker that provider packages can consume without importing Electron or builder dependencies. This enables a clean separation of concerns where provider packages depend only on the abstract interface, while the concrete implementation lives in the builder package.Changes
New file:
packages/ai/src/transport/IBackendsTransport.tsIEnsureRunningRequest— request payload for acquiring a running backendIRunningHandle— handle returned byensureRunning()with refcount-based lifecycleIBackendStatus— status snapshot mirroring the electron-side typeIBackendsTransport— main interface with three methods:ensureRunning()— acquire or share a running backend processsubscribeStatus()— subscribe to backend status updates with unsubscribe callbackinstall()— install a backend with optional progress reportingUpdated:
packages/ai/package.json"./backends-transport"export path pointing to the new interface fileImplementation Details
stringfor backend identifiers (not a closed union) so provider packages don't need to know the full set of backend names; the transport implementation in builder coerces toBackendNameIRunningHandle.release()is fire-and-forget to avoid blocking on broker acksreadonlyproperties,Iprefix for public interfaces, no Electron imports in the interface definitionhttps://claude.ai/code/session_01Avr2i3ryqAUJUFRRZZ3Mf3