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/bin/cli.js CHANGED
@@ -2609,8 +2609,13 @@ class Intelligence {
2609
2609
  }
2610
2610
 
2611
2611
  sessionEnd() {
2612
- const duration = this.now() - (this.sessionStartTime || this.data.stats.last_session);
2613
- const actions = this.data.trajectories.filter(t => t.timestamp >= this.data.stats.last_session).length;
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
  // ============================================