@hanhnd/agent-kit 1.0.31 → 1.0.33
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/dist/cli/commands/cli-digest-pending.test.js +111 -0
- package/dist/cli/commands/cli-memory.test.js +34 -0
- package/dist/cli/commands/memory.d.ts +1 -0
- package/dist/cli/commands/memory.js +90 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +9 -0
- package/dist/cli/utils/args.d.ts +8 -0
- package/dist/cli/utils/args.js +31 -0
- package/dist/cli.js +16489 -0
- package/dist/{tools/config.d.ts → core/config/index.d.ts} +4 -9
- package/dist/{tools/config.js → core/config/index.js} +20 -23
- package/dist/core/handoffs/index.d.ts +16 -0
- package/dist/{tools/handoffs.js → core/handoffs/index.js} +4 -5
- package/dist/{tools/security.d.ts → core/security/index.d.ts} +0 -19
- package/dist/{tools/security.js → core/security/index.js} +3 -80
- package/dist/entrypoints/cli.d.ts +2 -0
- package/dist/entrypoints/cli.js +11 -0
- package/dist/entrypoints/server.js +37 -0
- package/dist/{tools → mcp}/agent.js +3 -14
- package/dist/{tools → mcp}/core.d.ts +1 -1
- package/dist/{tools → mcp}/core.js +3 -5
- package/dist/{tools → mcp}/integration.js +5 -11
- package/dist/mcp/memory.d.ts +15 -0
- package/dist/{tools → mcp}/memory.js +40 -12
- package/dist/{kit-server.js → server.js} +720 -224
- package/dist/services/digest/background.d.ts +11 -0
- package/dist/services/digest/background.js +258 -0
- package/dist/services/digest/constants.d.ts +17 -0
- package/dist/services/digest/constants.js +19 -0
- package/dist/services/digest/digest-background.test.js +206 -0
- package/dist/services/digest/digest-init.test.js +33 -0
- package/dist/services/digest/digest-llama-local.test.js +21 -0
- package/dist/services/digest/digest-pending.test.d.ts +1 -0
- package/dist/services/digest/digest-pending.test.js +192 -0
- package/dist/services/digest/digest-processor.test.d.ts +1 -0
- package/dist/services/digest/digest-processor.test.js +32 -0
- package/dist/services/digest/files.d.ts +6 -0
- package/dist/services/digest/files.js +45 -0
- package/dist/services/digest/model-registry.d.ts +2 -0
- package/dist/services/digest/model-registry.js +49 -0
- package/dist/services/digest/processor.d.ts +13 -0
- package/dist/services/digest/processor.js +188 -0
- package/dist/services/digest/providers/llama-local.d.ts +2 -0
- package/dist/services/digest/providers/llama-local.js +135 -0
- package/dist/services/digest/types.d.ts +117 -0
- package/dist/services/digest/types.js +6 -0
- package/dist/services/digest/worker.d.ts +2 -0
- package/dist/services/digest/worker.js +51 -0
- package/dist/{utils → services/integration}/credentials.js +1 -1
- package/dist/{utils/parser.js → services/integration/parser/adf.js} +3 -6
- package/dist/{memory → services/memory}/chunker.d.ts +0 -2
- package/dist/{memory → services/memory}/chunker.js +5 -7
- package/dist/services/memory/chunker.test.d.ts +1 -0
- package/dist/{memory/__tests__ → services/memory}/chunker.test.js +1 -34
- package/dist/services/memory/constants.d.ts +5 -0
- package/dist/services/memory/constants.js +13 -0
- package/dist/{memory → services/memory}/embedder.d.ts +3 -2
- package/dist/{memory → services/memory}/embedder.js +15 -6
- package/dist/services/memory/embedder.test.d.ts +1 -0
- package/dist/services/memory/embedder.test.js +13 -0
- package/dist/{memory → services/memory}/index.d.ts +1 -1
- package/dist/{memory → services/memory}/index.js +1 -1
- package/dist/{memory → services/memory}/indexer.d.ts +6 -2
- package/dist/{memory → services/memory}/indexer.js +15 -37
- package/dist/services/memory/indexer.test.d.ts +1 -0
- package/dist/{memory/__tests__ → services/memory}/indexer.test.js +11 -15
- package/dist/services/memory/memory.test.d.ts +1 -0
- package/dist/{tools/__tests__ → services/memory}/memory.test.js +82 -19
- package/dist/{memory → services/memory}/store.js +6 -18
- package/dist/services/memory/store.test.d.ts +1 -0
- package/dist/{memory/__tests__ → services/memory}/store.test.js +18 -5
- package/dist/{memory → services/memory}/types.d.ts +8 -2
- package/dist/services/memory/types.js +6 -0
- package/dist/utils/async.d.ts +1 -0
- package/dist/utils/async.js +15 -0
- package/dist/utils/files.d.ts +7 -0
- package/dist/utils/files.js +77 -0
- package/dist/utils/files.test.d.ts +1 -0
- package/dist/utils/files.test.js +81 -0
- package/dist/utils/hash.d.ts +1 -0
- package/dist/utils/hash.js +4 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/json.d.ts +1 -0
- package/dist/utils/json.js +3 -0
- package/dist/utils/paths.d.ts +0 -1
- package/dist/utils/paths.js +1 -1
- package/dist/utils/temp-dir.test.d.ts +4 -0
- package/dist/utils/temp-dir.test.js +20 -0
- package/package.json +8 -6
- package/dist/memory/__tests__/embedder.test.js +0 -14
- package/dist/memory/types.js +0 -9
- package/dist/tools/handoffs.d.ts +0 -22
- package/dist/tools/memory.d.ts +0 -16
- /package/dist/{memory/__tests__/chunker.test.d.ts → cli/commands/cli-digest-pending.test.d.ts} +0 -0
- /package/dist/{memory/__tests__/embedder.test.d.ts → cli/commands/cli-memory.test.d.ts} +0 -0
- /package/dist/{kit-server.d.ts → entrypoints/server.d.ts} +0 -0
- /package/dist/{tools → mcp}/agent.d.ts +0 -0
- /package/dist/{tools → mcp}/integration.d.ts +0 -0
- /package/dist/{memory/__tests__/indexer.test.d.ts → services/digest/digest-background.test.d.ts} +0 -0
- /package/dist/{memory/__tests__/store.test.d.ts → services/digest/digest-init.test.d.ts} +0 -0
- /package/dist/{tools/__tests__/memory.test.d.ts → services/digest/digest-llama-local.test.d.ts} +0 -0
- /package/dist/{utils → services/integration}/credentials.d.ts +0 -0
- /package/dist/{utils/parser.d.ts → services/integration/parser/adf.d.ts} +0 -0
- /package/dist/{memory → services/memory}/store.d.ts +0 -0
|
@@ -2987,7 +2987,7 @@ var require_compile = __commonJS({
|
|
|
2987
2987
|
const schOrFunc = root.refs[ref];
|
|
2988
2988
|
if (schOrFunc)
|
|
2989
2989
|
return schOrFunc;
|
|
2990
|
-
let _sch =
|
|
2990
|
+
let _sch = resolve5.call(this, root, ref);
|
|
2991
2991
|
if (_sch === void 0) {
|
|
2992
2992
|
const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
2993
2993
|
const { schemaId } = this.opts;
|
|
@@ -3014,7 +3014,7 @@ var require_compile = __commonJS({
|
|
|
3014
3014
|
function sameSchemaEnv(s1, s2) {
|
|
3015
3015
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3016
3016
|
}
|
|
3017
|
-
function
|
|
3017
|
+
function resolve5(root, ref) {
|
|
3018
3018
|
let sch;
|
|
3019
3019
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3020
3020
|
ref = sch;
|
|
@@ -3229,8 +3229,8 @@ var require_utils = __commonJS({
|
|
|
3229
3229
|
}
|
|
3230
3230
|
return ind;
|
|
3231
3231
|
}
|
|
3232
|
-
function removeDotSegments(
|
|
3233
|
-
let input =
|
|
3232
|
+
function removeDotSegments(path15) {
|
|
3233
|
+
let input = path15;
|
|
3234
3234
|
const output = [];
|
|
3235
3235
|
let nextSlash = -1;
|
|
3236
3236
|
let len = 0;
|
|
@@ -3429,8 +3429,8 @@ var require_schemes = __commonJS({
|
|
|
3429
3429
|
wsComponent.secure = void 0;
|
|
3430
3430
|
}
|
|
3431
3431
|
if (wsComponent.resourceName) {
|
|
3432
|
-
const [
|
|
3433
|
-
wsComponent.path =
|
|
3432
|
+
const [path15, query] = wsComponent.resourceName.split("?");
|
|
3433
|
+
wsComponent.path = path15 && path15 !== "/" ? path15 : void 0;
|
|
3434
3434
|
wsComponent.query = query;
|
|
3435
3435
|
wsComponent.resourceName = void 0;
|
|
3436
3436
|
}
|
|
@@ -3589,55 +3589,55 @@ var require_fast_uri = __commonJS({
|
|
|
3589
3589
|
}
|
|
3590
3590
|
return uri;
|
|
3591
3591
|
}
|
|
3592
|
-
function
|
|
3592
|
+
function resolve5(baseURI, relativeURI, options) {
|
|
3593
3593
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3594
3594
|
const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
3595
3595
|
schemelessOptions.skipEscape = true;
|
|
3596
3596
|
return serialize(resolved, schemelessOptions);
|
|
3597
3597
|
}
|
|
3598
|
-
function resolveComponent(base,
|
|
3598
|
+
function resolveComponent(base, relative4, options, skipNormalization) {
|
|
3599
3599
|
const target = {};
|
|
3600
3600
|
if (!skipNormalization) {
|
|
3601
3601
|
base = parse3(serialize(base, options), options);
|
|
3602
|
-
|
|
3602
|
+
relative4 = parse3(serialize(relative4, options), options);
|
|
3603
3603
|
}
|
|
3604
3604
|
options = options || {};
|
|
3605
|
-
if (!options.tolerant &&
|
|
3606
|
-
target.scheme =
|
|
3607
|
-
target.userinfo =
|
|
3608
|
-
target.host =
|
|
3609
|
-
target.port =
|
|
3610
|
-
target.path = removeDotSegments(
|
|
3611
|
-
target.query =
|
|
3605
|
+
if (!options.tolerant && relative4.scheme) {
|
|
3606
|
+
target.scheme = relative4.scheme;
|
|
3607
|
+
target.userinfo = relative4.userinfo;
|
|
3608
|
+
target.host = relative4.host;
|
|
3609
|
+
target.port = relative4.port;
|
|
3610
|
+
target.path = removeDotSegments(relative4.path || "");
|
|
3611
|
+
target.query = relative4.query;
|
|
3612
3612
|
} else {
|
|
3613
|
-
if (
|
|
3614
|
-
target.userinfo =
|
|
3615
|
-
target.host =
|
|
3616
|
-
target.port =
|
|
3617
|
-
target.path = removeDotSegments(
|
|
3618
|
-
target.query =
|
|
3613
|
+
if (relative4.userinfo !== void 0 || relative4.host !== void 0 || relative4.port !== void 0) {
|
|
3614
|
+
target.userinfo = relative4.userinfo;
|
|
3615
|
+
target.host = relative4.host;
|
|
3616
|
+
target.port = relative4.port;
|
|
3617
|
+
target.path = removeDotSegments(relative4.path || "");
|
|
3618
|
+
target.query = relative4.query;
|
|
3619
3619
|
} else {
|
|
3620
|
-
if (!
|
|
3620
|
+
if (!relative4.path) {
|
|
3621
3621
|
target.path = base.path;
|
|
3622
|
-
if (
|
|
3623
|
-
target.query =
|
|
3622
|
+
if (relative4.query !== void 0) {
|
|
3623
|
+
target.query = relative4.query;
|
|
3624
3624
|
} else {
|
|
3625
3625
|
target.query = base.query;
|
|
3626
3626
|
}
|
|
3627
3627
|
} else {
|
|
3628
|
-
if (
|
|
3629
|
-
target.path = removeDotSegments(
|
|
3628
|
+
if (relative4.path[0] === "/") {
|
|
3629
|
+
target.path = removeDotSegments(relative4.path);
|
|
3630
3630
|
} else {
|
|
3631
3631
|
if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
|
|
3632
|
-
target.path = "/" +
|
|
3632
|
+
target.path = "/" + relative4.path;
|
|
3633
3633
|
} else if (!base.path) {
|
|
3634
|
-
target.path =
|
|
3634
|
+
target.path = relative4.path;
|
|
3635
3635
|
} else {
|
|
3636
|
-
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) +
|
|
3636
|
+
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative4.path;
|
|
3637
3637
|
}
|
|
3638
3638
|
target.path = removeDotSegments(target.path);
|
|
3639
3639
|
}
|
|
3640
|
-
target.query =
|
|
3640
|
+
target.query = relative4.query;
|
|
3641
3641
|
}
|
|
3642
3642
|
target.userinfo = base.userinfo;
|
|
3643
3643
|
target.host = base.host;
|
|
@@ -3645,7 +3645,7 @@ var require_fast_uri = __commonJS({
|
|
|
3645
3645
|
}
|
|
3646
3646
|
target.scheme = base.scheme;
|
|
3647
3647
|
}
|
|
3648
|
-
target.fragment =
|
|
3648
|
+
target.fragment = relative4.fragment;
|
|
3649
3649
|
return target;
|
|
3650
3650
|
}
|
|
3651
3651
|
function equal(uriA, uriB, options) {
|
|
@@ -3816,7 +3816,7 @@ var require_fast_uri = __commonJS({
|
|
|
3816
3816
|
var fastUri = {
|
|
3817
3817
|
SCHEMES,
|
|
3818
3818
|
normalize,
|
|
3819
|
-
resolve:
|
|
3819
|
+
resolve: resolve5,
|
|
3820
3820
|
resolveComponent,
|
|
3821
3821
|
equal,
|
|
3822
3822
|
serialize,
|
|
@@ -6792,12 +6792,12 @@ var require_dist = __commonJS({
|
|
|
6792
6792
|
throw new Error(`Unknown format "${name}"`);
|
|
6793
6793
|
return f;
|
|
6794
6794
|
};
|
|
6795
|
-
function addFormats(ajv, list,
|
|
6795
|
+
function addFormats(ajv, list, fs11, exportName) {
|
|
6796
6796
|
var _a;
|
|
6797
6797
|
var _b;
|
|
6798
6798
|
(_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
6799
6799
|
for (const f of list)
|
|
6800
|
-
ajv.addFormat(f,
|
|
6800
|
+
ajv.addFormat(f, fs11[f]);
|
|
6801
6801
|
}
|
|
6802
6802
|
module.exports = exports = formatsPlugin;
|
|
6803
6803
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -22171,8 +22171,8 @@ function getErrorMap() {
|
|
|
22171
22171
|
|
|
22172
22172
|
// ../node_modules/zod/v3/helpers/parseUtil.js
|
|
22173
22173
|
var makeIssue = (params) => {
|
|
22174
|
-
const { data, path:
|
|
22175
|
-
const fullPath = [...
|
|
22174
|
+
const { data, path: path15, errorMaps, issueData } = params;
|
|
22175
|
+
const fullPath = [...path15, ...issueData.path || []];
|
|
22176
22176
|
const fullIssue = {
|
|
22177
22177
|
...issueData,
|
|
22178
22178
|
path: fullPath
|
|
@@ -22288,11 +22288,11 @@ var errorUtil;
|
|
|
22288
22288
|
|
|
22289
22289
|
// ../node_modules/zod/v3/types.js
|
|
22290
22290
|
var ParseInputLazyPath = class {
|
|
22291
|
-
constructor(parent, value,
|
|
22291
|
+
constructor(parent, value, path15, key) {
|
|
22292
22292
|
this._cachedPath = [];
|
|
22293
22293
|
this.parent = parent;
|
|
22294
22294
|
this.data = value;
|
|
22295
|
-
this._path =
|
|
22295
|
+
this._path = path15;
|
|
22296
22296
|
this._key = key;
|
|
22297
22297
|
}
|
|
22298
22298
|
get path() {
|
|
@@ -25930,10 +25930,10 @@ function assignProp(target, prop, value) {
|
|
|
25930
25930
|
configurable: true
|
|
25931
25931
|
});
|
|
25932
25932
|
}
|
|
25933
|
-
function getElementAtPath(obj,
|
|
25934
|
-
if (!
|
|
25933
|
+
function getElementAtPath(obj, path15) {
|
|
25934
|
+
if (!path15)
|
|
25935
25935
|
return obj;
|
|
25936
|
-
return
|
|
25936
|
+
return path15.reduce((acc, key) => acc?.[key], obj);
|
|
25937
25937
|
}
|
|
25938
25938
|
function promiseAllObject(promisesObj) {
|
|
25939
25939
|
const keys = Object.keys(promisesObj);
|
|
@@ -26253,11 +26253,11 @@ function aborted(x, startIndex = 0) {
|
|
|
26253
26253
|
}
|
|
26254
26254
|
return false;
|
|
26255
26255
|
}
|
|
26256
|
-
function prefixIssues(
|
|
26256
|
+
function prefixIssues(path15, issues) {
|
|
26257
26257
|
return issues.map((iss) => {
|
|
26258
26258
|
var _a;
|
|
26259
26259
|
(_a = iss).path ?? (_a.path = []);
|
|
26260
|
-
iss.path.unshift(
|
|
26260
|
+
iss.path.unshift(path15);
|
|
26261
26261
|
return iss;
|
|
26262
26262
|
});
|
|
26263
26263
|
}
|
|
@@ -33768,7 +33768,7 @@ var Protocol = class {
|
|
|
33768
33768
|
return;
|
|
33769
33769
|
}
|
|
33770
33770
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
33771
|
-
await new Promise((
|
|
33771
|
+
await new Promise((resolve5) => setTimeout(resolve5, pollInterval));
|
|
33772
33772
|
options?.signal?.throwIfAborted();
|
|
33773
33773
|
}
|
|
33774
33774
|
} catch (error2) {
|
|
@@ -33785,7 +33785,7 @@ var Protocol = class {
|
|
|
33785
33785
|
*/
|
|
33786
33786
|
request(request, resultSchema, options) {
|
|
33787
33787
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
33788
|
-
return new Promise((
|
|
33788
|
+
return new Promise((resolve5, reject) => {
|
|
33789
33789
|
const earlyReject = (error2) => {
|
|
33790
33790
|
reject(error2);
|
|
33791
33791
|
};
|
|
@@ -33863,7 +33863,7 @@ var Protocol = class {
|
|
|
33863
33863
|
if (!parseResult.success) {
|
|
33864
33864
|
reject(parseResult.error);
|
|
33865
33865
|
} else {
|
|
33866
|
-
|
|
33866
|
+
resolve5(parseResult.data);
|
|
33867
33867
|
}
|
|
33868
33868
|
} catch (error2) {
|
|
33869
33869
|
reject(error2);
|
|
@@ -34124,12 +34124,12 @@ var Protocol = class {
|
|
|
34124
34124
|
}
|
|
34125
34125
|
} catch {
|
|
34126
34126
|
}
|
|
34127
|
-
return new Promise((
|
|
34127
|
+
return new Promise((resolve5, reject) => {
|
|
34128
34128
|
if (signal.aborted) {
|
|
34129
34129
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
34130
34130
|
return;
|
|
34131
34131
|
}
|
|
34132
|
-
const timeoutId = setTimeout(
|
|
34132
|
+
const timeoutId = setTimeout(resolve5, interval);
|
|
34133
34133
|
signal.addEventListener("abort", () => {
|
|
34134
34134
|
clearTimeout(timeoutId);
|
|
34135
34135
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -35229,7 +35229,7 @@ var McpServer = class {
|
|
|
35229
35229
|
let task = createTaskResult.task;
|
|
35230
35230
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
35231
35231
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
35232
|
-
await new Promise((
|
|
35232
|
+
await new Promise((resolve5) => setTimeout(resolve5, pollInterval));
|
|
35233
35233
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
35234
35234
|
if (!updatedTask) {
|
|
35235
35235
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -35872,20 +35872,20 @@ var StdioServerTransport = class {
|
|
|
35872
35872
|
this.onclose?.();
|
|
35873
35873
|
}
|
|
35874
35874
|
send(message) {
|
|
35875
|
-
return new Promise((
|
|
35875
|
+
return new Promise((resolve5) => {
|
|
35876
35876
|
const json = serializeMessage(message);
|
|
35877
35877
|
if (this._stdout.write(json)) {
|
|
35878
|
-
|
|
35878
|
+
resolve5();
|
|
35879
35879
|
} else {
|
|
35880
|
-
this._stdout.once("drain",
|
|
35880
|
+
this._stdout.once("drain", resolve5);
|
|
35881
35881
|
}
|
|
35882
35882
|
});
|
|
35883
35883
|
}
|
|
35884
35884
|
};
|
|
35885
35885
|
|
|
35886
|
-
// src/
|
|
35887
|
-
import * as
|
|
35888
|
-
import * as
|
|
35886
|
+
// src/mcp/core.ts
|
|
35887
|
+
import * as fs3 from "fs";
|
|
35888
|
+
import * as path4 from "path";
|
|
35889
35889
|
|
|
35890
35890
|
// src/utils/utils.ts
|
|
35891
35891
|
function getWorkspaceRoot() {
|
|
@@ -35898,42 +35898,128 @@ function mcpJson(obj) {
|
|
|
35898
35898
|
return mcpText(JSON.stringify(obj, null, 2));
|
|
35899
35899
|
}
|
|
35900
35900
|
|
|
35901
|
-
// src/
|
|
35902
|
-
import * as
|
|
35903
|
-
import * as
|
|
35901
|
+
// src/core/config/index.ts
|
|
35902
|
+
import * as fs2 from "fs";
|
|
35903
|
+
import * as path2 from "path";
|
|
35904
35904
|
|
|
35905
|
-
// src/memory/
|
|
35905
|
+
// src/services/memory/constants.ts
|
|
35906
35906
|
var DEFAULT_MEMORY_CONFIG = {
|
|
35907
35907
|
enabled: false,
|
|
35908
35908
|
wikiDir: "",
|
|
35909
35909
|
topK: 5,
|
|
35910
35910
|
chunkSize: 1500,
|
|
35911
35911
|
overlapLines: 2,
|
|
35912
|
-
embeddingModel: "
|
|
35912
|
+
embeddingModel: "small" /* SMALL */,
|
|
35913
35913
|
vectorDimension: 384
|
|
35914
35914
|
};
|
|
35915
|
+
var LOCK_RETRY_MS = 50;
|
|
35916
|
+
var LOCK_TIMEOUT_MS = 500;
|
|
35917
|
+
var RRF_K = 60;
|
|
35915
35918
|
|
|
35916
|
-
// src/
|
|
35919
|
+
// src/utils/files.ts
|
|
35920
|
+
import * as fs from "node:fs";
|
|
35921
|
+
import * as path from "node:path";
|
|
35922
|
+
function atomicWriteTextFile(filePath, content) {
|
|
35923
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
35924
|
+
const tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
35925
|
+
fs.writeFileSync(tempPath, content, "utf8");
|
|
35926
|
+
fs.renameSync(tempPath, filePath);
|
|
35927
|
+
}
|
|
35928
|
+
function atomicWriteJsonFile(filePath, value) {
|
|
35929
|
+
atomicWriteTextFile(filePath, `${JSON.stringify(value, null, 2)}
|
|
35930
|
+
`);
|
|
35931
|
+
}
|
|
35932
|
+
function tryWriteFileExclusive(filePath, content) {
|
|
35933
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
35934
|
+
try {
|
|
35935
|
+
fs.writeFileSync(filePath, content, { flag: "wx" });
|
|
35936
|
+
return true;
|
|
35937
|
+
} catch (err) {
|
|
35938
|
+
if (err.code === "EEXIST") return false;
|
|
35939
|
+
throw err;
|
|
35940
|
+
}
|
|
35941
|
+
}
|
|
35942
|
+
async function acquireLock(lockPath, timeoutMs, retryMs) {
|
|
35943
|
+
const deadline = Date.now() + timeoutMs;
|
|
35944
|
+
while (Date.now() < deadline) {
|
|
35945
|
+
try {
|
|
35946
|
+
if (tryWriteFileExclusive(lockPath, String(process.pid))) return true;
|
|
35947
|
+
} catch {
|
|
35948
|
+
}
|
|
35949
|
+
await new Promise((r) => setTimeout(r, retryMs));
|
|
35950
|
+
}
|
|
35951
|
+
return false;
|
|
35952
|
+
}
|
|
35953
|
+
function releaseLock(lockPath, opts = {}) {
|
|
35954
|
+
try {
|
|
35955
|
+
fs.unlinkSync(lockPath);
|
|
35956
|
+
} catch (err) {
|
|
35957
|
+
if (opts.ignoreErrors || err.code === "ENOENT") return;
|
|
35958
|
+
throw err;
|
|
35959
|
+
}
|
|
35960
|
+
}
|
|
35961
|
+
function tryAcquireProcessLock(lockPath) {
|
|
35962
|
+
const lockContent = JSON.stringify({ pid: process.pid });
|
|
35963
|
+
if (tryWriteFileExclusive(lockPath, lockContent)) return true;
|
|
35964
|
+
let pid;
|
|
35965
|
+
try {
|
|
35966
|
+
const raw = fs.readFileSync(lockPath, "utf8");
|
|
35967
|
+
pid = JSON.parse(raw).pid;
|
|
35968
|
+
} catch {
|
|
35969
|
+
}
|
|
35970
|
+
if (pid !== void 0) {
|
|
35971
|
+
try {
|
|
35972
|
+
process.kill(pid, 0);
|
|
35973
|
+
return false;
|
|
35974
|
+
} catch (err) {
|
|
35975
|
+
if (err.code !== "ESRCH") return false;
|
|
35976
|
+
}
|
|
35977
|
+
}
|
|
35978
|
+
try {
|
|
35979
|
+
fs.unlinkSync(lockPath);
|
|
35980
|
+
} catch {
|
|
35981
|
+
}
|
|
35982
|
+
return tryWriteFileExclusive(lockPath, lockContent);
|
|
35983
|
+
}
|
|
35984
|
+
|
|
35985
|
+
// src/core/config/index.ts
|
|
35917
35986
|
function resolveMemoryConfig(settings2, workspaceRoot2) {
|
|
35918
35987
|
const override = settings2.memory ?? {};
|
|
35919
35988
|
return {
|
|
35920
35989
|
...DEFAULT_MEMORY_CONFIG,
|
|
35921
35990
|
...override,
|
|
35922
35991
|
enabled: override.enabled ?? DEFAULT_MEMORY_CONFIG.enabled,
|
|
35923
|
-
wikiDir: typeof override.wikiDir === "string" && override.wikiDir.length > 0 ? override.wikiDir :
|
|
35992
|
+
wikiDir: typeof override.wikiDir === "string" && override.wikiDir.length > 0 ? override.wikiDir : path2.join(workspaceRoot2, ".agent-kit", "wiki")
|
|
35924
35993
|
};
|
|
35925
35994
|
}
|
|
35926
35995
|
function loadProjectSettings(projectDir) {
|
|
35927
|
-
const settingsPath =
|
|
35928
|
-
if (
|
|
35996
|
+
const settingsPath = path2.join(projectDir, ".agent-kit", "settings.json");
|
|
35997
|
+
if (fs2.existsSync(settingsPath)) {
|
|
35929
35998
|
try {
|
|
35930
|
-
return JSON.parse(
|
|
35999
|
+
return JSON.parse(fs2.readFileSync(settingsPath, "utf-8"));
|
|
35931
36000
|
} catch (error2) {
|
|
35932
36001
|
console.error(`[agent-kit] Warning: Failed to parse ${settingsPath}:`, error2);
|
|
35933
36002
|
}
|
|
35934
36003
|
}
|
|
35935
36004
|
return {};
|
|
35936
36005
|
}
|
|
36006
|
+
function writeProjectSettings(workspaceRoot2, patch) {
|
|
36007
|
+
const settingsPath = path2.join(workspaceRoot2, ".agent-kit", "settings.json");
|
|
36008
|
+
const current = loadProjectSettings(workspaceRoot2);
|
|
36009
|
+
atomicWriteJsonFile(settingsPath, { ...current, ...patch });
|
|
36010
|
+
}
|
|
36011
|
+
function resolveConversationDigestConfig(settings2) {
|
|
36012
|
+
const digest = settings2.memory?.conversationDigest;
|
|
36013
|
+
if (!digest?.initialized || typeof digest.modelId !== "string" || typeof digest.initializedAt !== "string") {
|
|
36014
|
+
return void 0;
|
|
36015
|
+
}
|
|
36016
|
+
return {
|
|
36017
|
+
enabled: digest.enabled !== false,
|
|
36018
|
+
initialized: true,
|
|
36019
|
+
modelId: digest.modelId,
|
|
36020
|
+
initializedAt: digest.initializedAt
|
|
36021
|
+
};
|
|
36022
|
+
}
|
|
35937
36023
|
var FORBIDDEN_FILES = [
|
|
35938
36024
|
".env",
|
|
35939
36025
|
".bashrc",
|
|
@@ -35965,17 +36051,10 @@ var FORBIDDEN_PATTERNS = [
|
|
|
35965
36051
|
/secrets\.json$/i,
|
|
35966
36052
|
/secret\.json$/i
|
|
35967
36053
|
];
|
|
35968
|
-
var FORBIDDEN_DIRS = [
|
|
35969
|
-
".git",
|
|
35970
|
-
".ssh",
|
|
35971
|
-
".aws",
|
|
35972
|
-
".kube",
|
|
35973
|
-
".gnupg",
|
|
35974
|
-
".docker"
|
|
35975
|
-
];
|
|
36054
|
+
var FORBIDDEN_DIRS = [".git", ".ssh", ".aws", ".kube", ".gnupg", ".docker"];
|
|
35976
36055
|
|
|
35977
|
-
// src/
|
|
35978
|
-
import * as
|
|
36056
|
+
// src/core/handoffs/index.ts
|
|
36057
|
+
import * as path3 from "path";
|
|
35979
36058
|
var HANDOFF_TYPES = [
|
|
35980
36059
|
"brainstorm",
|
|
35981
36060
|
"clarification",
|
|
@@ -36018,16 +36097,16 @@ function resolveHandoffPath(input) {
|
|
|
36018
36097
|
content: input.content,
|
|
36019
36098
|
type: canonicalType
|
|
36020
36099
|
});
|
|
36021
|
-
const relativePath =
|
|
36100
|
+
const relativePath = path3.join(".agent-kit", "handoffs", featureSlug, `${canonicalType}.md`);
|
|
36022
36101
|
return {
|
|
36023
36102
|
featureSlug,
|
|
36024
36103
|
canonicalType,
|
|
36025
|
-
filePath:
|
|
36104
|
+
filePath: path3.join(input.workspaceRoot, relativePath),
|
|
36026
36105
|
relativePath
|
|
36027
36106
|
};
|
|
36028
36107
|
}
|
|
36029
36108
|
|
|
36030
|
-
// src/
|
|
36109
|
+
// src/mcp/core.ts
|
|
36031
36110
|
function registerCoreTools(server2) {
|
|
36032
36111
|
server2.tool(
|
|
36033
36112
|
"kit_save_handoff",
|
|
@@ -36047,11 +36126,11 @@ function registerCoreTools(server2) {
|
|
|
36047
36126
|
slug,
|
|
36048
36127
|
content
|
|
36049
36128
|
});
|
|
36050
|
-
const handoffDir =
|
|
36051
|
-
if (!
|
|
36052
|
-
|
|
36129
|
+
const handoffDir = path4.dirname(location.filePath);
|
|
36130
|
+
if (!fs3.existsSync(handoffDir)) {
|
|
36131
|
+
fs3.mkdirSync(handoffDir, { recursive: true });
|
|
36053
36132
|
}
|
|
36054
|
-
|
|
36133
|
+
fs3.writeFileSync(location.filePath, content, "utf8");
|
|
36055
36134
|
return mcpText(`\u2705 Saved to: ${location.filePath}`);
|
|
36056
36135
|
} catch (error2) {
|
|
36057
36136
|
return mcpText(`Error saving handoff: ${error2}`);
|
|
@@ -36060,31 +36139,31 @@ function registerCoreTools(server2) {
|
|
|
36060
36139
|
);
|
|
36061
36140
|
}
|
|
36062
36141
|
|
|
36063
|
-
// src/
|
|
36142
|
+
// src/mcp/agent.ts
|
|
36064
36143
|
import { spawn } from "child_process";
|
|
36065
36144
|
import { randomUUID } from "crypto";
|
|
36066
|
-
import * as
|
|
36067
|
-
import * as
|
|
36145
|
+
import * as fs4 from "fs";
|
|
36146
|
+
import * as path6 from "path";
|
|
36068
36147
|
|
|
36069
|
-
// src/
|
|
36148
|
+
// src/core/security/index.ts
|
|
36070
36149
|
import { execFileSync } from "child_process";
|
|
36071
|
-
import * as
|
|
36150
|
+
import * as path5 from "path";
|
|
36072
36151
|
function sanitize(input) {
|
|
36073
36152
|
return String(input).replace(/[;&|`$<>\\]/g, "").trim().slice(0, 500);
|
|
36074
36153
|
}
|
|
36075
36154
|
function validatePath(filePath, baseDir = process.cwd()) {
|
|
36076
|
-
const resolved =
|
|
36077
|
-
const root =
|
|
36078
|
-
if (resolved !== root && !resolved.startsWith(root +
|
|
36155
|
+
const resolved = path5.resolve(baseDir, filePath);
|
|
36156
|
+
const root = path5.resolve(baseDir);
|
|
36157
|
+
if (resolved !== root && !resolved.startsWith(root + path5.sep)) {
|
|
36079
36158
|
throw new Error(`Path traversal detected: ${filePath}`);
|
|
36080
36159
|
}
|
|
36081
|
-
const segments = resolved.split(
|
|
36160
|
+
const segments = resolved.split(path5.sep);
|
|
36082
36161
|
for (const segment of segments) {
|
|
36083
36162
|
if (FORBIDDEN_DIRS.some((d) => segment.toLowerCase() === d.toLowerCase())) {
|
|
36084
36163
|
throw new Error(`Access to sensitive directory is FORBIDDEN: ${segment}`);
|
|
36085
36164
|
}
|
|
36086
36165
|
}
|
|
36087
|
-
const fileName =
|
|
36166
|
+
const fileName = path5.basename(resolved);
|
|
36088
36167
|
const isExactForbidden = FORBIDDEN_FILES.some((f) => fileName.toLowerCase() === f.toLowerCase());
|
|
36089
36168
|
const isPatternForbidden = FORBIDDEN_PATTERNS.some((re) => re.test(fileName));
|
|
36090
36169
|
if (isExactForbidden || isPatternForbidden) {
|
|
@@ -36092,7 +36171,6 @@ function validatePath(filePath, baseDir = process.cwd()) {
|
|
|
36092
36171
|
}
|
|
36093
36172
|
return resolved;
|
|
36094
36173
|
}
|
|
36095
|
-
var GIT_TIMEOUT = parseInt(process.env.GEMINI_KIT_GIT_TIMEOUT || "30000", 10);
|
|
36096
36174
|
function commandExists(cmd) {
|
|
36097
36175
|
try {
|
|
36098
36176
|
const checkCmd = process.platform === "win32" ? "where" : "which";
|
|
@@ -36117,7 +36195,7 @@ function sanitizeOutput(text) {
|
|
|
36117
36195
|
// AWS access keys
|
|
36118
36196
|
/xox[baprs]-[A-Za-z0-9-]{10,}/g,
|
|
36119
36197
|
// Slack tokens
|
|
36120
|
-
/[Aa]tlassian[_
|
|
36198
|
+
/[Aa]tlassian[_-]?[Aa][Pp][Ii][_-]?[Tt]oken[^\s]*\s*[:=]\s*\S+/g
|
|
36121
36199
|
// Atlassian token patterns
|
|
36122
36200
|
];
|
|
36123
36201
|
let sanitized = text;
|
|
@@ -36127,7 +36205,7 @@ function sanitizeOutput(text) {
|
|
|
36127
36205
|
return sanitized;
|
|
36128
36206
|
}
|
|
36129
36207
|
|
|
36130
|
-
// src/
|
|
36208
|
+
// src/mcp/agent.ts
|
|
36131
36209
|
var AGENT_TIMEOUT = parseInt(process.env.KIT_AGENT_TIMEOUT || "300000", 10);
|
|
36132
36210
|
var jobRegistry = /* @__PURE__ */ new Map();
|
|
36133
36211
|
var INSTALL_HINTS = {
|
|
@@ -36142,36 +36220,27 @@ function agentArgs(agent, prompt, workspaceRoot2) {
|
|
|
36142
36220
|
case "claude":
|
|
36143
36221
|
return ["--dangerously-skip-permissions", "-p", prompt];
|
|
36144
36222
|
case "codex":
|
|
36145
|
-
return [
|
|
36146
|
-
"--ask-for-approval",
|
|
36147
|
-
"never",
|
|
36148
|
-
"--sandbox",
|
|
36149
|
-
"workspace-write",
|
|
36150
|
-
"--cd",
|
|
36151
|
-
workspaceRoot2,
|
|
36152
|
-
"exec",
|
|
36153
|
-
prompt
|
|
36154
|
-
];
|
|
36223
|
+
return ["--ask-for-approval", "never", "--sandbox", "workspace-write", "--cd", workspaceRoot2, "exec", prompt];
|
|
36155
36224
|
}
|
|
36156
36225
|
}
|
|
36157
36226
|
function taskSlug(task) {
|
|
36158
36227
|
return task.toLowerCase().replace(/[^a-z0-9\s]/g, "").trim().split(/\s+/).slice(0, 6).join("-").slice(0, 48);
|
|
36159
36228
|
}
|
|
36160
36229
|
function initAgentLog(workspaceRoot2, slug, agent) {
|
|
36161
|
-
const logsDir =
|
|
36162
|
-
|
|
36230
|
+
const logsDir = path6.join(workspaceRoot2, ".agent-kit", "logs", "agents");
|
|
36231
|
+
fs4.mkdirSync(logsDir, { recursive: true });
|
|
36163
36232
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
36164
|
-
const logFile =
|
|
36233
|
+
const logFile = path6.join(logsDir, `delegate-${now}-${slug}.log`);
|
|
36165
36234
|
const header = `Agent: ${agent}
|
|
36166
36235
|
Date: ${now}
|
|
36167
36236
|
${"\u2500".repeat(60)}
|
|
36168
36237
|
|
|
36169
36238
|
`;
|
|
36170
|
-
|
|
36171
|
-
const logStream =
|
|
36239
|
+
fs4.writeFileSync(logFile, header, "utf-8");
|
|
36240
|
+
const logStream = fs4.createWriteStream(logFile, { flags: "a" });
|
|
36172
36241
|
logStream.on("error", () => {
|
|
36173
36242
|
});
|
|
36174
|
-
return { logPath:
|
|
36243
|
+
return { logPath: path6.relative(workspaceRoot2, logFile), logStream };
|
|
36175
36244
|
}
|
|
36176
36245
|
function registerAgentTools(server2) {
|
|
36177
36246
|
server2.tool(
|
|
@@ -36179,9 +36248,7 @@ function registerAgentTools(server2) {
|
|
|
36179
36248
|
"!Important: Trigger only when user explicitly asks to delegate a task to an external agent CLI (gemini, claude, or codex). The task can be a direct message or a path to a handoff file (.agent-kit/handoffs/feature-slug/plan.md).",
|
|
36180
36249
|
{
|
|
36181
36250
|
agent: external_exports.enum(["gemini", "claude", "codex"]).describe('The agent CLI to invoke: "gemini", "claude", or "codex"'),
|
|
36182
|
-
task: external_exports.string().describe(
|
|
36183
|
-
'Task message or path to a handoff file (e.g., ".agent-kit/handoffs/feature-slug/plan.md")'
|
|
36184
|
-
)
|
|
36251
|
+
task: external_exports.string().describe('Task message or path to a handoff file (e.g., ".agent-kit/handoffs/feature-slug/plan.md")')
|
|
36185
36252
|
},
|
|
36186
36253
|
async ({ agent, task }, extra) => {
|
|
36187
36254
|
const workspaceRoot2 = getWorkspaceRoot();
|
|
@@ -36190,11 +36257,11 @@ function registerAgentTools(server2) {
|
|
|
36190
36257
|
let killChild;
|
|
36191
36258
|
try {
|
|
36192
36259
|
let prompt = task;
|
|
36193
|
-
const resolvedTask =
|
|
36194
|
-
if (
|
|
36260
|
+
const resolvedTask = path6.resolve(workspaceRoot2, task);
|
|
36261
|
+
if (fs4.existsSync(resolvedTask) && fs4.statSync(resolvedTask).isFile()) {
|
|
36195
36262
|
try {
|
|
36196
36263
|
validatePath(task, workspaceRoot2);
|
|
36197
|
-
prompt =
|
|
36264
|
+
prompt = fs4.readFileSync(resolvedTask, "utf-8");
|
|
36198
36265
|
} catch (err) {
|
|
36199
36266
|
return mcpText(`Error reading task file: ${err}`);
|
|
36200
36267
|
}
|
|
@@ -36247,7 +36314,7 @@ function registerAgentTools(server2) {
|
|
|
36247
36314
|
};
|
|
36248
36315
|
if (extra.signal.aborted) killChild();
|
|
36249
36316
|
else extra.signal.addEventListener("abort", killChild);
|
|
36250
|
-
await new Promise((
|
|
36317
|
+
await new Promise((resolve5, reject) => {
|
|
36251
36318
|
child.stdout?.on("data", (data) => {
|
|
36252
36319
|
job.chunks.push(data.toString());
|
|
36253
36320
|
job.logStream.write(data);
|
|
@@ -36257,11 +36324,8 @@ function registerAgentTools(server2) {
|
|
|
36257
36324
|
job.logStream.write(data);
|
|
36258
36325
|
});
|
|
36259
36326
|
child.on("close", (code, signal) => {
|
|
36260
|
-
if (code === 0)
|
|
36261
|
-
else
|
|
36262
|
-
reject(
|
|
36263
|
-
new Error(`Process exited with code ${code}${signal ? ` (signal: ${signal})` : ""}`)
|
|
36264
|
-
);
|
|
36327
|
+
if (code === 0) resolve5();
|
|
36328
|
+
else reject(new Error(`Process exited with code ${code}${signal ? ` (signal: ${signal})` : ""}`));
|
|
36265
36329
|
});
|
|
36266
36330
|
child.on("error", reject);
|
|
36267
36331
|
});
|
|
@@ -36291,21 +36355,21 @@ function registerAgentTools(server2) {
|
|
|
36291
36355
|
);
|
|
36292
36356
|
}
|
|
36293
36357
|
|
|
36294
|
-
// src/
|
|
36295
|
-
import { writeFileSync as
|
|
36358
|
+
// src/mcp/integration.ts
|
|
36359
|
+
import { writeFileSync as writeFileSync4 } from "fs";
|
|
36296
36360
|
|
|
36297
|
-
// src/
|
|
36298
|
-
import * as
|
|
36361
|
+
// src/services/integration/credentials.ts
|
|
36362
|
+
import * as fs5 from "fs";
|
|
36299
36363
|
|
|
36300
36364
|
// src/utils/paths.ts
|
|
36301
36365
|
import * as os from "os";
|
|
36302
|
-
import * as
|
|
36303
|
-
var AGENT_KIT_HOME =
|
|
36304
|
-
var CREDENTIALS_FILE =
|
|
36305
|
-
var MODEL_CACHE_DIR =
|
|
36306
|
-
var FASTEMBED_CACHE_DIR =
|
|
36366
|
+
import * as path7 from "path";
|
|
36367
|
+
var AGENT_KIT_HOME = path7.join(os.homedir(), ".agent-kit");
|
|
36368
|
+
var CREDENTIALS_FILE = path7.join(AGENT_KIT_HOME, "credentials");
|
|
36369
|
+
var MODEL_CACHE_DIR = path7.join(AGENT_KIT_HOME, "cache", "models");
|
|
36370
|
+
var FASTEMBED_CACHE_DIR = path7.join(MODEL_CACHE_DIR, "fastembed");
|
|
36307
36371
|
|
|
36308
|
-
// src/
|
|
36372
|
+
// src/services/integration/credentials.ts
|
|
36309
36373
|
var cachedCredentials = null;
|
|
36310
36374
|
function parseIni(content) {
|
|
36311
36375
|
const result = {};
|
|
@@ -36330,12 +36394,12 @@ function parseIni(content) {
|
|
|
36330
36394
|
}
|
|
36331
36395
|
function loadCredentials() {
|
|
36332
36396
|
if (cachedCredentials !== null) return cachedCredentials;
|
|
36333
|
-
if (!
|
|
36397
|
+
if (!fs5.existsSync(CREDENTIALS_FILE)) {
|
|
36334
36398
|
cachedCredentials = {};
|
|
36335
36399
|
return cachedCredentials;
|
|
36336
36400
|
}
|
|
36337
36401
|
try {
|
|
36338
|
-
const stat =
|
|
36402
|
+
const stat = fs5.statSync(CREDENTIALS_FILE);
|
|
36339
36403
|
const mode = stat.mode & 511;
|
|
36340
36404
|
if (mode !== 384) {
|
|
36341
36405
|
process.stderr.write(
|
|
@@ -36345,7 +36409,7 @@ function loadCredentials() {
|
|
|
36345
36409
|
}
|
|
36346
36410
|
} catch {
|
|
36347
36411
|
}
|
|
36348
|
-
const content =
|
|
36412
|
+
const content = fs5.readFileSync(CREDENTIALS_FILE, "utf-8");
|
|
36349
36413
|
const ini = parseIni(content);
|
|
36350
36414
|
const profile = process.env.KIT_PROFILE ?? "default";
|
|
36351
36415
|
cachedCredentials = ini[profile] ?? {};
|
|
@@ -36364,7 +36428,7 @@ function getCredential(key) {
|
|
|
36364
36428
|
return loadCredentials()[key];
|
|
36365
36429
|
}
|
|
36366
36430
|
|
|
36367
|
-
// src/
|
|
36431
|
+
// src/services/integration/parser/adf.ts
|
|
36368
36432
|
function adfToMarkdown(adf) {
|
|
36369
36433
|
if (!adf || typeof adf !== "object") return "No description";
|
|
36370
36434
|
const content = adf.content;
|
|
@@ -36474,9 +36538,7 @@ ${renderNodes(node.content, listDepth, node.type).trim()}
|
|
|
36474
36538
|
for (const row of rows) {
|
|
36475
36539
|
if (row.type !== "tableRow") continue;
|
|
36476
36540
|
const cells = row.content || [];
|
|
36477
|
-
const rendered = cells.map(
|
|
36478
|
-
(c) => renderNodes(c.content).trim().replace(/\n+/g, " ").replace(/\|/g, "\\|")
|
|
36479
|
-
);
|
|
36541
|
+
const rendered = cells.map((c) => renderNodes(c.content).trim().replace(/\n+/g, " ").replace(/\|/g, "\\|"));
|
|
36480
36542
|
result += "| " + rendered.join(" | ") + " |\n";
|
|
36481
36543
|
if (isFirstRow) {
|
|
36482
36544
|
result += "| " + cells.map(() => "---").join(" | ") + " |\n";
|
|
@@ -36488,7 +36550,7 @@ ${renderNodes(node.content, listDepth, node.type).trim()}
|
|
|
36488
36550
|
return renderNodes(content).trim() || "No description";
|
|
36489
36551
|
}
|
|
36490
36552
|
|
|
36491
|
-
// src/
|
|
36553
|
+
// src/mcp/integration.ts
|
|
36492
36554
|
var BitbucketPrSchema = external_exports.object({
|
|
36493
36555
|
id: external_exports.number(),
|
|
36494
36556
|
title: external_exports.string(),
|
|
@@ -36545,9 +36607,7 @@ function registerIntegrationTools(server2) {
|
|
|
36545
36607
|
"Get Bitbucket PR details and optionally the diff. Accepts a full PR URL or a numeric PR ID with workspace + repoSlug.",
|
|
36546
36608
|
{
|
|
36547
36609
|
input: external_exports.string().describe("Bitbucket PR URL or numeric PR ID"),
|
|
36548
|
-
workspace: external_exports.string().optional().describe(
|
|
36549
|
-
"Bitbucket workspace slug (required for numeric ID if BITBUCKET_DEFAULT_WORKSPACE not set)"
|
|
36550
|
-
),
|
|
36610
|
+
workspace: external_exports.string().optional().describe("Bitbucket workspace slug (required for numeric ID if BITBUCKET_DEFAULT_WORKSPACE not set)"),
|
|
36551
36611
|
repoSlug: external_exports.string().optional().describe("Bitbucket repo slug (required for numeric ID)"),
|
|
36552
36612
|
includeDiff: external_exports.boolean().optional().default(true).describe("Include unified diff in response")
|
|
36553
36613
|
},
|
|
@@ -36572,9 +36632,7 @@ function registerIntegrationTools(server2) {
|
|
|
36572
36632
|
);
|
|
36573
36633
|
}
|
|
36574
36634
|
if (!repo || !prId) {
|
|
36575
|
-
return mcpText(
|
|
36576
|
-
`\u274C Could not parse PR URL. Expected: bitbucket.org/{ws}/{repo}/pull-requests/{id}`
|
|
36577
|
-
);
|
|
36635
|
+
return mcpText(`\u274C Could not parse PR URL. Expected: bitbucket.org/{ws}/{repo}/pull-requests/{id}`);
|
|
36578
36636
|
}
|
|
36579
36637
|
const safeWs = sanitize(ws);
|
|
36580
36638
|
const safeRepo = sanitize(repo);
|
|
@@ -36606,7 +36664,7 @@ ${diff}
|
|
|
36606
36664
|
} else {
|
|
36607
36665
|
const filePath = `/tmp/kit-pr-${prId}-${Date.now()}.diff`;
|
|
36608
36666
|
try {
|
|
36609
|
-
|
|
36667
|
+
writeFileSync4(filePath, diff, "utf8");
|
|
36610
36668
|
output += `
|
|
36611
36669
|
|
|
36612
36670
|
### Diff
|
|
@@ -36678,10 +36736,10 @@ ${ticket.fields.labels?.join(", ") || "None"}`;
|
|
|
36678
36736
|
);
|
|
36679
36737
|
}
|
|
36680
36738
|
|
|
36681
|
-
// src/
|
|
36682
|
-
import * as
|
|
36739
|
+
// src/mcp/memory.ts
|
|
36740
|
+
import * as path14 from "path";
|
|
36683
36741
|
|
|
36684
|
-
// src/memory/embedder.ts
|
|
36742
|
+
// src/services/memory/embedder.ts
|
|
36685
36743
|
var EmbedderError = class extends Error {
|
|
36686
36744
|
constructor(message, cause) {
|
|
36687
36745
|
super(message);
|
|
@@ -36718,16 +36776,25 @@ var Embedder = class {
|
|
|
36718
36776
|
isReady() {
|
|
36719
36777
|
return this.pipeline !== null;
|
|
36720
36778
|
}
|
|
36779
|
+
async initialize() {
|
|
36780
|
+
if (!this.pipeline) {
|
|
36781
|
+
await this.loadModel();
|
|
36782
|
+
}
|
|
36783
|
+
}
|
|
36721
36784
|
async loadModel() {
|
|
36722
36785
|
try {
|
|
36723
36786
|
const { EmbeddingModel, FlagEmbedding } = await import("fastembed");
|
|
36724
36787
|
const modelMap = {
|
|
36725
|
-
"
|
|
36726
|
-
"
|
|
36727
|
-
"
|
|
36788
|
+
["tiny" /* TINY */]: EmbeddingModel.AllMiniLML6V2,
|
|
36789
|
+
["small" /* SMALL */]: EmbeddingModel.BGESmallENV15,
|
|
36790
|
+
["large" /* LARGE */]: EmbeddingModel.BGEBaseENV15
|
|
36728
36791
|
};
|
|
36729
36792
|
const model = modelMap[this.modelName] ?? EmbeddingModel.BGESmallENV15;
|
|
36730
|
-
const embedder = await FlagEmbedding.init({
|
|
36793
|
+
const embedder = await FlagEmbedding.init({
|
|
36794
|
+
model,
|
|
36795
|
+
cacheDir: FASTEMBED_CACHE_DIR,
|
|
36796
|
+
showDownloadProgress: false
|
|
36797
|
+
});
|
|
36731
36798
|
this.pipeline = async (texts) => {
|
|
36732
36799
|
const result = [];
|
|
36733
36800
|
for await (const batch of embedder.embed(texts, texts.length)) {
|
|
@@ -36743,14 +36810,19 @@ var Embedder = class {
|
|
|
36743
36810
|
}
|
|
36744
36811
|
};
|
|
36745
36812
|
|
|
36746
|
-
// src/memory/indexer.ts
|
|
36747
|
-
import * as
|
|
36748
|
-
import * as
|
|
36813
|
+
// src/services/memory/indexer.ts
|
|
36814
|
+
import * as fs6 from "fs";
|
|
36815
|
+
import * as path8 from "path";
|
|
36749
36816
|
|
|
36750
|
-
// src/
|
|
36751
|
-
import { createHash } from "crypto";
|
|
36817
|
+
// src/utils/hash.ts
|
|
36818
|
+
import { createHash } from "node:crypto";
|
|
36819
|
+
function sha256Hex(content) {
|
|
36820
|
+
return createHash("sha256").update(content).digest("hex");
|
|
36821
|
+
}
|
|
36822
|
+
|
|
36823
|
+
// src/services/memory/chunker.ts
|
|
36752
36824
|
function computeChunkId(content) {
|
|
36753
|
-
return
|
|
36825
|
+
return sha256Hex(content).slice(0, 16);
|
|
36754
36826
|
}
|
|
36755
36827
|
function cleanContentForEmbedding(text) {
|
|
36756
36828
|
return text.replace(/<!--[\s\S]*?-->/g, "");
|
|
@@ -36879,27 +36951,7 @@ ${sectionText}` : sectionText;
|
|
|
36879
36951
|
return chunks;
|
|
36880
36952
|
}
|
|
36881
36953
|
|
|
36882
|
-
// src/memory/indexer.ts
|
|
36883
|
-
var LOCK_RETRY_MS = 50;
|
|
36884
|
-
var LOCK_TIMEOUT_MS = 500;
|
|
36885
|
-
async function acquireLock(lockPath) {
|
|
36886
|
-
const deadline = Date.now() + LOCK_TIMEOUT_MS;
|
|
36887
|
-
while (Date.now() < deadline) {
|
|
36888
|
-
try {
|
|
36889
|
-
fs5.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
36890
|
-
return true;
|
|
36891
|
-
} catch {
|
|
36892
|
-
await new Promise((r) => setTimeout(r, LOCK_RETRY_MS));
|
|
36893
|
-
}
|
|
36894
|
-
}
|
|
36895
|
-
return false;
|
|
36896
|
-
}
|
|
36897
|
-
function releaseLock(lockPath) {
|
|
36898
|
-
try {
|
|
36899
|
-
fs5.unlinkSync(lockPath);
|
|
36900
|
-
} catch {
|
|
36901
|
-
}
|
|
36902
|
-
}
|
|
36954
|
+
// src/services/memory/indexer.ts
|
|
36903
36955
|
var MemoryIndexer = class {
|
|
36904
36956
|
constructor(store, embedder, config2) {
|
|
36905
36957
|
this.store = store;
|
|
@@ -36911,26 +36963,26 @@ var MemoryIndexer = class {
|
|
|
36911
36963
|
return this.indexFileRelativeTo(absolutePath, this.config.wikiDir);
|
|
36912
36964
|
}
|
|
36913
36965
|
async indexFileRelativeTo(absolutePath, sourceRoot) {
|
|
36914
|
-
const source =
|
|
36915
|
-
const
|
|
36966
|
+
const source = path8.relative(sourceRoot, absolutePath);
|
|
36967
|
+
const existingChunkIds = this.store.hashesBySource(source);
|
|
36916
36968
|
let text;
|
|
36917
36969
|
try {
|
|
36918
|
-
text =
|
|
36970
|
+
text = fs6.readFileSync(absolutePath, "utf8");
|
|
36919
36971
|
} catch (err) {
|
|
36920
36972
|
console.warn(`[memory-indexer] Cannot read file ${absolutePath}:`, err);
|
|
36921
|
-
return { indexed: 0, deleted: 0, skipped:
|
|
36973
|
+
return { indexed: 0, deleted: 0, skipped: existingChunkIds.size };
|
|
36922
36974
|
}
|
|
36923
36975
|
const allChunks = chunkMarkdown(text, source, this.config);
|
|
36924
|
-
const
|
|
36925
|
-
const toIndex = allChunks.filter((
|
|
36926
|
-
const toDelete = [...
|
|
36976
|
+
const currentChunkIds = new Set(allChunks.map((chunk) => chunk.id));
|
|
36977
|
+
const toIndex = allChunks.filter((chunk) => !existingChunkIds.has(chunk.id));
|
|
36978
|
+
const toDelete = [...existingChunkIds].filter((id) => !currentChunkIds.has(id));
|
|
36927
36979
|
let embeddings = [];
|
|
36928
36980
|
if (toIndex.length > 0) {
|
|
36929
36981
|
try {
|
|
36930
36982
|
embeddings = await this.embedder.embed(toIndex.map((c) => c.content));
|
|
36931
36983
|
} catch (err) {
|
|
36932
36984
|
console.warn(`[memory-indexer] Embedding failed for ${absolutePath}:`, err);
|
|
36933
|
-
return { indexed: 0, deleted: 0, skipped:
|
|
36985
|
+
return { indexed: 0, deleted: 0, skipped: existingChunkIds.size };
|
|
36934
36986
|
}
|
|
36935
36987
|
}
|
|
36936
36988
|
if (toIndex.length > 0) {
|
|
@@ -36947,20 +36999,20 @@ var MemoryIndexer = class {
|
|
|
36947
36999
|
}
|
|
36948
37000
|
async indexDirectory(rootDir, opts = {}) {
|
|
36949
37001
|
const totals = { indexed: 0, deleted: 0, skipped: 0 };
|
|
36950
|
-
if (!
|
|
37002
|
+
if (!fs6.existsSync(rootDir)) return totals;
|
|
36951
37003
|
const relativeBase = opts.relativeBase ?? this.config.wikiDir;
|
|
36952
37004
|
const excludeFiles = new Set(opts.excludeFiles ?? []);
|
|
36953
37005
|
const files = [];
|
|
36954
37006
|
const walk = (dirPath) => {
|
|
36955
37007
|
let entries;
|
|
36956
37008
|
try {
|
|
36957
|
-
entries =
|
|
37009
|
+
entries = fs6.readdirSync(dirPath, { withFileTypes: true });
|
|
36958
37010
|
} catch (err) {
|
|
36959
37011
|
console.warn(`[memory-indexer] Cannot scan directory ${dirPath}:`, err);
|
|
36960
37012
|
return;
|
|
36961
37013
|
}
|
|
36962
37014
|
for (const entry of entries) {
|
|
36963
|
-
const entryPath =
|
|
37015
|
+
const entryPath = path8.join(dirPath, entry.name);
|
|
36964
37016
|
if (entry.isDirectory()) {
|
|
36965
37017
|
walk(entryPath);
|
|
36966
37018
|
continue;
|
|
@@ -36971,9 +37023,7 @@ var MemoryIndexer = class {
|
|
|
36971
37023
|
}
|
|
36972
37024
|
};
|
|
36973
37025
|
walk(rootDir);
|
|
36974
|
-
const currentSources = new Set(
|
|
36975
|
-
files.map((file) => path7.relative(relativeBase, file))
|
|
36976
|
-
);
|
|
37026
|
+
const currentSources = new Set(files.map((file) => path8.relative(relativeBase, file)));
|
|
36977
37027
|
for (const stale of this.store.indexedSources()) {
|
|
36978
37028
|
if (!currentSources.has(stale)) {
|
|
36979
37029
|
this.store.deleteBySource(stale);
|
|
@@ -37004,22 +37054,21 @@ var MemoryIndexer = class {
|
|
|
37004
37054
|
if (bm25Ids.size > 0) {
|
|
37005
37055
|
denseResults = denseResults.filter((result) => bm25Ids.has(result.id));
|
|
37006
37056
|
}
|
|
37007
|
-
const k = 60;
|
|
37008
37057
|
const scoreMap = /* @__PURE__ */ new Map();
|
|
37009
37058
|
denseResults.forEach((r, rank) => {
|
|
37010
|
-
scoreMap.set(r.id, { dense: 1 / (
|
|
37059
|
+
scoreMap.set(r.id, { dense: 1 / (RRF_K + rank + 1), bm25: 0 });
|
|
37011
37060
|
});
|
|
37012
37061
|
bm25Results.forEach((r, rank) => {
|
|
37013
37062
|
const existing = scoreMap.get(r.id);
|
|
37014
37063
|
if (existing) {
|
|
37015
|
-
existing.bm25 = 1 / (
|
|
37064
|
+
existing.bm25 = 1 / (RRF_K + rank + 1);
|
|
37016
37065
|
} else {
|
|
37017
|
-
scoreMap.set(r.id, { dense: 0, bm25: 1 / (
|
|
37066
|
+
scoreMap.set(r.id, { dense: 0, bm25: 1 / (RRF_K + rank + 1) });
|
|
37018
37067
|
}
|
|
37019
37068
|
});
|
|
37020
37069
|
const hasDense = this.store.vecAvailable && denseResults.length > 0;
|
|
37021
37070
|
const numRetrievers = hasDense ? 2 : 1;
|
|
37022
|
-
const maxScore = numRetrievers /
|
|
37071
|
+
const maxScore = numRetrievers / (RRF_K + 1);
|
|
37023
37072
|
const ranked = [...scoreMap.entries()].map(([id, scores]) => ({
|
|
37024
37073
|
id,
|
|
37025
37074
|
totalScore: scores.dense + scores.bm25,
|
|
@@ -37040,7 +37089,7 @@ var MemoryIndexer = class {
|
|
|
37040
37089
|
const retriever = r.hasDense && r.hasBm25 ? "both" : r.hasDense ? "dense" : "bm25";
|
|
37041
37090
|
let contentSource = "file";
|
|
37042
37091
|
try {
|
|
37043
|
-
chunk.content =
|
|
37092
|
+
chunk.content = fs6.readFileSync(path8.join(this.config.wikiDir, chunk.source), "utf8");
|
|
37044
37093
|
} catch {
|
|
37045
37094
|
contentSource = "fallback";
|
|
37046
37095
|
}
|
|
@@ -37050,26 +37099,27 @@ var MemoryIndexer = class {
|
|
|
37050
37099
|
}
|
|
37051
37100
|
async save(content) {
|
|
37052
37101
|
const datePart = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
37053
|
-
const rawDir =
|
|
37054
|
-
const savePath =
|
|
37102
|
+
const rawDir = path8.join(this.config.wikiDir, "raw");
|
|
37103
|
+
const savePath = path8.join(rawDir, `conv_save_${datePart}.md`);
|
|
37055
37104
|
const lockPath = `${savePath}.lock`;
|
|
37056
|
-
|
|
37057
|
-
const acquired = await acquireLock(lockPath);
|
|
37105
|
+
fs6.mkdirSync(rawDir, { recursive: true });
|
|
37106
|
+
const acquired = await acquireLock(lockPath, LOCK_TIMEOUT_MS, LOCK_RETRY_MS);
|
|
37058
37107
|
if (!acquired) {
|
|
37059
37108
|
console.warn("[memory-indexer] Could not acquire write lock, writing anyway (fail-open)");
|
|
37060
37109
|
}
|
|
37061
37110
|
try {
|
|
37062
|
-
|
|
37111
|
+
fs6.appendFileSync(savePath, `
|
|
37063
37112
|
${content}
|
|
37064
37113
|
`, "utf8");
|
|
37065
37114
|
} finally {
|
|
37066
|
-
if (acquired) releaseLock(lockPath);
|
|
37115
|
+
if (acquired) releaseLock(lockPath, { ignoreErrors: true });
|
|
37067
37116
|
}
|
|
37068
37117
|
return { indexed: 0, deleted: 0, skipped: 0 };
|
|
37069
37118
|
}
|
|
37070
37119
|
async startupIndex() {
|
|
37071
37120
|
try {
|
|
37072
|
-
await this.
|
|
37121
|
+
await this.embedder.initialize();
|
|
37122
|
+
await this.indexDirectory(path8.join(this.config.wikiDir, "compiled"), {
|
|
37073
37123
|
relativeBase: this.config.wikiDir,
|
|
37074
37124
|
excludeFiles: ["index.md", "log.md"]
|
|
37075
37125
|
});
|
|
@@ -37084,11 +37134,11 @@ ${content}
|
|
|
37084
37134
|
}
|
|
37085
37135
|
};
|
|
37086
37136
|
|
|
37087
|
-
// src/memory/store.ts
|
|
37137
|
+
// src/services/memory/store.ts
|
|
37088
37138
|
var import_stopword = __toESM(require_stopword_cjs(), 1);
|
|
37089
37139
|
import Database from "better-sqlite3";
|
|
37090
|
-
import * as
|
|
37091
|
-
import * as
|
|
37140
|
+
import * as fs7 from "fs";
|
|
37141
|
+
import * as path9 from "path";
|
|
37092
37142
|
var StoreError = class extends Error {
|
|
37093
37143
|
constructor(message, cause) {
|
|
37094
37144
|
super(message);
|
|
@@ -37099,7 +37149,7 @@ var StoreError = class extends Error {
|
|
|
37099
37149
|
var MemoryStore = class {
|
|
37100
37150
|
constructor(dbPath, config2) {
|
|
37101
37151
|
this.config = config2;
|
|
37102
|
-
|
|
37152
|
+
fs7.mkdirSync(path9.dirname(dbPath), { recursive: true });
|
|
37103
37153
|
this.db = this.openDatabase(dbPath);
|
|
37104
37154
|
}
|
|
37105
37155
|
db;
|
|
@@ -37115,7 +37165,7 @@ var MemoryStore = class {
|
|
|
37115
37165
|
} catch (err) {
|
|
37116
37166
|
console.error("[memory-store] DB open failed, recreating:", err);
|
|
37117
37167
|
try {
|
|
37118
|
-
|
|
37168
|
+
fs7.unlinkSync(dbPath);
|
|
37119
37169
|
} catch {
|
|
37120
37170
|
}
|
|
37121
37171
|
const db = new Database(dbPath);
|
|
@@ -37330,8 +37380,424 @@ var MemoryStore = class {
|
|
|
37330
37380
|
}
|
|
37331
37381
|
};
|
|
37332
37382
|
|
|
37333
|
-
// src/
|
|
37334
|
-
|
|
37383
|
+
// src/services/digest/processor.ts
|
|
37384
|
+
import * as fs10 from "node:fs";
|
|
37385
|
+
import * as path13 from "node:path";
|
|
37386
|
+
|
|
37387
|
+
// src/services/digest/constants.ts
|
|
37388
|
+
import * as path10 from "node:path";
|
|
37389
|
+
var DEFAULT_DIGEST_MODEL_ID = "default" /* DEFAULT */;
|
|
37390
|
+
var DEFAULT_DIGEST_MAX_INPUT_CHARS = 3e3;
|
|
37391
|
+
var DEFAULT_DIGEST_TIMEOUT_MS = 12e4;
|
|
37392
|
+
var KIT_DIR = ".agent-kit";
|
|
37393
|
+
var WIKI_DIR = path10.join(KIT_DIR, "wiki");
|
|
37394
|
+
var WIKI_RAW_DIR = path10.join(WIKI_DIR, "raw");
|
|
37395
|
+
var PROVISIONAL_DIGEST_DIR = path10.join(WIKI_DIR, "compiled", "provisional", "conversation-digests");
|
|
37396
|
+
var DIGEST_WORKER_DIR = path10.join(WIKI_DIR, "digest");
|
|
37397
|
+
var DIGEST_LOCKFILE_REL_PATH = path10.join(DIGEST_WORKER_DIR, "digest-worker.lock");
|
|
37398
|
+
var DIGEST_WORKER_STATUS_REL_PATH = path10.join(DIGEST_WORKER_DIR, "digest-worker.status.json");
|
|
37399
|
+
var DIGEST_WORKER_LOG_REL_PATH = path10.join(DIGEST_WORKER_DIR, "digest-worker.log");
|
|
37400
|
+
var LLAMA_CONTEXT_SIZE = 4096;
|
|
37401
|
+
var LLAMA_MAX_GENERATED_TOKENS = 512;
|
|
37402
|
+
var LLAMA_TEMPERATURE = 0.1;
|
|
37403
|
+
|
|
37404
|
+
// src/services/digest/files.ts
|
|
37405
|
+
import * as fs8 from "node:fs";
|
|
37406
|
+
import * as path11 from "node:path";
|
|
37407
|
+
function defaultProvisionalDigestDir(workspaceRoot2) {
|
|
37408
|
+
return path11.join(workspaceRoot2, PROVISIONAL_DIGEST_DIR);
|
|
37409
|
+
}
|
|
37410
|
+
function readConversationDigestInput(workspaceRoot2, inputPath) {
|
|
37411
|
+
const absoluteInput = path11.isAbsolute(inputPath) ? inputPath : path11.resolve(workspaceRoot2, inputPath);
|
|
37412
|
+
const content = fs8.readFileSync(absoluteInput, "utf8");
|
|
37413
|
+
return {
|
|
37414
|
+
sourcePath: path11.relative(workspaceRoot2, absoluteInput),
|
|
37415
|
+
content,
|
|
37416
|
+
contentHash: sha256Hex(content)
|
|
37417
|
+
};
|
|
37418
|
+
}
|
|
37419
|
+
function provisionalDigestPath(outDir, input) {
|
|
37420
|
+
const safeName = path11.basename(input.sourcePath).replace(/\.[^.]+$/, "").replace(/[^a-z0-9._-]+/gi, "-");
|
|
37421
|
+
return path11.join(outDir, `${input.contentHash.slice(0, 16)}-${safeName}.md`);
|
|
37422
|
+
}
|
|
37423
|
+
function findExistingProvisionalDigest(outDir, input) {
|
|
37424
|
+
const markdownPath = provisionalDigestPath(outDir, input);
|
|
37425
|
+
return fs8.existsSync(markdownPath) ? markdownPath : void 0;
|
|
37426
|
+
}
|
|
37427
|
+
function writeProvisionalDigestFile(outDir, input, markdown) {
|
|
37428
|
+
const markdownPath = provisionalDigestPath(outDir, input);
|
|
37429
|
+
atomicWriteTextFile(markdownPath, markdown);
|
|
37430
|
+
return markdownPath;
|
|
37431
|
+
}
|
|
37432
|
+
function writeConversationDigestSettings(workspaceRoot2, digest) {
|
|
37433
|
+
const current = loadProjectSettings(workspaceRoot2);
|
|
37434
|
+
const memory = current.memory ?? {};
|
|
37435
|
+
writeProjectSettings(workspaceRoot2, {
|
|
37436
|
+
memory: {
|
|
37437
|
+
...memory,
|
|
37438
|
+
enabled: memory.enabled ?? true,
|
|
37439
|
+
conversationDigest: digest
|
|
37440
|
+
}
|
|
37441
|
+
});
|
|
37442
|
+
}
|
|
37443
|
+
|
|
37444
|
+
// src/services/digest/model-registry.ts
|
|
37445
|
+
var DigestModelRegistryError = class extends Error {
|
|
37446
|
+
constructor(message) {
|
|
37447
|
+
super(message);
|
|
37448
|
+
this.name = "DigestModelRegistryError";
|
|
37449
|
+
}
|
|
37450
|
+
};
|
|
37451
|
+
var DIGEST_MODEL_REGISTRY = {
|
|
37452
|
+
["tiny" /* TINY */]: {
|
|
37453
|
+
id: "tiny" /* TINY */,
|
|
37454
|
+
ggufUri: "hf:bartowski/Qwen2.5-0.5B-Instruct-GGUF/Qwen2.5-0.5B-Instruct-Q4_K_M.gguf",
|
|
37455
|
+
approxSizeBytes: 4e8,
|
|
37456
|
+
license: "Apache-2.0",
|
|
37457
|
+
sourceUrl: "https://huggingface.co/bartowski/Qwen2.5-0.5B-Instruct-GGUF",
|
|
37458
|
+
enabled: true
|
|
37459
|
+
},
|
|
37460
|
+
["default" /* DEFAULT */]: {
|
|
37461
|
+
id: "default" /* DEFAULT */,
|
|
37462
|
+
ggufUri: "hf:bartowski/Qwen2.5-1.5B-Instruct-GGUF/Qwen2.5-1.5B-Instruct-Q4_K_M.gguf",
|
|
37463
|
+
approxSizeBytes: 1e9,
|
|
37464
|
+
license: "Apache-2.0",
|
|
37465
|
+
sourceUrl: "https://huggingface.co/bartowski/Qwen2.5-1.5B-Instruct-GGUF",
|
|
37466
|
+
enabled: true
|
|
37467
|
+
},
|
|
37468
|
+
["large" /* LARGE */]: {
|
|
37469
|
+
id: "large" /* LARGE */,
|
|
37470
|
+
ggufUri: "hf:bartowski/Qwen2.5-3B-Instruct-GGUF/Qwen2.5-3B-Instruct-Q4_K_M.gguf",
|
|
37471
|
+
approxSizeBytes: 19e8,
|
|
37472
|
+
license: "Apache-2.0",
|
|
37473
|
+
sourceUrl: "https://huggingface.co/bartowski/Qwen2.5-3B-Instruct-GGUF",
|
|
37474
|
+
enabled: true
|
|
37475
|
+
}
|
|
37476
|
+
};
|
|
37477
|
+
function getDigestModelSpec(modelId) {
|
|
37478
|
+
if (!modelId.trim()) {
|
|
37479
|
+
throw new DigestModelRegistryError("Digest model id is required");
|
|
37480
|
+
}
|
|
37481
|
+
const spec = DIGEST_MODEL_REGISTRY[modelId];
|
|
37482
|
+
if (!spec) {
|
|
37483
|
+
throw new DigestModelRegistryError(`Unknown digest model: ${modelId}`);
|
|
37484
|
+
}
|
|
37485
|
+
if (spec.enabled !== true) {
|
|
37486
|
+
throw new DigestModelRegistryError(`Digest model is disabled: ${modelId}`);
|
|
37487
|
+
}
|
|
37488
|
+
if (!spec.ggufUri || !spec.sourceUrl) {
|
|
37489
|
+
throw new DigestModelRegistryError(`Digest model spec is incomplete: ${modelId}`);
|
|
37490
|
+
}
|
|
37491
|
+
return spec;
|
|
37492
|
+
}
|
|
37493
|
+
|
|
37494
|
+
// src/services/digest/providers/llama-local.ts
|
|
37495
|
+
import * as fs9 from "node:fs";
|
|
37496
|
+
import * as path12 from "node:path";
|
|
37497
|
+
import { getLlama, LlamaChatSession, createModelDownloader } from "node-llama-cpp";
|
|
37498
|
+
|
|
37499
|
+
// src/utils/async.ts
|
|
37500
|
+
async function withTimeout(promise, timeoutMs, createError) {
|
|
37501
|
+
let timer;
|
|
37502
|
+
const timeout = new Promise((_resolve, reject) => {
|
|
37503
|
+
timer = setTimeout(() => {
|
|
37504
|
+
reject(createError());
|
|
37505
|
+
}, timeoutMs);
|
|
37506
|
+
});
|
|
37507
|
+
try {
|
|
37508
|
+
return await Promise.race([promise, timeout]);
|
|
37509
|
+
} finally {
|
|
37510
|
+
if (timer) clearTimeout(timer);
|
|
37511
|
+
}
|
|
37512
|
+
}
|
|
37513
|
+
|
|
37514
|
+
// src/services/digest/providers/llama-local.ts
|
|
37515
|
+
var LlamaLocalDigestProviderError = class extends Error {
|
|
37516
|
+
constructor(message) {
|
|
37517
|
+
super(message);
|
|
37518
|
+
this.name = "LlamaLocalDigestProviderError";
|
|
37519
|
+
}
|
|
37520
|
+
};
|
|
37521
|
+
function titleFromSource(sourcePath) {
|
|
37522
|
+
return path12.basename(sourcePath).replace(/\.[^.]+$/, "").replace(/[_-]+/g, " ");
|
|
37523
|
+
}
|
|
37524
|
+
function trimConversationExport(content, maxInputChars) {
|
|
37525
|
+
const trimmed = content.trim();
|
|
37526
|
+
if (trimmed.length <= maxInputChars) return trimmed;
|
|
37527
|
+
return [
|
|
37528
|
+
"[Earlier conversation content omitted to fit the local digest context window.]",
|
|
37529
|
+
trimmed.slice(-maxInputChars)
|
|
37530
|
+
].join("\n\n");
|
|
37531
|
+
}
|
|
37532
|
+
function buildPrompt(input, maxInputChars) {
|
|
37533
|
+
const conversationExport = trimConversationExport(input.content, maxInputChars);
|
|
37534
|
+
return [
|
|
37535
|
+
{
|
|
37536
|
+
role: "system",
|
|
37537
|
+
content: [
|
|
37538
|
+
"# ROLE",
|
|
37539
|
+
"You write short project-memory wiki pages from developer transcripts.",
|
|
37540
|
+
"Your output is temporary recall to prevent blind steps.",
|
|
37541
|
+
"",
|
|
37542
|
+
"# RULES",
|
|
37543
|
+
"1. Read the end of the export FIRST to discover the ultimate resolution.",
|
|
37544
|
+
"2. What the user says LAST ALWAYS overrides earlier agreements.",
|
|
37545
|
+
"3. Capture absolute engineering conclusions, never conversational pleasantries.",
|
|
37546
|
+
"4. Return Markdown only. Do not wrap output in code blocks (```markdown ... ```)."
|
|
37547
|
+
].join("\n")
|
|
37548
|
+
},
|
|
37549
|
+
{
|
|
37550
|
+
role: "user",
|
|
37551
|
+
content: [
|
|
37552
|
+
"Generate a high-level project memory page. STRICTLY adhere to this architectural layout:",
|
|
37553
|
+
"",
|
|
37554
|
+
"<layout>",
|
|
37555
|
+
"# Digest: " + titleFromSource(input.sourcePath),
|
|
37556
|
+
"- **Ultimate Core Resolution**: [Describe the final working state of the feature and what problem it solves in 1-2 sentences. No conversational filler.]",
|
|
37557
|
+
"- **Architectural Changes**: [List 3-4 high-level engineering decisions made (e.g., shifts in hook timing, data isolation, atomic locks). Focus on systemic changes, NOT individual files.]",
|
|
37558
|
+
"- **Component State**: [Briefly state how the Plugin side and the MCP/CLI side now interact based on the final decision.]",
|
|
37559
|
+
"- **Considered & Rejected**: [List concepts proposed but discarded (e.g., initial hooks location, mocking strategies). Omit if empty.]",
|
|
37560
|
+
"</layout>",
|
|
37561
|
+
"",
|
|
37562
|
+
"# CRITICAL RULES:",
|
|
37563
|
+
"- DO NOT list individual file paths, line numbers, or specific test cases (EXCLUDE lists of files).",
|
|
37564
|
+
"- Focus entirely on the SYSTEM DESIGN and ARCHITECTURE that the next engineer needs to know.",
|
|
37565
|
+
"- Keep output under 300 tokens. Stop immediately after the last valid section.",
|
|
37566
|
+
"",
|
|
37567
|
+
"Source path: " + input.sourcePath,
|
|
37568
|
+
'<conversation_export format="memory-kit">',
|
|
37569
|
+
conversationExport,
|
|
37570
|
+
"</conversation_export>"
|
|
37571
|
+
].join("\n")
|
|
37572
|
+
}
|
|
37573
|
+
];
|
|
37574
|
+
}
|
|
37575
|
+
function stripCodeFence(text) {
|
|
37576
|
+
const trimmed = text.trim();
|
|
37577
|
+
const match = trimmed.match(/^```(?:markdown|md)?\s*\n([\s\S]*?)\n```$/i);
|
|
37578
|
+
return match ? match[1].trim() : trimmed;
|
|
37579
|
+
}
|
|
37580
|
+
function sanitizeConversationDigestMarkdown(generatedText) {
|
|
37581
|
+
return stripCodeFence(generatedText).trim() + "\n";
|
|
37582
|
+
}
|
|
37583
|
+
async function createLlamaLocalDigestProvider(modelId) {
|
|
37584
|
+
const spec = getDigestModelSpec(modelId);
|
|
37585
|
+
const modelCacheDir = path12.join(MODEL_CACHE_DIR, "llama");
|
|
37586
|
+
fs9.mkdirSync(modelCacheDir, { recursive: true });
|
|
37587
|
+
let modelFilePath;
|
|
37588
|
+
try {
|
|
37589
|
+
const downloader = await createModelDownloader({
|
|
37590
|
+
modelUri: spec.ggufUri,
|
|
37591
|
+
dirPath: modelCacheDir
|
|
37592
|
+
});
|
|
37593
|
+
modelFilePath = downloader.entrypointFilePath;
|
|
37594
|
+
if (!fs9.existsSync(modelFilePath)) {
|
|
37595
|
+
await downloader.download();
|
|
37596
|
+
}
|
|
37597
|
+
} catch (err) {
|
|
37598
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
37599
|
+
throw new LlamaLocalDigestProviderError(`Failed to download model: ${message}`);
|
|
37600
|
+
}
|
|
37601
|
+
let llama;
|
|
37602
|
+
let model;
|
|
37603
|
+
try {
|
|
37604
|
+
llama = await getLlama();
|
|
37605
|
+
model = await llama.loadModel({ modelPath: modelFilePath });
|
|
37606
|
+
} catch (err) {
|
|
37607
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
37608
|
+
throw new LlamaLocalDigestProviderError(`Failed to load model: ${message}`);
|
|
37609
|
+
}
|
|
37610
|
+
return {
|
|
37611
|
+
id: "llama-local",
|
|
37612
|
+
async dispose() {
|
|
37613
|
+
await model.dispose();
|
|
37614
|
+
},
|
|
37615
|
+
async generateDigestMarkdown(input, options) {
|
|
37616
|
+
const messages = buildPrompt(input, options.maxInputChars);
|
|
37617
|
+
const systemContent = messages[0].content;
|
|
37618
|
+
const userContent = messages[1].content;
|
|
37619
|
+
const context = await model.createContext({ contextSize: LLAMA_CONTEXT_SIZE });
|
|
37620
|
+
try {
|
|
37621
|
+
const session = new LlamaChatSession({
|
|
37622
|
+
contextSequence: context.getSequence(),
|
|
37623
|
+
systemPrompt: systemContent
|
|
37624
|
+
});
|
|
37625
|
+
const response = await withTimeout(
|
|
37626
|
+
session.prompt(userContent, {
|
|
37627
|
+
maxTokens: LLAMA_MAX_GENERATED_TOKENS,
|
|
37628
|
+
temperature: LLAMA_TEMPERATURE
|
|
37629
|
+
}),
|
|
37630
|
+
options.timeoutMs,
|
|
37631
|
+
() => new LlamaLocalDigestProviderError(`Llama provider timed out after ${options.timeoutMs}ms`)
|
|
37632
|
+
);
|
|
37633
|
+
return sanitizeConversationDigestMarkdown(response);
|
|
37634
|
+
} finally {
|
|
37635
|
+
await context.dispose();
|
|
37636
|
+
}
|
|
37637
|
+
}
|
|
37638
|
+
};
|
|
37639
|
+
}
|
|
37640
|
+
|
|
37641
|
+
// src/services/digest/processor.ts
|
|
37642
|
+
function digestLockPath(workspaceRoot2) {
|
|
37643
|
+
return path13.join(workspaceRoot2, DIGEST_LOCKFILE_REL_PATH);
|
|
37644
|
+
}
|
|
37645
|
+
function discoverPendingConversationFiles(workspaceRoot2) {
|
|
37646
|
+
const rawDir = path13.join(workspaceRoot2, WIKI_RAW_DIR);
|
|
37647
|
+
let files;
|
|
37648
|
+
try {
|
|
37649
|
+
files = fs10.readdirSync(rawDir).filter((f) => f.startsWith("conv_") && f.endsWith(".md")).map((f) => path13.join(rawDir, f)).sort((a, b) => fs10.statSync(a).mtimeMs - fs10.statSync(b).mtimeMs);
|
|
37650
|
+
} catch (err) {
|
|
37651
|
+
if (err.code === "ENOENT") {
|
|
37652
|
+
files = [];
|
|
37653
|
+
} else {
|
|
37654
|
+
throw err;
|
|
37655
|
+
}
|
|
37656
|
+
}
|
|
37657
|
+
const outDir = defaultProvisionalDigestDir(workspaceRoot2);
|
|
37658
|
+
return files.filter((f) => {
|
|
37659
|
+
try {
|
|
37660
|
+
const input = readConversationDigestInput(workspaceRoot2, f);
|
|
37661
|
+
return !findExistingProvisionalDigest(outDir, input);
|
|
37662
|
+
} catch {
|
|
37663
|
+
return false;
|
|
37664
|
+
}
|
|
37665
|
+
});
|
|
37666
|
+
}
|
|
37667
|
+
async function indexProvisionalDigestFile(workspaceRoot2, markdownPath) {
|
|
37668
|
+
try {
|
|
37669
|
+
const settings2 = loadProjectSettings(workspaceRoot2);
|
|
37670
|
+
const config2 = resolveMemoryConfig(settings2, workspaceRoot2);
|
|
37671
|
+
const store = new MemoryStore(path13.join(config2.wikiDir, "index.db"), config2);
|
|
37672
|
+
const embedder = { embed: async (_texts) => [], initialize: async () => {
|
|
37673
|
+
} };
|
|
37674
|
+
const indexer = new MemoryIndexer(store, embedder, config2);
|
|
37675
|
+
await indexer.indexFile(markdownPath);
|
|
37676
|
+
return { indexed: true };
|
|
37677
|
+
} catch (err) {
|
|
37678
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
37679
|
+
return { indexed: false, error: message };
|
|
37680
|
+
}
|
|
37681
|
+
}
|
|
37682
|
+
async function digestConversationFile(options) {
|
|
37683
|
+
const outDir = options.outDir ? path13.resolve(options.workspaceRoot, options.outDir) : defaultProvisionalDigestDir(options.workspaceRoot);
|
|
37684
|
+
const input = readConversationDigestInput(options.workspaceRoot, options.inputPath);
|
|
37685
|
+
const existingPath = findExistingProvisionalDigest(outDir, input);
|
|
37686
|
+
if (existingPath) {
|
|
37687
|
+
const indexResult = await indexProvisionalDigestFile(options.workspaceRoot, existingPath);
|
|
37688
|
+
return {
|
|
37689
|
+
markdown: existingPath,
|
|
37690
|
+
status: "provisional",
|
|
37691
|
+
contentHash: input.contentHash,
|
|
37692
|
+
skipped: true,
|
|
37693
|
+
...indexResult
|
|
37694
|
+
};
|
|
37695
|
+
}
|
|
37696
|
+
const provider = await createLlamaLocalDigestProvider(options.modelId);
|
|
37697
|
+
try {
|
|
37698
|
+
const markdown = await provider.generateDigestMarkdown(input, {
|
|
37699
|
+
modelId: options.modelId,
|
|
37700
|
+
maxInputChars: options.maxInputChars ?? DEFAULT_DIGEST_MAX_INPUT_CHARS,
|
|
37701
|
+
timeoutMs: options.timeoutMs ?? DEFAULT_DIGEST_TIMEOUT_MS
|
|
37702
|
+
});
|
|
37703
|
+
const markdownPath = writeProvisionalDigestFile(outDir, input, markdown);
|
|
37704
|
+
const indexResult = await indexProvisionalDigestFile(options.workspaceRoot, markdownPath);
|
|
37705
|
+
return {
|
|
37706
|
+
markdown: markdownPath,
|
|
37707
|
+
status: "provisional",
|
|
37708
|
+
contentHash: input.contentHash,
|
|
37709
|
+
skipped: false,
|
|
37710
|
+
...indexResult
|
|
37711
|
+
};
|
|
37712
|
+
} finally {
|
|
37713
|
+
await provider.dispose?.();
|
|
37714
|
+
}
|
|
37715
|
+
}
|
|
37716
|
+
async function digestPendingConversations({
|
|
37717
|
+
workspaceRoot: workspaceRoot2,
|
|
37718
|
+
digestFn = digestConversationFile,
|
|
37719
|
+
onProgress
|
|
37720
|
+
}) {
|
|
37721
|
+
const digestConfig = resolveConversationDigestConfig(loadProjectSettings(workspaceRoot2));
|
|
37722
|
+
if (!digestConfig || digestConfig.enabled === false) {
|
|
37723
|
+
return { ok: true, initialized: false, action: "noop", reason: "not-initialized" };
|
|
37724
|
+
}
|
|
37725
|
+
const lockPath = digestLockPath(workspaceRoot2);
|
|
37726
|
+
if (!tryAcquireProcessLock(lockPath)) {
|
|
37727
|
+
return { ok: true, initialized: true, action: "noop", reason: "locked" };
|
|
37728
|
+
}
|
|
37729
|
+
try {
|
|
37730
|
+
const candidates = discoverPendingConversationFiles(workspaceRoot2);
|
|
37731
|
+
if (candidates.length === 0) {
|
|
37732
|
+
return { ok: true, initialized: true, action: "noop", reason: "no-pending" };
|
|
37733
|
+
}
|
|
37734
|
+
let count = 0;
|
|
37735
|
+
let skipped = 0;
|
|
37736
|
+
let errors = 0;
|
|
37737
|
+
for (const filePath of candidates) {
|
|
37738
|
+
try {
|
|
37739
|
+
const result = await digestFn({
|
|
37740
|
+
workspaceRoot: workspaceRoot2,
|
|
37741
|
+
inputPath: filePath,
|
|
37742
|
+
modelId: digestConfig.modelId
|
|
37743
|
+
});
|
|
37744
|
+
if (result.skipped) {
|
|
37745
|
+
skipped++;
|
|
37746
|
+
} else {
|
|
37747
|
+
count++;
|
|
37748
|
+
}
|
|
37749
|
+
} catch {
|
|
37750
|
+
errors++;
|
|
37751
|
+
}
|
|
37752
|
+
if (onProgress) {
|
|
37753
|
+
await onProgress({ processed: count, skipped, errors });
|
|
37754
|
+
}
|
|
37755
|
+
}
|
|
37756
|
+
return { ok: true, initialized: true, action: "digested", count, skipped, errors };
|
|
37757
|
+
} catch (err) {
|
|
37758
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
37759
|
+
return { ok: false, initialized: true, action: "error", error: message };
|
|
37760
|
+
} finally {
|
|
37761
|
+
releaseLock(lockPath);
|
|
37762
|
+
}
|
|
37763
|
+
}
|
|
37764
|
+
async function initializeConversationDigestModel(input) {
|
|
37765
|
+
try {
|
|
37766
|
+
getDigestModelSpec(input.modelId);
|
|
37767
|
+
if (input.allowDownload !== true) {
|
|
37768
|
+
return {
|
|
37769
|
+
initialized: false,
|
|
37770
|
+
modelId: input.modelId,
|
|
37771
|
+
error: "Digest model initialization requires explicit download permission"
|
|
37772
|
+
};
|
|
37773
|
+
}
|
|
37774
|
+
const loadedProvider = await createLlamaLocalDigestProvider(input.modelId);
|
|
37775
|
+
await loadedProvider?.dispose?.();
|
|
37776
|
+
const initializedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
37777
|
+
writeConversationDigestSettings(input.workspaceRoot, {
|
|
37778
|
+
enabled: input.enabled ?? true,
|
|
37779
|
+
initialized: true,
|
|
37780
|
+
modelId: input.modelId,
|
|
37781
|
+
initializedAt
|
|
37782
|
+
});
|
|
37783
|
+
await digestPendingConversations({ workspaceRoot: input.workspaceRoot });
|
|
37784
|
+
return {
|
|
37785
|
+
initialized: true,
|
|
37786
|
+
modelId: input.modelId,
|
|
37787
|
+
initializedAt
|
|
37788
|
+
};
|
|
37789
|
+
} catch (err) {
|
|
37790
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
37791
|
+
return {
|
|
37792
|
+
initialized: false,
|
|
37793
|
+
modelId: input.modelId,
|
|
37794
|
+
error: message
|
|
37795
|
+
};
|
|
37796
|
+
}
|
|
37797
|
+
}
|
|
37798
|
+
|
|
37799
|
+
// src/mcp/memory.ts
|
|
37800
|
+
function registerMemoryToolHandlers(server2, indexer, store, config2, workspaceRoot2 = process.cwd()) {
|
|
37335
37801
|
server2.tool(
|
|
37336
37802
|
"kit_memory_search",
|
|
37337
37803
|
"Search persistent memory for context relevant to the current question. Returns semantically relevant results using hybrid dense+BM25+RRF search.",
|
|
@@ -37381,18 +37847,48 @@ ${content}`;
|
|
|
37381
37847
|
}
|
|
37382
37848
|
}
|
|
37383
37849
|
);
|
|
37850
|
+
server2.tool(
|
|
37851
|
+
"kit_memory_digest_init",
|
|
37852
|
+
"Initialize or toggle local conversation digesting. Downloads/cache-loads the pinned local model only when explicitly invoked.",
|
|
37853
|
+
{
|
|
37854
|
+
model_id: external_exports.string().optional().describe("Digest model id"),
|
|
37855
|
+
enabled: external_exports.boolean().optional().describe("Enable or disable conversation digesting")
|
|
37856
|
+
},
|
|
37857
|
+
async ({ model_id, enabled }) => {
|
|
37858
|
+
try {
|
|
37859
|
+
const existingConfig = resolveConversationDigestConfig(loadProjectSettings(workspaceRoot2));
|
|
37860
|
+
const result = await initializeConversationDigestModel({
|
|
37861
|
+
workspaceRoot: workspaceRoot2,
|
|
37862
|
+
modelId: model_id ?? existingConfig?.modelId ?? DEFAULT_DIGEST_MODEL_ID,
|
|
37863
|
+
allowDownload: true,
|
|
37864
|
+
enabled
|
|
37865
|
+
});
|
|
37866
|
+
return mcpJson({
|
|
37867
|
+
initialized: result.initialized,
|
|
37868
|
+
model_id: result.modelId,
|
|
37869
|
+
initialized_at: result.initializedAt,
|
|
37870
|
+
error: result.error
|
|
37871
|
+
});
|
|
37872
|
+
} catch (err) {
|
|
37873
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
37874
|
+
return mcpJson({ initialized: false, error: message });
|
|
37875
|
+
}
|
|
37876
|
+
}
|
|
37877
|
+
);
|
|
37384
37878
|
}
|
|
37385
|
-
function registerMemoryTools(server2, settings2, workspaceRoot2) {
|
|
37879
|
+
function registerMemoryTools(server2, settings2, workspaceRoot2, overrides) {
|
|
37386
37880
|
if (settings2.memory?.enabled !== true) return null;
|
|
37387
|
-
const config2 = resolveMemoryConfig(settings2, workspaceRoot2);
|
|
37388
|
-
const store = new MemoryStore(
|
|
37389
|
-
const
|
|
37390
|
-
|
|
37391
|
-
|
|
37881
|
+
const config2 = overrides?.config ?? resolveMemoryConfig(settings2, workspaceRoot2);
|
|
37882
|
+
const store = overrides?.store ?? new MemoryStore(path14.join(config2.wikiDir, "index.db"), config2);
|
|
37883
|
+
const indexer = overrides?.indexer ?? (() => {
|
|
37884
|
+
const embedder = new Embedder(config2.embeddingModel);
|
|
37885
|
+
return new MemoryIndexer(store, embedder, config2);
|
|
37886
|
+
})();
|
|
37887
|
+
registerMemoryToolHandlers(server2, indexer, store, config2, workspaceRoot2);
|
|
37392
37888
|
return indexer;
|
|
37393
37889
|
}
|
|
37394
37890
|
|
|
37395
|
-
// src/
|
|
37891
|
+
// src/entrypoints/server.ts
|
|
37396
37892
|
var server = new McpServer({
|
|
37397
37893
|
name: "kit-agents",
|
|
37398
37894
|
version: "1.0.0"
|