@massa-ai/opencode-plugin 1.2.1

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.
Files changed (3) hide show
  1. package/dist/config-cli.js +1353 -0
  2. package/dist/index.js +14244 -0
  3. package/package.json +48 -0
@@ -0,0 +1,1353 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+ var __create = Object.create;
4
+ var __getProtoOf = Object.getPrototypeOf;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ function __accessProp(key) {
10
+ return this[key];
11
+ }
12
+ var __toESMCache_node;
13
+ var __toESMCache_esm;
14
+ var __toESM = (mod, isNodeMode, target) => {
15
+ var canCache = mod != null && typeof mod === "object";
16
+ if (canCache) {
17
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
18
+ var cached = cache.get(mod);
19
+ if (cached)
20
+ return cached;
21
+ }
22
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
23
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
24
+ for (let key of __getOwnPropNames(mod))
25
+ if (!__hasOwnProp.call(to, key))
26
+ __defProp(to, key, {
27
+ get: __accessProp.bind(mod, key),
28
+ enumerable: true
29
+ });
30
+ if (canCache)
31
+ cache.set(mod, to);
32
+ return to;
33
+ };
34
+ var __toCommonJS = (from) => {
35
+ var entry = (__moduleCache ??= new WeakMap).get(from), desc;
36
+ if (entry)
37
+ return entry;
38
+ entry = __defProp({}, "__esModule", { value: true });
39
+ if (from && typeof from === "object" || typeof from === "function") {
40
+ for (var key of __getOwnPropNames(from))
41
+ if (!__hasOwnProp.call(entry, key))
42
+ __defProp(entry, key, {
43
+ get: __accessProp.bind(from, key),
44
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
45
+ });
46
+ }
47
+ __moduleCache.set(from, entry);
48
+ return entry;
49
+ };
50
+ var __moduleCache;
51
+ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
52
+ var __returnValue = (v) => v;
53
+ function __exportSetter(name, newValue) {
54
+ this[name] = __returnValue.bind(null, newValue);
55
+ }
56
+ var __export = (target, all) => {
57
+ for (var name in all)
58
+ __defProp(target, name, {
59
+ get: all[name],
60
+ enumerable: true,
61
+ configurable: true,
62
+ set: __exportSetter.bind(all, name)
63
+ });
64
+ };
65
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
66
+ var __require = import.meta.require;
67
+
68
+ // ../../node_modules/dotenv/lib/main.js
69
+ var require_main = __commonJS((exports, module) => {
70
+ var fs = __require("fs");
71
+ var path = __require("path");
72
+ var os = __require("os");
73
+ var crypto = __require("crypto");
74
+ var TIPS = [
75
+ "\u25C8 encrypted .env [www.dotenvx.com]",
76
+ "\u25C8 secrets for agents [www.dotenvx.com]",
77
+ "\u2301 auth for agents [www.vestauth.com]",
78
+ "\u2318 custom filepath { path: '/custom/path/.env' }",
79
+ "\u2318 enable debugging { debug: true }",
80
+ "\u2318 override existing { override: true }",
81
+ "\u2318 suppress logs { quiet: true }",
82
+ "\u2318 multiple files { path: ['.env.local', '.env'] }"
83
+ ];
84
+ function _getRandomTip() {
85
+ return TIPS[Math.floor(Math.random() * TIPS.length)];
86
+ }
87
+ function parseBoolean(value) {
88
+ if (typeof value === "string") {
89
+ return !["false", "0", "no", "off", ""].includes(value.toLowerCase());
90
+ }
91
+ return Boolean(value);
92
+ }
93
+ function supportsAnsi() {
94
+ return process.stdout.isTTY;
95
+ }
96
+ function dim(text) {
97
+ return supportsAnsi() ? `\x1B[2m${text}\x1B[0m` : text;
98
+ }
99
+ var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
100
+ function parse(src) {
101
+ const obj = {};
102
+ let lines = src.toString();
103
+ lines = lines.replace(/\r\n?/mg, `
104
+ `);
105
+ let match;
106
+ while ((match = LINE.exec(lines)) != null) {
107
+ const key = match[1];
108
+ let value = match[2] || "";
109
+ value = value.trim();
110
+ const maybeQuote = value[0];
111
+ value = value.replace(/^(['"`])([\s\S]*)\1$/mg, "$2");
112
+ if (maybeQuote === '"') {
113
+ value = value.replace(/\\n/g, `
114
+ `);
115
+ value = value.replace(/\\r/g, "\r");
116
+ }
117
+ obj[key] = value;
118
+ }
119
+ return obj;
120
+ }
121
+ function _parseVault(options) {
122
+ options = options || {};
123
+ const vaultPath = _vaultPath(options);
124
+ options.path = vaultPath;
125
+ const result = DotenvModule.configDotenv(options);
126
+ if (!result.parsed) {
127
+ const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
128
+ err.code = "MISSING_DATA";
129
+ throw err;
130
+ }
131
+ const keys = _dotenvKey(options).split(",");
132
+ const length = keys.length;
133
+ let decrypted;
134
+ for (let i = 0;i < length; i++) {
135
+ try {
136
+ const key = keys[i].trim();
137
+ const attrs = _instructions(result, key);
138
+ decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
139
+ break;
140
+ } catch (error) {
141
+ if (i + 1 >= length) {
142
+ throw error;
143
+ }
144
+ }
145
+ }
146
+ return DotenvModule.parse(decrypted);
147
+ }
148
+ function _warn(message) {
149
+ console.error(`\u26A0 ${message}`);
150
+ }
151
+ function _debug(message) {
152
+ console.log(`\u2506 ${message}`);
153
+ }
154
+ function _log(message) {
155
+ console.log(`\u25C7 ${message}`);
156
+ }
157
+ function _dotenvKey(options) {
158
+ if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
159
+ return options.DOTENV_KEY;
160
+ }
161
+ if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
162
+ return process.env.DOTENV_KEY;
163
+ }
164
+ return "";
165
+ }
166
+ function _instructions(result, dotenvKey) {
167
+ let uri;
168
+ try {
169
+ uri = new URL(dotenvKey);
170
+ } catch (error) {
171
+ if (error.code === "ERR_INVALID_URL") {
172
+ const err = new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
173
+ err.code = "INVALID_DOTENV_KEY";
174
+ throw err;
175
+ }
176
+ throw error;
177
+ }
178
+ const key = uri.password;
179
+ if (!key) {
180
+ const err = new Error("INVALID_DOTENV_KEY: Missing key part");
181
+ err.code = "INVALID_DOTENV_KEY";
182
+ throw err;
183
+ }
184
+ const environment = uri.searchParams.get("environment");
185
+ if (!environment) {
186
+ const err = new Error("INVALID_DOTENV_KEY: Missing environment part");
187
+ err.code = "INVALID_DOTENV_KEY";
188
+ throw err;
189
+ }
190
+ const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
191
+ const ciphertext = result.parsed[environmentKey];
192
+ if (!ciphertext) {
193
+ const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
194
+ err.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
195
+ throw err;
196
+ }
197
+ return { ciphertext, key };
198
+ }
199
+ function _vaultPath(options) {
200
+ let possibleVaultPath = null;
201
+ if (options && options.path && options.path.length > 0) {
202
+ if (Array.isArray(options.path)) {
203
+ for (const filepath of options.path) {
204
+ if (fs.existsSync(filepath)) {
205
+ possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
206
+ }
207
+ }
208
+ } else {
209
+ possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
210
+ }
211
+ } else {
212
+ possibleVaultPath = path.resolve(process.cwd(), ".env.vault");
213
+ }
214
+ if (fs.existsSync(possibleVaultPath)) {
215
+ return possibleVaultPath;
216
+ }
217
+ return null;
218
+ }
219
+ function _resolveHome(envPath) {
220
+ return envPath[0] === "~" ? path.join(os.homedir(), envPath.slice(1)) : envPath;
221
+ }
222
+ function _configVault(options) {
223
+ const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
224
+ const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options && options.quiet);
225
+ if (debug || !quiet) {
226
+ _log("loading env from encrypted .env.vault");
227
+ }
228
+ const parsed = DotenvModule._parseVault(options);
229
+ let processEnv = process.env;
230
+ if (options && options.processEnv != null) {
231
+ processEnv = options.processEnv;
232
+ }
233
+ DotenvModule.populate(processEnv, parsed, options);
234
+ return { parsed };
235
+ }
236
+ function configDotenv(options) {
237
+ const dotenvPath = path.resolve(process.cwd(), ".env");
238
+ let encoding = "utf8";
239
+ let processEnv = process.env;
240
+ if (options && options.processEnv != null) {
241
+ processEnv = options.processEnv;
242
+ }
243
+ let debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || options && options.debug);
244
+ let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options && options.quiet);
245
+ if (options && options.encoding) {
246
+ encoding = options.encoding;
247
+ } else {
248
+ if (debug) {
249
+ _debug("no encoding is specified (UTF-8 is used by default)");
250
+ }
251
+ }
252
+ let optionPaths = [dotenvPath];
253
+ if (options && options.path) {
254
+ if (!Array.isArray(options.path)) {
255
+ optionPaths = [_resolveHome(options.path)];
256
+ } else {
257
+ optionPaths = [];
258
+ for (const filepath of options.path) {
259
+ optionPaths.push(_resolveHome(filepath));
260
+ }
261
+ }
262
+ }
263
+ let lastError;
264
+ const parsedAll = {};
265
+ for (const path2 of optionPaths) {
266
+ try {
267
+ const parsed = DotenvModule.parse(fs.readFileSync(path2, { encoding }));
268
+ DotenvModule.populate(parsedAll, parsed, options);
269
+ } catch (e) {
270
+ if (debug) {
271
+ _debug(`failed to load ${path2} ${e.message}`);
272
+ }
273
+ lastError = e;
274
+ }
275
+ }
276
+ const populated = DotenvModule.populate(processEnv, parsedAll, options);
277
+ debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug);
278
+ quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet);
279
+ if (debug || !quiet) {
280
+ const keysCount = Object.keys(populated).length;
281
+ const shortPaths = [];
282
+ for (const filePath of optionPaths) {
283
+ try {
284
+ const relative = path.relative(process.cwd(), filePath);
285
+ shortPaths.push(relative);
286
+ } catch (e) {
287
+ if (debug) {
288
+ _debug(`failed to load ${filePath} ${e.message}`);
289
+ }
290
+ lastError = e;
291
+ }
292
+ }
293
+ _log(`injected env (${keysCount}) from ${shortPaths.join(",")} ${dim(`// tip: ${_getRandomTip()}`)}`);
294
+ }
295
+ if (lastError) {
296
+ return { parsed: parsedAll, error: lastError };
297
+ } else {
298
+ return { parsed: parsedAll };
299
+ }
300
+ }
301
+ function config(options) {
302
+ if (_dotenvKey(options).length === 0) {
303
+ return DotenvModule.configDotenv(options);
304
+ }
305
+ const vaultPath = _vaultPath(options);
306
+ if (!vaultPath) {
307
+ _warn(`you set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}`);
308
+ return DotenvModule.configDotenv(options);
309
+ }
310
+ return DotenvModule._configVault(options);
311
+ }
312
+ function decrypt(encrypted, keyStr) {
313
+ const key = Buffer.from(keyStr.slice(-64), "hex");
314
+ let ciphertext = Buffer.from(encrypted, "base64");
315
+ const nonce = ciphertext.subarray(0, 12);
316
+ const authTag = ciphertext.subarray(-16);
317
+ ciphertext = ciphertext.subarray(12, -16);
318
+ try {
319
+ const aesgcm = crypto.createDecipheriv("aes-256-gcm", key, nonce);
320
+ aesgcm.setAuthTag(authTag);
321
+ return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
322
+ } catch (error) {
323
+ const isRange = error instanceof RangeError;
324
+ const invalidKeyLength = error.message === "Invalid key length";
325
+ const decryptionFailed = error.message === "Unsupported state or unable to authenticate data";
326
+ if (isRange || invalidKeyLength) {
327
+ const err = new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
328
+ err.code = "INVALID_DOTENV_KEY";
329
+ throw err;
330
+ } else if (decryptionFailed) {
331
+ const err = new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
332
+ err.code = "DECRYPTION_FAILED";
333
+ throw err;
334
+ } else {
335
+ throw error;
336
+ }
337
+ }
338
+ }
339
+ function populate(processEnv, parsed, options = {}) {
340
+ const debug = Boolean(options && options.debug);
341
+ const override = Boolean(options && options.override);
342
+ const populated = {};
343
+ if (typeof parsed !== "object") {
344
+ const err = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
345
+ err.code = "OBJECT_REQUIRED";
346
+ throw err;
347
+ }
348
+ for (const key of Object.keys(parsed)) {
349
+ if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
350
+ if (override === true) {
351
+ processEnv[key] = parsed[key];
352
+ populated[key] = parsed[key];
353
+ }
354
+ if (debug) {
355
+ if (override === true) {
356
+ _debug(`"${key}" is already defined and WAS overwritten`);
357
+ } else {
358
+ _debug(`"${key}" is already defined and was NOT overwritten`);
359
+ }
360
+ }
361
+ } else {
362
+ processEnv[key] = parsed[key];
363
+ populated[key] = parsed[key];
364
+ }
365
+ }
366
+ return populated;
367
+ }
368
+ var DotenvModule = {
369
+ configDotenv,
370
+ _configVault,
371
+ _parseVault,
372
+ config,
373
+ decrypt,
374
+ parse,
375
+ populate
376
+ };
377
+ exports.configDotenv = DotenvModule.configDotenv;
378
+ exports._configVault = DotenvModule._configVault;
379
+ exports._parseVault = DotenvModule._parseVault;
380
+ exports.config = DotenvModule.config;
381
+ exports.decrypt = DotenvModule.decrypt;
382
+ exports.parse = DotenvModule.parse;
383
+ exports.populate = DotenvModule.populate;
384
+ module.exports = DotenvModule;
385
+ });
386
+
387
+ // ../../packages/shared/dist/config/xdg.js
388
+ import path from "path";
389
+ import os from "os";
390
+ function xdgEnv(name, fallback) {
391
+ const v = process.env[name];
392
+ return v && v.trim() ? v : fallback;
393
+ }
394
+ function xdgConfigHome() {
395
+ return xdgEnv("XDG_CONFIG_HOME", path.join(os.homedir(), ".config"));
396
+ }
397
+ function configDir(app) {
398
+ return path.join(xdgConfigHome(), app);
399
+ }
400
+ var init_xdg = () => {};
401
+
402
+ // ../../packages/shared/dist/config/massa-ai-config.js
403
+ import path2 from "path";
404
+ var defaultMassaAiConfig;
405
+ var init_massa_ai_config = __esm(() => {
406
+ init_xdg();
407
+ defaultMassaAiConfig = {
408
+ database: {
409
+ url: ""
410
+ },
411
+ embedding: {
412
+ provider: "ollama",
413
+ model: "nomic-embed-text:latest",
414
+ baseURL: "http://localhost:11434",
415
+ dimensions: 768
416
+ },
417
+ compression: {
418
+ defaultStrategy: "code_structure",
419
+ minTokensForCompression: 100,
420
+ targetCompressionRatio: 0.7
421
+ },
422
+ impact: {
423
+ bfsCteEnabled: false
424
+ },
425
+ capturePolicy: undefined,
426
+ cache: {
427
+ enabled: true,
428
+ l1MaxSizeMB: 100,
429
+ l2MaxSizeMB: 500,
430
+ defaultTTLSeconds: 3600
431
+ },
432
+ dataDir: path2.join(configDir("massa-ai"), "data"),
433
+ logging: {
434
+ level: "info",
435
+ enableMetrics: false
436
+ },
437
+ search: {
438
+ autoReindexMaxFiles: 200,
439
+ queryUnderstanding: {
440
+ enabled: false,
441
+ hydeEnabled: true,
442
+ cacheTtlMs: 300000,
443
+ cacheMaxSize: 256
444
+ },
445
+ rerank: {
446
+ enabled: false,
447
+ rerankWindow: 50
448
+ }
449
+ },
450
+ llm: {
451
+ enabled: false,
452
+ baseUrl: "http://localhost:11434/v1",
453
+ apiKey: "ollama",
454
+ model: "qwen2.5:7b-instruct",
455
+ codeModel: "qwen2.5-coder:7b",
456
+ temperature: 0.2,
457
+ maxOutputTokens: 8000,
458
+ timeoutMs: 90000,
459
+ disableThink: true
460
+ },
461
+ memory: {
462
+ decay: {
463
+ lambda: 0.02,
464
+ sigma: 0.6,
465
+ mu: 0.04,
466
+ coldThreshold: 0.2
467
+ },
468
+ bootstrap: {
469
+ enabled: true,
470
+ maxSeedMemories: 8,
471
+ centralityLimit: 10,
472
+ gitLogLimit: 20,
473
+ refreshEnabled: true
474
+ },
475
+ autoImprove: {
476
+ enabled: true,
477
+ reviewGate: false,
478
+ minObservations: 8,
479
+ minIntervalMs: 300000,
480
+ maxWindow: 16,
481
+ minQueryHits: 3,
482
+ minFileHits: 3,
483
+ minFixHits: 2
484
+ },
485
+ autoImportance: {
486
+ enabled: false
487
+ }
488
+ },
489
+ hooks: {
490
+ enabled: true,
491
+ maxPayloadBytes: 65536,
492
+ queue: {
493
+ maxPending: 256
494
+ },
495
+ bridge: {
496
+ enabled: true,
497
+ minObservations: 8,
498
+ minIntervalMs: 300000,
499
+ maxWindow: 8
500
+ }
501
+ },
502
+ synapse: {
503
+ enabled: true,
504
+ inhibition: {
505
+ diversityPenalty: { enabled: true, threshold: 0.85, lambda: 0.4, samePathPenalty: 0.15 },
506
+ temporalInhibition: { enabled: true, penaltyAgeMs: 3600000, penalty: 0.15 },
507
+ confidenceGate: {
508
+ enabled: true,
509
+ thresholds: { specific: 0.55, focused: 0.4, broad: 0.25 }
510
+ },
511
+ chainInhibition: { enabled: true }
512
+ },
513
+ scoring: {
514
+ attention: {
515
+ enabled: false,
516
+ rerankWindow: 50,
517
+ recencyHalfLifeMs: 7 * 24 * 60 * 60 * 1000,
518
+ semanticScale: 1,
519
+ weights: {
520
+ semantic: 0.25,
521
+ recency: 0.15,
522
+ accessHeat: 0.15,
523
+ taskAlign: 0.2,
524
+ agentAffinity: 0.1,
525
+ confidence: 0.15
526
+ }
527
+ }
528
+ },
529
+ metacognition: {
530
+ enabled: true,
531
+ lowConfidenceThreshold: 0.15,
532
+ definitiveTopScore: 0.8,
533
+ definitiveGap: 0.2
534
+ },
535
+ buffer: {
536
+ enabled: true,
537
+ maxSize: 20,
538
+ ttlMs: 900000,
539
+ hitBoost: 1.3,
540
+ matchThreshold: 0.4
541
+ }
542
+ },
543
+ handoffs: {
544
+ enabled: true
545
+ }
546
+ };
547
+ });
548
+
549
+ // ../../packages/shared/dist/config/config-loader.js
550
+ var exports_config_loader = {};
551
+ __export(exports_config_loader, {
552
+ saveConfig: () => saveConfig,
553
+ migrateDataDirOnce: () => migrateDataDirOnce,
554
+ loadConfigSafe: () => loadConfigSafe,
555
+ loadConfig: () => loadConfig,
556
+ initConfig: () => initConfig,
557
+ getConfigPath: () => getConfigPath,
558
+ getConfigForEnv: () => getConfigForEnv,
559
+ getConfigDir: () => getConfigDir,
560
+ configExists: () => configExists
561
+ });
562
+ import fs from "fs";
563
+ import path3 from "path";
564
+ import os2 from "os";
565
+ function getConfigDir() {
566
+ return CONFIG_DIR;
567
+ }
568
+ function getConfigPath() {
569
+ return CONFIG_FILE;
570
+ }
571
+ function configExists() {
572
+ return fs.existsSync(CONFIG_FILE);
573
+ }
574
+ function loadConfig() {
575
+ if (!fs.existsSync(CONFIG_FILE)) {
576
+ return defaultMassaAiConfig;
577
+ }
578
+ try {
579
+ const content = fs.readFileSync(CONFIG_FILE, "utf-8");
580
+ const userConfig = JSON.parse(content);
581
+ return {
582
+ ...defaultMassaAiConfig,
583
+ ...userConfig,
584
+ database: { ...defaultMassaAiConfig.database, ...userConfig.database },
585
+ embedding: { ...defaultMassaAiConfig.embedding, ...userConfig.embedding },
586
+ compression: { ...defaultMassaAiConfig.compression, ...userConfig.compression },
587
+ cache: { ...defaultMassaAiConfig.cache, ...userConfig.cache },
588
+ logging: { ...defaultMassaAiConfig.logging, ...userConfig.logging },
589
+ search: { ...defaultMassaAiConfig.search, ...userConfig.search },
590
+ llm: { ...defaultMassaAiConfig.llm, ...userConfig.llm },
591
+ memory: { ...defaultMassaAiConfig.memory, ...userConfig.memory },
592
+ hooks: { ...defaultMassaAiConfig.hooks, ...userConfig.hooks },
593
+ handoffs: { ...defaultMassaAiConfig.handoffs, ...userConfig.handoffs }
594
+ };
595
+ } catch (error) {
596
+ console.error(`Error loading config from ${CONFIG_FILE}:`, error);
597
+ return defaultMassaAiConfig;
598
+ }
599
+ }
600
+ function loadConfigSafe() {
601
+ try {
602
+ return loadConfig();
603
+ } catch {
604
+ return defaultMassaAiConfig;
605
+ }
606
+ }
607
+ function migrateDataDirOnce() {
608
+ if (migrationAttempted)
609
+ return;
610
+ migrationAttempted = true;
611
+ try {
612
+ const oldDir = path3.join(os2.homedir(), ".massa-ai-data");
613
+ const newDir = path3.join(getConfigDir(), "data");
614
+ if (fs.existsSync(newDir))
615
+ return;
616
+ if (!fs.existsSync(oldDir))
617
+ return;
618
+ fs.mkdirSync(path3.dirname(newDir), { recursive: true });
619
+ try {
620
+ fs.renameSync(oldDir, newDir);
621
+ console.warn(`[massa-ai] Migrated data directory: ${oldDir} -> ${newDir}`);
622
+ } catch (renameErr) {
623
+ console.error(`[massa-ai] Could not move data directory ${oldDir} -> ${newDir} ` + `(rename failed: ${renameErr?.code || renameErr?.message}). ` + `Move it manually, e.g.:
624
+ ` + ` mv "${oldDir}" "${newDir}"`);
625
+ }
626
+ } catch (err) {
627
+ console.error(`[massa-ai] Data directory migration skipped:`, err);
628
+ }
629
+ }
630
+ function saveConfig(config) {
631
+ if (!fs.existsSync(CONFIG_DIR)) {
632
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
633
+ }
634
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
635
+ }
636
+ function initConfig() {
637
+ if (!fs.existsSync(CONFIG_FILE)) {
638
+ saveConfig(defaultMassaAiConfig);
639
+ console.log(`Created default config at ${CONFIG_FILE}`);
640
+ }
641
+ }
642
+ function getConfigForEnv() {
643
+ const config = loadConfig();
644
+ const env = {};
645
+ if (config.embedding.provider === "ollama") {
646
+ env.OLLAMA_EMBEDDING_MODEL = config.embedding.model;
647
+ env.OLLAMA_BASE_URL = config.embedding.baseURL || "http://localhost:11434";
648
+ if (config.embedding.dimensions) {
649
+ env.OLLAMA_EMBEDDING_DIMENSIONS = String(config.embedding.dimensions);
650
+ }
651
+ } else if (config.embedding.provider === "mistral") {
652
+ env.MISTRAL_API_KEY = config.embedding.apiKey || "";
653
+ env.MISTRAL_TEXT_EMBEDDING_MODEL = config.embedding.model;
654
+ } else if (config.embedding.provider === "openai") {
655
+ env.OPENAI_API_KEY = config.embedding.apiKey || "";
656
+ env.OPENAI_EMBEDDING_MODEL = config.embedding.model;
657
+ }
658
+ env.LOG_LEVEL = config.logging.level;
659
+ env.ENABLE_METRICS = String(config.logging.enableMetrics);
660
+ return env;
661
+ }
662
+ var CONFIG_DIR, CONFIG_FILE, migrationAttempted = false;
663
+ var init_config_loader = __esm(() => {
664
+ init_massa_ai_config();
665
+ init_xdg();
666
+ CONFIG_DIR = configDir("massa-ai");
667
+ CONFIG_FILE = path3.join(CONFIG_DIR, "config.json");
668
+ });
669
+
670
+ // ../../packages/shared/dist/env.js
671
+ var import_dotenv = __toESM(require_main(), 1);
672
+ import { existsSync } from "fs";
673
+ import { resolve, dirname } from "path";
674
+ function findEnvFile() {
675
+ let dir = process.cwd();
676
+ while (true) {
677
+ const envPath = resolve(dir, ".env");
678
+ if (existsSync(envPath)) {
679
+ return envPath;
680
+ }
681
+ const parent = dirname(dir);
682
+ if (parent === dir)
683
+ break;
684
+ dir = parent;
685
+ }
686
+ return;
687
+ }
688
+ var envPath = findEnvFile();
689
+ import_dotenv.config({ path: envPath });
690
+ try {
691
+ const { loadConfigSafe: loadConfigSafe2, migrateDataDirOnce: migrateDataDirOnce2 } = (init_config_loader(), __toCommonJS(exports_config_loader));
692
+ migrateDataDirOnce2();
693
+ const cfg = loadConfigSafe2();
694
+ if (cfg.database?.url && !process.env.DATABASE_URL) {
695
+ process.env.DATABASE_URL = cfg.database.url;
696
+ }
697
+ if (cfg.llm?.apiKey && !process.env.RLM_LLM_API_KEY) {
698
+ process.env.RLM_LLM_API_KEY = cfg.llm.apiKey;
699
+ }
700
+ if (cfg.embedding?.apiKey && !process.env.OLLAMA_API_KEY) {
701
+ process.env.OLLAMA_API_KEY = cfg.embedding.apiKey;
702
+ }
703
+ } catch {}
704
+
705
+ // ../../packages/shared/dist/config/index.js
706
+ init_config_loader();
707
+ init_massa_ai_config();
708
+ init_config_loader();
709
+ import path4 from "path";
710
+ var DEFAULT_LLM_MODEL = "qwen2.5:7b-instruct";
711
+ var DEFAULT_LLM_CODE_MODEL = "qwen2.5-coder:7b";
712
+ function envNum(key, fallback) {
713
+ const s = process.env[key];
714
+ if (s === undefined || s === "")
715
+ return fallback;
716
+ const n = Number(s);
717
+ return Number.isFinite(n) ? n : fallback;
718
+ }
719
+ function envBool(key, fallback) {
720
+ const s = process.env[key];
721
+ if (s === undefined || s === "")
722
+ return fallback;
723
+ const lower = s.toLowerCase();
724
+ if (lower === "true" || lower === "1")
725
+ return true;
726
+ if (lower === "false" || lower === "0")
727
+ return false;
728
+ return fallback;
729
+ }
730
+ function envString(key, fallback) {
731
+ const s = process.env[key];
732
+ return s === undefined || s === "" ? fallback : s;
733
+ }
734
+ var MAX_IGNORE_PATTERNS = 1024;
735
+ function validateCapturePolicyConfig(raw) {
736
+ if (!raw || typeof raw !== "object")
737
+ throw new TypeError("capturePolicy must be an object");
738
+ const p = raw;
739
+ const allowedKeys = new Set(["rules", "maxMatchWork", "maxIgnorePatterns"]);
740
+ for (const key of Object.keys(p)) {
741
+ if (!allowedKeys.has(key)) {
742
+ throw new TypeError(`capturePolicy: unknown field "${key}" (denyUnknownFields=true)`);
743
+ }
744
+ }
745
+ if (!Array.isArray(p.rules))
746
+ throw new TypeError("capturePolicy.rules must be an array");
747
+ const validDispositions = new Set(["Keep", "Drop", "MetadataOnly"]);
748
+ let dropCount = 0;
749
+ for (const rule of p.rules) {
750
+ if (!rule || typeof rule !== "object")
751
+ throw new TypeError("capturePolicy.rules[] must be objects");
752
+ if (typeof rule.pattern !== "string" || !rule.pattern) {
753
+ throw new TypeError("capturePolicy.rules[].pattern must be a non-empty string");
754
+ }
755
+ if (typeof rule.disposition !== "string" || !validDispositions.has(rule.disposition)) {
756
+ throw new TypeError(`capturePolicy.rules[].disposition must be Keep|Drop|MetadataOnly (got ${String(rule.disposition)})`);
757
+ }
758
+ if (rule.disposition === "Drop")
759
+ dropCount++;
760
+ }
761
+ const maxIgnore = typeof p.maxIgnorePatterns === "number" ? p.maxIgnorePatterns : MAX_IGNORE_PATTERNS;
762
+ if (dropCount > maxIgnore) {
763
+ throw new TypeError(`capturePolicy: ${dropCount} Drop rules exceed maxIgnorePatterns=${maxIgnore}`);
764
+ }
765
+ if (p.maxMatchWork !== undefined) {
766
+ if (typeof p.maxMatchWork !== "number" || p.maxMatchWork < 0) {
767
+ throw new TypeError("capturePolicy.maxMatchWork must be a non-negative number");
768
+ }
769
+ }
770
+ return {
771
+ rules: p.rules,
772
+ ...p.maxMatchWork !== undefined && { maxMatchWork: p.maxMatchWork },
773
+ ...p.maxIgnorePatterns !== undefined && { maxIgnorePatterns: p.maxIgnorePatterns }
774
+ };
775
+ }
776
+ function getGlobalDataDir() {
777
+ const envOverride = process.env.MASSA_AI_DATA_DIR;
778
+ if (envOverride && envOverride.trim())
779
+ return envOverride;
780
+ const fileConfig = loadConfigSafe();
781
+ if (fileConfig.dataDir)
782
+ return fileConfig.dataDir;
783
+ return path4.join(getConfigDir(), "data");
784
+ }
785
+ var DEFAULT_ALLOWED_EXTENSIONS = [
786
+ ".ts",
787
+ ".js",
788
+ ".tsx",
789
+ ".jsx",
790
+ ".vue",
791
+ ".dart",
792
+ ".py",
793
+ ".php",
794
+ ".java",
795
+ ".go",
796
+ ".rs",
797
+ ".cpp",
798
+ ".c",
799
+ ".h",
800
+ ".md",
801
+ ".json",
802
+ ".yaml",
803
+ ".yml",
804
+ ".hpp",
805
+ ".cs",
806
+ ".rb",
807
+ ".swift",
808
+ ".kt",
809
+ ".kts",
810
+ ".scala",
811
+ ".lua",
812
+ ".zig",
813
+ ".ex",
814
+ ".exs",
815
+ ".erl",
816
+ ".clj",
817
+ ".ml",
818
+ ".hs"
819
+ ];
820
+ var fileConfig = loadConfigSafe();
821
+ var fileCacheL1Bytes = fileConfig.cache?.l1MaxSizeMB ? fileConfig.cache.l1MaxSizeMB * 1024 * 1024 : undefined;
822
+ var fileCacheL2Bytes = fileConfig.cache?.l2MaxSizeMB ? fileConfig.cache.l2MaxSizeMB * 1024 * 1024 : undefined;
823
+ var defaultConfig = {
824
+ name: "massa-ai-server",
825
+ version: "1.0.0",
826
+ dataDir: getGlobalDataDir(),
827
+ cache: {
828
+ l1: {
829
+ maxSize: envNum("L1_CACHE_MAX_SIZE", fileCacheL1Bytes ?? 100 * 1024 * 1024),
830
+ defaultTTL: envNum("L1_CACHE_TTL", fileConfig.cache?.defaultTTLSeconds ?? 300)
831
+ },
832
+ l2: {
833
+ maxSize: envNum("L2_CACHE_MAX_SIZE", fileCacheL2Bytes ?? 500 * 1024 * 1024),
834
+ defaultTTL: envNum("L2_CACHE_TTL", fileConfig.cache?.defaultTTLSeconds ?? 3600)
835
+ },
836
+ embedding: {
837
+ maxAgeHours: 168
838
+ }
839
+ },
840
+ search: {
841
+ autoReindexMaxFiles: envNum("AUTOREINDEX_MAX_FILES", fileConfig.search?.autoReindexMaxFiles ?? 200),
842
+ queryUnderstanding: {
843
+ enabled: envBool("SEARCH_QUERY_UNDERSTANDING_ENABLED", fileConfig.search?.queryUnderstanding?.enabled ?? false),
844
+ hydeEnabled: envBool("SEARCH_QUERY_UNDERSTANDING_HYDE_ENABLED", fileConfig.search?.queryUnderstanding?.hydeEnabled ?? true),
845
+ cacheTtlMs: envNum("SEARCH_QUERY_UNDERSTANDING_CACHE_TTL_MS", fileConfig.search?.queryUnderstanding?.cacheTtlMs ?? 300000),
846
+ cacheMaxSize: envNum("SEARCH_QUERY_UNDERSTANDING_CACHE_MAX_SIZE", fileConfig.search?.queryUnderstanding?.cacheMaxSize ?? 256)
847
+ },
848
+ rerank: {
849
+ enabled: envBool("SEARCH_RERANK_ENABLED", fileConfig.search?.rerank?.enabled ?? false),
850
+ rerankWindow: envNum("SEARCH_RERANK_WINDOW", fileConfig.search?.rerank?.rerankWindow ?? 50)
851
+ }
852
+ },
853
+ llm: {
854
+ enabled: envBool("RLM_LLM_ENABLED", fileConfig.llm?.enabled ?? false),
855
+ baseUrl: envString("RLM_LLM_BASE_URL", fileConfig.llm?.baseUrl ?? "http://localhost:11434/v1"),
856
+ apiKey: envString("RLM_LLM_API_KEY", fileConfig.llm?.apiKey ?? "ollama"),
857
+ model: envString("RLM_LLM_MODEL", fileConfig.llm?.model ?? DEFAULT_LLM_MODEL),
858
+ codeModel: envString("RLM_LLM_CODE_MODEL", fileConfig.llm?.codeModel ?? DEFAULT_LLM_CODE_MODEL),
859
+ temperature: envNum("RLM_LLM_TEMPERATURE", fileConfig.llm?.temperature ?? 0.2),
860
+ maxOutputTokens: envNum("RLM_LLM_MAX_OUTPUT_TOKENS", fileConfig.llm?.maxOutputTokens ?? 8000),
861
+ timeoutMs: envNum("RLM_LLM_TIMEOUT_MS", fileConfig.llm?.timeoutMs ?? 90000),
862
+ disableThink: envBool("RLM_LLM_DISABLE_THINK", fileConfig.llm?.disableThink ?? true)
863
+ },
864
+ memory: {
865
+ decay: {
866
+ lambda: fileConfig.memory?.decay?.lambda ?? 0.02,
867
+ sigma: fileConfig.memory?.decay?.sigma ?? 0.6,
868
+ mu: fileConfig.memory?.decay?.mu ?? 0.04,
869
+ coldThreshold: fileConfig.memory?.decay?.coldThreshold ?? 0.2
870
+ },
871
+ bootstrap: {
872
+ enabled: envBool("BOOTSTRAP_ENABLED", fileConfig.memory?.bootstrap?.enabled ?? true),
873
+ maxSeedMemories: envNum("BOOTSTRAP_MAX_SEED_MEMORIES", fileConfig.memory?.bootstrap?.maxSeedMemories ?? 8),
874
+ centralityLimit: envNum("BOOTSTRAP_CENTRALITY_LIMIT", fileConfig.memory?.bootstrap?.centralityLimit ?? 10),
875
+ gitLogLimit: envNum("BOOTSTRAP_GIT_LOG_LIMIT", fileConfig.memory?.bootstrap?.gitLogLimit ?? 20),
876
+ refreshEnabled: envBool("BOOTSTRAP_REFRESH_ENABLED", fileConfig.memory?.bootstrap?.refreshEnabled ?? true)
877
+ },
878
+ autoImprove: {
879
+ enabled: envBool("AUTO_IMPROVE_ENABLED", fileConfig.memory?.autoImprove?.enabled ?? true),
880
+ reviewGate: envBool("AUTO_IMPROVE_REVIEW_GATE", fileConfig.memory?.autoImprove?.reviewGate ?? false),
881
+ minObservations: envNum("AUTO_IMPROVE_MIN_OBS", fileConfig.memory?.autoImprove?.minObservations ?? 8),
882
+ minIntervalMs: envNum("AUTO_IMPROVE_MIN_INTERVAL_MS", fileConfig.memory?.autoImprove?.minIntervalMs ?? 5 * 60 * 1000),
883
+ maxWindow: envNum("AUTO_IMPROVE_MAX_WINDOW", fileConfig.memory?.autoImprove?.maxWindow ?? 16),
884
+ minQueryHits: envNum("AUTO_IMPROVE_MIN_QUERY_HITS", fileConfig.memory?.autoImprove?.minQueryHits ?? 3),
885
+ minFileHits: envNum("AUTO_IMPROVE_MIN_FILE_HITS", fileConfig.memory?.autoImprove?.minFileHits ?? 3),
886
+ minFixHits: envNum("AUTO_IMPROVE_MIN_FIX_HITS", fileConfig.memory?.autoImprove?.minFixHits ?? 2)
887
+ },
888
+ autoImportance: {
889
+ enabled: envBool("AUTO_IMPORTANCE_ENABLED", fileConfig.memory?.autoImportance?.enabled ?? false)
890
+ }
891
+ },
892
+ hooks: {
893
+ enabled: envBool("HOOKS_ENABLED", fileConfig.hooks?.enabled ?? true),
894
+ maxPayloadBytes: envNum("HOOKS_MAX_PAYLOAD_BYTES", fileConfig.hooks?.maxPayloadBytes ?? 65536),
895
+ queue: {
896
+ maxPending: envNum("HOOKS_QUEUE_MAX_PENDING", fileConfig.hooks?.queue?.maxPending ?? 256)
897
+ },
898
+ bridge: {
899
+ enabled: envBool("HOOKS_BRIDGE_ENABLED", fileConfig.hooks?.bridge?.enabled ?? true),
900
+ minObservations: envNum("HOOKS_BRIDGE_MIN_OBS", fileConfig.hooks?.bridge?.minObservations ?? 8),
901
+ minIntervalMs: envNum("HOOKS_BRIDGE_MIN_INTERVAL_MS", fileConfig.hooks?.bridge?.minIntervalMs ?? 5 * 60 * 1000),
902
+ maxWindow: envNum("HOOKS_BRIDGE_MAX_WINDOW", fileConfig.hooks?.bridge?.maxWindow ?? 8)
903
+ }
904
+ },
905
+ handoffs: {
906
+ enabled: envBool("HANDOFFS_ENABLED", true)
907
+ },
908
+ compression: {
909
+ defaultStrategy: fileConfig.compression?.defaultStrategy ?? "code_structure",
910
+ minTokensForCompression: envNum("MIN_TOKENS_FOR_COMPRESSION", fileConfig.compression?.minTokensForCompression ?? 100),
911
+ targetCompressionRatio: envNum("TARGET_COMPRESSION_RATIO", fileConfig.compression?.targetCompressionRatio ?? 0.7),
912
+ prompt: process.env.RLM_LLM_PROMPT || fileConfig.compression?.prompt || undefined
913
+ },
914
+ impact: {
915
+ bfsCteEnabled: envBool("MASSA_AI_IMPACT_BFS_CTE", fileConfig.impact?.bfsCteEnabled ?? false)
916
+ },
917
+ capturePolicy: fileConfig.capturePolicy ? validateCapturePolicyConfig(fileConfig.capturePolicy) : undefined,
918
+ readFile: {
919
+ extraRoots: envString("MASSA_AI_READ_FILE_ROOTS", "").split(":").map((s) => s.trim()).filter((s) => s.length > 0)
920
+ },
921
+ filterValidation: {
922
+ maxFilterPatterns: envNum("MAX_FILTER_PATTERNS", 32)
923
+ },
924
+ rateLimit: {
925
+ requestsPerMinute: envNum("REQUESTS_PER_MINUTE", 60),
926
+ tokensPerMinute: envNum("TOKENS_PER_MINUTE", 1e5)
927
+ },
928
+ security: {
929
+ maxInputLength: envNum("MAX_INPUT_LENGTH", 1e5),
930
+ sanitizeInputs: process.env.SANITIZE_INPUTS !== "false",
931
+ maxIndexSize: 1e5,
932
+ maxFileSize: 1024 * 1024,
933
+ allowedExtensions: [...DEFAULT_ALLOWED_EXTENSIONS],
934
+ excludePatterns: [
935
+ "node_modules/**",
936
+ ".git/**",
937
+ "dist/**",
938
+ "build/**",
939
+ ".next/**",
940
+ "coverage/**",
941
+ "**/generated/**",
942
+ "*.min.js",
943
+ "*.min.css"
944
+ ]
945
+ },
946
+ logging: {
947
+ level: process.env.LOG_LEVEL || fileConfig.logging?.level || "info",
948
+ enableMetrics: process.env.ENABLE_METRICS === "true" || process.env.ENABLE_METRICS === undefined && !!fileConfig.logging?.enableMetrics
949
+ },
950
+ synapse: {
951
+ enabled: process.env.SYNAPSE_ENABLED !== "false",
952
+ inhibition: {
953
+ diversityPenalty: {
954
+ enabled: true,
955
+ threshold: 0.85,
956
+ lambda: 0.4,
957
+ samePathPenalty: 0.15
958
+ },
959
+ temporalInhibition: {
960
+ enabled: true,
961
+ penaltyAgeMs: 3600000,
962
+ penalty: 0.15
963
+ },
964
+ confidenceGate: {
965
+ enabled: true,
966
+ thresholds: { specific: 0.55, focused: 0.4, broad: 0.25 }
967
+ },
968
+ chainInhibition: { enabled: true }
969
+ },
970
+ scoring: {
971
+ attention: {
972
+ enabled: process.env.SYNAPSE_ATTENTION_ENABLED === "true",
973
+ rerankWindow: 50,
974
+ recencyHalfLifeMs: 7 * 24 * 60 * 60 * 1000,
975
+ semanticScale: 1,
976
+ weights: {
977
+ semantic: 0.25,
978
+ recency: 0.15,
979
+ accessHeat: 0.15,
980
+ taskAlign: 0.2,
981
+ agentAffinity: 0.1,
982
+ confidence: 0.15
983
+ }
984
+ }
985
+ },
986
+ metacognition: {
987
+ enabled: true,
988
+ lowConfidenceThreshold: 0.15,
989
+ definitiveTopScore: 0.8,
990
+ definitiveGap: 0.2
991
+ },
992
+ buffer: {
993
+ enabled: true,
994
+ maxSize: 20,
995
+ ttlMs: 900000,
996
+ hitBoost: 1.3,
997
+ matchThreshold: 0.4
998
+ }
999
+ }
1000
+ };
1001
+
1002
+ class Config {
1003
+ config;
1004
+ constructor(overrides) {
1005
+ this.config = this.mergeConfig(defaultConfig, overrides);
1006
+ this.validate();
1007
+ }
1008
+ mergeConfig(defaults, overrides) {
1009
+ if (!overrides)
1010
+ return defaults;
1011
+ return {
1012
+ ...defaults,
1013
+ ...overrides,
1014
+ cache: {
1015
+ l1: { ...defaults.cache.l1, ...overrides.cache?.l1 },
1016
+ l2: { ...defaults.cache.l2, ...overrides.cache?.l2 },
1017
+ embedding: {
1018
+ ...defaults.cache.embedding,
1019
+ ...overrides.cache?.embedding
1020
+ }
1021
+ },
1022
+ search: {
1023
+ ...defaults.search,
1024
+ ...overrides.search,
1025
+ queryUnderstanding: {
1026
+ ...defaults.search.queryUnderstanding,
1027
+ ...overrides.search?.queryUnderstanding
1028
+ },
1029
+ rerank: {
1030
+ ...defaults.search.rerank,
1031
+ ...overrides.search?.rerank
1032
+ }
1033
+ },
1034
+ llm: { ...defaults.llm, ...overrides.llm },
1035
+ memory: {
1036
+ ...defaults.memory,
1037
+ ...overrides.memory,
1038
+ decay: { ...defaults.memory.decay, ...overrides.memory?.decay },
1039
+ bootstrap: { ...defaults.memory.bootstrap, ...overrides.memory?.bootstrap },
1040
+ autoImprove: { ...defaults.memory.autoImprove, ...overrides.memory?.autoImprove },
1041
+ autoImportance: { ...defaults.memory.autoImportance, ...overrides.memory?.autoImportance }
1042
+ },
1043
+ hooks: {
1044
+ ...defaults.hooks,
1045
+ ...overrides.hooks,
1046
+ queue: { ...defaults.hooks.queue, ...overrides.hooks?.queue },
1047
+ bridge: { ...defaults.hooks.bridge, ...overrides.hooks?.bridge }
1048
+ },
1049
+ handoffs: {
1050
+ ...defaults.handoffs,
1051
+ ...overrides.handoffs
1052
+ },
1053
+ compression: {
1054
+ ...defaults.compression,
1055
+ ...overrides.compression
1056
+ },
1057
+ impact: {
1058
+ ...defaults.impact,
1059
+ ...overrides.impact
1060
+ },
1061
+ rateLimit: { ...defaults.rateLimit, ...overrides.rateLimit },
1062
+ security: { ...defaults.security, ...overrides.security },
1063
+ logging: { ...defaults.logging, ...overrides.logging },
1064
+ synapse: {
1065
+ ...defaults.synapse,
1066
+ ...overrides.synapse,
1067
+ inhibition: {
1068
+ ...defaults.synapse.inhibition,
1069
+ ...overrides.synapse?.inhibition,
1070
+ diversityPenalty: {
1071
+ ...defaults.synapse.inhibition.diversityPenalty,
1072
+ ...overrides.synapse?.inhibition?.diversityPenalty
1073
+ },
1074
+ temporalInhibition: {
1075
+ ...defaults.synapse.inhibition.temporalInhibition,
1076
+ ...overrides.synapse?.inhibition?.temporalInhibition
1077
+ },
1078
+ confidenceGate: {
1079
+ ...defaults.synapse.inhibition.confidenceGate,
1080
+ ...overrides.synapse?.inhibition?.confidenceGate,
1081
+ thresholds: {
1082
+ ...defaults.synapse.inhibition.confidenceGate.thresholds,
1083
+ ...overrides.synapse?.inhibition?.confidenceGate?.thresholds
1084
+ }
1085
+ },
1086
+ chainInhibition: {
1087
+ ...defaults.synapse.inhibition.chainInhibition,
1088
+ ...overrides.synapse?.inhibition?.chainInhibition
1089
+ }
1090
+ },
1091
+ scoring: {
1092
+ ...defaults.synapse.scoring,
1093
+ ...overrides.synapse?.scoring,
1094
+ attention: {
1095
+ ...defaults.synapse.scoring.attention,
1096
+ ...overrides.synapse?.scoring?.attention,
1097
+ weights: {
1098
+ ...defaults.synapse.scoring.attention.weights,
1099
+ ...overrides.synapse?.scoring?.attention?.weights
1100
+ }
1101
+ }
1102
+ },
1103
+ metacognition: {
1104
+ ...defaults.synapse.metacognition,
1105
+ ...overrides.synapse?.metacognition
1106
+ },
1107
+ buffer: {
1108
+ ...defaults.synapse.buffer,
1109
+ ...overrides.synapse?.buffer
1110
+ }
1111
+ }
1112
+ };
1113
+ }
1114
+ validate() {
1115
+ if (this.config.compression.targetCompressionRatio < 0 || this.config.compression.targetCompressionRatio > 1) {
1116
+ throw new Error("targetCompressionRatio must be between 0 and 1");
1117
+ }
1118
+ }
1119
+ get(key) {
1120
+ return this.config[key];
1121
+ }
1122
+ getNested(path5) {
1123
+ return path5.split(".").reduce((obj, key) => obj?.[key], this.config);
1124
+ }
1125
+ getAll() {
1126
+ return { ...this.config };
1127
+ }
1128
+ set(key, value) {
1129
+ this.config[key] = value;
1130
+ }
1131
+ }
1132
+ var config = new Config;
1133
+
1134
+ // src/config-cli.ts
1135
+ import { promises as fs2 } from "fs";
1136
+ import path5 from "path";
1137
+ import os3 from "os";
1138
+ import { fileURLToPath } from "url";
1139
+ var args = process.argv.slice(2);
1140
+ var command = args[0];
1141
+ var __dirname2 = path5.dirname(fileURLToPath(import.meta.url));
1142
+ function help() {
1143
+ console.log(`
1144
+ massa-ai-config - Configuration manager for massa-ai
1145
+
1146
+ Usage:
1147
+ massa-ai-config <command> [options]
1148
+
1149
+ Commands:
1150
+ init Initialize massa-ai configuration
1151
+ --ollama Use Ollama (local, default)
1152
+ --mistral <key> Use Mistral with API key
1153
+ --openai <key> Use OpenAI with API key
1154
+
1155
+ path Show config file path
1156
+ show Show current configuration
1157
+ set <key> <val> Set a configuration value
1158
+ use <provider> Switch embedding provider
1159
+ --api-key <key> API key (required for mistral/openai)
1160
+ --model <name> Model name
1161
+ --base-url <url> Base URL (for ollama)
1162
+
1163
+ agents Manage the 12 subagent specialist definitions
1164
+ agents install [--user|--project] Write 12 agent .md files
1165
+ agents uninstall [--user|--project] Remove only massa-ai-owned agents
1166
+
1167
+ Examples:
1168
+ massa-ai-config init
1169
+ massa-ai-config init --mistral your-api-key
1170
+ massa-ai-config use ollama --model nomic-embed-text:latest
1171
+ massa-ai-config use mistral --api-key your-key
1172
+ massa-ai-config set embedding.dimensions 1024
1173
+ massa-ai-config agents install --user
1174
+ `);
1175
+ }
1176
+ function parseOptions(args2) {
1177
+ const options = {};
1178
+ for (let i = 0;i < args2.length; i++) {
1179
+ if (args2[i].startsWith("--")) {
1180
+ const key = args2[i].slice(2);
1181
+ if (i + 1 < args2.length && !args2[i + 1].startsWith("--")) {
1182
+ options[key] = args2[i + 1];
1183
+ i++;
1184
+ } else {
1185
+ options[key] = true;
1186
+ }
1187
+ }
1188
+ }
1189
+ return options;
1190
+ }
1191
+ if (!command || command === "--help" || command === "-h") {
1192
+ help();
1193
+ process.exit(0);
1194
+ }
1195
+ var options = parseOptions(args.slice(1));
1196
+ switch (command) {
1197
+ case "init": {
1198
+ initConfig();
1199
+ if (options.mistral && typeof options.mistral === "string") {
1200
+ const config2 = loadConfig();
1201
+ config2.embedding = {
1202
+ provider: "mistral",
1203
+ model: "mistral-embed",
1204
+ apiKey: options.mistral,
1205
+ dimensions: 1024
1206
+ };
1207
+ saveConfig(config2);
1208
+ console.log("\u2713 Configured for Mistral embeddings");
1209
+ } else if (options.openai && typeof options.openai === "string") {
1210
+ const config2 = loadConfig();
1211
+ config2.embedding = {
1212
+ provider: "openai",
1213
+ model: "text-embedding-3-small",
1214
+ apiKey: options.openai,
1215
+ dimensions: 1536
1216
+ };
1217
+ saveConfig(config2);
1218
+ console.log("\u2713 Configured for OpenAI embeddings");
1219
+ } else {
1220
+ console.log("\u2713 Configured for Ollama (local) embeddings");
1221
+ }
1222
+ console.log(`
1223
+ Config file: ${getConfigPath()}`);
1224
+ break;
1225
+ }
1226
+ case "path": {
1227
+ console.log(getConfigPath());
1228
+ break;
1229
+ }
1230
+ case "show": {
1231
+ if (!configExists()) {
1232
+ console.log("No config file found. Run `massa-ai-config init` to create one.");
1233
+ console.log(`
1234
+ Using defaults:`);
1235
+ console.log(JSON.stringify(defaultMassaAiConfig, null, 2));
1236
+ process.exit(0);
1237
+ }
1238
+ const config2 = loadConfig();
1239
+ console.log(JSON.stringify(config2, null, 2));
1240
+ break;
1241
+ }
1242
+ case "set": {
1243
+ const key = args[1];
1244
+ const value = args[2];
1245
+ if (!key || !value) {
1246
+ console.error("Usage: massa-ai-config set <key> <value>");
1247
+ process.exit(1);
1248
+ }
1249
+ const config2 = loadConfig();
1250
+ const keys = key.split(".");
1251
+ let obj = config2;
1252
+ for (let i = 0;i < keys.length - 1; i++) {
1253
+ obj = obj[keys[i]];
1254
+ }
1255
+ const parsedValue = isNaN(Number(value)) ? value : Number(value);
1256
+ obj[keys[keys.length - 1]] = parsedValue;
1257
+ saveConfig(config2);
1258
+ console.log(`\u2713 Set ${key} = ${value}`);
1259
+ break;
1260
+ }
1261
+ case "use": {
1262
+ const provider = args[1];
1263
+ if (!provider || !["ollama", "mistral", "openai"].includes(provider)) {
1264
+ console.error("Provider must be: ollama, mistral, or openai");
1265
+ process.exit(1);
1266
+ }
1267
+ const config2 = loadConfig();
1268
+ if (provider === "ollama") {
1269
+ config2.embedding = {
1270
+ provider: "ollama",
1271
+ model: options.model || "nomic-embed-text:latest",
1272
+ baseURL: options["base-url"] || "http://localhost:11434",
1273
+ dimensions: 768
1274
+ };
1275
+ } else if (provider === "mistral") {
1276
+ if (!options["api-key"]) {
1277
+ console.error("Error: --api-key required for Mistral");
1278
+ process.exit(1);
1279
+ }
1280
+ config2.embedding = {
1281
+ provider: "mistral",
1282
+ model: options.model || "mistral-embed",
1283
+ apiKey: options["api-key"],
1284
+ dimensions: 1024
1285
+ };
1286
+ } else if (provider === "openai") {
1287
+ if (!options["api-key"]) {
1288
+ console.error("Error: --api-key required for OpenAI");
1289
+ process.exit(1);
1290
+ }
1291
+ config2.embedding = {
1292
+ provider: "openai",
1293
+ model: options.model || "text-embedding-3-small",
1294
+ apiKey: options["api-key"],
1295
+ dimensions: 1536
1296
+ };
1297
+ }
1298
+ saveConfig(config2);
1299
+ console.log(`\u2713 Switched to ${provider} embeddings`);
1300
+ console.log(` Model: ${config2.embedding.model}`);
1301
+ break;
1302
+ }
1303
+ case "agents": {
1304
+ const subcommand = args[1];
1305
+ if (subcommand !== "install" && subcommand !== "uninstall") {
1306
+ console.error("Usage: massa-ai-config agents <install|uninstall> [--user|--project]");
1307
+ process.exit(1);
1308
+ }
1309
+ const scope = typeof options.project === "boolean" ? "project" : "user";
1310
+ const agentsDir = scope === "project" ? path5.join(process.cwd(), ".opencode/agents") : path5.join(process.env.XDG_CONFIG_HOME && process.env.XDG_CONFIG_HOME.trim() || path5.join(os3.homedir(), ".config"), "opencode", "agents");
1311
+ const sourceAgentsDir = path5.resolve(__dirname2, "..", "agents");
1312
+ if (subcommand === "install") {
1313
+ await fs2.mkdir(agentsDir, { recursive: true });
1314
+ let count = 0;
1315
+ const entries = await fs2.readdir(sourceAgentsDir);
1316
+ for (const entry of entries) {
1317
+ if (!entry.startsWith("massa-ai-") || !entry.endsWith(".md"))
1318
+ continue;
1319
+ const src = path5.join(sourceAgentsDir, entry);
1320
+ const dest = path5.join(agentsDir, entry);
1321
+ await fs2.copyFile(src, dest);
1322
+ count++;
1323
+ }
1324
+ console.log(`+ ${count} subagent specialists: investigator, planner, builder, reviewer, context-curator, verification-agent, requirements-analyst, architecture-specialist, test-engineer, documentation-agent, audit-specialist, mobile-specialist`);
1325
+ console.log(` written to: ${agentsDir}`);
1326
+ } else {
1327
+ let removed = 0;
1328
+ try {
1329
+ const entries = await fs2.readdir(agentsDir);
1330
+ for (const entry of entries) {
1331
+ if (!entry.startsWith("massa-ai-") || !entry.endsWith(".md"))
1332
+ continue;
1333
+ const filePath = path5.join(agentsDir, entry);
1334
+ const content = await fs2.readFile(filePath, "utf8");
1335
+ if (content.includes("massa-ai-owned: true")) {
1336
+ await fs2.unlink(filePath);
1337
+ removed++;
1338
+ }
1339
+ }
1340
+ } catch (e) {
1341
+ if (e.code !== "ENOENT")
1342
+ throw e;
1343
+ }
1344
+ console.log(`- removed ${removed} massa-ai-owned agent files from ${agentsDir}`);
1345
+ console.log(" User agents preserved.");
1346
+ }
1347
+ break;
1348
+ }
1349
+ default:
1350
+ console.error(`Unknown command: ${command}`);
1351
+ help();
1352
+ process.exit(1);
1353
+ }