diff --git a/ts/EFFECT_NATIVE_REWRITE_AUDIT.md b/ts/EFFECT_NATIVE_REWRITE_AUDIT.md index accc7943..9af0c5db 100644 --- a/ts/EFFECT_NATIVE_REWRITE_AUDIT.md +++ b/ts/EFFECT_NATIVE_REWRITE_AUDIT.md @@ -2005,6 +2005,29 @@ Notes: - `cd ts && bun run lint` - `git diff --check` +### 2026-06-04: Librarian Effect.fn Helper Slice + +- Status: migrated and package-verified. +- Completed: + - `ts/packages/flow/src/librarian/service.ts` now defines its reusable + librarian generator helpers with `Effect.fn` or `Effect.fnUntraced` + instead of arrow functions returning `Effect.gen`. + - `consumeOnceEffect` and both per-message response senders use + `Effect.fnUntraced` for small hot-path callbacks. + - `runLibrarianServiceEffect`, `getDocumentMetadataEffect`, + `listChildrenEffect`, `uploadChunkEffect`, `getUploadStatusEffect`, and + `abortUploadEffect` use named `Effect.fn` wrappers while preserving their + tagged-error behavior and Promise compatibility method surfaces. + - The focused scan for librarian-service helper `=> Effect.gen` patterns is + clean. +- Verification: + - `cd ts/packages/flow && bunx --bun vitest run src/__tests__/librarian-service.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: diff --git a/ts/packages/flow/src/librarian/service.ts b/ts/packages/flow/src/librarian/service.ts index 8e1f5859..000ec3ad 100644 --- a/ts/packages/flow/src/librarian/service.ts +++ b/ts/packages/flow/src/librarian/service.ts @@ -254,10 +254,9 @@ const modifyResult = ( const uploadBytesReceived = (session: UploadSession): number => [...session.chunks.values()].reduce((sum, chunk) => sum + chunk.length, 0); -const consumeOnceEffect = ( +const consumeOnceEffect = Effect.fnUntraced(function* ( service: LibrarianService, -): Effect.Effect => - Effect.gen(function* () { +) { const state = yield* SynchronizedRef.get(service.state); const libConsumer = state.libConsumer; if (libConsumer === null) { @@ -299,10 +298,9 @@ const consumeOnceEffect = ( } }); -const runLibrarianServiceEffect = ( +const runLibrarianServiceEffect = Effect.fn("LibrarianService.run")(function* ( service: LibrarianService, -): Effect.Effect => - Effect.gen(function* () { +) { yield* Effect.tryPromise({ try: () => ensureDirectory(joinPath(service.dataDir, "docs")), catch: (cause) => librarianServiceError("ensure-data-dir", cause), @@ -379,8 +377,9 @@ export function makeLibrarianService(config: LibrarianServiceConfig): LibrarianS const dataDir = resolveDataDir(config); const persistPath = joinPath(dataDir, "librarian-state.json"); - const getDocumentMetadataEffect = (request: LibrarianRequest): Effect.Effect => - Effect.gen(function* () { + const getDocumentMetadataEffect = Effect.fn("LibrarianService.getDocumentMetadata")(function* ( + request: LibrarianRequest, + ) { const current = yield* getService; const id = current.documentId(request); if (id === undefined || id.length === 0) { @@ -395,8 +394,9 @@ export function makeLibrarianService(config: LibrarianServiceConfig): LibrarianS return current.documentResponse(doc); }); - const listChildrenEffect = (request: LibrarianRequest): Effect.Effect => - Effect.gen(function* () { + const listChildrenEffect = Effect.fn("LibrarianService.listChildren")(function* ( + request: LibrarianRequest, + ) { const current = yield* getService; const parentId = current.documentId(request); if (parentId === undefined || parentId.length === 0) { @@ -414,8 +414,9 @@ export function makeLibrarianService(config: LibrarianServiceConfig): LibrarianS return current.documentsResponse(children); }); - const uploadChunkEffect = (request: LibrarianRequest): Effect.Effect => - Effect.gen(function* () { + const uploadChunkEffect = Effect.fn("LibrarianService.uploadChunk")(function* ( + request: LibrarianRequest, + ) { const current = yield* getService; const req = current.requestRecord(request); const uploadId = optionalString(req["upload-id"]); @@ -456,8 +457,9 @@ export function makeLibrarianService(config: LibrarianServiceConfig): LibrarianS }); }); - const getUploadStatusEffect = (request: LibrarianRequest): Effect.Effect => - Effect.gen(function* () { + const getUploadStatusEffect = Effect.fn("LibrarianService.getUploadStatus")(function* ( + request: LibrarianRequest, + ) { const current = yield* getService; const uploadId = optionalString(current.requestRecord(request)["upload-id"]); if (uploadId === undefined) { @@ -482,8 +484,9 @@ export function makeLibrarianService(config: LibrarianServiceConfig): LibrarianS }; }); - const abortUploadEffect = (request: LibrarianRequest): Effect.Effect => - Effect.gen(function* () { + const abortUploadEffect = Effect.fn("LibrarianService.abortUpload")(function* ( + request: LibrarianRequest, + ) { const current = yield* getService; const uploadId = optionalString(current.requestRecord(request)["upload-id"]); if (uploadId === undefined) { @@ -672,8 +675,7 @@ export function makeLibrarianService(config: LibrarianServiceConfig): LibrarianS return; } - const sendResponse = (response: LibrarianResponse): Effect.Effect => - Effect.gen(function* () { + const sendResponse = Effect.fnUntraced(function* (response: LibrarianResponse) { const producer = (yield* SynchronizedRef.get(service.state)).libProducer; if (producer === null) { return yield* librarianServiceError("librarian-respond", "Librarian producer not started"); @@ -1378,8 +1380,7 @@ export function makeLibrarianService(config: LibrarianServiceConfig): LibrarianS return; } - const sendResponse = (response: CollectionManagementResponse): Effect.Effect => - Effect.gen(function* () { + const sendResponse = Effect.fnUntraced(function* (response: CollectionManagementResponse) { const producer = (yield* SynchronizedRef.get(service.state)).colProducer; if (producer === null) { return yield* librarianServiceError("collection-respond", "Collection producer not started");