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,126 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import { getGlobalModelCacheDir, getConfigPath } from '../utils/paths.js';
|
|
5
|
+
import { success, error, warn, heading } from '../utils/display.js';
|
|
6
|
+
import { getDirectorySize, formatBytes } from '../utils/fs.js';
|
|
7
|
+
export async function doctorCommand() {
|
|
8
|
+
heading('Distill Doctor');
|
|
9
|
+
console.log();
|
|
10
|
+
const checks = [];
|
|
11
|
+
// 1. Node version
|
|
12
|
+
const nodeVersion = process.version;
|
|
13
|
+
const major = parseInt(nodeVersion.slice(1).split('.')[0], 10);
|
|
14
|
+
if (major >= 18) {
|
|
15
|
+
checks.push({ name: 'Node.js version', status: 'pass', message: `${nodeVersion} (>= 18 required)` });
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
checks.push({ name: 'Node.js version', status: 'fail', message: `${nodeVersion} — Node 18+ is required` });
|
|
19
|
+
}
|
|
20
|
+
// 2. TensorFlow.js
|
|
21
|
+
try {
|
|
22
|
+
await import('@tensorflow/tfjs-node');
|
|
23
|
+
checks.push({ name: 'TensorFlow.js (native)', status: 'pass', message: 'tfjs-node loaded successfully' });
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
try {
|
|
27
|
+
await import('@tensorflow/tfjs');
|
|
28
|
+
checks.push({ name: 'TensorFlow.js (pure JS)', status: 'warn', message: 'Native bindings unavailable, using pure JS fallback (slower)' });
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
checks.push({ name: 'TensorFlow.js', status: 'fail', message: 'Neither tfjs-node nor tfjs could be loaded. Run: npm install' });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// 3. Transformers.js
|
|
35
|
+
try {
|
|
36
|
+
await import('@xenova/transformers');
|
|
37
|
+
checks.push({ name: 'Transformers.js', status: 'pass', message: 'Loaded successfully' });
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
checks.push({ name: 'Transformers.js', status: 'fail', message: 'Could not load @xenova/transformers. Run: npm install' });
|
|
41
|
+
}
|
|
42
|
+
// 4. Embedding model downloaded
|
|
43
|
+
const modelCacheDir = getGlobalModelCacheDir();
|
|
44
|
+
const modelMarker = path.join(modelCacheDir, 'Xenova', 'all-MiniLM-L6-v2');
|
|
45
|
+
if (fs.existsSync(modelMarker)) {
|
|
46
|
+
const size = getDirectorySize(modelMarker);
|
|
47
|
+
checks.push({ name: 'Embedding model', status: 'pass', message: `Downloaded (${formatBytes(size)}) at ${modelMarker}` });
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
checks.push({ name: 'Embedding model', status: 'warn', message: 'Not downloaded yet. Will download on first "expressible distill train" (~80MB). Or run: expressible distill setup' });
|
|
51
|
+
}
|
|
52
|
+
// 5. Disk space
|
|
53
|
+
try {
|
|
54
|
+
const stats = fs.statfsSync(os.homedir());
|
|
55
|
+
const freeBytes = stats.bfree * stats.bsize;
|
|
56
|
+
const freeMB = freeBytes / (1024 * 1024);
|
|
57
|
+
if (freeMB > 500) {
|
|
58
|
+
checks.push({ name: 'Disk space', status: 'pass', message: `${formatBytes(freeBytes)} free` });
|
|
59
|
+
}
|
|
60
|
+
else if (freeMB > 100) {
|
|
61
|
+
checks.push({ name: 'Disk space', status: 'warn', message: `${formatBytes(freeBytes)} free — may be tight for training` });
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
checks.push({ name: 'Disk space', status: 'fail', message: `${formatBytes(freeBytes)} free — insufficient for model download and training` });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
checks.push({ name: 'Disk space', status: 'warn', message: 'Could not check disk space' });
|
|
69
|
+
}
|
|
70
|
+
// 6. Current project
|
|
71
|
+
const configPath = getConfigPath(process.cwd());
|
|
72
|
+
if (fs.existsSync(configPath)) {
|
|
73
|
+
try {
|
|
74
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
75
|
+
checks.push({ name: 'Current project', status: 'pass', message: `"${config.name}" (${config.type})` });
|
|
76
|
+
// Check samples
|
|
77
|
+
const samplesDir = path.join(process.cwd(), 'samples');
|
|
78
|
+
if (fs.existsSync(samplesDir)) {
|
|
79
|
+
const inputFiles = fs.readdirSync(samplesDir).filter((f) => f.includes('.input.'));
|
|
80
|
+
if (inputFiles.length >= 10) {
|
|
81
|
+
checks.push({ name: 'Training samples', status: 'pass', message: `${inputFiles.length} samples (minimum 10)` });
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
checks.push({ name: 'Training samples', status: 'warn', message: `${inputFiles.length} samples — need at least 10` });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Check model
|
|
88
|
+
const modelMetadata = path.join(process.cwd(), 'model', 'metadata.json');
|
|
89
|
+
if (fs.existsSync(modelMetadata)) {
|
|
90
|
+
const meta = JSON.parse(fs.readFileSync(modelMetadata, 'utf-8'));
|
|
91
|
+
checks.push({ name: 'Trained model', status: 'pass', message: `Trained at ${new Date(meta.trainedAt).toLocaleString()}` });
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
checks.push({ name: 'Trained model', status: 'warn', message: 'No model trained yet. Run: expressible distill train' });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
checks.push({ name: 'Current project', status: 'fail', message: 'distill.config.json is corrupted' });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
checks.push({ name: 'Current project', status: 'warn', message: 'Not inside a distill project directory' });
|
|
103
|
+
}
|
|
104
|
+
// Print results
|
|
105
|
+
let hasFailures = false;
|
|
106
|
+
for (const check of checks) {
|
|
107
|
+
if (check.status === 'pass') {
|
|
108
|
+
success(`${check.name}: ${check.message}`);
|
|
109
|
+
}
|
|
110
|
+
else if (check.status === 'warn') {
|
|
111
|
+
warn(`${check.name}: ${check.message}`);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
error(`${check.name}: ${check.message}`);
|
|
115
|
+
hasFailures = true;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
console.log();
|
|
119
|
+
if (hasFailures) {
|
|
120
|
+
error('Some checks failed. Fix the issues above before using distill.');
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
success('All checks passed.');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"AAOA,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoDpE"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { findTaskDir, getModelDir, getModelMetadataPath, ensureDir } from '../utils/paths.js';
|
|
4
|
+
import { readConfig } from '../core/config.js';
|
|
5
|
+
import { success, error, info } from '../utils/display.js';
|
|
6
|
+
export async function exportCommand(outputDir) {
|
|
7
|
+
const taskDir = findTaskDir();
|
|
8
|
+
const config = readConfig(taskDir);
|
|
9
|
+
const modelDir = getModelDir(taskDir);
|
|
10
|
+
const metadataPath = getModelMetadataPath(taskDir);
|
|
11
|
+
if (!fs.existsSync(metadataPath)) {
|
|
12
|
+
error('No trained model found. Run "expressible distill train" first.');
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
const resolvedDir = path.resolve(outputDir);
|
|
16
|
+
ensureDir(resolvedDir);
|
|
17
|
+
// Copy model files
|
|
18
|
+
const modelFiles = fs.readdirSync(modelDir).filter((f) => {
|
|
19
|
+
const fullPath = path.join(modelDir, f);
|
|
20
|
+
return fs.statSync(fullPath).isFile();
|
|
21
|
+
});
|
|
22
|
+
for (const file of modelFiles) {
|
|
23
|
+
fs.copyFileSync(path.join(modelDir, file), path.join(resolvedDir, file));
|
|
24
|
+
}
|
|
25
|
+
// Generate standalone inference script
|
|
26
|
+
const inferenceScript = generateInferenceScript();
|
|
27
|
+
fs.writeFileSync(path.join(resolvedDir, 'inference.js'), inferenceScript, 'utf-8');
|
|
28
|
+
// Generate a package.json for the exported model
|
|
29
|
+
const exportPackageJson = {
|
|
30
|
+
name: `${config.name}-model`,
|
|
31
|
+
version: '1.0.0',
|
|
32
|
+
type: 'module',
|
|
33
|
+
description: `Exported distill model for ${config.name}`,
|
|
34
|
+
dependencies: {
|
|
35
|
+
'@tensorflow/tfjs-node': '^4.22.0',
|
|
36
|
+
'@xenova/transformers': '^2.17.2',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
fs.writeFileSync(path.join(resolvedDir, 'package.json'), JSON.stringify(exportPackageJson, null, 2) + '\n', 'utf-8');
|
|
40
|
+
success(`Model exported to ${resolvedDir}`);
|
|
41
|
+
info('To use: npm install && node inference.js "your input text"');
|
|
42
|
+
}
|
|
43
|
+
function generateInferenceScript() {
|
|
44
|
+
return `#!/usr/bin/env node
|
|
45
|
+
// Standalone inference script for distill classifier model
|
|
46
|
+
// Usage: node inference.js "your input text"
|
|
47
|
+
// Requires: npm install @tensorflow/tfjs-node @xenova/transformers
|
|
48
|
+
|
|
49
|
+
import tf from '@tensorflow/tfjs-node';
|
|
50
|
+
import { pipeline, env } from '@xenova/transformers';
|
|
51
|
+
import { readFileSync } from 'fs';
|
|
52
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
53
|
+
import { dirname, join } from 'path';
|
|
54
|
+
|
|
55
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
56
|
+
const __dirname = dirname(__filename);
|
|
57
|
+
|
|
58
|
+
async function main() {
|
|
59
|
+
const input = process.argv[2];
|
|
60
|
+
if (!input) {
|
|
61
|
+
console.error('Usage: node inference.js "your input text"');
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Load metadata
|
|
66
|
+
const metadata = JSON.parse(readFileSync(join(__dirname, 'metadata.json'), 'utf-8'));
|
|
67
|
+
|
|
68
|
+
// Load embedding model
|
|
69
|
+
env.allowLocalModels = true;
|
|
70
|
+
const extractor = await pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2');
|
|
71
|
+
|
|
72
|
+
// Embed input
|
|
73
|
+
const result = await extractor(input, { pooling: 'mean', normalize: true });
|
|
74
|
+
const embedding = result.tolist()[0];
|
|
75
|
+
|
|
76
|
+
// Load trained model
|
|
77
|
+
const model = await tf.loadLayersModel(pathToFileURL(join(__dirname, 'model.json')).toString());
|
|
78
|
+
|
|
79
|
+
// Predict
|
|
80
|
+
const inputTensor = tf.tensor2d([embedding]);
|
|
81
|
+
const output = model.predict(inputTensor);
|
|
82
|
+
const scores = await output.data();
|
|
83
|
+
|
|
84
|
+
const results = metadata.categories.map((cat, i) => ({
|
|
85
|
+
category: cat,
|
|
86
|
+
confidence: Math.round(scores[i] * 1000) / 1000,
|
|
87
|
+
}));
|
|
88
|
+
results.sort((a, b) => b.confidence - a.confidence);
|
|
89
|
+
|
|
90
|
+
console.log(JSON.stringify({
|
|
91
|
+
input,
|
|
92
|
+
output: results[0].category,
|
|
93
|
+
confidence: results[0].confidence,
|
|
94
|
+
allScores: results,
|
|
95
|
+
}, null, 2));
|
|
96
|
+
|
|
97
|
+
inputTensor.dispose();
|
|
98
|
+
output.dispose();
|
|
99
|
+
model.dispose();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
main().catch(err => {
|
|
103
|
+
console.error('Inference failed:', err.message);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
});
|
|
106
|
+
`;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.js","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9F,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAG3D,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,SAAiB;IACnD,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,YAAY,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAEnD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACjC,KAAK,CAAC,gEAAgE,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5C,SAAS,CAAC,WAAW,CAAC,CAAC;IAEvB,mBAAmB;IACnB,MAAM,UAAU,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACxC,OAAO,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;IAC3E,CAAC;IAED,uCAAuC;IACvC,MAAM,eAAe,GAAG,uBAAuB,EAAE,CAAC;IAClD,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EACtC,eAAe,EACf,OAAO,CACR,CAAC;IAEF,iDAAiD;IACjD,MAAM,iBAAiB,GAAG;QACxB,IAAI,EAAE,GAAG,MAAM,CAAC,IAAI,QAAQ;QAC5B,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,8BAA8B,MAAM,CAAC,IAAI,EAAE;QACxD,YAAY,EAAE;YACZ,uBAAuB,EAAE,SAAS;YAClC,sBAAsB,EAAE,SAAS;SAClC;KACF,CAAC;IAEF,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EACtC,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EACjD,OAAO,CACR,CAAC;IAEF,OAAO,CAAC,qBAAqB,WAAW,EAAE,CAAC,CAAC;IAC5C,IAAI,CAAC,4DAA4D,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,uBAAuB;IAC9B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8DR,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAOA,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoCjE"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { getTaskDir, getSamplesDir, getModelDir, getValidationDir, getInternalDir, ensureDir } from '../utils/paths.js';
|
|
4
|
+
import { writeConfig } from '../core/config.js';
|
|
5
|
+
import { success, error, info } from '../utils/display.js';
|
|
6
|
+
export async function initCommand(taskName) {
|
|
7
|
+
const taskDir = getTaskDir(taskName);
|
|
8
|
+
if (fs.existsSync(taskDir) && fs.readdirSync(taskDir).length > 0) {
|
|
9
|
+
error(`Directory "${taskName}" already exists and is not empty.`);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
const answers = await inquirer.prompt([
|
|
13
|
+
{
|
|
14
|
+
type: 'input',
|
|
15
|
+
name: 'description',
|
|
16
|
+
message: 'Brief description of this task (optional):',
|
|
17
|
+
default: '',
|
|
18
|
+
},
|
|
19
|
+
]);
|
|
20
|
+
// Create directory structure
|
|
21
|
+
ensureDir(taskDir);
|
|
22
|
+
ensureDir(getSamplesDir(taskDir));
|
|
23
|
+
ensureDir(getModelDir(taskDir));
|
|
24
|
+
ensureDir(getValidationDir(taskDir));
|
|
25
|
+
ensureDir(getInternalDir(taskDir));
|
|
26
|
+
const config = {
|
|
27
|
+
name: taskName,
|
|
28
|
+
type: 'classify',
|
|
29
|
+
description: answers.description,
|
|
30
|
+
createdAt: new Date().toISOString(),
|
|
31
|
+
version: '1.0.0',
|
|
32
|
+
};
|
|
33
|
+
writeConfig(taskDir, config);
|
|
34
|
+
success(`Created distill project "${taskName}"`);
|
|
35
|
+
info(`Add training examples with: cd ${taskName} && expressible distill add`);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACxH,OAAO,EAAE,WAAW,EAAsB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB;IAChD,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAErC,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjE,KAAK,CAAC,cAAc,QAAQ,oCAAoC,CAAC,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;QACpC;YACE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,4CAA4C;YACrD,OAAO,EAAE,EAAE;SACZ;KACF,CAAC,CAAC;IAEH,6BAA6B;IAC7B,SAAS,CAAC,OAAO,CAAC,CAAC;IACnB,SAAS,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;IAClC,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;IAChC,SAAS,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;IACrC,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IAEnC,MAAM,MAAM,GAAkB;QAC5B,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,OAAO,EAAE,OAAO;KACjB,CAAC;IAEF,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAE7B,OAAO,CAAC,4BAA4B,QAAQ,GAAG,CAAC,CAAC;IACjD,IAAI,CAAC,kCAAkC,QAAQ,6BAA6B,CAAC,CAAC;AAChF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retrain.d.ts","sourceRoot":"","sources":["../../src/commands/retrain.ts"],"names":[],"mappings":"AAUA,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CA6JpD"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { findTaskDir, getModelDir, getModelMetadataPath, ensureDir } from '../utils/paths.js';
|
|
4
|
+
import { readConfig } from '../core/config.js';
|
|
5
|
+
import { loadSamples, loadValidationResults } from '../core/data.js';
|
|
6
|
+
import { embedTexts } from '../core/embeddings.js';
|
|
7
|
+
import { trainClassifier } from '../core/classifier.js';
|
|
8
|
+
import { success, error, warn, info, heading, table } from '../utils/display.js';
|
|
9
|
+
export async function retrainCommand() {
|
|
10
|
+
const taskDir = findTaskDir();
|
|
11
|
+
const config = readConfig(taskDir);
|
|
12
|
+
// Load previous accuracy
|
|
13
|
+
const metadataPath = getModelMetadataPath(taskDir);
|
|
14
|
+
let previousAccuracy = null;
|
|
15
|
+
if (fs.existsSync(metadataPath)) {
|
|
16
|
+
const prevMeta = JSON.parse(fs.readFileSync(metadataPath, 'utf-8'));
|
|
17
|
+
previousAccuracy = prevMeta.accuracy ?? null;
|
|
18
|
+
}
|
|
19
|
+
// Archive current model
|
|
20
|
+
const modelDir = getModelDir(taskDir);
|
|
21
|
+
if (fs.existsSync(metadataPath)) {
|
|
22
|
+
const archiveDir = path.join(modelDir, 'archive', new Date().toISOString().replace(/[:.]/g, '-'));
|
|
23
|
+
ensureDir(archiveDir);
|
|
24
|
+
const modelFiles = fs.readdirSync(modelDir).filter((f) => !f.startsWith('archive'));
|
|
25
|
+
for (const file of modelFiles) {
|
|
26
|
+
const src = path.join(modelDir, file);
|
|
27
|
+
if (fs.statSync(src).isFile()) {
|
|
28
|
+
fs.copyFileSync(src, path.join(archiveDir, file));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
info('Previous model archived.');
|
|
32
|
+
}
|
|
33
|
+
// Build training set from samples + validation results
|
|
34
|
+
const originalSamples = loadSamples(taskDir);
|
|
35
|
+
const validation = loadValidationResults(taskDir);
|
|
36
|
+
const trainingSamples = [...originalSamples];
|
|
37
|
+
// Add validated items
|
|
38
|
+
let addedFromReview = 0;
|
|
39
|
+
let excludedFromReview = 0;
|
|
40
|
+
let skippedConflicts = 0;
|
|
41
|
+
for (const item of validation.items) {
|
|
42
|
+
if (!item.reviewedAt)
|
|
43
|
+
continue;
|
|
44
|
+
if (item.approved) {
|
|
45
|
+
// Thumbs up: add prediction as training data (if not already in samples)
|
|
46
|
+
const existingForInput = trainingSamples.find((s) => s.input.trim() === item.input.trim());
|
|
47
|
+
if (existingForInput && existingForInput.output.trim() !== item.predictedOutput.trim()) {
|
|
48
|
+
// Original sample has a different label — don't add conflicting data
|
|
49
|
+
skippedConflicts++;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (!existingForInput) {
|
|
53
|
+
trainingSamples.push({
|
|
54
|
+
id: `review-${item.id}`,
|
|
55
|
+
input: item.input,
|
|
56
|
+
output: item.predictedOutput,
|
|
57
|
+
});
|
|
58
|
+
addedFromReview++;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else if (item.correctedOutput) {
|
|
62
|
+
// Thumbs down with correction: add corrected version
|
|
63
|
+
const exists = trainingSamples.some((s) => s.input.trim() === item.input.trim() && s.output.trim() === item.correctedOutput.trim());
|
|
64
|
+
if (!exists) {
|
|
65
|
+
trainingSamples.push({
|
|
66
|
+
id: `corrected-${item.id}`,
|
|
67
|
+
input: item.input,
|
|
68
|
+
output: item.correctedOutput,
|
|
69
|
+
});
|
|
70
|
+
addedFromReview++;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
// Thumbs down without correction: exclude
|
|
75
|
+
excludedFromReview++;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (skippedConflicts > 0) {
|
|
79
|
+
warn(`${skippedConflicts} approved prediction(s) skipped — original sample has a different label.`);
|
|
80
|
+
}
|
|
81
|
+
info(`Training set: ${originalSamples.length} original + ${addedFromReview} from review`);
|
|
82
|
+
if (excludedFromReview > 0) {
|
|
83
|
+
info(`${excludedFromReview} rejected items excluded (no correction provided)`);
|
|
84
|
+
}
|
|
85
|
+
if (trainingSamples.length < 10) {
|
|
86
|
+
error(`Not enough training samples (${trainingSamples.length}). At least 10 are required.`);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
heading(`Retraining model "${config.name}"`);
|
|
90
|
+
// Warn about categories with few samples before training
|
|
91
|
+
const categoryCounts = new Map();
|
|
92
|
+
for (const s of trainingSamples) {
|
|
93
|
+
categoryCounts.set(s.output, (categoryCounts.get(s.output) || 0) + 1);
|
|
94
|
+
}
|
|
95
|
+
for (const [cat, count] of categoryCounts) {
|
|
96
|
+
if (count < 5) {
|
|
97
|
+
warn(`Category "${cat}" has only ${count} sample(s). Aim for at least 10 per category.`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const startTime = Date.now();
|
|
101
|
+
const inputs = trainingSamples.map((s) => s.input);
|
|
102
|
+
const embeddings = await embedTexts(inputs, taskDir);
|
|
103
|
+
const labels = trainingSamples.map((s) => s.output);
|
|
104
|
+
const result = await trainClassifier(embeddings, labels, taskDir);
|
|
105
|
+
const newAccuracy = result.valAccuracy;
|
|
106
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
107
|
+
heading('Retraining Complete');
|
|
108
|
+
const rows = [
|
|
109
|
+
['Training samples', String(trainingSamples.length)],
|
|
110
|
+
['Time elapsed', `${elapsed}s`],
|
|
111
|
+
];
|
|
112
|
+
if (previousAccuracy !== null) {
|
|
113
|
+
const prevPct = (previousAccuracy * 100).toFixed(1);
|
|
114
|
+
const newPct = (newAccuracy * 100).toFixed(1);
|
|
115
|
+
const diff = ((newAccuracy - previousAccuracy) * 100).toFixed(1);
|
|
116
|
+
const direction = newAccuracy > previousAccuracy ? 'improved' : newAccuracy < previousAccuracy ? 'decreased' : 'unchanged';
|
|
117
|
+
rows.push(['Previous accuracy', `${prevPct}%`]);
|
|
118
|
+
rows.push(['New accuracy', `${newPct}%`]);
|
|
119
|
+
rows.push(['Change', `${direction} by ${Math.abs(parseFloat(diff))}%`]);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
rows.push(['Accuracy', `${(newAccuracy * 100).toFixed(1)}%`]);
|
|
123
|
+
}
|
|
124
|
+
table(rows);
|
|
125
|
+
// Contextual post-training warnings
|
|
126
|
+
const valFraction = result.numSamples < 30 ? 0.1 : 0.2;
|
|
127
|
+
const valSamples = Math.max(1, Math.floor(result.numSamples * valFraction));
|
|
128
|
+
if (valSamples < 5) {
|
|
129
|
+
warn(`Validation set is very small (${valSamples} sample(s)). Accuracy estimate may be unreliable. Add more training data.`);
|
|
130
|
+
}
|
|
131
|
+
else if (result.accuracy > 0.9 && newAccuracy < 0.5) {
|
|
132
|
+
warn(`High training accuracy (${(result.accuracy * 100).toFixed(0)}%) but low validation accuracy (${(newAccuracy * 100).toFixed(0)}%) suggests overfitting. Add more samples, especially for underrepresented categories.`);
|
|
133
|
+
}
|
|
134
|
+
else if (newAccuracy < 0.6) {
|
|
135
|
+
warn(`Validation accuracy is low (${(newAccuracy * 100).toFixed(0)}%). Consider adding more diverse training examples.`);
|
|
136
|
+
}
|
|
137
|
+
success('New model saved to model/');
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=retrain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retrain.js","sourceRoot":"","sources":["../../src/commands/retrain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../src/commands/review.ts"],"names":[],"mappings":"AAOA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CA6CnD"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { findTaskDir } from '../utils/paths.js';
|
|
2
|
+
import { loadSamples, loadValidationResults, saveValidationResults } from '../core/data.js';
|
|
3
|
+
import { embedText } from '../core/embeddings.js';
|
|
4
|
+
import { predict } from '../core/classifier.js';
|
|
5
|
+
import { error, info } from '../utils/display.js';
|
|
6
|
+
export async function reviewCommand() {
|
|
7
|
+
const taskDir = findTaskDir();
|
|
8
|
+
const samples = loadSamples(taskDir);
|
|
9
|
+
if (samples.length === 0) {
|
|
10
|
+
error('No samples found. Add training data first with: expressible distill add');
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
// Generate predictions for all samples
|
|
14
|
+
info('Generating predictions for review...');
|
|
15
|
+
const existingResults = loadValidationResults(taskDir);
|
|
16
|
+
const existingIds = new Set(existingResults.items.map((i) => i.id));
|
|
17
|
+
const newItems = [];
|
|
18
|
+
for (const sample of samples) {
|
|
19
|
+
if (existingIds.has(sample.id))
|
|
20
|
+
continue;
|
|
21
|
+
const embedding = await embedText(sample.input, taskDir);
|
|
22
|
+
let predictedOutput;
|
|
23
|
+
try {
|
|
24
|
+
const result = await predict(embedding, taskDir);
|
|
25
|
+
predictedOutput = result.category;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
predictedOutput = '(no model trained — showing expected output)';
|
|
29
|
+
}
|
|
30
|
+
newItems.push({
|
|
31
|
+
id: sample.id,
|
|
32
|
+
input: sample.input,
|
|
33
|
+
predictedOutput,
|
|
34
|
+
approved: false,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
const allItems = [...existingResults.items, ...newItems];
|
|
38
|
+
const results = { items: allItems };
|
|
39
|
+
saveValidationResults(taskDir, results);
|
|
40
|
+
// Start Express server
|
|
41
|
+
const { startReviewServer } = await import('../ui/server.js');
|
|
42
|
+
await startReviewServer(taskDir, results);
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/commands/review.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC5F,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAW,KAAK,EAAE,IAAI,EAAW,MAAM,qBAAqB,CAAC;AAGpE,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAErC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,yEAAyE,CAAC,CAAC;QACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,uCAAuC;IACvC,IAAI,CAAC,sCAAsC,CAAC,CAAC;IAE7C,MAAM,eAAe,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEpE,MAAM,QAAQ,GAAuB,EAAE,CAAC;IAExC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAAE,SAAS;QAEzC,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACzD,IAAI,eAAuB,CAAC;QAE5B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACjD,eAAe,GAAG,MAAM,CAAC,QAAQ,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC;YACP,eAAe,GAAG,8CAA8C,CAAC;QACnE,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC;YACZ,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,eAAe;YACf,QAAQ,EAAE,KAAK;SAChB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,CAAC,GAAG,eAAe,CAAC,KAAK,EAAE,GAAG,QAAQ,CAAC,CAAC;IACzD,MAAM,OAAO,GAAsB,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IACvD,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAExC,uBAAuB;IACvB,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAC9D,MAAM,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAwBA,wBAAsB,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgEjE"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { glob } from 'glob';
|
|
4
|
+
import { findTaskDir } from '../utils/paths.js';
|
|
5
|
+
import { embedText } from '../core/embeddings.js';
|
|
6
|
+
import { predict } from '../core/classifier.js';
|
|
7
|
+
import { error } from '../utils/display.js';
|
|
8
|
+
async function runSingle(input, taskDir) {
|
|
9
|
+
const embedding = await embedText(input, taskDir);
|
|
10
|
+
const result = await predict(embedding, taskDir);
|
|
11
|
+
return {
|
|
12
|
+
input,
|
|
13
|
+
output: result.category,
|
|
14
|
+
confidence: Math.round(result.confidence * 100) / 100,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export async function runCommand(inputArg) {
|
|
18
|
+
const taskDir = findTaskDir();
|
|
19
|
+
const inputs = [];
|
|
20
|
+
if (inputArg) {
|
|
21
|
+
// Check if it's a file path first, then try glob patterns, otherwise treat as text
|
|
22
|
+
if (fs.existsSync(inputArg)) {
|
|
23
|
+
const stat = fs.statSync(inputArg);
|
|
24
|
+
if (stat.isFile()) {
|
|
25
|
+
const content = fs.readFileSync(path.resolve(inputArg), 'utf-8').trim();
|
|
26
|
+
inputs.push(content);
|
|
27
|
+
}
|
|
28
|
+
else if (stat.isDirectory()) {
|
|
29
|
+
error(`"${inputArg}" is a directory. Provide a file path or text input.`);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else if (/[*?{}\[\]]/.test(inputArg)) {
|
|
34
|
+
// Only try glob expansion if the input contains glob metacharacters
|
|
35
|
+
const matches = await glob(inputArg);
|
|
36
|
+
if (matches.length > 0) {
|
|
37
|
+
for (const match of matches) {
|
|
38
|
+
const content = fs.readFileSync(path.resolve(match), 'utf-8').trim();
|
|
39
|
+
inputs.push(content);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
error(`Glob pattern "${inputArg}" matched no files.`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// Treat as raw text input
|
|
49
|
+
inputs.push(inputArg);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// Read from stdin
|
|
54
|
+
const chunks = [];
|
|
55
|
+
const stdin = process.stdin;
|
|
56
|
+
if (stdin.isTTY) {
|
|
57
|
+
error('No input provided. Use: expressible distill run <file> or echo "text" | expressible distill run');
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
await new Promise((resolve) => {
|
|
61
|
+
stdin.on('data', (chunk) => chunks.push(chunk));
|
|
62
|
+
stdin.on('end', () => resolve());
|
|
63
|
+
});
|
|
64
|
+
const stdinText = Buffer.concat(chunks).toString('utf-8').trim();
|
|
65
|
+
if (!stdinText) {
|
|
66
|
+
error('No input received from stdin.');
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
inputs.push(stdinText);
|
|
70
|
+
}
|
|
71
|
+
const results = [];
|
|
72
|
+
for (const input of inputs) {
|
|
73
|
+
const result = await runSingle(input, taskDir);
|
|
74
|
+
results.push(result);
|
|
75
|
+
}
|
|
76
|
+
if (results.length === 1) {
|
|
77
|
+
console.log(JSON.stringify(results[0], null, 2));
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
console.log(JSON.stringify(results, null, 2));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAGA,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAgBlD"}
|