neuronlayer 0.1.0 → 0.1.2
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/README.md +156 -96
- package/dist/index.js +515 -493
- package/package.json +13 -13
- package/src/cli/commands.ts +133 -3
- package/src/index.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -8,8 +8,7 @@ var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
|
8
8
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
9
9
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
10
10
|
}) : x)(function(x) {
|
|
11
|
-
if (typeof require !== "undefined")
|
|
12
|
-
return require.apply(this, arguments);
|
|
11
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
13
12
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
14
13
|
});
|
|
15
14
|
var __commonJS = (cb, mod) => function __require2() {
|
|
@@ -2048,38 +2047,28 @@ var require_fast_deep_equal = __commonJS({
|
|
|
2048
2047
|
"node_modules/fast-deep-equal/index.js"(exports, module) {
|
|
2049
2048
|
"use strict";
|
|
2050
2049
|
module.exports = function equal(a, b) {
|
|
2051
|
-
if (a === b)
|
|
2052
|
-
return true;
|
|
2050
|
+
if (a === b) return true;
|
|
2053
2051
|
if (a && b && typeof a == "object" && typeof b == "object") {
|
|
2054
|
-
if (a.constructor !== b.constructor)
|
|
2055
|
-
return false;
|
|
2052
|
+
if (a.constructor !== b.constructor) return false;
|
|
2056
2053
|
var length, i, keys;
|
|
2057
2054
|
if (Array.isArray(a)) {
|
|
2058
2055
|
length = a.length;
|
|
2059
|
-
if (length != b.length)
|
|
2060
|
-
return false;
|
|
2056
|
+
if (length != b.length) return false;
|
|
2061
2057
|
for (i = length; i-- !== 0; )
|
|
2062
|
-
if (!equal(a[i], b[i]))
|
|
2063
|
-
return false;
|
|
2058
|
+
if (!equal(a[i], b[i])) return false;
|
|
2064
2059
|
return true;
|
|
2065
2060
|
}
|
|
2066
|
-
if (a.constructor === RegExp)
|
|
2067
|
-
|
|
2068
|
-
if (a.
|
|
2069
|
-
return a.valueOf() === b.valueOf();
|
|
2070
|
-
if (a.toString !== Object.prototype.toString)
|
|
2071
|
-
return a.toString() === b.toString();
|
|
2061
|
+
if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
|
|
2062
|
+
if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
|
|
2063
|
+
if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
|
|
2072
2064
|
keys = Object.keys(a);
|
|
2073
2065
|
length = keys.length;
|
|
2074
|
-
if (length !== Object.keys(b).length)
|
|
2075
|
-
return false;
|
|
2066
|
+
if (length !== Object.keys(b).length) return false;
|
|
2076
2067
|
for (i = length; i-- !== 0; )
|
|
2077
|
-
if (!Object.prototype.hasOwnProperty.call(b, keys[i]))
|
|
2078
|
-
return false;
|
|
2068
|
+
if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
|
|
2079
2069
|
for (i = length; i-- !== 0; ) {
|
|
2080
2070
|
var key = keys[i];
|
|
2081
|
-
if (!equal(a[key], b[key]))
|
|
2082
|
-
return false;
|
|
2071
|
+
if (!equal(a[key], b[key])) return false;
|
|
2083
2072
|
}
|
|
2084
2073
|
return true;
|
|
2085
2074
|
}
|
|
@@ -3235,8 +3224,7 @@ var require_utils = __commonJS({
|
|
|
3235
3224
|
function findToken(str, token) {
|
|
3236
3225
|
let ind = 0;
|
|
3237
3226
|
for (let i = 0; i < str.length; i++) {
|
|
3238
|
-
if (str[i] === token)
|
|
3239
|
-
ind++;
|
|
3227
|
+
if (str[i] === token) ind++;
|
|
3240
3228
|
}
|
|
3241
3229
|
return ind;
|
|
3242
3230
|
}
|
|
@@ -3694,8 +3682,7 @@ var require_fast_uri = __commonJS({
|
|
|
3694
3682
|
const options = Object.assign({}, opts);
|
|
3695
3683
|
const uriTokens = [];
|
|
3696
3684
|
const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
|
|
3697
|
-
if (schemeHandler && schemeHandler.serialize)
|
|
3698
|
-
schemeHandler.serialize(component, options);
|
|
3685
|
+
if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
|
|
3699
3686
|
if (component.path !== void 0) {
|
|
3700
3687
|
if (!options.skipEscape) {
|
|
3701
3688
|
component.path = escape(component.path);
|
|
@@ -4744,6 +4731,7 @@ var require_pattern = __commonJS({
|
|
|
4744
4731
|
"use strict";
|
|
4745
4732
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4746
4733
|
var code_1 = require_code2();
|
|
4734
|
+
var util_1 = require_util();
|
|
4747
4735
|
var codegen_1 = require_codegen();
|
|
4748
4736
|
var error2 = {
|
|
4749
4737
|
message: ({ schemaCode }) => (0, codegen_1.str)`must match pattern "${schemaCode}"`,
|
|
@@ -4756,10 +4744,18 @@ var require_pattern = __commonJS({
|
|
|
4756
4744
|
$data: true,
|
|
4757
4745
|
error: error2,
|
|
4758
4746
|
code(cxt) {
|
|
4759
|
-
const { data, $data, schema, schemaCode, it } = cxt;
|
|
4747
|
+
const { gen, data, $data, schema, schemaCode, it } = cxt;
|
|
4760
4748
|
const u = it.opts.unicodeRegExp ? "u" : "";
|
|
4761
|
-
|
|
4762
|
-
|
|
4749
|
+
if ($data) {
|
|
4750
|
+
const { regExp } = it.opts.code;
|
|
4751
|
+
const regExpCode = regExp.code === "new RegExp" ? (0, codegen_1._)`new RegExp` : (0, util_1.useFunc)(gen, regExp);
|
|
4752
|
+
const valid = gen.let("valid");
|
|
4753
|
+
gen.try(() => gen.assign(valid, (0, codegen_1._)`${regExpCode}(${schemaCode}, ${u}).test(${data})`), () => gen.assign(valid, false));
|
|
4754
|
+
cxt.fail$data((0, codegen_1._)`!${valid}`);
|
|
4755
|
+
} else {
|
|
4756
|
+
const regExp = (0, code_1.usePattern)(cxt, schema);
|
|
4757
|
+
cxt.fail$data((0, codegen_1._)`!${regExp}.test(${data})`);
|
|
4758
|
+
}
|
|
4763
4759
|
}
|
|
4764
4760
|
};
|
|
4765
4761
|
exports.default = def;
|
|
@@ -15218,7 +15214,7 @@ function _stringbool(Classes, _params) {
|
|
|
15218
15214
|
type: "pipe",
|
|
15219
15215
|
in: stringSchema,
|
|
15220
15216
|
out: booleanSchema,
|
|
15221
|
-
transform: (input, payload) => {
|
|
15217
|
+
transform: ((input, payload) => {
|
|
15222
15218
|
let data = input;
|
|
15223
15219
|
if (params.case !== "sensitive")
|
|
15224
15220
|
data = data.toLowerCase();
|
|
@@ -15237,14 +15233,14 @@ function _stringbool(Classes, _params) {
|
|
|
15237
15233
|
});
|
|
15238
15234
|
return {};
|
|
15239
15235
|
}
|
|
15240
|
-
},
|
|
15241
|
-
reverseTransform: (input, _payload) => {
|
|
15236
|
+
}),
|
|
15237
|
+
reverseTransform: ((input, _payload) => {
|
|
15242
15238
|
if (input === true) {
|
|
15243
15239
|
return truthyArray[0] || "true";
|
|
15244
15240
|
} else {
|
|
15245
15241
|
return falsyArray[0] || "false";
|
|
15246
15242
|
}
|
|
15247
|
-
},
|
|
15243
|
+
}),
|
|
15248
15244
|
error: params.error
|
|
15249
15245
|
});
|
|
15250
15246
|
return codec2;
|
|
@@ -16482,10 +16478,10 @@ var ZodType2 = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
|
|
|
16482
16478
|
inst.with = inst.check;
|
|
16483
16479
|
inst.clone = (def2, params) => clone(inst, def2, params);
|
|
16484
16480
|
inst.brand = () => inst;
|
|
16485
|
-
inst.register = (reg, meta3) => {
|
|
16481
|
+
inst.register = ((reg, meta3) => {
|
|
16486
16482
|
reg.add(inst, meta3);
|
|
16487
16483
|
return inst;
|
|
16488
|
-
};
|
|
16484
|
+
});
|
|
16489
16485
|
inst.parse = (data, params) => parse2(inst, data, params, { callee: inst.parse });
|
|
16490
16486
|
inst.safeParse = (data, params) => safeParse3(inst, data, params);
|
|
16491
16487
|
inst.parseAsync = async (data, params) => parseAsync2(inst, data, params, { callee: inst.parseAsync });
|
|
@@ -20126,6 +20122,147 @@ var ExperimentalServerTasks = class {
|
|
|
20126
20122
|
requestStream(request, resultSchema, options) {
|
|
20127
20123
|
return this._server.requestStream(request, resultSchema, options);
|
|
20128
20124
|
}
|
|
20125
|
+
/**
|
|
20126
|
+
* Sends a sampling request and returns an AsyncGenerator that yields response messages.
|
|
20127
|
+
* The generator is guaranteed to end with either a 'result' or 'error' message.
|
|
20128
|
+
*
|
|
20129
|
+
* For task-augmented requests, yields 'taskCreated' and 'taskStatus' messages
|
|
20130
|
+
* before the final result.
|
|
20131
|
+
*
|
|
20132
|
+
* @example
|
|
20133
|
+
* ```typescript
|
|
20134
|
+
* const stream = server.experimental.tasks.createMessageStream({
|
|
20135
|
+
* messages: [{ role: 'user', content: { type: 'text', text: 'Hello' } }],
|
|
20136
|
+
* maxTokens: 100
|
|
20137
|
+
* }, {
|
|
20138
|
+
* onprogress: (progress) => {
|
|
20139
|
+
* // Handle streaming tokens via progress notifications
|
|
20140
|
+
* console.log('Progress:', progress.message);
|
|
20141
|
+
* }
|
|
20142
|
+
* });
|
|
20143
|
+
*
|
|
20144
|
+
* for await (const message of stream) {
|
|
20145
|
+
* switch (message.type) {
|
|
20146
|
+
* case 'taskCreated':
|
|
20147
|
+
* console.log('Task created:', message.task.taskId);
|
|
20148
|
+
* break;
|
|
20149
|
+
* case 'taskStatus':
|
|
20150
|
+
* console.log('Task status:', message.task.status);
|
|
20151
|
+
* break;
|
|
20152
|
+
* case 'result':
|
|
20153
|
+
* console.log('Final result:', message.result);
|
|
20154
|
+
* break;
|
|
20155
|
+
* case 'error':
|
|
20156
|
+
* console.error('Error:', message.error);
|
|
20157
|
+
* break;
|
|
20158
|
+
* }
|
|
20159
|
+
* }
|
|
20160
|
+
* ```
|
|
20161
|
+
*
|
|
20162
|
+
* @param params - The sampling request parameters
|
|
20163
|
+
* @param options - Optional request options (timeout, signal, task creation params, onprogress, etc.)
|
|
20164
|
+
* @returns AsyncGenerator that yields ResponseMessage objects
|
|
20165
|
+
*
|
|
20166
|
+
* @experimental
|
|
20167
|
+
*/
|
|
20168
|
+
createMessageStream(params, options) {
|
|
20169
|
+
const clientCapabilities = this._server.getClientCapabilities();
|
|
20170
|
+
if ((params.tools || params.toolChoice) && !clientCapabilities?.sampling?.tools) {
|
|
20171
|
+
throw new Error("Client does not support sampling tools capability.");
|
|
20172
|
+
}
|
|
20173
|
+
if (params.messages.length > 0) {
|
|
20174
|
+
const lastMessage = params.messages[params.messages.length - 1];
|
|
20175
|
+
const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [lastMessage.content];
|
|
20176
|
+
const hasToolResults = lastContent.some((c) => c.type === "tool_result");
|
|
20177
|
+
const previousMessage = params.messages.length > 1 ? params.messages[params.messages.length - 2] : void 0;
|
|
20178
|
+
const previousContent = previousMessage ? Array.isArray(previousMessage.content) ? previousMessage.content : [previousMessage.content] : [];
|
|
20179
|
+
const hasPreviousToolUse = previousContent.some((c) => c.type === "tool_use");
|
|
20180
|
+
if (hasToolResults) {
|
|
20181
|
+
if (lastContent.some((c) => c.type !== "tool_result")) {
|
|
20182
|
+
throw new Error("The last message must contain only tool_result content if any is present");
|
|
20183
|
+
}
|
|
20184
|
+
if (!hasPreviousToolUse) {
|
|
20185
|
+
throw new Error("tool_result blocks are not matching any tool_use from the previous message");
|
|
20186
|
+
}
|
|
20187
|
+
}
|
|
20188
|
+
if (hasPreviousToolUse) {
|
|
20189
|
+
const toolUseIds = new Set(previousContent.filter((c) => c.type === "tool_use").map((c) => c.id));
|
|
20190
|
+
const toolResultIds = new Set(lastContent.filter((c) => c.type === "tool_result").map((c) => c.toolUseId));
|
|
20191
|
+
if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id) => toolResultIds.has(id))) {
|
|
20192
|
+
throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match");
|
|
20193
|
+
}
|
|
20194
|
+
}
|
|
20195
|
+
}
|
|
20196
|
+
return this.requestStream({
|
|
20197
|
+
method: "sampling/createMessage",
|
|
20198
|
+
params
|
|
20199
|
+
}, CreateMessageResultSchema, options);
|
|
20200
|
+
}
|
|
20201
|
+
/**
|
|
20202
|
+
* Sends an elicitation request and returns an AsyncGenerator that yields response messages.
|
|
20203
|
+
* The generator is guaranteed to end with either a 'result' or 'error' message.
|
|
20204
|
+
*
|
|
20205
|
+
* For task-augmented requests (especially URL-based elicitation), yields 'taskCreated'
|
|
20206
|
+
* and 'taskStatus' messages before the final result.
|
|
20207
|
+
*
|
|
20208
|
+
* @example
|
|
20209
|
+
* ```typescript
|
|
20210
|
+
* const stream = server.experimental.tasks.elicitInputStream({
|
|
20211
|
+
* mode: 'url',
|
|
20212
|
+
* message: 'Please authenticate',
|
|
20213
|
+
* elicitationId: 'auth-123',
|
|
20214
|
+
* url: 'https://example.com/auth'
|
|
20215
|
+
* }, {
|
|
20216
|
+
* task: { ttl: 300000 } // Task-augmented for long-running auth flow
|
|
20217
|
+
* });
|
|
20218
|
+
*
|
|
20219
|
+
* for await (const message of stream) {
|
|
20220
|
+
* switch (message.type) {
|
|
20221
|
+
* case 'taskCreated':
|
|
20222
|
+
* console.log('Task created:', message.task.taskId);
|
|
20223
|
+
* break;
|
|
20224
|
+
* case 'taskStatus':
|
|
20225
|
+
* console.log('Task status:', message.task.status);
|
|
20226
|
+
* break;
|
|
20227
|
+
* case 'result':
|
|
20228
|
+
* console.log('User action:', message.result.action);
|
|
20229
|
+
* break;
|
|
20230
|
+
* case 'error':
|
|
20231
|
+
* console.error('Error:', message.error);
|
|
20232
|
+
* break;
|
|
20233
|
+
* }
|
|
20234
|
+
* }
|
|
20235
|
+
* ```
|
|
20236
|
+
*
|
|
20237
|
+
* @param params - The elicitation request parameters
|
|
20238
|
+
* @param options - Optional request options (timeout, signal, task creation params, etc.)
|
|
20239
|
+
* @returns AsyncGenerator that yields ResponseMessage objects
|
|
20240
|
+
*
|
|
20241
|
+
* @experimental
|
|
20242
|
+
*/
|
|
20243
|
+
elicitInputStream(params, options) {
|
|
20244
|
+
const clientCapabilities = this._server.getClientCapabilities();
|
|
20245
|
+
const mode = params.mode ?? "form";
|
|
20246
|
+
switch (mode) {
|
|
20247
|
+
case "url": {
|
|
20248
|
+
if (!clientCapabilities?.elicitation?.url) {
|
|
20249
|
+
throw new Error("Client does not support url elicitation.");
|
|
20250
|
+
}
|
|
20251
|
+
break;
|
|
20252
|
+
}
|
|
20253
|
+
case "form": {
|
|
20254
|
+
if (!clientCapabilities?.elicitation?.form) {
|
|
20255
|
+
throw new Error("Client does not support form elicitation.");
|
|
20256
|
+
}
|
|
20257
|
+
break;
|
|
20258
|
+
}
|
|
20259
|
+
}
|
|
20260
|
+
const normalizedParams = mode === "form" && params.mode === void 0 ? { ...params, mode: "form" } : params;
|
|
20261
|
+
return this.requestStream({
|
|
20262
|
+
method: "elicitation/create",
|
|
20263
|
+
params: normalizedParams
|
|
20264
|
+
}, ElicitResultSchema, options);
|
|
20265
|
+
}
|
|
20129
20266
|
/**
|
|
20130
20267
|
* Gets the current status of a task.
|
|
20131
20268
|
*
|
|
@@ -21133,8 +21270,7 @@ var Tier2Storage = class {
|
|
|
21133
21270
|
getEmbedding(fileId) {
|
|
21134
21271
|
const stmt = this.db.prepare("SELECT embedding, dimension FROM embeddings WHERE file_id = ?");
|
|
21135
21272
|
const result = stmt.get(fileId);
|
|
21136
|
-
if (!result)
|
|
21137
|
-
return null;
|
|
21273
|
+
if (!result) return null;
|
|
21138
21274
|
return new Float32Array(result.embedding.buffer, result.embedding.byteOffset, result.dimension);
|
|
21139
21275
|
}
|
|
21140
21276
|
getAllEmbeddings() {
|
|
@@ -21173,8 +21309,7 @@ var Tier2Storage = class {
|
|
|
21173
21309
|
return searchResults;
|
|
21174
21310
|
}
|
|
21175
21311
|
cosineSimilarity(a, b) {
|
|
21176
|
-
if (a.length !== b.length)
|
|
21177
|
-
return 0;
|
|
21312
|
+
if (a.length !== b.length) return 0;
|
|
21178
21313
|
let dotProduct = 0;
|
|
21179
21314
|
let normA = 0;
|
|
21180
21315
|
let normB = 0;
|
|
@@ -21218,8 +21353,7 @@ var Tier2Storage = class {
|
|
|
21218
21353
|
getDecision(id) {
|
|
21219
21354
|
const stmt = this.db.prepare("SELECT * FROM decisions WHERE id = ?");
|
|
21220
21355
|
const row = stmt.get(id);
|
|
21221
|
-
if (!row)
|
|
21222
|
-
return null;
|
|
21356
|
+
if (!row) return null;
|
|
21223
21357
|
return {
|
|
21224
21358
|
id: row.id,
|
|
21225
21359
|
title: row.title,
|
|
@@ -21356,8 +21490,7 @@ var Tier2Storage = class {
|
|
|
21356
21490
|
getProjectSummary() {
|
|
21357
21491
|
const stmt = this.db.prepare("SELECT name, description, languages, key_directories, architecture_notes FROM project_summary WHERE id = 1");
|
|
21358
21492
|
const row = stmt.get();
|
|
21359
|
-
if (!row)
|
|
21360
|
-
return null;
|
|
21493
|
+
if (!row) return null;
|
|
21361
21494
|
return {
|
|
21362
21495
|
name: row.name,
|
|
21363
21496
|
description: row.description,
|
|
@@ -21468,8 +21601,7 @@ var Tier2Storage = class {
|
|
|
21468
21601
|
query += " LIMIT 1";
|
|
21469
21602
|
const stmt = this.db.prepare(query);
|
|
21470
21603
|
const row = stmt.get(...params);
|
|
21471
|
-
if (!row)
|
|
21472
|
-
return null;
|
|
21604
|
+
if (!row) return null;
|
|
21473
21605
|
return {
|
|
21474
21606
|
id: row.id,
|
|
21475
21607
|
fileId: row.fileId,
|
|
@@ -21577,8 +21709,7 @@ var Tier2Storage = class {
|
|
|
21577
21709
|
// Phase 2: Dependency graph helpers
|
|
21578
21710
|
getFileDependencies(filePath) {
|
|
21579
21711
|
const file2 = this.getFile(filePath);
|
|
21580
|
-
if (!file2)
|
|
21581
|
-
return [];
|
|
21712
|
+
if (!file2) return [];
|
|
21582
21713
|
const imports = this.getImportsByFile(file2.id);
|
|
21583
21714
|
const deps = [];
|
|
21584
21715
|
for (const imp of imports) {
|
|
@@ -21657,8 +21788,7 @@ var Tier3Storage = class {
|
|
|
21657
21788
|
const sessions = this.getRecentSessions(50);
|
|
21658
21789
|
const results = [];
|
|
21659
21790
|
for (const session of sessions) {
|
|
21660
|
-
if (!session.summary)
|
|
21661
|
-
continue;
|
|
21791
|
+
if (!session.summary) continue;
|
|
21662
21792
|
const summaryLower = session.summary.toLowerCase();
|
|
21663
21793
|
let matchCount = 0;
|
|
21664
21794
|
for (const keyword of keywords) {
|
|
@@ -21709,8 +21839,7 @@ var EmbeddingGenerator = class {
|
|
|
21709
21839
|
this.modelName = modelName;
|
|
21710
21840
|
}
|
|
21711
21841
|
async initialize() {
|
|
21712
|
-
if (this.initialized)
|
|
21713
|
-
return;
|
|
21842
|
+
if (this.initialized) return;
|
|
21714
21843
|
if (this.initializing) {
|
|
21715
21844
|
while (this.initializing) {
|
|
21716
21845
|
await new Promise((resolve3) => setTimeout(resolve3, 100));
|
|
@@ -21840,8 +21969,7 @@ var ASTParser = class {
|
|
|
21840
21969
|
this.dataDir = dataDir;
|
|
21841
21970
|
}
|
|
21842
21971
|
async initialize() {
|
|
21843
|
-
if (this.initialized)
|
|
21844
|
-
return;
|
|
21972
|
+
if (this.initialized) return;
|
|
21845
21973
|
try {
|
|
21846
21974
|
await Parser.init();
|
|
21847
21975
|
this.parser = new Parser();
|
|
@@ -22120,8 +22248,7 @@ var ASTParser = class {
|
|
|
22120
22248
|
const trimmed = line.trim();
|
|
22121
22249
|
const lineNum = i + 1;
|
|
22122
22250
|
const indent = line.length - line.trimStart().length;
|
|
22123
|
-
if (trimmed.startsWith("#"))
|
|
22124
|
-
continue;
|
|
22251
|
+
if (trimmed.startsWith("#")) continue;
|
|
22125
22252
|
let match = trimmed.match(patterns.function);
|
|
22126
22253
|
if (match && match[1]) {
|
|
22127
22254
|
symbols.push({
|
|
@@ -22209,8 +22336,7 @@ var ASTParser = class {
|
|
|
22209
22336
|
findPythonBlockEnd(lines, startIndex, baseIndent) {
|
|
22210
22337
|
for (let i = startIndex + 1; i < lines.length; i++) {
|
|
22211
22338
|
const line = lines[i] || "";
|
|
22212
|
-
if (line.trim() === "")
|
|
22213
|
-
continue;
|
|
22339
|
+
if (line.trim() === "") continue;
|
|
22214
22340
|
const indent = line.length - line.trimStart().length;
|
|
22215
22341
|
if (indent <= baseIndent) {
|
|
22216
22342
|
return i;
|
|
@@ -22369,12 +22495,9 @@ var CODE_EXTENSIONS = new Set(Object.keys(LANGUAGE_MAP));
|
|
|
22369
22495
|
function detectLanguage(filePath) {
|
|
22370
22496
|
const ext = extname(filePath).toLowerCase();
|
|
22371
22497
|
const filename = filePath.split(/[/\\]/).pop()?.toLowerCase() || "";
|
|
22372
|
-
if (filename === "dockerfile")
|
|
22373
|
-
|
|
22374
|
-
if (filename === "
|
|
22375
|
-
return "makefile";
|
|
22376
|
-
if (filename === "cmakelists.txt")
|
|
22377
|
-
return "cmake";
|
|
22498
|
+
if (filename === "dockerfile") return "dockerfile";
|
|
22499
|
+
if (filename === "makefile") return "makefile";
|
|
22500
|
+
if (filename === "cmakelists.txt") return "cmake";
|
|
22378
22501
|
return LANGUAGE_MAP[ext] || "plaintext";
|
|
22379
22502
|
}
|
|
22380
22503
|
function isCodeFile(filePath) {
|
|
@@ -22392,8 +22515,7 @@ function getPreview(content, maxLength = 1e3) {
|
|
|
22392
22515
|
return content.slice(0, maxLength) + "\n... [truncated]";
|
|
22393
22516
|
}
|
|
22394
22517
|
function countLines(content) {
|
|
22395
|
-
if (!content)
|
|
22396
|
-
return 0;
|
|
22518
|
+
if (!content) return 0;
|
|
22397
22519
|
return content.split("\n").length;
|
|
22398
22520
|
}
|
|
22399
22521
|
|
|
@@ -22609,8 +22731,7 @@ import { dirname as dirname4, basename } from "path";
|
|
|
22609
22731
|
// src/utils/tokens.ts
|
|
22610
22732
|
var AVG_CHARS_PER_TOKEN = 4;
|
|
22611
22733
|
function estimateTokens(text) {
|
|
22612
|
-
if (!text)
|
|
22613
|
-
return 0;
|
|
22734
|
+
if (!text) return 0;
|
|
22614
22735
|
return Math.ceil(text.length / AVG_CHARS_PER_TOKEN);
|
|
22615
22736
|
}
|
|
22616
22737
|
var TokenBudget = class {
|
|
@@ -23229,8 +23350,7 @@ var LearningEngine = class {
|
|
|
23229
23350
|
updateFileAccess(filePath) {
|
|
23230
23351
|
const fileStmt = this.db.prepare("SELECT id FROM files WHERE path = ?");
|
|
23231
23352
|
const file2 = fileStmt.get(filePath);
|
|
23232
|
-
if (!file2)
|
|
23233
|
-
return;
|
|
23353
|
+
if (!file2) return;
|
|
23234
23354
|
const stmt = this.db.prepare(`
|
|
23235
23355
|
INSERT INTO file_access (file_id, access_count, last_accessed, relevance_score)
|
|
23236
23356
|
VALUES (?, 1, unixepoch(), 0.5)
|
|
@@ -23246,16 +23366,14 @@ var LearningEngine = class {
|
|
|
23246
23366
|
getPersonalizedBoost(filePath) {
|
|
23247
23367
|
const fileStmt = this.db.prepare("SELECT id FROM files WHERE path = ?");
|
|
23248
23368
|
const file2 = fileStmt.get(filePath);
|
|
23249
|
-
if (!file2)
|
|
23250
|
-
return 1;
|
|
23369
|
+
if (!file2) return 1;
|
|
23251
23370
|
const stmt = this.db.prepare(`
|
|
23252
23371
|
SELECT access_count, last_accessed, relevance_score
|
|
23253
23372
|
FROM file_access
|
|
23254
23373
|
WHERE file_id = ?
|
|
23255
23374
|
`);
|
|
23256
23375
|
const stats = stmt.get(file2.id);
|
|
23257
|
-
if (!stats)
|
|
23258
|
-
return 1;
|
|
23376
|
+
if (!stats) return 1;
|
|
23259
23377
|
const frequencyBoost = 1 + Math.log10(1 + stats.accessCount) * 0.2;
|
|
23260
23378
|
const hoursSinceAccess = (Date.now() / 1e3 - stats.lastAccessed) / 3600;
|
|
23261
23379
|
const recencyBoost = Math.exp(-hoursSinceAccess / 168);
|
|
@@ -23594,53 +23712,31 @@ var FileSummarizer = class {
|
|
|
23594
23712
|
inferPurpose(fileName, content, symbols) {
|
|
23595
23713
|
const lowerName = fileName.toLowerCase();
|
|
23596
23714
|
const lowerContent = content.toLowerCase();
|
|
23597
|
-
if (lowerName.includes("middleware"))
|
|
23598
|
-
|
|
23599
|
-
if (lowerName.includes("
|
|
23600
|
-
|
|
23601
|
-
if (lowerName.includes("
|
|
23602
|
-
|
|
23603
|
-
if (lowerName.includes("
|
|
23604
|
-
|
|
23605
|
-
if (lowerName.includes("
|
|
23606
|
-
|
|
23607
|
-
if (lowerName.includes("
|
|
23608
|
-
|
|
23609
|
-
if (lowerName.includes("
|
|
23610
|
-
|
|
23611
|
-
if (lowerName.includes("
|
|
23612
|
-
|
|
23613
|
-
if (lowerName.includes("
|
|
23614
|
-
|
|
23615
|
-
if (
|
|
23616
|
-
|
|
23617
|
-
if (
|
|
23618
|
-
return "Tests";
|
|
23619
|
-
if (lowerName.includes("hook"))
|
|
23620
|
-
return "React hooks";
|
|
23621
|
-
if (lowerName.includes("context"))
|
|
23622
|
-
return "React context provider";
|
|
23623
|
-
if (lowerName.includes("store"))
|
|
23624
|
-
return "State management";
|
|
23625
|
-
if (lowerName.includes("api"))
|
|
23626
|
-
return "API client/definitions";
|
|
23627
|
-
if (lowerName.includes("auth"))
|
|
23628
|
-
return "Authentication";
|
|
23629
|
-
if (lowerName.includes("db") || lowerName.includes("database"))
|
|
23630
|
-
return "Database operations";
|
|
23631
|
-
if (lowerContent.includes("express") && lowerContent.includes("router"))
|
|
23632
|
-
return "Express router";
|
|
23633
|
-
if (lowerContent.includes("mongoose") || lowerContent.includes("prisma"))
|
|
23634
|
-
return "Database model";
|
|
23635
|
-
if (lowerContent.includes("usestate") || lowerContent.includes("useeffect"))
|
|
23636
|
-
return "React component";
|
|
23637
|
-
if (lowerContent.includes("describe(") && lowerContent.includes("it("))
|
|
23638
|
-
return "Test suite";
|
|
23715
|
+
if (lowerName.includes("middleware")) return "Request middleware/interceptor";
|
|
23716
|
+
if (lowerName.includes("route") || lowerName.includes("router")) return "API route definitions";
|
|
23717
|
+
if (lowerName.includes("controller")) return "Request handler/controller";
|
|
23718
|
+
if (lowerName.includes("service")) return "Business logic service";
|
|
23719
|
+
if (lowerName.includes("model")) return "Data model definitions";
|
|
23720
|
+
if (lowerName.includes("schema")) return "Schema/validation definitions";
|
|
23721
|
+
if (lowerName.includes("util") || lowerName.includes("helper")) return "Utility functions";
|
|
23722
|
+
if (lowerName.includes("config")) return "Configuration";
|
|
23723
|
+
if (lowerName.includes("constant")) return "Constants/enums";
|
|
23724
|
+
if (lowerName.includes("type") || lowerName.includes("interface")) return "Type definitions";
|
|
23725
|
+
if (lowerName.includes("test") || lowerName.includes("spec")) return "Tests";
|
|
23726
|
+
if (lowerName.includes("hook")) return "React hooks";
|
|
23727
|
+
if (lowerName.includes("context")) return "React context provider";
|
|
23728
|
+
if (lowerName.includes("store")) return "State management";
|
|
23729
|
+
if (lowerName.includes("api")) return "API client/definitions";
|
|
23730
|
+
if (lowerName.includes("auth")) return "Authentication";
|
|
23731
|
+
if (lowerName.includes("db") || lowerName.includes("database")) return "Database operations";
|
|
23732
|
+
if (lowerContent.includes("express") && lowerContent.includes("router")) return "Express router";
|
|
23733
|
+
if (lowerContent.includes("mongoose") || lowerContent.includes("prisma")) return "Database model";
|
|
23734
|
+
if (lowerContent.includes("usestate") || lowerContent.includes("useeffect")) return "React component";
|
|
23735
|
+
if (lowerContent.includes("describe(") && lowerContent.includes("it(")) return "Test suite";
|
|
23639
23736
|
const hasClasses = symbols.some((s) => s.kind === "class");
|
|
23640
23737
|
const hasInterfaces = symbols.some((s) => s.kind === "interface");
|
|
23641
23738
|
const hasFunctions = symbols.some((s) => s.kind === "function");
|
|
23642
|
-
if (hasInterfaces && !hasClasses && !hasFunctions)
|
|
23643
|
-
return "Type definitions";
|
|
23739
|
+
if (hasInterfaces && !hasClasses && !hasFunctions) return "Type definitions";
|
|
23644
23740
|
if (hasClasses && symbols.filter((s) => s.kind === "class").length === 1) {
|
|
23645
23741
|
const className = symbols.find((s) => s.kind === "class")?.name;
|
|
23646
23742
|
return `${className} implementation`;
|
|
@@ -23704,8 +23800,7 @@ var FileSummarizer = class {
|
|
|
23704
23800
|
// Get summaries for multiple files
|
|
23705
23801
|
getSummaries(fileIds) {
|
|
23706
23802
|
const result = /* @__PURE__ */ new Map();
|
|
23707
|
-
if (fileIds.length === 0)
|
|
23708
|
-
return result;
|
|
23803
|
+
if (fileIds.length === 0) return result;
|
|
23709
23804
|
const placeholders = fileIds.map(() => "?").join(",");
|
|
23710
23805
|
const stmt = this.db.prepare(`
|
|
23711
23806
|
SELECT file_id, summary
|
|
@@ -23721,8 +23816,7 @@ var FileSummarizer = class {
|
|
|
23721
23816
|
// Check if summary needs regeneration
|
|
23722
23817
|
needsRegeneration(fileId, fileLastModified) {
|
|
23723
23818
|
const summary = this.getSummary(fileId);
|
|
23724
|
-
if (!summary)
|
|
23725
|
-
return true;
|
|
23819
|
+
if (!summary) return true;
|
|
23726
23820
|
return fileLastModified > summary.generatedAt;
|
|
23727
23821
|
}
|
|
23728
23822
|
// Get compression ratio stats
|
|
@@ -23861,8 +23955,7 @@ var ProjectManager = class {
|
|
|
23861
23955
|
// Update project stats
|
|
23862
23956
|
updateProjectStats(projectId, stats) {
|
|
23863
23957
|
const project = this.registry.projects[projectId];
|
|
23864
|
-
if (!project)
|
|
23865
|
-
return;
|
|
23958
|
+
if (!project) return;
|
|
23866
23959
|
if (stats.totalFiles !== void 0) {
|
|
23867
23960
|
project.totalFiles = stats.totalFiles;
|
|
23868
23961
|
}
|
|
@@ -23919,13 +24012,11 @@ var ProjectManager = class {
|
|
|
23919
24012
|
join5(homeDir, "Documents")
|
|
23920
24013
|
];
|
|
23921
24014
|
for (const searchDir of searchDirs) {
|
|
23922
|
-
if (!existsSync4(searchDir))
|
|
23923
|
-
continue;
|
|
24015
|
+
if (!existsSync4(searchDir)) continue;
|
|
23924
24016
|
try {
|
|
23925
24017
|
const entries = readdirSync(searchDir, { withFileTypes: true });
|
|
23926
24018
|
for (const entry of entries) {
|
|
23927
|
-
if (!entry.isDirectory())
|
|
23928
|
-
continue;
|
|
24019
|
+
if (!entry.isDirectory()) continue;
|
|
23929
24020
|
const projectPath = join5(searchDir, entry.name);
|
|
23930
24021
|
const projectIndicators = [
|
|
23931
24022
|
"package.json",
|
|
@@ -24161,8 +24252,7 @@ ${decision.files.map((f) => `- \`${f}\``).join("\n")}
|
|
|
24161
24252
|
`;
|
|
24162
24253
|
}
|
|
24163
24254
|
getExistingADRFiles(dir) {
|
|
24164
|
-
if (!existsSync5(dir))
|
|
24165
|
-
return [];
|
|
24255
|
+
if (!existsSync5(dir)) return [];
|
|
24166
24256
|
try {
|
|
24167
24257
|
const { readdirSync: readdirSync4 } = __require("fs");
|
|
24168
24258
|
return readdirSync4(dir).filter((f) => /^\d{4}-.*\.md$/.test(f)).sort();
|
|
@@ -24171,8 +24261,7 @@ ${decision.files.map((f) => `- \`${f}\``).join("\n")}
|
|
|
24171
24261
|
}
|
|
24172
24262
|
}
|
|
24173
24263
|
getNextADRNumber(existingFiles) {
|
|
24174
|
-
if (existingFiles.length === 0)
|
|
24175
|
-
return 1;
|
|
24264
|
+
if (existingFiles.length === 0) return 1;
|
|
24176
24265
|
const numbers = existingFiles.map((f) => parseInt(f.split("-")[0] || "0", 10)).filter((n) => !isNaN(n));
|
|
24177
24266
|
return Math.max(...numbers, 0) + 1;
|
|
24178
24267
|
}
|
|
@@ -24220,8 +24309,7 @@ var FeatureContextManager = class extends EventEmitter3 {
|
|
|
24220
24309
|
this.recordChange(filePath, diff, linesChanged);
|
|
24221
24310
|
}
|
|
24222
24311
|
touchFile(filePath) {
|
|
24223
|
-
if (!this.current)
|
|
24224
|
-
return;
|
|
24312
|
+
if (!this.current) return;
|
|
24225
24313
|
const relativePath = this.toRelativePath(filePath);
|
|
24226
24314
|
const existing = this.current.files.find((f) => f.path === relativePath);
|
|
24227
24315
|
if (existing) {
|
|
@@ -24243,8 +24331,7 @@ var FeatureContextManager = class extends EventEmitter3 {
|
|
|
24243
24331
|
}
|
|
24244
24332
|
// ========== CHANGE TRACKING ==========
|
|
24245
24333
|
recordChange(filePath, diff, linesChanged) {
|
|
24246
|
-
if (!this.current)
|
|
24247
|
-
return;
|
|
24334
|
+
if (!this.current) return;
|
|
24248
24335
|
const relativePath = this.toRelativePath(filePath);
|
|
24249
24336
|
this.current.changes.unshift({
|
|
24250
24337
|
file: relativePath,
|
|
@@ -24265,8 +24352,7 @@ var FeatureContextManager = class extends EventEmitter3 {
|
|
|
24265
24352
|
// ========== QUERY TRACKING ==========
|
|
24266
24353
|
onQuery(query, filesUsed) {
|
|
24267
24354
|
this.ensureContext();
|
|
24268
|
-
if (!this.current)
|
|
24269
|
-
return;
|
|
24355
|
+
if (!this.current) return;
|
|
24270
24356
|
const relativeFiles = filesUsed.map((f) => this.toRelativePath(f));
|
|
24271
24357
|
this.current.queries.unshift({
|
|
24272
24358
|
query,
|
|
@@ -24283,8 +24369,7 @@ var FeatureContextManager = class extends EventEmitter3 {
|
|
|
24283
24369
|
// ========== HOT CACHE ==========
|
|
24284
24370
|
async preloadFile(filePath) {
|
|
24285
24371
|
const relativePath = this.toRelativePath(filePath);
|
|
24286
|
-
if (this.fileContents.has(relativePath))
|
|
24287
|
-
return;
|
|
24372
|
+
if (this.fileContents.has(relativePath)) return;
|
|
24288
24373
|
try {
|
|
24289
24374
|
const absolutePath = this.toAbsolutePath(relativePath);
|
|
24290
24375
|
const content = readFileSync6(absolutePath, "utf-8");
|
|
@@ -24327,8 +24412,7 @@ var FeatureContextManager = class extends EventEmitter3 {
|
|
|
24327
24412
|
};
|
|
24328
24413
|
}
|
|
24329
24414
|
generateSummary() {
|
|
24330
|
-
if (!this.current)
|
|
24331
|
-
return "";
|
|
24415
|
+
if (!this.current) return "";
|
|
24332
24416
|
const topFiles = this.current.files.sort((a, b) => b.touchCount - a.touchCount).slice(0, 5).map((f) => basename3(f.path)).join(", ");
|
|
24333
24417
|
const recentChanges = this.current.changes.length;
|
|
24334
24418
|
const durationMs = Date.now() - this.current.startedAt.getTime();
|
|
@@ -24345,8 +24429,7 @@ var FeatureContextManager = class extends EventEmitter3 {
|
|
|
24345
24429
|
return this.recent;
|
|
24346
24430
|
}
|
|
24347
24431
|
getCurrentSummary() {
|
|
24348
|
-
if (!this.current)
|
|
24349
|
-
return null;
|
|
24432
|
+
if (!this.current) return null;
|
|
24350
24433
|
return {
|
|
24351
24434
|
name: this.current.name,
|
|
24352
24435
|
files: this.current.files.length,
|
|
@@ -24382,16 +24465,14 @@ var FeatureContextManager = class extends EventEmitter3 {
|
|
|
24382
24465
|
return this.current;
|
|
24383
24466
|
}
|
|
24384
24467
|
setContextName(name) {
|
|
24385
|
-
if (!this.current)
|
|
24386
|
-
return false;
|
|
24468
|
+
if (!this.current) return false;
|
|
24387
24469
|
this.current.name = name;
|
|
24388
24470
|
this.save();
|
|
24389
24471
|
return true;
|
|
24390
24472
|
}
|
|
24391
24473
|
switchToRecent(contextId) {
|
|
24392
24474
|
const found = this.recent.find((c) => c.id === contextId);
|
|
24393
|
-
if (!found)
|
|
24394
|
-
return false;
|
|
24475
|
+
if (!found) return false;
|
|
24395
24476
|
if (this.current) {
|
|
24396
24477
|
this.current.status = "paused";
|
|
24397
24478
|
this.recent.unshift(this.current);
|
|
@@ -24407,16 +24488,14 @@ var FeatureContextManager = class extends EventEmitter3 {
|
|
|
24407
24488
|
}
|
|
24408
24489
|
reloadFiles() {
|
|
24409
24490
|
this.fileContents.clear();
|
|
24410
|
-
if (!this.current)
|
|
24411
|
-
return;
|
|
24491
|
+
if (!this.current) return;
|
|
24412
24492
|
const topFiles = this.current.files.sort((a, b) => b.touchCount - a.touchCount).slice(0, 10);
|
|
24413
24493
|
for (const file2 of topFiles) {
|
|
24414
24494
|
this.preloadFile(file2.path);
|
|
24415
24495
|
}
|
|
24416
24496
|
}
|
|
24417
24497
|
completeContext() {
|
|
24418
|
-
if (!this.current)
|
|
24419
|
-
return false;
|
|
24498
|
+
if (!this.current) return false;
|
|
24420
24499
|
this.current.status = "completed";
|
|
24421
24500
|
this.recent.unshift(this.current);
|
|
24422
24501
|
this.recent = this.recent.slice(0, MAX_RECENT_CONTEXTS);
|
|
@@ -24431,8 +24510,7 @@ var FeatureContextManager = class extends EventEmitter3 {
|
|
|
24431
24510
|
clearInterval(this.inactivityTimer);
|
|
24432
24511
|
}
|
|
24433
24512
|
this.inactivityTimer = setInterval(() => {
|
|
24434
|
-
if (!this.current)
|
|
24435
|
-
return;
|
|
24513
|
+
if (!this.current) return;
|
|
24436
24514
|
const inactiveMs = Date.now() - this.current.lastActiveAt.getTime();
|
|
24437
24515
|
if (inactiveMs > TTL_MINUTES * 60 * 1e3) {
|
|
24438
24516
|
this.current.status = "paused";
|
|
@@ -24584,8 +24662,7 @@ var FeatureContextManager = class extends EventEmitter3 {
|
|
|
24584
24662
|
];
|
|
24585
24663
|
for (let i = 0; i < Math.min(3, context.queries.length); i++) {
|
|
24586
24664
|
const query = context.queries[i];
|
|
24587
|
-
if (!query)
|
|
24588
|
-
continue;
|
|
24665
|
+
if (!query) continue;
|
|
24589
24666
|
for (const pattern of errorPatterns) {
|
|
24590
24667
|
if (pattern.test(query.query)) {
|
|
24591
24668
|
return query.query;
|
|
@@ -24789,8 +24866,7 @@ var ArchitectureGenerator = class _ArchitectureGenerator {
|
|
|
24789
24866
|
try {
|
|
24790
24867
|
const entries = readdirSync2(srcDir, { withFileTypes: true });
|
|
24791
24868
|
for (const entry of entries) {
|
|
24792
|
-
if (!entry.isDirectory())
|
|
24793
|
-
continue;
|
|
24869
|
+
if (!entry.isDirectory()) continue;
|
|
24794
24870
|
const dirName = entry.name.toLowerCase();
|
|
24795
24871
|
const layerName = _ArchitectureGenerator.LAYER_MAPPING[dirName];
|
|
24796
24872
|
if (layerName) {
|
|
@@ -24858,8 +24934,7 @@ var ArchitectureGenerator = class _ArchitectureGenerator {
|
|
|
24858
24934
|
for (const layer of layers) {
|
|
24859
24935
|
for (const filePath of layer.files.slice(0, 5)) {
|
|
24860
24936
|
const file2 = this.tier2.getFile(filePath);
|
|
24861
|
-
if (!file2)
|
|
24862
|
-
continue;
|
|
24937
|
+
if (!file2) continue;
|
|
24863
24938
|
const symbols = this.tier2.getSymbolsByFile(file2.id);
|
|
24864
24939
|
const exports = symbols.filter((s) => s.exported);
|
|
24865
24940
|
if (exports.length > 0) {
|
|
@@ -24878,18 +24953,12 @@ var ArchitectureGenerator = class _ArchitectureGenerator {
|
|
|
24878
24953
|
inferComponentPurpose(filePath, symbols) {
|
|
24879
24954
|
const name = basename4(filePath, ".ts").toLowerCase();
|
|
24880
24955
|
const mainExport = symbols.find((s) => s.kind === "class" || s.kind === "function");
|
|
24881
|
-
if (name.includes("engine"))
|
|
24882
|
-
|
|
24883
|
-
if (name.includes("
|
|
24884
|
-
|
|
24885
|
-
if (name.includes("
|
|
24886
|
-
|
|
24887
|
-
if (name.includes("indexer"))
|
|
24888
|
-
return "Content indexing";
|
|
24889
|
-
if (name.includes("context"))
|
|
24890
|
-
return "Context management";
|
|
24891
|
-
if (name.includes("config"))
|
|
24892
|
-
return "Configuration handling";
|
|
24956
|
+
if (name.includes("engine")) return "Main orchestration engine";
|
|
24957
|
+
if (name.includes("server")) return "Server implementation";
|
|
24958
|
+
if (name.includes("storage")) return "Data storage management";
|
|
24959
|
+
if (name.includes("indexer")) return "Content indexing";
|
|
24960
|
+
if (name.includes("context")) return "Context management";
|
|
24961
|
+
if (name.includes("config")) return "Configuration handling";
|
|
24893
24962
|
if (mainExport) {
|
|
24894
24963
|
return `Provides ${mainExport.name}`;
|
|
24895
24964
|
}
|
|
@@ -25165,8 +25234,7 @@ var ComponentGenerator = class {
|
|
|
25165
25234
|
const lines = output.trim().split("\n").filter(Boolean);
|
|
25166
25235
|
for (const line of lines) {
|
|
25167
25236
|
const [hash2, subject, author, dateStr] = line.split("|");
|
|
25168
|
-
if (!hash2 || !subject)
|
|
25169
|
-
continue;
|
|
25237
|
+
if (!hash2 || !subject) continue;
|
|
25170
25238
|
const { added, removed } = this.getCommitLineChanges(hash2, filePath);
|
|
25171
25239
|
history.push({
|
|
25172
25240
|
date: new Date(dateStr || Date.now()),
|
|
@@ -25298,8 +25366,7 @@ var ChangelogGenerator = class {
|
|
|
25298
25366
|
const lines = output.trim().split("\n").filter(Boolean);
|
|
25299
25367
|
for (const line of lines) {
|
|
25300
25368
|
const [hash2, subject, author, dateStr] = line.split("|");
|
|
25301
|
-
if (!hash2 || !subject)
|
|
25302
|
-
continue;
|
|
25369
|
+
if (!hash2 || !subject) continue;
|
|
25303
25370
|
const { files, additions, deletions } = this.getCommitStats(hash2);
|
|
25304
25371
|
commits.push({
|
|
25305
25372
|
hash: hash2.slice(0, 8),
|
|
@@ -25332,10 +25399,8 @@ var ChangelogGenerator = class {
|
|
|
25332
25399
|
}
|
|
25333
25400
|
const insertMatch = line.match(/(\d+)\s+insertion/);
|
|
25334
25401
|
const deleteMatch = line.match(/(\d+)\s+deletion/);
|
|
25335
|
-
if (insertMatch)
|
|
25336
|
-
|
|
25337
|
-
if (deleteMatch)
|
|
25338
|
-
deletions = parseInt(deleteMatch[1], 10);
|
|
25402
|
+
if (insertMatch) additions = parseInt(insertMatch[1], 10);
|
|
25403
|
+
if (deleteMatch) deletions = parseInt(deleteMatch[1], 10);
|
|
25339
25404
|
}
|
|
25340
25405
|
return { files, additions, deletions };
|
|
25341
25406
|
} catch {
|
|
@@ -25605,10 +25670,8 @@ var DocValidator = class {
|
|
|
25605
25670
|
if (filePath.includes("index.") || filePath.includes("/src/")) {
|
|
25606
25671
|
return "high";
|
|
25607
25672
|
}
|
|
25608
|
-
if (dependents.length >= 5)
|
|
25609
|
-
|
|
25610
|
-
if (dependents.length >= 2)
|
|
25611
|
-
return "medium";
|
|
25673
|
+
if (dependents.length >= 5) return "high";
|
|
25674
|
+
if (dependents.length >= 2) return "medium";
|
|
25612
25675
|
return "low";
|
|
25613
25676
|
}
|
|
25614
25677
|
mapSymbolKindToType(kind) {
|
|
@@ -25666,20 +25729,15 @@ var DocValidator = class {
|
|
|
25666
25729
|
formatTimeDiff(later, earlier) {
|
|
25667
25730
|
const diffMs = later.getTime() - earlier.getTime();
|
|
25668
25731
|
const diffDays = Math.floor(diffMs / (24 * 60 * 60 * 1e3));
|
|
25669
|
-
if (diffDays === 0)
|
|
25670
|
-
|
|
25671
|
-
if (diffDays
|
|
25672
|
-
|
|
25673
|
-
if (diffDays < 7)
|
|
25674
|
-
return `${diffDays} days`;
|
|
25675
|
-
if (diffDays < 30)
|
|
25676
|
-
return `${Math.floor(diffDays / 7)} weeks`;
|
|
25732
|
+
if (diffDays === 0) return "today";
|
|
25733
|
+
if (diffDays === 1) return "1 day";
|
|
25734
|
+
if (diffDays < 7) return `${diffDays} days`;
|
|
25735
|
+
if (diffDays < 30) return `${Math.floor(diffDays / 7)} weeks`;
|
|
25677
25736
|
return `${Math.floor(diffDays / 30)} months`;
|
|
25678
25737
|
}
|
|
25679
25738
|
calculateScore(outdated, undocumented) {
|
|
25680
25739
|
const totalFiles = this.tier2.getFileCount();
|
|
25681
|
-
if (totalFiles === 0)
|
|
25682
|
-
return 100;
|
|
25740
|
+
if (totalFiles === 0) return 100;
|
|
25683
25741
|
const outdatedPenalty = outdated.length / totalFiles * 30;
|
|
25684
25742
|
const highUndoc = undocumented.filter((u) => u.importance === "high").length;
|
|
25685
25743
|
const mediumUndoc = undocumented.filter((u) => u.importance === "medium").length;
|
|
@@ -25795,8 +25853,7 @@ var ActivityTracker = class {
|
|
|
25795
25853
|
const lines = output.trim().split("\n").filter(Boolean);
|
|
25796
25854
|
for (const line of lines) {
|
|
25797
25855
|
const [hash2, subject, author, dateStr] = line.split("|");
|
|
25798
|
-
if (!hash2 || !subject)
|
|
25799
|
-
continue;
|
|
25856
|
+
if (!hash2 || !subject) continue;
|
|
25800
25857
|
const files = this.getCommitFiles(hash2);
|
|
25801
25858
|
changes.push({
|
|
25802
25859
|
timestamp: new Date(dateStr || Date.now()),
|
|
@@ -26023,8 +26080,7 @@ var ContextHealthMonitor = class {
|
|
|
26023
26080
|
}
|
|
26024
26081
|
removeChunk(id) {
|
|
26025
26082
|
const index = this.contextChunks.findIndex((c) => c.id === id);
|
|
26026
|
-
if (index === -1)
|
|
26027
|
-
return false;
|
|
26083
|
+
if (index === -1) return false;
|
|
26028
26084
|
const chunk = this.contextChunks[index];
|
|
26029
26085
|
this.currentTokens -= chunk.tokens;
|
|
26030
26086
|
this.contextChunks.splice(index, 1);
|
|
@@ -26254,8 +26310,7 @@ var DriftDetector = class {
|
|
|
26254
26310
|
const earlier = messages[i];
|
|
26255
26311
|
for (let j = i + 1; j < messages.length; j++) {
|
|
26256
26312
|
const later = messages[j];
|
|
26257
|
-
if (earlier.role !== "assistant" || later.role !== "assistant")
|
|
26258
|
-
continue;
|
|
26313
|
+
if (earlier.role !== "assistant" || later.role !== "assistant") continue;
|
|
26259
26314
|
for (const pattern of CONTRADICTION_PATTERNS) {
|
|
26260
26315
|
const earlierMatch = earlier.content.match(pattern.earlier);
|
|
26261
26316
|
const laterMatch = later.content.match(pattern.later);
|
|
@@ -26441,8 +26496,7 @@ var CompactionEngine = class {
|
|
|
26441
26496
|
};
|
|
26442
26497
|
}
|
|
26443
26498
|
generateSummaries(chunks) {
|
|
26444
|
-
if (chunks.length === 0)
|
|
26445
|
-
return [];
|
|
26499
|
+
if (chunks.length === 0) return [];
|
|
26446
26500
|
const grouped = {};
|
|
26447
26501
|
for (const chunk of chunks) {
|
|
26448
26502
|
if (!grouped[chunk.type]) {
|
|
@@ -26452,8 +26506,7 @@ var CompactionEngine = class {
|
|
|
26452
26506
|
}
|
|
26453
26507
|
const summaries = [];
|
|
26454
26508
|
for (const [type, typeChunks] of Object.entries(grouped)) {
|
|
26455
|
-
if (typeChunks.length === 0)
|
|
26456
|
-
continue;
|
|
26509
|
+
if (typeChunks.length === 0) continue;
|
|
26457
26510
|
const allContent = typeChunks.map((c) => c.content).join(" ");
|
|
26458
26511
|
const summary = this.extractiveSummarize(allContent, type);
|
|
26459
26512
|
summaries.push(summary);
|
|
@@ -26622,8 +26675,7 @@ var CriticalContextManager = class {
|
|
|
26622
26675
|
WHERE id = ?
|
|
26623
26676
|
`);
|
|
26624
26677
|
const row = stmt.get(id);
|
|
26625
|
-
if (!row)
|
|
26626
|
-
return null;
|
|
26678
|
+
if (!row) return null;
|
|
26627
26679
|
return {
|
|
26628
26680
|
id: row.id,
|
|
26629
26681
|
type: row.type,
|
|
@@ -26953,16 +27005,13 @@ ${code}` : code;
|
|
|
26953
27005
|
}
|
|
26954
27006
|
switch (patternName) {
|
|
26955
27007
|
case "error-handling":
|
|
26956
|
-
if (/catch\s*\(\s*\w+\s*\)\s*\{[\s\S]*\}/.test(code))
|
|
26957
|
-
confidence += 10;
|
|
27008
|
+
if (/catch\s*\(\s*\w+\s*\)\s*\{[\s\S]*\}/.test(code)) confidence += 10;
|
|
26958
27009
|
break;
|
|
26959
27010
|
case "async-await":
|
|
26960
|
-
if (/await\s+[^;]+;/.test(code) && /async\s+/.test(code))
|
|
26961
|
-
confidence += 10;
|
|
27011
|
+
if (/await\s+[^;]+;/.test(code) && /async\s+/.test(code)) confidence += 10;
|
|
26962
27012
|
break;
|
|
26963
27013
|
case "null-check":
|
|
26964
|
-
if (/\?\.\w+/.test(code) || /!==?\s*null/.test(code))
|
|
26965
|
-
confidence += 10;
|
|
27014
|
+
if (/\?\.\w+/.test(code) || /!==?\s*null/.test(code)) confidence += 10;
|
|
26966
27015
|
break;
|
|
26967
27016
|
}
|
|
26968
27017
|
return Math.min(95, confidence);
|
|
@@ -26975,8 +27024,7 @@ ${code}` : code;
|
|
|
26975
27024
|
const pattern = CODE_PATTERNS.find((p) => p.name === patternName);
|
|
26976
27025
|
if (pattern && pattern.regex.test(preview)) {
|
|
26977
27026
|
examples.push(file2.path);
|
|
26978
|
-
if (examples.length >= 3)
|
|
26979
|
-
break;
|
|
27027
|
+
if (examples.length >= 3) break;
|
|
26980
27028
|
}
|
|
26981
27029
|
}
|
|
26982
27030
|
return examples;
|
|
@@ -27351,8 +27399,7 @@ var ConflictChecker = class {
|
|
|
27351
27399
|
const conflicts = [];
|
|
27352
27400
|
try {
|
|
27353
27401
|
const codeApproach = this.extractApproach(code);
|
|
27354
|
-
if (!codeApproach)
|
|
27355
|
-
return [];
|
|
27402
|
+
if (!codeApproach) return [];
|
|
27356
27403
|
const codeEmbedding = await this.embeddingGenerator.embed(codeApproach);
|
|
27357
27404
|
const relatedDecisions = this.tier2.searchDecisions(codeEmbedding, 5);
|
|
27358
27405
|
for (const related of relatedDecisions) {
|
|
@@ -27498,8 +27545,7 @@ var ConfidenceScorer = class _ConfidenceScorer {
|
|
|
27498
27545
|
};
|
|
27499
27546
|
}
|
|
27500
27547
|
calculateCodeScore(matches) {
|
|
27501
|
-
if (matches.length === 0)
|
|
27502
|
-
return 0;
|
|
27548
|
+
if (matches.length === 0) return 0;
|
|
27503
27549
|
let totalWeight = 0;
|
|
27504
27550
|
let weightedSum = 0;
|
|
27505
27551
|
for (const match of matches) {
|
|
@@ -27510,14 +27556,12 @@ var ConfidenceScorer = class _ConfidenceScorer {
|
|
|
27510
27556
|
return totalWeight > 0 ? weightedSum / totalWeight : 0;
|
|
27511
27557
|
}
|
|
27512
27558
|
calculateDecisionScore(matches) {
|
|
27513
|
-
if (matches.length === 0)
|
|
27514
|
-
return 50;
|
|
27559
|
+
if (matches.length === 0) return 50;
|
|
27515
27560
|
const totalRelevance = matches.reduce((sum, m) => sum + m.relevance, 0);
|
|
27516
27561
|
return totalRelevance / matches.length;
|
|
27517
27562
|
}
|
|
27518
27563
|
calculatePatternScore(matches) {
|
|
27519
|
-
if (matches.length === 0)
|
|
27520
|
-
return 30;
|
|
27564
|
+
if (matches.length === 0) return 30;
|
|
27521
27565
|
const totalConfidence = matches.reduce((sum, m) => sum + m.confidence, 0);
|
|
27522
27566
|
return totalConfidence / matches.length;
|
|
27523
27567
|
}
|
|
@@ -27525,12 +27569,9 @@ var ConfidenceScorer = class _ConfidenceScorer {
|
|
|
27525
27569
|
return codeScore * WEIGHTS.codebase + decisionScore * WEIGHTS.decision + patternScore * WEIGHTS.pattern;
|
|
27526
27570
|
}
|
|
27527
27571
|
determineLevel(score) {
|
|
27528
|
-
if (score >= THRESHOLDS.high)
|
|
27529
|
-
|
|
27530
|
-
if (score >= THRESHOLDS.
|
|
27531
|
-
return "medium";
|
|
27532
|
-
if (score >= THRESHOLDS.low)
|
|
27533
|
-
return "low";
|
|
27572
|
+
if (score >= THRESHOLDS.high) return "high";
|
|
27573
|
+
if (score >= THRESHOLDS.medium) return "medium";
|
|
27574
|
+
if (score >= THRESHOLDS.low) return "low";
|
|
27534
27575
|
return "guessing";
|
|
27535
27576
|
}
|
|
27536
27577
|
generateReasoning(level, sources, warnings) {
|
|
@@ -27585,10 +27626,13 @@ var ConfidenceScorer = class _ConfidenceScorer {
|
|
|
27585
27626
|
switch (level) {
|
|
27586
27627
|
case "high":
|
|
27587
27628
|
return "\u{1F7E2}";
|
|
27629
|
+
// Green circle
|
|
27588
27630
|
case "medium":
|
|
27589
27631
|
return "\u{1F7E1}";
|
|
27632
|
+
// Yellow circle
|
|
27590
27633
|
case "low":
|
|
27591
27634
|
return "\u{1F7E0}";
|
|
27635
|
+
// Orange circle
|
|
27592
27636
|
case "guessing":
|
|
27593
27637
|
return "\u{1F534}";
|
|
27594
27638
|
}
|
|
@@ -27665,8 +27709,7 @@ var ChangeTracker = class {
|
|
|
27665
27709
|
`git log --oneline -${limit} --format="%H|%an|%ad|%s" --date=unix`,
|
|
27666
27710
|
{ cwd: this.projectPath, encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 }
|
|
27667
27711
|
).trim();
|
|
27668
|
-
if (!logOutput)
|
|
27669
|
-
return 0;
|
|
27712
|
+
if (!logOutput) return 0;
|
|
27670
27713
|
const commits = logOutput.split("\n").filter(Boolean);
|
|
27671
27714
|
let synced = 0;
|
|
27672
27715
|
for (const commitLine of commits) {
|
|
@@ -27676,20 +27719,17 @@ var ChangeTracker = class {
|
|
|
27676
27719
|
const existing = this.db.prepare(
|
|
27677
27720
|
"SELECT id FROM change_history WHERE commit_hash = ?"
|
|
27678
27721
|
).get(hash2);
|
|
27679
|
-
if (existing)
|
|
27680
|
-
continue;
|
|
27722
|
+
if (existing) continue;
|
|
27681
27723
|
try {
|
|
27682
27724
|
const filesOutput = execSync5(
|
|
27683
27725
|
`git show --numstat --format="" ${hash2}`,
|
|
27684
27726
|
{ cwd: this.projectPath, encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 }
|
|
27685
27727
|
).trim();
|
|
27686
|
-
if (!filesOutput)
|
|
27687
|
-
continue;
|
|
27728
|
+
if (!filesOutput) continue;
|
|
27688
27729
|
const files = filesOutput.split("\n").filter(Boolean);
|
|
27689
27730
|
for (const fileLine of files) {
|
|
27690
27731
|
const [added, removed, filePath] = fileLine.split(" ");
|
|
27691
|
-
if (!filePath)
|
|
27692
|
-
continue;
|
|
27732
|
+
if (!filePath) continue;
|
|
27693
27733
|
let diff = "";
|
|
27694
27734
|
try {
|
|
27695
27735
|
const fullDiff = execSync5(
|
|
@@ -27729,10 +27769,8 @@ var ChangeTracker = class {
|
|
|
27729
27769
|
}
|
|
27730
27770
|
}
|
|
27731
27771
|
inferChangeType(added, removed, _filePath) {
|
|
27732
|
-
if (removed === 0 && added > 0)
|
|
27733
|
-
|
|
27734
|
-
if (added === 0 && removed > 0)
|
|
27735
|
-
return "delete";
|
|
27772
|
+
if (removed === 0 && added > 0) return "add";
|
|
27773
|
+
if (added === 0 && removed > 0) return "delete";
|
|
27736
27774
|
return "modify";
|
|
27737
27775
|
}
|
|
27738
27776
|
// Query changes
|
|
@@ -27829,8 +27867,7 @@ var ChangeTracker = class {
|
|
|
27829
27867
|
return this.queryChanges({ since }).changes;
|
|
27830
27868
|
}
|
|
27831
27869
|
parseSince(since) {
|
|
27832
|
-
if (since instanceof Date)
|
|
27833
|
-
return since;
|
|
27870
|
+
if (since instanceof Date) return since;
|
|
27834
27871
|
const now = /* @__PURE__ */ new Date();
|
|
27835
27872
|
const lower = since.toLowerCase();
|
|
27836
27873
|
if (lower === "today") {
|
|
@@ -28082,12 +28119,9 @@ var BugCorrelator = class {
|
|
|
28082
28119
|
score += 40;
|
|
28083
28120
|
}
|
|
28084
28121
|
const hoursAgo = (Date.now() - change.timestamp.getTime()) / (1e3 * 60 * 60);
|
|
28085
|
-
if (hoursAgo < 2)
|
|
28086
|
-
|
|
28087
|
-
else if (hoursAgo <
|
|
28088
|
-
score += 20;
|
|
28089
|
-
else if (hoursAgo < 24)
|
|
28090
|
-
score += 10;
|
|
28122
|
+
if (hoursAgo < 2) score += 30;
|
|
28123
|
+
else if (hoursAgo < 6) score += 20;
|
|
28124
|
+
else if (hoursAgo < 24) score += 10;
|
|
28091
28125
|
const diffLower = change.diff.toLowerCase();
|
|
28092
28126
|
let keywordMatches = 0;
|
|
28093
28127
|
for (const keyword of keywords) {
|
|
@@ -28113,8 +28147,7 @@ var BugCorrelator = class {
|
|
|
28113
28147
|
findSimilarBugs(error2, limit = 5) {
|
|
28114
28148
|
try {
|
|
28115
28149
|
const keywords = error2.split(/\s+/).filter((w) => w.length > 3).slice(0, 5).join(" OR ");
|
|
28116
|
-
if (!keywords)
|
|
28117
|
-
return [];
|
|
28150
|
+
if (!keywords) return [];
|
|
28118
28151
|
const rows = this.db.prepare(`
|
|
28119
28152
|
SELECT id, error, cause, fix_diff, file, timestamp, status
|
|
28120
28153
|
FROM bug_history
|
|
@@ -28150,8 +28183,7 @@ var BugCorrelator = class {
|
|
|
28150
28183
|
const words2 = new Set(error2.toLowerCase().split(/\s+/));
|
|
28151
28184
|
let matches = 0;
|
|
28152
28185
|
for (const word of words1) {
|
|
28153
|
-
if (words2.has(word))
|
|
28154
|
-
matches++;
|
|
28186
|
+
if (words2.has(word)) matches++;
|
|
28155
28187
|
}
|
|
28156
28188
|
const total = Math.max(words1.size, words2.size);
|
|
28157
28189
|
return total > 0 ? Math.round(matches / total * 100) : 0;
|
|
@@ -28186,14 +28218,11 @@ var BugCorrelator = class {
|
|
|
28186
28218
|
return parts.join(". ");
|
|
28187
28219
|
}
|
|
28188
28220
|
getSuggestedFix(pastBugs, _error) {
|
|
28189
|
-
if (pastBugs.length === 0)
|
|
28190
|
-
return null;
|
|
28221
|
+
if (pastBugs.length === 0) return null;
|
|
28191
28222
|
const bestMatch = pastBugs.find((bug) => bug.fix || bug.fixDiff);
|
|
28192
28223
|
if (bestMatch) {
|
|
28193
|
-
if (bestMatch.fix)
|
|
28194
|
-
|
|
28195
|
-
if (bestMatch.fixDiff)
|
|
28196
|
-
return `Apply similar fix:
|
|
28224
|
+
if (bestMatch.fix) return bestMatch.fix;
|
|
28225
|
+
if (bestMatch.fixDiff) return `Apply similar fix:
|
|
28197
28226
|
${bestMatch.fixDiff.slice(0, 200)}`;
|
|
28198
28227
|
}
|
|
28199
28228
|
return null;
|
|
@@ -28525,8 +28554,7 @@ var ChangeIntelligence = class {
|
|
|
28525
28554
|
}
|
|
28526
28555
|
// Initialize by syncing git history
|
|
28527
28556
|
initialize() {
|
|
28528
|
-
if (this.initialized)
|
|
28529
|
-
return 0;
|
|
28557
|
+
if (this.initialized) return 0;
|
|
28530
28558
|
const synced = this.changeTracker.syncFromGit(100);
|
|
28531
28559
|
this.initialized = true;
|
|
28532
28560
|
return synced;
|
|
@@ -28692,8 +28720,7 @@ var PatternLibrary = class {
|
|
|
28692
28720
|
}
|
|
28693
28721
|
seedDefaultPatterns() {
|
|
28694
28722
|
const count = this.db.prepare("SELECT COUNT(*) as count FROM patterns").get();
|
|
28695
|
-
if (count.count > 0)
|
|
28696
|
-
return;
|
|
28723
|
+
if (count.count > 0) return;
|
|
28697
28724
|
const defaultPatterns = [
|
|
28698
28725
|
{
|
|
28699
28726
|
name: "Error Handling",
|
|
@@ -28930,8 +28957,7 @@ export function MyComponent({ value, onChange }: Props) {
|
|
|
28930
28957
|
// Add example to pattern
|
|
28931
28958
|
addExample(id, example, isAntiPattern = false) {
|
|
28932
28959
|
const pattern = this.getPattern(id);
|
|
28933
|
-
if (!pattern)
|
|
28934
|
-
return false;
|
|
28960
|
+
if (!pattern) return false;
|
|
28935
28961
|
const field = isAntiPattern ? "anti_patterns" : "examples";
|
|
28936
28962
|
const current = isAntiPattern ? pattern.antiPatterns : pattern.examples;
|
|
28937
28963
|
current.push(example);
|
|
@@ -28944,8 +28970,7 @@ export function MyComponent({ value, onChange }: Props) {
|
|
|
28944
28970
|
// Add rule to pattern
|
|
28945
28971
|
addRule(id, rule) {
|
|
28946
28972
|
const pattern = this.getPattern(id);
|
|
28947
|
-
if (!pattern)
|
|
28948
|
-
return false;
|
|
28973
|
+
if (!pattern) return false;
|
|
28949
28974
|
pattern.rules.push(rule);
|
|
28950
28975
|
this.db.prepare("UPDATE patterns SET rules = ? WHERE id = ?").run(
|
|
28951
28976
|
JSON.stringify(pattern.rules),
|
|
@@ -29078,8 +29103,7 @@ var PatternLearner = class {
|
|
|
29078
29103
|
let patternsLearned = 0;
|
|
29079
29104
|
let examplesAdded = 0;
|
|
29080
29105
|
for (const file2 of files) {
|
|
29081
|
-
if (!file2.preview)
|
|
29082
|
-
continue;
|
|
29106
|
+
if (!file2.preview) continue;
|
|
29083
29107
|
const filePatterns = this.detectPatterns(file2.preview);
|
|
29084
29108
|
for (const detected of filePatterns) {
|
|
29085
29109
|
categories[detected.category] = (categories[detected.category] || 0) + 1;
|
|
@@ -29314,8 +29338,7 @@ var PatternValidator = class {
|
|
|
29314
29338
|
const patterns = category ? this.patternLibrary.getPatternsByCategory(category) : this.patternLibrary.getAllPatterns();
|
|
29315
29339
|
const matchedPattern = this.findBestMatch(code, patterns);
|
|
29316
29340
|
for (const rule of VALIDATION_RULES) {
|
|
29317
|
-
if (rule.category !== "all" && rule.category !== category)
|
|
29318
|
-
continue;
|
|
29341
|
+
if (rule.category !== "all" && rule.category !== category) continue;
|
|
29319
29342
|
const matches = rule.check.test(code);
|
|
29320
29343
|
if (rule.isViolation && matches) {
|
|
29321
29344
|
violations.push({
|
|
@@ -29399,18 +29422,12 @@ var PatternValidator = class {
|
|
|
29399
29422
|
}
|
|
29400
29423
|
// Detect what category of code this is
|
|
29401
29424
|
detectCategory(code) {
|
|
29402
|
-
if (/try\s*\{[\s\S]*catch/.test(code))
|
|
29403
|
-
|
|
29404
|
-
if (/
|
|
29405
|
-
|
|
29406
|
-
if (/
|
|
29407
|
-
|
|
29408
|
-
if (/if\s*\(\s*!?\w+\s*(?:===?|!==?)/.test(code))
|
|
29409
|
-
return "validation";
|
|
29410
|
-
if (/async\s+function|await\s+/.test(code))
|
|
29411
|
-
return "data_fetching";
|
|
29412
|
-
if (/console\.|logger\./.test(code))
|
|
29413
|
-
return "logging";
|
|
29425
|
+
if (/try\s*\{[\s\S]*catch/.test(code)) return "error_handling";
|
|
29426
|
+
if (/fetch\s*\(|axios\.|api\./.test(code)) return "api_call";
|
|
29427
|
+
if (/function\s+\w+.*\{[\s\S]*return\s*[(<]/.test(code)) return "component";
|
|
29428
|
+
if (/if\s*\(\s*!?\w+\s*(?:===?|!==?)/.test(code)) return "validation";
|
|
29429
|
+
if (/async\s+function|await\s+/.test(code)) return "data_fetching";
|
|
29430
|
+
if (/console\.|logger\./.test(code)) return "logging";
|
|
29414
29431
|
return null;
|
|
29415
29432
|
}
|
|
29416
29433
|
// Find the best matching pattern
|
|
@@ -29447,14 +29464,12 @@ var PatternValidator = class {
|
|
|
29447
29464
|
calculateSimilarity(code1, code2) {
|
|
29448
29465
|
const tokens1 = this.tokenize(code1);
|
|
29449
29466
|
const tokens2 = this.tokenize(code2);
|
|
29450
|
-
if (tokens1.length === 0 || tokens2.length === 0)
|
|
29451
|
-
return 0;
|
|
29467
|
+
if (tokens1.length === 0 || tokens2.length === 0) return 0;
|
|
29452
29468
|
const set1 = new Set(tokens1);
|
|
29453
29469
|
const set2 = new Set(tokens2);
|
|
29454
29470
|
let matches = 0;
|
|
29455
29471
|
for (const token of set1) {
|
|
29456
|
-
if (set2.has(token))
|
|
29457
|
-
matches++;
|
|
29472
|
+
if (set2.has(token)) matches++;
|
|
29458
29473
|
}
|
|
29459
29474
|
return matches / Math.max(set1.size, set2.size) * 100;
|
|
29460
29475
|
}
|
|
@@ -29551,15 +29566,13 @@ var DuplicateDetector = class {
|
|
|
29551
29566
|
const intentLower = intent.toLowerCase();
|
|
29552
29567
|
const intentWords = intentLower.split(/\s+/);
|
|
29553
29568
|
for (const [_key, func] of this.functionIndex) {
|
|
29554
|
-
if (!func.exported)
|
|
29555
|
-
continue;
|
|
29569
|
+
if (!func.exported) continue;
|
|
29556
29570
|
let relevance = 0;
|
|
29557
29571
|
const funcLower = func.name.toLowerCase();
|
|
29558
29572
|
const docLower = (func.docstring || "").toLowerCase();
|
|
29559
29573
|
const combined = `${funcLower} ${docLower}`;
|
|
29560
29574
|
for (const word of intentWords) {
|
|
29561
|
-
if (word.length < 3)
|
|
29562
|
-
continue;
|
|
29575
|
+
if (word.length < 3) continue;
|
|
29563
29576
|
if (funcLower.includes(word)) {
|
|
29564
29577
|
relevance += 30;
|
|
29565
29578
|
}
|
|
@@ -29603,17 +29616,14 @@ var DuplicateDetector = class {
|
|
|
29603
29616
|
calculateNameSimilarity(name1, name2) {
|
|
29604
29617
|
const lower1 = name1.toLowerCase();
|
|
29605
29618
|
const lower2 = name2.toLowerCase();
|
|
29606
|
-
if (lower1 === lower2)
|
|
29607
|
-
|
|
29608
|
-
if (lower1.includes(lower2) || lower2.includes(lower1))
|
|
29609
|
-
return 70;
|
|
29619
|
+
if (lower1 === lower2) return 100;
|
|
29620
|
+
if (lower1.includes(lower2) || lower2.includes(lower1)) return 70;
|
|
29610
29621
|
const tokens1 = this.camelCaseToTokens(name1);
|
|
29611
29622
|
const tokens2 = this.camelCaseToTokens(name2);
|
|
29612
29623
|
let matches = 0;
|
|
29613
29624
|
for (const t1 of tokens1) {
|
|
29614
29625
|
for (const t2 of tokens2) {
|
|
29615
|
-
if (t1 === t2)
|
|
29616
|
-
matches++;
|
|
29626
|
+
if (t1 === t2) matches++;
|
|
29617
29627
|
}
|
|
29618
29628
|
}
|
|
29619
29629
|
const totalTokens = Math.max(tokens1.length, tokens2.length);
|
|
@@ -29627,8 +29637,7 @@ var DuplicateDetector = class {
|
|
|
29627
29637
|
let total = 0;
|
|
29628
29638
|
for (const key of Object.keys(struct1)) {
|
|
29629
29639
|
total++;
|
|
29630
|
-
if (struct1[key] === struct2[key])
|
|
29631
|
-
matches++;
|
|
29640
|
+
if (struct1[key] === struct2[key]) matches++;
|
|
29632
29641
|
}
|
|
29633
29642
|
return total > 0 ? matches / total * 100 : 0;
|
|
29634
29643
|
}
|
|
@@ -29650,8 +29659,7 @@ var DuplicateDetector = class {
|
|
|
29650
29659
|
// Extract parameters from signature
|
|
29651
29660
|
extractParameters(signature) {
|
|
29652
29661
|
const match = signature.match(/\(([^)]*)\)/);
|
|
29653
|
-
if (!match)
|
|
29654
|
-
return [];
|
|
29662
|
+
if (!match) return [];
|
|
29655
29663
|
return match[1].split(",").map((p) => p.trim()).filter(Boolean).map((p) => p.split(":")[0].trim());
|
|
29656
29664
|
}
|
|
29657
29665
|
// Extract return type from signature
|
|
@@ -29669,8 +29677,7 @@ var DuplicateDetector = class {
|
|
|
29669
29677
|
let exportedFunctions = 0;
|
|
29670
29678
|
const byPurpose = {};
|
|
29671
29679
|
for (const [_key, func] of this.functionIndex) {
|
|
29672
|
-
if (func.exported)
|
|
29673
|
-
exportedFunctions++;
|
|
29680
|
+
if (func.exported) exportedFunctions++;
|
|
29674
29681
|
const purpose = this.detectPurpose(func.name) || "other";
|
|
29675
29682
|
byPurpose[purpose] = (byPurpose[purpose] || 0) + 1;
|
|
29676
29683
|
}
|
|
@@ -29697,8 +29704,7 @@ var ArchitectureEnforcement = class {
|
|
|
29697
29704
|
}
|
|
29698
29705
|
// Initialize by learning patterns from codebase
|
|
29699
29706
|
initialize() {
|
|
29700
|
-
if (this.initialized)
|
|
29701
|
-
return { patternsLearned: 0, examplesAdded: 0 };
|
|
29707
|
+
if (this.initialized) return { patternsLearned: 0, examplesAdded: 0 };
|
|
29702
29708
|
const result = this.patternLearner.learnFromCodebase();
|
|
29703
29709
|
this.initialized = true;
|
|
29704
29710
|
return {
|
|
@@ -29905,10 +29911,8 @@ var TestParser = class {
|
|
|
29905
29911
|
if (inTest) {
|
|
29906
29912
|
testContent += "\n" + line;
|
|
29907
29913
|
for (const char of line) {
|
|
29908
|
-
if (char === "{" || char === "(")
|
|
29909
|
-
|
|
29910
|
-
if (char === "}" || char === ")")
|
|
29911
|
-
braceCount--;
|
|
29914
|
+
if (char === "{" || char === "(") braceCount++;
|
|
29915
|
+
if (char === "}" || char === ")") braceCount--;
|
|
29912
29916
|
}
|
|
29913
29917
|
if (braceCount <= 0) {
|
|
29914
29918
|
const assertions = this.extractJsAssertions(testContent, testStartLine);
|
|
@@ -30039,20 +30043,16 @@ var TestParser = class {
|
|
|
30039
30043
|
testContent = line;
|
|
30040
30044
|
braceCount = 0;
|
|
30041
30045
|
for (const char of line) {
|
|
30042
|
-
if (char === "{")
|
|
30043
|
-
|
|
30044
|
-
if (char === "}")
|
|
30045
|
-
braceCount--;
|
|
30046
|
+
if (char === "{") braceCount++;
|
|
30047
|
+
if (char === "}") braceCount--;
|
|
30046
30048
|
}
|
|
30047
30049
|
continue;
|
|
30048
30050
|
}
|
|
30049
30051
|
if (inTest) {
|
|
30050
30052
|
testContent += "\n" + line;
|
|
30051
30053
|
for (const char of line) {
|
|
30052
|
-
if (char === "{")
|
|
30053
|
-
|
|
30054
|
-
if (char === "}")
|
|
30055
|
-
braceCount--;
|
|
30054
|
+
if (char === "{") braceCount++;
|
|
30055
|
+
if (char === "}") braceCount--;
|
|
30056
30056
|
}
|
|
30057
30057
|
if (braceCount <= 0) {
|
|
30058
30058
|
const assertions = this.extractGoAssertions(testContent, testStartLine);
|
|
@@ -30091,13 +30091,10 @@ var TestParser = class {
|
|
|
30091
30091
|
const namespaceImport = match[2];
|
|
30092
30092
|
const defaultImport = match[3];
|
|
30093
30093
|
const source = match[4];
|
|
30094
|
-
if (!source)
|
|
30095
|
-
continue;
|
|
30094
|
+
if (!source) continue;
|
|
30096
30095
|
const symbols = [...namedImports];
|
|
30097
|
-
if (namespaceImport)
|
|
30098
|
-
|
|
30099
|
-
if (defaultImport)
|
|
30100
|
-
symbols.push(defaultImport);
|
|
30096
|
+
if (namespaceImport) symbols.push(`* as ${namespaceImport}`);
|
|
30097
|
+
if (defaultImport) symbols.push(defaultImport);
|
|
30101
30098
|
imports.push({
|
|
30102
30099
|
source,
|
|
30103
30100
|
symbols,
|
|
@@ -30110,8 +30107,7 @@ var TestParser = class {
|
|
|
30110
30107
|
const destructured = destructuredStr ? destructuredStr.split(",").map((s) => s.trim()).filter(Boolean) : [];
|
|
30111
30108
|
const variable = match[2];
|
|
30112
30109
|
const source = match[3];
|
|
30113
|
-
if (!source)
|
|
30114
|
-
continue;
|
|
30110
|
+
if (!source) continue;
|
|
30115
30111
|
const symbols = destructured.length > 0 ? destructured : variable ? [variable] : [];
|
|
30116
30112
|
imports.push({
|
|
30117
30113
|
source,
|
|
@@ -30128,8 +30124,7 @@ var TestParser = class {
|
|
|
30128
30124
|
while ((match = fromImportRegex.exec(content)) !== null) {
|
|
30129
30125
|
const source = match[1];
|
|
30130
30126
|
const importedItemsStr = match[2];
|
|
30131
|
-
if (!source || !importedItemsStr)
|
|
30132
|
-
continue;
|
|
30127
|
+
if (!source || !importedItemsStr) continue;
|
|
30133
30128
|
const importedItems = importedItemsStr.split(",").map((s) => {
|
|
30134
30129
|
const trimmed = s.trim();
|
|
30135
30130
|
const parts = trimmed.split(/\s+as\s+/);
|
|
@@ -30144,8 +30139,7 @@ var TestParser = class {
|
|
|
30144
30139
|
const importRegex = /^import\s+([\w.]+)(?:\s+as\s+(\w+))?/gm;
|
|
30145
30140
|
while ((match = importRegex.exec(content)) !== null) {
|
|
30146
30141
|
const source = match[1];
|
|
30147
|
-
if (!source)
|
|
30148
|
-
continue;
|
|
30142
|
+
if (!source) continue;
|
|
30149
30143
|
const sourceParts = source.split(".");
|
|
30150
30144
|
const alias = match[2] ?? sourceParts[sourceParts.length - 1] ?? source;
|
|
30151
30145
|
imports.push({
|
|
@@ -30162,8 +30156,7 @@ var TestParser = class {
|
|
|
30162
30156
|
let match;
|
|
30163
30157
|
while ((match = singleImportRegex.exec(content)) !== null) {
|
|
30164
30158
|
const source = match[1];
|
|
30165
|
-
if (!source)
|
|
30166
|
-
continue;
|
|
30159
|
+
if (!source) continue;
|
|
30167
30160
|
const sourceParts = source.split("/");
|
|
30168
30161
|
const pkg = sourceParts[sourceParts.length - 1] ?? source;
|
|
30169
30162
|
imports.push({
|
|
@@ -30175,15 +30168,13 @@ var TestParser = class {
|
|
|
30175
30168
|
const importBlockRegex = /import\s*\(\s*([\s\S]*?)\s*\)/g;
|
|
30176
30169
|
while ((match = importBlockRegex.exec(content)) !== null) {
|
|
30177
30170
|
const block = match[1];
|
|
30178
|
-
if (!block)
|
|
30179
|
-
continue;
|
|
30171
|
+
if (!block) continue;
|
|
30180
30172
|
const lineRegex = /(?:(\w+)\s+)?"([^"]+)"/g;
|
|
30181
30173
|
let lineMatch;
|
|
30182
30174
|
while ((lineMatch = lineRegex.exec(block)) !== null) {
|
|
30183
30175
|
const alias = lineMatch[1];
|
|
30184
30176
|
const source = lineMatch[2];
|
|
30185
|
-
if (!source)
|
|
30186
|
-
continue;
|
|
30177
|
+
if (!source) continue;
|
|
30187
30178
|
const sourceParts = source.split("/");
|
|
30188
30179
|
const pkg = alias ?? sourceParts[sourceParts.length - 1] ?? source;
|
|
30189
30180
|
imports.push({
|
|
@@ -30198,8 +30189,7 @@ var TestParser = class {
|
|
|
30198
30189
|
getCoveredFilesFromImports(imports) {
|
|
30199
30190
|
return imports.filter((imp) => imp.isRelative).map((imp) => {
|
|
30200
30191
|
let path = imp.source;
|
|
30201
|
-
if (path.startsWith("./"))
|
|
30202
|
-
path = path.slice(2);
|
|
30192
|
+
if (path.startsWith("./")) path = path.slice(2);
|
|
30203
30193
|
if (!path.match(/\.[jt]sx?$|\.py$|\.go$/)) {
|
|
30204
30194
|
return path;
|
|
30205
30195
|
}
|
|
@@ -30227,8 +30217,7 @@ var TestParser = class {
|
|
|
30227
30217
|
];
|
|
30228
30218
|
for (let i = 0; i < lines.length; i++) {
|
|
30229
30219
|
const line = lines[i];
|
|
30230
|
-
if (!line)
|
|
30231
|
-
continue;
|
|
30220
|
+
if (!line) continue;
|
|
30232
30221
|
const lineNum = startLine + i;
|
|
30233
30222
|
for (const pattern of patterns) {
|
|
30234
30223
|
const match = line.match(pattern.regex);
|
|
@@ -30268,8 +30257,7 @@ var TestParser = class {
|
|
|
30268
30257
|
];
|
|
30269
30258
|
for (let i = 0; i < lines.length; i++) {
|
|
30270
30259
|
const line = lines[i];
|
|
30271
|
-
if (!line)
|
|
30272
|
-
continue;
|
|
30260
|
+
if (!line) continue;
|
|
30273
30261
|
const lineNum = startLine + i;
|
|
30274
30262
|
for (const pattern of patterns) {
|
|
30275
30263
|
const match = line.match(pattern.regex);
|
|
@@ -30305,8 +30293,7 @@ var TestParser = class {
|
|
|
30305
30293
|
];
|
|
30306
30294
|
for (let i = 0; i < lines.length; i++) {
|
|
30307
30295
|
const line = lines[i];
|
|
30308
|
-
if (!line)
|
|
30309
|
-
continue;
|
|
30296
|
+
if (!line) continue;
|
|
30310
30297
|
const lineNum = startLine + i;
|
|
30311
30298
|
for (const pattern of patterns) {
|
|
30312
30299
|
const match = line.match(pattern.regex);
|
|
@@ -30434,12 +30421,9 @@ var TestIndexer = class {
|
|
|
30434
30421
|
try {
|
|
30435
30422
|
const pkg = JSON.parse(readFileSync8(packageJsonPath, "utf-8"));
|
|
30436
30423
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
30437
|
-
if (allDeps["vitest"])
|
|
30438
|
-
|
|
30439
|
-
if (allDeps["
|
|
30440
|
-
return "jest";
|
|
30441
|
-
if (allDeps["mocha"])
|
|
30442
|
-
return "mocha";
|
|
30424
|
+
if (allDeps["vitest"]) return "vitest";
|
|
30425
|
+
if (allDeps["jest"]) return "jest";
|
|
30426
|
+
if (allDeps["mocha"]) return "mocha";
|
|
30443
30427
|
} catch {
|
|
30444
30428
|
}
|
|
30445
30429
|
}
|
|
@@ -30474,12 +30458,9 @@ var TestIndexer = class {
|
|
|
30474
30458
|
const hasJsTests = this.hasFilesMatching(["**/*.test.ts", "**/*.spec.ts"]);
|
|
30475
30459
|
const hasPyTests = this.hasFilesMatching(["**/test_*.py", "**/*_test.py"]);
|
|
30476
30460
|
const hasGoTests = this.hasFilesMatching(["**/*_test.go"]);
|
|
30477
|
-
if (hasGoTests)
|
|
30478
|
-
|
|
30479
|
-
if (
|
|
30480
|
-
return "pytest";
|
|
30481
|
-
if (hasJsTests)
|
|
30482
|
-
return "jest";
|
|
30461
|
+
if (hasGoTests) return "go";
|
|
30462
|
+
if (hasPyTests) return "pytest";
|
|
30463
|
+
if (hasJsTests) return "jest";
|
|
30483
30464
|
return "unknown";
|
|
30484
30465
|
}
|
|
30485
30466
|
hasFilesMatching(patterns) {
|
|
@@ -30490,8 +30471,7 @@ var TestIndexer = class {
|
|
|
30490
30471
|
ignore: IGNORE_PATTERNS,
|
|
30491
30472
|
nodir: true
|
|
30492
30473
|
});
|
|
30493
|
-
if (files.length > 0)
|
|
30494
|
-
return true;
|
|
30474
|
+
if (files.length > 0) return true;
|
|
30495
30475
|
} catch {
|
|
30496
30476
|
}
|
|
30497
30477
|
}
|
|
@@ -30522,8 +30502,7 @@ var TestIndexer = class {
|
|
|
30522
30502
|
}
|
|
30523
30503
|
parseTestFile(absolutePath, relativePath) {
|
|
30524
30504
|
const cached2 = this.testCache.get(relativePath);
|
|
30525
|
-
if (cached2)
|
|
30526
|
-
return cached2;
|
|
30505
|
+
if (cached2) return cached2;
|
|
30527
30506
|
try {
|
|
30528
30507
|
const content = readFileSync8(absolutePath, "utf-8");
|
|
30529
30508
|
const tests = this.parser.parseFile(content, relativePath, this.framework);
|
|
@@ -30896,8 +30875,7 @@ var ChangeValidator = class {
|
|
|
30896
30875
|
let match;
|
|
30897
30876
|
while ((match = pattern.exec(code)) !== null) {
|
|
30898
30877
|
const captured = match[1];
|
|
30899
|
-
if (!captured)
|
|
30900
|
-
continue;
|
|
30878
|
+
if (!captured) continue;
|
|
30901
30879
|
if (captured.includes(",")) {
|
|
30902
30880
|
const names = captured.split(",").map((s) => {
|
|
30903
30881
|
const parts = s.trim().split(/\s+as\s+/);
|
|
@@ -30915,12 +30893,9 @@ var ChangeValidator = class {
|
|
|
30915
30893
|
const hasAdditions = parsed.addedLines.length > 0 || parsed.modifiedFunctions.some((f) => f.changeType === "added");
|
|
30916
30894
|
const hasDeletions = parsed.removedLines.length > 0 || parsed.modifiedFunctions.some((f) => f.changeType === "removed");
|
|
30917
30895
|
const hasModifications = parsed.modifiedFunctions.some((f) => f.changeType === "modified" || f.changeType === "signature_changed");
|
|
30918
|
-
if (hasDeletions && !hasAdditions)
|
|
30919
|
-
|
|
30920
|
-
if (hasAdditions &&
|
|
30921
|
-
return "add";
|
|
30922
|
-
if (hasModifications || hasAdditions && hasDeletions)
|
|
30923
|
-
return "modify";
|
|
30896
|
+
if (hasDeletions && !hasAdditions) return "delete";
|
|
30897
|
+
if (hasAdditions && !hasDeletions && !hasModifications) return "add";
|
|
30898
|
+
if (hasModifications || hasAdditions && hasDeletions) return "modify";
|
|
30924
30899
|
return "refactor";
|
|
30925
30900
|
}
|
|
30926
30901
|
calculateRisk(parsed, affectedTests) {
|
|
@@ -30938,10 +30913,8 @@ var ChangeValidator = class {
|
|
|
30938
30913
|
if (affectedTests.length > 10) {
|
|
30939
30914
|
riskScore += 15;
|
|
30940
30915
|
}
|
|
30941
|
-
if (riskScore >= 50)
|
|
30942
|
-
|
|
30943
|
-
if (riskScore >= 25)
|
|
30944
|
-
return "medium";
|
|
30916
|
+
if (riskScore >= 50) return "high";
|
|
30917
|
+
if (riskScore >= 25) return "medium";
|
|
30945
30918
|
return "low";
|
|
30946
30919
|
}
|
|
30947
30920
|
generateReasoning(parsed, affectedTests, risk) {
|
|
@@ -31085,8 +31058,7 @@ var TestSuggester = class {
|
|
|
31085
31058
|
return updates;
|
|
31086
31059
|
}
|
|
31087
31060
|
generateAssertionUpdate(failure) {
|
|
31088
|
-
if (!failure.assertion)
|
|
31089
|
-
return null;
|
|
31061
|
+
if (!failure.assertion) return null;
|
|
31090
31062
|
const assertion = failure.assertion;
|
|
31091
31063
|
let after = assertion.code;
|
|
31092
31064
|
let reason = failure.reason;
|
|
@@ -31335,8 +31307,7 @@ func Test${functionName}(t *testing.T) {
|
|
|
31335
31307
|
}
|
|
31336
31308
|
parseParameters(signature) {
|
|
31337
31309
|
const match = signature.match(/\(([^)]*)\)/);
|
|
31338
|
-
if (!match || !match[1]?.trim())
|
|
31339
|
-
return [];
|
|
31310
|
+
if (!match || !match[1]?.trim()) return [];
|
|
31340
31311
|
return match[1].split(",").map((p) => p.trim()).filter(Boolean).map((p) => {
|
|
31341
31312
|
const parts = p.split(/[:\s]+/);
|
|
31342
31313
|
const firstPart = parts[0];
|
|
@@ -31345,48 +31316,31 @@ func Test${functionName}(t *testing.T) {
|
|
|
31345
31316
|
}
|
|
31346
31317
|
getExampleValue(param) {
|
|
31347
31318
|
const lower = param.toLowerCase();
|
|
31348
|
-
if (lower.includes("name") || lower.includes("str") || lower.includes("text"))
|
|
31349
|
-
|
|
31350
|
-
if (lower.includes("
|
|
31351
|
-
|
|
31352
|
-
if (lower.includes("
|
|
31353
|
-
|
|
31354
|
-
if (lower.includes("
|
|
31355
|
-
return "true";
|
|
31356
|
-
if (lower.includes("list") || lower.includes("array") || lower.includes("items"))
|
|
31357
|
-
return "[]";
|
|
31358
|
-
if (lower.includes("obj") || lower.includes("data") || lower.includes("options"))
|
|
31359
|
-
return "{}";
|
|
31360
|
-
if (lower.includes("fn") || lower.includes("callback") || lower.includes("handler"))
|
|
31361
|
-
return "() => {}";
|
|
31319
|
+
if (lower.includes("name") || lower.includes("str") || lower.includes("text")) return "'test'";
|
|
31320
|
+
if (lower.includes("id")) return "'123'";
|
|
31321
|
+
if (lower.includes("num") || lower.includes("count") || lower.includes("index")) return "1";
|
|
31322
|
+
if (lower.includes("flag") || lower.includes("is") || lower.includes("has")) return "true";
|
|
31323
|
+
if (lower.includes("list") || lower.includes("array") || lower.includes("items")) return "[]";
|
|
31324
|
+
if (lower.includes("obj") || lower.includes("data") || lower.includes("options")) return "{}";
|
|
31325
|
+
if (lower.includes("fn") || lower.includes("callback") || lower.includes("handler")) return "() => {}";
|
|
31362
31326
|
return "/* TODO */";
|
|
31363
31327
|
}
|
|
31364
31328
|
getPythonExampleValue(param) {
|
|
31365
31329
|
const lower = param.toLowerCase();
|
|
31366
|
-
if (lower.includes("name") || lower.includes("str") || lower.includes("text"))
|
|
31367
|
-
|
|
31368
|
-
if (lower.includes("
|
|
31369
|
-
|
|
31370
|
-
if (lower.includes("
|
|
31371
|
-
|
|
31372
|
-
if (lower.includes("flag") || lower.includes("is") || lower.includes("has"))
|
|
31373
|
-
return "True";
|
|
31374
|
-
if (lower.includes("list") || lower.includes("array") || lower.includes("items"))
|
|
31375
|
-
return "[]";
|
|
31376
|
-
if (lower.includes("obj") || lower.includes("data") || lower.includes("dict"))
|
|
31377
|
-
return "{}";
|
|
31330
|
+
if (lower.includes("name") || lower.includes("str") || lower.includes("text")) return '"test"';
|
|
31331
|
+
if (lower.includes("id")) return '"123"';
|
|
31332
|
+
if (lower.includes("num") || lower.includes("count") || lower.includes("index")) return "1";
|
|
31333
|
+
if (lower.includes("flag") || lower.includes("is") || lower.includes("has")) return "True";
|
|
31334
|
+
if (lower.includes("list") || lower.includes("array") || lower.includes("items")) return "[]";
|
|
31335
|
+
if (lower.includes("obj") || lower.includes("data") || lower.includes("dict")) return "{}";
|
|
31378
31336
|
return "None # TODO";
|
|
31379
31337
|
}
|
|
31380
31338
|
getGoExampleValue(param) {
|
|
31381
31339
|
const lower = param.toLowerCase();
|
|
31382
|
-
if (lower.includes("name") || lower.includes("str") || lower.includes("text"))
|
|
31383
|
-
|
|
31384
|
-
if (lower.includes("
|
|
31385
|
-
|
|
31386
|
-
if (lower.includes("num") || lower.includes("count") || lower.includes("index"))
|
|
31387
|
-
return "1";
|
|
31388
|
-
if (lower.includes("flag") || lower.includes("is") || lower.includes("has"))
|
|
31389
|
-
return "true";
|
|
31340
|
+
if (lower.includes("name") || lower.includes("str") || lower.includes("text")) return '"test"';
|
|
31341
|
+
if (lower.includes("id")) return '"123"';
|
|
31342
|
+
if (lower.includes("num") || lower.includes("count") || lower.includes("index")) return "1";
|
|
31343
|
+
if (lower.includes("flag") || lower.includes("is") || lower.includes("has")) return "true";
|
|
31390
31344
|
return "nil /* TODO */";
|
|
31391
31345
|
}
|
|
31392
31346
|
formatTestUpdates(updates) {
|
|
@@ -31972,24 +31926,15 @@ function formatTimeAgo(date4) {
|
|
|
31972
31926
|
const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
|
|
31973
31927
|
const diffWeeks = Math.floor(diffDays / 7);
|
|
31974
31928
|
const diffMonths = Math.floor(diffDays / 30);
|
|
31975
|
-
if (diffMins < 1)
|
|
31976
|
-
|
|
31977
|
-
if (
|
|
31978
|
-
|
|
31979
|
-
if (
|
|
31980
|
-
|
|
31981
|
-
if (
|
|
31982
|
-
|
|
31983
|
-
if (
|
|
31984
|
-
return `${diffDays} days ago`;
|
|
31985
|
-
if (diffWeeks === 1)
|
|
31986
|
-
return "1 week ago";
|
|
31987
|
-
if (diffWeeks < 4)
|
|
31988
|
-
return `${diffWeeks} weeks ago`;
|
|
31989
|
-
if (diffMonths === 1)
|
|
31990
|
-
return "1 month ago";
|
|
31991
|
-
if (diffMonths < 12)
|
|
31992
|
-
return `${diffMonths} months ago`;
|
|
31929
|
+
if (diffMins < 1) return "just now";
|
|
31930
|
+
if (diffMins < 60) return `${diffMins} minute${diffMins > 1 ? "s" : ""} ago`;
|
|
31931
|
+
if (diffHours < 24) return `${diffHours} hour${diffHours > 1 ? "s" : ""} ago`;
|
|
31932
|
+
if (diffDays === 1) return "yesterday";
|
|
31933
|
+
if (diffDays < 7) return `${diffDays} days ago`;
|
|
31934
|
+
if (diffWeeks === 1) return "1 week ago";
|
|
31935
|
+
if (diffWeeks < 4) return `${diffWeeks} weeks ago`;
|
|
31936
|
+
if (diffMonths === 1) return "1 month ago";
|
|
31937
|
+
if (diffMonths < 12) return `${diffMonths} months ago`;
|
|
31993
31938
|
return date4.toLocaleDateString();
|
|
31994
31939
|
}
|
|
31995
31940
|
function formatTimeAgoWithContext(date4, action, file2) {
|
|
@@ -32077,8 +32022,7 @@ var DejaVuDetector = class {
|
|
|
32077
32022
|
const embedding = await this.embeddingGenerator.embed(query);
|
|
32078
32023
|
const searchResults = this.tier2.search(embedding, 10);
|
|
32079
32024
|
for (const result of searchResults) {
|
|
32080
|
-
if (result.similarity < this.SIMILARITY_THRESHOLD)
|
|
32081
|
-
continue;
|
|
32025
|
+
if (result.similarity < this.SIMILARITY_THRESHOLD) continue;
|
|
32082
32026
|
const usageStmt = this.db.prepare(`
|
|
32083
32027
|
SELECT ue.query, ue.timestamp, qp.avg_usefulness
|
|
32084
32028
|
FROM usage_events ue
|
|
@@ -32129,8 +32073,7 @@ var DejaVuDetector = class {
|
|
|
32129
32073
|
`);
|
|
32130
32074
|
const rows = stmt.all(this.MAX_AGE_DAYS);
|
|
32131
32075
|
for (const row of rows) {
|
|
32132
|
-
if (!row.query)
|
|
32133
|
-
continue;
|
|
32076
|
+
if (!row.query) continue;
|
|
32134
32077
|
const similarity = this.calculateTextSimilarity(query, row.query);
|
|
32135
32078
|
if (similarity >= this.SIMILARITY_THRESHOLD * 0.8) {
|
|
32136
32079
|
const resultFiles = row.result_files ? this.parseJsonArray(row.result_files) : [];
|
|
@@ -32258,8 +32201,7 @@ var DejaVuDetector = class {
|
|
|
32258
32201
|
return Math.exp(-diffDays / (this.MAX_AGE_DAYS / 3));
|
|
32259
32202
|
}
|
|
32260
32203
|
parseJsonArray(json2) {
|
|
32261
|
-
if (!json2)
|
|
32262
|
-
return [];
|
|
32204
|
+
if (!json2) return [];
|
|
32263
32205
|
try {
|
|
32264
32206
|
const parsed = JSON.parse(json2);
|
|
32265
32207
|
return Array.isArray(parsed) ? parsed : [];
|
|
@@ -32706,24 +32648,20 @@ var CodeVerifier = class {
|
|
|
32706
32648
|
let match;
|
|
32707
32649
|
const esPattern = new RegExp(IMPORT_PATTERNS.esImport.source, "g");
|
|
32708
32650
|
while ((match = esPattern.exec(code)) !== null) {
|
|
32709
|
-
if (match[1])
|
|
32710
|
-
imports.add(match[1]);
|
|
32651
|
+
if (match[1]) imports.add(match[1]);
|
|
32711
32652
|
}
|
|
32712
32653
|
const dynamicPattern = new RegExp(IMPORT_PATTERNS.dynamicImport.source, "g");
|
|
32713
32654
|
while ((match = dynamicPattern.exec(code)) !== null) {
|
|
32714
|
-
if (match[1])
|
|
32715
|
-
imports.add(match[1]);
|
|
32655
|
+
if (match[1]) imports.add(match[1]);
|
|
32716
32656
|
}
|
|
32717
32657
|
const requirePattern = new RegExp(IMPORT_PATTERNS.require.source, "g");
|
|
32718
32658
|
while ((match = requirePattern.exec(code)) !== null) {
|
|
32719
|
-
if (match[1])
|
|
32720
|
-
imports.add(match[1]);
|
|
32659
|
+
if (match[1]) imports.add(match[1]);
|
|
32721
32660
|
}
|
|
32722
32661
|
return imports;
|
|
32723
32662
|
}
|
|
32724
32663
|
verifyRelativeImport(importPath, file2, issues) {
|
|
32725
|
-
if (!file2)
|
|
32726
|
-
return;
|
|
32664
|
+
if (!file2) return;
|
|
32727
32665
|
const baseDir = dirname7(join13(this.projectPath, file2));
|
|
32728
32666
|
const possibleExtensions = [".ts", ".tsx", ".js", ".jsx", ".json", ""];
|
|
32729
32667
|
const possibleIndexes = ["index.ts", "index.tsx", "index.js", "index.jsx"];
|
|
@@ -32810,8 +32748,7 @@ var CodeVerifier = class {
|
|
|
32810
32748
|
}
|
|
32811
32749
|
getPackageDependencies() {
|
|
32812
32750
|
const deps = /* @__PURE__ */ new Set();
|
|
32813
|
-
if (!this.packageJson)
|
|
32814
|
-
return deps;
|
|
32751
|
+
if (!this.packageJson) return deps;
|
|
32815
32752
|
const allDeps = {
|
|
32816
32753
|
...this.packageJson.dependencies || {},
|
|
32817
32754
|
...this.packageJson.devDependencies || {},
|
|
@@ -32865,10 +32802,8 @@ var CodeVerifier = class {
|
|
|
32865
32802
|
if (highSeverityCount >= 2) {
|
|
32866
32803
|
return "fail";
|
|
32867
32804
|
}
|
|
32868
|
-
if (score >= 70)
|
|
32869
|
-
|
|
32870
|
-
if (score >= 40)
|
|
32871
|
-
return "warning";
|
|
32805
|
+
if (score >= 70) return "pass";
|
|
32806
|
+
if (score >= 40) return "warning";
|
|
32872
32807
|
return "fail";
|
|
32873
32808
|
}
|
|
32874
32809
|
buildSummary(results, verdict) {
|
|
@@ -33032,8 +32967,7 @@ var MemoryLayerEngine = class {
|
|
|
33032
32967
|
});
|
|
33033
32968
|
}
|
|
33034
32969
|
async initialize() {
|
|
33035
|
-
if (this.initialized)
|
|
33036
|
-
return;
|
|
32970
|
+
if (this.initialized) return;
|
|
33037
32971
|
console.error(`Initializing MemoryLayer for: ${this.config.projectPath}`);
|
|
33038
32972
|
try {
|
|
33039
32973
|
this.initializationStatus = "indexing";
|
|
@@ -33315,8 +33249,7 @@ ${decision.description}`;
|
|
|
33315
33249
|
// Phase 3: Get file summary (compressed representation)
|
|
33316
33250
|
getFileSummary(filePath) {
|
|
33317
33251
|
const file2 = this.tier2.getFile(filePath);
|
|
33318
|
-
if (!file2)
|
|
33319
|
-
return null;
|
|
33252
|
+
if (!file2) return null;
|
|
33320
33253
|
const cached2 = this.summarizer.getSummary(file2.id);
|
|
33321
33254
|
if (cached2 && !this.summarizer.needsRegeneration(file2.id, file2.lastModified)) {
|
|
33322
33255
|
return cached2.summary;
|
|
@@ -33989,8 +33922,7 @@ function isErrorMessage(str) {
|
|
|
33989
33922
|
return errorPatterns.some((pattern) => pattern.test(str));
|
|
33990
33923
|
}
|
|
33991
33924
|
function detectQueryAction(input) {
|
|
33992
|
-
if (input.action)
|
|
33993
|
-
return input.action;
|
|
33925
|
+
if (input.action) return input.action;
|
|
33994
33926
|
if (input.code && input.code.length > 20) {
|
|
33995
33927
|
if (containsCode(input.code)) {
|
|
33996
33928
|
return "confidence";
|
|
@@ -34011,10 +33943,8 @@ function detectQueryAction(input) {
|
|
|
34011
33943
|
return "context";
|
|
34012
33944
|
}
|
|
34013
33945
|
function detectRecordType(input) {
|
|
34014
|
-
if (input.type)
|
|
34015
|
-
|
|
34016
|
-
if (input.action)
|
|
34017
|
-
return input.action;
|
|
33946
|
+
if (input.type) return input.type;
|
|
33947
|
+
if (input.action) return input.action;
|
|
34018
33948
|
if (input.pattern_id && input.code) {
|
|
34019
33949
|
return "example";
|
|
34020
33950
|
}
|
|
@@ -34081,8 +34011,7 @@ function validateRecordInput(input) {
|
|
|
34081
34011
|
return { valid: true, type };
|
|
34082
34012
|
}
|
|
34083
34013
|
function detectReviewAction(input) {
|
|
34084
|
-
if (input.action)
|
|
34085
|
-
return input.action;
|
|
34014
|
+
if (input.action) return input.action;
|
|
34086
34015
|
if (input.error && isErrorMessage(input.error)) {
|
|
34087
34016
|
return "bugs";
|
|
34088
34017
|
}
|
|
@@ -34119,8 +34048,7 @@ function getReviewChecks(input) {
|
|
|
34119
34048
|
};
|
|
34120
34049
|
}
|
|
34121
34050
|
function detectStatusAction(input) {
|
|
34122
|
-
if (input.action)
|
|
34123
|
-
return input.action;
|
|
34051
|
+
if (input.action) return input.action;
|
|
34124
34052
|
if (input.since) {
|
|
34125
34053
|
if (input.author || input.file) {
|
|
34126
34054
|
return "changed";
|
|
@@ -34214,10 +34142,8 @@ function calculateRiskScore(patternResult, conflicts, testResult, confidence) {
|
|
|
34214
34142
|
return Math.min(100, riskScore);
|
|
34215
34143
|
}
|
|
34216
34144
|
function getVerdict(riskScore) {
|
|
34217
|
-
if (riskScore >= 70)
|
|
34218
|
-
|
|
34219
|
-
if (riskScore >= 30)
|
|
34220
|
-
return "warning";
|
|
34145
|
+
if (riskScore >= 70) return "reject";
|
|
34146
|
+
if (riskScore >= 30) return "warning";
|
|
34221
34147
|
return "approve";
|
|
34222
34148
|
}
|
|
34223
34149
|
function aggregateReviewResults(patternResult, conflicts, confidence, existingAlternatives, testResult, sourcesUsed) {
|
|
@@ -35593,12 +35519,9 @@ async function handleMemoryVerify(engine, input) {
|
|
|
35593
35519
|
if (runAll || checks.includes("imports") || checks.includes("security") || checks.includes("dependencies")) {
|
|
35594
35520
|
sourcesUsed.push("code_verifier");
|
|
35595
35521
|
const verifierChecks = [];
|
|
35596
|
-
if (runAll || checks.includes("imports"))
|
|
35597
|
-
|
|
35598
|
-
if (runAll || checks.includes("
|
|
35599
|
-
verifierChecks.push("security");
|
|
35600
|
-
if (runAll || checks.includes("dependencies"))
|
|
35601
|
-
verifierChecks.push("dependencies");
|
|
35522
|
+
if (runAll || checks.includes("imports")) verifierChecks.push("imports");
|
|
35523
|
+
if (runAll || checks.includes("security")) verifierChecks.push("security");
|
|
35524
|
+
if (runAll || checks.includes("dependencies")) verifierChecks.push("dependencies");
|
|
35602
35525
|
const verification = await engine.verifyCode(input.code, input.file, verifierChecks);
|
|
35603
35526
|
if (verification.imports) {
|
|
35604
35527
|
response.imports = {
|
|
@@ -35710,10 +35633,8 @@ function calculateVerdict(response) {
|
|
|
35710
35633
|
if (hallucinatedImports >= 2) {
|
|
35711
35634
|
return "fail";
|
|
35712
35635
|
}
|
|
35713
|
-
if (response.score >= 70)
|
|
35714
|
-
|
|
35715
|
-
if (response.score >= 40)
|
|
35716
|
-
return "warning";
|
|
35636
|
+
if (response.score >= 70) return "pass";
|
|
35637
|
+
if (response.score >= 40) return "warning";
|
|
35717
35638
|
return "fail";
|
|
35718
35639
|
}
|
|
35719
35640
|
function buildSummary(response) {
|
|
@@ -35740,12 +35661,9 @@ function buildSummary(response) {
|
|
|
35740
35661
|
const high = response.security.issues.filter((i) => i.severity === "high").length;
|
|
35741
35662
|
const medium = response.security.issues.filter((i) => i.severity === "medium").length;
|
|
35742
35663
|
const secParts = [];
|
|
35743
|
-
if (critical > 0)
|
|
35744
|
-
|
|
35745
|
-
if (
|
|
35746
|
-
secParts.push(`${high} high`);
|
|
35747
|
-
if (medium > 0)
|
|
35748
|
-
secParts.push(`${medium} medium`);
|
|
35664
|
+
if (critical > 0) secParts.push(`${critical} critical`);
|
|
35665
|
+
if (high > 0) secParts.push(`${high} high`);
|
|
35666
|
+
if (medium > 0) secParts.push(`${medium} medium`);
|
|
35749
35667
|
parts.push(`Security: ${secParts.join(", ")}`);
|
|
35750
35668
|
}
|
|
35751
35669
|
}
|
|
@@ -36337,6 +36255,7 @@ async function handleToolCall(engine, toolName, args) {
|
|
|
36337
36255
|
query
|
|
36338
36256
|
};
|
|
36339
36257
|
}
|
|
36258
|
+
// Phase 4: Multi-project tools
|
|
36340
36259
|
case "list_projects": {
|
|
36341
36260
|
const projects = engine.listProjects();
|
|
36342
36261
|
const activeProject = engine.getActiveProject();
|
|
@@ -36459,6 +36378,7 @@ async function handleToolCall(engine, toolName, args) {
|
|
|
36459
36378
|
}))
|
|
36460
36379
|
};
|
|
36461
36380
|
}
|
|
36381
|
+
// Phase 5: Active Feature Context tools
|
|
36462
36382
|
case "get_active_context": {
|
|
36463
36383
|
const hotContext = engine.getHotContext();
|
|
36464
36384
|
const summary = engine.getActiveContextSummary();
|
|
@@ -36544,6 +36464,7 @@ async function handleToolCall(engine, toolName, args) {
|
|
|
36544
36464
|
} : null
|
|
36545
36465
|
};
|
|
36546
36466
|
}
|
|
36467
|
+
// Phase 6: Living Documentation tools
|
|
36547
36468
|
case "generate_docs": {
|
|
36548
36469
|
const path = args.path;
|
|
36549
36470
|
const type = args.type || (path ? "component" : "architecture");
|
|
@@ -36765,6 +36686,7 @@ async function handleToolCall(engine, toolName, args) {
|
|
|
36765
36686
|
message: items.length === 0 ? "All exported code is documented!" : `Found ${items.length} undocumented items across ${byFile.size} files`
|
|
36766
36687
|
};
|
|
36767
36688
|
}
|
|
36689
|
+
// Phase 7: Context Rot Prevention tools
|
|
36768
36690
|
case "get_context_health": {
|
|
36769
36691
|
const includeHistory = args.include_history;
|
|
36770
36692
|
const health = engine.getContextHealth();
|
|
@@ -36857,6 +36779,7 @@ async function handleToolCall(engine, toolName, args) {
|
|
|
36857
36779
|
message: items.length === 0 ? "No critical context marked. Consider marking important decisions and requirements." : `${items.length} critical items will be preserved during compaction`
|
|
36858
36780
|
};
|
|
36859
36781
|
}
|
|
36782
|
+
// Phase 8: Confidence Scoring tools
|
|
36860
36783
|
case "get_confidence": {
|
|
36861
36784
|
const code = args.code;
|
|
36862
36785
|
const context = args.context;
|
|
@@ -36966,6 +36889,7 @@ async function handleToolCall(engine, toolName, args) {
|
|
|
36966
36889
|
message: result.hasConflicts ? `Found ${result.conflicts.length} conflict(s) with past decisions` : "No conflicts with past decisions"
|
|
36967
36890
|
};
|
|
36968
36891
|
}
|
|
36892
|
+
// Phase 9: Change Intelligence tools
|
|
36969
36893
|
case "what_changed": {
|
|
36970
36894
|
const since = args.since;
|
|
36971
36895
|
const file2 = args.file;
|
|
@@ -37067,6 +36991,7 @@ async function handleToolCall(engine, toolName, args) {
|
|
|
37067
36991
|
message: suggestions.length === 0 ? "No fix suggestions available" : `Found ${suggestions.length} fix suggestion(s)`
|
|
37068
36992
|
};
|
|
37069
36993
|
}
|
|
36994
|
+
// Phase 10: Architecture Enforcement tools
|
|
37070
36995
|
case "validate_pattern": {
|
|
37071
36996
|
const code = args.code;
|
|
37072
36997
|
const type = args.type;
|
|
@@ -37216,6 +37141,7 @@ async function handleToolCall(engine, toolName, args) {
|
|
|
37216
37141
|
message: `${stats.patterns.total} patterns learned, ${stats.functions.total} functions indexed`
|
|
37217
37142
|
};
|
|
37218
37143
|
}
|
|
37144
|
+
// Phase 11: Test-Aware Suggestions tools
|
|
37219
37145
|
case "get_related_tests": {
|
|
37220
37146
|
const file2 = args.file;
|
|
37221
37147
|
const fn = args.function;
|
|
@@ -37668,7 +37594,8 @@ function parseArgs(args) {
|
|
|
37668
37594
|
|
|
37669
37595
|
// src/cli/commands.ts
|
|
37670
37596
|
import { join as join16 } from "path";
|
|
37671
|
-
import { existsSync as existsSync14 } from "fs";
|
|
37597
|
+
import { existsSync as existsSync14, readFileSync as readFileSync11, writeFileSync as writeFileSync5, mkdirSync as mkdirSync7 } from "fs";
|
|
37598
|
+
import { homedir as homedir2 } from "os";
|
|
37672
37599
|
var projectManager = new ProjectManager();
|
|
37673
37600
|
function listProjects() {
|
|
37674
37601
|
const projects = projectManager.listProjects();
|
|
@@ -37840,6 +37767,94 @@ function showProject(projectId) {
|
|
|
37840
37767
|
data: project
|
|
37841
37768
|
};
|
|
37842
37769
|
}
|
|
37770
|
+
function configureMCPClient(clientName, configPath, serverName, projectPath) {
|
|
37771
|
+
let config2 = { mcpServers: {} };
|
|
37772
|
+
try {
|
|
37773
|
+
if (existsSync14(configPath)) {
|
|
37774
|
+
const content = readFileSync11(configPath, "utf-8");
|
|
37775
|
+
config2 = JSON.parse(content);
|
|
37776
|
+
} else {
|
|
37777
|
+
const sep = process.platform === "win32" ? "\\" : "/";
|
|
37778
|
+
const configDir = configPath.substring(0, configPath.lastIndexOf(sep));
|
|
37779
|
+
mkdirSync7(configDir, { recursive: true });
|
|
37780
|
+
}
|
|
37781
|
+
} catch {
|
|
37782
|
+
}
|
|
37783
|
+
if (!config2.mcpServers) {
|
|
37784
|
+
config2.mcpServers = {};
|
|
37785
|
+
}
|
|
37786
|
+
config2.mcpServers[serverName] = {
|
|
37787
|
+
command: "npx",
|
|
37788
|
+
args: ["-y", "neuronlayer", "--project", projectPath]
|
|
37789
|
+
};
|
|
37790
|
+
try {
|
|
37791
|
+
writeFileSync5(configPath, JSON.stringify(config2, null, 2));
|
|
37792
|
+
return { success: true, message: `${clientName}: ${configPath}` };
|
|
37793
|
+
} catch (err) {
|
|
37794
|
+
return { success: false, message: `${clientName}: Failed - ${err instanceof Error ? err.message : String(err)}` };
|
|
37795
|
+
}
|
|
37796
|
+
}
|
|
37797
|
+
function initProject(projectPath) {
|
|
37798
|
+
const targetPath = projectPath || process.cwd();
|
|
37799
|
+
const addResult = addProject(targetPath);
|
|
37800
|
+
if (!addResult.success) {
|
|
37801
|
+
return addResult;
|
|
37802
|
+
}
|
|
37803
|
+
const projectInfo = addResult.data;
|
|
37804
|
+
const serverName = `neuronlayer-${projectInfo.name.toLowerCase().replace(/[^a-z0-9]/g, "-")}`;
|
|
37805
|
+
const platform = process.platform;
|
|
37806
|
+
const configuredClients = [];
|
|
37807
|
+
const failedClients = [];
|
|
37808
|
+
let claudeConfigPath;
|
|
37809
|
+
if (platform === "win32") {
|
|
37810
|
+
claudeConfigPath = join16(homedir2(), "AppData", "Roaming", "Claude", "claude_desktop_config.json");
|
|
37811
|
+
} else if (platform === "darwin") {
|
|
37812
|
+
claudeConfigPath = join16(homedir2(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
37813
|
+
} else {
|
|
37814
|
+
claudeConfigPath = join16(homedir2(), ".config", "claude", "claude_desktop_config.json");
|
|
37815
|
+
}
|
|
37816
|
+
const claudeResult = configureMCPClient("Claude Desktop", claudeConfigPath, serverName, targetPath);
|
|
37817
|
+
if (claudeResult.success) {
|
|
37818
|
+
configuredClients.push(claudeResult.message);
|
|
37819
|
+
} else {
|
|
37820
|
+
failedClients.push(claudeResult.message);
|
|
37821
|
+
}
|
|
37822
|
+
const openCodeConfigPath = join16(homedir2(), ".opencode", "config.json");
|
|
37823
|
+
const openCodeResult = configureMCPClient("OpenCode", openCodeConfigPath, serverName, targetPath);
|
|
37824
|
+
if (openCodeResult.success) {
|
|
37825
|
+
configuredClients.push(openCodeResult.message);
|
|
37826
|
+
} else {
|
|
37827
|
+
failedClients.push(openCodeResult.message);
|
|
37828
|
+
}
|
|
37829
|
+
const claudeCodeConfigPath = join16(homedir2(), ".claude.json");
|
|
37830
|
+
const claudeCodeResult = configureMCPClient("Claude Code", claudeCodeConfigPath, serverName, targetPath);
|
|
37831
|
+
if (claudeCodeResult.success) {
|
|
37832
|
+
configuredClients.push(claudeCodeResult.message);
|
|
37833
|
+
}
|
|
37834
|
+
let message = `
|
|
37835
|
+
NeuronLayer initialized!
|
|
37836
|
+
|
|
37837
|
+
Project: ${projectInfo.name}
|
|
37838
|
+
Path: ${targetPath}
|
|
37839
|
+
Data: ${projectInfo.dataDir}
|
|
37840
|
+
|
|
37841
|
+
Configured MCP Clients:
|
|
37842
|
+
${configuredClients.map((c) => " \u2713 " + c).join("\n")}
|
|
37843
|
+
`;
|
|
37844
|
+
if (failedClients.length > 0) {
|
|
37845
|
+
message += `
|
|
37846
|
+
Failed:
|
|
37847
|
+
${failedClients.map((c) => " \u2717 " + c).join("\n")}`;
|
|
37848
|
+
}
|
|
37849
|
+
message += `
|
|
37850
|
+
|
|
37851
|
+
Restart your AI tools to activate.`;
|
|
37852
|
+
return {
|
|
37853
|
+
success: true,
|
|
37854
|
+
message: message.trim(),
|
|
37855
|
+
data: { projectInfo, serverName, configuredClients }
|
|
37856
|
+
};
|
|
37857
|
+
}
|
|
37843
37858
|
function printHelp() {
|
|
37844
37859
|
console.log(`
|
|
37845
37860
|
MemoryLayer CLI - Persistent Memory for AI Coding Assistants
|
|
@@ -37848,6 +37863,7 @@ USAGE:
|
|
|
37848
37863
|
memorylayer [command] [options]
|
|
37849
37864
|
|
|
37850
37865
|
COMMANDS:
|
|
37866
|
+
init [path] Initialize project + auto-configure Claude Desktop
|
|
37851
37867
|
(no command) Start MCP server for Claude Desktop
|
|
37852
37868
|
projects list List all registered projects
|
|
37853
37869
|
projects add <path> Add a project to the registry
|
|
@@ -37864,8 +37880,12 @@ OPTIONS:
|
|
|
37864
37880
|
--format <type> ADR format: madr, nygard, simple
|
|
37865
37881
|
|
|
37866
37882
|
EXAMPLES:
|
|
37883
|
+
# Quick setup (auto-configures Claude Desktop)
|
|
37884
|
+
cd /path/to/project
|
|
37885
|
+
neuronlayer init
|
|
37886
|
+
|
|
37867
37887
|
# Start MCP server
|
|
37868
|
-
|
|
37888
|
+
neuronlayer --project /path/to/project
|
|
37869
37889
|
|
|
37870
37890
|
# List all projects
|
|
37871
37891
|
memorylayer projects list
|
|
@@ -37882,7 +37902,7 @@ EXAMPLES:
|
|
|
37882
37902
|
# Discover projects
|
|
37883
37903
|
memorylayer projects discover
|
|
37884
37904
|
|
|
37885
|
-
For more information, visit: https://github.com/
|
|
37905
|
+
For more information, visit: https://github.com/abhisavakar/neuronlayer
|
|
37886
37906
|
`);
|
|
37887
37907
|
}
|
|
37888
37908
|
function executeCLI(args) {
|
|
@@ -37894,6 +37914,13 @@ function executeCLI(args) {
|
|
|
37894
37914
|
case "-h":
|
|
37895
37915
|
printHelp();
|
|
37896
37916
|
break;
|
|
37917
|
+
case "init": {
|
|
37918
|
+
const path = args[1];
|
|
37919
|
+
const result = initProject(path);
|
|
37920
|
+
console.log(result.message);
|
|
37921
|
+
if (!result.success) process.exit(1);
|
|
37922
|
+
break;
|
|
37923
|
+
}
|
|
37897
37924
|
case "projects": {
|
|
37898
37925
|
switch (subcommand) {
|
|
37899
37926
|
case "list":
|
|
@@ -37908,8 +37935,7 @@ function executeCLI(args) {
|
|
|
37908
37935
|
}
|
|
37909
37936
|
const result = addProject(path);
|
|
37910
37937
|
console.log(result.message);
|
|
37911
|
-
if (!result.success)
|
|
37912
|
-
process.exit(1);
|
|
37938
|
+
if (!result.success) process.exit(1);
|
|
37913
37939
|
break;
|
|
37914
37940
|
}
|
|
37915
37941
|
case "remove": {
|
|
@@ -37921,8 +37947,7 @@ function executeCLI(args) {
|
|
|
37921
37947
|
}
|
|
37922
37948
|
const result = removeProject(id);
|
|
37923
37949
|
console.log(result.message);
|
|
37924
|
-
if (!result.success)
|
|
37925
|
-
process.exit(1);
|
|
37950
|
+
if (!result.success) process.exit(1);
|
|
37926
37951
|
break;
|
|
37927
37952
|
}
|
|
37928
37953
|
case "switch": {
|
|
@@ -37934,16 +37959,14 @@ function executeCLI(args) {
|
|
|
37934
37959
|
}
|
|
37935
37960
|
const result = switchProject(id);
|
|
37936
37961
|
console.log(result.message);
|
|
37937
|
-
if (!result.success)
|
|
37938
|
-
process.exit(1);
|
|
37962
|
+
if (!result.success) process.exit(1);
|
|
37939
37963
|
break;
|
|
37940
37964
|
}
|
|
37941
37965
|
case "show": {
|
|
37942
37966
|
const id = args[2];
|
|
37943
37967
|
const result = showProject(id);
|
|
37944
37968
|
console.log(result.message);
|
|
37945
|
-
if (!result.success)
|
|
37946
|
-
process.exit(1);
|
|
37969
|
+
if (!result.success) process.exit(1);
|
|
37947
37970
|
break;
|
|
37948
37971
|
}
|
|
37949
37972
|
case "discover":
|
|
@@ -37972,8 +37995,7 @@ function executeCLI(args) {
|
|
|
37972
37995
|
}
|
|
37973
37996
|
const result = exportDecisions(void 0, { outputDir, format });
|
|
37974
37997
|
console.log(result.message);
|
|
37975
|
-
if (!result.success)
|
|
37976
|
-
process.exit(1);
|
|
37998
|
+
if (!result.success) process.exit(1);
|
|
37977
37999
|
break;
|
|
37978
38000
|
}
|
|
37979
38001
|
default:
|
|
@@ -37986,7 +38008,7 @@ function executeCLI(args) {
|
|
|
37986
38008
|
async function main() {
|
|
37987
38009
|
const args = process.argv.slice(2);
|
|
37988
38010
|
const firstArg = args[0];
|
|
37989
|
-
const cliCommands = ["projects", "export", "help", "--help", "-h"];
|
|
38011
|
+
const cliCommands = ["init", "projects", "export", "help", "--help", "-h"];
|
|
37990
38012
|
if (firstArg && cliCommands.includes(firstArg)) {
|
|
37991
38013
|
executeCLI(args);
|
|
37992
38014
|
return;
|