va-claw 0.1.4 → 0.2.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/va-claw-bundle.mjs +152 -71
- package/package.json +4 -1
- package/packages/cli/dist/.tsbuildinfo +1 -1
- package/packages/cli/dist/handlers.d.ts.map +1 -1
- package/packages/cli/dist/handlers.js +13 -2
- package/packages/cli/dist/handlers.js.map +1 -1
- package/packages/identity/dist/.tsbuildinfo +1 -1
- package/packages/identity/dist/render.d.ts.map +1 -1
- package/packages/identity/dist/render.js +12 -0
- package/packages/identity/dist/render.js.map +1 -1
- package/packages/memory/dist/.tsbuildinfo +1 -1
- package/packages/memory/dist/embedding.d.ts +11 -1
- package/packages/memory/dist/embedding.d.ts.map +1 -1
- package/packages/memory/dist/embedding.js +44 -15
- package/packages/memory/dist/embedding.js.map +1 -1
- package/packages/memory/dist/memory-store.d.ts +3 -0
- package/packages/memory/dist/memory-store.d.ts.map +1 -1
- package/packages/memory/dist/memory-store.js +58 -18
- package/packages/memory/dist/memory-store.js.map +1 -1
- package/packages/memory/dist/sqlite.js.map +1 -1
- package/packages/memory/package.json +3 -0
- package/skills/memory-protocol.md +48 -0
package/dist/va-claw-bundle.mjs
CHANGED
|
@@ -149,6 +149,12 @@ function toClaudeMdSnippet(config) {
|
|
|
149
149
|
"- Manage claws with `va-claw claw list | add | set | remove | heartbeat`.",
|
|
150
150
|
'- If asked "va/claw \u5728\u5E72\u4EC0\u4E48" / "my claws are doing what" / similar fleet questions, call `va-claw protocol --text` and answer from it.',
|
|
151
151
|
'- If the user asks a non-technical phrasing like "\u73B0\u5728\u90FD\u5728\u5E72\u561B", interpret it as a fleet status request and run `va-claw protocol --text`.',
|
|
152
|
+
"",
|
|
153
|
+
"Memory protocol:",
|
|
154
|
+
'- At session start, run `va-claw memory recall "<current topic or task>"` before answering.',
|
|
155
|
+
'- After important work, run `va-claw memory memorize "<key>" "<essence>" --tags <tags> --importance <0.0-1.0>`.',
|
|
156
|
+
"- Use importance `0.8-1.0` for decisions or hard-won knowledge; use `0.5` for routine outputs.",
|
|
157
|
+
"- Do not memorize every message; store only things worth remembering across sessions.",
|
|
152
158
|
"<!-- va-claw:identity:end -->"
|
|
153
159
|
].join("\n");
|
|
154
160
|
}
|
|
@@ -172,7 +178,13 @@ function toCodexSystemPrompt(config) {
|
|
|
172
178
|
"Use `va-claw protocol` in terminal to get long-running claw state.",
|
|
173
179
|
'Use `va-claw protocol --text` when a user asks in plain language, including Chinese phrases like "va/claw \u5728\u5E72\u4EC0\u4E48".',
|
|
174
180
|
"Use `va-claw claw list` and `va-claw claw set <name> --status <status>` to manage claws.",
|
|
175
|
-
"If the user asks what claws are doing, run `va-claw protocol --text` and summarize only from that output."
|
|
181
|
+
"If the user asks what claws are doing, run `va-claw protocol --text` and summarize only from that output.",
|
|
182
|
+
"",
|
|
183
|
+
"Memory protocol:",
|
|
184
|
+
'At session start, run `va-claw memory recall "<current topic or task>"` before answering.',
|
|
185
|
+
'After important work, run `va-claw memory memorize "<key>" "<essence>" --tags <tags> --importance <0.0-1.0>`.',
|
|
186
|
+
"Use importance `0.8-1.0` for decisions or hard-won knowledge; use `0.5` for routine outputs.",
|
|
187
|
+
"Do not memorize every message; store only things worth remembering across sessions."
|
|
176
188
|
].join("\n");
|
|
177
189
|
}
|
|
178
190
|
|
|
@@ -947,31 +959,40 @@ var E = class {
|
|
|
947
959
|
// packages/daemon/dist/wake-cycle.js
|
|
948
960
|
import { spawn } from "node:child_process";
|
|
949
961
|
import { appendFile, mkdir as mkdir3 } from "node:fs/promises";
|
|
950
|
-
import { homedir as
|
|
962
|
+
import { homedir as homedir5 } from "node:os";
|
|
951
963
|
import { dirname as dirname3, resolve as resolve3 } from "node:path";
|
|
952
964
|
|
|
953
965
|
// packages/memory/dist/default-store.js
|
|
954
|
-
import { homedir as
|
|
955
|
-
import { join } from "node:path";
|
|
966
|
+
import { homedir as homedir3 } from "node:os";
|
|
967
|
+
import { join as join2 } from "node:path";
|
|
956
968
|
|
|
957
969
|
// packages/memory/dist/memory-store.js
|
|
958
970
|
import { randomUUID } from "node:crypto";
|
|
959
971
|
|
|
960
972
|
// packages/memory/dist/embedding.js
|
|
961
|
-
|
|
973
|
+
import { homedir as homedir2 } from "node:os";
|
|
974
|
+
import { join } from "node:path";
|
|
975
|
+
var EMBEDDING_DIMENSIONS = 384;
|
|
976
|
+
var EMBEDDING_MODEL = "Xenova/paraphrase-multilingual-MiniLM-L12-v2";
|
|
977
|
+
var EMBEDDING_CACHE_DIR = join(homedir2(), ".va-claw", "models");
|
|
978
|
+
var embeddingExtractorPromise;
|
|
979
|
+
var embeddingExtractorOverride;
|
|
962
980
|
function buildSearchText(text2, metadata) {
|
|
963
981
|
const metadataText = metadata ? flattenMetadata(metadata).join(" ") : "";
|
|
964
982
|
return `${text2} ${metadataText}`.trim().toLowerCase();
|
|
965
983
|
}
|
|
966
|
-
function createEmbedding(input) {
|
|
967
|
-
const
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
const index = Math.abs(hash) % EMBEDDING_DIMENSIONS;
|
|
971
|
-
vector[index] += hash < 0 ? -1 : 1;
|
|
984
|
+
async function createEmbedding(input) {
|
|
985
|
+
const normalizedInput = input.trim();
|
|
986
|
+
if (!normalizedInput) {
|
|
987
|
+
return Array.from({ length: EMBEDDING_DIMENSIONS }, () => 0);
|
|
972
988
|
}
|
|
973
|
-
const
|
|
974
|
-
|
|
989
|
+
const extractor = await getEmbeddingExtractor();
|
|
990
|
+
const tensor = await extractor(normalizedInput, { pooling: "mean", normalize: true });
|
|
991
|
+
const vector = Array.from(tensor.data);
|
|
992
|
+
if (vector.length !== EMBEDDING_DIMENSIONS) {
|
|
993
|
+
throw new Error(`Expected ${EMBEDDING_DIMENSIONS}-dim embedding from ${EMBEDDING_MODEL}, received ${vector.length}.`);
|
|
994
|
+
}
|
|
995
|
+
return vector;
|
|
975
996
|
}
|
|
976
997
|
function cosineSimilarity(left, right) {
|
|
977
998
|
const size = Math.min(left.length, right.length);
|
|
@@ -1005,13 +1026,25 @@ function flattenMetadata(value) {
|
|
|
1005
1026
|
}
|
|
1006
1027
|
return [];
|
|
1007
1028
|
}
|
|
1008
|
-
function
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
hash ^= token.charCodeAt(index);
|
|
1012
|
-
hash = Math.imul(hash, 16777619);
|
|
1029
|
+
async function getEmbeddingExtractor() {
|
|
1030
|
+
if (embeddingExtractorOverride) {
|
|
1031
|
+
return embeddingExtractorOverride;
|
|
1013
1032
|
}
|
|
1014
|
-
|
|
1033
|
+
if (!embeddingExtractorPromise) {
|
|
1034
|
+
embeddingExtractorPromise = loadEmbeddingExtractor().catch((error) => {
|
|
1035
|
+
embeddingExtractorPromise = void 0;
|
|
1036
|
+
throw error;
|
|
1037
|
+
});
|
|
1038
|
+
}
|
|
1039
|
+
return embeddingExtractorPromise;
|
|
1040
|
+
}
|
|
1041
|
+
async function loadEmbeddingExtractor() {
|
|
1042
|
+
const transformers = await import("@huggingface/transformers");
|
|
1043
|
+
process.env.HF_HOME ??= EMBEDDING_CACHE_DIR;
|
|
1044
|
+
process.env.TRANSFORMERS_CACHE ??= EMBEDDING_CACHE_DIR;
|
|
1045
|
+
transformers.env.cacheDir = EMBEDDING_CACHE_DIR;
|
|
1046
|
+
const extractor = await transformers.pipeline("feature-extraction", EMBEDDING_MODEL);
|
|
1047
|
+
return extractor;
|
|
1015
1048
|
}
|
|
1016
1049
|
|
|
1017
1050
|
// packages/memory/dist/forgetting-curve.js
|
|
@@ -1213,8 +1246,10 @@ var KEYWORD_WEIGHTS = {
|
|
|
1213
1246
|
};
|
|
1214
1247
|
var MemoryStore = class {
|
|
1215
1248
|
db;
|
|
1249
|
+
embeddingEnabled;
|
|
1216
1250
|
constructor(options = {}) {
|
|
1217
1251
|
this.db = new SqliteMemoryDb(options);
|
|
1252
|
+
this.embeddingEnabled = this.db.vectorAvailable;
|
|
1218
1253
|
}
|
|
1219
1254
|
async memorize(key, essence, options = {}) {
|
|
1220
1255
|
const existing = this.db.getByKey(key);
|
|
@@ -1238,7 +1273,7 @@ var MemoryStore = class {
|
|
|
1238
1273
|
metadata: existingEntry?.metadata ? JSON.stringify(existingEntry.metadata) : null,
|
|
1239
1274
|
created_at: existingEntry?.createdAt ?? now,
|
|
1240
1275
|
search_text: searchText,
|
|
1241
|
-
embedding: this.
|
|
1276
|
+
embedding: await this.createStoredEmbedding(searchText),
|
|
1242
1277
|
key,
|
|
1243
1278
|
tags: JSON.stringify(tags),
|
|
1244
1279
|
trigger_conditions: JSON.stringify(triggerConditions),
|
|
@@ -1282,7 +1317,7 @@ var MemoryStore = class {
|
|
|
1282
1317
|
trigger_conditions: JSON.stringify(normalizeStringArray(nextTriggerConditions)),
|
|
1283
1318
|
importance: nextImportance,
|
|
1284
1319
|
search_text: searchText,
|
|
1285
|
-
embedding: this.
|
|
1320
|
+
embedding: await this.createStoredEmbedding(searchText, searchText === row.search_text ? row.embedding : null),
|
|
1286
1321
|
updated_at: nowString()
|
|
1287
1322
|
};
|
|
1288
1323
|
this.db.upsertByKey(updated);
|
|
@@ -1294,26 +1329,28 @@ var MemoryStore = class {
|
|
|
1294
1329
|
async recall(query, limit = 5) {
|
|
1295
1330
|
const safeLimit = Number.isFinite(limit) ? Math.max(0, Math.floor(limit)) : 5;
|
|
1296
1331
|
const tokens = keywordTokens(query);
|
|
1297
|
-
|
|
1332
|
+
const queryEmbedding = await this.loadQueryEmbedding(query);
|
|
1333
|
+
if (tokens.length === 0 && !queryEmbedding) {
|
|
1298
1334
|
return [];
|
|
1299
1335
|
}
|
|
1300
1336
|
const now = nowString();
|
|
1301
|
-
const
|
|
1302
|
-
|
|
1337
|
+
const scoredRows = this.db.listAll().map((row) => {
|
|
1338
|
+
const entry = toMemoryEntry(row);
|
|
1303
1339
|
const keywordScore = computeKeywordScore(entry, tokens);
|
|
1304
|
-
|
|
1340
|
+
const embeddingScore = queryEmbedding && row.embedding ? cosineSimilarity(queryEmbedding, parseEmbedding(row.embedding)) : 0;
|
|
1341
|
+
const relevanceScore = keywordScore > 0 ? keywordScore : embeddingScore;
|
|
1342
|
+
if (relevanceScore <= 0) {
|
|
1305
1343
|
return void 0;
|
|
1306
1344
|
}
|
|
1307
1345
|
const retention = computeRetention(entry.strength, entry.lastAccessedAt ?? entry.updatedAt, entry.decayTau, entry.importance, entry.accessCount);
|
|
1308
1346
|
return {
|
|
1309
1347
|
entry,
|
|
1310
1348
|
keywordScore,
|
|
1311
|
-
retention
|
|
1349
|
+
retention,
|
|
1350
|
+
finalScore: relevanceScore * 0.7 + retention * 0.3
|
|
1312
1351
|
};
|
|
1313
|
-
})
|
|
1314
|
-
|
|
1315
|
-
return { ...candidate, finalScore };
|
|
1316
|
-
}).sort((left, right) => right.finalScore - left.finalScore || right.retention - left.retention);
|
|
1352
|
+
});
|
|
1353
|
+
const scored = scoredRows.filter((candidate) => candidate !== void 0).sort((left, right) => right.finalScore - left.finalScore || right.retention - left.retention);
|
|
1317
1354
|
const results = [];
|
|
1318
1355
|
for (const selected of scored.slice(0, safeLimit)) {
|
|
1319
1356
|
const strengthenedStrength = reinforceOnAccess(selected.entry.strength, selected.entry.importance);
|
|
@@ -1391,7 +1428,7 @@ var MemoryStore = class {
|
|
|
1391
1428
|
last_accessed_at: nowIso,
|
|
1392
1429
|
updated_at: nowIso,
|
|
1393
1430
|
search_text: searchText,
|
|
1394
|
-
embedding: this.
|
|
1431
|
+
embedding: await this.createStoredEmbedding(searchText, row.embedding)
|
|
1395
1432
|
};
|
|
1396
1433
|
this.db.upsertByKey(updated);
|
|
1397
1434
|
survivors.push(toMemoryEntry(updated));
|
|
@@ -1437,9 +1474,16 @@ var MemoryStore = class {
|
|
|
1437
1474
|
if (safeTopK <= 0) {
|
|
1438
1475
|
return [];
|
|
1439
1476
|
}
|
|
1440
|
-
if (
|
|
1441
|
-
|
|
1442
|
-
|
|
1477
|
+
if (query.trim().length === 0) {
|
|
1478
|
+
return this.db.searchByKeywords(query, safeTopK).map((row) => toMemoryEntry(row));
|
|
1479
|
+
}
|
|
1480
|
+
const queryEmbedding = await this.loadQueryEmbedding(query);
|
|
1481
|
+
if (queryEmbedding) {
|
|
1482
|
+
const tokens = keywordTokens(query);
|
|
1483
|
+
return this.db.listAll().map((row) => {
|
|
1484
|
+
const score = row.embedding ? cosineSimilarity(queryEmbedding, parseEmbedding(row.embedding)) : computeKeywordScore(toMemoryEntry(row), tokens);
|
|
1485
|
+
return { row, score };
|
|
1486
|
+
}).filter(({ score }) => score > 0).sort((left, right) => right.score - left.score || compareRows(left.row, right.row)).slice(0, safeTopK).map(({ row }) => toMemoryEntry(row));
|
|
1443
1487
|
}
|
|
1444
1488
|
return this.db.searchByKeywords(query, safeTopK).map((row) => toMemoryEntry(row));
|
|
1445
1489
|
}
|
|
@@ -1467,7 +1511,7 @@ var MemoryStore = class {
|
|
|
1467
1511
|
...row,
|
|
1468
1512
|
metadata: serializedMetadata,
|
|
1469
1513
|
search_text: searchText,
|
|
1470
|
-
embedding: this.
|
|
1514
|
+
embedding: await this.createStoredEmbedding(searchText, row.embedding)
|
|
1471
1515
|
});
|
|
1472
1516
|
}
|
|
1473
1517
|
}
|
|
@@ -1479,6 +1523,18 @@ var MemoryStore = class {
|
|
|
1479
1523
|
close() {
|
|
1480
1524
|
this.db.close();
|
|
1481
1525
|
}
|
|
1526
|
+
async createStoredEmbedding(searchText, fallback = null) {
|
|
1527
|
+
if (!this.embeddingEnabled) {
|
|
1528
|
+
return null;
|
|
1529
|
+
}
|
|
1530
|
+
return createStoredEmbedding(searchText, fallback);
|
|
1531
|
+
}
|
|
1532
|
+
async loadQueryEmbedding(query) {
|
|
1533
|
+
if (!this.embeddingEnabled) {
|
|
1534
|
+
return null;
|
|
1535
|
+
}
|
|
1536
|
+
return loadQueryEmbedding(query);
|
|
1537
|
+
}
|
|
1482
1538
|
};
|
|
1483
1539
|
function buildSearchTextFromParts(essence, context) {
|
|
1484
1540
|
const searchMetadata = {
|
|
@@ -1518,6 +1574,20 @@ function parseEmbedding(embedding) {
|
|
|
1518
1574
|
const value = JSON.parse(embedding);
|
|
1519
1575
|
return Array.isArray(value) ? value.filter((item) => typeof item === "number") : [];
|
|
1520
1576
|
}
|
|
1577
|
+
async function createStoredEmbedding(searchText, fallback = null) {
|
|
1578
|
+
try {
|
|
1579
|
+
return JSON.stringify(await createEmbedding(searchText));
|
|
1580
|
+
} catch {
|
|
1581
|
+
return fallback;
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
async function loadQueryEmbedding(query) {
|
|
1585
|
+
try {
|
|
1586
|
+
return await createEmbedding(query);
|
|
1587
|
+
} catch {
|
|
1588
|
+
return null;
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1521
1591
|
function parseMetadata(metadata) {
|
|
1522
1592
|
if (!metadata) {
|
|
1523
1593
|
return null;
|
|
@@ -1595,7 +1665,7 @@ function toISOString(time) {
|
|
|
1595
1665
|
var defaultStore = null;
|
|
1596
1666
|
function createMemoryStore(options = {}) {
|
|
1597
1667
|
return new MemoryStore({
|
|
1598
|
-
dbPath: options.dbPath ??
|
|
1668
|
+
dbPath: options.dbPath ?? join2(homedir3(), ".va-claw", "memory.db"),
|
|
1599
1669
|
enableVectorSearch: options.enableVectorSearch,
|
|
1600
1670
|
vectorExtensionPath: options.vectorExtensionPath
|
|
1601
1671
|
});
|
|
@@ -1758,16 +1828,16 @@ function splitInlineArray(value) {
|
|
|
1758
1828
|
}
|
|
1759
1829
|
|
|
1760
1830
|
// packages/skills/dist/paths.js
|
|
1761
|
-
import { homedir as
|
|
1762
|
-
import { isAbsolute, join as
|
|
1831
|
+
import { homedir as homedir4 } from "node:os";
|
|
1832
|
+
import { isAbsolute, join as join3, resolve as resolve2 } from "node:path";
|
|
1763
1833
|
var overrides = {};
|
|
1764
1834
|
function resolveInstalledSkillsDir() {
|
|
1765
|
-
const baseDir = overrides.homeDir ? resolve2(overrides.homeDir) : resolve2(
|
|
1766
|
-
return
|
|
1835
|
+
const baseDir = overrides.homeDir ? resolve2(overrides.homeDir) : resolve2(homedir4(), ".va-claw");
|
|
1836
|
+
return join3(baseDir, "skills");
|
|
1767
1837
|
}
|
|
1768
1838
|
function resolveProjectSkillsDir() {
|
|
1769
1839
|
const baseDir = overrides.projectDir ? resolve2(overrides.projectDir) : process.cwd();
|
|
1770
|
-
return
|
|
1840
|
+
return join3(baseDir, "skills");
|
|
1771
1841
|
}
|
|
1772
1842
|
function resolveSkillLookupDirs(dir) {
|
|
1773
1843
|
if (dir) {
|
|
@@ -1777,10 +1847,10 @@ function resolveSkillLookupDirs(dir) {
|
|
|
1777
1847
|
}
|
|
1778
1848
|
function resolvePathInput(value) {
|
|
1779
1849
|
if (value === "~") {
|
|
1780
|
-
return
|
|
1850
|
+
return homedir4();
|
|
1781
1851
|
}
|
|
1782
1852
|
if (value.startsWith("~/")) {
|
|
1783
|
-
return resolve2(
|
|
1853
|
+
return resolve2(homedir4(), value.slice(2));
|
|
1784
1854
|
}
|
|
1785
1855
|
return isAbsolute(value) ? value : resolve2(value);
|
|
1786
1856
|
}
|
|
@@ -1816,7 +1886,7 @@ function normalize(value) {
|
|
|
1816
1886
|
|
|
1817
1887
|
// packages/skills/dist/store.js
|
|
1818
1888
|
import { access, mkdir as mkdir2, readFile as readFile2, readdir, rm, writeFile as writeFile2 } from "node:fs/promises";
|
|
1819
|
-
import { join as
|
|
1889
|
+
import { join as join4 } from "node:path";
|
|
1820
1890
|
async function loadSkill(nameOrPath) {
|
|
1821
1891
|
const path = await resolveSkillPath(nameOrPath);
|
|
1822
1892
|
return readSkillFile(path);
|
|
@@ -1836,14 +1906,14 @@ async function listSkills(dir) {
|
|
|
1836
1906
|
return skills;
|
|
1837
1907
|
}
|
|
1838
1908
|
async function installSkill(content, name) {
|
|
1839
|
-
const skillPath =
|
|
1909
|
+
const skillPath = join4(resolveInstalledSkillsDir(), toSkillFileName(name));
|
|
1840
1910
|
parseSkillMarkdown(content, skillPath);
|
|
1841
1911
|
await mkdir2(resolveInstalledSkillsDir(), { recursive: true });
|
|
1842
1912
|
await writeFile2(skillPath, content, "utf8");
|
|
1843
1913
|
return skillPath;
|
|
1844
1914
|
}
|
|
1845
1915
|
async function removeSkill(name) {
|
|
1846
|
-
await rm(
|
|
1916
|
+
await rm(join4(resolveInstalledSkillsDir(), toSkillFileName(name)), { force: true });
|
|
1847
1917
|
}
|
|
1848
1918
|
function injectSkillIntoPrompt(skill, basePrompt) {
|
|
1849
1919
|
const prompt = basePrompt.trimEnd();
|
|
@@ -1853,7 +1923,7 @@ function injectSkillIntoPrompt(skill, basePrompt) {
|
|
|
1853
1923
|
${skillBlock}`;
|
|
1854
1924
|
}
|
|
1855
1925
|
async function resolveSkillPath(nameOrPath) {
|
|
1856
|
-
const candidates = looksLikePath(nameOrPath) ? [resolvePathInput(nameOrPath)] : resolveSkillLookupDirs().map((dir) =>
|
|
1926
|
+
const candidates = looksLikePath(nameOrPath) ? [resolvePathInput(nameOrPath)] : resolveSkillLookupDirs().map((dir) => join4(dir, toSkillFileName(nameOrPath)));
|
|
1857
1927
|
for (const candidate of candidates) {
|
|
1858
1928
|
if (await exists(candidate)) {
|
|
1859
1929
|
return candidate;
|
|
@@ -1866,7 +1936,7 @@ async function readSkillsFromDir(dir) {
|
|
|
1866
1936
|
return [];
|
|
1867
1937
|
}
|
|
1868
1938
|
const names = (await readdir(dir)).filter((entry) => entry.toLowerCase().endsWith(".md")).sort();
|
|
1869
|
-
return Promise.all(names.map((name) => readSkillFile(
|
|
1939
|
+
return Promise.all(names.map((name) => readSkillFile(join4(dir, name))));
|
|
1870
1940
|
}
|
|
1871
1941
|
async function readSkillFile(path) {
|
|
1872
1942
|
return parseSkillMarkdown(await readFile2(path, "utf8"), path);
|
|
@@ -2085,7 +2155,7 @@ async function writeWakeLogSafe(entry, deps) {
|
|
|
2085
2155
|
}
|
|
2086
2156
|
}
|
|
2087
2157
|
async function writeWakeLog(entry) {
|
|
2088
|
-
const logPath = resolve3(
|
|
2158
|
+
const logPath = resolve3(homedir5(), ".va-claw", "wake.log");
|
|
2089
2159
|
await mkdir3(dirname3(logPath), { recursive: true });
|
|
2090
2160
|
await appendFile(logPath, `${JSON.stringify(entry)}
|
|
2091
2161
|
`, "utf8");
|
|
@@ -2164,24 +2234,24 @@ import { dirname as dirname5 } from "node:path";
|
|
|
2164
2234
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
2165
2235
|
|
|
2166
2236
|
// packages/daemon/dist/service-files.js
|
|
2167
|
-
import { homedir as
|
|
2168
|
-
import { dirname as dirname4, join as
|
|
2237
|
+
import { homedir as homedir6 } from "node:os";
|
|
2238
|
+
import { dirname as dirname4, join as join5, resolve as resolve4 } from "node:path";
|
|
2169
2239
|
import { fileURLToPath } from "node:url";
|
|
2170
2240
|
function createServiceDefinition(type) {
|
|
2171
2241
|
const packageRoot = resolve4(dirname4(fileURLToPath(import.meta.url)), "..");
|
|
2172
2242
|
const repoRoot = resolve4(packageRoot, "../..");
|
|
2173
|
-
const runnerPath =
|
|
2243
|
+
const runnerPath = join5(packageRoot, "dist", "runner.js");
|
|
2174
2244
|
const nodePath = process.execPath;
|
|
2175
2245
|
if (type === "launchd") {
|
|
2176
2246
|
return {
|
|
2177
|
-
path:
|
|
2247
|
+
path: join5(homedir6(), "Library", "LaunchAgents", "com.va-claw.daemon.plist"),
|
|
2178
2248
|
content: renderLaunchdPlist(repoRoot, [nodePath, runnerPath]),
|
|
2179
2249
|
command: "launchctl",
|
|
2180
|
-
args: ["load",
|
|
2250
|
+
args: ["load", join5(homedir6(), "Library", "LaunchAgents", "com.va-claw.daemon.plist")]
|
|
2181
2251
|
};
|
|
2182
2252
|
}
|
|
2183
2253
|
return {
|
|
2184
|
-
path:
|
|
2254
|
+
path: join5(homedir6(), ".config", "systemd", "user", "va-claw.service"),
|
|
2185
2255
|
content: renderSystemdUnit(repoRoot, [nodePath, runnerPath]),
|
|
2186
2256
|
command: "systemctl",
|
|
2187
2257
|
args: ["--user", "enable", "--now", "va-claw.service"]
|
|
@@ -2191,7 +2261,7 @@ function createUninstallCommand(type) {
|
|
|
2191
2261
|
if (type === "launchd") {
|
|
2192
2262
|
return {
|
|
2193
2263
|
command: "launchctl",
|
|
2194
|
-
args: ["unload",
|
|
2264
|
+
args: ["unload", join5(homedir6(), "Library", "LaunchAgents", "com.va-claw.daemon.plist")]
|
|
2195
2265
|
};
|
|
2196
2266
|
}
|
|
2197
2267
|
return {
|
|
@@ -2273,8 +2343,8 @@ function runCommand(command, args, allowFailure = false) {
|
|
|
2273
2343
|
|
|
2274
2344
|
// packages/cli/dist/install-files.js
|
|
2275
2345
|
import { access as access2, mkdir as mkdir5, readFile as readFile3, writeFile as writeFile4 } from "node:fs/promises";
|
|
2276
|
-
import { homedir as
|
|
2277
|
-
import { dirname as dirname6, join as
|
|
2346
|
+
import { homedir as homedir7 } from "node:os";
|
|
2347
|
+
import { dirname as dirname6, join as join6 } from "node:path";
|
|
2278
2348
|
var CLAUDE_MARKERS = {
|
|
2279
2349
|
start: "<!-- va-claw:identity:start -->",
|
|
2280
2350
|
end: "<!-- va-claw:identity:end -->"
|
|
@@ -2283,17 +2353,17 @@ var CODEX_MARKERS = {
|
|
|
2283
2353
|
start: "<!-- va-claw:codex:start -->",
|
|
2284
2354
|
end: "<!-- va-claw:codex:end -->"
|
|
2285
2355
|
};
|
|
2286
|
-
function resolveClaudeMdPath(home =
|
|
2287
|
-
return
|
|
2356
|
+
function resolveClaudeMdPath(home = homedir7()) {
|
|
2357
|
+
return join6(home, ".claude", "CLAUDE.md");
|
|
2288
2358
|
}
|
|
2289
|
-
function resolveCodexInstructionsPath(home =
|
|
2290
|
-
return
|
|
2359
|
+
function resolveCodexInstructionsPath(home = homedir7()) {
|
|
2360
|
+
return join6(home, ".codex", "instructions.md");
|
|
2291
2361
|
}
|
|
2292
|
-
function resolveMemoryDbPath(home =
|
|
2293
|
-
return
|
|
2362
|
+
function resolveMemoryDbPath(home = homedir7()) {
|
|
2363
|
+
return join6(home, ".va-claw", "memory.db");
|
|
2294
2364
|
}
|
|
2295
|
-
function resolveClawRegistryPath(home =
|
|
2296
|
-
return
|
|
2365
|
+
function resolveClawRegistryPath(home = homedir7()) {
|
|
2366
|
+
return join6(home, ".va-claw", "claws.json");
|
|
2297
2367
|
}
|
|
2298
2368
|
async function fileExists(path) {
|
|
2299
2369
|
try {
|
|
@@ -2632,8 +2702,8 @@ function parseMetadata2(raw) {
|
|
|
2632
2702
|
}
|
|
2633
2703
|
|
|
2634
2704
|
// packages/cli/dist/platform.js
|
|
2635
|
-
import { homedir as
|
|
2636
|
-
import { join as
|
|
2705
|
+
import { homedir as homedir8 } from "node:os";
|
|
2706
|
+
import { join as join7 } from "node:path";
|
|
2637
2707
|
function detectServiceType(platform) {
|
|
2638
2708
|
if (platform === "darwin") {
|
|
2639
2709
|
return "launchd";
|
|
@@ -2660,7 +2730,7 @@ function stopInstalledService(type, spawnSync4) {
|
|
|
2660
2730
|
spawnSync4("systemctl", ["--user", "stop", "va-claw.service"], { encoding: "utf8" });
|
|
2661
2731
|
}
|
|
2662
2732
|
function resolveLaunchdPath() {
|
|
2663
|
-
return
|
|
2733
|
+
return join7(homedir8(), "Library", "LaunchAgents", "com.va-claw.daemon.plist");
|
|
2664
2734
|
}
|
|
2665
2735
|
|
|
2666
2736
|
// packages/cli/dist/claw-store.js
|
|
@@ -2799,6 +2869,7 @@ async function saveClawRegistry(registryPath, registry) {
|
|
|
2799
2869
|
|
|
2800
2870
|
// packages/cli/dist/handlers.js
|
|
2801
2871
|
var CLAW_FLEET_PROTOCOL_SKILL_URL = "https://raw.githubusercontent.com/Vadaski/va-claw/main/skills/claw-fleet-protocol.md";
|
|
2872
|
+
var MEMORY_SKILL_URL = "https://raw.githubusercontent.com/Vadaski/va-claw/main/skills/memory-protocol.md";
|
|
2802
2873
|
async function runInstall(target, deps) {
|
|
2803
2874
|
const installTarget = normalizeInstallTarget(target);
|
|
2804
2875
|
const config = await deps.fileExists(deps.configPath) ? await deps.loadIdentity() : await deps.runInstallWizard();
|
|
@@ -2819,6 +2890,10 @@ async function runInstall(target, deps) {
|
|
|
2819
2890
|
if (fleetSkillName) {
|
|
2820
2891
|
summary.push(`Claw fleet protocol skill: ${fleetSkillName}`);
|
|
2821
2892
|
}
|
|
2893
|
+
const memorySkillName = await installMemoryProtocolSkill(deps);
|
|
2894
|
+
if (memorySkillName) {
|
|
2895
|
+
summary.push(`Memory protocol skill: ${memorySkillName}`);
|
|
2896
|
+
}
|
|
2822
2897
|
for (const line of summary) {
|
|
2823
2898
|
writeLine(deps.stdout, line);
|
|
2824
2899
|
}
|
|
@@ -2978,13 +3053,19 @@ async function buildProtocolReport(deps) {
|
|
|
2978
3053
|
};
|
|
2979
3054
|
}
|
|
2980
3055
|
async function installFleetProtocolSkill(deps) {
|
|
3056
|
+
return installRemoteSkill(deps, CLAW_FLEET_PROTOCOL_SKILL_URL, "claw-fleet-protocol");
|
|
3057
|
+
}
|
|
3058
|
+
async function installMemoryProtocolSkill(deps) {
|
|
3059
|
+
return installRemoteSkill(deps, MEMORY_SKILL_URL, "memory-protocol");
|
|
3060
|
+
}
|
|
3061
|
+
async function installRemoteSkill(deps, url, name) {
|
|
2981
3062
|
try {
|
|
2982
|
-
const response = await fetch(
|
|
3063
|
+
const response = await fetch(url);
|
|
2983
3064
|
if (!response.ok) {
|
|
2984
3065
|
return null;
|
|
2985
3066
|
}
|
|
2986
3067
|
const content = await response.text();
|
|
2987
|
-
return await deps.skillInstall(content,
|
|
3068
|
+
return await deps.skillInstall(content, name);
|
|
2988
3069
|
} catch {
|
|
2989
3070
|
return null;
|
|
2990
3071
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "va-claw",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Persistent memory, identity, and wake-loop daemon for Claude Code & Codex",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -38,6 +38,9 @@
|
|
|
38
38
|
"bundle": "node scripts/bundle.mjs",
|
|
39
39
|
"prepublishOnly": "pnpm run build && node scripts/bundle.mjs"
|
|
40
40
|
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@huggingface/transformers": "latest"
|
|
43
|
+
},
|
|
41
44
|
"devDependencies": {
|
|
42
45
|
"esbuild": "^0.27.3",
|
|
43
46
|
"typescript": "file:vendor/typescript"
|