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