expressible 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 +190 -0
- package/README.md +261 -0
- package/dist/commands/add.d.ts +9 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +175 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +126 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/export.d.ts +2 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +108 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +37 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/retrain.d.ts +2 -0
- package/dist/commands/retrain.d.ts.map +1 -0
- package/dist/commands/retrain.js +139 -0
- package/dist/commands/retrain.js.map +1 -0
- package/dist/commands/review.d.ts +2 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +44 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/run.d.ts +2 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +83 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/setup.d.ts +2 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +15 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/stats.d.ts +2 -0
- package/dist/commands/stats.d.ts.map +1 -0
- package/dist/commands/stats.js +52 -0
- package/dist/commands/stats.js.map +1 -0
- package/dist/commands/train.d.ts +2 -0
- package/dist/commands/train.d.ts.map +1 -0
- package/dist/commands/train.js +63 -0
- package/dist/commands/train.js.map +1 -0
- package/dist/core/classifier.d.ts +18 -0
- package/dist/core/classifier.d.ts.map +1 -0
- package/dist/core/classifier.js +220 -0
- package/dist/core/classifier.js.map +1 -0
- package/dist/core/config.d.ts +11 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +15 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/data.d.ts +23 -0
- package/dist/core/data.d.ts.map +1 -0
- package/dist/core/data.js +66 -0
- package/dist/core/data.js.map +1 -0
- package/dist/core/embeddings.d.ts +4 -0
- package/dist/core/embeddings.d.ts.map +1 -0
- package/dist/core/embeddings.js +80 -0
- package/dist/core/embeddings.js.map +1 -0
- package/dist/core/model-io.d.ts +11 -0
- package/dist/core/model-io.d.ts.map +1 -0
- package/dist/core/model-io.js +76 -0
- package/dist/core/model-io.js.map +1 -0
- package/dist/core/tf.d.ts +4 -0
- package/dist/core/tf.d.ts.map +1 -0
- package/dist/core/tf.js +21 -0
- package/dist/core/tf.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +161 -0
- package/dist/index.js.map +1 -0
- package/dist/ui/server.d.ts +3 -0
- package/dist/ui/server.d.ts.map +1 -0
- package/dist/ui/server.js +107 -0
- package/dist/ui/server.js.map +1 -0
- package/dist/ui/static/index.html +486 -0
- package/dist/ui/static/static/index.html +486 -0
- package/dist/utils/display.d.ts +9 -0
- package/dist/utils/display.d.ts.map +1 -0
- package/dist/utils/display.js +34 -0
- package/dist/utils/display.js.map +1 -0
- package/dist/utils/fs.d.ts +3 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +31 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/paths.d.ts +13 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +55 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/similarity.d.ts +6 -0
- package/dist/utils/similarity.d.ts.map +1 -0
- package/dist/utils/similarity.js +23 -0
- package/dist/utils/similarity.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import crypto from 'node:crypto';
|
|
4
|
+
import { getEmbeddingsCachePath, getGlobalModelCacheDir, ensureDir } from '../utils/paths.js';
|
|
5
|
+
import { info } from '../utils/display.js';
|
|
6
|
+
let pipelineInstance = null;
|
|
7
|
+
function contentHash(text) {
|
|
8
|
+
return crypto.createHash('sha256').update(text).digest('hex').slice(0, 32);
|
|
9
|
+
}
|
|
10
|
+
async function loadPipeline() {
|
|
11
|
+
if (pipelineInstance)
|
|
12
|
+
return pipelineInstance;
|
|
13
|
+
const cacheDir = getGlobalModelCacheDir();
|
|
14
|
+
ensureDir(cacheDir);
|
|
15
|
+
const transformers = await import('@xenova/transformers');
|
|
16
|
+
transformers.env.cacheDir = cacheDir;
|
|
17
|
+
transformers.env.allowLocalModels = true;
|
|
18
|
+
// Check if model is already downloaded
|
|
19
|
+
const modelMarker = path.join(cacheDir, 'Xenova', 'all-MiniLM-L6-v2');
|
|
20
|
+
const isFirstRun = !fs.existsSync(modelMarker);
|
|
21
|
+
if (isFirstRun) {
|
|
22
|
+
info('Downloading embedding model (all-MiniLM-L6-v2, ~80MB)...');
|
|
23
|
+
info('This is a one-time download.');
|
|
24
|
+
}
|
|
25
|
+
const extractor = await transformers.pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2');
|
|
26
|
+
pipelineInstance = async (text) => {
|
|
27
|
+
const result = await extractor(text, { pooling: 'mean', normalize: true });
|
|
28
|
+
return result;
|
|
29
|
+
};
|
|
30
|
+
return pipelineInstance;
|
|
31
|
+
}
|
|
32
|
+
function loadCache(taskDir) {
|
|
33
|
+
const cachePath = getEmbeddingsCachePath(taskDir);
|
|
34
|
+
if (fs.existsSync(cachePath)) {
|
|
35
|
+
const raw = fs.readFileSync(cachePath, 'utf-8');
|
|
36
|
+
return JSON.parse(raw);
|
|
37
|
+
}
|
|
38
|
+
return {};
|
|
39
|
+
}
|
|
40
|
+
function saveCache(taskDir, cache) {
|
|
41
|
+
const cachePath = getEmbeddingsCachePath(taskDir);
|
|
42
|
+
const dir = path.dirname(cachePath);
|
|
43
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
44
|
+
fs.writeFileSync(cachePath, JSON.stringify(cache), 'utf-8');
|
|
45
|
+
}
|
|
46
|
+
export async function embedTexts(texts, taskDir) {
|
|
47
|
+
const pipe = await loadPipeline();
|
|
48
|
+
const cache = loadCache(taskDir);
|
|
49
|
+
const results = new Array(texts.length);
|
|
50
|
+
const uncachedIndices = [];
|
|
51
|
+
const uncachedTexts = [];
|
|
52
|
+
for (let i = 0; i < texts.length; i++) {
|
|
53
|
+
const hash = contentHash(texts[i]);
|
|
54
|
+
if (cache[hash]) {
|
|
55
|
+
results[i] = cache[hash];
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
uncachedIndices.push(i);
|
|
59
|
+
uncachedTexts.push(texts[i]);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (uncachedTexts.length > 0) {
|
|
63
|
+
for (let j = 0; j < uncachedTexts.length; j++) {
|
|
64
|
+
const output = await pipe(uncachedTexts[j]);
|
|
65
|
+
const embedding = output.tolist()[0];
|
|
66
|
+
const globalIndex = uncachedIndices[j];
|
|
67
|
+
results[globalIndex] = embedding;
|
|
68
|
+
const hash = contentHash(uncachedTexts[j]);
|
|
69
|
+
cache[hash] = embedding;
|
|
70
|
+
}
|
|
71
|
+
saveCache(taskDir, cache);
|
|
72
|
+
}
|
|
73
|
+
return results;
|
|
74
|
+
}
|
|
75
|
+
export async function embedText(text, taskDir) {
|
|
76
|
+
const results = await embedTexts([text], taskDir);
|
|
77
|
+
return results[0];
|
|
78
|
+
}
|
|
79
|
+
export const EMBEDDING_DIM = 384;
|
|
80
|
+
//# sourceMappingURL=embeddings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../src/core/embeddings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom file system IO handler for TensorFlow.js model save/load.
|
|
3
|
+
* Works with both @tensorflow/tfjs-node and pure @tensorflow/tfjs,
|
|
4
|
+
* avoiding the file:// URL scheme which is only handled by tfjs-node.
|
|
5
|
+
*
|
|
6
|
+
* The returned object implements TF's IOHandler interface:
|
|
7
|
+
* save(modelArtifacts) → writes model.json + weights.bin to modelDir
|
|
8
|
+
* load() → reads model.json + weights.bin from modelDir
|
|
9
|
+
*/
|
|
10
|
+
export declare function fileIOHandler(modelDir: string): any;
|
|
11
|
+
//# sourceMappingURL=model-io.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-io.d.ts","sourceRoot":"","sources":["../../src/core/model-io.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAEH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CA2EnD"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Custom file system IO handler for TensorFlow.js model save/load.
|
|
5
|
+
* Works with both @tensorflow/tfjs-node and pure @tensorflow/tfjs,
|
|
6
|
+
* avoiding the file:// URL scheme which is only handled by tfjs-node.
|
|
7
|
+
*
|
|
8
|
+
* The returned object implements TF's IOHandler interface:
|
|
9
|
+
* save(modelArtifacts) → writes model.json + weights.bin to modelDir
|
|
10
|
+
* load() → reads model.json + weights.bin from modelDir
|
|
11
|
+
*/
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
+
export function fileIOHandler(modelDir) {
|
|
14
|
+
return {
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
async save(modelArtifacts) {
|
|
17
|
+
const weightsPath = path.join(modelDir, 'weights.bin');
|
|
18
|
+
if (modelArtifacts.weightData) {
|
|
19
|
+
const data = Array.isArray(modelArtifacts.weightData)
|
|
20
|
+
? Buffer.concat(modelArtifacts.weightData.map((b) => Buffer.from(b)))
|
|
21
|
+
: Buffer.from(modelArtifacts.weightData);
|
|
22
|
+
fs.writeFileSync(weightsPath, data);
|
|
23
|
+
}
|
|
24
|
+
const modelJson = {
|
|
25
|
+
modelTopology: modelArtifacts.modelTopology,
|
|
26
|
+
format: modelArtifacts.format,
|
|
27
|
+
generatedBy: modelArtifacts.generatedBy,
|
|
28
|
+
convertedBy: modelArtifacts.convertedBy,
|
|
29
|
+
};
|
|
30
|
+
if (modelArtifacts.weightSpecs) {
|
|
31
|
+
modelJson.weightsManifest = [
|
|
32
|
+
{
|
|
33
|
+
paths: ['weights.bin'],
|
|
34
|
+
weights: modelArtifacts.weightSpecs,
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
fs.writeFileSync(path.join(modelDir, 'model.json'), JSON.stringify(modelJson), 'utf-8');
|
|
39
|
+
return {
|
|
40
|
+
modelArtifactsInfo: {
|
|
41
|
+
dateSaved: new Date(),
|
|
42
|
+
modelTopologyType: 'JSON',
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
async load() {
|
|
47
|
+
const modelJsonPath = path.join(modelDir, 'model.json');
|
|
48
|
+
const modelJson = JSON.parse(fs.readFileSync(modelJsonPath, 'utf-8'));
|
|
49
|
+
const weightSpecs = [];
|
|
50
|
+
const weightBuffers = [];
|
|
51
|
+
for (const group of modelJson.weightsManifest) {
|
|
52
|
+
for (const weightPath of group.paths) {
|
|
53
|
+
weightBuffers.push(fs.readFileSync(path.join(modelDir, weightPath)));
|
|
54
|
+
}
|
|
55
|
+
weightSpecs.push(...group.weights);
|
|
56
|
+
}
|
|
57
|
+
const totalLength = weightBuffers.reduce((sum, b) => sum + b.length, 0);
|
|
58
|
+
const weightData = new ArrayBuffer(totalLength);
|
|
59
|
+
const view = new Uint8Array(weightData);
|
|
60
|
+
let offset = 0;
|
|
61
|
+
for (const buf of weightBuffers) {
|
|
62
|
+
view.set(buf, offset);
|
|
63
|
+
offset += buf.length;
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
modelTopology: modelJson.modelTopology,
|
|
67
|
+
weightSpecs,
|
|
68
|
+
weightData,
|
|
69
|
+
format: modelJson.format,
|
|
70
|
+
generatedBy: modelJson.generatedBy,
|
|
71
|
+
convertedBy: modelJson.convertedBy,
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=model-io.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-io.js","sourceRoot":"","sources":["../../src/core/model-io.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tf.d.ts","sourceRoot":"","sources":["../../src/core/tf.ts"],"names":[],"mappings":"AAEA,KAAK,EAAE,GAAG,cAAc,uBAAuB,CAAC,CAAC;AAIjD,wBAAsB,MAAM,IAAI,OAAO,CAAC,EAAE,CAAC,CAiB1C"}
|
package/dist/core/tf.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { warn } from '../utils/display.js';
|
|
2
|
+
let tfInstance = null;
|
|
3
|
+
export async function loadTf() {
|
|
4
|
+
if (tfInstance)
|
|
5
|
+
return tfInstance;
|
|
6
|
+
try {
|
|
7
|
+
tfInstance = await import('@tensorflow/tfjs-node');
|
|
8
|
+
return tfInstance;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
warn('Native TensorFlow bindings unavailable. Using pure JS fallback (slower).');
|
|
12
|
+
try {
|
|
13
|
+
tfInstance = await import('@tensorflow/tfjs');
|
|
14
|
+
return tfInstance;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
throw new Error('Could not load TensorFlow.js. Run "npm install" in the project directory, or run "expressible distill doctor" to diagnose.');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=tf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tf.js","sourceRoot":"","sources":["../../src/core/tf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAI3C,IAAI,UAAU,GAAc,IAAI,CAAC;AAEjC,MAAM,CAAC,KAAK,UAAU,MAAM;IAC1B,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC;IAElC,IAAI,CAAC;QACH,UAAU,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QACnD,OAAO,UAAU,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC,0EAA0E,CAAC,CAAC;QACjF,IAAI,CAAC;YACH,UAAU,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAkB,CAAC;YAC/D,OAAO,UAAU,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CACb,4HAA4H,CAC7H,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { error } from './utils/display.js';
|
|
4
|
+
let verbose = false;
|
|
5
|
+
const program = new Command();
|
|
6
|
+
program
|
|
7
|
+
.name('expressible')
|
|
8
|
+
.description('Open-source CLI toolkit by Expressible AI, Inc.')
|
|
9
|
+
.version('0.1.0')
|
|
10
|
+
.option('--verbose', 'Show detailed error messages and stack traces')
|
|
11
|
+
.hook('preAction', (thisCommand) => {
|
|
12
|
+
const opts = thisCommand.optsWithGlobals();
|
|
13
|
+
if (opts['verbose']) {
|
|
14
|
+
verbose = true;
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
// --- distill subcommand group ---
|
|
18
|
+
const distill = program
|
|
19
|
+
.command('distill')
|
|
20
|
+
.description('Train small, local ML models from input/output example pairs');
|
|
21
|
+
distill
|
|
22
|
+
.command('init <task-name>')
|
|
23
|
+
.description('Create a new distill project')
|
|
24
|
+
.action(async (taskName) => {
|
|
25
|
+
try {
|
|
26
|
+
const { initCommand } = await import('./commands/init.js');
|
|
27
|
+
await initCommand(taskName);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
handleError(err);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
distill
|
|
34
|
+
.command('add')
|
|
35
|
+
.description('Add training examples')
|
|
36
|
+
.option('-i, --input <file>', 'Input file path')
|
|
37
|
+
.option('-o, --output <file>', 'Output file path')
|
|
38
|
+
.option('-d, --dir <directory>', 'Bulk import from directory of paired files')
|
|
39
|
+
.option('-f, --file <file>', 'Import from JSON file (array of {input, output} objects)')
|
|
40
|
+
.action(async (options) => {
|
|
41
|
+
try {
|
|
42
|
+
const { addCommand } = await import('./commands/add.js');
|
|
43
|
+
await addCommand(options);
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
handleError(err);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
distill
|
|
50
|
+
.command('train')
|
|
51
|
+
.description('Train a model from your samples')
|
|
52
|
+
.action(async () => {
|
|
53
|
+
try {
|
|
54
|
+
const { trainCommand } = await import('./commands/train.js');
|
|
55
|
+
await trainCommand();
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
handleError(err);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
distill
|
|
62
|
+
.command('run [input]')
|
|
63
|
+
.description('Run inference on input text or files')
|
|
64
|
+
.action(async (input) => {
|
|
65
|
+
try {
|
|
66
|
+
const { runCommand } = await import('./commands/run.js');
|
|
67
|
+
await runCommand(input);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
handleError(err);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
distill
|
|
74
|
+
.command('review')
|
|
75
|
+
.description('Open the review UI to score model predictions')
|
|
76
|
+
.action(async () => {
|
|
77
|
+
try {
|
|
78
|
+
const { reviewCommand } = await import('./commands/review.js');
|
|
79
|
+
await reviewCommand();
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
handleError(err);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
distill
|
|
86
|
+
.command('retrain')
|
|
87
|
+
.description('Retrain the model using review feedback')
|
|
88
|
+
.action(async () => {
|
|
89
|
+
try {
|
|
90
|
+
const { retrainCommand } = await import('./commands/retrain.js');
|
|
91
|
+
await retrainCommand();
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
handleError(err);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
distill
|
|
98
|
+
.command('stats')
|
|
99
|
+
.description('Show project statistics')
|
|
100
|
+
.action(async () => {
|
|
101
|
+
try {
|
|
102
|
+
const { statsCommand } = await import('./commands/stats.js');
|
|
103
|
+
await statsCommand();
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
handleError(err);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
distill
|
|
110
|
+
.command('export <output-dir>')
|
|
111
|
+
.description('Export model for standalone use')
|
|
112
|
+
.action(async (outputDir) => {
|
|
113
|
+
try {
|
|
114
|
+
const { exportCommand } = await import('./commands/export.js');
|
|
115
|
+
await exportCommand(outputDir);
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
handleError(err);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
distill
|
|
122
|
+
.command('doctor')
|
|
123
|
+
.description('Check system requirements and project health')
|
|
124
|
+
.action(async () => {
|
|
125
|
+
try {
|
|
126
|
+
const { doctorCommand } = await import('./commands/doctor.js');
|
|
127
|
+
await doctorCommand();
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
handleError(err);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
distill
|
|
134
|
+
.command('setup')
|
|
135
|
+
.description('Download embedding model and prepare for offline use')
|
|
136
|
+
.action(async () => {
|
|
137
|
+
try {
|
|
138
|
+
const { setupCommand } = await import('./commands/setup.js');
|
|
139
|
+
await setupCommand();
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
handleError(err);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
function handleError(err) {
|
|
146
|
+
if (err instanceof Error) {
|
|
147
|
+
error(err.message);
|
|
148
|
+
if (verbose && err.stack) {
|
|
149
|
+
console.error('\n' + err.stack);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
error(String(err));
|
|
154
|
+
}
|
|
155
|
+
if (!verbose) {
|
|
156
|
+
console.error('\nRun with --verbose for detailed error information.');
|
|
157
|
+
}
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
program.parse();
|
|
161
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/ui/server.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAoB,MAAM,iBAAiB,CAAC;AAK3E,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CAyHf"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { createServer } from 'node:http';
|
|
5
|
+
import { saveValidationResults } from '../core/data.js';
|
|
6
|
+
import { success, info } from '../utils/display.js';
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
export async function startReviewServer(taskDir, results) {
|
|
10
|
+
const app = express();
|
|
11
|
+
app.use(express.json());
|
|
12
|
+
// Serve static files
|
|
13
|
+
const staticDir = path.join(__dirname, 'static');
|
|
14
|
+
app.use(express.static(staticDir));
|
|
15
|
+
// API: get all items
|
|
16
|
+
app.get('/api/items', (_req, res) => {
|
|
17
|
+
res.json(results.items);
|
|
18
|
+
});
|
|
19
|
+
// API: score an item
|
|
20
|
+
app.post('/api/score', (req, res) => {
|
|
21
|
+
const { id, approved, correctedOutput } = req.body;
|
|
22
|
+
const item = results.items.find((i) => i.id === id);
|
|
23
|
+
if (!item) {
|
|
24
|
+
res.status(404).json({ error: 'Item not found' });
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
item.approved = approved;
|
|
28
|
+
item.reviewedAt = new Date().toISOString();
|
|
29
|
+
if (correctedOutput !== undefined) {
|
|
30
|
+
item.correctedOutput = correctedOutput;
|
|
31
|
+
}
|
|
32
|
+
saveValidationResults(taskDir, results);
|
|
33
|
+
res.json({ ok: true });
|
|
34
|
+
});
|
|
35
|
+
// API: get stats
|
|
36
|
+
app.get('/api/stats', (_req, res) => {
|
|
37
|
+
const total = results.items.length;
|
|
38
|
+
const reviewed = results.items.filter((i) => i.reviewedAt).length;
|
|
39
|
+
const approved = results.items.filter((i) => i.approved === true).length;
|
|
40
|
+
const rejected = results.items.filter((i) => i.reviewedAt && i.approved === false).length;
|
|
41
|
+
const approvalRate = reviewed > 0 ? (approved / reviewed) * 100 : 0;
|
|
42
|
+
res.json({
|
|
43
|
+
total,
|
|
44
|
+
reviewed,
|
|
45
|
+
approved,
|
|
46
|
+
rejected,
|
|
47
|
+
approvalRate: Math.round(approvalRate * 10) / 10,
|
|
48
|
+
remaining: total - reviewed,
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
// API: shutdown
|
|
52
|
+
app.post('/api/shutdown', (_req, res) => {
|
|
53
|
+
res.json({ ok: true });
|
|
54
|
+
info('Review session ended.');
|
|
55
|
+
setTimeout(() => process.exit(0), 500);
|
|
56
|
+
});
|
|
57
|
+
const server = createServer(app);
|
|
58
|
+
const startPort = 3847;
|
|
59
|
+
const maxAttempts = 20;
|
|
60
|
+
await new Promise((resolve, reject) => {
|
|
61
|
+
let attempt = 0;
|
|
62
|
+
const tryPort = (port) => {
|
|
63
|
+
const onError = (err) => {
|
|
64
|
+
server.removeListener('listening', onListening);
|
|
65
|
+
if (err.code === 'EADDRINUSE' && attempt < maxAttempts) {
|
|
66
|
+
attempt++;
|
|
67
|
+
tryPort(port + 1);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
reject(new Error(`Could not find an available port (tried ${startPort}-${port}). Close other services or try again.`));
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const onListening = () => {
|
|
74
|
+
server.removeListener('error', onError);
|
|
75
|
+
resolve();
|
|
76
|
+
};
|
|
77
|
+
server.once('error', onError);
|
|
78
|
+
server.once('listening', onListening);
|
|
79
|
+
server.listen(port);
|
|
80
|
+
};
|
|
81
|
+
tryPort(startPort);
|
|
82
|
+
});
|
|
83
|
+
const address = server.address();
|
|
84
|
+
const port = typeof address === 'object' && address ? address.port : startPort;
|
|
85
|
+
const url = `http://localhost:${port}`;
|
|
86
|
+
success(`Review server running at ${url}`);
|
|
87
|
+
info('Press Ctrl+C to stop the server.');
|
|
88
|
+
// Try to open browser
|
|
89
|
+
try {
|
|
90
|
+
const openModule = await import('open');
|
|
91
|
+
await openModule.default(url);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
info(`Open ${url} in your browser to start reviewing.`);
|
|
95
|
+
}
|
|
96
|
+
// Handle graceful shutdown
|
|
97
|
+
const shutdown = () => {
|
|
98
|
+
info('\nShutting down review server...');
|
|
99
|
+
server.close(() => {
|
|
100
|
+
success('Server stopped. Review results saved.');
|
|
101
|
+
process.exit(0);
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
process.on('SIGINT', shutdown);
|
|
105
|
+
process.on('SIGTERM', shutdown);
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/ui/server.ts"],"names":[],"mappings":"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"}
|