ruvector 0.1.65 → 0.1.66
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/.ruvector/intelligence.json +125 -0
- package/README.md +169 -20
- package/bin/cli.js +443 -0
- package/bin/mcp-server.js +337 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +8 -1
- package/dist/core/learning-engine.d.ts +160 -0
- package/dist/core/learning-engine.d.ts.map +1 -0
- package/dist/core/learning-engine.js +589 -0
- package/dist/core/tensor-compress.d.ts +134 -0
- package/dist/core/tensor-compress.d.ts.map +1 -0
- package/dist/core/tensor-compress.js +432 -0
- package/package.json +1 -1
- package/ruvector.db +0 -0
package/bin/cli.js
CHANGED
|
@@ -3916,6 +3916,449 @@ hooksCmd.command('route-enhanced')
|
|
|
3916
3916
|
}));
|
|
3917
3917
|
});
|
|
3918
3918
|
|
|
3919
|
+
// ============================================
|
|
3920
|
+
// LEARNING & COMPRESSION COMMANDS (v2.1)
|
|
3921
|
+
// ============================================
|
|
3922
|
+
|
|
3923
|
+
let TensorCompressClass = null;
|
|
3924
|
+
let LearningEngineClass = null;
|
|
3925
|
+
|
|
3926
|
+
function loadLearningModules() {
|
|
3927
|
+
if (LearningEngineClass) return true;
|
|
3928
|
+
try {
|
|
3929
|
+
const core = require('../dist/core/index.js');
|
|
3930
|
+
TensorCompressClass = core.TensorCompress;
|
|
3931
|
+
LearningEngineClass = core.LearningEngine;
|
|
3932
|
+
return true;
|
|
3933
|
+
} catch (e) {
|
|
3934
|
+
return false;
|
|
3935
|
+
}
|
|
3936
|
+
}
|
|
3937
|
+
|
|
3938
|
+
// Learning algorithm configuration
|
|
3939
|
+
hooksCmd.command('learning-config')
|
|
3940
|
+
.description('Configure learning algorithms for different tasks')
|
|
3941
|
+
.option('-t, --task <type>', 'Task type (agent-routing, error-avoidance, confidence-scoring, trajectory-learning, context-ranking, memory-recall)')
|
|
3942
|
+
.option('-a, --algorithm <alg>', 'Algorithm (q-learning, sarsa, double-q, actor-critic, ppo, decision-transformer, monte-carlo, td-lambda, dqn)')
|
|
3943
|
+
.option('-l, --learning-rate <rate>', 'Learning rate (0.0-1.0)', parseFloat)
|
|
3944
|
+
.option('-g, --gamma <gamma>', 'Discount factor (0.0-1.0)', parseFloat)
|
|
3945
|
+
.option('-e, --epsilon <epsilon>', 'Exploration rate (0.0-1.0)', parseFloat)
|
|
3946
|
+
.option('--lambda <lambda>', 'Lambda for TD(λ)', parseFloat)
|
|
3947
|
+
.option('--list', 'List all algorithms and their descriptions')
|
|
3948
|
+
.option('--show', 'Show current configuration')
|
|
3949
|
+
.action(async (opts) => {
|
|
3950
|
+
if (!loadLearningModules()) {
|
|
3951
|
+
console.log(JSON.stringify({ success: false, error: 'Learning modules not available. Run npm run build.' }));
|
|
3952
|
+
return;
|
|
3953
|
+
}
|
|
3954
|
+
|
|
3955
|
+
if (opts.list) {
|
|
3956
|
+
const algorithms = LearningEngineClass.getAlgorithms();
|
|
3957
|
+
console.log(JSON.stringify({
|
|
3958
|
+
success: true,
|
|
3959
|
+
algorithms: algorithms.map(a => ({
|
|
3960
|
+
name: a.algorithm,
|
|
3961
|
+
description: a.description,
|
|
3962
|
+
bestFor: a.bestFor
|
|
3963
|
+
}))
|
|
3964
|
+
}));
|
|
3965
|
+
return;
|
|
3966
|
+
}
|
|
3967
|
+
|
|
3968
|
+
// Load existing intelligence data
|
|
3969
|
+
const dataPath = path.join(process.cwd(), '.ruvector', 'intelligence.json');
|
|
3970
|
+
let data = {};
|
|
3971
|
+
try {
|
|
3972
|
+
if (fs.existsSync(dataPath)) {
|
|
3973
|
+
data = JSON.parse(fs.readFileSync(dataPath, 'utf-8'));
|
|
3974
|
+
}
|
|
3975
|
+
} catch (e) {}
|
|
3976
|
+
|
|
3977
|
+
const engine = new LearningEngineClass();
|
|
3978
|
+
if (data.learning) {
|
|
3979
|
+
engine.import(data.learning);
|
|
3980
|
+
}
|
|
3981
|
+
|
|
3982
|
+
if (opts.show) {
|
|
3983
|
+
const tasks = ['agent-routing', 'error-avoidance', 'confidence-scoring', 'trajectory-learning', 'context-ranking', 'memory-recall'];
|
|
3984
|
+
const configs = {};
|
|
3985
|
+
for (const task of tasks) {
|
|
3986
|
+
configs[task] = engine.getConfig(task);
|
|
3987
|
+
}
|
|
3988
|
+
console.log(JSON.stringify({ success: true, configs }));
|
|
3989
|
+
return;
|
|
3990
|
+
}
|
|
3991
|
+
|
|
3992
|
+
if (!opts.task) {
|
|
3993
|
+
console.log(JSON.stringify({ success: false, error: 'Specify --task or use --list/--show' }));
|
|
3994
|
+
return;
|
|
3995
|
+
}
|
|
3996
|
+
|
|
3997
|
+
const config = {};
|
|
3998
|
+
if (opts.algorithm) config.algorithm = opts.algorithm;
|
|
3999
|
+
if (opts.learningRate !== undefined) config.learningRate = opts.learningRate;
|
|
4000
|
+
if (opts.gamma !== undefined) config.discountFactor = opts.gamma;
|
|
4001
|
+
if (opts.epsilon !== undefined) config.epsilon = opts.epsilon;
|
|
4002
|
+
if (opts.lambda !== undefined) config.lambda = opts.lambda;
|
|
4003
|
+
|
|
4004
|
+
engine.configure(opts.task, config);
|
|
4005
|
+
|
|
4006
|
+
// Save
|
|
4007
|
+
data.learning = engine.export();
|
|
4008
|
+
fs.mkdirSync(path.dirname(dataPath), { recursive: true });
|
|
4009
|
+
fs.writeFileSync(dataPath, JSON.stringify(data, null, 2));
|
|
4010
|
+
|
|
4011
|
+
console.log(JSON.stringify({
|
|
4012
|
+
success: true,
|
|
4013
|
+
task: opts.task,
|
|
4014
|
+
config: engine.getConfig(opts.task)
|
|
4015
|
+
}));
|
|
4016
|
+
});
|
|
4017
|
+
|
|
4018
|
+
// Learning statistics
|
|
4019
|
+
hooksCmd.command('learning-stats')
|
|
4020
|
+
.description('Show learning algorithm statistics and performance')
|
|
4021
|
+
.option('--json', 'Output as JSON')
|
|
4022
|
+
.action(async (opts) => {
|
|
4023
|
+
if (!loadLearningModules()) {
|
|
4024
|
+
console.log(JSON.stringify({ success: false, error: 'Learning modules not available' }));
|
|
4025
|
+
return;
|
|
4026
|
+
}
|
|
4027
|
+
|
|
4028
|
+
const dataPath = path.join(process.cwd(), '.ruvector', 'intelligence.json');
|
|
4029
|
+
let data = {};
|
|
4030
|
+
try {
|
|
4031
|
+
if (fs.existsSync(dataPath)) {
|
|
4032
|
+
data = JSON.parse(fs.readFileSync(dataPath, 'utf-8'));
|
|
4033
|
+
}
|
|
4034
|
+
} catch (e) {}
|
|
4035
|
+
|
|
4036
|
+
const engine = new LearningEngineClass();
|
|
4037
|
+
if (data.learning) {
|
|
4038
|
+
engine.import(data.learning);
|
|
4039
|
+
}
|
|
4040
|
+
|
|
4041
|
+
const summary = engine.getStatsSummary();
|
|
4042
|
+
|
|
4043
|
+
if (opts.json) {
|
|
4044
|
+
console.log(JSON.stringify({ success: true, ...summary }));
|
|
4045
|
+
} else {
|
|
4046
|
+
console.log(chalk.bold.cyan('\n📊 Learning Statistics\n'));
|
|
4047
|
+
console.log(` Best Algorithm: ${chalk.green(summary.bestAlgorithm)}`);
|
|
4048
|
+
console.log(` Total Updates: ${summary.totalUpdates}`);
|
|
4049
|
+
console.log(` Avg Reward: ${summary.avgReward.toFixed(4)}`);
|
|
4050
|
+
|
|
4051
|
+
if (summary.algorithms.length > 0) {
|
|
4052
|
+
console.log(chalk.bold('\n Algorithm Performance:'));
|
|
4053
|
+
for (const alg of summary.algorithms) {
|
|
4054
|
+
console.log(` ${alg.algorithm.padEnd(20)} updates: ${String(alg.updates).padStart(6)} avgReward: ${alg.avgReward.toFixed(3).padStart(8)} convergence: ${alg.convergenceScore.toFixed(3)}`);
|
|
4055
|
+
}
|
|
4056
|
+
}
|
|
4057
|
+
console.log('');
|
|
4058
|
+
}
|
|
4059
|
+
});
|
|
4060
|
+
|
|
4061
|
+
// Manual learning update
|
|
4062
|
+
hooksCmd.command('learning-update')
|
|
4063
|
+
.description('Manually record a learning experience')
|
|
4064
|
+
.requiredOption('-t, --task <type>', 'Task type')
|
|
4065
|
+
.requiredOption('-s, --state <state>', 'Current state')
|
|
4066
|
+
.requiredOption('-a, --action <action>', 'Action taken')
|
|
4067
|
+
.requiredOption('-r, --reward <reward>', 'Reward received', parseFloat)
|
|
4068
|
+
.option('-n, --next-state <state>', 'Next state')
|
|
4069
|
+
.option('-d, --done', 'Episode is done')
|
|
4070
|
+
.action(async (opts) => {
|
|
4071
|
+
if (!loadLearningModules()) {
|
|
4072
|
+
console.log(JSON.stringify({ success: false, error: 'Learning modules not available' }));
|
|
4073
|
+
return;
|
|
4074
|
+
}
|
|
4075
|
+
|
|
4076
|
+
const dataPath = path.join(process.cwd(), '.ruvector', 'intelligence.json');
|
|
4077
|
+
let data = {};
|
|
4078
|
+
try {
|
|
4079
|
+
if (fs.existsSync(dataPath)) {
|
|
4080
|
+
data = JSON.parse(fs.readFileSync(dataPath, 'utf-8'));
|
|
4081
|
+
}
|
|
4082
|
+
} catch (e) {}
|
|
4083
|
+
|
|
4084
|
+
const engine = new LearningEngineClass();
|
|
4085
|
+
if (data.learning) {
|
|
4086
|
+
engine.import(data.learning);
|
|
4087
|
+
}
|
|
4088
|
+
|
|
4089
|
+
const experience = {
|
|
4090
|
+
state: opts.state,
|
|
4091
|
+
action: opts.action,
|
|
4092
|
+
reward: opts.reward,
|
|
4093
|
+
nextState: opts.nextState || opts.state,
|
|
4094
|
+
done: opts.done || false,
|
|
4095
|
+
timestamp: Date.now()
|
|
4096
|
+
};
|
|
4097
|
+
|
|
4098
|
+
const delta = engine.update(opts.task, experience);
|
|
4099
|
+
|
|
4100
|
+
// Save
|
|
4101
|
+
data.learning = engine.export();
|
|
4102
|
+
fs.writeFileSync(dataPath, JSON.stringify(data, null, 2));
|
|
4103
|
+
|
|
4104
|
+
console.log(JSON.stringify({
|
|
4105
|
+
success: true,
|
|
4106
|
+
task: opts.task,
|
|
4107
|
+
experience,
|
|
4108
|
+
delta,
|
|
4109
|
+
algorithm: engine.getConfig(opts.task).algorithm
|
|
4110
|
+
}));
|
|
4111
|
+
});
|
|
4112
|
+
|
|
4113
|
+
// TensorCompress commands
|
|
4114
|
+
hooksCmd.command('compress')
|
|
4115
|
+
.description('Compress pattern storage using TensorCompress')
|
|
4116
|
+
.option('--force', 'Force recompression of all patterns')
|
|
4117
|
+
.option('--stats', 'Show compression statistics only')
|
|
4118
|
+
.action(async (opts) => {
|
|
4119
|
+
if (!loadLearningModules()) {
|
|
4120
|
+
console.log(JSON.stringify({ success: false, error: 'Compression modules not available' }));
|
|
4121
|
+
return;
|
|
4122
|
+
}
|
|
4123
|
+
|
|
4124
|
+
const dataPath = path.join(process.cwd(), '.ruvector', 'intelligence.json');
|
|
4125
|
+
let data = {};
|
|
4126
|
+
try {
|
|
4127
|
+
if (fs.existsSync(dataPath)) {
|
|
4128
|
+
data = JSON.parse(fs.readFileSync(dataPath, 'utf-8'));
|
|
4129
|
+
}
|
|
4130
|
+
} catch (e) {}
|
|
4131
|
+
|
|
4132
|
+
const compress = new TensorCompressClass({
|
|
4133
|
+
autoCompress: false,
|
|
4134
|
+
hotThreshold: 0.8,
|
|
4135
|
+
warmThreshold: 0.4,
|
|
4136
|
+
coolThreshold: 0.1,
|
|
4137
|
+
coldThreshold: 0.01
|
|
4138
|
+
});
|
|
4139
|
+
|
|
4140
|
+
// Import existing compressed data
|
|
4141
|
+
if (data.compressedPatterns) {
|
|
4142
|
+
compress.import(data.compressedPatterns);
|
|
4143
|
+
}
|
|
4144
|
+
|
|
4145
|
+
// Also compress any uncompressed patterns from the regular patterns
|
|
4146
|
+
if (data.patterns && !data.compressedPatterns) {
|
|
4147
|
+
for (const [key, value] of Object.entries(data.patterns)) {
|
|
4148
|
+
if (Array.isArray(value) && value.length > 0 && typeof value[0] === 'number') {
|
|
4149
|
+
compress.store(key, value);
|
|
4150
|
+
}
|
|
4151
|
+
}
|
|
4152
|
+
}
|
|
4153
|
+
|
|
4154
|
+
if (opts.stats) {
|
|
4155
|
+
const stats = compress.getStats();
|
|
4156
|
+
console.log(JSON.stringify({ success: true, ...stats }));
|
|
4157
|
+
return;
|
|
4158
|
+
}
|
|
4159
|
+
|
|
4160
|
+
// Recompress based on access patterns
|
|
4161
|
+
const stats = compress.recompressAll();
|
|
4162
|
+
|
|
4163
|
+
// Save compressed data
|
|
4164
|
+
data.compressedPatterns = compress.export();
|
|
4165
|
+
fs.writeFileSync(dataPath, JSON.stringify(data, null, 2));
|
|
4166
|
+
|
|
4167
|
+
console.log(JSON.stringify({
|
|
4168
|
+
success: true,
|
|
4169
|
+
message: 'Compression complete',
|
|
4170
|
+
...stats
|
|
4171
|
+
}));
|
|
4172
|
+
});
|
|
4173
|
+
|
|
4174
|
+
hooksCmd.command('compress-stats')
|
|
4175
|
+
.description('Show TensorCompress statistics')
|
|
4176
|
+
.option('--json', 'Output as JSON')
|
|
4177
|
+
.action(async (opts) => {
|
|
4178
|
+
if (!loadLearningModules()) {
|
|
4179
|
+
console.log(JSON.stringify({ success: false, error: 'Compression modules not available' }));
|
|
4180
|
+
return;
|
|
4181
|
+
}
|
|
4182
|
+
|
|
4183
|
+
const dataPath = path.join(process.cwd(), '.ruvector', 'intelligence.json');
|
|
4184
|
+
let data = {};
|
|
4185
|
+
try {
|
|
4186
|
+
if (fs.existsSync(dataPath)) {
|
|
4187
|
+
data = JSON.parse(fs.readFileSync(dataPath, 'utf-8'));
|
|
4188
|
+
}
|
|
4189
|
+
} catch (e) {}
|
|
4190
|
+
|
|
4191
|
+
const compress = new TensorCompressClass({ autoCompress: false });
|
|
4192
|
+
if (data.compressedPatterns) {
|
|
4193
|
+
compress.import(data.compressedPatterns);
|
|
4194
|
+
}
|
|
4195
|
+
|
|
4196
|
+
const stats = compress.getStats();
|
|
4197
|
+
|
|
4198
|
+
if (opts.json) {
|
|
4199
|
+
console.log(JSON.stringify({ success: true, ...stats }));
|
|
4200
|
+
} else {
|
|
4201
|
+
console.log(chalk.bold.cyan('\n📦 TensorCompress Statistics\n'));
|
|
4202
|
+
console.log(` Total Tensors: ${stats.totalTensors}`);
|
|
4203
|
+
console.log(` Original Size: ${(stats.originalBytes / 1024).toFixed(2)} KB`);
|
|
4204
|
+
console.log(` Compressed Size: ${(stats.compressedBytes / 1024).toFixed(2)} KB`);
|
|
4205
|
+
console.log(` Savings: ${chalk.green(stats.savingsPercent.toFixed(1) + '%')}`);
|
|
4206
|
+
|
|
4207
|
+
console.log(chalk.bold('\n By Compression Level:'));
|
|
4208
|
+
console.log(` none (hot): ${stats.byLevel.none}`);
|
|
4209
|
+
console.log(` half (warm): ${stats.byLevel.half}`);
|
|
4210
|
+
console.log(` pq8 (cool): ${stats.byLevel.pq8}`);
|
|
4211
|
+
console.log(` pq4 (cold): ${stats.byLevel.pq4}`);
|
|
4212
|
+
console.log(` binary (archive): ${stats.byLevel.binary}`);
|
|
4213
|
+
console.log('');
|
|
4214
|
+
}
|
|
4215
|
+
});
|
|
4216
|
+
|
|
4217
|
+
// Store embedding with compression
|
|
4218
|
+
hooksCmd.command('compress-store')
|
|
4219
|
+
.description('Store an embedding with adaptive compression')
|
|
4220
|
+
.requiredOption('-k, --key <key>', 'Storage key')
|
|
4221
|
+
.requiredOption('-v, --vector <vector>', 'Vector as JSON array')
|
|
4222
|
+
.option('-l, --level <level>', 'Compression level (none, half, pq8, pq4, binary)')
|
|
4223
|
+
.action(async (opts) => {
|
|
4224
|
+
if (!loadLearningModules()) {
|
|
4225
|
+
console.log(JSON.stringify({ success: false, error: 'Compression modules not available' }));
|
|
4226
|
+
return;
|
|
4227
|
+
}
|
|
4228
|
+
|
|
4229
|
+
let vector;
|
|
4230
|
+
try {
|
|
4231
|
+
vector = JSON.parse(opts.vector);
|
|
4232
|
+
} catch (e) {
|
|
4233
|
+
console.log(JSON.stringify({ success: false, error: 'Invalid vector JSON' }));
|
|
4234
|
+
return;
|
|
4235
|
+
}
|
|
4236
|
+
|
|
4237
|
+
const dataPath = path.join(process.cwd(), '.ruvector', 'intelligence.json');
|
|
4238
|
+
let data = {};
|
|
4239
|
+
try {
|
|
4240
|
+
if (fs.existsSync(dataPath)) {
|
|
4241
|
+
data = JSON.parse(fs.readFileSync(dataPath, 'utf-8'));
|
|
4242
|
+
}
|
|
4243
|
+
} catch (e) {}
|
|
4244
|
+
|
|
4245
|
+
const compress = new TensorCompressClass({ autoCompress: false });
|
|
4246
|
+
if (data.compressedPatterns) {
|
|
4247
|
+
compress.import(data.compressedPatterns);
|
|
4248
|
+
}
|
|
4249
|
+
|
|
4250
|
+
compress.store(opts.key, vector, opts.level);
|
|
4251
|
+
|
|
4252
|
+
data.compressedPatterns = compress.export();
|
|
4253
|
+
fs.mkdirSync(path.dirname(dataPath), { recursive: true });
|
|
4254
|
+
fs.writeFileSync(dataPath, JSON.stringify(data, null, 2));
|
|
4255
|
+
|
|
4256
|
+
const stats = compress.getStats();
|
|
4257
|
+
console.log(JSON.stringify({
|
|
4258
|
+
success: true,
|
|
4259
|
+
key: opts.key,
|
|
4260
|
+
level: opts.level || 'auto',
|
|
4261
|
+
originalDim: vector.length,
|
|
4262
|
+
totalTensors: stats.totalTensors
|
|
4263
|
+
}));
|
|
4264
|
+
});
|
|
4265
|
+
|
|
4266
|
+
// Retrieve compressed embedding
|
|
4267
|
+
hooksCmd.command('compress-get')
|
|
4268
|
+
.description('Retrieve a compressed embedding')
|
|
4269
|
+
.requiredOption('-k, --key <key>', 'Storage key')
|
|
4270
|
+
.action(async (opts) => {
|
|
4271
|
+
if (!loadLearningModules()) {
|
|
4272
|
+
console.log(JSON.stringify({ success: false, error: 'Compression modules not available' }));
|
|
4273
|
+
return;
|
|
4274
|
+
}
|
|
4275
|
+
|
|
4276
|
+
const dataPath = path.join(process.cwd(), '.ruvector', 'intelligence.json');
|
|
4277
|
+
let data = {};
|
|
4278
|
+
try {
|
|
4279
|
+
if (fs.existsSync(dataPath)) {
|
|
4280
|
+
data = JSON.parse(fs.readFileSync(dataPath, 'utf-8'));
|
|
4281
|
+
}
|
|
4282
|
+
} catch (e) {}
|
|
4283
|
+
|
|
4284
|
+
const compress = new TensorCompressClass({ autoCompress: false });
|
|
4285
|
+
if (data.compressedPatterns) {
|
|
4286
|
+
compress.import(data.compressedPatterns);
|
|
4287
|
+
}
|
|
4288
|
+
|
|
4289
|
+
const vector = compress.get(opts.key);
|
|
4290
|
+
if (!vector) {
|
|
4291
|
+
console.log(JSON.stringify({ success: false, error: 'Key not found' }));
|
|
4292
|
+
return;
|
|
4293
|
+
}
|
|
4294
|
+
|
|
4295
|
+
console.log(JSON.stringify({
|
|
4296
|
+
success: true,
|
|
4297
|
+
key: opts.key,
|
|
4298
|
+
vector: Array.from(vector),
|
|
4299
|
+
dimension: vector.length
|
|
4300
|
+
}));
|
|
4301
|
+
});
|
|
4302
|
+
|
|
4303
|
+
// Combined learning action with best algorithm
|
|
4304
|
+
hooksCmd.command('learn')
|
|
4305
|
+
.description('Record learning outcome and get best action recommendation')
|
|
4306
|
+
.requiredOption('-s, --state <state>', 'Current state (e.g., file extension, task type)')
|
|
4307
|
+
.option('-a, --action <action>', 'Action taken')
|
|
4308
|
+
.option('-r, --reward <reward>', 'Reward (-1 to 1)', parseFloat)
|
|
4309
|
+
.option('--actions <actions>', 'Available actions (comma-separated)')
|
|
4310
|
+
.option('-t, --task <type>', 'Task type', 'agent-routing')
|
|
4311
|
+
.action(async (opts) => {
|
|
4312
|
+
if (!loadLearningModules()) {
|
|
4313
|
+
console.log(JSON.stringify({ success: false, error: 'Learning modules not available' }));
|
|
4314
|
+
return;
|
|
4315
|
+
}
|
|
4316
|
+
|
|
4317
|
+
const dataPath = path.join(process.cwd(), '.ruvector', 'intelligence.json');
|
|
4318
|
+
let data = {};
|
|
4319
|
+
try {
|
|
4320
|
+
if (fs.existsSync(dataPath)) {
|
|
4321
|
+
data = JSON.parse(fs.readFileSync(dataPath, 'utf-8'));
|
|
4322
|
+
}
|
|
4323
|
+
} catch (e) {}
|
|
4324
|
+
|
|
4325
|
+
const engine = new LearningEngineClass();
|
|
4326
|
+
if (data.learning) {
|
|
4327
|
+
engine.import(data.learning);
|
|
4328
|
+
}
|
|
4329
|
+
|
|
4330
|
+
let result = { success: true };
|
|
4331
|
+
|
|
4332
|
+
// If action and reward provided, record the experience
|
|
4333
|
+
if (opts.action && opts.reward !== undefined) {
|
|
4334
|
+
const experience = {
|
|
4335
|
+
state: opts.state,
|
|
4336
|
+
action: opts.action,
|
|
4337
|
+
reward: opts.reward,
|
|
4338
|
+
nextState: opts.state,
|
|
4339
|
+
done: true,
|
|
4340
|
+
timestamp: Date.now()
|
|
4341
|
+
};
|
|
4342
|
+
|
|
4343
|
+
const delta = engine.update(opts.task, experience);
|
|
4344
|
+
result.recorded = { experience, delta, algorithm: engine.getConfig(opts.task).algorithm };
|
|
4345
|
+
}
|
|
4346
|
+
|
|
4347
|
+
// Get best action recommendation
|
|
4348
|
+
if (opts.actions) {
|
|
4349
|
+
const actions = opts.actions.split(',').map(a => a.trim());
|
|
4350
|
+
const best = engine.getBestAction(opts.task, opts.state, actions);
|
|
4351
|
+
result.recommendation = best;
|
|
4352
|
+
}
|
|
4353
|
+
|
|
4354
|
+
// Save
|
|
4355
|
+
data.learning = engine.export();
|
|
4356
|
+
fs.mkdirSync(path.dirname(dataPath), { recursive: true });
|
|
4357
|
+
fs.writeFileSync(dataPath, JSON.stringify(data, null, 2));
|
|
4358
|
+
|
|
4359
|
+
console.log(JSON.stringify(result));
|
|
4360
|
+
});
|
|
4361
|
+
|
|
3919
4362
|
// ============================================
|
|
3920
4363
|
// END NEW CAPABILITY COMMANDS
|
|
3921
4364
|
// ============================================
|