agentsmesh 0.36.0 → 0.38.0
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/CHANGELOG.md +48 -0
- package/README.md +2 -0
- package/dist/canonical.js +242 -123
- package/dist/canonical.js.map +1 -1
- package/dist/cli.js +261 -253
- package/dist/engine.js +421 -157
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +433 -164
- package/dist/index.js.map +1 -1
- package/dist/{init-Dtp4V1_v.d.ts → init-z8Dlr5Cm.d.ts} +2 -7
- package/dist/lessons.d.ts +2 -2
- package/dist/lessons.js +151 -33
- package/dist/lessons.js.map +1 -1
- package/dist/targets.js +231 -103
- package/dist/targets.js.map +1 -1
- package/package.json +2 -2
|
@@ -137,7 +137,7 @@ declare const DEFAULT_RECALL_LIMIT = 10;
|
|
|
137
137
|
* lean; without a budget a broad match can return ~450+ rule-tokens. `--all`
|
|
138
138
|
* (CLI) bypasses both caps. The top result is always kept (see RankOptions).
|
|
139
139
|
*/
|
|
140
|
-
declare const DEFAULT_RECALL_MAX_TOKENS =
|
|
140
|
+
declare const DEFAULT_RECALL_MAX_TOKENS = 1200;
|
|
141
141
|
/**
|
|
142
142
|
* Rank matched lessons by relevance and apply optional caps. Three lightweight
|
|
143
143
|
* signals are weighted-reciprocal-rank-fused (RRF): trigger specificity (inverse
|
|
@@ -383,13 +383,8 @@ declare function importLegacyLessons(projectRoot: string, options: ImportLegacyO
|
|
|
383
383
|
/**
|
|
384
384
|
* Cross-platform process lock backed by an atomic mkdir.
|
|
385
385
|
*
|
|
386
|
-
* Acquire semantics: mkdir with no `recursive` option is atomic per POSIX and
|
|
387
|
-
* returns EEXIST if the directory already exists. That makes it a reliable
|
|
388
|
-
* cross-process mutex without any third-party dependency.
|
|
389
|
-
*
|
|
390
386
|
* Stale recovery: the holder writes its PID and start timestamp into the lock
|
|
391
|
-
* dir.
|
|
392
|
-
* once. A live holder (or one on another host, whose PID we cannot probe) is
|
|
387
|
+
* dir. A dead same-host holder is evicted at once. A live or remote holder is
|
|
393
388
|
* evicted only past `staleMs` — an hours-long bound that catches a hung
|
|
394
389
|
* process or a recycled PID, never a slow but healthy run.
|
|
395
390
|
*/
|
package/dist/lessons.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { o as RankedLesson, j as LessonsQuery, A as AddLessonInput, a as AddLessonOptions, b as AddLessonResult } from './init-
|
|
2
|
-
export { c as AddLessonTriggers, D as DEFAULT_RECALL_LIMIT, X as DEFAULT_RECALL_MAX_TOKENS, I as ImportLegacyOptions, d as ImportLegacyReport, Y as LESSONS_LOCK_FILENAME, L as LESSONS_PROCEDURAL_RULE, e as Lesson, f as LessonStatus, g as LessonsGraph, Z as LessonsGraphExistsError, h as LessonsGraphSchema, i as LessonsPaths, M as MatchedLesson, k as MergeLessonsOptions, l as MergeLessonsResult, m as MutateOptions, R as RankOptions, n as RankReason, S as ScaffoldLessonsResult, p as StripMarkersOptions, q as StripMarkersReport, T as Topic, r as Trigger, s as TriggerKind, U as UnknownTopicError, V as ValidationFinding, t as ValidationLevel, u as ValidationReport, v as acquireLessonsLock, w as addLesson, x as graphFilePath, y as importLegacyLessons, _ as lessonsLockPath, z as lessonsPaths, B as loadLessonsGraph, C as mergeLessons, E as mutateLessonsGraph, F as parseGraph, G as queryLessons, H as rankLessons, J as scaffoldLessons, K as serializeGraph, N as stripLegacyMarkers, O as stripMarkersInGraph, P as toRelPath, Q as tryLoadLessonsGraph, W as validateLessonsGraph } from './init-
|
|
1
|
+
import { o as RankedLesson, j as LessonsQuery, A as AddLessonInput, a as AddLessonOptions, b as AddLessonResult } from './init-z8Dlr5Cm.js';
|
|
2
|
+
export { c as AddLessonTriggers, D as DEFAULT_RECALL_LIMIT, X as DEFAULT_RECALL_MAX_TOKENS, I as ImportLegacyOptions, d as ImportLegacyReport, Y as LESSONS_LOCK_FILENAME, L as LESSONS_PROCEDURAL_RULE, e as Lesson, f as LessonStatus, g as LessonsGraph, Z as LessonsGraphExistsError, h as LessonsGraphSchema, i as LessonsPaths, M as MatchedLesson, k as MergeLessonsOptions, l as MergeLessonsResult, m as MutateOptions, R as RankOptions, n as RankReason, S as ScaffoldLessonsResult, p as StripMarkersOptions, q as StripMarkersReport, T as Topic, r as Trigger, s as TriggerKind, U as UnknownTopicError, V as ValidationFinding, t as ValidationLevel, u as ValidationReport, v as acquireLessonsLock, w as addLesson, x as graphFilePath, y as importLegacyLessons, _ as lessonsLockPath, z as lessonsPaths, B as loadLessonsGraph, C as mergeLessons, E as mutateLessonsGraph, F as parseGraph, G as queryLessons, H as rankLessons, J as scaffoldLessons, K as serializeGraph, N as stripLegacyMarkers, O as stripMarkersInGraph, P as toRelPath, Q as tryLoadLessonsGraph, W as validateLessonsGraph } from './init-z8Dlr5Cm.js';
|
|
3
3
|
import 'zod';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/lessons.js
CHANGED
|
@@ -2,11 +2,11 @@ import { z } from 'zod';
|
|
|
2
2
|
import { readFileSync, existsSync, mkdirSync, writeFileSync, rmSync, statSync, renameSync, readdirSync, realpathSync, appendFileSync } from 'fs';
|
|
3
3
|
import { resolve, dirname, join, relative, sep, basename, extname } from 'path';
|
|
4
4
|
import { stringify, parse, parseDocument, YAMLSeq, YAMLMap } from 'yaml';
|
|
5
|
-
import { createHash } from 'crypto';
|
|
5
|
+
import { createHash, randomUUID } from 'crypto';
|
|
6
6
|
import picomatch from 'picomatch';
|
|
7
|
-
import { mkdir, rm, writeFile, readFile, stat, lstat,
|
|
7
|
+
import { mkdir, rm, writeFile, readFile, stat, lstat, open, rename } from 'fs/promises';
|
|
8
8
|
import { tmpdir, hostname } from 'os';
|
|
9
|
-
import 'timers/promises';
|
|
9
|
+
import { setTimeout as setTimeout$1 } from 'timers/promises';
|
|
10
10
|
|
|
11
11
|
// src/lessons/graph-schema.ts
|
|
12
12
|
var CURRENT_GRAPH_VERSION = 2;
|
|
@@ -1190,8 +1190,7 @@ async function acquireProcessLock(lockPath, opts = {}) {
|
|
|
1190
1190
|
if (acquired) return acquired;
|
|
1191
1191
|
const existing = await inspectLock(lockPath);
|
|
1192
1192
|
if (existing !== "young" && isStale(existing, stale)) {
|
|
1193
|
-
await rm(lockPath, { recursive: true, force: true })
|
|
1194
|
-
});
|
|
1193
|
+
await rm(lockPath, { recursive: true, force: true });
|
|
1195
1194
|
continue;
|
|
1196
1195
|
}
|
|
1197
1196
|
if (attempt >= retries) {
|
|
@@ -1215,7 +1214,13 @@ async function tryAcquire(lockPath) {
|
|
|
1215
1214
|
started: Date.now(),
|
|
1216
1215
|
hostname: getHostname()
|
|
1217
1216
|
};
|
|
1218
|
-
|
|
1217
|
+
try {
|
|
1218
|
+
await writeFile(metadataPath, JSON.stringify(metadata), "utf-8");
|
|
1219
|
+
} catch (error) {
|
|
1220
|
+
await rm(lockPath, { recursive: true, force: true }).catch(() => {
|
|
1221
|
+
});
|
|
1222
|
+
throw error;
|
|
1223
|
+
}
|
|
1219
1224
|
let released = false;
|
|
1220
1225
|
const cleanup = () => {
|
|
1221
1226
|
if (released) return;
|
|
@@ -1582,6 +1587,28 @@ function collectFanout(graph, findings) {
|
|
|
1582
1587
|
function normalizeRule2(rule) {
|
|
1583
1588
|
return rule.trim().replace(/\s+/g, " ").toLowerCase();
|
|
1584
1589
|
}
|
|
1590
|
+
var TIED_TRIGGER_SET_THRESHOLD = 5;
|
|
1591
|
+
function collectTriggerSetCollisions(graph, findings) {
|
|
1592
|
+
const bySet = /* @__PURE__ */ new Map();
|
|
1593
|
+
for (const [id, lesson] of Object.entries(graph.lessons)) {
|
|
1594
|
+
if (lesson.status !== "active") continue;
|
|
1595
|
+
const key = [...lesson.triggers].sort().join(",");
|
|
1596
|
+
if (key === "") continue;
|
|
1597
|
+
const group = bySet.get(key);
|
|
1598
|
+
if (group === void 0) bySet.set(key, [id]);
|
|
1599
|
+
else group.push(id);
|
|
1600
|
+
}
|
|
1601
|
+
const contested = [...bySet.values()].filter((ids) => ids.length > TIED_TRIGGER_SET_THRESHOLD);
|
|
1602
|
+
if (contested.length === 0) return;
|
|
1603
|
+
const largest = contested.reduce((a, b) => b.length > a.length ? b : a);
|
|
1604
|
+
const affected = contested.reduce((n, ids) => n + ids.length, 0);
|
|
1605
|
+
findings.push({
|
|
1606
|
+
level: "warning",
|
|
1607
|
+
code: "TIED_TRIGGER_SETS",
|
|
1608
|
+
message: `${contested.length} trigger set(s) are each shared by more than ${TIED_TRIGGER_SET_THRESHOLD} active lessons (largest ${largest.length}, ${affected} lessons in total). Identical triggers score identically on specificity, so recall picks among them by weaker signals \u2014 split the triggers so the lesson that matters for a given file can win.`,
|
|
1609
|
+
lessonIds: largest.sort()
|
|
1610
|
+
});
|
|
1611
|
+
}
|
|
1585
1612
|
|
|
1586
1613
|
// src/lessons/validate-keywords.ts
|
|
1587
1614
|
function collectLowSignalKeywords(graph, findings) {
|
|
@@ -1646,6 +1673,7 @@ function validateLessonsGraph(graph, options = {}) {
|
|
|
1646
1673
|
collectDuplicateTriggers(graph, findings);
|
|
1647
1674
|
collectOrphans(graph, findings);
|
|
1648
1675
|
collectFanout(graph, findings);
|
|
1676
|
+
collectTriggerSetCollisions(graph, findings);
|
|
1649
1677
|
collectLowSignalKeywords(graph, findings);
|
|
1650
1678
|
collectStopwordKeywords(graph, findings);
|
|
1651
1679
|
collectRunnerAnchoredPatterns(graph, findings);
|
|
@@ -2239,7 +2267,7 @@ function buildTopicCoherence(matches) {
|
|
|
2239
2267
|
|
|
2240
2268
|
// src/lessons/ranking.ts
|
|
2241
2269
|
var DEFAULT_RECALL_LIMIT = 10;
|
|
2242
|
-
var DEFAULT_RECALL_MAX_TOKENS =
|
|
2270
|
+
var DEFAULT_RECALL_MAX_TOKENS = 1200;
|
|
2243
2271
|
var RRF_K = 60;
|
|
2244
2272
|
var SPECIFICITY_WEIGHT = 5;
|
|
2245
2273
|
var TOPIC_COHERENCE_WEIGHT = 2;
|
|
@@ -3038,6 +3066,91 @@ function shouldNormalizeLineEndings(path) {
|
|
|
3038
3066
|
const base = basename(path).toLowerCase();
|
|
3039
3067
|
return TEXT_DOTFILES.has(base);
|
|
3040
3068
|
}
|
|
3069
|
+
var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
3070
|
+
".png",
|
|
3071
|
+
".jpg",
|
|
3072
|
+
".jpeg",
|
|
3073
|
+
".gif",
|
|
3074
|
+
".bmp",
|
|
3075
|
+
".ico",
|
|
3076
|
+
".webp",
|
|
3077
|
+
".avif",
|
|
3078
|
+
".tiff",
|
|
3079
|
+
".pdf",
|
|
3080
|
+
".zip",
|
|
3081
|
+
".gz",
|
|
3082
|
+
".tgz",
|
|
3083
|
+
".bz2",
|
|
3084
|
+
".xz",
|
|
3085
|
+
".7z",
|
|
3086
|
+
".rar",
|
|
3087
|
+
".jar",
|
|
3088
|
+
".woff",
|
|
3089
|
+
".woff2",
|
|
3090
|
+
".ttf",
|
|
3091
|
+
".otf",
|
|
3092
|
+
".eot",
|
|
3093
|
+
".mp3",
|
|
3094
|
+
".mp4",
|
|
3095
|
+
".wav",
|
|
3096
|
+
".ogg",
|
|
3097
|
+
".webm",
|
|
3098
|
+
".mov",
|
|
3099
|
+
".wasm",
|
|
3100
|
+
".bin",
|
|
3101
|
+
".dat",
|
|
3102
|
+
".db",
|
|
3103
|
+
".sqlite",
|
|
3104
|
+
".so",
|
|
3105
|
+
".dylib",
|
|
3106
|
+
".dll",
|
|
3107
|
+
".exe",
|
|
3108
|
+
".class",
|
|
3109
|
+
".pyc",
|
|
3110
|
+
// Office and design documents are zip or proprietary containers.
|
|
3111
|
+
".xlsx",
|
|
3112
|
+
".xls",
|
|
3113
|
+
".docx",
|
|
3114
|
+
".doc",
|
|
3115
|
+
".pptx",
|
|
3116
|
+
".ppt",
|
|
3117
|
+
".odt",
|
|
3118
|
+
".ods",
|
|
3119
|
+
".psd",
|
|
3120
|
+
".ai",
|
|
3121
|
+
".sketch",
|
|
3122
|
+
".fig",
|
|
3123
|
+
".heic",
|
|
3124
|
+
".heif",
|
|
3125
|
+
// Archives, columnar data, models and compressed payloads.
|
|
3126
|
+
".tar",
|
|
3127
|
+
".zst",
|
|
3128
|
+
".br",
|
|
3129
|
+
".lz4",
|
|
3130
|
+
".parquet",
|
|
3131
|
+
".avro",
|
|
3132
|
+
".orc",
|
|
3133
|
+
".pkl",
|
|
3134
|
+
".npy",
|
|
3135
|
+
".npz",
|
|
3136
|
+
".onnx",
|
|
3137
|
+
".pt",
|
|
3138
|
+
".safetensors",
|
|
3139
|
+
".gguf",
|
|
3140
|
+
".sqlite3",
|
|
3141
|
+
".avi",
|
|
3142
|
+
".mkv",
|
|
3143
|
+
".flac",
|
|
3144
|
+
".aac",
|
|
3145
|
+
".m4a",
|
|
3146
|
+
".ttc"
|
|
3147
|
+
]);
|
|
3148
|
+
function isBinaryPayloadPath(path) {
|
|
3149
|
+
return BINARY_EXTENSIONS.has(extname(path).toLowerCase());
|
|
3150
|
+
}
|
|
3151
|
+
function payloadEncodingFor(path) {
|
|
3152
|
+
return isBinaryPayloadPath(path) ? "latin1" : "utf-8";
|
|
3153
|
+
}
|
|
3041
3154
|
function normalizeLineEndings(content) {
|
|
3042
3155
|
return content.replace(/\r\n?/g, "\n");
|
|
3043
3156
|
}
|
|
@@ -3045,11 +3158,28 @@ var EXECUTABLE_SCRIPT_EXTENSIONS = /* @__PURE__ */ new Set([".sh", ".bash", ".zs
|
|
|
3045
3158
|
function executableModeFor(path) {
|
|
3046
3159
|
return EXECUTABLE_SCRIPT_EXTENSIONS.has(extname(path).toLowerCase()) ? 493 : void 0;
|
|
3047
3160
|
}
|
|
3161
|
+
var TRANSIENT_RENAME_CODES = /* @__PURE__ */ new Set(["EPERM", "EACCES", "EBUSY", "ENOTEMPTY", "EEXIST"]);
|
|
3162
|
+
async function renameWithRetry(from, to, options = {}) {
|
|
3163
|
+
const attempts = options.attempts ?? 5;
|
|
3164
|
+
const delayMs = options.delayMs ?? 50;
|
|
3165
|
+
for (let attempt = 0; ; attempt++) {
|
|
3166
|
+
try {
|
|
3167
|
+
await rename(from, to);
|
|
3168
|
+
return;
|
|
3169
|
+
} catch (err) {
|
|
3170
|
+
const code = err.code;
|
|
3171
|
+
const transient = code !== void 0 && TRANSIENT_RENAME_CODES.has(code);
|
|
3172
|
+
if (!transient || attempt >= attempts - 1) throw err;
|
|
3173
|
+
await setTimeout$1(delayMs * 2 ** attempt);
|
|
3174
|
+
}
|
|
3175
|
+
}
|
|
3176
|
+
}
|
|
3048
3177
|
|
|
3049
3178
|
// src/utils/filesystem/fs.ts
|
|
3050
3179
|
async function readFileSafe(path) {
|
|
3051
3180
|
try {
|
|
3052
|
-
const data = await readFile(path,
|
|
3181
|
+
const data = await readFile(path, payloadEncodingFor(path));
|
|
3182
|
+
if (isBinaryPayloadPath(path)) return data;
|
|
3053
3183
|
return data.startsWith(UTF8_BOM) ? data.slice(UTF8_BOM.length) : data;
|
|
3054
3184
|
} catch (err) {
|
|
3055
3185
|
const e = err;
|
|
@@ -3073,40 +3203,28 @@ async function writeFileAtomic(path, content, options) {
|
|
|
3073
3203
|
{ errnoCode: "EISDIR" }
|
|
3074
3204
|
);
|
|
3075
3205
|
}
|
|
3076
|
-
if (info.isSymbolicLink()) {
|
|
3077
|
-
await unlink(path).catch((e) => {
|
|
3078
|
-
if (e.code !== "ENOENT") throw e;
|
|
3079
|
-
});
|
|
3080
|
-
}
|
|
3081
3206
|
} catch (err) {
|
|
3082
3207
|
if (err instanceof FileSystemError) throw err;
|
|
3083
3208
|
const e = err;
|
|
3084
3209
|
if (e.code !== "ENOENT") throw err;
|
|
3085
3210
|
}
|
|
3086
|
-
const tmpPath = `${path}.tmp`;
|
|
3211
|
+
const tmpPath = `${path}.tmp-${randomUUID()}`;
|
|
3087
3212
|
const payload = shouldNormalizeLineEndings(path) ? normalizeLineEndings(content) : content;
|
|
3088
3213
|
const mode = executableModeFor(path);
|
|
3214
|
+
let handle;
|
|
3215
|
+
let ownsTemporaryFile = false;
|
|
3089
3216
|
try {
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
}
|
|
3098
|
-
const writeOpts = {
|
|
3099
|
-
encoding: "utf-8",
|
|
3100
|
-
flag: "w"
|
|
3101
|
-
};
|
|
3102
|
-
if (mode !== void 0) writeOpts.mode = mode;
|
|
3103
|
-
await writeFile(tmpPath, payload, writeOpts);
|
|
3104
|
-
await rename(tmpPath, path);
|
|
3105
|
-
if (mode !== void 0) {
|
|
3106
|
-
await chmod(path, mode);
|
|
3107
|
-
}
|
|
3217
|
+
handle = await open(tmpPath, "wx", mode);
|
|
3218
|
+
ownsTemporaryFile = true;
|
|
3219
|
+
await handle.writeFile(payload, payloadEncodingFor(path));
|
|
3220
|
+
if (mode !== void 0) await handle.chmod(mode);
|
|
3221
|
+
await handle.close();
|
|
3222
|
+
handle = void 0;
|
|
3223
|
+
await renameWithRetry(tmpPath, path);
|
|
3108
3224
|
} catch (err) {
|
|
3109
|
-
await
|
|
3225
|
+
await handle?.close().catch(() => {
|
|
3226
|
+
});
|
|
3227
|
+
if (ownsTemporaryFile) await rm(tmpPath, { force: true }).catch(() => {
|
|
3110
3228
|
});
|
|
3111
3229
|
const e = err;
|
|
3112
3230
|
throw new FileSystemError(
|