@swapai/core 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/classifier.ts","../src/config.ts","../src/evaluation.ts","../src/runtime.ts","../src/needle.ts","../src/storage.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { join } from \"node:path\";\n\nimport { normalizeConfig, validateResult } from \"./config.js\";\nimport { averageError, resultError } from \"./evaluation.js\";\nimport { SwapAIError } from \"./errors.js\";\nimport {\n NEEDLE_VERSION,\n createNeedleRuntime,\n type LoadedNeedleModel,\n type NeedleRuntime,\n} from \"./runtime.js\";\nimport { openStorage, type Storage } from \"./storage.js\";\nimport type {\n Classifier,\n InitConfig,\n NormalizedInitConfig,\n ReferenceClassifier,\n ResultConfig,\n ResultFor,\n ResultValue,\n} from \"./types.js\";\n\nconst TRAINING_LEASE_DURATION_MS = 5 * 60 * 1000;\nconst TRAINING_LEASE_RENEWAL_MS = 60 * 1000;\nconst ARTIFACT_LOCK_WAIT_MS = 30_000;\n\nexport function init<const Config extends ResultConfig>(\n inputConfig: InitConfig<Config>,\n): Classifier<ResultFor<Config>> {\n const config = normalizeConfig(inputConfig);\n const dataDirectory = config.dataDirectory ?? join(process.cwd(), \".swapai\");\n const storage = openClassifierStorage(config, dataDirectory);\n const runtime = createNeedleRuntime({\n dataDirectory,\n onBackgroundError: (error) =>\n reportBackgroundError(\n config,\n new SwapAIError(\"service_unavailable\", error.message, { cause: error }),\n ),\n });\n\n return createClassifier(config, storage, runtime);\n}\n\nfunction openClassifierStorage<const Config extends ResultConfig>(\n config: NormalizedInitConfig<Config>,\n dataDirectory: string,\n): Storage {\n try {\n return openStorage({\n dataDirectory,\n name: config.name,\n maxTrainingSet: config.maxTrainingSet,\n config: {\n result: config.result,\n retrainOnCount: config.retrainOnCount,\n acceptableError: config.acceptableError,\n retestInterval: config.retestInterval,\n retestRevertOn: config.retestRevertOn,\n model: config.model,\n },\n });\n } catch (error) {\n throw new SwapAIError(\n error instanceof TypeError ? \"invalid_configuration\" : \"storage_failed\",\n error instanceof Error ? error.message : \"Could not open SwapAI storage\",\n { cause: error },\n );\n }\n}\n\nfunction createClassifier<const Config extends ResultConfig>(\n config: NormalizedInitConfig<Config>,\n storage: Storage,\n runtime: NeedleRuntime,\n): Classifier<ResultFor<Config>> {\n type Result = ResultFor<Config>;\n\n const initialState = storage.snapshot();\n let closed = false;\n let closing = false;\n let closePromise: Promise<void> | null = null;\n let trained = initialState.trained && !initialState.clearPending;\n let loadedModel: LoadedNeedleModel | null = null;\n let loadedModelEpoch: number | null = null;\n let operationQueue: Promise<void> = Promise.resolve();\n let trainingQueue: Promise<void> = Promise.resolve();\n let trainingScheduled = false;\n const trainingLeaseOwner = `${process.pid}:${randomUUID()}`;\n let classificationQueue: Promise<void> = Promise.resolve();\n let queuedFailure: SwapAIError | null = null;\n let clearFailure: SwapAIError | null = null;\n let dataEpoch = initialState.dataEpoch;\n let clearedEpoch = initialState.clearPending\n ? initialState.dataEpoch - 1\n : initialState.dataEpoch;\n\n const saved = initialState;\n if (\n !saved.clearPending &&\n saved.trained &&\n (saved.modelPath === null || saved.needleVersion !== NEEDLE_VERSION)\n ) {\n if (storage.archiveAndReset(saved.dataEpoch) !== null) {\n const reset = storage.snapshot();\n dataEpoch = reset.dataEpoch;\n clearedEpoch = reset.dataEpoch;\n trained = false;\n }\n }\n\n const startup = startRuntime();\n\n async function startRuntime(): Promise<void> {\n const startupEpoch = dataEpoch;\n const beforeRuntime = storage.snapshot();\n if (beforeRuntime.clearPending) {\n trained = false;\n dataEpoch = beforeRuntime.dataEpoch;\n try {\n await performDurableClear(beforeRuntime.dataEpoch);\n } catch (error) {\n rememberClearFailure(error);\n }\n }\n try {\n await runtime.ready();\n const snapshot = storage.snapshot();\n if (snapshot.clearPending) {\n trained = false;\n dataEpoch = snapshot.dataEpoch;\n return;\n }\n if (snapshot.trained && snapshot.modelPath !== null) {\n const restoredModel = await runtime.loadModel({\n modelPath: snapshot.modelPath,\n resultConfig: config.result,\n });\n const current = storage.snapshot();\n if (\n startupEpoch === current.dataEpoch &&\n !current.clearPending &&\n current.trained\n ) {\n loadedModel = restoredModel;\n loadedModelEpoch = startupEpoch;\n trained = true;\n } else {\n await restoredModel.close();\n }\n }\n } catch (error) {\n const swapAIError = toSwapAIError(\n error,\n \"service_unavailable\",\n \"Needle could not start\",\n );\n rememberBackgroundFailure(swapAIError);\n }\n }\n\n function rememberBackgroundFailure(error: SwapAIError): void {\n queuedFailure = error;\n reportBackgroundError(config, error);\n }\n\n function rememberClearFailure(error: unknown): void {\n clearFailure = toSwapAIError(\n error,\n \"storage_failed\",\n `Could not completely clear classifier \"${config.name}\"`,\n );\n reportBackgroundError(config, clearFailure);\n }\n\n function refreshStoredState() {\n const snapshot = storage.snapshot();\n dataEpoch = snapshot.dataEpoch;\n if (snapshot.clearPending) {\n trained = false;\n } else {\n trained = snapshot.trained;\n clearedEpoch = snapshot.dataEpoch;\n }\n return snapshot;\n }\n\n function enqueue(operation: () => void | Promise<void>): Promise<void> {\n const result = operationQueue.then(operation);\n operationQueue = result.catch((error: unknown) => {\n rememberBackgroundFailure(\n toSwapAIError(error, \"storage_failed\", \"Background work failed\"),\n );\n });\n return result;\n }\n\n function persistExample(\n input: string,\n result: Result,\n epoch = dataEpoch,\n ): Promise<void> {\n if (epoch !== dataEpoch) return Promise.resolve();\n return enqueue(() => {\n if (epoch !== dataEpoch) return;\n if (storage.addExample(input, result, epoch) !== null) scheduleTraining();\n });\n }\n\n function shouldTrain(snapshot = storage.snapshot()): boolean {\n return (\n clearedEpoch === dataEpoch &&\n snapshot.dataEpoch === dataEpoch &&\n !snapshot.clearPending &&\n !snapshot.trained &&\n snapshot.examplesUsedForTraining < config.maxTrainingSet &&\n snapshot.newExamplesSinceTraining >= config.retrainOnCount\n );\n }\n\n function scheduleTraining(): void {\n if (trainingScheduled || !shouldTrain()) return;\n trainingScheduled = true;\n let completedAttempt = false;\n const attempt = operationQueue.then(async () => {\n completedAttempt = await trainWhenDue();\n });\n trainingQueue = attempt\n .catch((error: unknown) => {\n rememberBackgroundFailure(\n toSwapAIError(error, \"service_unavailable\", \"Needle training failed\"),\n );\n })\n .finally(() => {\n trainingScheduled = false;\n if (completedAttempt) scheduleTraining();\n });\n }\n\n async function trainWhenDue(): Promise<boolean> {\n const trainingEpoch = dataEpoch;\n if (!shouldTrain()) return false;\n if (\n !storage.claimTrainingLease(\n trainingLeaseOwner,\n TRAINING_LEASE_DURATION_MS,\n trainingEpoch,\n )\n ) {\n return false;\n }\n\n let leaseHeld = true;\n const renewTrainingLease = (): boolean => {\n if (!leaseHeld) return false;\n try {\n leaseHeld = storage.claimTrainingLease(\n trainingLeaseOwner,\n TRAINING_LEASE_DURATION_MS,\n trainingEpoch,\n );\n } catch {\n leaseHeld = false;\n }\n return leaseHeld;\n };\n const leaseRenewal = setInterval(\n renewTrainingLease,\n TRAINING_LEASE_RENEWAL_MS,\n );\n leaseRenewal.unref();\n\n try {\n const snapshot = storage.snapshot();\n if (!shouldTrain(snapshot)) return false;\n\n if (\n !storage.markTrainingAttempted(\n snapshot.activeExampleCount,\n trainingEpoch,\n )\n ) {\n return false;\n }\n const trainingExamples = storage.listExamplesForTraining(\n \"training\",\n snapshot.activeGeneration,\n trainingEpoch,\n );\n const heldOutExamples = storage.listExamplesForTraining(\n \"held_out\",\n snapshot.activeGeneration,\n trainingEpoch,\n );\n\n if (trainingExamples === null || heldOutExamples === null) return false;\n if (trainingExamples.length === 0 || heldOutExamples.length === 0) {\n return true;\n }\n\n const candidate = await runtime.train({\n classifierName: config.name,\n generation: snapshot.activeGeneration,\n expectedEpoch: trainingEpoch,\n examples: trainingExamples.map(({ input, result }) => ({ input, result })),\n resultConfig: config.result,\n });\n const candidateModel = await runtime.loadModel({\n modelPath: candidate.modelPath,\n resultConfig: config.result,\n });\n\n try {\n const comparisons = [];\n for (const example of heldOutExamples) {\n const candidateResult = validateResult(\n config.result,\n await candidateModel.classify(example.input),\n );\n comparisons.push({\n reference: validateResult(config.result, example.result),\n candidate: candidateResult,\n });\n }\n\n if (averageError(config.result, comparisons) > config.acceptableError) {\n return true;\n }\n\n if (!renewTrainingLease()) {\n const current = refreshStoredState();\n if (\n current.dataEpoch !== trainingEpoch ||\n current.clearPending\n ) {\n await runtime.clearClassifierGenerationArtifacts(\n config.name,\n snapshot.activeGeneration,\n );\n return false;\n }\n throw new SwapAIError(\n \"service_unavailable\",\n `Classifier \"${config.name}\" lost its training lease`,\n );\n }\n\n if (trainingEpoch !== refreshStoredState().dataEpoch) {\n await runtime.clearClassifierGenerationArtifacts(\n config.name,\n snapshot.activeGeneration,\n );\n return false;\n }\n if (storage.promoteGeneration(candidate, trainingEpoch) === null) {\n await runtime.clearClassifierGenerationArtifacts(\n config.name,\n snapshot.activeGeneration,\n );\n return false;\n }\n if (loadedModel !== null) await loadedModel.close();\n if (trainingEpoch !== refreshStoredState().dataEpoch) {\n await runtime.clearClassifierGenerationArtifacts(\n config.name,\n snapshot.activeGeneration,\n );\n return false;\n }\n loadedModel = candidateModel;\n loadedModelEpoch = trainingEpoch;\n trained = true;\n return true;\n } finally {\n if (loadedModel !== candidateModel) await candidateModel.close();\n }\n } finally {\n clearInterval(leaseRenewal);\n storage.releaseTrainingLease(trainingLeaseOwner);\n }\n }\n\n async function model(expectedEpoch: number): Promise<LoadedNeedleModel> {\n await startup;\n const current = refreshStoredState();\n if (\n !trained ||\n current.clearPending ||\n current.dataEpoch !== expectedEpoch\n ) {\n throw new SwapAIError(\n \"not_trained\",\n `Classifier \"${config.name}\" has not passed its held-out test`,\n );\n }\n if (loadedModel !== null && loadedModelEpoch !== expectedEpoch) {\n await loadedModel.close();\n loadedModel = null;\n loadedModelEpoch = null;\n }\n if (loadedModel === null) {\n if (current.modelPath === null) {\n throw new SwapAIError(\n \"service_unavailable\",\n `Classifier \"${config.name}\" is trained but has no saved model`,\n );\n }\n await runtime.ready();\n const restored = await runtime.loadModel({\n modelPath: current.modelPath,\n resultConfig: config.result,\n });\n const afterLoad = refreshStoredState();\n if (\n afterLoad.dataEpoch !== expectedEpoch ||\n afterLoad.clearPending ||\n !afterLoad.trained\n ) {\n await restored.close();\n throw new SwapAIError(\n \"not_trained\",\n `Classifier \"${config.name}\" has been cleared`,\n );\n }\n loadedModel = restored;\n loadedModelEpoch = expectedEpoch;\n }\n return loadedModel;\n }\n\n async function callReference(\n input: string,\n reference: ReferenceClassifier<Result>,\n ): Promise<Result> {\n return validateResult(config.result, await reference(input));\n }\n\n async function fallbackToReference(\n input: string,\n reference: ReferenceClassifier<Result> | undefined,\n candidateError: unknown,\n retestDue: boolean,\n epoch: number,\n ): Promise<Result> {\n if (reference === undefined) {\n throw toSwapAIError(\n candidateError,\n \"classification_failed\",\n \"Needle classification failed\",\n );\n }\n reportBackgroundError(\n config,\n toSwapAIError(\n candidateError,\n \"classification_failed\",\n \"Needle classification failed; the reference classifier was used\",\n ),\n );\n const referenceResult = await callReference(input, reference);\n await persistExample(input, referenceResult, epoch);\n if (retestDue && epoch === dataEpoch) {\n if (storage.recordLocalClassification(epoch) === null) return referenceResult;\n const failures = storage.recordRetest(false, epoch);\n if (failures !== null && failures >= config.retestRevertOn) {\n await disableModel(epoch);\n }\n }\n return referenceResult;\n }\n\n async function disableModel(epoch: number): Promise<void> {\n if (storage.archiveAndReset(epoch) === null) return;\n refreshStoredState();\n trained = false;\n const previousModel = loadedModel;\n loadedModel = null;\n loadedModelEpoch = null;\n if (previousModel !== null) await previousModel.close();\n }\n\n async function classifyNow(\n input: string,\n reference: ReferenceClassifier<Result> | undefined,\n epoch: number,\n ): Promise<Result> {\n assertOpen(closed);\n\n if (!trained) {\n if (reference === undefined) {\n throw new SwapAIError(\n \"not_trained\",\n `Classifier \"${config.name}\" has not passed its held-out test`,\n );\n }\n const referenceResult = await callReference(input, reference);\n await persistExample(input, referenceResult, epoch);\n return referenceResult;\n }\n\n const snapshot = storage.snapshot();\n const retestDue =\n config.retestInterval > 0 &&\n snapshot.localClassificationsSinceRetest + 1 >= config.retestInterval;\n\n let candidateResult: Result;\n try {\n candidateResult = validateResult(\n config.result,\n await (await model(epoch)).classify(input),\n );\n } catch (error) {\n return fallbackToReference(input, reference, error, retestDue, epoch);\n }\n\n const afterClassification = refreshStoredState();\n if (\n afterClassification.dataEpoch !== epoch ||\n afterClassification.clearPending\n ) {\n return fallbackToReference(\n input,\n reference,\n new SwapAIError(\n \"not_trained\",\n `Classifier \"${config.name}\" was cleared during classification`,\n ),\n retestDue,\n epoch,\n );\n }\n\n if (!retestDue || reference === undefined) {\n if (\n epoch !== dataEpoch ||\n storage.recordLocalClassification(epoch) === null\n ) {\n return fallbackToReference(\n input,\n reference,\n new SwapAIError(\n \"not_trained\",\n `Classifier \"${config.name}\" was cleared before returning its result`,\n ),\n retestDue,\n epoch,\n );\n }\n return candidateResult;\n }\n\n const referenceResult = await callReference(input, reference);\n await persistExample(input, referenceResult, epoch);\n if (epoch !== dataEpoch) return referenceResult;\n if (storage.recordLocalClassification(epoch) === null) return referenceResult;\n const passed =\n resultError(config.result, referenceResult, candidateResult) <=\n config.acceptableError;\n const failures = storage.recordRetest(passed, epoch);\n\n if (\n !passed &&\n failures !== null &&\n failures >= config.retestRevertOn\n ) {\n await disableModel(epoch);\n }\n\n return referenceResult;\n }\n\n async function performDurableClear(clearEpoch: number): Promise<void> {\n trained = false;\n const deletionFailures: unknown[] = [];\n const throwDeletionFailures = (): void => {\n if (deletionFailures.length === 1) throw deletionFailures[0];\n if (deletionFailures.length > 1) {\n throw new AggregateError(\n deletionFailures,\n `Could not completely clear classifier \"${config.name}\"`,\n );\n }\n };\n const previousModel = loadedModel;\n if (previousModel !== null) {\n try {\n await previousModel.close();\n if (loadedModel === previousModel) {\n loadedModel = null;\n loadedModelEpoch = null;\n }\n } catch (error) {\n deletionFailures.push(error);\n }\n }\n\n const lockWaitStarted = Date.now();\n let clearState = refreshStoredState();\n while (\n clearState.clearPending &&\n clearState.dataEpoch === clearEpoch &&\n ((clearState.trainingLeaseOwner !== null &&\n clearState.trainingLeaseEpoch === null &&\n clearState.trainingLeaseUntil !== null &&\n clearState.trainingLeaseUntil > Date.now()) ||\n !storage.claimArtifactWriteLock())\n ) {\n if (Date.now() - lockWaitStarted >= ARTIFACT_LOCK_WAIT_MS) {\n throw new SwapAIError(\n \"storage_failed\",\n `Timed out waiting to clear classifier \"${config.name}\" while training was still running`,\n );\n }\n await new Promise<void>((resolve) => setTimeout(resolve, 10));\n clearState = refreshStoredState();\n }\n\n if (!clearState.clearPending || clearState.dataEpoch !== clearEpoch) {\n throwDeletionFailures();\n return;\n }\n try {\n try {\n storage.eraseTrainingData(clearEpoch);\n } catch (error) {\n deletionFailures.push(error);\n }\n clearState = refreshStoredState();\n if (\n clearState.clearPending &&\n clearState.dataEpoch === clearEpoch &&\n clearState.clearErased &&\n clearState.clearArtifactGenerationMax !== null\n ) {\n try {\n await runtime.clearClassifierArtifactsThroughGeneration(\n config.name,\n clearState.clearArtifactGenerationMax,\n );\n } catch (error) {\n deletionFailures.push(error);\n }\n }\n throwDeletionFailures();\n\n storage.finishClearTrainingData(clearEpoch);\n const current = refreshStoredState();\n if (!current.clearPending) {\n clearFailure = null;\n clearedEpoch = current.dataEpoch;\n }\n } finally {\n storage.releaseArtifactWriteLock();\n }\n }\n\n async function flushNow(): Promise<void> {\n const clearFailureBeforeFlush = clearFailure;\n await startup;\n while (true) {\n const operations = operationQueue;\n await operations;\n const training = trainingQueue;\n await training;\n if (operations === operationQueue && training === trainingQueue) break;\n }\n if (\n clearFailure !== null &&\n clearFailure !== clearFailureBeforeFlush\n ) {\n throw clearFailure;\n }\n const pending = refreshStoredState();\n if (pending.clearPending || clearFailureBeforeFlush !== null) {\n try {\n await performDurableClear(pending.dataEpoch);\n if (!refreshStoredState().clearPending) clearFailure = null;\n } catch (error) {\n rememberClearFailure(error);\n }\n }\n if (refreshStoredState().clearPending) {\n clearFailure ??= new SwapAIError(\n \"storage_failed\",\n `Could not completely clear classifier \"${config.name}\"`,\n );\n throw clearFailure;\n }\n if (clearFailure !== null) throw clearFailure;\n if (queuedFailure !== null) {\n const failure = queuedFailure;\n queuedFailure = null;\n throw failure;\n }\n }\n\n const classifier: Classifier<Result> = {\n isTrained() {\n assertOpen(closed || closing);\n refreshStoredState();\n return trained;\n },\n\n logClassification(input, result) {\n assertOpen(closed || closing);\n const validResult = validateResult(config.result, result);\n const epoch = refreshStoredState().dataEpoch;\n void persistExample(input, validResult, epoch);\n },\n\n clearTrainingData() {\n assertOpen(closed || closing);\n trained = false;\n const clearEpoch = storage.beginClearTrainingData();\n dataEpoch = clearEpoch;\n const trainingBeforeClear = trainingQueue;\n const classificationsBeforeClear = classificationQueue;\n void enqueue(async () => {\n await startup;\n await trainingBeforeClear;\n await classificationsBeforeClear;\n try {\n await performDurableClear(clearEpoch);\n } catch (error) {\n rememberClearFailure(error);\n }\n });\n },\n\n classify(input, reference) {\n assertOpen(closed || closing);\n const epoch = refreshStoredState().dataEpoch;\n const task = classificationQueue.then(() =>\n classifyNow(input, reference, epoch),\n );\n classificationQueue = task.then(\n () => undefined,\n () => undefined,\n );\n return task;\n },\n\n async flush() {\n assertOpen(closed || closing);\n await flushNow();\n },\n\n close() {\n if (closed) return Promise.resolve();\n if (closePromise !== null) return closePromise;\n closing = true;\n closePromise = (async () => {\n try {\n await classificationQueue;\n await flushNow();\n } catch (error) {\n closing = false;\n closePromise = null;\n throw error;\n }\n const failures: unknown[] = [];\n if (loadedModel !== null) {\n try {\n await loadedModel.close();\n } catch (error) {\n failures.push(error);\n }\n }\n loadedModel = null;\n loadedModelEpoch = null;\n try {\n await runtime.close();\n } catch (error) {\n failures.push(error);\n }\n try {\n storage.close();\n } catch (error) {\n failures.push(error);\n }\n closed = true;\n closing = false;\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1) {\n throw new AggregateError(\n failures,\n `Could not completely close classifier \"${config.name}\"`,\n );\n }\n })();\n return closePromise;\n },\n };\n\n return classifier;\n}\n\nfunction assertOpen(closed: boolean): void {\n if (closed) {\n throw new SwapAIError(\"service_unavailable\", \"Classifier is closed\");\n }\n}\n\nfunction toSwapAIError(\n error: unknown,\n code: \"classification_failed\" | \"service_unavailable\" | \"storage_failed\",\n message: string,\n): SwapAIError {\n if (error instanceof SwapAIError) return error;\n return new SwapAIError(code, message, { cause: error });\n}\n\nfunction reportBackgroundError(\n config: NormalizedInitConfig<ResultConfig>,\n error: SwapAIError,\n): void {\n try {\n config.onBackgroundError?.(error);\n } catch {\n // A reporting callback must not interrupt classification or storage work.\n }\n}\n","import { SwapAIError } from \"./errors.js\";\nimport type {\n InitConfig,\n NormalizedInitConfig,\n ResultConfig,\n ResultFor,\n} from \"./types.js\";\n\nfunction invalidConfiguration(message: string): never {\n throw new SwapAIError(\"invalid_configuration\", message);\n}\n\nfunction requirePositiveInteger(value: number, field: string): void {\n if (!Number.isInteger(value) || value <= 0) {\n invalidConfiguration(`${field} must be a positive integer`);\n }\n}\n\nfunction requireNonNegativeInteger(value: number, field: string): void {\n if (!Number.isInteger(value) || value < 0) {\n invalidConfiguration(`${field} must be a non-negative integer`);\n }\n}\n\nfunction normalizeAcceptableError(value: number | `${number}%`): number {\n let normalized: number;\n\n if (typeof value === \"number\") {\n normalized = value;\n } else {\n const match = /^\\s*(\\d+(?:\\.\\d+)?)%\\s*$/.exec(value);\n if (match === null) {\n invalidConfiguration(\n \"acceptableError must be a number or a percentage such as \\\"10%\\\"\",\n );\n }\n normalized = Number(match[1]) / 100;\n }\n\n if (!Number.isFinite(normalized) || normalized < 0 || normalized > 1) {\n invalidConfiguration(\"acceptableError must be between 0 and 1\");\n }\n\n return normalized;\n}\n\nfunction validateResultConfig(result: ResultConfig): void {\n if (result.type === \"number\") {\n if (!Number.isFinite(result.min) || !Number.isFinite(result.max)) {\n invalidConfiguration(\"number result bounds must be finite\");\n }\n if (result.max <= result.min) {\n invalidConfiguration(\"number result max must be greater than min\");\n }\n return;\n }\n\n if (result.type === \"string\") {\n if (result.values.length === 0) {\n invalidConfiguration(\"string result values must not be empty\");\n }\n if (\n result.values.some((value) => typeof value !== \"string\") ||\n new Set(result.values).size !== result.values.length\n ) {\n invalidConfiguration(\"string result values must be unique strings\");\n }\n }\n}\n\nexport function normalizeConfig<const Config extends ResultConfig>(\n config: InitConfig<Config>,\n): NormalizedInitConfig<Config> {\n if (typeof config.name !== \"string\" || config.name.trim() === \"\") {\n invalidConfiguration(\"name must not be empty\");\n }\n\n validateResultConfig(config.result);\n requirePositiveInteger(config.retrainOnCount, \"retrainOnCount\");\n requireNonNegativeInteger(config.retestInterval, \"retestInterval\");\n requirePositiveInteger(config.retestRevertOn, \"retestRevertOn\");\n requirePositiveInteger(config.maxTrainingSet, \"maxTrainingSet\");\n\n if (config.maxTrainingSet < config.retrainOnCount) {\n invalidConfiguration(\n \"maxTrainingSet must be greater than or equal to retrainOnCount\",\n );\n }\n if (config.model !== \"needle2\") {\n invalidConfiguration('model must be \"needle2\"');\n }\n if (\n config.dataDirectory !== undefined &&\n (typeof config.dataDirectory !== \"string\" ||\n config.dataDirectory.trim() === \"\")\n ) {\n invalidConfiguration(\"dataDirectory must not be empty\");\n }\n if (\n config.onBackgroundError !== undefined &&\n typeof config.onBackgroundError !== \"function\"\n ) {\n invalidConfiguration(\"onBackgroundError must be a function\");\n }\n\n return {\n ...config,\n acceptableError: normalizeAcceptableError(config.acceptableError),\n };\n}\n\nexport function validateResult<const Config extends ResultConfig>(\n config: Config,\n value: unknown,\n): ResultFor<Config> {\n const valid =\n config.type === \"number\"\n ? typeof value === \"number\" &&\n Number.isFinite(value) &&\n value >= config.min &&\n value <= config.max\n : config.type === \"boolean\"\n ? typeof value === \"boolean\"\n : typeof value === \"string\" && config.values.includes(value);\n\n if (!valid) {\n throw new SwapAIError(\n \"invalid_result\",\n \"classification result does not match the declared allowed results\",\n );\n }\n\n return value as ResultFor<Config>;\n}\n","import { validateResult } from \"./config.js\";\nimport { SwapAIError } from \"./errors.js\";\nimport type {\n ResultComparison,\n ResultConfig,\n ResultFor,\n} from \"./types.js\";\n\nexport function resultError<const Config extends ResultConfig>(\n config: Config,\n reference: ResultFor<Config>,\n candidate: ResultFor<Config>,\n): number {\n const validReference = validateResult(config, reference);\n const validCandidate = validateResult(config, candidate);\n\n if (config.type === \"number\") {\n return (\n Math.abs((validReference as number) - (validCandidate as number)) /\n (config.max - config.min)\n );\n }\n\n return validReference === validCandidate ? 0 : 1;\n}\n\nexport function averageError<const Config extends ResultConfig>(\n config: Config,\n comparisons: readonly ResultComparison<ResultFor<Config>>[],\n): number {\n if (comparisons.length === 0) {\n throw new SwapAIError(\n \"invalid_result\",\n \"at least one held-out example is required to calculate average error\",\n );\n }\n\n const total = comparisons.reduce(\n (sum, comparison) =>\n sum + resultError(config, comparison.reference, comparison.candidate),\n 0,\n );\n\n return total / comparisons.length;\n}\n","import { createHash, randomUUID } from \"node:crypto\";\nimport { spawn } from \"node:child_process\";\nimport {\n chmod,\n copyFile,\n mkdir,\n readFile,\n readdir,\n rm,\n stat,\n writeFile,\n} from \"node:fs/promises\";\nimport { createInterface } from \"node:readline\";\nimport { dirname, join, resolve, sep } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { SwapAIError } from \"./errors.js\";\nimport {\n createNeedleTool,\n createTrainingLine,\n validateNeedleResult,\n type NeedleExample,\n type NeedleResultConfig,\n type NeedleResultValue,\n} from \"./needle.js\";\n\nexport const NEEDLE_VERSION = \"2.0.14\";\nconst UV_VERSION = \"0.11.4\";\nconst PYTHON_VERSION = \"3.12\";\n\nexport interface CommandOptions {\n readonly cwd?: string;\n readonly env?: NodeJS.ProcessEnv;\n readonly timeoutMs?: number;\n readonly stdin?: string;\n}\n\nexport type RunCommand = (\n command: string,\n args: readonly string[],\n options?: CommandOptions,\n) => Promise<{ readonly stdout: string; readonly stderr: string }>;\n\nexport interface NeedleChildProcess {\n readonly stdin: NodeJS.WritableStream;\n readonly stdout: NodeJS.ReadableStream;\n readonly stderr: NodeJS.ReadableStream;\n on(event: string, listener: (...args: any[]) => void): this;\n once(event: string, listener: (...args: any[]) => void): this;\n kill(signal?: NodeJS.Signals): boolean;\n}\n\nexport type NeedleSpawn = (\n command: string,\n args: readonly string[],\n options: { readonly cwd: string; readonly env: NodeJS.ProcessEnv },\n) => NeedleChildProcess;\n\nexport interface NeedleRuntimeDependencies {\n readonly runCommand?: RunCommand;\n readonly spawnProcess?: NeedleSpawn;\n readonly fetch?: typeof globalThis.fetch;\n readonly workerPath?: string;\n readonly requirementsPath?: string;\n}\n\nexport interface CreateNeedleRuntimeOptions {\n readonly dataDirectory: string;\n readonly onBackgroundError?: (error: NeedleRuntimeError) => void;\n readonly dependencies?: NeedleRuntimeDependencies;\n}\n\nexport interface TrainNeedleModelOptions {\n readonly classifierName: string;\n readonly generation: number;\n readonly expectedEpoch: number;\n readonly examples: readonly NeedleExample[];\n readonly resultConfig: NeedleResultConfig;\n readonly epochs?: number;\n}\n\nexport interface TrainedNeedleModel {\n readonly modelPath: string;\n readonly needleVersion: typeof NEEDLE_VERSION;\n}\n\nexport interface LoadNeedleModelOptions {\n readonly modelPath: string;\n readonly resultConfig: NeedleResultConfig;\n}\n\nexport interface LoadedNeedleModel {\n classify(input: string): Promise<NeedleResultValue>;\n close(): Promise<void>;\n}\n\nexport interface NeedleRuntime {\n ready(): Promise<void>;\n train(options: TrainNeedleModelOptions): Promise<TrainedNeedleModel>;\n loadModel(options: LoadNeedleModelOptions): Promise<LoadedNeedleModel>;\n clearClassifierArtifacts(classifierName: string): Promise<void>;\n clearClassifierGenerationArtifacts(\n classifierName: string,\n generation: number,\n ): Promise<void>;\n clearClassifierArtifactsThroughGeneration(\n classifierName: string,\n maximumGeneration: number,\n ): Promise<void>;\n close(): Promise<void>;\n}\n\nexport class NeedleRuntimeError extends SwapAIError {\n declare readonly code: \"service_unavailable\" | \"classification_failed\";\n\n constructor(\n code: \"service_unavailable\" | \"classification_failed\",\n message: string,\n cause?: unknown,\n ) {\n super(code, message, cause === undefined ? undefined : { cause });\n this.name = \"NeedleRuntimeError\";\n }\n}\n\nexport function createNeedleRuntime(\n options: CreateNeedleRuntimeOptions,\n): NeedleRuntime {\n return new ManagedNeedleRuntime(options);\n}\n\nclass ManagedNeedleRuntime implements NeedleRuntime {\n readonly #dataDirectory: string;\n readonly #runtimeDirectory: string;\n readonly #runCommand: RunCommand;\n readonly #spawnProcess: NeedleSpawn;\n readonly #fetch: typeof globalThis.fetch;\n readonly #workerPath: string;\n readonly #requirementsPath: string;\n readonly #onBackgroundError: ((error: NeedleRuntimeError) => void) | undefined;\n readonly #models = new Set<NeedleModelProcess>();\n #readyPromise: Promise<void> | undefined;\n #pythonPath: string | undefined;\n #environment: NodeJS.ProcessEnv | undefined;\n #closed = false;\n\n constructor(options: CreateNeedleRuntimeOptions) {\n this.#dataDirectory = resolve(options.dataDirectory);\n this.#runtimeDirectory = join(this.#dataDirectory, \"runtime\");\n this.#runCommand = options.dependencies?.runCommand ?? runCommand;\n this.#spawnProcess = options.dependencies?.spawnProcess ?? spawnProcess;\n this.#fetch = options.dependencies?.fetch ?? globalThis.fetch;\n this.#workerPath =\n options.dependencies?.workerPath ??\n fileURLToPath(new URL(\"../python/swapai_worker.py\", import.meta.url));\n this.#requirementsPath =\n options.dependencies?.requirementsPath ??\n fileURLToPath(new URL(\"../python/requirements.lock\", import.meta.url));\n this.#onBackgroundError = options.onBackgroundError;\n }\n\n ready(): Promise<void> {\n if (this.#closed) {\n return Promise.reject(\n new NeedleRuntimeError(\"service_unavailable\", \"Needle runtime is closed.\"),\n );\n }\n this.#readyPromise ??= this.#prepare().catch((error: unknown) => {\n this.#readyPromise = undefined;\n throw toRuntimeError(\"Could not prepare Needle.\", error);\n });\n return this.#readyPromise;\n }\n\n async train(options: TrainNeedleModelOptions): Promise<TrainedNeedleModel> {\n if (!Number.isSafeInteger(options.generation) || options.generation < 0) {\n throw new NeedleRuntimeError(\n \"service_unavailable\",\n \"Needle generation must be a non-negative integer.\",\n );\n }\n if (!Number.isSafeInteger(options.expectedEpoch) || options.expectedEpoch < 0) {\n throw new NeedleRuntimeError(\n \"service_unavailable\",\n \"Needle data epoch must be a non-negative integer.\",\n );\n }\n if (options.examples.length === 0) {\n throw new NeedleRuntimeError(\n \"service_unavailable\",\n \"Needle needs at least one training example.\",\n );\n }\n await this.ready();\n\n const classifierDirectory = join(\n this.#dataDirectory,\n \"classifiers\",\n classifierKey(options.classifierName),\n );\n const generationDirectory = join(\n classifierDirectory,\n `generation-${options.generation}`,\n );\n const checkpointDirectory = join(generationDirectory, \"checkpoints\");\n const candidateDirectory = join(\n generationDirectory,\n \"candidates\",\n randomUUID(),\n );\n const trainingPath = join(candidateDirectory, \"training.jsonl\");\n const modelPath = join(candidateDirectory, \"model.cact\");\n await mkdir(checkpointDirectory, { recursive: true, mode: 0o700 });\n await mkdir(candidateDirectory, { recursive: true, mode: 0o700 });\n\n const lines = options.examples.map((example) =>\n createTrainingLine(example.input, example.result, options.resultConfig),\n );\n const lockPath = join(\n this.#dataDirectory,\n \"locks\",\n `${createHash(\"sha256\").update(options.classifierName).digest(\"hex\")}.sqlite`,\n );\n\n try {\n await this.#runCommand(\n this.#pythonPath!,\n [\n this.#workerPath,\n \"train\",\n \"--training-data\",\n trainingPath,\n \"--output\",\n modelPath,\n \"--checkpoint-dir\",\n checkpointDirectory,\n \"--epochs\",\n String(options.epochs ?? 10),\n \"--artifact-lock-database\",\n lockPath,\n \"--main-database\",\n join(this.#dataDirectory, \"swapai.sqlite\"),\n \"--classifier-name\",\n options.classifierName,\n \"--expected-epoch\",\n String(options.expectedEpoch),\n ],\n {\n cwd: candidateDirectory,\n env: this.#environment!,\n timeoutMs: 6 * 60 * 60 * 1000,\n stdin: `${lines.join(\"\\n\")}\\n`,\n },\n );\n await stat(modelPath);\n } catch (error) {\n throw toRuntimeError(\"Needle training failed.\", error);\n }\n\n return { modelPath, needleVersion: NEEDLE_VERSION };\n }\n\n async loadModel(options: LoadNeedleModelOptions): Promise<LoadedNeedleModel> {\n await this.ready();\n try {\n await stat(options.modelPath);\n } catch (error) {\n throw toRuntimeError(`Needle model does not exist: ${options.modelPath}`, error);\n }\n\n const schemaPath = `${options.modelPath}.schema.json`;\n await writeFile(\n schemaPath,\n JSON.stringify([createNeedleTool(options.resultConfig)]),\n \"utf8\",\n );\n\n const process = this.#spawnProcess(\n this.#pythonPath!,\n [\n \"-u\",\n this.#workerPath,\n \"serve\",\n \"--model\",\n options.modelPath,\n \"--schema\",\n schemaPath,\n ],\n { cwd: dirname(options.modelPath), env: this.#environment! },\n );\n const model = new NeedleModelProcess(\n process,\n options.resultConfig,\n (error) => this.#onBackgroundError?.(error),\n () => this.#models.delete(model),\n );\n this.#models.add(model);\n try {\n await model.ready();\n return model;\n } catch (error) {\n this.#models.delete(model);\n process.kill(\"SIGTERM\");\n throw toRuntimeError(\"Needle model could not start.\", error);\n }\n }\n\n async clearClassifierArtifacts(classifierName: string): Promise<void> {\n await rm(\n join(this.#dataDirectory, \"classifiers\", classifierKey(classifierName)),\n { recursive: true, force: true },\n );\n }\n\n async clearClassifierGenerationArtifacts(\n classifierName: string,\n generation: number,\n ): Promise<void> {\n if (!Number.isSafeInteger(generation) || generation < 0) {\n throw new NeedleRuntimeError(\n \"service_unavailable\",\n \"Classifier generation must be a non-negative safe integer.\",\n );\n }\n const classifierDirectory = resolve(\n this.#dataDirectory,\n \"classifiers\",\n classifierKey(classifierName),\n );\n const generationDirectory = resolve(\n classifierDirectory,\n `generation-${generation}`,\n );\n if (!generationDirectory.startsWith(`${classifierDirectory}${sep}`)) {\n throw new NeedleRuntimeError(\n \"service_unavailable\",\n \"Classifier generation path is outside its classifier directory.\",\n );\n }\n await rm(generationDirectory, { recursive: true, force: true });\n }\n\n async clearClassifierArtifactsThroughGeneration(\n classifierName: string,\n maximumGeneration: number,\n ): Promise<void> {\n if (!Number.isSafeInteger(maximumGeneration) || maximumGeneration < 0) {\n throw new NeedleRuntimeError(\n \"service_unavailable\",\n \"Maximum classifier generation must be a non-negative safe integer.\",\n );\n }\n const classifierDirectory = join(\n this.#dataDirectory,\n \"classifiers\",\n classifierKey(classifierName),\n );\n let entries;\n try {\n entries = await readdir(classifierDirectory, { withFileTypes: true });\n } catch (error) {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return;\n }\n throw error;\n }\n await Promise.all(\n entries.map(async (entry) => {\n const match = /^generation-(\\d+)$/.exec(entry.name);\n if (!entry.isDirectory() || match === null) return;\n const generation = Number(match[1]);\n if (generation > maximumGeneration) return;\n await rm(join(classifierDirectory, entry.name), {\n recursive: true,\n force: true,\n });\n }),\n );\n }\n\n async close(): Promise<void> {\n if (this.#closed) return;\n this.#closed = true;\n await Promise.allSettled([...this.#models].map((model) => model.close()));\n this.#models.clear();\n }\n\n async #prepare(): Promise<void> {\n const installDirectory = join(\n this.#runtimeDirectory,\n `needle-${NEEDLE_VERSION}`,\n );\n const environmentDirectory = join(installDirectory, \".venv\");\n const markerPath = join(installDirectory, \"installed.json\");\n await mkdir(installDirectory, { recursive: true });\n\n const baseEnvironment = this.#makeEnvironment();\n const uvPath = await this.#findOrInstallUv(baseEnvironment);\n const pythonPath = pythonIn(environmentDirectory);\n const environment = this.#makeEnvironment(uvPath, environmentDirectory);\n\n if (!(await exists(pythonPath))) {\n await this.#runCommand(\n uvPath,\n [\"venv\", \"--python\", PYTHON_VERSION, environmentDirectory],\n { cwd: installDirectory, env: environment, timeoutMs: 15 * 60 * 1000 },\n );\n }\n\n const requirementsDigest = createHash(\"sha256\")\n .update(await readFile(this.#requirementsPath))\n .digest(\"hex\");\n const marker = await readJson(markerPath);\n let installRequired =\n marker?.needleVersion !== NEEDLE_VERSION ||\n marker.requirementsDigest !== requirementsDigest;\n let forceReinstall = false;\n const healthCheck = [\n \"-c\",\n `import needle, jax, flax, optax; assert needle.__version__ == \"${NEEDLE_VERSION}\"`,\n ] as const;\n\n if (!installRequired) {\n try {\n await this.#runCommand(pythonPath, healthCheck, {\n cwd: installDirectory,\n env: environment,\n timeoutMs: 60_000,\n });\n } catch {\n installRequired = true;\n forceReinstall = true;\n }\n }\n\n if (installRequired) {\n await this.#runCommand(\n uvPath,\n [\n \"pip\",\n \"install\",\n \"--python\",\n pythonPath,\n ...(forceReinstall ? [\"--reinstall\"] : []),\n \"--require-hashes\",\n \"--requirement\",\n this.#requirementsPath,\n ],\n { cwd: installDirectory, env: environment, timeoutMs: 30 * 60 * 1000 },\n );\n await this.#runCommand(pythonPath, healthCheck, {\n cwd: installDirectory,\n env: environment,\n timeoutMs: 60_000,\n });\n await writeFile(\n markerPath,\n JSON.stringify({ needleVersion: NEEDLE_VERSION, requirementsDigest }),\n \"utf8\",\n );\n }\n\n this.#pythonPath = pythonPath;\n this.#environment = environment;\n }\n\n #makeEnvironment(\n uvPath?: string,\n environmentDirectory?: string,\n ): NodeJS.ProcessEnv {\n const pathParts = [\n environmentDirectory ? dirname(pythonIn(environmentDirectory)) : undefined,\n uvPath ? dirname(uvPath) : undefined,\n process.env.PATH,\n ].filter((part): part is string => Boolean(part));\n return {\n ...process.env,\n PATH: pathParts.join(process.platform === \"win32\" ? \";\" : \":\"),\n PYTHONNOUSERSITE: \"1\",\n PYTHONUNBUFFERED: \"1\",\n NEEDLE_TELEMETRY: \"0\",\n DO_NOT_TRACK: \"1\",\n HF_HOME: join(this.#runtimeDirectory, \"huggingface\"),\n UV_CACHE_DIR: join(this.#runtimeDirectory, \"uv-cache\"),\n XDG_CACHE_HOME: join(this.#runtimeDirectory, \"cache\"),\n };\n }\n\n async #findOrInstallUv(environment: NodeJS.ProcessEnv): Promise<string> {\n const candidates = [process.env.SWAPAI_UV_PATH, \"uv\"].filter(\n (candidate): candidate is string => Boolean(candidate),\n );\n for (const candidate of candidates) {\n try {\n await this.#runCommand(candidate, [\"--version\"], {\n env: environment,\n timeoutMs: 30_000,\n });\n return candidate;\n } catch {\n // Try the managed copy next.\n }\n }\n\n const managed = join(\n this.#runtimeDirectory,\n \"tools\",\n process.platform === \"win32\" ? \"uv.exe\" : \"uv\",\n );\n if (!(await exists(managed))) {\n await this.#downloadUv(managed, environment);\n }\n await this.#runCommand(managed, [\"--version\"], {\n env: environment,\n timeoutMs: 30_000,\n });\n return managed;\n }\n\n async #downloadUv(\n destination: string,\n environment: NodeJS.ProcessEnv,\n ): Promise<void> {\n const asset = uvAsset();\n const toolsDirectory = dirname(destination);\n const archivePath = join(toolsDirectory, asset);\n const extractDirectory = join(toolsDirectory, `uv-${UV_VERSION}`);\n await mkdir(extractDirectory, { recursive: true });\n const release = `https://github.com/astral-sh/uv/releases/download/${UV_VERSION}`;\n\n const [archiveResponse, sumsResponse] = await Promise.all([\n this.#fetch(`${release}/${asset}`, {\n signal: AbortSignal.timeout(5 * 60 * 1000),\n }),\n this.#fetch(`${release}/sha256.sum`, {\n signal: AbortSignal.timeout(5 * 60 * 1000),\n }),\n ]);\n if (!archiveResponse.ok || !sumsResponse.ok) {\n throw new Error(`Could not download the managed uv ${UV_VERSION} binary.`);\n }\n const archive = Buffer.from(await archiveResponse.arrayBuffer());\n const sums = await sumsResponse.text();\n const expected = checksumFor(asset, sums);\n const actual = createHash(\"sha256\").update(archive).digest(\"hex\");\n if (actual !== expected) {\n throw new Error(\"The managed uv download failed its SHA-256 check.\");\n }\n await writeFile(archivePath, archive);\n await this.#runCommand(\n \"tar\",\n [asset.endsWith(\".tar.gz\") ? \"-xzf\" : \"-xf\", archivePath, \"-C\", extractDirectory],\n { env: environment, timeoutMs: 5 * 60 * 1000 },\n );\n const extracted = await findFile(\n extractDirectory,\n process.platform === \"win32\" ? \"uv.exe\" : \"uv\",\n );\n if (!extracted) throw new Error(\"The managed uv archive did not contain uv.\");\n await copyFile(extracted, destination);\n if (process.platform !== \"win32\") await chmod(destination, 0o755);\n }\n}\n\nclass NeedleModelProcess implements LoadedNeedleModel {\n readonly #process: NeedleChildProcess;\n readonly #resultConfig: NeedleResultConfig;\n readonly #onBackgroundError: (error: NeedleRuntimeError) => void;\n readonly #onClose: () => void;\n readonly #pending = new Map<\n number,\n {\n readonly resolve: (value: NeedleResultValue) => void;\n readonly reject: (error: NeedleRuntimeError) => void;\n }\n >();\n readonly #readyPromise: Promise<void>;\n readonly #exitPromise: Promise<void>;\n #resolveReady!: () => void;\n #rejectReady!: (error: NeedleRuntimeError) => void;\n #resolveExit!: () => void;\n #requestId = 0;\n #ready = false;\n #exited = false;\n #closing = false;\n #stderr = \"\";\n\n constructor(\n process: NeedleChildProcess,\n resultConfig: NeedleResultConfig,\n onBackgroundError: (error: NeedleRuntimeError) => void,\n onClose: () => void,\n ) {\n this.#process = process;\n this.#resultConfig = resultConfig;\n this.#onBackgroundError = onBackgroundError;\n this.#onClose = onClose;\n this.#readyPromise = new Promise((resolve, reject) => {\n this.#resolveReady = resolve;\n this.#rejectReady = reject;\n });\n this.#exitPromise = new Promise((resolve) => {\n this.#resolveExit = resolve;\n });\n this.#listen();\n }\n\n ready(): Promise<void> {\n return withTimeout(\n this.#readyPromise,\n 300_000,\n \"Needle did not become ready within five minutes.\",\n );\n }\n\n classify(input: string): Promise<NeedleResultValue> {\n if (!this.#ready || this.#closing || this.#exited) {\n return Promise.reject(\n new NeedleRuntimeError(\"service_unavailable\", \"Needle model is not running.\"),\n );\n }\n const id = ++this.#requestId;\n const result = new Promise<NeedleResultValue>((resolve, reject) => {\n this.#pending.set(id, { resolve, reject });\n this.#process.stdin.write(\n `${JSON.stringify({ id, type: \"classify\", input })}\\n`,\n (error?: Error | null) => {\n if (!error) return;\n this.#pending.delete(id);\n reject(\n new NeedleRuntimeError(\n \"service_unavailable\",\n \"Could not send input to Needle.\",\n error,\n ),\n );\n },\n );\n });\n return withTimeout(\n result,\n 60_000,\n \"Needle did not classify the input within one minute.\",\n () => this.#pending.delete(id),\n );\n }\n\n async close(): Promise<void> {\n if (this.#exited) return;\n if (!this.#closing) {\n this.#closing = true;\n this.#process.stdin.write(`${JSON.stringify({ type: \"close\" })}\\n`);\n }\n try {\n await withTimeout(this.#exitPromise, 5_000, \"Needle did not stop.\");\n } catch {\n this.#process.kill(\"SIGTERM\");\n try {\n await withTimeout(this.#exitPromise, 2_000, \"Needle ignored SIGTERM.\");\n } catch {\n this.#process.kill(\"SIGKILL\");\n await withTimeout(this.#exitPromise, 2_000, \"Needle ignored SIGKILL.\");\n }\n }\n }\n\n #listen(): void {\n const lines = createInterface({ input: this.#process.stdout });\n lines.on(\"line\", (line) => this.#handleLine(line));\n this.#process.stderr.on(\"data\", (chunk: Buffer | string) => {\n this.#stderr = `${this.#stderr}${chunk.toString()}`.slice(-16_384);\n });\n this.#process.once(\"error\", (error: Error) => {\n this.#fail(\n new NeedleRuntimeError(\"service_unavailable\", \"Needle process failed.\", error),\n );\n });\n this.#process.once(\n \"exit\",\n (code: number | null, signal: NodeJS.Signals | null) => {\n this.#exited = true;\n this.#resolveExit();\n this.#onClose();\n if (this.#closing && code === 0) {\n this.#ready = false;\n return;\n }\n const detail = this.#stderr.trim();\n this.#fail(\n new NeedleRuntimeError(\n \"service_unavailable\",\n `Needle stopped${code === null ? ` with ${signal ?? \"a signal\"}` : ` with code ${code}`}${detail ? `: ${detail}` : \".\"}`,\n ),\n );\n },\n );\n }\n\n #handleLine(line: string): void {\n let message: unknown;\n try {\n message = JSON.parse(line);\n } catch (error) {\n this.#fail(\n new NeedleRuntimeError(\n \"service_unavailable\",\n \"Needle returned invalid process data.\",\n error,\n ),\n );\n return;\n }\n if (!isRecord(message)) return;\n\n if (message.type === \"ready\") {\n if (message.needleVersion !== NEEDLE_VERSION) {\n this.#fail(\n new NeedleRuntimeError(\n \"service_unavailable\",\n `Needle ${NEEDLE_VERSION} is required; worker reported ${String(message.needleVersion)}.`,\n ),\n );\n return;\n }\n this.#ready = true;\n this.#resolveReady();\n return;\n }\n if (message.type === \"error\" && !this.#ready) {\n this.#fail(\n new NeedleRuntimeError(\n \"service_unavailable\",\n `Needle could not start: ${String(message.message ?? \"unknown error\")}`,\n ),\n );\n return;\n }\n if (typeof message.id !== \"number\") return;\n const pending = this.#pending.get(message.id);\n if (!pending) return;\n this.#pending.delete(message.id);\n\n if (message.ok !== true) {\n const workerError = isRecord(message.error)\n ? String(message.error.message ?? \"Needle classification failed.\")\n : \"Needle classification failed.\";\n pending.reject(\n new NeedleRuntimeError(\"classification_failed\", workerError),\n );\n return;\n }\n try {\n pending.resolve(validateNeedleResult(message.result, this.#resultConfig));\n } catch (error) {\n pending.reject(\n new NeedleRuntimeError(\n \"classification_failed\",\n \"Needle returned an invalid classification.\",\n error,\n ),\n );\n }\n }\n\n #fail(error: NeedleRuntimeError): void {\n const wasReady = this.#ready;\n this.#ready = false;\n if (!wasReady) this.#rejectReady(error);\n for (const pending of this.#pending.values()) pending.reject(error);\n this.#pending.clear();\n if (wasReady && !this.#closing) this.#onBackgroundError(error);\n if (!this.#exited && !this.#closing) this.#process.kill(\"SIGTERM\");\n }\n}\n\nconst spawnProcess: NeedleSpawn = (command, args, options) =>\n spawn(command, [...args], {\n cwd: options.cwd,\n env: options.env,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n\nconst runCommand: RunCommand = (command, args, options) =>\n new Promise((resolve, reject) => {\n const child = spawn(command, [...args], {\n cwd: options?.cwd,\n env: options?.env,\n stdio: [options?.stdin === undefined ? \"ignore\" : \"pipe\", \"pipe\", \"pipe\"],\n });\n if (options?.stdin !== undefined && child.stdin !== null) {\n child.stdin.on(\"error\", () => undefined);\n child.stdin.end(options.stdin, \"utf8\");\n }\n let stdout = \"\";\n let stderr = \"\";\n let timedOut = false;\n let settled = false;\n let forceKill: ReturnType<typeof setTimeout> | undefined;\n let rejectAfterKill: ReturnType<typeof setTimeout> | undefined;\n const timeout = options?.timeoutMs === undefined\n ? undefined\n : setTimeout(() => {\n timedOut = true;\n child.kill(\"SIGTERM\");\n forceKill = setTimeout(() => {\n child.kill(\"SIGKILL\");\n rejectAfterKill = setTimeout(() => {\n if (settled) return;\n settled = true;\n clearTimers();\n reject(new Error(`${command} exceeded its time limit.`));\n }, 2_000);\n rejectAfterKill.unref();\n }, 2_000);\n forceKill.unref();\n }, options.timeoutMs);\n timeout?.unref();\n const clearTimers = () => {\n if (timeout !== undefined) clearTimeout(timeout);\n if (forceKill !== undefined) clearTimeout(forceKill);\n if (rejectAfterKill !== undefined) clearTimeout(rejectAfterKill);\n };\n child.stdout!.on(\"data\", (chunk: Buffer | string) => {\n stdout = `${stdout}${chunk.toString()}`.slice(-262_144);\n });\n child.stderr!.on(\"data\", (chunk: Buffer | string) => {\n stderr = `${stderr}${chunk.toString()}`.slice(-262_144);\n });\n child.once(\"error\", (error) => {\n if (settled) return;\n settled = true;\n clearTimers();\n reject(error);\n });\n child.once(\"exit\", (code, signal) => {\n if (settled) return;\n settled = true;\n clearTimers();\n if (timedOut) {\n reject(new Error(`${command} exceeded its time limit.`));\n return;\n }\n if (code === 0) {\n resolve({ stdout, stderr });\n return;\n }\n reject(\n new Error(\n `${command} failed${code === null ? ` with ${signal ?? \"a signal\"}` : ` with code ${code}`}${stderr.trim() ? `: ${stderr.trim()}` : \".\"}`,\n ),\n );\n });\n });\n\nfunction classifierKey(name: string): string {\n const readable = name\n .normalize(\"NFKD\")\n .replace(/[^a-zA-Z0-9_-]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 40) || \"classifier\";\n const hash = createHash(\"sha256\").update(name).digest(\"hex\").slice(0, 12);\n return `${readable}-${hash}`;\n}\n\nfunction pythonIn(environmentDirectory: string): string {\n return process.platform === \"win32\"\n ? join(environmentDirectory, \"Scripts\", \"python.exe\")\n : join(environmentDirectory, \"bin\", \"python\");\n}\n\nasync function exists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readJson(path: string): Promise<Record<string, unknown> | undefined> {\n try {\n const value: unknown = JSON.parse(await readFile(path, \"utf8\"));\n return isRecord(value) ? value : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction uvAsset(): string {\n const key = `${process.platform}-${process.arch}`;\n const assets: Record<string, string> = {\n \"darwin-arm64\": \"uv-aarch64-apple-darwin.tar.gz\",\n \"darwin-x64\": \"uv-x86_64-apple-darwin.tar.gz\",\n \"linux-arm64\": \"uv-aarch64-unknown-linux-gnu.tar.gz\",\n \"linux-x64\": \"uv-x86_64-unknown-linux-gnu.tar.gz\",\n \"win32-arm64\": \"uv-aarch64-pc-windows-msvc.zip\",\n \"win32-x64\": \"uv-x86_64-pc-windows-msvc.zip\",\n };\n const asset = assets[key];\n if (!asset) throw new Error(`SwapAI does not support uv on ${key}.`);\n return asset;\n}\n\nfunction checksumFor(asset: string, sums: string): string {\n for (const line of sums.split(\"\\n\")) {\n const [hash, file] = line.trim().split(/\\s+\\*?/);\n if (file === asset && /^[a-f0-9]{64}$/i.test(hash ?? \"\")) return hash!;\n }\n throw new Error(`The uv checksum list did not contain ${asset}.`);\n}\n\nasync function findFile(directory: string, name: string): Promise<string | undefined> {\n for (const entry of await readdir(directory, { withFileTypes: true })) {\n const path = join(directory, entry.name);\n if (entry.isFile() && entry.name === name) return path;\n if (entry.isDirectory()) {\n const nested = await findFile(path, name);\n if (nested) return nested;\n }\n }\n return undefined;\n}\n\nfunction withTimeout<T>(\n promise: Promise<T>,\n milliseconds: number,\n message: string,\n onTimeout?: () => void,\n): Promise<T> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n onTimeout?.();\n reject(new NeedleRuntimeError(\"service_unavailable\", message));\n }, milliseconds);\n timer.unref();\n promise.then(\n (value) => {\n clearTimeout(timer);\n resolve(value);\n },\n (error) => {\n clearTimeout(timer);\n reject(error);\n },\n );\n });\n}\n\nfunction toRuntimeError(message: string, cause: unknown): NeedleRuntimeError {\n return cause instanceof NeedleRuntimeError\n ? cause\n : new NeedleRuntimeError(\"service_unavailable\", message, cause);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","export type NeedleResultConfig =\n | { readonly type: \"number\"; readonly min: number; readonly max: number }\n | { readonly type: \"boolean\" }\n | { readonly type: \"string\"; readonly values: readonly string[] };\n\nexport type NeedleResultValue = number | boolean | string;\n\nexport interface NeedleExample {\n readonly input: string;\n readonly result: NeedleResultValue;\n}\n\nexport interface NeedleTool {\n readonly name: \"classify\";\n readonly description: string;\n readonly parameters: {\n readonly type: \"object\";\n readonly properties: {\n readonly result: Record<string, unknown>;\n };\n readonly required: readonly [\"result\"];\n readonly additionalProperties: false;\n };\n}\n\nexport function createNeedleTool(config: NeedleResultConfig): NeedleTool {\n const description = \"The classification result.\";\n let result: Record<string, unknown>;\n\n switch (config.type) {\n case \"number\":\n result = {\n type: \"number\",\n minimum: config.min,\n maximum: config.max,\n description,\n };\n break;\n case \"boolean\":\n result = { type: \"boolean\", description };\n break;\n case \"string\":\n result = { type: \"string\", enum: [...config.values], description };\n break;\n }\n\n return {\n name: \"classify\",\n description: \"Classify every supplied input and always return the learned result.\",\n parameters: {\n type: \"object\",\n properties: { result },\n required: [\"result\"],\n additionalProperties: false,\n },\n };\n}\n\nexport function createTrainingLine(\n input: string,\n value: NeedleResultValue,\n config: NeedleResultConfig,\n): string {\n const result = validateNeedleResult(value, config);\n return JSON.stringify({\n query: input,\n tools: [createNeedleTool(config)],\n answers: [{ name: \"classify\", arguments: { result } }],\n });\n}\n\nexport function validateNeedleResult(\n value: unknown,\n config: NeedleResultConfig,\n): NeedleResultValue {\n switch (config.type) {\n case \"number\":\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n value < config.min ||\n value > config.max\n ) {\n throw new TypeError(\n `Needle returned a number outside ${config.min} to ${config.max}.`,\n );\n }\n return value;\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n throw new TypeError(\"Needle did not return a boolean result.\");\n }\n return value;\n case \"string\":\n if (typeof value !== \"string\" || !config.values.includes(value)) {\n throw new TypeError(\"Needle returned a value that is not an allowed string result.\");\n }\n return value;\n }\n}\n\nexport function readClassificationResult(\n response: unknown,\n config: NeedleResultConfig,\n): NeedleResultValue {\n if (!isRecord(response) || !Array.isArray(response.function_calls)) {\n throw new TypeError(\"Needle did not return exactly one classify call.\");\n }\n\n const calls = response.function_calls;\n const call = calls[0];\n if (\n calls.length !== 1 ||\n !isRecord(call) ||\n call.name !== \"classify\" ||\n !isRecord(call.arguments) ||\n !(\"result\" in call.arguments)\n ) {\n throw new TypeError(\"Needle did not return exactly one classify call.\");\n }\n\n return validateNeedleResult(call.arguments.result, config);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { createHash } from \"node:crypto\";\nimport { chmodSync, mkdirSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { join } from \"node:path\";\nimport type { DatabaseSync as DatabaseSyncType } from \"node:sqlite\";\n\nconst { DatabaseSync } = createRequire(import.meta.url)(\"node:sqlite\") as typeof import(\"node:sqlite\");\n\nexport type StoredResult = number | boolean | string;\nexport type ExampleSplit = \"training\" | \"held_out\";\nexport type GenerationStatus = \"active\" | \"archived\";\n\nexport interface OpenStorageOptions {\n dataDirectory: string;\n name: string;\n config: unknown;\n maxTrainingSet: number;\n}\n\nexport interface StoredExample {\n id: number;\n generation: number;\n input: string;\n result: StoredResult;\n split: ExampleSplit;\n createdAt: number;\n}\n\nexport interface StoredGeneration {\n generation: number;\n status: GenerationStatus;\n trained: boolean;\n modelPath: string | null;\n needleVersion: string | null;\n createdAt: number;\n archivedAt: number | null;\n}\n\nexport interface StorageSnapshot {\n name: string;\n config: unknown;\n activeGeneration: number;\n activeExampleCount: number;\n totalExamplesLogged: number;\n newExamplesSinceTraining: number;\n trainingAttempts: number;\n examplesUsedForTraining: number;\n localClassificationsSinceRetest: number;\n totalLocalClassifications: number;\n totalRetests: number;\n consecutiveRetestFailures: number;\n trained: boolean;\n modelPath: string | null;\n needleVersion: string | null;\n dataEpoch: number;\n clearPending: boolean;\n clearErased: boolean;\n clearArtifactGenerationMax: number | null;\n trainingLeaseOwner: string | null;\n trainingLeaseEpoch: number | null;\n trainingLeaseUntil: number | null;\n}\n\nexport interface PromotedModel {\n modelPath: string;\n needleVersion: string;\n}\n\nexport interface Storage {\n readonly databasePath: string;\n snapshot(): StorageSnapshot;\n addExample(\n input: string,\n result: StoredResult,\n expectedDataEpoch?: number,\n ): StoredExample | null;\n listExamples(split?: ExampleSplit, generation?: number): StoredExample[];\n listExamplesForTraining(\n split: ExampleSplit,\n generation: number,\n expectedDataEpoch: number,\n ): StoredExample[] | null;\n markTrainingAttempted(exampleCount: number, expectedDataEpoch?: number): boolean;\n promoteGeneration(\n model: PromotedModel,\n expectedDataEpoch?: number,\n ): StoredGeneration | null;\n recordLocalClassification(expectedDataEpoch?: number): number | null;\n recordRetest(passed: boolean, expectedDataEpoch?: number): number | null;\n claimTrainingLease(\n owner: string,\n durationMs: number,\n expectedDataEpoch?: number,\n ): boolean;\n releaseTrainingLease(owner: string): void;\n archiveAndReset(expectedDataEpoch?: number): StoredGeneration | null;\n beginClearTrainingData(): number;\n eraseTrainingData(dataEpoch: number): StoredGeneration | null;\n finishClearTrainingData(dataEpoch: number): boolean;\n clearTrainingData(): StoredGeneration;\n claimArtifactWriteLock(): boolean;\n releaseArtifactWriteLock(): void;\n listGenerations(): StoredGeneration[];\n close(): void;\n}\n\ninterface ClassifierRow {\n name: string;\n config_json: string;\n active_generation: number;\n total_examples_logged: number;\n new_examples_since_training: number;\n training_attempts: number;\n examples_used_for_training: number;\n local_classifications_since_retest: number;\n total_local_classifications: number;\n total_retests: number;\n consecutive_retest_failures: number;\n trained: number;\n model_path: string | null;\n needle_version: string | null;\n active_example_count: number;\n data_epoch: number;\n clear_pending: number;\n clear_erased: number;\n clear_artifact_generation_max: number | null;\n training_lease_owner: string | null;\n training_lease_epoch: number | null;\n training_lease_until: number | null;\n}\n\ninterface ExampleRow {\n id: number;\n generation: number;\n input: string;\n result_json: string;\n split: ExampleSplit;\n created_at: number;\n}\n\ninterface GenerationRow {\n generation: number;\n status: GenerationStatus;\n trained: number;\n model_path: string | null;\n needle_version: string | null;\n created_at: number;\n archived_at: number | null;\n}\n\nconst SCHEMA = `\n CREATE TABLE IF NOT EXISTS classifiers (\n name TEXT PRIMARY KEY,\n config_json TEXT NOT NULL,\n max_training_set INTEGER NOT NULL,\n active_generation INTEGER NOT NULL DEFAULT 1,\n total_examples_logged INTEGER NOT NULL DEFAULT 0,\n new_examples_since_training INTEGER NOT NULL DEFAULT 0,\n training_attempts INTEGER NOT NULL DEFAULT 0,\n examples_used_for_training INTEGER NOT NULL DEFAULT 0,\n local_classifications_since_retest INTEGER NOT NULL DEFAULT 0,\n total_local_classifications INTEGER NOT NULL DEFAULT 0,\n total_retests INTEGER NOT NULL DEFAULT 0,\n consecutive_retest_failures INTEGER NOT NULL DEFAULT 0,\n training_lease_owner TEXT,\n training_lease_until INTEGER,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n data_epoch INTEGER NOT NULL DEFAULT 0,\n clear_pending INTEGER NOT NULL DEFAULT 0,\n clear_erased INTEGER NOT NULL DEFAULT 0,\n clear_artifact_generation_max INTEGER,\n training_lease_epoch INTEGER\n );\n\n CREATE TABLE IF NOT EXISTS generations (\n classifier_name TEXT NOT NULL,\n generation INTEGER NOT NULL,\n status TEXT NOT NULL CHECK (status IN ('active', 'archived')),\n trained INTEGER NOT NULL DEFAULT 0,\n model_path TEXT,\n needle_version TEXT,\n created_at INTEGER NOT NULL,\n archived_at INTEGER,\n PRIMARY KEY (classifier_name, generation),\n FOREIGN KEY (classifier_name) REFERENCES classifiers(name) ON DELETE CASCADE\n );\n\n CREATE TABLE IF NOT EXISTS examples (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n classifier_name TEXT NOT NULL,\n generation INTEGER NOT NULL,\n input TEXT NOT NULL,\n result_json TEXT NOT NULL,\n split TEXT NOT NULL CHECK (split IN ('training', 'held_out')),\n created_at INTEGER NOT NULL,\n FOREIGN KEY (classifier_name, generation)\n REFERENCES generations(classifier_name, generation) ON DELETE CASCADE\n );\n\n CREATE INDEX IF NOT EXISTS examples_by_generation\n ON examples(classifier_name, generation, id);\n CREATE INDEX IF NOT EXISTS examples_by_split\n ON examples(classifier_name, generation, split, id);\n\n CREATE TRIGGER IF NOT EXISTS swapai_v2_classifiers_insert\n BEFORE INSERT ON classifiers\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n CREATE TRIGGER IF NOT EXISTS swapai_v2_classifiers_update\n BEFORE UPDATE ON classifiers\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n CREATE TRIGGER IF NOT EXISTS swapai_v2_classifiers_delete\n BEFORE DELETE ON classifiers\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n CREATE TRIGGER IF NOT EXISTS swapai_v2_generations_insert\n BEFORE INSERT ON generations\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n CREATE TRIGGER IF NOT EXISTS swapai_v2_generations_update\n BEFORE UPDATE ON generations\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n CREATE TRIGGER IF NOT EXISTS swapai_v2_generations_delete\n BEFORE DELETE ON generations\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n CREATE TRIGGER IF NOT EXISTS swapai_v2_examples_insert\n BEFORE INSERT ON examples\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n CREATE TRIGGER IF NOT EXISTS swapai_v2_examples_update\n BEFORE UPDATE ON examples\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n CREATE TRIGGER IF NOT EXISTS swapai_v2_examples_delete\n BEFORE DELETE ON examples\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n`;\n\nexport function assignExampleSplit(name: string, input: string): ExampleSplit {\n const hash = createHash(\"sha256\")\n .update(name)\n .update(\"\\0\")\n .update(input)\n .digest();\n\n return hash.readUInt32BE(0) % 10 < 8 ? \"training\" : \"held_out\";\n}\n\nexport function openStorage(options: OpenStorageOptions): Storage {\n if (!Number.isSafeInteger(options.maxTrainingSet) || options.maxTrainingSet <= 0) {\n throw new TypeError(\"maxTrainingSet must be a positive integer\");\n }\n\n mkdirSync(options.dataDirectory, { recursive: true, mode: 0o700 });\n chmodSync(options.dataDirectory, 0o700);\n const databasePath = join(options.dataDirectory, \"swapai.sqlite\");\n const database = new DatabaseSync(databasePath);\n let artifactLockDatabase: DatabaseSyncType | null = null;\n try {\n database.function(\n \"swapai_writer_version\",\n { deterministic: true },\n () => 2,\n );\n chmodSync(databasePath, 0o600);\n database.exec(\"PRAGMA journal_mode = WAL\");\n database.exec(\"PRAGMA foreign_keys = ON\");\n database.exec(\"PRAGMA secure_delete = ON\");\n database.exec(\"PRAGMA busy_timeout = 5000\");\n const secureDelete = requiredRow<{ secure_delete: number }>(\n database.prepare(\"PRAGMA secure_delete\").get(),\n );\n if (secureDelete.secure_delete !== 1) {\n throw new Error(\"SQLite secure deletion could not be enabled\");\n }\n database.exec(SCHEMA);\n migrateClassifierColumns(database);\n const lockDirectory = join(options.dataDirectory, \"locks\");\n mkdirSync(lockDirectory, { recursive: true, mode: 0o700 });\n chmodSync(lockDirectory, 0o700);\n const lockPath = join(\n lockDirectory,\n `${createHash(\"sha256\").update(options.name).digest(\"hex\")}.sqlite`,\n );\n artifactLockDatabase = new DatabaseSync(lockPath);\n chmodSync(lockPath, 0o600);\n artifactLockDatabase.exec(\"PRAGMA busy_timeout = 0\");\n artifactLockDatabase.exec(\n \"CREATE TABLE IF NOT EXISTS artifact_lock (id INTEGER PRIMARY KEY)\",\n );\n\n const now = Date.now();\n const configJson = stringifyJson(options.config, \"classifier config\");\n const existing = database.prepare(`\n SELECT config_json FROM classifiers WHERE name = ?\n `).get(options.name) as { config_json: string } | undefined;\n\n if (\n existing !== undefined\n && criticalConfigJson(existing.config_json) !== criticalConfigJson(configJson)\n ) {\n throw new TypeError(\n `Classifier \"${options.name}\" already exists with different result or behavior settings`,\n );\n }\n\n transaction(database, () => {\n database.prepare(`\n INSERT INTO classifiers (\n name, config_json, max_training_set, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?)\n ON CONFLICT(name) DO UPDATE SET\n config_json = excluded.config_json,\n max_training_set = excluded.max_training_set,\n updated_at = excluded.updated_at\n `).run(options.name, configJson, options.maxTrainingSet, now, now);\n\n database.prepare(`\n INSERT OR IGNORE INTO generations (\n classifier_name, generation, status, created_at\n ) VALUES (?, 1, 'active', ?)\n `).run(options.name, now);\n\n trimExamples(\n database,\n options.name,\n activeGeneration(database, options.name),\n options.maxTrainingSet,\n );\n });\n } catch (error) {\n try {\n artifactLockDatabase?.close();\n } catch {\n // Preserve the initialization error after attempting to close both handles.\n }\n try {\n database.close();\n } catch {\n // Preserve the initialization error after attempting to close both handles.\n }\n throw error;\n }\n\n const initializedArtifactLockDatabase = artifactLockDatabase;\n\n let closed = false;\n let artifactLockHeld = false;\n\n const storage: Storage = {\n databasePath,\n\n snapshot() {\n assertOpen(closed);\n const row = requiredRow<ClassifierRow>(database.prepare(`\n SELECT\n c.name,\n c.config_json,\n c.active_generation,\n c.total_examples_logged,\n c.new_examples_since_training,\n c.training_attempts,\n c.examples_used_for_training,\n c.local_classifications_since_retest,\n c.total_local_classifications,\n c.total_retests,\n c.consecutive_retest_failures,\n g.trained,\n g.model_path,\n g.needle_version,\n c.data_epoch,\n c.clear_pending,\n c.clear_erased,\n c.clear_artifact_generation_max,\n c.training_lease_owner,\n c.training_lease_epoch,\n c.training_lease_until,\n (\n SELECT COUNT(*)\n FROM examples e\n WHERE e.classifier_name = c.name\n AND e.generation = c.active_generation\n ) AS active_example_count\n FROM classifiers c\n JOIN generations g\n ON g.classifier_name = c.name\n AND g.generation = c.active_generation\n WHERE c.name = ?\n `).get(options.name));\n\n return {\n name: row.name,\n config: JSON.parse(row.config_json) as unknown,\n activeGeneration: row.active_generation,\n activeExampleCount: row.active_example_count,\n totalExamplesLogged: row.total_examples_logged,\n newExamplesSinceTraining: row.new_examples_since_training,\n trainingAttempts: row.training_attempts,\n examplesUsedForTraining: row.examples_used_for_training,\n localClassificationsSinceRetest: row.local_classifications_since_retest,\n totalLocalClassifications: row.total_local_classifications,\n totalRetests: row.total_retests,\n consecutiveRetestFailures: row.consecutive_retest_failures,\n trained: row.trained === 1,\n modelPath: row.model_path,\n needleVersion: row.needle_version,\n dataEpoch: row.data_epoch,\n clearPending: row.clear_pending === 1,\n clearErased: row.clear_erased === 1,\n clearArtifactGenerationMax: row.clear_artifact_generation_max,\n trainingLeaseOwner: row.training_lease_owner,\n trainingLeaseEpoch: row.training_lease_epoch,\n trainingLeaseUntil: row.training_lease_until,\n };\n },\n\n addExample(input, result, expectedDataEpoch) {\n assertOpen(closed);\n const split = assignExampleSplit(options.name, input);\n const createdAt = Date.now();\n const resultJson = stringifyJson(result, \"classification result\");\n let id = 0;\n let generation = 0;\n let accepted = false;\n\n transaction(database, () => {\n const state = classifierState(database, options.name);\n const epoch = expectedDataEpoch ?? state.data_epoch;\n if (state.data_epoch !== epoch || state.clear_pending === 1) return;\n generation = state.active_generation;\n const insertion = database.prepare(`\n INSERT INTO examples (\n classifier_name, generation, input, result_json, split, created_at\n ) VALUES (?, ?, ?, ?, ?, ?)\n `).run(options.name, generation, input, resultJson, split, createdAt);\n id = Number(insertion.lastInsertRowid);\n accepted = true;\n\n database.prepare(`\n UPDATE classifiers\n SET total_examples_logged = total_examples_logged + 1,\n new_examples_since_training = new_examples_since_training + 1,\n updated_at = ?\n WHERE name = ?\n `).run(createdAt, options.name);\n\n trimExamples(database, options.name, generation, options.maxTrainingSet);\n });\n\n return accepted\n ? { id, generation, input, result, split, createdAt }\n : null;\n },\n\n listExamples(split, generation) {\n assertOpen(closed);\n const selectedGeneration = generation ?? activeGeneration(database, options.name);\n const rows = split === undefined\n ? database.prepare(`\n SELECT id, generation, input, result_json, split, created_at\n FROM examples\n WHERE classifier_name = ? AND generation = ?\n ORDER BY id\n `).all(options.name, selectedGeneration)\n : database.prepare(`\n SELECT id, generation, input, result_json, split, created_at\n FROM examples\n WHERE classifier_name = ? AND generation = ? AND split = ?\n ORDER BY id\n `).all(options.name, selectedGeneration, split);\n\n return rows.map((value) => mapExample(row<ExampleRow>(value)));\n },\n\n listExamplesForTraining(split, generation, expectedDataEpoch) {\n assertOpen(closed);\n let examples: StoredExample[] | null = null;\n transaction(database, () => {\n const state = classifierState(database, options.name);\n if (\n state.data_epoch !== expectedDataEpoch ||\n state.clear_pending === 1 ||\n state.active_generation !== generation\n ) {\n return;\n }\n examples = database.prepare(`\n SELECT id, generation, input, result_json, split, created_at\n FROM examples\n WHERE classifier_name = ? AND generation = ? AND split = ?\n ORDER BY id\n `).all(options.name, generation, split).map((value) =>\n mapExample(row<ExampleRow>(value)),\n );\n });\n return examples;\n },\n\n markTrainingAttempted(exampleCount, expectedDataEpoch) {\n assertOpen(closed);\n if (!Number.isSafeInteger(exampleCount) || exampleCount <= 0) {\n throw new TypeError(\"training example count must be a positive integer\");\n }\n const epoch = expectedDataEpoch ?? storage.snapshot().dataEpoch;\n const result = database.prepare(`\n UPDATE classifiers\n SET new_examples_since_training = 0,\n training_attempts = training_attempts + 1,\n examples_used_for_training = ?,\n updated_at = ?\n WHERE name = ? AND data_epoch = ? AND clear_pending = 0\n `).run(exampleCount, Date.now(), options.name, epoch);\n return result.changes === 1;\n },\n\n promoteGeneration(model, expectedDataEpoch) {\n assertOpen(closed);\n let generation = 0;\n let promoted = false;\n transaction(database, () => {\n const state = classifierState(database, options.name);\n const epoch = expectedDataEpoch ?? state.data_epoch;\n if (state.data_epoch !== epoch || state.clear_pending === 1) return;\n generation = state.active_generation;\n database.prepare(`\n UPDATE generations\n SET trained = 1, model_path = ?, needle_version = ?\n WHERE classifier_name = ? AND generation = ?\n `).run(model.modelPath, model.needleVersion, options.name, generation);\n promoted = true;\n });\n return promoted\n ? generationByNumber(database, options.name, generation)\n : null;\n },\n\n recordLocalClassification(expectedDataEpoch) {\n assertOpen(closed);\n const epoch = expectedDataEpoch ?? storage.snapshot().dataEpoch;\n const result = database.prepare(`\n UPDATE classifiers\n SET local_classifications_since_retest = local_classifications_since_retest + 1,\n total_local_classifications = total_local_classifications + 1,\n updated_at = ?\n WHERE name = ? AND data_epoch = ? AND clear_pending = 0\n `).run(Date.now(), options.name, epoch);\n if (result.changes !== 1) return null;\n return storage.snapshot().localClassificationsSinceRetest;\n },\n\n recordRetest(passed, expectedDataEpoch) {\n assertOpen(closed);\n const epoch = expectedDataEpoch ?? storage.snapshot().dataEpoch;\n const result = database.prepare(`\n UPDATE classifiers\n SET local_classifications_since_retest = 0,\n total_retests = total_retests + 1,\n consecutive_retest_failures = CASE\n WHEN ? = 1 THEN 0\n ELSE consecutive_retest_failures + 1\n END,\n updated_at = ?\n WHERE name = ? AND data_epoch = ? AND clear_pending = 0\n `).run(passed ? 1 : 0, Date.now(), options.name, epoch);\n if (result.changes !== 1) return null;\n return storage.snapshot().consecutiveRetestFailures;\n },\n\n claimTrainingLease(owner, durationMs, expectedDataEpoch) {\n assertOpen(closed);\n if (owner.trim() === \"\" || !Number.isSafeInteger(durationMs) || durationMs <= 0) {\n throw new TypeError(\"training lease needs an owner and positive duration\");\n }\n const now = Date.now();\n const epoch = expectedDataEpoch ?? storage.snapshot().dataEpoch;\n const result = database.prepare(`\n UPDATE classifiers\n SET training_lease_owner = ?,\n training_lease_until = ?,\n training_lease_epoch = ?,\n updated_at = ?\n WHERE name = ?\n AND data_epoch = ?\n AND clear_pending = 0\n AND (\n training_lease_owner IS NULL\n OR training_lease_until <= ?\n OR training_lease_owner = ?\n )\n `).run(owner, now + durationMs, epoch, now, options.name, epoch, now, owner);\n return result.changes === 1;\n },\n\n releaseTrainingLease(owner) {\n assertOpen(closed);\n database.prepare(`\n UPDATE classifiers\n SET training_lease_owner = NULL,\n training_lease_until = NULL,\n training_lease_epoch = NULL,\n updated_at = ?\n WHERE name = ? AND training_lease_owner = ?\n `).run(Date.now(), options.name, owner);\n },\n\n archiveAndReset(expectedDataEpoch) {\n assertOpen(closed);\n let nextGeneration = 0;\n const changedAt = Date.now();\n let reset = false;\n\n transaction(database, () => {\n const state = classifierState(database, options.name);\n const epoch = expectedDataEpoch ?? state.data_epoch;\n if (state.data_epoch !== epoch || state.clear_pending === 1) return;\n const currentGeneration = state.active_generation;\n database.prepare(`\n UPDATE generations\n SET status = 'archived', archived_at = ?\n WHERE classifier_name = ? AND generation = ?\n `).run(changedAt, options.name, currentGeneration);\n\n const maximum = requiredRow<{ maximum: number }>(database.prepare(`\n SELECT MAX(generation) AS maximum\n FROM generations\n WHERE classifier_name = ?\n `).get(options.name));\n nextGeneration = maximum.maximum + 1;\n\n database.prepare(`\n INSERT INTO generations (\n classifier_name, generation, status, created_at\n ) VALUES (?, ?, 'active', ?)\n `).run(options.name, nextGeneration, changedAt);\n\n database.prepare(`\n UPDATE classifiers\n SET active_generation = ?,\n data_epoch = data_epoch + 1,\n new_examples_since_training = 0,\n training_attempts = 0,\n examples_used_for_training = 0,\n training_lease_owner = NULL,\n training_lease_until = NULL,\n training_lease_epoch = NULL,\n local_classifications_since_retest = 0,\n consecutive_retest_failures = 0,\n updated_at = ?\n WHERE name = ?\n `).run(nextGeneration, changedAt, options.name);\n reset = true;\n });\n\n return reset\n ? generationByNumber(database, options.name, nextGeneration)\n : null;\n },\n\n beginClearTrainingData() {\n assertOpen(closed);\n database.prepare(`\n UPDATE classifiers\n SET data_epoch = data_epoch + 1,\n clear_pending = 1,\n clear_erased = 0,\n clear_artifact_generation_max = (\n SELECT MAX(generation)\n FROM generations\n WHERE classifier_name = ?\n ),\n updated_at = ?\n WHERE name = ?\n `).run(options.name, Date.now(), options.name);\n return classifierState(database, options.name).data_epoch;\n },\n\n eraseTrainingData(dataEpoch) {\n assertOpen(closed);\n let nextGeneration = 0;\n const changedAt = Date.now();\n let erased = false;\n\n transaction(database, () => {\n const state = classifierState(database, options.name);\n if (state.data_epoch !== dataEpoch || state.clear_pending !== 1) return;\n if (state.clear_erased === 1) return;\n const maximum = requiredRow<{ maximum: number }>(database.prepare(`\n SELECT MAX(generation) AS maximum\n FROM generations\n WHERE classifier_name = ?\n `).get(options.name));\n nextGeneration = maximum.maximum + 1;\n\n database.prepare(`\n DELETE FROM examples WHERE classifier_name = ?\n `).run(options.name);\n database.prepare(`\n DELETE FROM generations WHERE classifier_name = ?\n `).run(options.name);\n database.prepare(`\n INSERT INTO generations (\n classifier_name, generation, status, created_at\n ) VALUES (?, ?, 'active', ?)\n `).run(options.name, nextGeneration, changedAt);\n database.prepare(`\n UPDATE classifiers\n SET active_generation = ?,\n total_examples_logged = 0,\n new_examples_since_training = 0,\n training_attempts = 0,\n examples_used_for_training = 0,\n local_classifications_since_retest = 0,\n total_local_classifications = 0,\n total_retests = 0,\n consecutive_retest_failures = 0,\n training_lease_owner = NULL,\n training_lease_until = NULL,\n training_lease_epoch = NULL,\n clear_erased = 1,\n updated_at = ?\n WHERE name = ?\n `).run(nextGeneration, changedAt, options.name);\n erased = true;\n });\n\n if (!erased) return null;\n\n truncateWriteAheadLog(database);\n\n return generationByNumber(database, options.name, nextGeneration);\n },\n\n finishClearTrainingData(dataEpoch) {\n assertOpen(closed);\n const state = classifierState(database, options.name);\n if (\n state.data_epoch !== dataEpoch ||\n state.clear_pending !== 1 ||\n state.clear_erased !== 1\n ) {\n return false;\n }\n truncateWriteAheadLog(database);\n const result = database.prepare(`\n UPDATE classifiers\n SET clear_pending = 0, updated_at = ?\n WHERE name = ?\n AND data_epoch = ?\n AND clear_pending = 1\n AND clear_erased = 1\n `).run(Date.now(), options.name, dataEpoch);\n return result.changes === 1;\n },\n\n clearTrainingData() {\n const dataEpoch = storage.beginClearTrainingData();\n if (!storage.claimArtifactWriteLock()) {\n throw new Error(\"Classifier artifacts are currently being written\");\n }\n try {\n const generation = storage.eraseTrainingData(dataEpoch);\n if (generation === null || !storage.finishClearTrainingData(dataEpoch)) {\n throw new Error(\"Training data clear was superseded\");\n }\n return generation;\n } finally {\n storage.releaseArtifactWriteLock();\n }\n },\n\n claimArtifactWriteLock() {\n assertOpen(closed);\n if (artifactLockHeld) return true;\n try {\n initializedArtifactLockDatabase.exec(\"BEGIN IMMEDIATE\");\n artifactLockHeld = true;\n return true;\n } catch (error) {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"ERR_SQLITE_ERROR\" &&\n \"message\" in error &&\n typeof error.message === \"string\" &&\n /locked|busy/i.test(error.message)\n ) {\n return false;\n }\n throw error;\n }\n },\n\n releaseArtifactWriteLock() {\n assertOpen(closed);\n if (!artifactLockHeld) return;\n initializedArtifactLockDatabase.exec(\"COMMIT\");\n artifactLockHeld = false;\n },\n\n listGenerations() {\n assertOpen(closed);\n return database.prepare(`\n SELECT\n generation, status, trained, model_path, needle_version,\n created_at, archived_at\n FROM generations\n WHERE classifier_name = ?\n ORDER BY generation\n `).all(options.name).map((value) => mapGeneration(row<GenerationRow>(value)));\n },\n\n close() {\n if (closed) {\n return;\n }\n if (artifactLockHeld) {\n initializedArtifactLockDatabase.exec(\"ROLLBACK\");\n artifactLockHeld = false;\n }\n initializedArtifactLockDatabase.close();\n closed = true;\n database.close();\n },\n };\n\n return storage;\n}\n\nfunction activeGeneration(database: DatabaseSyncType, name: string): number {\n const active = requiredRow<{ active_generation: number }>(database.prepare(`\n SELECT active_generation FROM classifiers WHERE name = ?\n `).get(name));\n return active.active_generation;\n}\n\nfunction truncateWriteAheadLog(database: DatabaseSyncType): void {\n database.exec(\"PRAGMA busy_timeout = 0\");\n let checkpoint: { busy: number; log: number; checkpointed: number };\n try {\n checkpoint = requiredRow<{\n busy: number;\n log: number;\n checkpointed: number;\n }>(database.prepare(\"PRAGMA wal_checkpoint(TRUNCATE)\").get());\n } finally {\n database.exec(\"PRAGMA busy_timeout = 5000\");\n }\n if (checkpoint.busy !== 0) {\n throw new Error(\n \"SQLite WAL could not be truncated after clearing training data\",\n );\n }\n}\n\nfunction classifierState(\n database: DatabaseSyncType,\n name: string,\n): {\n active_generation: number;\n data_epoch: number;\n clear_pending: number;\n clear_erased: number;\n clear_artifact_generation_max: number | null;\n training_lease_owner: string | null;\n training_lease_epoch: number | null;\n training_lease_until: number | null;\n} {\n return requiredRow(database.prepare(`\n SELECT\n active_generation,\n data_epoch,\n clear_pending,\n clear_erased,\n clear_artifact_generation_max,\n training_lease_owner,\n training_lease_epoch,\n training_lease_until\n FROM classifiers\n WHERE name = ?\n `).get(name));\n}\n\nfunction migrateClassifierColumns(database: DatabaseSyncType): void {\n transaction(database, () => {\n const columns = new Set(\n database.prepare(\"PRAGMA table_info(classifiers)\").all().map((value) =>\n row<{ name: string }>(value).name,\n ),\n );\n if (!columns.has(\"data_epoch\")) {\n database.exec(\n \"ALTER TABLE classifiers ADD COLUMN data_epoch INTEGER NOT NULL DEFAULT 0\",\n );\n }\n if (!columns.has(\"clear_pending\")) {\n database.exec(\n \"ALTER TABLE classifiers ADD COLUMN clear_pending INTEGER NOT NULL DEFAULT 0\",\n );\n }\n if (!columns.has(\"clear_erased\")) {\n database.exec(\n \"ALTER TABLE classifiers ADD COLUMN clear_erased INTEGER NOT NULL DEFAULT 0\",\n );\n }\n if (!columns.has(\"clear_artifact_generation_max\")) {\n database.exec(\n \"ALTER TABLE classifiers ADD COLUMN clear_artifact_generation_max INTEGER\",\n );\n }\n if (!columns.has(\"training_lease_epoch\")) {\n database.exec(\n \"ALTER TABLE classifiers ADD COLUMN training_lease_epoch INTEGER\",\n );\n }\n });\n}\n\nfunction generationByNumber(\n database: DatabaseSyncType,\n name: string,\n generation: number,\n): StoredGeneration {\n const stored = requiredRow<GenerationRow>(database.prepare(`\n SELECT\n generation, status, trained, model_path, needle_version,\n created_at, archived_at\n FROM generations\n WHERE classifier_name = ? AND generation = ?\n `).get(name, generation));\n return mapGeneration(stored);\n}\n\nfunction trimExamples(\n database: DatabaseSyncType,\n name: string,\n generation: number,\n maxTrainingSet: number,\n): void {\n database.prepare(`\n DELETE FROM examples\n WHERE classifier_name = ?\n AND generation = ?\n AND id NOT IN (\n SELECT id\n FROM examples\n WHERE classifier_name = ? AND generation = ?\n ORDER BY id DESC\n LIMIT ?\n )\n `).run(name, generation, name, generation, maxTrainingSet);\n}\n\nfunction mapExample(stored: ExampleRow): StoredExample {\n return {\n id: stored.id,\n generation: stored.generation,\n input: stored.input,\n result: JSON.parse(stored.result_json) as StoredResult,\n split: stored.split,\n createdAt: stored.created_at,\n };\n}\n\nfunction mapGeneration(stored: GenerationRow): StoredGeneration {\n return {\n generation: stored.generation,\n status: stored.status,\n trained: stored.trained === 1,\n modelPath: stored.model_path,\n needleVersion: stored.needle_version,\n createdAt: stored.created_at,\n archivedAt: stored.archived_at,\n };\n}\n\nfunction transaction(database: DatabaseSyncType, action: () => void): void {\n database.exec(\"BEGIN IMMEDIATE\");\n try {\n action();\n database.exec(\"COMMIT\");\n } catch (error) {\n database.exec(\"ROLLBACK\");\n throw error;\n }\n}\n\nfunction stringifyJson(value: unknown, description: string): string {\n const serialized = JSON.stringify(value);\n if (serialized === undefined) {\n throw new TypeError(`${description} must be JSON serializable`);\n }\n return serialized;\n}\n\nfunction criticalConfigJson(configJson: string): string {\n const config = JSON.parse(configJson) as unknown;\n if (!isRecord(config)) {\n throw new TypeError(\"classifier config must be an object\");\n }\n\n const critical: Record<string, unknown> = {};\n for (const key of [\n \"result\",\n \"retrainOnCount\",\n \"acceptableError\",\n \"retestInterval\",\n \"retestRevertOn\",\n \"model\",\n ]) {\n if (Object.hasOwn(config, key)) {\n critical[key] = config[key];\n }\n }\n\n if (typeof critical.acceptableError === \"string\") {\n const percentage = /^(\\d+(?:\\.\\d+)?)%$/.exec(critical.acceptableError);\n if (percentage !== null) {\n critical.acceptableError = Number(percentage[1]) / 100;\n }\n }\n\n if (isRecord(critical.result) && Array.isArray(critical.result.values)) {\n critical.result = {\n ...critical.result,\n values: [...critical.result.values].sort(compareJsonValues),\n };\n }\n\n return JSON.stringify(sortObjectKeys(critical));\n}\n\nfunction sortObjectKeys(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(sortObjectKeys);\n }\n if (!isRecord(value)) {\n return value;\n }\n\n return Object.fromEntries(\n Object.entries(value)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, child]) => [key, sortObjectKeys(child)]),\n );\n}\n\nfunction compareJsonValues(left: unknown, right: unknown): number {\n return JSON.stringify(sortObjectKeys(left)).localeCompare(\n JSON.stringify(sortObjectKeys(right)),\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction assertOpen(closed: boolean): void {\n if (closed) {\n throw new Error(\"Storage is closed\");\n }\n}\n\nfunction row<T>(value: unknown): T {\n return value as T;\n}\n\nfunction requiredRow<T>(value: unknown): T {\n if (value === undefined) {\n throw new Error(\"Expected stored classifier data\");\n }\n return row<T>(value);\n}\n"],"mappings":"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","names":["randomUUID","join","process","resolve","createHash","join","row","isRecord","join","randomUUID","assertOpen","referenceResult","resolve"]}
1
+ {"version":3,"sources":["../src/classifier.ts","../src/config.ts","../src/evaluation.ts","../src/runtime.ts","../src/needle.ts","../src/storage.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { join } from \"node:path\";\n\nimport { normalizeConfig, validateResult } from \"./config.js\";\nimport { averageError, resultError } from \"./evaluation.js\";\nimport { SwapAIError } from \"./errors.js\";\nimport {\n createNeedleRuntime,\n hasNeedleModelArtifacts,\n NeedleModelArtifactError,\n needleModelVersion,\n type LoadedNeedleModel,\n type NeedleRuntime,\n} from \"./runtime.js\";\nimport { openStorage, type Storage } from \"./storage.js\";\nimport type {\n Classifier,\n InitConfig,\n NormalizedInitConfig,\n ReferenceClassifier,\n ResultConfig,\n ResultFor,\n ResultValue,\n} from \"./types.js\";\n\nconst TRAINING_LEASE_DURATION_MS = 5 * 60 * 1000;\nconst TRAINING_LEASE_RENEWAL_MS = 60 * 1000;\nconst ARTIFACT_LOCK_WAIT_MS = 30_000;\n\nexport function init<const Config extends ResultConfig>(\n inputConfig: InitConfig<Config>,\n): Classifier<ResultFor<Config>> {\n const config = normalizeConfig(inputConfig);\n const dataDirectory = config.dataDirectory ?? join(process.cwd(), \".swapai\");\n const storage = openClassifierStorage(config, dataDirectory);\n const runtime = createNeedleRuntime({\n dataDirectory,\n onBackgroundError: (error) =>\n reportBackgroundError(\n config,\n new SwapAIError(\"service_unavailable\", error.message, { cause: error }),\n ),\n });\n\n return createClassifier(config, storage, runtime);\n}\n\nfunction openClassifierStorage<const Config extends ResultConfig>(\n config: NormalizedInitConfig<Config>,\n dataDirectory: string,\n): Storage {\n try {\n return openStorage({\n dataDirectory,\n name: config.name,\n maxTrainingSet: config.maxTrainingSet,\n config: {\n result: config.result,\n retrainOnCount: config.retrainOnCount,\n acceptableError: config.acceptableError,\n retestInterval: config.retestInterval,\n retestRevertOn: config.retestRevertOn,\n model: config.model,\n },\n });\n } catch (error) {\n throw new SwapAIError(\n error instanceof TypeError ? \"invalid_configuration\" : \"storage_failed\",\n error instanceof Error ? error.message : \"Could not open SwapAI storage\",\n { cause: error },\n );\n }\n}\n\nfunction createClassifier<const Config extends ResultConfig>(\n config: NormalizedInitConfig<Config>,\n storage: Storage,\n runtime: NeedleRuntime,\n): Classifier<ResultFor<Config>> {\n type Result = ResultFor<Config>;\n\n const initialState = storage.snapshot();\n let closed = false;\n let closing = false;\n let closePromise: Promise<void> | null = null;\n let trained = initialState.trained && !initialState.clearPending;\n let loadedModel: LoadedNeedleModel | null = null;\n let loadedModelEpoch: number | null = null;\n let operationQueue: Promise<void> = Promise.resolve();\n let trainingQueue: Promise<void> = Promise.resolve();\n let trainingScheduled = false;\n const trainingLeaseOwner = `${process.pid}:${randomUUID()}`;\n let classificationQueue: Promise<void> = Promise.resolve();\n let queuedFailure: SwapAIError | null = null;\n let clearFailure: SwapAIError | null = null;\n let dataEpoch = initialState.dataEpoch;\n let clearedEpoch = initialState.clearPending\n ? initialState.dataEpoch - 1\n : initialState.dataEpoch;\n\n const saved = initialState;\n if (\n !saved.clearPending &&\n saved.trained &&\n (saved.modelPath === null ||\n saved.needleVersion !== needleModelVersion(config.result) ||\n !hasNeedleModelArtifacts({\n modelPath: saved.modelPath,\n resultConfig: config.result,\n }))\n ) {\n if (\n storage.archiveAndReset(saved.dataEpoch, { retainExamples: true }) !== null\n ) {\n const reset = storage.snapshot();\n dataEpoch = reset.dataEpoch;\n clearedEpoch = reset.dataEpoch;\n trained = false;\n }\n }\n\n const startup = startRuntime();\n\n async function startRuntime(): Promise<void> {\n const startupEpoch = dataEpoch;\n const beforeRuntime = storage.snapshot();\n if (beforeRuntime.clearPending) {\n trained = false;\n dataEpoch = beforeRuntime.dataEpoch;\n try {\n await performDurableClear(beforeRuntime.dataEpoch);\n } catch (error) {\n rememberClearFailure(error);\n }\n }\n try {\n await runtime.ready();\n } catch (error) {\n rememberBackgroundFailure(toSwapAIError(\n error,\n \"service_unavailable\",\n \"Needle could not start\",\n ));\n return;\n }\n const snapshot = storage.snapshot();\n if (snapshot.clearPending) {\n trained = false;\n dataEpoch = snapshot.dataEpoch;\n return;\n }\n if (snapshot.trained && snapshot.modelPath !== null) {\n try {\n const restoredModel = await runtime.loadModel({\n modelPath: snapshot.modelPath,\n resultConfig: config.result,\n });\n const current = storage.snapshot();\n if (\n startupEpoch === current.dataEpoch &&\n !current.clearPending &&\n current.trained\n ) {\n loadedModel = restoredModel;\n loadedModelEpoch = startupEpoch;\n trained = true;\n } else {\n await restoredModel.close();\n }\n } catch (error) {\n if (\n error instanceof NeedleModelArtifactError &&\n storage.archiveAndReset(snapshot.dataEpoch, {\n retainExamples: true,\n }) !== null\n ) {\n const reset = refreshStoredState();\n dataEpoch = reset.dataEpoch;\n clearedEpoch = reset.dataEpoch;\n trained = false;\n }\n const loadError = toSwapAIError(\n error,\n \"service_unavailable\",\n error instanceof NeedleModelArtifactError\n ? `Could not load classifier \"${config.name}\"; retraining from saved examples`\n : `Could not load classifier \"${config.name}\"`,\n );\n if (error instanceof NeedleModelArtifactError) {\n reportBackgroundError(config, loadError);\n } else {\n rememberBackgroundFailure(loadError);\n }\n }\n }\n scheduleTraining();\n }\n\n function rememberBackgroundFailure(error: SwapAIError): void {\n queuedFailure = error;\n reportBackgroundError(config, error);\n }\n\n function rememberClearFailure(error: unknown): void {\n clearFailure = toSwapAIError(\n error,\n \"storage_failed\",\n `Could not completely clear classifier \"${config.name}\"`,\n );\n reportBackgroundError(config, clearFailure);\n }\n\n function refreshStoredState() {\n const snapshot = storage.snapshot();\n dataEpoch = snapshot.dataEpoch;\n if (snapshot.clearPending) {\n trained = false;\n } else {\n trained = snapshot.trained;\n clearedEpoch = snapshot.dataEpoch;\n }\n return snapshot;\n }\n\n function enqueue(operation: () => void | Promise<void>): Promise<void> {\n const result = operationQueue.then(operation);\n operationQueue = result.catch((error: unknown) => {\n rememberBackgroundFailure(\n toSwapAIError(error, \"storage_failed\", \"Background work failed\"),\n );\n });\n return result;\n }\n\n function persistExample(\n input: string,\n result: Result,\n epoch = dataEpoch,\n ): Promise<void> {\n if (epoch !== dataEpoch) return Promise.resolve();\n return enqueue(() => {\n if (epoch !== dataEpoch) return;\n if (storage.addExample(input, result, epoch) !== null) scheduleTraining();\n });\n }\n\n function shouldTrain(snapshot = storage.snapshot()): boolean {\n return (\n clearedEpoch === dataEpoch &&\n snapshot.dataEpoch === dataEpoch &&\n !snapshot.clearPending &&\n !snapshot.trained &&\n snapshot.examplesUsedForTraining < config.maxTrainingSet &&\n snapshot.newExamplesSinceTraining >= config.retrainOnCount\n );\n }\n\n function scheduleTraining(): void {\n if (trainingScheduled || !shouldTrain()) return;\n trainingScheduled = true;\n let completedAttempt = false;\n const attempt = operationQueue.then(async () => {\n completedAttempt = await trainWhenDue();\n });\n trainingQueue = attempt\n .catch((error: unknown) => {\n rememberBackgroundFailure(\n toSwapAIError(error, \"service_unavailable\", \"Needle training failed\"),\n );\n })\n .finally(() => {\n trainingScheduled = false;\n if (completedAttempt) scheduleTraining();\n });\n }\n\n async function trainWhenDue(): Promise<boolean> {\n const trainingEpoch = dataEpoch;\n if (!shouldTrain()) return false;\n if (\n !storage.claimTrainingLease(\n trainingLeaseOwner,\n TRAINING_LEASE_DURATION_MS,\n trainingEpoch,\n )\n ) {\n return false;\n }\n\n let leaseHeld = true;\n const renewTrainingLease = (): boolean => {\n if (!leaseHeld) return false;\n try {\n leaseHeld = storage.claimTrainingLease(\n trainingLeaseOwner,\n TRAINING_LEASE_DURATION_MS,\n trainingEpoch,\n );\n } catch {\n leaseHeld = false;\n }\n return leaseHeld;\n };\n const leaseRenewal = setInterval(\n renewTrainingLease,\n TRAINING_LEASE_RENEWAL_MS,\n );\n leaseRenewal.unref();\n\n try {\n const snapshot = storage.snapshot();\n if (!shouldTrain(snapshot)) return false;\n\n if (\n !storage.markTrainingAttempted(\n snapshot.activeExampleCount,\n trainingEpoch,\n )\n ) {\n return false;\n }\n const trainingExamples = storage.listExamplesForTraining(\n \"training\",\n snapshot.activeGeneration,\n trainingEpoch,\n );\n const heldOutExamples = storage.listExamplesForTraining(\n \"held_out\",\n snapshot.activeGeneration,\n trainingEpoch,\n );\n\n if (trainingExamples === null || heldOutExamples === null) return false;\n if (trainingExamples.length === 0 || heldOutExamples.length === 0) {\n return true;\n }\n\n const candidate = await runtime.train({\n classifierName: config.name,\n generation: snapshot.activeGeneration,\n expectedEpoch: trainingEpoch,\n examples: trainingExamples.map(({ input, result }) => ({ input, result })),\n resultConfig: config.result,\n acceptableError: config.acceptableError,\n });\n const candidateModel = await runtime.loadModel({\n modelPath: candidate.modelPath,\n resultConfig: config.result,\n });\n\n try {\n const comparisons = [];\n for (const example of heldOutExamples) {\n let candidateResult: Result;\n try {\n candidateResult = validateResult(\n config.result,\n await candidateModel.classify(example.input),\n );\n } catch (error) {\n if (\n error instanceof SwapAIError &&\n error.code === \"classification_failed\"\n ) {\n return true;\n }\n throw error;\n }\n comparisons.push({\n reference: validateResult(config.result, example.result),\n candidate: candidateResult,\n });\n }\n\n if (averageError(config.result, comparisons) > config.acceptableError) {\n return true;\n }\n\n if (!renewTrainingLease()) {\n const current = refreshStoredState();\n if (\n current.dataEpoch !== trainingEpoch ||\n current.clearPending\n ) {\n await runtime.clearClassifierGenerationArtifacts(\n config.name,\n snapshot.activeGeneration,\n );\n return false;\n }\n throw new SwapAIError(\n \"service_unavailable\",\n `Classifier \"${config.name}\" lost its training lease`,\n );\n }\n\n if (trainingEpoch !== refreshStoredState().dataEpoch) {\n await runtime.clearClassifierGenerationArtifacts(\n config.name,\n snapshot.activeGeneration,\n );\n return false;\n }\n if (storage.promoteGeneration(candidate, trainingEpoch) === null) {\n await runtime.clearClassifierGenerationArtifacts(\n config.name,\n snapshot.activeGeneration,\n );\n return false;\n }\n if (loadedModel !== null) await loadedModel.close();\n if (trainingEpoch !== refreshStoredState().dataEpoch) {\n await runtime.clearClassifierGenerationArtifacts(\n config.name,\n snapshot.activeGeneration,\n );\n return false;\n }\n loadedModel = candidateModel;\n loadedModelEpoch = trainingEpoch;\n trained = true;\n return true;\n } finally {\n if (loadedModel !== candidateModel) await candidateModel.close();\n }\n } finally {\n clearInterval(leaseRenewal);\n storage.releaseTrainingLease(trainingLeaseOwner);\n }\n }\n\n async function model(expectedEpoch: number): Promise<LoadedNeedleModel> {\n await startup;\n const current = refreshStoredState();\n if (\n !trained ||\n current.clearPending ||\n current.dataEpoch !== expectedEpoch\n ) {\n throw new SwapAIError(\n \"not_trained\",\n `Classifier \"${config.name}\" has not passed its held-out test`,\n );\n }\n if (loadedModel !== null && loadedModelEpoch !== expectedEpoch) {\n await loadedModel.close();\n loadedModel = null;\n loadedModelEpoch = null;\n }\n if (loadedModel === null) {\n if (current.modelPath === null) {\n throw new SwapAIError(\n \"service_unavailable\",\n `Classifier \"${config.name}\" is trained but has no saved model`,\n );\n }\n await runtime.ready();\n let restored: LoadedNeedleModel;\n try {\n restored = await runtime.loadModel({\n modelPath: current.modelPath,\n resultConfig: config.result,\n });\n } catch (error) {\n if (\n error instanceof NeedleModelArtifactError &&\n storage.archiveAndReset(expectedEpoch, { retainExamples: true }) !== null\n ) {\n const reset = refreshStoredState();\n dataEpoch = reset.dataEpoch;\n clearedEpoch = reset.dataEpoch;\n trained = false;\n scheduleTraining();\n }\n throw error;\n }\n const afterLoad = refreshStoredState();\n if (\n afterLoad.dataEpoch !== expectedEpoch ||\n afterLoad.clearPending ||\n !afterLoad.trained\n ) {\n await restored.close();\n throw new SwapAIError(\n \"not_trained\",\n `Classifier \"${config.name}\" has been cleared`,\n );\n }\n loadedModel = restored;\n loadedModelEpoch = expectedEpoch;\n }\n return loadedModel;\n }\n\n async function callReference(\n input: string,\n reference: ReferenceClassifier<Result>,\n ): Promise<Result> {\n return validateResult(config.result, await reference(input));\n }\n\n async function fallbackToReference(\n input: string,\n reference: ReferenceClassifier<Result> | undefined,\n candidateError: unknown,\n retestDue: boolean,\n epoch: number,\n ): Promise<Result> {\n if (reference === undefined) {\n throw toSwapAIError(\n candidateError,\n \"classification_failed\",\n \"Needle classification failed\",\n );\n }\n reportBackgroundError(\n config,\n toSwapAIError(\n candidateError,\n \"classification_failed\",\n \"Needle classification failed; the reference classifier was used\",\n ),\n );\n const referenceResult = await callReference(input, reference);\n await persistExample(input, referenceResult, epoch);\n if (retestDue && epoch === dataEpoch) {\n if (storage.recordLocalClassification(epoch) === null) return referenceResult;\n const failures = storage.recordRetest(false, epoch);\n if (failures !== null && failures >= config.retestRevertOn) {\n await disableModel(epoch);\n }\n }\n return referenceResult;\n }\n\n async function disableModel(epoch: number): Promise<void> {\n if (storage.archiveAndReset(epoch) === null) return;\n refreshStoredState();\n trained = false;\n const previousModel = loadedModel;\n loadedModel = null;\n loadedModelEpoch = null;\n if (previousModel !== null) await previousModel.close();\n }\n\n async function classifyNow(\n input: string,\n reference: ReferenceClassifier<Result> | undefined,\n epoch: number,\n ): Promise<Result> {\n assertOpen(closed);\n\n if (!trained) {\n if (reference === undefined) {\n throw new SwapAIError(\n \"not_trained\",\n `Classifier \"${config.name}\" has not passed its held-out test`,\n );\n }\n const referenceResult = await callReference(input, reference);\n await persistExample(input, referenceResult, epoch);\n return referenceResult;\n }\n\n const snapshot = storage.snapshot();\n const retestDue =\n config.retestInterval > 0 &&\n snapshot.localClassificationsSinceRetest + 1 >= config.retestInterval;\n\n let candidateResult: Result;\n try {\n candidateResult = validateResult(\n config.result,\n await (await model(epoch)).classify(input),\n );\n } catch (error) {\n return fallbackToReference(input, reference, error, retestDue, epoch);\n }\n\n const afterClassification = refreshStoredState();\n if (\n afterClassification.dataEpoch !== epoch ||\n afterClassification.clearPending\n ) {\n return fallbackToReference(\n input,\n reference,\n new SwapAIError(\n \"not_trained\",\n `Classifier \"${config.name}\" was cleared during classification`,\n ),\n retestDue,\n epoch,\n );\n }\n\n if (!retestDue || reference === undefined) {\n if (\n epoch !== dataEpoch ||\n storage.recordLocalClassification(epoch) === null\n ) {\n return fallbackToReference(\n input,\n reference,\n new SwapAIError(\n \"not_trained\",\n `Classifier \"${config.name}\" was cleared before returning its result`,\n ),\n retestDue,\n epoch,\n );\n }\n return candidateResult;\n }\n\n const referenceResult = await callReference(input, reference);\n await persistExample(input, referenceResult, epoch);\n if (epoch !== dataEpoch) return referenceResult;\n if (storage.recordLocalClassification(epoch) === null) return referenceResult;\n const passed =\n resultError(config.result, referenceResult, candidateResult) <=\n config.acceptableError;\n const failures = storage.recordRetest(passed, epoch);\n\n if (\n !passed &&\n failures !== null &&\n failures >= config.retestRevertOn\n ) {\n await disableModel(epoch);\n }\n\n return referenceResult;\n }\n\n async function performDurableClear(clearEpoch: number): Promise<void> {\n trained = false;\n const deletionFailures: unknown[] = [];\n const throwDeletionFailures = (): void => {\n if (deletionFailures.length === 1) throw deletionFailures[0];\n if (deletionFailures.length > 1) {\n throw new AggregateError(\n deletionFailures,\n `Could not completely clear classifier \"${config.name}\"`,\n );\n }\n };\n const previousModel = loadedModel;\n if (previousModel !== null) {\n try {\n await previousModel.close();\n if (loadedModel === previousModel) {\n loadedModel = null;\n loadedModelEpoch = null;\n }\n } catch (error) {\n deletionFailures.push(error);\n }\n }\n\n const lockWaitStarted = Date.now();\n let clearState = refreshStoredState();\n while (\n clearState.clearPending &&\n clearState.dataEpoch === clearEpoch &&\n ((clearState.trainingLeaseOwner !== null &&\n clearState.trainingLeaseEpoch === null &&\n clearState.trainingLeaseUntil !== null &&\n clearState.trainingLeaseUntil > Date.now()) ||\n !storage.claimArtifactWriteLock())\n ) {\n if (Date.now() - lockWaitStarted >= ARTIFACT_LOCK_WAIT_MS) {\n throw new SwapAIError(\n \"storage_failed\",\n `Timed out waiting to clear classifier \"${config.name}\" while training was still running`,\n );\n }\n await new Promise<void>((resolve) => setTimeout(resolve, 10));\n clearState = refreshStoredState();\n }\n\n if (!clearState.clearPending || clearState.dataEpoch !== clearEpoch) {\n throwDeletionFailures();\n return;\n }\n try {\n try {\n storage.eraseTrainingData(clearEpoch);\n } catch (error) {\n deletionFailures.push(error);\n }\n clearState = refreshStoredState();\n if (\n clearState.clearPending &&\n clearState.dataEpoch === clearEpoch &&\n clearState.clearErased &&\n clearState.clearArtifactGenerationMax !== null\n ) {\n try {\n await runtime.clearClassifierArtifactsThroughGeneration(\n config.name,\n clearState.clearArtifactGenerationMax,\n );\n } catch (error) {\n deletionFailures.push(error);\n }\n }\n throwDeletionFailures();\n\n storage.finishClearTrainingData(clearEpoch);\n const current = refreshStoredState();\n if (!current.clearPending) {\n clearFailure = null;\n clearedEpoch = current.dataEpoch;\n }\n } finally {\n storage.releaseArtifactWriteLock();\n }\n }\n\n async function flushNow(): Promise<void> {\n const clearFailureBeforeFlush = clearFailure;\n await startup;\n while (true) {\n const operations = operationQueue;\n await operations;\n const training = trainingQueue;\n await training;\n if (operations === operationQueue && training === trainingQueue) break;\n }\n if (\n clearFailure !== null &&\n clearFailure !== clearFailureBeforeFlush\n ) {\n throw clearFailure;\n }\n const pending = refreshStoredState();\n if (pending.clearPending || clearFailureBeforeFlush !== null) {\n try {\n await performDurableClear(pending.dataEpoch);\n if (!refreshStoredState().clearPending) clearFailure = null;\n } catch (error) {\n rememberClearFailure(error);\n }\n }\n if (refreshStoredState().clearPending) {\n clearFailure ??= new SwapAIError(\n \"storage_failed\",\n `Could not completely clear classifier \"${config.name}\"`,\n );\n throw clearFailure;\n }\n if (clearFailure !== null) throw clearFailure;\n if (queuedFailure !== null) {\n const failure = queuedFailure;\n queuedFailure = null;\n throw failure;\n }\n }\n\n const classifier: Classifier<Result> = {\n isTrained() {\n assertOpen(closed || closing);\n refreshStoredState();\n return trained;\n },\n\n logClassification(input, result) {\n assertOpen(closed || closing);\n const validResult = validateResult(config.result, result);\n const epoch = refreshStoredState().dataEpoch;\n void persistExample(input, validResult, epoch);\n },\n\n clearTrainingData() {\n assertOpen(closed || closing);\n trained = false;\n const clearEpoch = storage.beginClearTrainingData();\n dataEpoch = clearEpoch;\n const trainingBeforeClear = trainingQueue;\n const classificationsBeforeClear = classificationQueue;\n void enqueue(async () => {\n await startup;\n await trainingBeforeClear;\n await classificationsBeforeClear;\n try {\n await performDurableClear(clearEpoch);\n } catch (error) {\n rememberClearFailure(error);\n }\n });\n },\n\n classify(input, reference) {\n assertOpen(closed || closing);\n const epoch = refreshStoredState().dataEpoch;\n const task = classificationQueue.then(() =>\n classifyNow(input, reference, epoch),\n );\n classificationQueue = task.then(\n () => undefined,\n () => undefined,\n );\n return task;\n },\n\n async flush() {\n assertOpen(closed || closing);\n await flushNow();\n },\n\n close() {\n if (closed) return Promise.resolve();\n if (closePromise !== null) return closePromise;\n closing = true;\n closePromise = (async () => {\n try {\n await classificationQueue;\n await flushNow();\n } catch (error) {\n closing = false;\n closePromise = null;\n throw error;\n }\n const failures: unknown[] = [];\n if (loadedModel !== null) {\n try {\n await loadedModel.close();\n } catch (error) {\n failures.push(error);\n }\n }\n loadedModel = null;\n loadedModelEpoch = null;\n try {\n await runtime.close();\n } catch (error) {\n failures.push(error);\n }\n try {\n storage.close();\n } catch (error) {\n failures.push(error);\n }\n closed = true;\n closing = false;\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1) {\n throw new AggregateError(\n failures,\n `Could not completely close classifier \"${config.name}\"`,\n );\n }\n })();\n return closePromise;\n },\n };\n\n return classifier;\n}\n\nfunction assertOpen(closed: boolean): void {\n if (closed) {\n throw new SwapAIError(\"service_unavailable\", \"Classifier is closed\");\n }\n}\n\nfunction toSwapAIError(\n error: unknown,\n code: \"classification_failed\" | \"service_unavailable\" | \"storage_failed\",\n message: string,\n): SwapAIError {\n if (error instanceof SwapAIError) return error;\n return new SwapAIError(code, message, { cause: error });\n}\n\nfunction reportBackgroundError(\n config: NormalizedInitConfig<ResultConfig>,\n error: SwapAIError,\n): void {\n try {\n config.onBackgroundError?.(error);\n } catch {\n // A reporting callback must not interrupt classification or storage work.\n }\n}\n","import { SwapAIError } from \"./errors.js\";\nimport type {\n InitConfig,\n NormalizedInitConfig,\n ResultConfig,\n ResultFor,\n} from \"./types.js\";\n\nfunction invalidConfiguration(message: string): never {\n throw new SwapAIError(\"invalid_configuration\", message);\n}\n\nfunction requirePositiveInteger(value: number, field: string): void {\n if (!Number.isInteger(value) || value <= 0) {\n invalidConfiguration(`${field} must be a positive integer`);\n }\n}\n\nfunction requireNonNegativeInteger(value: number, field: string): void {\n if (!Number.isInteger(value) || value < 0) {\n invalidConfiguration(`${field} must be a non-negative integer`);\n }\n}\n\nfunction normalizeAcceptableError(value: number | `${number}%`): number {\n let normalized: number;\n\n if (typeof value === \"number\") {\n normalized = value;\n } else {\n const match = /^\\s*(\\d+(?:\\.\\d+)?)%\\s*$/.exec(value);\n if (match === null) {\n invalidConfiguration(\n \"acceptableError must be a number or a percentage such as \\\"10%\\\"\",\n );\n }\n normalized = Number(match[1]) / 100;\n }\n\n if (!Number.isFinite(normalized) || normalized < 0 || normalized > 1) {\n invalidConfiguration(\"acceptableError must be between 0 and 1\");\n }\n\n return normalized;\n}\n\nfunction validateResultConfig(result: ResultConfig): void {\n if (result.type === \"number\") {\n if (!Number.isFinite(result.min) || !Number.isFinite(result.max)) {\n invalidConfiguration(\"number result bounds must be finite\");\n }\n if (result.max <= result.min) {\n invalidConfiguration(\"number result max must be greater than min\");\n }\n if (!Number.isFinite(result.max - result.min)) {\n invalidConfiguration(\"number result range must be finite\");\n }\n return;\n }\n\n if (result.type === \"string\") {\n if (result.values.length === 0) {\n invalidConfiguration(\"string result values must not be empty\");\n }\n if (\n result.values.some((value) => typeof value !== \"string\") ||\n new Set(result.values).size !== result.values.length\n ) {\n invalidConfiguration(\"string result values must be unique strings\");\n }\n }\n}\n\nexport function normalizeConfig<const Config extends ResultConfig>(\n config: InitConfig<Config>,\n): NormalizedInitConfig<Config> {\n if (typeof config.name !== \"string\" || config.name.trim() === \"\") {\n invalidConfiguration(\"name must not be empty\");\n }\n\n validateResultConfig(config.result);\n requirePositiveInteger(config.retrainOnCount, \"retrainOnCount\");\n requireNonNegativeInteger(config.retestInterval, \"retestInterval\");\n requirePositiveInteger(config.retestRevertOn, \"retestRevertOn\");\n requirePositiveInteger(config.maxTrainingSet, \"maxTrainingSet\");\n\n if (config.maxTrainingSet < config.retrainOnCount) {\n invalidConfiguration(\n \"maxTrainingSet must be greater than or equal to retrainOnCount\",\n );\n }\n if (config.model !== \"needle2\") {\n invalidConfiguration('model must be \"needle2\"');\n }\n if (\n config.dataDirectory !== undefined &&\n (typeof config.dataDirectory !== \"string\" ||\n config.dataDirectory.trim() === \"\")\n ) {\n invalidConfiguration(\"dataDirectory must not be empty\");\n }\n if (\n config.onBackgroundError !== undefined &&\n typeof config.onBackgroundError !== \"function\"\n ) {\n invalidConfiguration(\"onBackgroundError must be a function\");\n }\n\n return {\n ...config,\n acceptableError: normalizeAcceptableError(config.acceptableError),\n };\n}\n\nexport function validateResult<const Config extends ResultConfig>(\n config: Config,\n value: unknown,\n): ResultFor<Config> {\n const valid =\n config.type === \"number\"\n ? typeof value === \"number\" &&\n Number.isFinite(value) &&\n value >= config.min &&\n value <= config.max\n : config.type === \"boolean\"\n ? typeof value === \"boolean\"\n : typeof value === \"string\" && config.values.includes(value);\n\n if (!valid) {\n throw new SwapAIError(\n \"invalid_result\",\n \"classification result does not match the declared allowed results\",\n );\n }\n\n return value as ResultFor<Config>;\n}\n","import { validateResult } from \"./config.js\";\nimport { SwapAIError } from \"./errors.js\";\nimport type {\n ResultComparison,\n ResultConfig,\n ResultFor,\n} from \"./types.js\";\n\nexport function resultError<const Config extends ResultConfig>(\n config: Config,\n reference: ResultFor<Config>,\n candidate: ResultFor<Config>,\n): number {\n const validReference = validateResult(config, reference);\n const validCandidate = validateResult(config, candidate);\n\n if (config.type === \"number\") {\n return (\n Math.abs((validReference as number) - (validCandidate as number)) /\n (config.max - config.min)\n );\n }\n\n return validReference === validCandidate ? 0 : 1;\n}\n\nexport function averageError<const Config extends ResultConfig>(\n config: Config,\n comparisons: readonly ResultComparison<ResultFor<Config>>[],\n): number {\n if (comparisons.length === 0) {\n throw new SwapAIError(\n \"invalid_result\",\n \"at least one held-out example is required to calculate average error\",\n );\n }\n\n const total = comparisons.reduce(\n (sum, comparison) =>\n sum + resultError(config, comparison.reference, comparison.candidate),\n 0,\n );\n\n return total / comparisons.length;\n}\n","import { createHash, randomUUID } from \"node:crypto\";\nimport { spawn } from \"node:child_process\";\nimport { readFileSync, statSync } from \"node:fs\";\nimport {\n chmod,\n copyFile,\n mkdir,\n readFile,\n readdir,\n rm,\n stat,\n writeFile,\n} from \"node:fs/promises\";\nimport { createInterface } from \"node:readline\";\nimport { dirname, join, resolve, sep } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { SwapAIError } from \"./errors.js\";\nimport {\n createNeedleNumberLabels,\n createNeedleTool,\n createTrainingLine,\n decodeNeedleResult,\n validateNeedleResult,\n type NeedleExample,\n type NeedleNumberLabels,\n type NeedleResultConfig,\n type NeedleResultValue,\n} from \"./needle.js\";\n\nexport const NEEDLE_VERSION = \"2.0.14\";\nexport const NEEDLE_NUMBER_MODEL_VERSION =\n `${NEEDLE_VERSION}/number-buckets-v1`;\nconst UV_VERSION = \"0.11.4\";\nconst PYTHON_VERSION = \"3.12\";\n\nexport interface CommandOptions {\n readonly cwd?: string;\n readonly env?: NodeJS.ProcessEnv;\n readonly timeoutMs?: number;\n readonly stdin?: string;\n}\n\nexport type RunCommand = (\n command: string,\n args: readonly string[],\n options?: CommandOptions,\n) => Promise<{ readonly stdout: string; readonly stderr: string }>;\n\nexport interface NeedleChildProcess {\n readonly stdin: NodeJS.WritableStream;\n readonly stdout: NodeJS.ReadableStream;\n readonly stderr: NodeJS.ReadableStream;\n on(event: string, listener: (...args: any[]) => void): this;\n once(event: string, listener: (...args: any[]) => void): this;\n kill(signal?: NodeJS.Signals): boolean;\n}\n\nexport type NeedleSpawn = (\n command: string,\n args: readonly string[],\n options: { readonly cwd: string; readonly env: NodeJS.ProcessEnv },\n) => NeedleChildProcess;\n\nexport interface NeedleRuntimeDependencies {\n readonly runCommand?: RunCommand;\n readonly spawnProcess?: NeedleSpawn;\n readonly fetch?: typeof globalThis.fetch;\n readonly workerPath?: string;\n readonly requirementsPath?: string;\n}\n\nexport interface CreateNeedleRuntimeOptions {\n readonly dataDirectory: string;\n readonly onBackgroundError?: (error: NeedleRuntimeError) => void;\n readonly dependencies?: NeedleRuntimeDependencies;\n}\n\nexport interface TrainNeedleModelOptions {\n readonly classifierName: string;\n readonly generation: number;\n readonly expectedEpoch: number;\n readonly examples: readonly NeedleExample[];\n readonly resultConfig: NeedleResultConfig;\n readonly acceptableError?: number;\n readonly epochs?: number;\n}\n\nexport interface TrainedNeedleModel {\n readonly modelPath: string;\n readonly needleVersion: string;\n}\n\nexport function needleModelVersion(\n resultConfig: NeedleResultConfig,\n): string {\n return resultConfig.type === \"number\"\n ? NEEDLE_NUMBER_MODEL_VERSION\n : NEEDLE_VERSION;\n}\n\nexport interface LoadNeedleModelOptions {\n readonly modelPath: string;\n readonly resultConfig: NeedleResultConfig;\n}\n\nexport interface LoadedNeedleModel {\n classify(input: string): Promise<NeedleResultValue>;\n close(): Promise<void>;\n}\n\nexport class NeedleModelArtifactError extends SwapAIError {\n constructor(message: string, cause?: unknown) {\n super(\n \"service_unavailable\",\n message,\n cause === undefined ? undefined : { cause },\n );\n this.name = \"NeedleModelArtifactError\";\n }\n}\n\nexport function hasNeedleModelArtifacts(\n options: LoadNeedleModelOptions,\n): boolean {\n try {\n if (!statSync(options.modelPath).isFile()) return false;\n if (options.resultConfig.type !== \"number\") return true;\n const saved = JSON.parse(\n readFileSync(`${options.modelPath}.numbers.json`, \"utf8\"),\n ) as { format?: unknown; values?: unknown };\n if (\n saved.format !== 1 ||\n !Array.isArray(saved.values) ||\n saved.values.length === 0\n ) return false;\n const savedValues = saved.values as number[];\n const labels = createNeedleNumberLabels(savedValues, options.resultConfig);\n return labels.values.length === savedValues.length && labels.values.every(\n (value, index) => value === savedValues[index],\n );\n } catch {\n return false;\n }\n}\n\nexport interface NeedleRuntime {\n ready(): Promise<void>;\n train(options: TrainNeedleModelOptions): Promise<TrainedNeedleModel>;\n loadModel(options: LoadNeedleModelOptions): Promise<LoadedNeedleModel>;\n clearClassifierArtifacts(classifierName: string): Promise<void>;\n clearClassifierGenerationArtifacts(\n classifierName: string,\n generation: number,\n ): Promise<void>;\n clearClassifierArtifactsThroughGeneration(\n classifierName: string,\n maximumGeneration: number,\n ): Promise<void>;\n close(): Promise<void>;\n}\n\nexport class NeedleRuntimeError extends SwapAIError {\n declare readonly code: \"service_unavailable\" | \"classification_failed\";\n\n constructor(\n code: \"service_unavailable\" | \"classification_failed\",\n message: string,\n cause?: unknown,\n ) {\n super(code, message, cause === undefined ? undefined : { cause });\n this.name = \"NeedleRuntimeError\";\n }\n}\n\nexport function createNeedleRuntime(\n options: CreateNeedleRuntimeOptions,\n): NeedleRuntime {\n return new ManagedNeedleRuntime(options);\n}\n\nclass ManagedNeedleRuntime implements NeedleRuntime {\n readonly #dataDirectory: string;\n readonly #runtimeDirectory: string;\n readonly #runCommand: RunCommand;\n readonly #spawnProcess: NeedleSpawn;\n readonly #fetch: typeof globalThis.fetch;\n readonly #workerPath: string;\n readonly #requirementsPath: string;\n readonly #onBackgroundError: ((error: NeedleRuntimeError) => void) | undefined;\n readonly #models = new Set<NeedleModelProcess>();\n #readyPromise: Promise<void> | undefined;\n #pythonPath: string | undefined;\n #environment: NodeJS.ProcessEnv | undefined;\n #closed = false;\n\n constructor(options: CreateNeedleRuntimeOptions) {\n this.#dataDirectory = resolve(options.dataDirectory);\n this.#runtimeDirectory = join(this.#dataDirectory, \"runtime\");\n this.#runCommand = options.dependencies?.runCommand ?? runCommand;\n this.#spawnProcess = options.dependencies?.spawnProcess ?? spawnProcess;\n this.#fetch = options.dependencies?.fetch ?? globalThis.fetch;\n this.#workerPath =\n options.dependencies?.workerPath ??\n fileURLToPath(new URL(\"../python/swapai_worker.py\", import.meta.url));\n this.#requirementsPath =\n options.dependencies?.requirementsPath ??\n fileURLToPath(new URL(\"../python/requirements.lock\", import.meta.url));\n this.#onBackgroundError = options.onBackgroundError;\n }\n\n ready(): Promise<void> {\n if (this.#closed) {\n return Promise.reject(\n new NeedleRuntimeError(\"service_unavailable\", \"Needle runtime is closed.\"),\n );\n }\n this.#readyPromise ??= this.#prepare().catch((error: unknown) => {\n this.#readyPromise = undefined;\n throw toRuntimeError(\"Could not prepare Needle.\", error);\n });\n return this.#readyPromise;\n }\n\n async train(options: TrainNeedleModelOptions): Promise<TrainedNeedleModel> {\n if (!Number.isSafeInteger(options.generation) || options.generation < 0) {\n throw new NeedleRuntimeError(\n \"service_unavailable\",\n \"Needle generation must be a non-negative integer.\",\n );\n }\n if (!Number.isSafeInteger(options.expectedEpoch) || options.expectedEpoch < 0) {\n throw new NeedleRuntimeError(\n \"service_unavailable\",\n \"Needle data epoch must be a non-negative integer.\",\n );\n }\n if (options.examples.length === 0) {\n throw new NeedleRuntimeError(\n \"service_unavailable\",\n \"Needle needs at least one training example.\",\n );\n }\n await this.ready();\n\n const classifierDirectory = join(\n this.#dataDirectory,\n \"classifiers\",\n classifierKey(options.classifierName),\n );\n const generationDirectory = join(\n classifierDirectory,\n `generation-${options.generation}`,\n );\n const checkpointDirectory = join(generationDirectory, \"checkpoints\");\n const candidateDirectory = join(\n generationDirectory,\n \"candidates\",\n randomUUID(),\n );\n const trainingPath = join(candidateDirectory, \"training.jsonl\");\n const modelPath = join(candidateDirectory, \"model.cact\");\n await mkdir(checkpointDirectory, { recursive: true, mode: 0o700 });\n await mkdir(candidateDirectory, { recursive: true, mode: 0o700 });\n\n const numberLabels =\n options.resultConfig.type === \"number\"\n ? createNeedleNumberLabels(\n options.examples.map((example) => example.result as number),\n options.resultConfig,\n options.acceptableError,\n )\n : undefined;\n const lines = options.examples.map((example) =>\n createTrainingLine(\n example.input,\n example.result,\n options.resultConfig,\n numberLabels,\n ),\n );\n const lockPath = join(\n this.#dataDirectory,\n \"locks\",\n `${createHash(\"sha256\").update(options.classifierName).digest(\"hex\")}.sqlite`,\n );\n\n try {\n const trainArguments = [\n this.#workerPath,\n \"train\",\n \"--training-data\",\n trainingPath,\n \"--output\",\n modelPath,\n \"--checkpoint-dir\",\n checkpointDirectory,\n \"--epochs\",\n String(options.epochs ?? 10),\n \"--artifact-lock-database\",\n lockPath,\n \"--main-database\",\n join(this.#dataDirectory, \"swapai.sqlite\"),\n \"--classifier-name\",\n options.classifierName,\n \"--expected-epoch\",\n String(options.expectedEpoch),\n ];\n if (numberLabels) {\n trainArguments.push(\"--numeric-labels-from-stdin\");\n }\n await this.#runCommand(\n this.#pythonPath!,\n trainArguments,\n {\n cwd: candidateDirectory,\n env: this.#environment!,\n timeoutMs: 6 * 60 * 60 * 1000,\n stdin: numberLabels\n ? `${JSON.stringify({ format: 1, values: numberLabels.values })}\\n${lines.join(\"\\n\")}\\n`\n : `${lines.join(\"\\n\")}\\n`,\n },\n );\n await stat(modelPath);\n } catch (error) {\n throw toRuntimeError(\"Needle training failed.\", error);\n }\n\n return {\n modelPath,\n needleVersion: needleModelVersion(options.resultConfig),\n };\n }\n\n async loadModel(options: LoadNeedleModelOptions): Promise<LoadedNeedleModel> {\n await this.ready();\n try {\n await stat(options.modelPath);\n } catch (error) {\n throw new NeedleModelArtifactError(\n `Needle model does not exist: ${options.modelPath}`,\n error,\n );\n }\n\n let numberLabels: NeedleNumberLabels | undefined;\n if (options.resultConfig.type === \"number\") {\n try {\n const saved = JSON.parse(\n await readFile(`${options.modelPath}.numbers.json`, \"utf8\"),\n ) as { format?: unknown; values?: unknown };\n if (\n saved.format !== 1 ||\n !Array.isArray(saved.values) ||\n saved.values.length === 0\n ) {\n throw new TypeError(\"Numeric label map has an invalid format.\");\n }\n const savedValues = saved.values as unknown[];\n numberLabels = createNeedleNumberLabels(\n savedValues as number[],\n options.resultConfig,\n );\n if (\n numberLabels.values.length !== savedValues.length ||\n numberLabels.values.some(\n (value, index) => value !== savedValues[index],\n )\n ) {\n throw new TypeError(\"Numeric label map is not sorted and unique.\");\n }\n } catch (error) {\n throw new NeedleModelArtifactError(\n \"Could not load Needle numeric labels.\",\n error,\n );\n }\n }\n\n const schemaPath = `${options.modelPath}.schema.json`;\n await writeFile(\n schemaPath,\n JSON.stringify([createNeedleTool(options.resultConfig, numberLabels)]),\n \"utf8\",\n );\n\n const process = this.#spawnProcess(\n this.#pythonPath!,\n [\n \"-u\",\n this.#workerPath,\n \"serve\",\n \"--model\",\n options.modelPath,\n \"--schema\",\n schemaPath,\n ],\n { cwd: dirname(options.modelPath), env: this.#environment! },\n );\n const model = new NeedleModelProcess(\n process,\n options.resultConfig,\n numberLabels,\n (error) => this.#onBackgroundError?.(error),\n () => this.#models.delete(model),\n );\n this.#models.add(model);\n try {\n await model.ready();\n return model;\n } catch (error) {\n this.#models.delete(model);\n process.kill(\"SIGTERM\");\n throw toRuntimeError(\"Needle model could not start.\", error);\n }\n }\n\n async clearClassifierArtifacts(classifierName: string): Promise<void> {\n await rm(\n join(this.#dataDirectory, \"classifiers\", classifierKey(classifierName)),\n { recursive: true, force: true },\n );\n }\n\n async clearClassifierGenerationArtifacts(\n classifierName: string,\n generation: number,\n ): Promise<void> {\n if (!Number.isSafeInteger(generation) || generation < 0) {\n throw new NeedleRuntimeError(\n \"service_unavailable\",\n \"Classifier generation must be a non-negative safe integer.\",\n );\n }\n const classifierDirectory = resolve(\n this.#dataDirectory,\n \"classifiers\",\n classifierKey(classifierName),\n );\n const generationDirectory = resolve(\n classifierDirectory,\n `generation-${generation}`,\n );\n if (!generationDirectory.startsWith(`${classifierDirectory}${sep}`)) {\n throw new NeedleRuntimeError(\n \"service_unavailable\",\n \"Classifier generation path is outside its classifier directory.\",\n );\n }\n await rm(generationDirectory, { recursive: true, force: true });\n }\n\n async clearClassifierArtifactsThroughGeneration(\n classifierName: string,\n maximumGeneration: number,\n ): Promise<void> {\n if (!Number.isSafeInteger(maximumGeneration) || maximumGeneration < 0) {\n throw new NeedleRuntimeError(\n \"service_unavailable\",\n \"Maximum classifier generation must be a non-negative safe integer.\",\n );\n }\n const classifierDirectory = join(\n this.#dataDirectory,\n \"classifiers\",\n classifierKey(classifierName),\n );\n let entries;\n try {\n entries = await readdir(classifierDirectory, { withFileTypes: true });\n } catch (error) {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return;\n }\n throw error;\n }\n await Promise.all(\n entries.map(async (entry) => {\n const match = /^generation-(\\d+)$/.exec(entry.name);\n if (!entry.isDirectory() || match === null) return;\n const generation = Number(match[1]);\n if (generation > maximumGeneration) return;\n await rm(join(classifierDirectory, entry.name), {\n recursive: true,\n force: true,\n });\n }),\n );\n }\n\n async close(): Promise<void> {\n if (this.#closed) return;\n this.#closed = true;\n await Promise.allSettled([...this.#models].map((model) => model.close()));\n this.#models.clear();\n }\n\n async #prepare(): Promise<void> {\n const installDirectory = join(\n this.#runtimeDirectory,\n `needle-${NEEDLE_VERSION}`,\n );\n const environmentDirectory = join(installDirectory, \".venv\");\n const markerPath = join(installDirectory, \"installed.json\");\n await mkdir(installDirectory, { recursive: true });\n\n const baseEnvironment = this.#makeEnvironment();\n const uvPath = await this.#findOrInstallUv(baseEnvironment);\n const pythonPath = pythonIn(environmentDirectory);\n const environment = this.#makeEnvironment(uvPath, environmentDirectory);\n\n if (!(await exists(pythonPath))) {\n await this.#runCommand(\n uvPath,\n [\"venv\", \"--python\", PYTHON_VERSION, environmentDirectory],\n { cwd: installDirectory, env: environment, timeoutMs: 15 * 60 * 1000 },\n );\n }\n\n const requirementsDigest = createHash(\"sha256\")\n .update(await readFile(this.#requirementsPath))\n .digest(\"hex\");\n const marker = await readJson(markerPath);\n let installRequired =\n marker?.needleVersion !== NEEDLE_VERSION ||\n marker.requirementsDigest !== requirementsDigest;\n let forceReinstall = false;\n const healthCheck = [\n \"-c\",\n `import needle, jax, flax, optax; assert needle.__version__ == \"${NEEDLE_VERSION}\"`,\n ] as const;\n\n if (!installRequired) {\n try {\n await this.#runCommand(pythonPath, healthCheck, {\n cwd: installDirectory,\n env: environment,\n timeoutMs: 60_000,\n });\n } catch {\n installRequired = true;\n forceReinstall = true;\n }\n }\n\n if (installRequired) {\n await this.#runCommand(\n uvPath,\n [\n \"pip\",\n \"install\",\n \"--python\",\n pythonPath,\n ...(forceReinstall ? [\"--reinstall\"] : []),\n \"--require-hashes\",\n \"--requirement\",\n this.#requirementsPath,\n ],\n { cwd: installDirectory, env: environment, timeoutMs: 30 * 60 * 1000 },\n );\n await this.#runCommand(pythonPath, healthCheck, {\n cwd: installDirectory,\n env: environment,\n timeoutMs: 60_000,\n });\n await writeFile(\n markerPath,\n JSON.stringify({ needleVersion: NEEDLE_VERSION, requirementsDigest }),\n \"utf8\",\n );\n }\n\n this.#pythonPath = pythonPath;\n this.#environment = environment;\n }\n\n #makeEnvironment(\n uvPath?: string,\n environmentDirectory?: string,\n ): NodeJS.ProcessEnv {\n const pathParts = [\n environmentDirectory ? dirname(pythonIn(environmentDirectory)) : undefined,\n uvPath ? dirname(uvPath) : undefined,\n process.env.PATH,\n ].filter((part): part is string => Boolean(part));\n return {\n ...process.env,\n PATH: pathParts.join(process.platform === \"win32\" ? \";\" : \":\"),\n PYTHONNOUSERSITE: \"1\",\n PYTHONUNBUFFERED: \"1\",\n NEEDLE_TELEMETRY: \"0\",\n DO_NOT_TRACK: \"1\",\n HF_HOME: join(this.#runtimeDirectory, \"huggingface\"),\n UV_CACHE_DIR: join(this.#runtimeDirectory, \"uv-cache\"),\n XDG_CACHE_HOME: join(this.#runtimeDirectory, \"cache\"),\n };\n }\n\n async #findOrInstallUv(environment: NodeJS.ProcessEnv): Promise<string> {\n const candidates = [process.env.SWAPAI_UV_PATH, \"uv\"].filter(\n (candidate): candidate is string => Boolean(candidate),\n );\n for (const candidate of candidates) {\n try {\n await this.#runCommand(candidate, [\"--version\"], {\n env: environment,\n timeoutMs: 30_000,\n });\n return candidate;\n } catch {\n // Try the managed copy next.\n }\n }\n\n const managed = join(\n this.#runtimeDirectory,\n \"tools\",\n process.platform === \"win32\" ? \"uv.exe\" : \"uv\",\n );\n if (!(await exists(managed))) {\n await this.#downloadUv(managed, environment);\n }\n await this.#runCommand(managed, [\"--version\"], {\n env: environment,\n timeoutMs: 30_000,\n });\n return managed;\n }\n\n async #downloadUv(\n destination: string,\n environment: NodeJS.ProcessEnv,\n ): Promise<void> {\n const asset = uvAsset();\n const toolsDirectory = dirname(destination);\n const archivePath = join(toolsDirectory, asset);\n const extractDirectory = join(toolsDirectory, `uv-${UV_VERSION}`);\n await mkdir(extractDirectory, { recursive: true });\n const release = `https://github.com/astral-sh/uv/releases/download/${UV_VERSION}`;\n\n const [archiveResponse, sumsResponse] = await Promise.all([\n this.#fetch(`${release}/${asset}`, {\n signal: AbortSignal.timeout(5 * 60 * 1000),\n }),\n this.#fetch(`${release}/sha256.sum`, {\n signal: AbortSignal.timeout(5 * 60 * 1000),\n }),\n ]);\n if (!archiveResponse.ok || !sumsResponse.ok) {\n throw new Error(`Could not download the managed uv ${UV_VERSION} binary.`);\n }\n const archive = Buffer.from(await archiveResponse.arrayBuffer());\n const sums = await sumsResponse.text();\n const expected = checksumFor(asset, sums);\n const actual = createHash(\"sha256\").update(archive).digest(\"hex\");\n if (actual !== expected) {\n throw new Error(\"The managed uv download failed its SHA-256 check.\");\n }\n await writeFile(archivePath, archive);\n await this.#runCommand(\n \"tar\",\n [asset.endsWith(\".tar.gz\") ? \"-xzf\" : \"-xf\", archivePath, \"-C\", extractDirectory],\n { env: environment, timeoutMs: 5 * 60 * 1000 },\n );\n const extracted = await findFile(\n extractDirectory,\n process.platform === \"win32\" ? \"uv.exe\" : \"uv\",\n );\n if (!extracted) throw new Error(\"The managed uv archive did not contain uv.\");\n await copyFile(extracted, destination);\n if (process.platform !== \"win32\") await chmod(destination, 0o755);\n }\n}\n\nclass NeedleModelProcess implements LoadedNeedleModel {\n readonly #process: NeedleChildProcess;\n readonly #resultConfig: NeedleResultConfig;\n readonly #numberLabels: NeedleNumberLabels | undefined;\n readonly #onBackgroundError: (error: NeedleRuntimeError) => void;\n readonly #onClose: () => void;\n readonly #pending = new Map<\n number,\n {\n readonly resolve: (value: NeedleResultValue) => void;\n readonly reject: (error: NeedleRuntimeError) => void;\n }\n >();\n readonly #readyPromise: Promise<void>;\n readonly #exitPromise: Promise<void>;\n #resolveReady!: () => void;\n #rejectReady!: (error: NeedleRuntimeError) => void;\n #resolveExit!: () => void;\n #requestId = 0;\n #ready = false;\n #exited = false;\n #closing = false;\n #stderr = \"\";\n\n constructor(\n process: NeedleChildProcess,\n resultConfig: NeedleResultConfig,\n numberLabels: NeedleNumberLabels | undefined,\n onBackgroundError: (error: NeedleRuntimeError) => void,\n onClose: () => void,\n ) {\n this.#process = process;\n this.#resultConfig = resultConfig;\n this.#numberLabels = numberLabels;\n this.#onBackgroundError = onBackgroundError;\n this.#onClose = onClose;\n this.#readyPromise = new Promise((resolve, reject) => {\n this.#resolveReady = resolve;\n this.#rejectReady = reject;\n });\n this.#exitPromise = new Promise((resolve) => {\n this.#resolveExit = resolve;\n });\n this.#listen();\n }\n\n ready(): Promise<void> {\n return withTimeout(\n this.#readyPromise,\n 300_000,\n \"Needle did not become ready within five minutes.\",\n );\n }\n\n classify(input: string): Promise<NeedleResultValue> {\n if (!this.#ready || this.#closing || this.#exited) {\n return Promise.reject(\n new NeedleRuntimeError(\"service_unavailable\", \"Needle model is not running.\"),\n );\n }\n const id = ++this.#requestId;\n const result = new Promise<NeedleResultValue>((resolve, reject) => {\n this.#pending.set(id, { resolve, reject });\n this.#process.stdin.write(\n `${JSON.stringify({ id, type: \"classify\", input })}\\n`,\n (error?: Error | null) => {\n if (!error) return;\n this.#pending.delete(id);\n reject(\n new NeedleRuntimeError(\n \"service_unavailable\",\n \"Could not send input to Needle.\",\n error,\n ),\n );\n },\n );\n });\n return withTimeout(\n result,\n 60_000,\n \"Needle did not classify the input within one minute.\",\n () => this.#pending.delete(id),\n );\n }\n\n async close(): Promise<void> {\n if (this.#exited) return;\n if (!this.#closing) {\n this.#closing = true;\n this.#process.stdin.write(`${JSON.stringify({ type: \"close\" })}\\n`);\n }\n try {\n await withTimeout(this.#exitPromise, 5_000, \"Needle did not stop.\");\n } catch {\n this.#process.kill(\"SIGTERM\");\n try {\n await withTimeout(this.#exitPromise, 2_000, \"Needle ignored SIGTERM.\");\n } catch {\n this.#process.kill(\"SIGKILL\");\n await withTimeout(this.#exitPromise, 2_000, \"Needle ignored SIGKILL.\");\n }\n }\n }\n\n #listen(): void {\n const lines = createInterface({ input: this.#process.stdout });\n lines.on(\"line\", (line) => this.#handleLine(line));\n this.#process.stderr.on(\"data\", (chunk: Buffer | string) => {\n this.#stderr = `${this.#stderr}${chunk.toString()}`.slice(-16_384);\n });\n this.#process.once(\"error\", (error: Error) => {\n this.#fail(\n new NeedleRuntimeError(\"service_unavailable\", \"Needle process failed.\", error),\n );\n });\n this.#process.once(\n \"exit\",\n (code: number | null, signal: NodeJS.Signals | null) => {\n this.#exited = true;\n this.#resolveExit();\n this.#onClose();\n if (this.#closing && code === 0) {\n this.#ready = false;\n return;\n }\n const detail = this.#stderr.trim();\n this.#fail(\n new NeedleRuntimeError(\n \"service_unavailable\",\n `Needle stopped${code === null ? ` with ${signal ?? \"a signal\"}` : ` with code ${code}`}${detail ? `: ${detail}` : \".\"}`,\n ),\n );\n },\n );\n }\n\n #handleLine(line: string): void {\n let message: unknown;\n try {\n message = JSON.parse(line);\n } catch (error) {\n this.#fail(\n new NeedleRuntimeError(\n \"service_unavailable\",\n \"Needle returned invalid process data.\",\n error,\n ),\n );\n return;\n }\n if (!isRecord(message)) return;\n\n if (message.type === \"ready\") {\n if (message.needleVersion !== NEEDLE_VERSION) {\n this.#fail(\n new NeedleRuntimeError(\n \"service_unavailable\",\n `Needle ${NEEDLE_VERSION} is required; worker reported ${String(message.needleVersion)}.`,\n ),\n );\n return;\n }\n this.#ready = true;\n this.#resolveReady();\n return;\n }\n if (message.type === \"error\" && !this.#ready) {\n this.#fail(\n new NeedleRuntimeError(\n \"service_unavailable\",\n `Needle could not start: ${String(message.message ?? \"unknown error\")}`,\n ),\n );\n return;\n }\n if (typeof message.id !== \"number\") return;\n const pending = this.#pending.get(message.id);\n if (!pending) return;\n this.#pending.delete(message.id);\n\n if (message.ok !== true) {\n const workerError = isRecord(message.error)\n ? String(message.error.message ?? \"Needle classification failed.\")\n : \"Needle classification failed.\";\n pending.reject(\n new NeedleRuntimeError(\"classification_failed\", workerError),\n );\n return;\n }\n try {\n pending.resolve(\n decodeNeedleResult(\n message.result,\n this.#resultConfig,\n this.#numberLabels,\n ),\n );\n } catch (error) {\n pending.reject(\n new NeedleRuntimeError(\n \"classification_failed\",\n \"Needle returned an invalid classification.\",\n error,\n ),\n );\n }\n }\n\n #fail(error: NeedleRuntimeError): void {\n const wasReady = this.#ready;\n this.#ready = false;\n if (!wasReady) this.#rejectReady(error);\n for (const pending of this.#pending.values()) pending.reject(error);\n this.#pending.clear();\n if (wasReady && !this.#closing) this.#onBackgroundError(error);\n if (!this.#exited && !this.#closing) this.#process.kill(\"SIGTERM\");\n }\n}\n\nconst spawnProcess: NeedleSpawn = (command, args, options) =>\n spawn(command, [...args], {\n cwd: options.cwd,\n env: options.env,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n\nconst runCommand: RunCommand = (command, args, options) =>\n new Promise((resolve, reject) => {\n const child = spawn(command, [...args], {\n cwd: options?.cwd,\n env: options?.env,\n stdio: [options?.stdin === undefined ? \"ignore\" : \"pipe\", \"pipe\", \"pipe\"],\n });\n if (options?.stdin !== undefined && child.stdin !== null) {\n child.stdin.on(\"error\", () => undefined);\n child.stdin.end(options.stdin, \"utf8\");\n }\n let stdout = \"\";\n let stderr = \"\";\n let timedOut = false;\n let settled = false;\n let forceKill: ReturnType<typeof setTimeout> | undefined;\n let rejectAfterKill: ReturnType<typeof setTimeout> | undefined;\n const timeout = options?.timeoutMs === undefined\n ? undefined\n : setTimeout(() => {\n timedOut = true;\n child.kill(\"SIGTERM\");\n forceKill = setTimeout(() => {\n child.kill(\"SIGKILL\");\n rejectAfterKill = setTimeout(() => {\n if (settled) return;\n settled = true;\n clearTimers();\n reject(new Error(`${command} exceeded its time limit.`));\n }, 2_000);\n rejectAfterKill.unref();\n }, 2_000);\n forceKill.unref();\n }, options.timeoutMs);\n timeout?.unref();\n const clearTimers = () => {\n if (timeout !== undefined) clearTimeout(timeout);\n if (forceKill !== undefined) clearTimeout(forceKill);\n if (rejectAfterKill !== undefined) clearTimeout(rejectAfterKill);\n };\n child.stdout!.on(\"data\", (chunk: Buffer | string) => {\n stdout = `${stdout}${chunk.toString()}`.slice(-262_144);\n });\n child.stderr!.on(\"data\", (chunk: Buffer | string) => {\n stderr = `${stderr}${chunk.toString()}`.slice(-262_144);\n });\n child.once(\"error\", (error) => {\n if (settled) return;\n settled = true;\n clearTimers();\n reject(error);\n });\n child.once(\"exit\", (code, signal) => {\n if (settled) return;\n settled = true;\n clearTimers();\n if (timedOut) {\n reject(new Error(`${command} exceeded its time limit.`));\n return;\n }\n if (code === 0) {\n resolve({ stdout, stderr });\n return;\n }\n reject(\n new Error(\n `${command} failed${code === null ? ` with ${signal ?? \"a signal\"}` : ` with code ${code}`}${stderr.trim() ? `: ${stderr.trim()}` : \".\"}`,\n ),\n );\n });\n });\n\nfunction classifierKey(name: string): string {\n const readable = name\n .normalize(\"NFKD\")\n .replace(/[^a-zA-Z0-9_-]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 40) || \"classifier\";\n const hash = createHash(\"sha256\").update(name).digest(\"hex\").slice(0, 12);\n return `${readable}-${hash}`;\n}\n\nfunction pythonIn(environmentDirectory: string): string {\n return process.platform === \"win32\"\n ? join(environmentDirectory, \"Scripts\", \"python.exe\")\n : join(environmentDirectory, \"bin\", \"python\");\n}\n\nasync function exists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readJson(path: string): Promise<Record<string, unknown> | undefined> {\n try {\n const value: unknown = JSON.parse(await readFile(path, \"utf8\"));\n return isRecord(value) ? value : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction uvAsset(): string {\n const key = `${process.platform}-${process.arch}`;\n const assets: Record<string, string> = {\n \"darwin-arm64\": \"uv-aarch64-apple-darwin.tar.gz\",\n \"darwin-x64\": \"uv-x86_64-apple-darwin.tar.gz\",\n \"linux-arm64\": \"uv-aarch64-unknown-linux-gnu.tar.gz\",\n \"linux-x64\": \"uv-x86_64-unknown-linux-gnu.tar.gz\",\n \"win32-arm64\": \"uv-aarch64-pc-windows-msvc.zip\",\n \"win32-x64\": \"uv-x86_64-pc-windows-msvc.zip\",\n };\n const asset = assets[key];\n if (!asset) throw new Error(`SwapAI does not support uv on ${key}.`);\n return asset;\n}\n\nfunction checksumFor(asset: string, sums: string): string {\n for (const line of sums.split(\"\\n\")) {\n const [hash, file] = line.trim().split(/\\s+\\*?/);\n if (file === asset && /^[a-f0-9]{64}$/i.test(hash ?? \"\")) return hash!;\n }\n throw new Error(`The uv checksum list did not contain ${asset}.`);\n}\n\nasync function findFile(directory: string, name: string): Promise<string | undefined> {\n for (const entry of await readdir(directory, { withFileTypes: true })) {\n const path = join(directory, entry.name);\n if (entry.isFile() && entry.name === name) return path;\n if (entry.isDirectory()) {\n const nested = await findFile(path, name);\n if (nested) return nested;\n }\n }\n return undefined;\n}\n\nfunction withTimeout<T>(\n promise: Promise<T>,\n milliseconds: number,\n message: string,\n onTimeout?: () => void,\n): Promise<T> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n onTimeout?.();\n reject(new NeedleRuntimeError(\"service_unavailable\", message));\n }, milliseconds);\n timer.unref();\n promise.then(\n (value) => {\n clearTimeout(timer);\n resolve(value);\n },\n (error) => {\n clearTimeout(timer);\n reject(error);\n },\n );\n });\n}\n\nfunction toRuntimeError(message: string, cause: unknown): NeedleRuntimeError {\n return cause instanceof NeedleRuntimeError\n ? cause\n : new NeedleRuntimeError(\"service_unavailable\", message, cause);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","export type NeedleResultConfig =\n | { readonly type: \"number\"; readonly min: number; readonly max: number }\n | { readonly type: \"boolean\" }\n | { readonly type: \"string\"; readonly values: readonly string[] };\n\nexport type NeedleResultValue = number | boolean | string;\n\nexport interface NeedleExample {\n readonly input: string;\n readonly result: NeedleResultValue;\n}\n\nexport interface NeedleTool {\n readonly name: \"classify\";\n readonly description: string;\n readonly parameters: {\n readonly type: \"object\";\n readonly properties: {\n readonly result: Record<string, unknown>;\n };\n readonly required: readonly [\"result\"];\n readonly additionalProperties: false;\n };\n}\n\nexport interface NeedleNumberLabels {\n readonly values: readonly number[];\n}\n\nexport const MAX_NEEDLE_NUMBER_LABELS = 64;\n\nexport function createNeedleNumberLabels(\n values: readonly number[],\n config: Extract<NeedleResultConfig, { type: \"number\" }>,\n acceptableError = 0,\n): NeedleNumberLabels {\n if (\n typeof acceptableError !== \"number\" ||\n !Number.isFinite(acceptableError) ||\n acceptableError < 0 ||\n acceptableError > 1\n ) {\n throw new TypeError(\"acceptableError must be between 0 and 1.\");\n }\n const valid = values.map((value) =>\n validateNeedleResult(value, config) as number,\n );\n const unique = [...new Set(valid)].sort((left, right) => left - right);\n const desiredLabelCount = acceptableError === 0\n ? MAX_NEEDLE_NUMBER_LABELS\n : Math.min(\n MAX_NEEDLE_NUMBER_LABELS,\n Math.max(2, Math.floor(1 / (2 * acceptableError)) + 1),\n );\n if (unique.length <= desiredLabelCount) return { values: unique };\n\n const width = (config.max - config.min) / desiredLabelCount;\n const occupied = new Set<number>();\n for (const value of unique) {\n occupied.add(Math.min(\n desiredLabelCount - 1,\n Math.floor((value - config.min) / width),\n ));\n }\n return {\n values: [...occupied]\n .sort((left, right) => left - right)\n .map((index) => config.min + (index + 0.5) * width),\n };\n}\n\nfunction numberLabel(index: number, count: number): string {\n if (count === 1) return \"only_score\";\n if (count === 2) return index === 0 ? \"lower_score\" : \"higher_score\";\n return `score_bucket_${index}`;\n}\n\nfunction encodeNumberResult(\n value: number,\n labels: NeedleNumberLabels,\n): string {\n if (labels.values.length === 0) {\n throw new TypeError(\"Numeric result has no Needle label.\");\n }\n let closestIndex = 0;\n let closestDistance = Math.abs(value - labels.values[0]!);\n for (let index = 1; index < labels.values.length; index += 1) {\n const distance = Math.abs(value - labels.values[index]!);\n if (distance < closestDistance) {\n closestIndex = index;\n closestDistance = distance;\n }\n }\n return numberLabel(closestIndex, labels.values.length);\n}\n\nexport function createNeedleTool(\n config: NeedleResultConfig,\n numberLabels?: NeedleNumberLabels,\n): NeedleTool {\n const description = \"The classification result.\";\n let result: Record<string, unknown>;\n\n switch (config.type) {\n case \"number\":\n if (!numberLabels || numberLabels.values.length === 0) {\n throw new TypeError(\"Numeric Needle tools require at least one result label.\");\n }\n result = {\n type: \"string\",\n enum: numberLabels.values.map((_, index) =>\n numberLabel(index, numberLabels.values.length),\n ),\n description:\n `The numeric classification bucket from ${config.min} to ${config.max}.`,\n };\n break;\n case \"boolean\":\n result = { type: \"boolean\", description };\n break;\n case \"string\":\n result = { type: \"string\", enum: [...config.values], description };\n break;\n }\n\n return {\n name: \"classify\",\n description: \"Classify every supplied input and always return the learned result.\",\n parameters: {\n type: \"object\",\n properties: { result },\n required: [\"result\"],\n additionalProperties: false,\n },\n };\n}\n\nexport function createTrainingLine(\n input: string,\n value: NeedleResultValue,\n config: NeedleResultConfig,\n numberLabels?: NeedleNumberLabels,\n): string {\n const result = validateNeedleResult(value, config);\n const needleResult =\n config.type === \"number\"\n ? encodeNumberResult(result as number, numberLabels ?? { values: [] })\n : result;\n return JSON.stringify({\n query: input,\n tools: [createNeedleTool(config, numberLabels)],\n answers: [{ name: \"classify\", arguments: { result: needleResult } }],\n });\n}\n\nexport function validateNeedleResult(\n value: unknown,\n config: NeedleResultConfig,\n): NeedleResultValue {\n switch (config.type) {\n case \"number\":\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n value < config.min ||\n value > config.max\n ) {\n throw new TypeError(\n `Needle returned a number outside ${config.min} to ${config.max}.`,\n );\n }\n return value;\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n throw new TypeError(\"Needle did not return a boolean result.\");\n }\n return value;\n case \"string\":\n if (typeof value !== \"string\" || !config.values.includes(value)) {\n throw new TypeError(\"Needle returned a value that is not an allowed string result.\");\n }\n return value;\n }\n}\n\nexport function readClassificationResult(\n response: unknown,\n config: NeedleResultConfig,\n numberLabels?: NeedleNumberLabels,\n): NeedleResultValue {\n if (!isRecord(response) || !Array.isArray(response.function_calls)) {\n throw new TypeError(\"Needle did not return exactly one classify call.\");\n }\n\n const calls = response.function_calls;\n const call = calls[0];\n if (\n calls.length !== 1 ||\n !isRecord(call) ||\n call.name !== \"classify\" ||\n !isRecord(call.arguments) ||\n !(\"result\" in call.arguments)\n ) {\n throw new TypeError(\"Needle did not return exactly one classify call.\");\n }\n\n return decodeNeedleResult(call.arguments.result, config, numberLabels);\n}\n\nexport function decodeNeedleResult(\n result: unknown,\n config: NeedleResultConfig,\n numberLabels?: NeedleNumberLabels,\n): NeedleResultValue {\n if (config.type === \"number\") {\n if (typeof result !== \"string\") {\n throw new TypeError(\n `Needle returned a number outside ${config.min} to ${config.max}.`,\n );\n }\n const index = numberLabels?.values.findIndex(\n (_, candidateIndex) =>\n result === numberLabel(candidateIndex, numberLabels.values.length),\n ) ?? -1;\n const decoded = numberLabels?.values[index];\n if (index < 0 || decoded === undefined) {\n throw new TypeError(\n `Needle returned a number outside ${config.min} to ${config.max}.`,\n );\n }\n return validateNeedleResult(decoded, config);\n }\n return validateNeedleResult(result, config);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { createHash } from \"node:crypto\";\nimport { chmodSync, mkdirSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { join } from \"node:path\";\nimport type { DatabaseSync as DatabaseSyncType } from \"node:sqlite\";\n\nconst { DatabaseSync } = createRequire(import.meta.url)(\"node:sqlite\") as typeof import(\"node:sqlite\");\n\nexport type StoredResult = number | boolean | string;\nexport type ExampleSplit = \"training\" | \"held_out\";\nexport type GenerationStatus = \"active\" | \"archived\";\n\nexport interface OpenStorageOptions {\n dataDirectory: string;\n name: string;\n config: unknown;\n maxTrainingSet: number;\n}\n\nexport interface StoredExample {\n id: number;\n generation: number;\n input: string;\n result: StoredResult;\n split: ExampleSplit;\n createdAt: number;\n}\n\nexport interface StoredGeneration {\n generation: number;\n status: GenerationStatus;\n trained: boolean;\n modelPath: string | null;\n needleVersion: string | null;\n createdAt: number;\n archivedAt: number | null;\n}\n\nexport interface StorageSnapshot {\n name: string;\n config: unknown;\n activeGeneration: number;\n activeExampleCount: number;\n totalExamplesLogged: number;\n newExamplesSinceTraining: number;\n trainingAttempts: number;\n examplesUsedForTraining: number;\n localClassificationsSinceRetest: number;\n totalLocalClassifications: number;\n totalRetests: number;\n consecutiveRetestFailures: number;\n trained: boolean;\n modelPath: string | null;\n needleVersion: string | null;\n dataEpoch: number;\n clearPending: boolean;\n clearErased: boolean;\n clearArtifactGenerationMax: number | null;\n trainingLeaseOwner: string | null;\n trainingLeaseEpoch: number | null;\n trainingLeaseUntil: number | null;\n}\n\nexport interface PromotedModel {\n modelPath: string;\n needleVersion: string;\n}\n\nexport interface ArchiveAndResetOptions {\n readonly retainExamples?: boolean;\n}\n\nexport interface Storage {\n readonly databasePath: string;\n snapshot(): StorageSnapshot;\n addExample(\n input: string,\n result: StoredResult,\n expectedDataEpoch?: number,\n ): StoredExample | null;\n listExamples(split?: ExampleSplit, generation?: number): StoredExample[];\n listExamplesForTraining(\n split: ExampleSplit,\n generation: number,\n expectedDataEpoch: number,\n ): StoredExample[] | null;\n markTrainingAttempted(exampleCount: number, expectedDataEpoch?: number): boolean;\n promoteGeneration(\n model: PromotedModel,\n expectedDataEpoch?: number,\n ): StoredGeneration | null;\n recordLocalClassification(expectedDataEpoch?: number): number | null;\n recordRetest(passed: boolean, expectedDataEpoch?: number): number | null;\n claimTrainingLease(\n owner: string,\n durationMs: number,\n expectedDataEpoch?: number,\n ): boolean;\n releaseTrainingLease(owner: string): void;\n archiveAndReset(\n expectedDataEpoch?: number,\n options?: ArchiveAndResetOptions,\n ): StoredGeneration | null;\n beginClearTrainingData(): number;\n eraseTrainingData(dataEpoch: number): StoredGeneration | null;\n finishClearTrainingData(dataEpoch: number): boolean;\n clearTrainingData(): StoredGeneration;\n claimArtifactWriteLock(): boolean;\n releaseArtifactWriteLock(): void;\n listGenerations(): StoredGeneration[];\n close(): void;\n}\n\ninterface ClassifierRow {\n name: string;\n config_json: string;\n active_generation: number;\n total_examples_logged: number;\n new_examples_since_training: number;\n training_attempts: number;\n examples_used_for_training: number;\n local_classifications_since_retest: number;\n total_local_classifications: number;\n total_retests: number;\n consecutive_retest_failures: number;\n trained: number;\n model_path: string | null;\n needle_version: string | null;\n active_example_count: number;\n data_epoch: number;\n clear_pending: number;\n clear_erased: number;\n clear_artifact_generation_max: number | null;\n training_lease_owner: string | null;\n training_lease_epoch: number | null;\n training_lease_until: number | null;\n}\n\ninterface ExampleRow {\n id: number;\n generation: number;\n input: string;\n result_json: string;\n split: ExampleSplit;\n created_at: number;\n}\n\ninterface GenerationRow {\n generation: number;\n status: GenerationStatus;\n trained: number;\n model_path: string | null;\n needle_version: string | null;\n created_at: number;\n archived_at: number | null;\n}\n\nconst SCHEMA = `\n CREATE TABLE IF NOT EXISTS classifiers (\n name TEXT PRIMARY KEY,\n config_json TEXT NOT NULL,\n max_training_set INTEGER NOT NULL,\n active_generation INTEGER NOT NULL DEFAULT 1,\n total_examples_logged INTEGER NOT NULL DEFAULT 0,\n new_examples_since_training INTEGER NOT NULL DEFAULT 0,\n training_attempts INTEGER NOT NULL DEFAULT 0,\n examples_used_for_training INTEGER NOT NULL DEFAULT 0,\n local_classifications_since_retest INTEGER NOT NULL DEFAULT 0,\n total_local_classifications INTEGER NOT NULL DEFAULT 0,\n total_retests INTEGER NOT NULL DEFAULT 0,\n consecutive_retest_failures INTEGER NOT NULL DEFAULT 0,\n training_lease_owner TEXT,\n training_lease_until INTEGER,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n data_epoch INTEGER NOT NULL DEFAULT 0,\n clear_pending INTEGER NOT NULL DEFAULT 0,\n clear_erased INTEGER NOT NULL DEFAULT 0,\n clear_artifact_generation_max INTEGER,\n training_lease_epoch INTEGER\n );\n\n CREATE TABLE IF NOT EXISTS generations (\n classifier_name TEXT NOT NULL,\n generation INTEGER NOT NULL,\n status TEXT NOT NULL CHECK (status IN ('active', 'archived')),\n trained INTEGER NOT NULL DEFAULT 0,\n model_path TEXT,\n needle_version TEXT,\n created_at INTEGER NOT NULL,\n archived_at INTEGER,\n PRIMARY KEY (classifier_name, generation),\n FOREIGN KEY (classifier_name) REFERENCES classifiers(name) ON DELETE CASCADE\n );\n\n CREATE TABLE IF NOT EXISTS examples (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n classifier_name TEXT NOT NULL,\n generation INTEGER NOT NULL,\n input TEXT NOT NULL,\n result_json TEXT NOT NULL,\n split TEXT NOT NULL CHECK (split IN ('training', 'held_out')),\n created_at INTEGER NOT NULL,\n FOREIGN KEY (classifier_name, generation)\n REFERENCES generations(classifier_name, generation) ON DELETE CASCADE\n );\n\n CREATE INDEX IF NOT EXISTS examples_by_generation\n ON examples(classifier_name, generation, id);\n CREATE INDEX IF NOT EXISTS examples_by_split\n ON examples(classifier_name, generation, split, id);\n\n CREATE TRIGGER IF NOT EXISTS swapai_v2_classifiers_insert\n BEFORE INSERT ON classifiers\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n CREATE TRIGGER IF NOT EXISTS swapai_v2_classifiers_update\n BEFORE UPDATE ON classifiers\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n CREATE TRIGGER IF NOT EXISTS swapai_v2_classifiers_delete\n BEFORE DELETE ON classifiers\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n CREATE TRIGGER IF NOT EXISTS swapai_v2_generations_insert\n BEFORE INSERT ON generations\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n CREATE TRIGGER IF NOT EXISTS swapai_v2_generations_update\n BEFORE UPDATE ON generations\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n CREATE TRIGGER IF NOT EXISTS swapai_v2_generations_delete\n BEFORE DELETE ON generations\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n CREATE TRIGGER IF NOT EXISTS swapai_v2_examples_insert\n BEFORE INSERT ON examples\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n CREATE TRIGGER IF NOT EXISTS swapai_v2_examples_update\n BEFORE UPDATE ON examples\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n CREATE TRIGGER IF NOT EXISTS swapai_v2_examples_delete\n BEFORE DELETE ON examples\n WHEN swapai_writer_version() < 2\n BEGIN SELECT RAISE(ABORT, 'SwapAI writer is too old'); END;\n`;\n\nexport function assignExampleSplit(name: string, input: string): ExampleSplit {\n const hash = createHash(\"sha256\")\n .update(name)\n .update(\"\\0\")\n .update(input)\n .digest();\n\n return hash.readUInt32BE(0) % 10 < 8 ? \"training\" : \"held_out\";\n}\n\nexport function openStorage(options: OpenStorageOptions): Storage {\n if (!Number.isSafeInteger(options.maxTrainingSet) || options.maxTrainingSet <= 0) {\n throw new TypeError(\"maxTrainingSet must be a positive integer\");\n }\n\n mkdirSync(options.dataDirectory, { recursive: true, mode: 0o700 });\n chmodSync(options.dataDirectory, 0o700);\n const databasePath = join(options.dataDirectory, \"swapai.sqlite\");\n const database = new DatabaseSync(databasePath);\n let artifactLockDatabase: DatabaseSyncType | null = null;\n try {\n database.function(\n \"swapai_writer_version\",\n { deterministic: true },\n () => 2,\n );\n chmodSync(databasePath, 0o600);\n database.exec(\"PRAGMA journal_mode = WAL\");\n database.exec(\"PRAGMA foreign_keys = ON\");\n database.exec(\"PRAGMA secure_delete = ON\");\n database.exec(\"PRAGMA busy_timeout = 5000\");\n const secureDelete = requiredRow<{ secure_delete: number }>(\n database.prepare(\"PRAGMA secure_delete\").get(),\n );\n if (secureDelete.secure_delete !== 1) {\n throw new Error(\"SQLite secure deletion could not be enabled\");\n }\n database.exec(SCHEMA);\n migrateClassifierColumns(database);\n const lockDirectory = join(options.dataDirectory, \"locks\");\n mkdirSync(lockDirectory, { recursive: true, mode: 0o700 });\n chmodSync(lockDirectory, 0o700);\n const lockPath = join(\n lockDirectory,\n `${createHash(\"sha256\").update(options.name).digest(\"hex\")}.sqlite`,\n );\n artifactLockDatabase = new DatabaseSync(lockPath);\n chmodSync(lockPath, 0o600);\n artifactLockDatabase.exec(\"PRAGMA busy_timeout = 0\");\n artifactLockDatabase.exec(\n \"CREATE TABLE IF NOT EXISTS artifact_lock (id INTEGER PRIMARY KEY)\",\n );\n\n const now = Date.now();\n const configJson = stringifyJson(options.config, \"classifier config\");\n const existing = database.prepare(`\n SELECT config_json FROM classifiers WHERE name = ?\n `).get(options.name) as { config_json: string } | undefined;\n\n if (\n existing !== undefined\n && criticalConfigJson(existing.config_json) !== criticalConfigJson(configJson)\n ) {\n throw new TypeError(\n `Classifier \"${options.name}\" already exists with different result or behavior settings`,\n );\n }\n\n transaction(database, () => {\n database.prepare(`\n INSERT INTO classifiers (\n name, config_json, max_training_set, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?)\n ON CONFLICT(name) DO UPDATE SET\n config_json = excluded.config_json,\n max_training_set = excluded.max_training_set,\n updated_at = excluded.updated_at\n `).run(options.name, configJson, options.maxTrainingSet, now, now);\n\n database.prepare(`\n INSERT OR IGNORE INTO generations (\n classifier_name, generation, status, created_at\n ) VALUES (?, 1, 'active', ?)\n `).run(options.name, now);\n\n trimExamples(\n database,\n options.name,\n activeGeneration(database, options.name),\n options.maxTrainingSet,\n );\n });\n } catch (error) {\n try {\n artifactLockDatabase?.close();\n } catch {\n // Preserve the initialization error after attempting to close both handles.\n }\n try {\n database.close();\n } catch {\n // Preserve the initialization error after attempting to close both handles.\n }\n throw error;\n }\n\n const initializedArtifactLockDatabase = artifactLockDatabase;\n\n let closed = false;\n let artifactLockHeld = false;\n\n const storage: Storage = {\n databasePath,\n\n snapshot() {\n assertOpen(closed);\n const row = requiredRow<ClassifierRow>(database.prepare(`\n SELECT\n c.name,\n c.config_json,\n c.active_generation,\n c.total_examples_logged,\n c.new_examples_since_training,\n c.training_attempts,\n c.examples_used_for_training,\n c.local_classifications_since_retest,\n c.total_local_classifications,\n c.total_retests,\n c.consecutive_retest_failures,\n g.trained,\n g.model_path,\n g.needle_version,\n c.data_epoch,\n c.clear_pending,\n c.clear_erased,\n c.clear_artifact_generation_max,\n c.training_lease_owner,\n c.training_lease_epoch,\n c.training_lease_until,\n (\n SELECT COUNT(*)\n FROM examples e\n WHERE e.classifier_name = c.name\n AND e.generation = c.active_generation\n ) AS active_example_count\n FROM classifiers c\n JOIN generations g\n ON g.classifier_name = c.name\n AND g.generation = c.active_generation\n WHERE c.name = ?\n `).get(options.name));\n\n return {\n name: row.name,\n config: JSON.parse(row.config_json) as unknown,\n activeGeneration: row.active_generation,\n activeExampleCount: row.active_example_count,\n totalExamplesLogged: row.total_examples_logged,\n newExamplesSinceTraining: row.new_examples_since_training,\n trainingAttempts: row.training_attempts,\n examplesUsedForTraining: row.examples_used_for_training,\n localClassificationsSinceRetest: row.local_classifications_since_retest,\n totalLocalClassifications: row.total_local_classifications,\n totalRetests: row.total_retests,\n consecutiveRetestFailures: row.consecutive_retest_failures,\n trained: row.trained === 1,\n modelPath: row.model_path,\n needleVersion: row.needle_version,\n dataEpoch: row.data_epoch,\n clearPending: row.clear_pending === 1,\n clearErased: row.clear_erased === 1,\n clearArtifactGenerationMax: row.clear_artifact_generation_max,\n trainingLeaseOwner: row.training_lease_owner,\n trainingLeaseEpoch: row.training_lease_epoch,\n trainingLeaseUntil: row.training_lease_until,\n };\n },\n\n addExample(input, result, expectedDataEpoch) {\n assertOpen(closed);\n const split = assignExampleSplit(options.name, input);\n const createdAt = Date.now();\n const resultJson = stringifyJson(result, \"classification result\");\n let id = 0;\n let generation = 0;\n let accepted = false;\n\n transaction(database, () => {\n const state = classifierState(database, options.name);\n const epoch = expectedDataEpoch ?? state.data_epoch;\n if (state.data_epoch !== epoch || state.clear_pending === 1) return;\n generation = state.active_generation;\n const insertion = database.prepare(`\n INSERT INTO examples (\n classifier_name, generation, input, result_json, split, created_at\n ) VALUES (?, ?, ?, ?, ?, ?)\n `).run(options.name, generation, input, resultJson, split, createdAt);\n id = Number(insertion.lastInsertRowid);\n accepted = true;\n\n database.prepare(`\n UPDATE classifiers\n SET total_examples_logged = total_examples_logged + 1,\n new_examples_since_training = new_examples_since_training + 1,\n updated_at = ?\n WHERE name = ?\n `).run(createdAt, options.name);\n\n trimExamples(database, options.name, generation, options.maxTrainingSet);\n });\n\n return accepted\n ? { id, generation, input, result, split, createdAt }\n : null;\n },\n\n listExamples(split, generation) {\n assertOpen(closed);\n const selectedGeneration = generation ?? activeGeneration(database, options.name);\n const rows = split === undefined\n ? database.prepare(`\n SELECT id, generation, input, result_json, split, created_at\n FROM examples\n WHERE classifier_name = ? AND generation = ?\n ORDER BY id\n `).all(options.name, selectedGeneration)\n : database.prepare(`\n SELECT id, generation, input, result_json, split, created_at\n FROM examples\n WHERE classifier_name = ? AND generation = ? AND split = ?\n ORDER BY id\n `).all(options.name, selectedGeneration, split);\n\n return rows.map((value) => mapExample(row<ExampleRow>(value)));\n },\n\n listExamplesForTraining(split, generation, expectedDataEpoch) {\n assertOpen(closed);\n let examples: StoredExample[] | null = null;\n transaction(database, () => {\n const state = classifierState(database, options.name);\n if (\n state.data_epoch !== expectedDataEpoch ||\n state.clear_pending === 1 ||\n state.active_generation !== generation\n ) {\n return;\n }\n examples = database.prepare(`\n SELECT id, generation, input, result_json, split, created_at\n FROM examples\n WHERE classifier_name = ? AND generation = ? AND split = ?\n ORDER BY id\n `).all(options.name, generation, split).map((value) =>\n mapExample(row<ExampleRow>(value)),\n );\n });\n return examples;\n },\n\n markTrainingAttempted(exampleCount, expectedDataEpoch) {\n assertOpen(closed);\n if (!Number.isSafeInteger(exampleCount) || exampleCount <= 0) {\n throw new TypeError(\"training example count must be a positive integer\");\n }\n const epoch = expectedDataEpoch ?? storage.snapshot().dataEpoch;\n const result = database.prepare(`\n UPDATE classifiers\n SET new_examples_since_training = 0,\n training_attempts = training_attempts + 1,\n examples_used_for_training = ?,\n updated_at = ?\n WHERE name = ? AND data_epoch = ? AND clear_pending = 0\n `).run(exampleCount, Date.now(), options.name, epoch);\n return result.changes === 1;\n },\n\n promoteGeneration(model, expectedDataEpoch) {\n assertOpen(closed);\n let generation = 0;\n let promoted = false;\n transaction(database, () => {\n const state = classifierState(database, options.name);\n const epoch = expectedDataEpoch ?? state.data_epoch;\n if (state.data_epoch !== epoch || state.clear_pending === 1) return;\n generation = state.active_generation;\n database.prepare(`\n UPDATE generations\n SET trained = 1, model_path = ?, needle_version = ?\n WHERE classifier_name = ? AND generation = ?\n `).run(model.modelPath, model.needleVersion, options.name, generation);\n promoted = true;\n });\n return promoted\n ? generationByNumber(database, options.name, generation)\n : null;\n },\n\n recordLocalClassification(expectedDataEpoch) {\n assertOpen(closed);\n const epoch = expectedDataEpoch ?? storage.snapshot().dataEpoch;\n const result = database.prepare(`\n UPDATE classifiers\n SET local_classifications_since_retest = local_classifications_since_retest + 1,\n total_local_classifications = total_local_classifications + 1,\n updated_at = ?\n WHERE name = ? AND data_epoch = ? AND clear_pending = 0\n `).run(Date.now(), options.name, epoch);\n if (result.changes !== 1) return null;\n return storage.snapshot().localClassificationsSinceRetest;\n },\n\n recordRetest(passed, expectedDataEpoch) {\n assertOpen(closed);\n const epoch = expectedDataEpoch ?? storage.snapshot().dataEpoch;\n const result = database.prepare(`\n UPDATE classifiers\n SET local_classifications_since_retest = 0,\n total_retests = total_retests + 1,\n consecutive_retest_failures = CASE\n WHEN ? = 1 THEN 0\n ELSE consecutive_retest_failures + 1\n END,\n updated_at = ?\n WHERE name = ? AND data_epoch = ? AND clear_pending = 0\n `).run(passed ? 1 : 0, Date.now(), options.name, epoch);\n if (result.changes !== 1) return null;\n return storage.snapshot().consecutiveRetestFailures;\n },\n\n claimTrainingLease(owner, durationMs, expectedDataEpoch) {\n assertOpen(closed);\n if (owner.trim() === \"\" || !Number.isSafeInteger(durationMs) || durationMs <= 0) {\n throw new TypeError(\"training lease needs an owner and positive duration\");\n }\n const now = Date.now();\n const epoch = expectedDataEpoch ?? storage.snapshot().dataEpoch;\n const result = database.prepare(`\n UPDATE classifiers\n SET training_lease_owner = ?,\n training_lease_until = ?,\n training_lease_epoch = ?,\n updated_at = ?\n WHERE name = ?\n AND data_epoch = ?\n AND clear_pending = 0\n AND (\n training_lease_owner IS NULL\n OR training_lease_until <= ?\n OR training_lease_owner = ?\n )\n `).run(owner, now + durationMs, epoch, now, options.name, epoch, now, owner);\n return result.changes === 1;\n },\n\n releaseTrainingLease(owner) {\n assertOpen(closed);\n database.prepare(`\n UPDATE classifiers\n SET training_lease_owner = NULL,\n training_lease_until = NULL,\n training_lease_epoch = NULL,\n updated_at = ?\n WHERE name = ? AND training_lease_owner = ?\n `).run(Date.now(), options.name, owner);\n },\n\n archiveAndReset(expectedDataEpoch, resetOptions) {\n assertOpen(closed);\n let nextGeneration = 0;\n const changedAt = Date.now();\n let reset = false;\n\n transaction(database, () => {\n const state = classifierState(database, options.name);\n const epoch = expectedDataEpoch ?? state.data_epoch;\n if (state.data_epoch !== epoch || state.clear_pending === 1) return;\n const currentGeneration = state.active_generation;\n database.prepare(`\n UPDATE generations\n SET status = 'archived', archived_at = ?\n WHERE classifier_name = ? AND generation = ?\n `).run(changedAt, options.name, currentGeneration);\n\n const maximum = requiredRow<{ maximum: number }>(database.prepare(`\n SELECT MAX(generation) AS maximum\n FROM generations\n WHERE classifier_name = ?\n `).get(options.name));\n nextGeneration = maximum.maximum + 1;\n\n database.prepare(`\n INSERT INTO generations (\n classifier_name, generation, status, created_at\n ) VALUES (?, ?, 'active', ?)\n `).run(options.name, nextGeneration, changedAt);\n\n let retainedExampleCount = 0;\n if (resetOptions?.retainExamples) {\n retainedExampleCount = Number(database.prepare(`\n UPDATE examples\n SET generation = ?\n WHERE classifier_name = ? AND generation = ?\n `).run(nextGeneration, options.name, currentGeneration).changes);\n }\n\n database.prepare(`\n UPDATE classifiers\n SET active_generation = ?,\n data_epoch = data_epoch + 1,\n new_examples_since_training = ?,\n training_attempts = 0,\n examples_used_for_training = 0,\n training_lease_owner = NULL,\n training_lease_until = NULL,\n training_lease_epoch = NULL,\n local_classifications_since_retest = 0,\n consecutive_retest_failures = 0,\n updated_at = ?\n WHERE name = ?\n `).run(\n nextGeneration,\n retainedExampleCount,\n changedAt,\n options.name,\n );\n reset = true;\n });\n\n return reset\n ? generationByNumber(database, options.name, nextGeneration)\n : null;\n },\n\n beginClearTrainingData() {\n assertOpen(closed);\n database.prepare(`\n UPDATE classifiers\n SET data_epoch = data_epoch + 1,\n clear_pending = 1,\n clear_erased = 0,\n clear_artifact_generation_max = (\n SELECT MAX(generation)\n FROM generations\n WHERE classifier_name = ?\n ),\n updated_at = ?\n WHERE name = ?\n `).run(options.name, Date.now(), options.name);\n return classifierState(database, options.name).data_epoch;\n },\n\n eraseTrainingData(dataEpoch) {\n assertOpen(closed);\n let nextGeneration = 0;\n const changedAt = Date.now();\n let erased = false;\n\n transaction(database, () => {\n const state = classifierState(database, options.name);\n if (state.data_epoch !== dataEpoch || state.clear_pending !== 1) return;\n if (state.clear_erased === 1) return;\n const maximum = requiredRow<{ maximum: number }>(database.prepare(`\n SELECT MAX(generation) AS maximum\n FROM generations\n WHERE classifier_name = ?\n `).get(options.name));\n nextGeneration = maximum.maximum + 1;\n\n database.prepare(`\n DELETE FROM examples WHERE classifier_name = ?\n `).run(options.name);\n database.prepare(`\n DELETE FROM generations WHERE classifier_name = ?\n `).run(options.name);\n database.prepare(`\n INSERT INTO generations (\n classifier_name, generation, status, created_at\n ) VALUES (?, ?, 'active', ?)\n `).run(options.name, nextGeneration, changedAt);\n database.prepare(`\n UPDATE classifiers\n SET active_generation = ?,\n total_examples_logged = 0,\n new_examples_since_training = 0,\n training_attempts = 0,\n examples_used_for_training = 0,\n local_classifications_since_retest = 0,\n total_local_classifications = 0,\n total_retests = 0,\n consecutive_retest_failures = 0,\n training_lease_owner = NULL,\n training_lease_until = NULL,\n training_lease_epoch = NULL,\n clear_erased = 1,\n updated_at = ?\n WHERE name = ?\n `).run(nextGeneration, changedAt, options.name);\n erased = true;\n });\n\n if (!erased) return null;\n\n truncateWriteAheadLog(database);\n\n return generationByNumber(database, options.name, nextGeneration);\n },\n\n finishClearTrainingData(dataEpoch) {\n assertOpen(closed);\n const state = classifierState(database, options.name);\n if (\n state.data_epoch !== dataEpoch ||\n state.clear_pending !== 1 ||\n state.clear_erased !== 1\n ) {\n return false;\n }\n truncateWriteAheadLog(database);\n const result = database.prepare(`\n UPDATE classifiers\n SET clear_pending = 0, updated_at = ?\n WHERE name = ?\n AND data_epoch = ?\n AND clear_pending = 1\n AND clear_erased = 1\n `).run(Date.now(), options.name, dataEpoch);\n return result.changes === 1;\n },\n\n clearTrainingData() {\n const dataEpoch = storage.beginClearTrainingData();\n if (!storage.claimArtifactWriteLock()) {\n throw new Error(\"Classifier artifacts are currently being written\");\n }\n try {\n const generation = storage.eraseTrainingData(dataEpoch);\n if (generation === null || !storage.finishClearTrainingData(dataEpoch)) {\n throw new Error(\"Training data clear was superseded\");\n }\n return generation;\n } finally {\n storage.releaseArtifactWriteLock();\n }\n },\n\n claimArtifactWriteLock() {\n assertOpen(closed);\n if (artifactLockHeld) return true;\n try {\n initializedArtifactLockDatabase.exec(\"BEGIN IMMEDIATE\");\n artifactLockHeld = true;\n return true;\n } catch (error) {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"ERR_SQLITE_ERROR\" &&\n \"message\" in error &&\n typeof error.message === \"string\" &&\n /locked|busy/i.test(error.message)\n ) {\n return false;\n }\n throw error;\n }\n },\n\n releaseArtifactWriteLock() {\n assertOpen(closed);\n if (!artifactLockHeld) return;\n initializedArtifactLockDatabase.exec(\"COMMIT\");\n artifactLockHeld = false;\n },\n\n listGenerations() {\n assertOpen(closed);\n return database.prepare(`\n SELECT\n generation, status, trained, model_path, needle_version,\n created_at, archived_at\n FROM generations\n WHERE classifier_name = ?\n ORDER BY generation\n `).all(options.name).map((value) => mapGeneration(row<GenerationRow>(value)));\n },\n\n close() {\n if (closed) {\n return;\n }\n if (artifactLockHeld) {\n initializedArtifactLockDatabase.exec(\"ROLLBACK\");\n artifactLockHeld = false;\n }\n initializedArtifactLockDatabase.close();\n closed = true;\n database.close();\n },\n };\n\n return storage;\n}\n\nfunction activeGeneration(database: DatabaseSyncType, name: string): number {\n const active = requiredRow<{ active_generation: number }>(database.prepare(`\n SELECT active_generation FROM classifiers WHERE name = ?\n `).get(name));\n return active.active_generation;\n}\n\nfunction truncateWriteAheadLog(database: DatabaseSyncType): void {\n database.exec(\"PRAGMA busy_timeout = 0\");\n let checkpoint: { busy: number; log: number; checkpointed: number };\n try {\n checkpoint = requiredRow<{\n busy: number;\n log: number;\n checkpointed: number;\n }>(database.prepare(\"PRAGMA wal_checkpoint(TRUNCATE)\").get());\n } finally {\n database.exec(\"PRAGMA busy_timeout = 5000\");\n }\n if (checkpoint.busy !== 0) {\n throw new Error(\n \"SQLite WAL could not be truncated after clearing training data\",\n );\n }\n}\n\nfunction classifierState(\n database: DatabaseSyncType,\n name: string,\n): {\n active_generation: number;\n data_epoch: number;\n clear_pending: number;\n clear_erased: number;\n clear_artifact_generation_max: number | null;\n training_lease_owner: string | null;\n training_lease_epoch: number | null;\n training_lease_until: number | null;\n} {\n return requiredRow(database.prepare(`\n SELECT\n active_generation,\n data_epoch,\n clear_pending,\n clear_erased,\n clear_artifact_generation_max,\n training_lease_owner,\n training_lease_epoch,\n training_lease_until\n FROM classifiers\n WHERE name = ?\n `).get(name));\n}\n\nfunction migrateClassifierColumns(database: DatabaseSyncType): void {\n transaction(database, () => {\n const columns = new Set(\n database.prepare(\"PRAGMA table_info(classifiers)\").all().map((value) =>\n row<{ name: string }>(value).name,\n ),\n );\n if (!columns.has(\"data_epoch\")) {\n database.exec(\n \"ALTER TABLE classifiers ADD COLUMN data_epoch INTEGER NOT NULL DEFAULT 0\",\n );\n }\n if (!columns.has(\"clear_pending\")) {\n database.exec(\n \"ALTER TABLE classifiers ADD COLUMN clear_pending INTEGER NOT NULL DEFAULT 0\",\n );\n }\n if (!columns.has(\"clear_erased\")) {\n database.exec(\n \"ALTER TABLE classifiers ADD COLUMN clear_erased INTEGER NOT NULL DEFAULT 0\",\n );\n }\n if (!columns.has(\"clear_artifact_generation_max\")) {\n database.exec(\n \"ALTER TABLE classifiers ADD COLUMN clear_artifact_generation_max INTEGER\",\n );\n }\n if (!columns.has(\"training_lease_epoch\")) {\n database.exec(\n \"ALTER TABLE classifiers ADD COLUMN training_lease_epoch INTEGER\",\n );\n }\n });\n}\n\nfunction generationByNumber(\n database: DatabaseSyncType,\n name: string,\n generation: number,\n): StoredGeneration {\n const stored = requiredRow<GenerationRow>(database.prepare(`\n SELECT\n generation, status, trained, model_path, needle_version,\n created_at, archived_at\n FROM generations\n WHERE classifier_name = ? AND generation = ?\n `).get(name, generation));\n return mapGeneration(stored);\n}\n\nfunction trimExamples(\n database: DatabaseSyncType,\n name: string,\n generation: number,\n maxTrainingSet: number,\n): void {\n database.prepare(`\n DELETE FROM examples\n WHERE classifier_name = ?\n AND generation = ?\n AND id NOT IN (\n SELECT id\n FROM examples\n WHERE classifier_name = ? AND generation = ?\n ORDER BY id DESC\n LIMIT ?\n )\n `).run(name, generation, name, generation, maxTrainingSet);\n}\n\nfunction mapExample(stored: ExampleRow): StoredExample {\n return {\n id: stored.id,\n generation: stored.generation,\n input: stored.input,\n result: JSON.parse(stored.result_json) as StoredResult,\n split: stored.split,\n createdAt: stored.created_at,\n };\n}\n\nfunction mapGeneration(stored: GenerationRow): StoredGeneration {\n return {\n generation: stored.generation,\n status: stored.status,\n trained: stored.trained === 1,\n modelPath: stored.model_path,\n needleVersion: stored.needle_version,\n createdAt: stored.created_at,\n archivedAt: stored.archived_at,\n };\n}\n\nfunction transaction(database: DatabaseSyncType, action: () => void): void {\n database.exec(\"BEGIN IMMEDIATE\");\n try {\n action();\n database.exec(\"COMMIT\");\n } catch (error) {\n database.exec(\"ROLLBACK\");\n throw error;\n }\n}\n\nfunction stringifyJson(value: unknown, description: string): string {\n const serialized = JSON.stringify(value);\n if (serialized === undefined) {\n throw new TypeError(`${description} must be JSON serializable`);\n }\n return serialized;\n}\n\nfunction criticalConfigJson(configJson: string): string {\n const config = JSON.parse(configJson) as unknown;\n if (!isRecord(config)) {\n throw new TypeError(\"classifier config must be an object\");\n }\n\n const critical: Record<string, unknown> = {};\n for (const key of [\n \"result\",\n \"retrainOnCount\",\n \"acceptableError\",\n \"retestInterval\",\n \"retestRevertOn\",\n \"model\",\n ]) {\n if (Object.hasOwn(config, key)) {\n critical[key] = config[key];\n }\n }\n\n if (typeof critical.acceptableError === \"string\") {\n const percentage = /^(\\d+(?:\\.\\d+)?)%$/.exec(critical.acceptableError);\n if (percentage !== null) {\n critical.acceptableError = Number(percentage[1]) / 100;\n }\n }\n\n if (isRecord(critical.result) && Array.isArray(critical.result.values)) {\n critical.result = {\n ...critical.result,\n values: [...critical.result.values].sort(compareJsonValues),\n };\n }\n\n return JSON.stringify(sortObjectKeys(critical));\n}\n\nfunction sortObjectKeys(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(sortObjectKeys);\n }\n if (!isRecord(value)) {\n return value;\n }\n\n return Object.fromEntries(\n Object.entries(value)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, child]) => [key, sortObjectKeys(child)]),\n );\n}\n\nfunction compareJsonValues(left: unknown, right: unknown): number {\n return JSON.stringify(sortObjectKeys(left)).localeCompare(\n JSON.stringify(sortObjectKeys(right)),\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction assertOpen(closed: boolean): void {\n if (closed) {\n throw new Error(\"Storage is closed\");\n }\n}\n\nfunction row<T>(value: unknown): T {\n return value as T;\n}\n\nfunction requiredRow<T>(value: unknown): T {\n if (value === undefined) {\n throw new Error(\"Expected stored classifier data\");\n }\n return row<T>(value);\n}\n"],"mappings":"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","names":["randomUUID","join","process","resolve","createHash","join","row","isRecord","join","randomUUID","assertOpen","referenceResult","resolve"]}