@swapai/core 0.1.0
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/LICENSE +21 -0
- package/README.md +94 -0
- package/THIRD_PARTY_NOTICES.md +6 -0
- package/dist/chunk-SXECHZ3L.js +15 -0
- package/dist/chunk-SXECHZ3L.js.map +1 -0
- package/dist/effect.d.ts +7 -0
- package/dist/effect.js +55 -0
- package/dist/effect.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1682 -0
- package/dist/index.js.map +1 -0
- package/dist/types-DTbU1MEi.d.ts +51 -0
- package/package.json +65 -0
- package/python/requirements.in +1 -0
- package/python/requirements.lock +823 -0
- package/python/swapai_worker.py +173 -0
|
@@ -0,0 +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;\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 let closed = false;\n let trained = storage.snapshot().trained;\n let loadedModel: LoadedNeedleModel | 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\n const saved = storage.snapshot();\n if (\n saved.trained &&\n (saved.modelPath === null || saved.needleVersion !== NEEDLE_VERSION)\n ) {\n storage.archiveAndReset();\n trained = false;\n }\n\n const startup = startRuntime();\n\n async function startRuntime(): Promise<void> {\n try {\n await runtime.ready();\n const snapshot = storage.snapshot();\n if (snapshot.trained && snapshot.modelPath !== null) {\n loadedModel = await runtime.loadModel({\n modelPath: snapshot.modelPath,\n resultConfig: config.result,\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 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(input: string, result: Result): Promise<void> {\n return enqueue(() => {\n storage.addExample(input, result);\n scheduleTraining();\n });\n }\n\n function shouldTrain(snapshot = storage.snapshot()): boolean {\n return (\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 if (!shouldTrain()) return false;\n if (!storage.claimTrainingLease(trainingLeaseOwner, TRAINING_LEASE_DURATION_MS)) {\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 );\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 const trainingExamples = storage.listExamples(\"training\");\n const heldOutExamples = storage.listExamples(\"held_out\");\n storage.markTrainingAttempted(snapshot.activeExampleCount);\n\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 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 throw new SwapAIError(\n \"service_unavailable\",\n `Classifier \"${config.name}\" lost its training lease`,\n );\n }\n\n storage.promoteGeneration(candidate);\n if (loadedModel !== null) await loadedModel.close();\n loadedModel = candidateModel;\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(): Promise<LoadedNeedleModel> {\n await startup;\n if (!trained) {\n throw new SwapAIError(\n \"not_trained\",\n `Classifier \"${config.name}\" has not passed its held-out test`,\n );\n }\n if (loadedModel === null) {\n const snapshot = storage.snapshot();\n if (snapshot.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 loadedModel = await runtime.loadModel({\n modelPath: snapshot.modelPath,\n resultConfig: config.result,\n });\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 ): 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);\n if (retestDue) {\n storage.recordLocalClassification();\n const failures = storage.recordRetest(false);\n if (failures >= config.retestRevertOn) await disableModel();\n }\n return referenceResult;\n }\n\n async function disableModel(): Promise<void> {\n storage.archiveAndReset();\n trained = false;\n const previousModel = loadedModel;\n loadedModel = null;\n if (previousModel !== null) await previousModel.close();\n }\n\n async function classifyNow(\n input: string,\n reference: ReferenceClassifier<Result> | undefined,\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);\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()).classify(input),\n );\n } catch (error) {\n return fallbackToReference(input, reference, error, retestDue);\n }\n\n if (!retestDue || reference === undefined) {\n storage.recordLocalClassification();\n return candidateResult;\n }\n\n const referenceResult = await callReference(input, reference);\n await persistExample(input, referenceResult);\n storage.recordLocalClassification();\n const passed =\n resultError(config.result, referenceResult, candidateResult) <=\n config.acceptableError;\n const failures = storage.recordRetest(passed);\n\n if (!passed && failures >= config.retestRevertOn) {\n await disableModel();\n }\n\n return referenceResult;\n }\n\n const classifier: Classifier<Result> = {\n isTrained() {\n return trained;\n },\n\n logClassification(input, result) {\n assertOpen(closed);\n const validResult = validateResult(config.result, result);\n void persistExample(input, validResult);\n },\n\n classify(input, reference) {\n assertOpen(closed);\n const task = classificationQueue.then(() => classifyNow(input, reference));\n classificationQueue = task.then(\n () => undefined,\n () => undefined,\n );\n return task;\n },\n\n async flush() {\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 (queuedFailure !== null) {\n const failure = queuedFailure;\n queuedFailure = null;\n throw failure;\n }\n },\n\n async close() {\n if (closed) return;\n closed = true;\n let failure: unknown;\n try {\n await classificationQueue;\n await classifier.flush();\n } catch (error) {\n failure = error;\n } finally {\n if (loadedModel !== null) await loadedModel.close();\n loadedModel = null;\n await runtime.close();\n storage.close();\n }\n if (failure !== undefined) throw failure;\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 stat,\n writeFile,\n} from \"node:fs/promises\";\nimport { createInterface } from \"node:readline\";\nimport { dirname, join } 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}\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 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 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 = options.dataDirectory;\n this.#runtimeDirectory = join(options.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 (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 await writeFile(trainingPath, `${lines.join(\"\\n\")}\\n`, \"utf8\");\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 ],\n {\n cwd: candidateDirectory,\n env: this.#environment!,\n timeoutMs: 6 * 60 * 60 * 1000,\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 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 Promise.race([\n this.#exitPromise,\n new Promise<void>((resolve) => setTimeout(resolve, 2_000)),\n ]);\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: [\"ignore\", \"pipe\", \"pipe\"],\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}\n\nexport interface PromotedModel {\n modelPath: string;\n needleVersion: string;\n}\n\nexport interface Storage {\n readonly databasePath: string;\n snapshot(): StorageSnapshot;\n addExample(input: string, result: StoredResult): StoredExample;\n listExamples(split?: ExampleSplit, generation?: number): StoredExample[];\n markTrainingAttempted(exampleCount: number): void;\n promoteGeneration(model: PromotedModel): StoredGeneration;\n recordLocalClassification(): number;\n recordRetest(passed: boolean): number;\n claimTrainingLease(owner: string, durationMs: number): boolean;\n releaseTrainingLease(owner: string): void;\n archiveAndReset(): StoredGeneration;\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}\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 );\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\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 chmodSync(databasePath, 0o600);\n database.exec(\"PRAGMA journal_mode = WAL\");\n database.exec(\"PRAGMA foreign_keys = ON\");\n database.exec(\"PRAGMA busy_timeout = 5000\");\n database.exec(SCHEMA);\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 database.close();\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(database, options.name, activeGeneration(database, options.name), options.maxTrainingSet);\n });\n\n let closed = 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 (\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 };\n },\n\n addExample(input, result) {\n assertOpen(closed);\n const generation = activeGeneration(database, options.name);\n const split = assignExampleSplit(options.name, input);\n const createdAt = Date.now();\n const resultJson = stringifyJson(result, \"classification result\");\n let id = 0;\n\n transaction(database, () => {\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\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 { id, generation, input, result, split, createdAt };\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 markTrainingAttempted(exampleCount) {\n assertOpen(closed);\n if (!Number.isSafeInteger(exampleCount) || exampleCount <= 0) {\n throw new TypeError(\"training example count must be a positive integer\");\n }\n 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 = ?\n `).run(exampleCount, Date.now(), options.name);\n },\n\n promoteGeneration(model) {\n assertOpen(closed);\n const generation = activeGeneration(database, options.name);\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 return generationByNumber(database, options.name, generation);\n },\n\n recordLocalClassification() {\n assertOpen(closed);\n 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 = ?\n `).run(Date.now(), options.name);\n return storage.snapshot().localClassificationsSinceRetest;\n },\n\n recordRetest(passed) {\n assertOpen(closed);\n 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 = ?\n `).run(passed ? 1 : 0, Date.now(), options.name);\n return storage.snapshot().consecutiveRetestFailures;\n },\n\n claimTrainingLease(owner, durationMs) {\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 result = database.prepare(`\n UPDATE classifiers\n SET training_lease_owner = ?,\n training_lease_until = ?,\n updated_at = ?\n WHERE name = ?\n AND (\n training_lease_owner IS NULL\n OR training_lease_until <= ?\n OR training_lease_owner = ?\n )\n `).run(owner, now + durationMs, now, options.name, 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 updated_at = ?\n WHERE name = ? AND training_lease_owner = ?\n `).run(Date.now(), options.name, owner);\n },\n\n archiveAndReset() {\n assertOpen(closed);\n let nextGeneration = 0;\n const changedAt = Date.now();\n\n transaction(database, () => {\n const currentGeneration = activeGeneration(database, options.name);\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 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 local_classifications_since_retest = 0,\n consecutive_retest_failures = 0,\n updated_at = ?\n WHERE name = ?\n `).run(nextGeneration, changedAt, options.name);\n });\n\n return generationByNumber(database, options.name, nextGeneration);\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 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 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","createHash","join","row","now","isRecord","join","randomUUID","assertOpen","referenceResult"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
type SwapAIErrorCode = "invalid_configuration" | "invalid_result" | "not_trained" | "service_unavailable" | "classification_failed" | "storage_failed";
|
|
2
|
+
declare class SwapAIError extends Error {
|
|
3
|
+
readonly _tag: "SwapAIError";
|
|
4
|
+
readonly code: SwapAIErrorCode;
|
|
5
|
+
constructor(code: SwapAIErrorCode, message: string, options?: ErrorOptions);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
type ResultValue = number | boolean | string;
|
|
9
|
+
interface NumberResultConfig {
|
|
10
|
+
readonly type: "number";
|
|
11
|
+
readonly min: number;
|
|
12
|
+
readonly max: number;
|
|
13
|
+
}
|
|
14
|
+
interface BooleanResultConfig {
|
|
15
|
+
readonly type: "boolean";
|
|
16
|
+
}
|
|
17
|
+
interface StringResultConfig<Value extends string = string> {
|
|
18
|
+
readonly type: "string";
|
|
19
|
+
readonly values: readonly Value[];
|
|
20
|
+
}
|
|
21
|
+
type ResultConfig = NumberResultConfig | BooleanResultConfig | StringResultConfig;
|
|
22
|
+
type ResultFor<Config extends ResultConfig> = Config extends NumberResultConfig ? number : Config extends BooleanResultConfig ? boolean : Config extends StringResultConfig<infer Value> ? Value : never;
|
|
23
|
+
type ReferenceClassifier<Result extends ResultValue> = (input: string) => Result | Promise<Result>;
|
|
24
|
+
interface Classifier<Result extends ResultValue> {
|
|
25
|
+
isTrained(): boolean;
|
|
26
|
+
logClassification(input: string, result: Result): void;
|
|
27
|
+
classify(input: string, referenceClassifier?: ReferenceClassifier<Result>): Promise<Result>;
|
|
28
|
+
flush(): Promise<void>;
|
|
29
|
+
close(): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
interface InitConfig<Config extends ResultConfig = ResultConfig> {
|
|
32
|
+
readonly name: string;
|
|
33
|
+
readonly result: Config;
|
|
34
|
+
readonly retrainOnCount: number;
|
|
35
|
+
readonly acceptableError: number | `${number}%`;
|
|
36
|
+
readonly retestInterval: number;
|
|
37
|
+
readonly retestRevertOn: number;
|
|
38
|
+
readonly model: "needle2";
|
|
39
|
+
readonly maxTrainingSet: number;
|
|
40
|
+
readonly dataDirectory?: string;
|
|
41
|
+
readonly onBackgroundError?: (error: SwapAIError) => void;
|
|
42
|
+
}
|
|
43
|
+
type NormalizedInitConfig<Config extends ResultConfig = ResultConfig> = Omit<InitConfig<Config>, "acceptableError"> & {
|
|
44
|
+
readonly acceptableError: number;
|
|
45
|
+
};
|
|
46
|
+
interface ResultComparison<Result extends ResultValue> {
|
|
47
|
+
readonly reference: Result;
|
|
48
|
+
readonly candidate: Result;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export { type BooleanResultConfig as B, type Classifier as C, type InitConfig as I, type NormalizedInitConfig as N, type ResultValue as R, SwapAIError as S, type ResultConfig as a, type ResultFor as b, type NumberResultConfig as c, type ReferenceClassifier as d, type ResultComparison as e, type StringResultConfig as f };
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@swapai/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Replace paid classifiers with locally trained Needle 2 classifiers.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/smccamley/swapai.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://stuartmccamley.com/swapai",
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/smccamley/swapai/issues"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=22.13"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"python",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE",
|
|
24
|
+
"THIRD_PARTY_NOTICES.md"
|
|
25
|
+
],
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./effect": {
|
|
32
|
+
"types": "./dist/effect.d.ts",
|
|
33
|
+
"import": "./dist/effect.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsup",
|
|
38
|
+
"check": "tsc --noEmit",
|
|
39
|
+
"test": "vitest run --exclude test/needle.real.test.ts",
|
|
40
|
+
"test:real": "vitest run test/needle.real.test.ts --testTimeout=1800000",
|
|
41
|
+
"test:watch": "vitest",
|
|
42
|
+
"prepack": "npm run build",
|
|
43
|
+
"prepublishOnly": "npm run check && npm test"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"effect": "^3.22.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependenciesMeta": {
|
|
49
|
+
"effect": {
|
|
50
|
+
"optional": true
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^24.0.0",
|
|
55
|
+
"effect": "^3.22.0",
|
|
56
|
+
"tsup": "^8.5.0",
|
|
57
|
+
"typescript": "^5.9.0",
|
|
58
|
+
"vitest": "^3.2.0"
|
|
59
|
+
},
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public",
|
|
62
|
+
"provenance": true,
|
|
63
|
+
"registry": "https://registry.npmjs.org/"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cactus-needle[train]==2.0.14
|