squads-cli 0.5.0 → 0.6.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/README.md +161 -4
- package/dist/{chunk-HKWCBCEK.js → chunk-4CMAEQQY.js} +6 -2
- package/dist/chunk-4CMAEQQY.js.map +1 -0
- package/dist/{chunk-NA3IECJA.js → chunk-N7KDWU4W.js} +155 -58
- package/dist/chunk-N7KDWU4W.js.map +1 -0
- package/dist/{chunk-7PRYDHZW.js → chunk-NHGLXN2F.js} +8 -6
- package/dist/chunk-NHGLXN2F.js.map +1 -0
- package/dist/{chunk-QPH5OR7J.js → chunk-O7UV3FWI.js} +139 -21
- package/dist/chunk-O7UV3FWI.js.map +1 -0
- package/dist/{chunk-BV6S5AWZ.js → chunk-ZTQ7ISUR.js} +28 -109
- package/dist/chunk-ZTQ7ISUR.js.map +1 -0
- package/dist/cli.js +5493 -7665
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +110 -2
- package/dist/index.js +302 -26
- package/dist/index.js.map +1 -1
- package/dist/{memory-ZXDXF6KF.js → memory-VNF2VFRB.js} +2 -2
- package/dist/{sessions-F6LRY7EN.js → sessions-6PB7ALCE.js} +3 -3
- package/dist/{squad-parser-MSYE4PXL.js → squad-parser-4BI3G4RS.js} +4 -2
- package/dist/templates/seed/BUSINESS_BRIEF.md.template +27 -0
- package/dist/templates/seed/CLAUDE.md.template +69 -0
- package/dist/templates/seed/config/provider.yaml +4 -0
- package/dist/templates/seed/hooks/settings.json.template +31 -0
- package/dist/templates/seed/memory/company/manager/state.md +16 -0
- package/dist/templates/seed/memory/engineering/issue-solver/state.md +12 -0
- package/dist/templates/seed/memory/intelligence/intel-lead/state.md +9 -0
- package/dist/templates/seed/memory/marketing/content-drafter/state.md +12 -0
- package/dist/templates/seed/memory/operations/ops-lead/state.md +12 -0
- package/dist/templates/seed/memory/research/researcher/state.md +10 -0
- package/dist/templates/seed/skills/gh/SKILL.md +57 -0
- package/dist/templates/seed/skills/squads-cli/SKILL.md +88 -0
- package/dist/templates/seed/squads/company/SQUAD.md +49 -0
- package/dist/templates/seed/squads/company/company-critic.md +21 -0
- package/dist/templates/seed/squads/company/company-eval.md +21 -0
- package/dist/templates/seed/squads/company/event-dispatcher.md +21 -0
- package/dist/templates/seed/squads/company/goal-tracker.md +21 -0
- package/dist/templates/seed/squads/company/manager.md +66 -0
- package/dist/templates/seed/squads/engineering/SQUAD.md +48 -0
- package/dist/templates/seed/squads/engineering/code-reviewer.md +57 -0
- package/dist/templates/seed/squads/engineering/issue-solver.md +58 -0
- package/dist/templates/seed/squads/engineering/test-writer.md +50 -0
- package/dist/templates/seed/squads/intelligence/SQUAD.md +37 -0
- package/dist/templates/seed/squads/intelligence/intel-critic.md +36 -0
- package/dist/templates/seed/squads/intelligence/intel-eval.md +31 -0
- package/dist/templates/seed/squads/intelligence/intel-lead.md +71 -0
- package/dist/templates/seed/squads/marketing/SQUAD.md +47 -0
- package/dist/templates/seed/squads/marketing/content-drafter.md +71 -0
- package/dist/templates/seed/squads/marketing/growth-analyst.md +49 -0
- package/dist/templates/seed/squads/marketing/social-poster.md +44 -0
- package/dist/templates/seed/squads/operations/SQUAD.md +45 -0
- package/dist/templates/seed/squads/operations/finance-tracker.md +47 -0
- package/dist/templates/seed/squads/operations/goal-tracker.md +48 -0
- package/dist/templates/seed/squads/operations/ops-lead.md +58 -0
- package/dist/templates/seed/squads/research/SQUAD.md +38 -0
- package/dist/templates/seed/squads/research/analyst.md +27 -0
- package/dist/templates/seed/squads/research/research-critic.md +20 -0
- package/dist/templates/seed/squads/research/research-eval.md +20 -0
- package/dist/templates/seed/squads/research/researcher.md +28 -0
- package/dist/{terminal-JZSAQSN7.js → terminal-YKA4O5CX.js} +4 -2
- package/dist/{update-MAY6EXFQ.js → update-ALJKFFM7.js} +3 -2
- package/package.json +9 -22
- package/templates/seed/BUSINESS_BRIEF.md.template +27 -0
- package/templates/seed/CLAUDE.md.template +69 -0
- package/templates/seed/config/provider.yaml +4 -0
- package/templates/seed/hooks/settings.json.template +31 -0
- package/templates/seed/memory/company/manager/state.md +16 -0
- package/templates/seed/memory/engineering/issue-solver/state.md +12 -0
- package/templates/seed/memory/intelligence/intel-lead/state.md +9 -0
- package/templates/seed/memory/marketing/content-drafter/state.md +12 -0
- package/templates/seed/memory/operations/ops-lead/state.md +12 -0
- package/templates/seed/memory/research/researcher/state.md +10 -0
- package/templates/seed/skills/gh/SKILL.md +57 -0
- package/templates/seed/skills/squads-cli/SKILL.md +88 -0
- package/templates/seed/squads/company/SQUAD.md +49 -0
- package/templates/seed/squads/company/company-critic.md +21 -0
- package/templates/seed/squads/company/company-eval.md +21 -0
- package/templates/seed/squads/company/event-dispatcher.md +21 -0
- package/templates/seed/squads/company/goal-tracker.md +21 -0
- package/templates/seed/squads/company/manager.md +66 -0
- package/templates/seed/squads/engineering/SQUAD.md +48 -0
- package/templates/seed/squads/engineering/code-reviewer.md +57 -0
- package/templates/seed/squads/engineering/issue-solver.md +58 -0
- package/templates/seed/squads/engineering/test-writer.md +50 -0
- package/templates/seed/squads/intelligence/SQUAD.md +37 -0
- package/templates/seed/squads/intelligence/intel-critic.md +36 -0
- package/templates/seed/squads/intelligence/intel-eval.md +31 -0
- package/templates/seed/squads/intelligence/intel-lead.md +71 -0
- package/templates/seed/squads/marketing/SQUAD.md +47 -0
- package/templates/seed/squads/marketing/content-drafter.md +71 -0
- package/templates/seed/squads/marketing/growth-analyst.md +49 -0
- package/templates/seed/squads/marketing/social-poster.md +44 -0
- package/templates/seed/squads/operations/SQUAD.md +45 -0
- package/templates/seed/squads/operations/finance-tracker.md +47 -0
- package/templates/seed/squads/operations/goal-tracker.md +48 -0
- package/templates/seed/squads/operations/ops-lead.md +58 -0
- package/templates/seed/squads/research/SQUAD.md +38 -0
- package/templates/seed/squads/research/analyst.md +27 -0
- package/templates/seed/squads/research/research-critic.md +20 -0
- package/templates/seed/squads/research/research-eval.md +20 -0
- package/templates/seed/squads/research/researcher.md +28 -0
- package/dist/chunk-7PRYDHZW.js.map +0 -1
- package/dist/chunk-BV6S5AWZ.js.map +0 -1
- package/dist/chunk-HKWCBCEK.js.map +0 -1
- package/dist/chunk-NA3IECJA.js.map +0 -1
- package/dist/chunk-QPH5OR7J.js.map +0 -1
- package/docker/.env.example +0 -17
- package/docker/README.md +0 -92
- package/docker/docker-compose.engram.yml +0 -304
- package/docker/docker-compose.yml +0 -250
- package/docker/init-db.sql +0 -478
- package/docker/init-engram-db.sql +0 -148
- package/docker/init-langfuse-db.sh +0 -10
- package/docker/otel-collector.yaml +0 -34
- package/docker/squads-bridge/Dockerfile +0 -14
- package/docker/squads-bridge/Dockerfile.proxy +0 -14
- package/docker/squads-bridge/anthropic_proxy.py +0 -313
- package/docker/squads-bridge/requirements.txt +0 -7
- package/docker/squads-bridge/squads_bridge.py +0 -2299
- package/docker/telemetry-ping/Dockerfile +0 -10
- package/docker/telemetry-ping/deploy.sh +0 -69
- package/docker/telemetry-ping/main.py +0 -136
- package/docker/telemetry-ping/requirements.txt +0 -3
- /package/dist/{memory-ZXDXF6KF.js.map → memory-VNF2VFRB.js.map} +0 -0
- /package/dist/{sessions-F6LRY7EN.js.map → sessions-6PB7ALCE.js.map} +0 -0
- /package/dist/{squad-parser-MSYE4PXL.js.map → squad-parser-4BI3G4RS.js.map} +0 -0
- /package/dist/{terminal-JZSAQSN7.js.map → terminal-YKA4O5CX.js.map} +0 -0
- /package/dist/{update-MAY6EXFQ.js.map → update-ALJKFFM7.js.map} +0 -0
|
@@ -4,47 +4,19 @@ import {
|
|
|
4
4
|
} from "./chunk-7OCVIDC7.js";
|
|
5
5
|
|
|
6
6
|
// src/lib/memory.ts
|
|
7
|
-
import { readFileSync, writeFileSync as writeFileSync2, existsSync as existsSync2, readdirSync, mkdirSync as mkdirSync2 } from "fs";
|
|
7
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2, readdirSync, mkdirSync as mkdirSync2 } from "fs";
|
|
8
8
|
import { join as join2, dirname as dirname2 } from "path";
|
|
9
9
|
|
|
10
10
|
// src/lib/lock.ts
|
|
11
|
-
import
|
|
12
|
-
import { existsSync, writeFileSync, unlinkSync, mkdirSync } from "fs";
|
|
11
|
+
import { existsSync, writeFileSync, unlinkSync, mkdirSync, statSync, readFileSync, openSync, closeSync } from "fs";
|
|
13
12
|
import { join, dirname } from "path";
|
|
14
13
|
import { createHash } from "crypto";
|
|
15
14
|
var LOCK_TTL_MS = 3e4;
|
|
16
15
|
var LOCK_RETRY_DELAY_MS = 100;
|
|
17
16
|
var LOCK_MAX_RETRIES = 50;
|
|
18
|
-
var redisClient = null;
|
|
19
|
-
var redisAvailable = null;
|
|
20
|
-
async function getRedis() {
|
|
21
|
-
if (redisAvailable === false) return null;
|
|
22
|
-
if (!redisClient) {
|
|
23
|
-
try {
|
|
24
|
-
redisClient = new Redis({
|
|
25
|
-
host: process.env.REDIS_HOST || "localhost",
|
|
26
|
-
port: parseInt(process.env.REDIS_PORT || "6379"),
|
|
27
|
-
connectTimeout: 1e3,
|
|
28
|
-
maxRetriesPerRequest: 1,
|
|
29
|
-
lazyConnect: true
|
|
30
|
-
});
|
|
31
|
-
await redisClient.connect();
|
|
32
|
-
redisAvailable = true;
|
|
33
|
-
} catch {
|
|
34
|
-
redisAvailable = false;
|
|
35
|
-
redisClient = null;
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return redisClient;
|
|
40
|
-
}
|
|
41
17
|
function generateLockId() {
|
|
42
18
|
return `${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
43
19
|
}
|
|
44
|
-
function getLockKey(filePath) {
|
|
45
|
-
const hash = createHash("md5").update(filePath).digest("hex").slice(0, 12);
|
|
46
|
-
return `squads:lock:${hash}`;
|
|
47
|
-
}
|
|
48
20
|
function getFileLockPath(filePath) {
|
|
49
21
|
const lockDir = join(dirname(filePath), ".locks");
|
|
50
22
|
const hash = createHash("md5").update(filePath).digest("hex").slice(0, 12);
|
|
@@ -53,33 +25,6 @@ function getFileLockPath(filePath) {
|
|
|
53
25
|
function sleep(ms) {
|
|
54
26
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
55
27
|
}
|
|
56
|
-
async function acquireRedisLock(key, lockId) {
|
|
57
|
-
const redis = await getRedis();
|
|
58
|
-
if (!redis) return false;
|
|
59
|
-
try {
|
|
60
|
-
const result = await redis.set(key, lockId, "PX", LOCK_TTL_MS, "NX");
|
|
61
|
-
return result === "OK";
|
|
62
|
-
} catch {
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
async function releaseRedisLock(key, lockId) {
|
|
67
|
-
const redis = await getRedis();
|
|
68
|
-
if (!redis) return false;
|
|
69
|
-
try {
|
|
70
|
-
const script = `
|
|
71
|
-
if redis.call("get", KEYS[1]) == ARGV[1] then
|
|
72
|
-
return redis.call("del", KEYS[1])
|
|
73
|
-
else
|
|
74
|
-
return 0
|
|
75
|
-
end
|
|
76
|
-
`;
|
|
77
|
-
const result = await redis.eval(script, 1, key, lockId);
|
|
78
|
-
return result === 1;
|
|
79
|
-
} catch {
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
28
|
function acquireFileLock(lockPath, lockId) {
|
|
84
29
|
try {
|
|
85
30
|
const lockDir = dirname(lockPath);
|
|
@@ -87,7 +32,6 @@ function acquireFileLock(lockPath, lockId) {
|
|
|
87
32
|
mkdirSync(lockDir, { recursive: true });
|
|
88
33
|
}
|
|
89
34
|
if (existsSync(lockPath)) {
|
|
90
|
-
const { statSync, readFileSync: readFileSync2 } = __require("fs");
|
|
91
35
|
const stats = statSync(lockPath);
|
|
92
36
|
const ageMs = Date.now() - stats.mtimeMs;
|
|
93
37
|
if (ageMs > LOCK_TTL_MS) {
|
|
@@ -96,7 +40,6 @@ function acquireFileLock(lockPath, lockId) {
|
|
|
96
40
|
return false;
|
|
97
41
|
}
|
|
98
42
|
}
|
|
99
|
-
const { openSync, closeSync } = __require("fs");
|
|
100
43
|
const fd = openSync(lockPath, "wx");
|
|
101
44
|
writeFileSync(fd, lockId);
|
|
102
45
|
closeSync(fd);
|
|
@@ -108,8 +51,7 @@ function acquireFileLock(lockPath, lockId) {
|
|
|
108
51
|
function releaseFileLock(lockPath, lockId) {
|
|
109
52
|
try {
|
|
110
53
|
if (!existsSync(lockPath)) return true;
|
|
111
|
-
const
|
|
112
|
-
const currentId = readFileSync2(lockPath, "utf-8").trim();
|
|
54
|
+
const currentId = readFileSync(lockPath, "utf-8").trim();
|
|
113
55
|
if (currentId === lockId) {
|
|
114
56
|
unlinkSync(lockPath);
|
|
115
57
|
return true;
|
|
@@ -121,51 +63,22 @@ function releaseFileLock(lockPath, lockId) {
|
|
|
121
63
|
}
|
|
122
64
|
async function acquireLock(filePath) {
|
|
123
65
|
const lockId = generateLockId();
|
|
124
|
-
const redisKey = getLockKey(filePath);
|
|
125
66
|
const fileLockPath = getFileLockPath(filePath);
|
|
126
|
-
let
|
|
67
|
+
let gotLock = false;
|
|
127
68
|
for (let attempt = 0; attempt < LOCK_MAX_RETRIES; attempt++) {
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
break;
|
|
131
|
-
}
|
|
132
|
-
if (redisAvailable === false && acquireFileLock(fileLockPath, lockId)) {
|
|
133
|
-
useRedis = false;
|
|
69
|
+
if (acquireFileLock(fileLockPath, lockId)) {
|
|
70
|
+
gotLock = true;
|
|
134
71
|
break;
|
|
135
72
|
}
|
|
136
73
|
if (attempt < LOCK_MAX_RETRIES - 1) {
|
|
137
74
|
await sleep(LOCK_RETRY_DELAY_MS);
|
|
138
75
|
}
|
|
139
76
|
}
|
|
140
|
-
const redis = await getRedis();
|
|
141
|
-
let gotLock = false;
|
|
142
|
-
if (redis) {
|
|
143
|
-
try {
|
|
144
|
-
const currentOwner = await redis.get(redisKey);
|
|
145
|
-
gotLock = currentOwner === lockId;
|
|
146
|
-
} catch {
|
|
147
|
-
gotLock = false;
|
|
148
|
-
}
|
|
149
|
-
} else {
|
|
150
|
-
try {
|
|
151
|
-
if (existsSync(fileLockPath)) {
|
|
152
|
-
const { readFileSync: readFileSync2 } = __require("fs");
|
|
153
|
-
const currentId = readFileSync2(fileLockPath, "utf-8").trim();
|
|
154
|
-
gotLock = currentId === lockId;
|
|
155
|
-
}
|
|
156
|
-
} catch {
|
|
157
|
-
gotLock = false;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
77
|
if (!gotLock) {
|
|
161
78
|
return null;
|
|
162
79
|
}
|
|
163
80
|
return async () => {
|
|
164
|
-
|
|
165
|
-
await releaseRedisLock(redisKey, lockId);
|
|
166
|
-
} else {
|
|
167
|
-
releaseFileLock(fileLockPath, lockId);
|
|
168
|
-
}
|
|
81
|
+
releaseFileLock(fileLockPath, lockId);
|
|
169
82
|
};
|
|
170
83
|
}
|
|
171
84
|
async function withLock(filePath, fn) {
|
|
@@ -210,7 +123,7 @@ function listMemoryEntries(memoryDir) {
|
|
|
210
123
|
squad,
|
|
211
124
|
agent,
|
|
212
125
|
type,
|
|
213
|
-
content:
|
|
126
|
+
content: readFileSync2(filePath, "utf-8"),
|
|
214
127
|
path: filePath
|
|
215
128
|
});
|
|
216
129
|
}
|
|
@@ -244,8 +157,8 @@ function expandQuery(query) {
|
|
|
244
157
|
}
|
|
245
158
|
function getFileAge(filePath) {
|
|
246
159
|
try {
|
|
247
|
-
const { statSync } = __require("fs");
|
|
248
|
-
const stats =
|
|
160
|
+
const { statSync: statSync2 } = __require("fs");
|
|
161
|
+
const stats = statSync2(filePath);
|
|
249
162
|
const ageMs = Date.now() - stats.mtimeMs;
|
|
250
163
|
const ageDays = ageMs / (1e3 * 60 * 60 * 24);
|
|
251
164
|
return ageDays;
|
|
@@ -328,7 +241,7 @@ function getSquadState(squadName) {
|
|
|
328
241
|
squad: squadName,
|
|
329
242
|
agent,
|
|
330
243
|
type: "state",
|
|
331
|
-
content:
|
|
244
|
+
content: readFileSync2(statePath, "utf-8"),
|
|
332
245
|
path: statePath
|
|
333
246
|
});
|
|
334
247
|
}
|
|
@@ -370,15 +283,18 @@ async function appendToMemory(squadName, agentName, type, addition) {
|
|
|
370
283
|
await withLock(filePath, () => {
|
|
371
284
|
let existing = "";
|
|
372
285
|
if (existsSync2(filePath)) {
|
|
373
|
-
existing =
|
|
286
|
+
existing = readFileSync2(filePath, "utf-8");
|
|
374
287
|
}
|
|
375
288
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
376
|
-
const
|
|
289
|
+
const lines = addition.trim().split("\n");
|
|
290
|
+
const heading = lines[0].replace(/^#+\s*/, "").replace(/^\*\*/, "").replace(/\*\*$/, "");
|
|
291
|
+
const body = lines.slice(1).join("\n").trim();
|
|
292
|
+
const entry = body ? `## ${timestamp}: ${heading}
|
|
377
293
|
|
|
378
|
-
|
|
379
|
-
|
|
294
|
+
${body}` : `## ${timestamp}: ${heading}`;
|
|
295
|
+
const newContent = existing + `
|
|
380
296
|
|
|
381
|
-
${
|
|
297
|
+
${entry}`;
|
|
382
298
|
const dir = dirname2(filePath);
|
|
383
299
|
if (!existsSync2(dir)) {
|
|
384
300
|
mkdirSync2(dir, { recursive: true });
|
|
@@ -394,15 +310,18 @@ function appendToMemorySync(squadName, agentName, type, addition) {
|
|
|
394
310
|
const filePath = join2(memoryDir, squadName, agentName, `${type}.md`);
|
|
395
311
|
let existing = "";
|
|
396
312
|
if (existsSync2(filePath)) {
|
|
397
|
-
existing =
|
|
313
|
+
existing = readFileSync2(filePath, "utf-8");
|
|
398
314
|
}
|
|
399
315
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
400
|
-
const
|
|
316
|
+
const lines = addition.trim().split("\n");
|
|
317
|
+
const heading = lines[0].replace(/^#+\s*/, "").replace(/^\*\*/, "").replace(/\*\*$/, "");
|
|
318
|
+
const body = lines.slice(1).join("\n").trim();
|
|
319
|
+
const entry = body ? `## ${timestamp}: ${heading}
|
|
401
320
|
|
|
402
|
-
|
|
403
|
-
|
|
321
|
+
${body}` : `## ${timestamp}: ${heading}`;
|
|
322
|
+
const newContent = existing + `
|
|
404
323
|
|
|
405
|
-
${
|
|
324
|
+
${entry}`;
|
|
406
325
|
updateMemorySync(squadName, agentName, type, newContent.trim());
|
|
407
326
|
}
|
|
408
327
|
|
|
@@ -416,4 +335,4 @@ export {
|
|
|
416
335
|
appendToMemory,
|
|
417
336
|
appendToMemorySync
|
|
418
337
|
};
|
|
419
|
-
//# sourceMappingURL=chunk-
|
|
338
|
+
//# sourceMappingURL=chunk-ZTQ7ISUR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/memory.ts","../src/lib/lock.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { withLock } from './lock.js';\n\nexport interface MemoryEntry {\n squad: string;\n agent: string;\n type: 'state' | 'output' | 'learnings' | 'feedback';\n content: string;\n path: string;\n lastUpdated?: string;\n}\n\nexport interface SearchResult {\n entry: MemoryEntry;\n matches: string[];\n score: number;\n}\n\nexport function findMemoryDir(): string | null {\n let dir = process.cwd();\n\n for (let i = 0; i < 5; i++) {\n const memoryPath = join(dir, '.agents', 'memory');\n if (existsSync(memoryPath)) {\n return memoryPath;\n }\n const parent = join(dir, '..');\n if (parent === dir) break;\n dir = parent;\n }\n\n return null;\n}\n\nexport function listMemoryEntries(memoryDir: string): MemoryEntry[] {\n const entries: MemoryEntry[] = [];\n\n const squads = readdirSync(memoryDir, { withFileTypes: true })\n .filter(e => e.isDirectory())\n .map(e => e.name);\n\n for (const squad of squads) {\n const squadPath = join(memoryDir, squad);\n const agents = readdirSync(squadPath, { withFileTypes: true })\n .filter(e => e.isDirectory())\n .map(e => e.name);\n\n for (const agent of agents) {\n const agentPath = join(squadPath, agent);\n const files = readdirSync(agentPath).filter(f => f.endsWith('.md'));\n\n for (const file of files) {\n const filePath = join(agentPath, file);\n const type = file.replace('.md', '') as MemoryEntry['type'];\n\n entries.push({\n squad,\n agent,\n type,\n content: readFileSync(filePath, 'utf-8'),\n path: filePath\n });\n }\n }\n }\n\n return entries;\n}\n\n// Semantic expansions for common business terms\nconst SEMANTIC_EXPANSIONS: Record<string, string[]> = {\n 'pricing': ['price', 'cost', '$', 'revenue', 'fee', 'rate'],\n 'price': ['pricing', 'cost', '$', 'fee'],\n 'revenue': ['income', 'sales', 'mrr', 'arr', '$'],\n 'cost': ['expense', 'spend', 'budget', '$', 'price'],\n 'customer': ['client', 'lead', 'prospect', 'user'],\n 'client': ['customer', 'lead', 'prospect'],\n 'lead': ['prospect', 'customer', 'client', 'pipeline'],\n 'agent': ['squad', 'bot', 'ai'],\n 'squad': ['team', 'agent', 'group'],\n 'status': ['state', 'progress', 'health'],\n 'bug': ['issue', 'error', 'problem', 'fix'],\n 'feature': ['capability', 'function', 'ability'],\n};\n\nfunction expandQuery(query: string): string[] {\n const words = query.toLowerCase().split(/\\s+/);\n const expanded = new Set(words);\n\n for (const word of words) {\n if (SEMANTIC_EXPANSIONS[word]) {\n SEMANTIC_EXPANSIONS[word].forEach(syn => expanded.add(syn));\n }\n }\n\n return Array.from(expanded);\n}\n\nfunction getFileAge(filePath: string): number {\n try {\n const { statSync } = require('fs');\n const stats = statSync(filePath);\n const ageMs = Date.now() - stats.mtimeMs;\n const ageDays = ageMs / (1000 * 60 * 60 * 24);\n return ageDays;\n } catch {\n return 999;\n }\n}\n\nexport function searchMemory(query: string, memoryDir?: string): SearchResult[] {\n const dir = memoryDir || findMemoryDir();\n if (!dir) return [];\n\n const entries = listMemoryEntries(dir);\n const results: SearchResult[] = [];\n const queryLower = query.toLowerCase();\n const expandedTerms = expandQuery(queryLower);\n\n for (const entry of entries) {\n const contentLower = entry.content.toLowerCase();\n const lines = entry.content.split('\\n');\n const matches: string[] = [];\n let score = 0;\n let directHits = 0;\n let expandedHits = 0;\n\n // Check direct query words first\n const directWords = queryLower.split(/\\s+/);\n for (const word of directWords) {\n if (contentLower.includes(word)) {\n directHits += 1;\n score += 2; // Direct matches worth more\n }\n }\n\n // Check expanded terms\n for (const term of expandedTerms) {\n if (contentLower.includes(term)) {\n expandedHits += 1;\n score += 0.5; // Expanded matches worth less but still count\n\n // Find matching lines with context\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line.toLowerCase().includes(term) && line.trim() && !matches.includes(line.trim())) {\n matches.push(line.trim());\n }\n }\n }\n }\n\n // Boost score for exact phrase match\n if (contentLower.includes(queryLower)) {\n score += 5;\n }\n\n // Recency boost - files updated recently are more relevant\n const ageDays = getFileAge(entry.path);\n if (ageDays < 1) {\n score *= 1.5; // Updated today\n } else if (ageDays < 7) {\n score *= 1.2; // Updated this week\n } else if (ageDays > 30) {\n score *= 0.8; // Stale data penalty\n }\n\n // Type weighting - balanced across types\n const typeWeights: Record<string, number> = {\n 'state': 1.2, // Current state slightly preferred\n 'learnings': 1.1, // Learnings are valuable\n 'output': 1.0, // Recent outputs\n 'feedback': 0.9, // Feedback less commonly needed\n };\n score *= typeWeights[entry.type] || 1.0;\n\n if (score > 0 && (directHits > 0 || expandedHits > 1)) {\n results.push({ entry, matches: matches.slice(0, 7), score });\n }\n }\n\n // Sort by score descending\n return results.sort((a, b) => b.score - a.score);\n}\n\nexport function getSquadState(squadName: string): MemoryEntry[] {\n const memoryDir = findMemoryDir();\n if (!memoryDir) return [];\n\n const squadPath = join(memoryDir, squadName);\n if (!existsSync(squadPath)) return [];\n\n const entries: MemoryEntry[] = [];\n const agents = readdirSync(squadPath, { withFileTypes: true })\n .filter(e => e.isDirectory())\n .map(e => e.name);\n\n for (const agent of agents) {\n const statePath = join(squadPath, agent, 'state.md');\n if (existsSync(statePath)) {\n entries.push({\n squad: squadName,\n agent,\n type: 'state',\n content: readFileSync(statePath, 'utf-8'),\n path: statePath\n });\n }\n }\n\n return entries;\n}\n\n/**\n * Update memory file with distributed locking\n * Safe for concurrent access from multiple agents\n */\nexport async function updateMemory(\n squadName: string,\n agentName: string,\n type: MemoryEntry['type'],\n content: string\n): Promise<void> {\n const memoryDir = findMemoryDir();\n if (!memoryDir) {\n throw new Error('No .agents/memory directory found');\n }\n\n const filePath = join(memoryDir, squadName, agentName, `${type}.md`);\n const dir = dirname(filePath);\n\n await withLock(filePath, () => {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(filePath, content);\n });\n}\n\n/**\n * Sync version for backward compatibility (no locking - use with caution)\n * @deprecated Use async updateMemory() for safe concurrent access\n */\nexport function updateMemorySync(\n squadName: string,\n agentName: string,\n type: MemoryEntry['type'],\n content: string\n): void {\n const memoryDir = findMemoryDir();\n if (!memoryDir) {\n throw new Error('No .agents/memory directory found');\n }\n\n const filePath = join(memoryDir, squadName, agentName, `${type}.md`);\n const dir = dirname(filePath);\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n writeFileSync(filePath, content);\n}\n\n/**\n * Append to memory file with distributed locking\n * Safe for concurrent access from multiple agents\n */\nexport async function appendToMemory(\n squadName: string,\n agentName: string,\n type: MemoryEntry['type'],\n addition: string\n): Promise<void> {\n const memoryDir = findMemoryDir();\n if (!memoryDir) {\n throw new Error('No .agents/memory directory found');\n }\n\n const filePath = join(memoryDir, squadName, agentName, `${type}.md`);\n\n await withLock(filePath, () => {\n let existing = '';\n if (existsSync(filePath)) {\n existing = readFileSync(filePath, 'utf-8');\n }\n\n const timestamp = new Date().toISOString().split('T')[0];\n // Format: ## YYYY-MM-DD: First line as heading (synthesizer-friendly)\n const lines = addition.trim().split('\\n');\n const heading = lines[0].replace(/^#+\\s*/, '').replace(/^\\*\\*/, '').replace(/\\*\\*$/, '');\n const body = lines.slice(1).join('\\n').trim();\n const entry = body\n ? `## ${timestamp}: ${heading}\\n\\n${body}`\n : `## ${timestamp}: ${heading}`;\n const newContent = existing + `\\n\\n${entry}`;\n\n const dir = dirname(filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(filePath, newContent.trim());\n });\n}\n\n/**\n * Sync version for backward compatibility (no locking - use with caution)\n * @deprecated Use async appendToMemory() for safe concurrent access\n */\nexport function appendToMemorySync(\n squadName: string,\n agentName: string,\n type: MemoryEntry['type'],\n addition: string\n): void {\n const memoryDir = findMemoryDir();\n if (!memoryDir) {\n throw new Error('No .agents/memory directory found');\n }\n\n const filePath = join(memoryDir, squadName, agentName, `${type}.md`);\n\n let existing = '';\n if (existsSync(filePath)) {\n existing = readFileSync(filePath, 'utf-8');\n }\n\n const timestamp = new Date().toISOString().split('T')[0];\n // Format: ## YYYY-MM-DD: First line as heading (synthesizer-friendly)\n const lines = addition.trim().split('\\n');\n const heading = lines[0].replace(/^#+\\s*/, '').replace(/^\\*\\*/, '').replace(/\\*\\*$/, '');\n const body = lines.slice(1).join('\\n').trim();\n const entry = body\n ? `## ${timestamp}: ${heading}\\n\\n${body}`\n : `## ${timestamp}: ${heading}`;\n const newContent = existing + `\\n\\n${entry}`;\n\n updateMemorySync(squadName, agentName, type, newContent.trim());\n}\n","/**\n * File-based locking for safe concurrent file access\n */\n\nimport { existsSync, writeFileSync, unlinkSync, mkdirSync, statSync, readFileSync, openSync, closeSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { createHash } from 'crypto';\n\n// Lock configuration\nconst LOCK_TTL_MS = 30000; // 30 seconds max lock hold time\nconst LOCK_RETRY_DELAY_MS = 100;\nconst LOCK_MAX_RETRIES = 50; // 5 seconds max wait\n\n/**\n * Generate a unique lock ID for this process\n */\nfunction generateLockId(): string {\n return `${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n}\n\n/**\n * Get file lock path\n */\nfunction getFileLockPath(filePath: string): string {\n const lockDir = join(dirname(filePath), '.locks');\n const hash = createHash('md5').update(filePath).digest('hex').slice(0, 12);\n return join(lockDir, `${hash}.lock`);\n}\n\n/**\n * Sleep helper\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Acquire a file-based lock\n */\nfunction acquireFileLock(lockPath: string, lockId: string): boolean {\n try {\n const lockDir = dirname(lockPath);\n if (!existsSync(lockDir)) {\n mkdirSync(lockDir, { recursive: true });\n }\n\n // Check if lock exists and is still valid\n if (existsSync(lockPath)) {\n const stats = statSync(lockPath);\n const ageMs = Date.now() - stats.mtimeMs;\n\n // Lock expired - clean it up\n if (ageMs > LOCK_TTL_MS) {\n unlinkSync(lockPath);\n } else {\n return false; // Lock held by another process\n }\n }\n\n // Create lock file atomically using O_EXCL flag\n const fd = openSync(lockPath, 'wx');\n writeFileSync(fd, lockId);\n closeSync(fd);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Release a file-based lock\n */\nfunction releaseFileLock(lockPath: string, lockId: string): boolean {\n try {\n if (!existsSync(lockPath)) return true;\n\n const currentId = readFileSync(lockPath, 'utf-8').trim();\n\n if (currentId === lockId) {\n unlinkSync(lockPath);\n return true;\n }\n return false;\n } catch {\n return false;\n }\n}\n\n/**\n * Acquire a lock for a file path\n * Returns a release function, or null if lock couldn't be acquired\n */\nexport async function acquireLock(filePath: string): Promise<(() => Promise<void>) | null> {\n const lockId = generateLockId();\n const fileLockPath = getFileLockPath(filePath);\n\n let gotLock = false;\n\n for (let attempt = 0; attempt < LOCK_MAX_RETRIES; attempt++) {\n if (acquireFileLock(fileLockPath, lockId)) {\n gotLock = true;\n break;\n }\n\n // Wait and retry\n if (attempt < LOCK_MAX_RETRIES - 1) {\n await sleep(LOCK_RETRY_DELAY_MS);\n }\n }\n\n if (!gotLock) {\n return null;\n }\n\n // Return release function\n return async () => {\n releaseFileLock(fileLockPath, lockId);\n };\n}\n\n/**\n * Execute a function while holding a lock\n * Automatically acquires and releases the lock\n */\nexport async function withLock<T>(\n filePath: string,\n fn: () => T | Promise<T>\n): Promise<T> {\n const release = await acquireLock(filePath);\n\n if (!release) {\n throw new Error(`Failed to acquire lock for: ${filePath}`);\n }\n\n try {\n return await fn();\n } finally {\n await release();\n }\n}\n\n/**\n * Graceful shutdown - no-op (file locks don't need explicit cleanup)\n */\nexport async function closeLockClient(): Promise<void> {\n // No-op: file-based locks are self-cleaning via TTL\n}\n"],"mappings":"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","names":["readFileSync","writeFileSync","existsSync","mkdirSync","join","dirname","join","existsSync","readFileSync","statSync","dirname","mkdirSync","writeFileSync"]}
|