diff options
| author | Adam Malczewski <[email protected]> | 2026-06-21 12:09:09 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-21 12:09:09 +0900 |
| commit | d23de3254374d4d63c8e15c6ab9311c3c6f4da5b (patch) | |
| tree | 6105e3a8639555b2c925d412a567bcb8caa4075f /packages/host-bin/src | |
| parent | ba47df37f0c89bff4f0c3dd7d0bc2ef6c8062b92 (diff) | |
| download | dispatch-d23de3254374d4d63c8e15c6ab9311c3c6f4da5b.tar.gz dispatch-d23de3254374d4d63c8e15c6ab9311c3c6f4da5b.zip | |
feat(provider-umans): Umans AI Coding Plan provider + openai-stream lib
Extract a generic @dispatch/openai-stream library from provider-openai-compat
(convert-messages, convert-tools, parse-sse, listModels, stream, provider),
parameterizing createOpenAICompatProvider with uid=1000(tradam) gid=1000(tradam) groups=1000(tradam),966(docker),968(ollama),998(wheel) + hook.
Refactor provider-openai-compat to import from the lib (byte-identical behavior).
New @dispatch/provider-umans extension wraps the Umans OpenAI-compatible backend
(https://api.code.umans.ai/v1). Self-contained: reads UMANS_API_KEY from env
directly (no auth-apikey dep). transformBody maps reasoningEffort →
reasoning_effort (capping xhigh/max → high). Dynamic listModels via GET /v1/models.
host-bin: registered provider-umans in CORE_EXTENSIONS + umans credential
(gated on UMANS_API_KEY — the credential is the model-catalog index).
Verified: tsc EXIT 0, 1059 vitest, biome clean (293 files). Boot smoke:
umans models appear in GET /models (7 models live).
Diffstat (limited to 'packages/host-bin/src')
| -rw-r--r-- | packages/host-bin/src/main.ts | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/packages/host-bin/src/main.ts b/packages/host-bin/src/main.ts index 59ce47d..1928a8a 100644 --- a/packages/host-bin/src/main.ts +++ b/packages/host-bin/src/main.ts @@ -22,6 +22,7 @@ import { import { extension as lspExt } from "@dispatch/lsp"; import { extension as messageQueueExt } from "@dispatch/message-queue"; import { extension as providerOpenaiCompatExt } from "@dispatch/provider-openai-compat"; +import { extension as providerUmansExt } from "@dispatch/provider-umans"; import { extension as sessionOrchestratorExt } from "@dispatch/session-orchestrator"; import { extension as skillsExt } from "@dispatch/skills"; import { createSqliteStorage, extension as storageSqliteExt } from "@dispatch/storage-sqlite"; @@ -69,6 +70,7 @@ const CORE_EXTENSIONS: readonly Extension[] = [ conversationStoreExt, authApikeyExt, providerOpenaiCompatExt, + providerUmansExt, toolEditFileExt, toolReadFileExt, toolShellExt, @@ -148,6 +150,14 @@ async function boot(): Promise<void> { // Assemble the credential list. MVP keeps the hardcoded `opencode` credential // and adds a `claude` credential when an external Anthropic provider is loaded. const credentials = [{ name: "opencode", providerId: "openai-compat" }]; + + // The umans credential is always listed (it's the model-catalog index); the + // provider itself only registers when UMANS_API_KEY is set, so listCatalog + // gracefully skips it when the provider is absent. + if (process.env.UMANS_API_KEY) { + credentials.push({ name: "umans", providerId: "umans" }); + logger.info(`Registered credential "umans" → umans provider`); + } const hasAnthropic = externalExtensions.some((e) => e.manifest.contributes?.providers?.includes("anthropic"), ); |
