@massa-ai/tools-api 1.9.0 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +174 -14
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -938,6 +938,20 @@ function validateCapturePolicyConfig(raw2) {
|
|
|
938
938
|
...p.maxIgnorePatterns !== undefined && { maxIgnorePatterns: p.maxIgnorePatterns }
|
|
939
939
|
};
|
|
940
940
|
}
|
|
941
|
+
function validateAllowedExtensionsConfig(raw2) {
|
|
942
|
+
if (!Array.isArray(raw2)) {
|
|
943
|
+
throw new TypeError("security.allowedExtensions must be an array of strings");
|
|
944
|
+
}
|
|
945
|
+
if (raw2.length === 0) {
|
|
946
|
+
throw new TypeError("security.allowedExtensions must not be empty \u2014 an empty allow-list indexes nothing; omit the key to use the defaults");
|
|
947
|
+
}
|
|
948
|
+
for (const ext of raw2) {
|
|
949
|
+
if (typeof ext !== "string" || !ext.startsWith(".") || ext.length < 2) {
|
|
950
|
+
throw new TypeError(`security.allowedExtensions[] must be dot-prefixed extensions (got ${JSON.stringify(ext)})`);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
return [...raw2];
|
|
954
|
+
}
|
|
941
955
|
function getGlobalDataDir() {
|
|
942
956
|
const envOverride = process.env.MASSA_AI_DATA_DIR;
|
|
943
957
|
if (envOverride && envOverride.trim())
|
|
@@ -1233,7 +1247,7 @@ var init_config = __esm(() => {
|
|
|
1233
1247
|
sanitizeInputs: process.env.SANITIZE_INPUTS !== "false",
|
|
1234
1248
|
maxIndexSize: 1e5,
|
|
1235
1249
|
maxFileSize: 1024 * 1024,
|
|
1236
|
-
allowedExtensions: [...DEFAULT_ALLOWED_EXTENSIONS],
|
|
1250
|
+
allowedExtensions: fileConfig.security?.allowedExtensions ? validateAllowedExtensionsConfig(fileConfig.security.allowedExtensions) : [...DEFAULT_ALLOWED_EXTENSIONS],
|
|
1237
1251
|
excludePatterns: [
|
|
1238
1252
|
"node_modules/**",
|
|
1239
1253
|
".git/**",
|
|
@@ -106605,14 +106619,140 @@ var require_ignore = __commonJS((exports, module) => {
|
|
|
106605
106619
|
});
|
|
106606
106620
|
|
|
106607
106621
|
// ../../packages/core/dist/services/search/capture-policy.js
|
|
106608
|
-
|
|
106622
|
+
function globToRegex(pattern) {
|
|
106623
|
+
let re = "^";
|
|
106624
|
+
let i = 0;
|
|
106625
|
+
while (i < pattern.length) {
|
|
106626
|
+
const ch = pattern[i];
|
|
106627
|
+
if (ch === "*") {
|
|
106628
|
+
if (pattern[i + 1] === "*") {
|
|
106629
|
+
re += ".*";
|
|
106630
|
+
i += 2;
|
|
106631
|
+
if (pattern[i] === "/")
|
|
106632
|
+
i += 1;
|
|
106633
|
+
} else {
|
|
106634
|
+
re += "[^/]*";
|
|
106635
|
+
i += 1;
|
|
106636
|
+
}
|
|
106637
|
+
} else if (ch === "?") {
|
|
106638
|
+
re += "[^/]";
|
|
106639
|
+
i += 1;
|
|
106640
|
+
} else if (ch === ".") {
|
|
106641
|
+
re += "\\.";
|
|
106642
|
+
i += 1;
|
|
106643
|
+
} else if ("+()^${}|[]\\".includes(ch)) {
|
|
106644
|
+
re += "\\" + ch;
|
|
106645
|
+
i += 1;
|
|
106646
|
+
} else {
|
|
106647
|
+
re += ch;
|
|
106648
|
+
i += 1;
|
|
106649
|
+
}
|
|
106650
|
+
}
|
|
106651
|
+
re += "$";
|
|
106652
|
+
return new RegExp(re);
|
|
106653
|
+
}
|
|
106654
|
+
function validatePolicy(policy, opts = {}) {
|
|
106655
|
+
if (!policy || typeof policy !== "object")
|
|
106656
|
+
throw new TypeError("policy must be an object");
|
|
106657
|
+
const p = policy;
|
|
106658
|
+
const allowedKeys = new Set(["rules", "maxMatchWork", "maxIgnorePatterns"]);
|
|
106659
|
+
if (opts.denyUnknownFields) {
|
|
106660
|
+
for (const key of Object.keys(p)) {
|
|
106661
|
+
if (!allowedKeys.has(key)) {
|
|
106662
|
+
throw new TypeError(`policy: unknown field "${key}" (denyUnknownFields=true)`);
|
|
106663
|
+
}
|
|
106664
|
+
}
|
|
106665
|
+
}
|
|
106666
|
+
if (!Array.isArray(p.rules))
|
|
106667
|
+
throw new TypeError("policy.rules must be an array");
|
|
106668
|
+
const dropCount = p.rules.filter((r2) => r2?.disposition === "Drop").length;
|
|
106669
|
+
const maxIgnore = typeof p.maxIgnorePatterns === "number" ? p.maxIgnorePatterns : MAX_IGNORE_PATTERNS2;
|
|
106670
|
+
if (dropCount > maxIgnore) {
|
|
106671
|
+
throw new TypeError(`policy: ${dropCount} Drop rules exceed maxIgnorePatterns=${maxIgnore}`);
|
|
106672
|
+
}
|
|
106673
|
+
if (p.maxMatchWork !== undefined) {
|
|
106674
|
+
if (typeof p.maxMatchWork !== "number" || p.maxMatchWork < 0) {
|
|
106675
|
+
throw new TypeError("policy.maxMatchWork must be a non-negative number");
|
|
106676
|
+
}
|
|
106677
|
+
}
|
|
106678
|
+
}
|
|
106679
|
+
function matchesGlob(path8, pattern) {
|
|
106680
|
+
let re = regexCache.get(pattern);
|
|
106681
|
+
if (!re) {
|
|
106682
|
+
re = globToRegex(pattern);
|
|
106683
|
+
regexCache.set(pattern, re);
|
|
106684
|
+
}
|
|
106685
|
+
return re.test(path8);
|
|
106686
|
+
}
|
|
106687
|
+
var MAX_MATCH_WORK = 1e5, MAX_IGNORE_PATTERNS2 = 1024, DEFAULT_POLICY, applyPolicy = (filePath, policy) => {
|
|
106688
|
+
const normalized = filePath.trim();
|
|
106689
|
+
for (const rule of policy.rules) {
|
|
106690
|
+
if (matchesGlob(normalized, rule.pattern))
|
|
106691
|
+
return rule.disposition;
|
|
106692
|
+
}
|
|
106693
|
+
return "Keep";
|
|
106694
|
+
}, regexCache;
|
|
106609
106695
|
var init_capture_policy = __esm(() => {
|
|
106696
|
+
DEFAULT_POLICY = {
|
|
106697
|
+
rules: [
|
|
106698
|
+
{ pattern: "**/node_modules/**", disposition: "Drop" },
|
|
106699
|
+
{ pattern: "**/.git/**", disposition: "Drop" },
|
|
106700
|
+
{ pattern: "**/dist/**", disposition: "Drop" },
|
|
106701
|
+
{ pattern: "**/build/**", disposition: "Drop" },
|
|
106702
|
+
{ pattern: "**/coverage/**", disposition: "Drop" },
|
|
106703
|
+
{ pattern: ".env", disposition: "Drop" },
|
|
106704
|
+
{ pattern: ".env.*", disposition: "Drop" },
|
|
106705
|
+
{ pattern: "**/generated/**", disposition: "Drop" },
|
|
106706
|
+
{ pattern: "**/*.generated.*", disposition: "Drop" },
|
|
106707
|
+
{ pattern: "**/*.d.ts", disposition: "Drop" },
|
|
106708
|
+
{ pattern: "**/__tests__/**", disposition: "Drop" },
|
|
106709
|
+
{ pattern: "**/tests/**", disposition: "Drop" },
|
|
106710
|
+
{ pattern: "**/*.test.ts", disposition: "Drop" },
|
|
106711
|
+
{ pattern: "**/*.test.tsx", disposition: "Drop" },
|
|
106712
|
+
{ pattern: "**/*.test.js", disposition: "Drop" },
|
|
106713
|
+
{ pattern: "**/*.test.jsx", disposition: "Drop" },
|
|
106714
|
+
{ pattern: "**/*.spec.ts", disposition: "Drop" },
|
|
106715
|
+
{ pattern: "**/*.spec.tsx", disposition: "Drop" },
|
|
106716
|
+
{ pattern: "**/*.spec.js", disposition: "Drop" },
|
|
106717
|
+
{ pattern: "**/*.spec.jsx", disposition: "Drop" },
|
|
106718
|
+
{ pattern: "**/benchmarks/**", disposition: "Drop" },
|
|
106719
|
+
{ pattern: "**/fixtures/**", disposition: "Drop" },
|
|
106720
|
+
{ pattern: "**/*.wasm*", disposition: "Drop" },
|
|
106721
|
+
{ pattern: "**/*.min.*", disposition: "Drop" },
|
|
106722
|
+
{ pattern: "**/*.map", disposition: "Drop" },
|
|
106723
|
+
{ pattern: "**/lock.yaml", disposition: "Drop" },
|
|
106724
|
+
{ pattern: "**/pnpm-lock.yaml", disposition: "Drop" },
|
|
106725
|
+
{ pattern: "**/package-lock.json", disposition: "Drop" },
|
|
106726
|
+
{ pattern: "**/bun.lockb", disposition: "Drop" },
|
|
106727
|
+
{ pattern: "**/yarn.lock", disposition: "Drop" }
|
|
106728
|
+
],
|
|
106729
|
+
maxMatchWork: MAX_MATCH_WORK,
|
|
106730
|
+
maxIgnorePatterns: MAX_IGNORE_PATTERNS2
|
|
106731
|
+
};
|
|
106610
106732
|
regexCache = new Map;
|
|
106611
106733
|
});
|
|
106612
106734
|
|
|
106613
106735
|
// ../../packages/core/dist/services/search/ignore-patterns.js
|
|
106614
106736
|
import fs3 from "fs/promises";
|
|
106615
106737
|
import path8 from "path";
|
|
106738
|
+
function buildExtensionGlob(extensions2) {
|
|
106739
|
+
return extensions2.map((ext2) => `**/*${ext2}`);
|
|
106740
|
+
}
|
|
106741
|
+
function getActivePolicy() {
|
|
106742
|
+
if (cachedPolicy)
|
|
106743
|
+
return cachedPolicy;
|
|
106744
|
+
const fromConfig = config.get("capturePolicy");
|
|
106745
|
+
if (!fromConfig) {
|
|
106746
|
+
cachedPolicy = DEFAULT_POLICY;
|
|
106747
|
+
return cachedPolicy;
|
|
106748
|
+
}
|
|
106749
|
+
validatePolicy(fromConfig, { denyUnknownFields: true });
|
|
106750
|
+
cachedPolicy = fromConfig;
|
|
106751
|
+
return cachedPolicy;
|
|
106752
|
+
}
|
|
106753
|
+
function getActiveCapturePolicy() {
|
|
106754
|
+
return getActivePolicy();
|
|
106755
|
+
}
|
|
106616
106756
|
async function loadProjectIgnore(projectPath) {
|
|
106617
106757
|
const ig = ignore();
|
|
106618
106758
|
ig.add(DEFAULT_IGNORES);
|
|
@@ -106631,7 +106771,7 @@ async function loadProjectIgnore(projectPath) {
|
|
|
106631
106771
|
}
|
|
106632
106772
|
return ig;
|
|
106633
106773
|
}
|
|
106634
|
-
var import_ignore3, ignore, DEFAULT_EXTENSIONS, DEFAULT_IGNORES;
|
|
106774
|
+
var import_ignore3, ignore, DEFAULT_EXTENSIONS, DEFAULT_IGNORES, cachedPolicy;
|
|
106635
106775
|
var init_ignore_patterns = __esm(() => {
|
|
106636
106776
|
init_dist();
|
|
106637
106777
|
init_capture_policy();
|
|
@@ -106923,9 +107063,9 @@ class IndexManager {
|
|
|
106923
107063
|
try {
|
|
106924
107064
|
const securityConfig = config.get("security");
|
|
106925
107065
|
const allowedExtensions = securityConfig.allowedExtensions || DEFAULT_ALLOWED_EXTENSIONS;
|
|
106926
|
-
const
|
|
107066
|
+
const patterns = buildExtensionGlob(allowedExtensions);
|
|
106927
107067
|
const ig = await this.loadGitignore(projectPath);
|
|
106928
|
-
const matches = await globAsync(
|
|
107068
|
+
const matches = await globAsync(patterns, {
|
|
106929
107069
|
cwd: projectPath,
|
|
106930
107070
|
nodir: true,
|
|
106931
107071
|
dot: false
|
|
@@ -111224,7 +111364,7 @@ async function _indexProjectInternalImpl(rlm, projectPath, projectId, options =
|
|
|
111224
111364
|
];
|
|
111225
111365
|
try {
|
|
111226
111366
|
const ig = await loadGitignoreImpl(projectPath);
|
|
111227
|
-
const files = await globAsync2(
|
|
111367
|
+
const files = await globAsync2(buildExtensionGlob(allowedExtensions), {
|
|
111228
111368
|
cwd: projectPath,
|
|
111229
111369
|
absolute: true,
|
|
111230
111370
|
nodir: true,
|
|
@@ -111676,6 +111816,9 @@ class MemoryRepositoryPg {
|
|
|
111676
111816
|
if (filters.types && filters.types.length > 0) {
|
|
111677
111817
|
conditions.push(import_prisma2.Prisma.sql`type = ANY(${filters.types}::text[])`);
|
|
111678
111818
|
}
|
|
111819
|
+
if (filters.includePersistent === false) {
|
|
111820
|
+
conditions.push(import_prisma2.Prisma.sql`level <> ${MemoryLevel.PERSISTENT}`);
|
|
111821
|
+
}
|
|
111679
111822
|
const whereClause = import_prisma2.Prisma.sql`WHERE ${import_prisma2.Prisma.join(conditions, " AND ")}`;
|
|
111680
111823
|
const rows = await this.prisma.$queryRaw`
|
|
111681
111824
|
SELECT id, content, type, level,
|
|
@@ -111710,6 +111853,8 @@ class MemoryRepositoryPg {
|
|
|
111710
111853
|
conditions.push(import_prisma2.Prisma.sql`importance >= ${filters.minImportance}`);
|
|
111711
111854
|
if (filters?.types && filters.types.length > 0)
|
|
111712
111855
|
conditions.push(import_prisma2.Prisma.sql`type = ANY(${filters.types}::text[])`);
|
|
111856
|
+
if (filters?.includePersistent === false)
|
|
111857
|
+
conditions.push(import_prisma2.Prisma.sql`level <> ${MemoryLevel.PERSISTENT}`);
|
|
111713
111858
|
const whereClause = import_prisma2.Prisma.sql`WHERE ${import_prisma2.Prisma.join(conditions, " AND ")}
|
|
111714
111859
|
AND NOT EXISTS (
|
|
111715
111860
|
SELECT 1 FROM memory_edges me
|
|
@@ -115957,20 +116102,21 @@ class DiscoverStage {
|
|
|
115957
116102
|
payload: { projectId: ctx.projectId, projectPath: ctx.projectPath },
|
|
115958
116103
|
timestamp: Date.now()
|
|
115959
116104
|
});
|
|
115960
|
-
const
|
|
116105
|
+
const includeTests = opts.includeTests ?? false;
|
|
116106
|
+
const ig = await this.loadIgnore(ctx.projectPath, includeTests);
|
|
116107
|
+
const policy = this.loadPolicy(includeTests);
|
|
115961
116108
|
const allowedExts = config.get("security").allowedExtensions ?? DEFAULT_EXTENSIONS;
|
|
115962
116109
|
let relPaths;
|
|
115963
116110
|
if (opts.filesToProcess && opts.filesToProcess.length > 0) {
|
|
115964
116111
|
relPaths = opts.filesToProcess;
|
|
115965
116112
|
} else {
|
|
115966
|
-
const
|
|
115967
|
-
const found = await glob(pattern, {
|
|
116113
|
+
const found = await glob(buildExtensionGlob(allowedExts), {
|
|
115968
116114
|
cwd: ctx.projectPath,
|
|
115969
116115
|
nodir: true,
|
|
115970
116116
|
dot: false,
|
|
115971
116117
|
absolute: false
|
|
115972
116118
|
});
|
|
115973
|
-
relPaths = found.map((p) => path11.isAbsolute(p) ? path11.relative(ctx.projectPath, p) : p).filter((p) => !ig.ignores(p));
|
|
116119
|
+
relPaths = found.map((p) => path11.isAbsolute(p) ? path11.relative(ctx.projectPath, p) : p).filter((p) => !ig.ignores(p) && applyPolicy(p, policy) !== "Drop");
|
|
115974
116120
|
}
|
|
115975
116121
|
if (ctx.resumeCursor?.path) {
|
|
115976
116122
|
const cursorPath = ctx.resumeCursor.path;
|
|
@@ -116056,6 +116202,15 @@ class DiscoverStage {
|
|
|
116056
116202
|
throw new Error(`required_file_unreadable:${relativePath}:${err.message}`);
|
|
116057
116203
|
}
|
|
116058
116204
|
}
|
|
116205
|
+
loadPolicy(includeTests) {
|
|
116206
|
+
const policy = getActiveCapturePolicy();
|
|
116207
|
+
if (!includeTests)
|
|
116208
|
+
return policy;
|
|
116209
|
+
return {
|
|
116210
|
+
...policy,
|
|
116211
|
+
rules: policy.rules.filter((rule) => !(rule.disposition === "Drop" && TEST_IGNORE_PATTERNS.has(rule.pattern)))
|
|
116212
|
+
};
|
|
116213
|
+
}
|
|
116059
116214
|
async loadIgnore(projectPath, includeTests) {
|
|
116060
116215
|
if (!includeTests)
|
|
116061
116216
|
return loadProjectIgnore(projectPath);
|
|
@@ -116081,6 +116236,7 @@ var init_discover = __esm(() => {
|
|
|
116081
116236
|
init_dist();
|
|
116082
116237
|
init_symbol_repository_factory();
|
|
116083
116238
|
init_ignore_patterns();
|
|
116239
|
+
init_capture_policy();
|
|
116084
116240
|
import_ignore4 = __toESM(require_ignore(), 1);
|
|
116085
116241
|
ignore2 = import_ignore4.default.default ?? import_ignore4.default;
|
|
116086
116242
|
TEST_IGNORE_PATTERNS = new Set([
|
|
@@ -118910,19 +119066,22 @@ class StructuralResolverRegistry {
|
|
|
118910
119066
|
return resolver;
|
|
118911
119067
|
}
|
|
118912
119068
|
}
|
|
119069
|
+
function declarationGroupKey(file3, qualifiedName) {
|
|
119070
|
+
return `${file3}\x00${qualifiedName}`;
|
|
119071
|
+
}
|
|
118913
119072
|
function buildStructuralResolverDefinitions(documents) {
|
|
118914
119073
|
const groups = new Map;
|
|
118915
119074
|
const exportedRoots = new Set;
|
|
118916
119075
|
for (const document2 of documents)
|
|
118917
119076
|
for (const symbol27 of document2.structure.symbols) {
|
|
118918
|
-
const key =
|
|
119077
|
+
const key = declarationGroupKey(document2.file, symbol27.qualifiedName);
|
|
118919
119078
|
groups.set(key, (groups.get(key) ?? 0) + 1);
|
|
118920
119079
|
if (symbol27.exported && symbol27.qualifiedName === symbol27.name) {
|
|
118921
119080
|
exportedRoots.add(`${document2.file}\x00${symbol27.qualifiedName.split(".")[0]}`);
|
|
118922
119081
|
}
|
|
118923
119082
|
}
|
|
118924
119083
|
return Object.freeze(documents.flatMap((document2) => document2.structure.symbols.map((symbol27) => {
|
|
118925
|
-
const key =
|
|
119084
|
+
const key = declarationGroupKey(document2.file, symbol27.qualifiedName);
|
|
118926
119085
|
const visibleNested = document2.dialect === "java" ? symbol27.signatureMaterial.modifiers.includes("public") && (["class", "interface", "enum"].includes(symbol27.kind) || symbol27.signatureMaterial.modifiers.includes("static")) : !symbol27.signatureMaterial.modifiers.includes("private");
|
|
118927
119086
|
const isExportMarker = symbol27.kind === "export";
|
|
118928
119087
|
return Object.freeze({
|
|
@@ -123959,7 +124118,7 @@ class MemoryController {
|
|
|
123959
124118
|
types: types6,
|
|
123960
124119
|
minImportance = 0.3,
|
|
123961
124120
|
limit = 10,
|
|
123962
|
-
includePersistent
|
|
124121
|
+
includePersistent = true,
|
|
123963
124122
|
includeRelated = false
|
|
123964
124123
|
} = input;
|
|
123965
124124
|
logger.info("Searching memories", {
|
|
@@ -123977,7 +124136,8 @@ class MemoryController {
|
|
|
123977
124136
|
projectId,
|
|
123978
124137
|
agentId,
|
|
123979
124138
|
minImportance,
|
|
123980
|
-
types: types6
|
|
124139
|
+
types: types6,
|
|
124140
|
+
includePersistent
|
|
123981
124141
|
});
|
|
123982
124142
|
logger.info("FTS search completed", {
|
|
123983
124143
|
foundResults: ftsRows.length,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@massa-ai/tools-api",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"author": "luizgmassa",
|
|
5
5
|
"description": "massa-ai REST API server - Semantic code search, memory, and context compression",
|
|
6
6
|
"type": "module",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"test": "bun scripts/run-tests-isolated.ts"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@massa-ai/core": "^1.9.
|
|
25
|
-
"@massa-ai/shared": "^1.9.
|
|
24
|
+
"@massa-ai/core": "^1.9.1",
|
|
25
|
+
"@massa-ai/shared": "^1.9.1",
|
|
26
26
|
"elysia": "^1.2.25",
|
|
27
27
|
"@elysiajs/swagger": "^1.2.0",
|
|
28
28
|
"@elysiajs/cors": "^1.2.0",
|