From 4032d15d965e3a9a886bba60d59c4c522cfdbc3d Mon Sep 17 00:00:00 2001 From: elpresidank Date: Thu, 4 Jun 2026 07:21:30 -0500 Subject: [PATCH] Use Effect fn for Ollama embeddings --- ts/EFFECT_NATIVE_REWRITE_AUDIT.md | 26 +++++++- ts/packages/flow/src/embeddings/ollama.ts | 74 +++++++++++------------ 2 files changed, 59 insertions(+), 41 deletions(-) diff --git a/ts/EFFECT_NATIVE_REWRITE_AUDIT.md b/ts/EFFECT_NATIVE_REWRITE_AUDIT.md index c519f477..1155124f 100644 --- a/ts/EFFECT_NATIVE_REWRITE_AUDIT.md +++ b/ts/EFFECT_NATIVE_REWRITE_AUDIT.md @@ -2143,6 +2143,27 @@ Notes: - `cd ts && bun run lint` - `git diff --check` +### 2026-06-04: Ollama Embeddings Effect.fn Helper Slice + +- Status: migrated and package-verified. +- Completed: + - `ts/packages/flow/src/embeddings/ollama.ts` now defines the `embed` + service method as a named `Effect.fn` generator instead of returning a + nested `Effect.gen` from an `Effect.fn` callback. + - Empty embedding requests now return through the same generator path without + allocating a separate `Effect.succeed` helper. + - The public sync factory, effectful layer, `ManagedRuntime` facade, and + `NodeRuntime.runMain` entrypoint are unchanged. + - The focused scan for Ollama `return Effect.gen(...)` helper patterns is + clean. +- Verification: + - `cd ts/packages/flow && bunx --bun vitest run src/__tests__/ollama-embeddings.test.ts` + - `cd ts && bun run check:tsgo` + - `cd ts && bun run build` + - `cd ts && bun run test` + - `cd ts && bun run lint` + - `git diff --check` + ## Subagent Findings To Preserve - MCP/workbench: @@ -2301,9 +2322,8 @@ Notes: - Fresh strict signal sweep after the 2026-06-04 helper and collection slices found no production normal `Error`, raw `try`/`catch`, native `switch`, or Effect-focused type assertions under `ts/packages`. - - Remaining real helper-normalization targets from the fresh sweep are - embeddings/ollama, base processor flow helpers, and one workbench atom - helper. + - Remaining real helper-normalization targets from the fresh sweep are base + processor flow helpers and one workbench atom helper. - Remaining real long-lived native collection targets include base processor registries, Librarian service / collection manager state, prompt template cache, and a workbench module cache. Local traversal sets and test fakes diff --git a/ts/packages/flow/src/embeddings/ollama.ts b/ts/packages/flow/src/embeddings/ollama.ts index 92620f3f..97ab497a 100644 --- a/ts/packages/flow/src/embeddings/ollama.ts +++ b/ts/packages/flow/src/embeddings/ollama.ts @@ -79,52 +79,50 @@ const makeOllamaEmbeddingsFromConfig = ({ ollamaHost, fetchImpl, }: ResolvedOllamaEmbeddingsConfig): EmbeddingsServiceShape => ({ - embed: Effect.fn("OllamaEmbeddings.embed")((texts: ReadonlyArray, model?: string) => { + embed: Effect.fn("OllamaEmbeddings.embed")(function* (texts: ReadonlyArray, model?: string) { if (texts.length === 0) { - return Effect.succeed([]); + return []; } const useModel = model ?? defaultModel; const url = `${ollamaHost}/api/embed`; - return Effect.gen(function* () { - const body = yield* S.encodeUnknownEffect(S.UnknownFromJsonString)({ - model: useModel, - input: Array.from(texts), - }).pipe( - Effect.mapError((error) => ollamaEmbeddingsError("ollama.encode-request", error)) - ); + const body = yield* S.encodeUnknownEffect(S.UnknownFromJsonString)({ + model: useModel, + input: Array.from(texts), + }).pipe( + Effect.mapError((error) => ollamaEmbeddingsError("ollama.encode-request", error)) + ); - const response = yield* Effect.tryPromise({ - try: () => - fetchImpl(url, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body, - }), - catch: (error) => ollamaEmbeddingsError("ollama.fetch", error), - }); - - if (!response.ok) { - const errorBody = yield* Effect.tryPromise({ - try: () => response.text(), - catch: (error) => ollamaEmbeddingsError("ollama.error-body", error), - }); - return yield* ollamaEmbeddingsMessageError( - "ollama.embed", - `Ollama embeddings request failed (${response.status}): ${errorBody}`, - ); - } - - const data = yield* Effect.tryPromise({ - try: () => responseJson(response), - catch: (error) => ollamaEmbeddingsError("ollama.response-json", error), - }); - const decoded = yield* S.decodeUnknownEffect(OllamaEmbedResponse)(data).pipe( - Effect.mapError((error) => ollamaEmbeddingsError("ollama.decode-response", error)) - ); - return Array.from(decoded.embeddings, (vector) => Array.from(vector)); + const response = yield* Effect.tryPromise({ + try: () => + fetchImpl(url, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body, + }), + catch: (error) => ollamaEmbeddingsError("ollama.fetch", error), }); + + if (!response.ok) { + const errorBody = yield* Effect.tryPromise({ + try: () => response.text(), + catch: (error) => ollamaEmbeddingsError("ollama.error-body", error), + }); + return yield* ollamaEmbeddingsMessageError( + "ollama.embed", + `Ollama embeddings request failed (${response.status}): ${errorBody}`, + ); + } + + const data = yield* Effect.tryPromise({ + try: () => responseJson(response), + catch: (error) => ollamaEmbeddingsError("ollama.response-json", error), + }); + const decoded = yield* S.decodeUnknownEffect(OllamaEmbedResponse)(data).pipe( + Effect.mapError((error) => ollamaEmbeddingsError("ollama.decode-response", error)) + ); + return Array.from(decoded.embeddings, (vector) => Array.from(vector)); }), });