opencode-swarm 7.36.0 → 7.37.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/dist/cli/index.js +399 -21
- package/dist/index.js +399 -112
- package/dist/memory/sqlite-provider.d.ts +19 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var package_default;
|
|
|
34
34
|
var init_package = __esm(() => {
|
|
35
35
|
package_default = {
|
|
36
36
|
name: "opencode-swarm",
|
|
37
|
-
version: "7.
|
|
37
|
+
version: "7.37.0",
|
|
38
38
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
39
39
|
main: "dist/index.js",
|
|
40
40
|
types: "dist/index.d.ts",
|
|
@@ -45714,6 +45714,102 @@ var init_curator_decision_helpers = __esm(() => {
|
|
|
45714
45714
|
init_schema2();
|
|
45715
45715
|
});
|
|
45716
45716
|
|
|
45717
|
+
// src/memory/role-profiles.ts
|
|
45718
|
+
function resolveMemoryRecallProfile(agentRole) {
|
|
45719
|
+
const role = normalizeMemoryAgentRole(agentRole);
|
|
45720
|
+
return MEMORY_RECALL_PROFILES[role] ?? MEMORY_RECALL_PROFILES.coder;
|
|
45721
|
+
}
|
|
45722
|
+
function normalizeMemoryAgentRole(agentRole) {
|
|
45723
|
+
const base = stripKnownSwarmPrefix(agentRole ?? "architect");
|
|
45724
|
+
if (base === "reviewer" || base === "test_engineer")
|
|
45725
|
+
return "qa";
|
|
45726
|
+
if (base === "critic" || base === "critic_sounding_board" || base === "critic_drift_verifier" || base === "critic_hallucination_verifier") {
|
|
45727
|
+
return "security";
|
|
45728
|
+
}
|
|
45729
|
+
if (base === "curator_init" || base === "curator_phase")
|
|
45730
|
+
return "curator";
|
|
45731
|
+
if (base === "docs")
|
|
45732
|
+
return "sme";
|
|
45733
|
+
if (base === "architect" || base === "sme" || base === "coder" || base === "security" || base === "curator") {
|
|
45734
|
+
return base;
|
|
45735
|
+
}
|
|
45736
|
+
return "coder";
|
|
45737
|
+
}
|
|
45738
|
+
var MEMORY_RECALL_PROFILES;
|
|
45739
|
+
var init_role_profiles = __esm(() => {
|
|
45740
|
+
init_schema();
|
|
45741
|
+
MEMORY_RECALL_PROFILES = {
|
|
45742
|
+
architect: {
|
|
45743
|
+
kinds: [
|
|
45744
|
+
"project_fact",
|
|
45745
|
+
"architecture_decision",
|
|
45746
|
+
"repo_convention",
|
|
45747
|
+
"failure_pattern",
|
|
45748
|
+
"security_note"
|
|
45749
|
+
],
|
|
45750
|
+
maxItems: 10,
|
|
45751
|
+
tokenBudget: 1600
|
|
45752
|
+
},
|
|
45753
|
+
sme: {
|
|
45754
|
+
kinds: [
|
|
45755
|
+
"api_finding",
|
|
45756
|
+
"code_pattern",
|
|
45757
|
+
"repo_convention",
|
|
45758
|
+
"failure_pattern",
|
|
45759
|
+
"evidence"
|
|
45760
|
+
],
|
|
45761
|
+
maxItems: 8,
|
|
45762
|
+
tokenBudget: 1200
|
|
45763
|
+
},
|
|
45764
|
+
coder: {
|
|
45765
|
+
kinds: [
|
|
45766
|
+
"architecture_decision",
|
|
45767
|
+
"repo_convention",
|
|
45768
|
+
"code_pattern",
|
|
45769
|
+
"test_pattern",
|
|
45770
|
+
"failure_pattern"
|
|
45771
|
+
],
|
|
45772
|
+
maxItems: 8,
|
|
45773
|
+
tokenBudget: 1200
|
|
45774
|
+
},
|
|
45775
|
+
qa: {
|
|
45776
|
+
kinds: [
|
|
45777
|
+
"test_pattern",
|
|
45778
|
+
"failure_pattern",
|
|
45779
|
+
"repo_convention",
|
|
45780
|
+
"security_note"
|
|
45781
|
+
],
|
|
45782
|
+
maxItems: 8,
|
|
45783
|
+
tokenBudget: 1200
|
|
45784
|
+
},
|
|
45785
|
+
security: {
|
|
45786
|
+
kinds: [
|
|
45787
|
+
"security_note",
|
|
45788
|
+
"architecture_decision",
|
|
45789
|
+
"repo_convention",
|
|
45790
|
+
"evidence"
|
|
45791
|
+
],
|
|
45792
|
+
maxItems: 8,
|
|
45793
|
+
tokenBudget: 1200
|
|
45794
|
+
},
|
|
45795
|
+
curator: {
|
|
45796
|
+
kinds: [
|
|
45797
|
+
"project_fact",
|
|
45798
|
+
"architecture_decision",
|
|
45799
|
+
"repo_convention",
|
|
45800
|
+
"api_finding",
|
|
45801
|
+
"code_pattern",
|
|
45802
|
+
"test_pattern",
|
|
45803
|
+
"failure_pattern",
|
|
45804
|
+
"security_note",
|
|
45805
|
+
"evidence"
|
|
45806
|
+
],
|
|
45807
|
+
maxItems: 20,
|
|
45808
|
+
tokenBudget: 3000
|
|
45809
|
+
}
|
|
45810
|
+
};
|
|
45811
|
+
});
|
|
45812
|
+
|
|
45717
45813
|
// src/memory/scoring.ts
|
|
45718
45814
|
function tokenize(text) {
|
|
45719
45815
|
return new Set(text.toLowerCase().replace(/[^\w\s-]/g, " ").split(/\s+/).map((token) => token.trim()).filter(Boolean));
|
|
@@ -45767,13 +45863,16 @@ function kindProfileBoost(kind, request) {
|
|
|
45767
45863
|
return 0.5;
|
|
45768
45864
|
return request.kinds.includes(kind) ? 1 : 0;
|
|
45769
45865
|
}
|
|
45866
|
+
function roleProfileBoost(kind, context) {
|
|
45867
|
+
return context.roleProfileKinds?.has(kind) ? 1 : 0;
|
|
45868
|
+
}
|
|
45770
45869
|
function sameScope(a, b) {
|
|
45771
45870
|
return stableScopeKey(a) === stableScopeKey(b);
|
|
45772
45871
|
}
|
|
45773
45872
|
function scopeAllowed(recordScope, allowedScopes) {
|
|
45774
45873
|
return allowedScopes.some((scope) => sameScope(recordScope, scope));
|
|
45775
45874
|
}
|
|
45776
|
-
function scoreMemoryRecordDetailed(record3, request) {
|
|
45875
|
+
function scoreMemoryRecordDetailed(record3, request, context) {
|
|
45777
45876
|
if (!request.includeExpired && isExpired(record3)) {
|
|
45778
45877
|
return { item: null, skipReason: "filtered" };
|
|
45779
45878
|
}
|
|
@@ -45788,7 +45887,7 @@ function scoreMemoryRecordDetailed(record3, request) {
|
|
|
45788
45887
|
if (request.kinds && !request.kinds.includes(record3.kind)) {
|
|
45789
45888
|
return { item: null, skipReason: "filtered" };
|
|
45790
45889
|
}
|
|
45791
|
-
const queryTokens = request.mode === "injection" &&
|
|
45890
|
+
const queryTokens = request.mode === "injection" && context.taskTokens ? context.taskTokens : context.queryTokens;
|
|
45792
45891
|
const textTokens = tokenize(record3.text);
|
|
45793
45892
|
const tagTokens = tokenize(record3.tags.join(" "));
|
|
45794
45893
|
const fileTokens = tokenize([
|
|
@@ -45801,24 +45900,31 @@ function scoreMemoryRecordDetailed(record3, request) {
|
|
|
45801
45900
|
])
|
|
45802
45901
|
].filter((value) => typeof value === "string").join(" "));
|
|
45803
45902
|
const symbolTokens = tokenize(collectMetadataStrings(record3.metadata, ["symbol", "symbols"]).join(" "));
|
|
45804
|
-
const
|
|
45903
|
+
const kindTokens = tokenize(normalizeKindText(record3.kind));
|
|
45904
|
+
const sourceRefTokens = tokenize(record3.source.ref ?? "");
|
|
45905
|
+
const taskSearchTokens = unionTokens(textTokens, tagTokens, fileTokens, symbolTokens, kindTokens, sourceRefTokens);
|
|
45906
|
+
const taskTermOverlap = context.taskTokens ? overlap(context.taskTokens, taskSearchTokens) : 0;
|
|
45907
|
+
const kindQueryOverlap = overlap(queryTokens, kindTokens);
|
|
45805
45908
|
const textOverlap = overlap(queryTokens, textTokens);
|
|
45806
45909
|
const tagOverlap = overlap(queryTokens, tagTokens);
|
|
45807
45910
|
const fileOverlap = overlap(queryTokens, fileTokens);
|
|
45808
45911
|
const symbolOverlap = overlap(queryTokens, symbolTokens);
|
|
45809
45912
|
const kindMatch = request.kinds?.includes(record3.kind) ?? false;
|
|
45810
45913
|
const scopeMatch = scopeAllowed(record3.scope, request.scopes);
|
|
45914
|
+
const roleBoost = roleProfileBoost(record3.kind, context);
|
|
45811
45915
|
const hasQuerySignal = textOverlap > 0 || tagOverlap > 0 || fileOverlap > 0 || symbolOverlap > 0 || kindQueryOverlap > 0;
|
|
45812
45916
|
if (request.mode === "injection" && request.requireQuerySignal !== false && !hasQuerySignal) {
|
|
45813
45917
|
return { item: null, skipReason: "no_signal" };
|
|
45814
45918
|
}
|
|
45815
|
-
const score = textOverlap * 0.
|
|
45919
|
+
const score = textOverlap * 0.38 + tagOverlap * 0.16 + fileOverlap * 0.12 + symbolOverlap * 0.08 + taskTermOverlap * 0.08 + scopeSpecificityBoost(record3.scope) * 0.12 + kindProfileBoost(record3.kind, request) * 0.06 + roleBoost * 0.05 + record3.confidence * 0.08;
|
|
45816
45920
|
const reasonParts = [
|
|
45817
45921
|
textOverlap > 0 ? `text_overlap=${textOverlap.toFixed(2)}` : null,
|
|
45818
45922
|
tagOverlap > 0 ? `tag_overlap=${tagOverlap.toFixed(2)}` : null,
|
|
45819
45923
|
fileOverlap > 0 ? `file_overlap=${fileOverlap.toFixed(2)}` : null,
|
|
45820
45924
|
symbolOverlap > 0 ? `symbol_overlap=${symbolOverlap.toFixed(2)}` : null,
|
|
45925
|
+
taskTermOverlap > 0 ? `task_terms=${taskTermOverlap.toFixed(2)}` : null,
|
|
45821
45926
|
kindQueryOverlap > 0 ? `kind_query=${kindQueryOverlap.toFixed(2)}` : null,
|
|
45927
|
+
roleBoost > 0 ? "role_profile" : null,
|
|
45822
45928
|
`scope=${record3.scope.type}`,
|
|
45823
45929
|
`confidence=${record3.confidence.toFixed(2)}`
|
|
45824
45930
|
].filter(Boolean);
|
|
@@ -45840,6 +45946,7 @@ function scoreMemoryRecordDetailed(record3, request) {
|
|
|
45840
45946
|
}
|
|
45841
45947
|
function scoreMemoryRecordsWithDiagnostics(records, request) {
|
|
45842
45948
|
const minScore = request.minScore ?? 0;
|
|
45949
|
+
const context = createScoringContext(request);
|
|
45843
45950
|
const diagnostics = {
|
|
45844
45951
|
candidateCount: records.length,
|
|
45845
45952
|
preScoredFilteredCount: 0,
|
|
@@ -45850,7 +45957,7 @@ function scoreMemoryRecordsWithDiagnostics(records, request) {
|
|
|
45850
45957
|
};
|
|
45851
45958
|
const items = [];
|
|
45852
45959
|
for (const record3 of records) {
|
|
45853
|
-
const result = scoreMemoryRecordDetailed(record3, request);
|
|
45960
|
+
const result = scoreMemoryRecordDetailed(record3, request, context);
|
|
45854
45961
|
if (!result.item) {
|
|
45855
45962
|
if (result.skipReason === "filtered")
|
|
45856
45963
|
diagnostics.preScoredFilteredCount++;
|
|
@@ -45869,7 +45976,24 @@ function scoreMemoryRecordsWithDiagnostics(records, request) {
|
|
|
45869
45976
|
diagnostics.returnedCount = items.length;
|
|
45870
45977
|
return { items, diagnostics };
|
|
45871
45978
|
}
|
|
45979
|
+
function createScoringContext(request) {
|
|
45980
|
+
const taskTokens = request.task ? tokenize(request.task) : undefined;
|
|
45981
|
+
return {
|
|
45982
|
+
taskTokens,
|
|
45983
|
+
queryTokens: tokenize(request.query),
|
|
45984
|
+
roleProfileKinds: request.agentRole ? new Set(resolveMemoryRecallProfile(request.agentRole).kinds) : undefined
|
|
45985
|
+
};
|
|
45986
|
+
}
|
|
45987
|
+
function unionTokens(...sets) {
|
|
45988
|
+
const union3 = new Set;
|
|
45989
|
+
for (const set3 of sets) {
|
|
45990
|
+
for (const token of set3)
|
|
45991
|
+
union3.add(token);
|
|
45992
|
+
}
|
|
45993
|
+
return union3;
|
|
45994
|
+
}
|
|
45872
45995
|
var init_scoring = __esm(() => {
|
|
45996
|
+
init_role_profiles();
|
|
45873
45997
|
init_schema2();
|
|
45874
45998
|
});
|
|
45875
45999
|
|
|
@@ -46444,6 +46568,7 @@ class SQLiteMemoryProvider {
|
|
|
46444
46568
|
config;
|
|
46445
46569
|
initialized = false;
|
|
46446
46570
|
db = null;
|
|
46571
|
+
ftsAvailable = false;
|
|
46447
46572
|
memories = new Map;
|
|
46448
46573
|
proposals = new Map;
|
|
46449
46574
|
lastAutomaticJsonlMigration = null;
|
|
@@ -46491,6 +46616,7 @@ class SQLiteMemoryProvider {
|
|
|
46491
46616
|
this.db.run(`PRAGMA busy_timeout = ${busyTimeoutMs};`);
|
|
46492
46617
|
this.db.run("PRAGMA foreign_keys = ON;");
|
|
46493
46618
|
this.runMigrations();
|
|
46619
|
+
this.ftsAvailable = this.initializeFtsIndex();
|
|
46494
46620
|
this.lastAutomaticJsonlMigration = null;
|
|
46495
46621
|
await this.migrateLegacyJsonlIfNeeded();
|
|
46496
46622
|
const memoryLoad = this.loadMemories();
|
|
@@ -46532,6 +46658,7 @@ class SQLiteMemoryProvider {
|
|
|
46532
46658
|
if (this.config.hardDelete) {
|
|
46533
46659
|
this.memories.delete(id);
|
|
46534
46660
|
this.requireDb().run("DELETE FROM memory_items WHERE id = ?", [id]);
|
|
46661
|
+
this.deleteMemoryFts(id);
|
|
46535
46662
|
} else {
|
|
46536
46663
|
const tombstone = {
|
|
46537
46664
|
...existing,
|
|
@@ -46548,17 +46675,19 @@ class SQLiteMemoryProvider {
|
|
|
46548
46675
|
}
|
|
46549
46676
|
async recallWithDiagnostics(request) {
|
|
46550
46677
|
await this.initialize();
|
|
46551
|
-
const
|
|
46678
|
+
const scopedRecords = await this.list({
|
|
46552
46679
|
scopes: request.scopes,
|
|
46553
46680
|
kinds: request.kinds,
|
|
46554
46681
|
includeExpired: request.includeExpired
|
|
46555
46682
|
});
|
|
46556
|
-
const
|
|
46683
|
+
const candidates = this.selectRecallCandidates(request, scopedRecords);
|
|
46684
|
+
const result = scoreMemoryRecordsWithDiagnostics(candidates.records, request);
|
|
46685
|
+
const reranked = candidates.ftsOrder ? rerankWithFts(result.items, candidates.ftsOrder) : result.items;
|
|
46557
46686
|
return {
|
|
46558
|
-
items:
|
|
46687
|
+
items: reranked.slice(0, request.maxItems),
|
|
46559
46688
|
diagnostics: {
|
|
46560
46689
|
...result.diagnostics,
|
|
46561
|
-
returnedCount: Math.min(
|
|
46690
|
+
returnedCount: Math.min(reranked.length, request.maxItems)
|
|
46562
46691
|
}
|
|
46563
46692
|
};
|
|
46564
46693
|
}
|
|
@@ -46648,6 +46777,7 @@ class SQLiteMemoryProvider {
|
|
|
46648
46777
|
return;
|
|
46649
46778
|
this.db.close();
|
|
46650
46779
|
this.db = null;
|
|
46780
|
+
this.ftsAvailable = false;
|
|
46651
46781
|
this.initialized = false;
|
|
46652
46782
|
this.lastAutomaticJsonlMigration = null;
|
|
46653
46783
|
}
|
|
@@ -46677,6 +46807,38 @@ class SQLiteMemoryProvider {
|
|
|
46677
46807
|
markMigration(version4, name) {
|
|
46678
46808
|
this.requireDb().run("INSERT OR IGNORE INTO schema_migrations (version, name) VALUES (?, ?)", [version4, name]);
|
|
46679
46809
|
}
|
|
46810
|
+
selectRecallCandidates(request, scopedRecords) {
|
|
46811
|
+
const ftsQuery = buildFtsQuery(request);
|
|
46812
|
+
if (!this.ftsAvailable || !ftsQuery) {
|
|
46813
|
+
return { records: scopedRecords, usedFts: false };
|
|
46814
|
+
}
|
|
46815
|
+
const scopedIds = new Set(scopedRecords.map((record3) => record3.id));
|
|
46816
|
+
if (scopedIds.size === 0) {
|
|
46817
|
+
return { records: [], usedFts: true, ftsOrder: new Map };
|
|
46818
|
+
}
|
|
46819
|
+
try {
|
|
46820
|
+
const rows = this.requireDb().query(`SELECT id, bm25(${FTS_TABLE_NAME}) AS rank
|
|
46821
|
+
FROM ${FTS_TABLE_NAME}
|
|
46822
|
+
WHERE ${FTS_TABLE_NAME} MATCH ?
|
|
46823
|
+
AND id IN (SELECT value FROM json_each(?))
|
|
46824
|
+
ORDER BY rank ASC
|
|
46825
|
+
LIMIT ?`).all(ftsQuery, JSON.stringify(Array.from(scopedIds)), Math.max(100, request.maxItems * 20));
|
|
46826
|
+
const ftsOrder = new Map;
|
|
46827
|
+
for (const row of rows) {
|
|
46828
|
+
if (!scopedIds.has(row.id))
|
|
46829
|
+
continue;
|
|
46830
|
+
ftsOrder.set(row.id, ftsOrder.size);
|
|
46831
|
+
}
|
|
46832
|
+
if (ftsOrder.size === 0 && (request.mode ?? "manual") === "manual") {
|
|
46833
|
+
return { records: scopedRecords, usedFts: false };
|
|
46834
|
+
}
|
|
46835
|
+
const records = scopedRecords.filter((record3) => ftsOrder.has(record3.id));
|
|
46836
|
+
return { records, usedFts: true, ftsOrder };
|
|
46837
|
+
} catch {
|
|
46838
|
+
this.ftsAvailable = false;
|
|
46839
|
+
return { records: scopedRecords, usedFts: false };
|
|
46840
|
+
}
|
|
46841
|
+
}
|
|
46680
46842
|
runMigrations() {
|
|
46681
46843
|
const db = this.requireDb();
|
|
46682
46844
|
db.run(`CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
@@ -46702,16 +46864,82 @@ class SQLiteMemoryProvider {
|
|
|
46702
46864
|
apply();
|
|
46703
46865
|
}
|
|
46704
46866
|
}
|
|
46867
|
+
initializeFtsIndex() {
|
|
46868
|
+
const db = this.requireDb();
|
|
46869
|
+
try {
|
|
46870
|
+
if (!this.hasMigration(FTS_SCHEMA_MIGRATION_NAME)) {
|
|
46871
|
+
this.recreateFtsIndex();
|
|
46872
|
+
this.markMigration(FTS_SCHEMA_MIGRATION_VERSION, FTS_SCHEMA_MIGRATION_NAME);
|
|
46873
|
+
this.insertEvent("migration", String(FTS_SCHEMA_MIGRATION_VERSION), FTS_SCHEMA_MIGRATION_NAME);
|
|
46874
|
+
} else {
|
|
46875
|
+
db.run(`CREATE VIRTUAL TABLE IF NOT EXISTS ${FTS_TABLE_NAME} USING fts5(
|
|
46876
|
+
${ftsCreateColumnsSql()}
|
|
46877
|
+
)`);
|
|
46878
|
+
}
|
|
46879
|
+
this.ftsAvailable = true;
|
|
46880
|
+
const validMemoryCount = this.countValidMemoryRows();
|
|
46881
|
+
const ftsCount = db.query(`SELECT COUNT(*) AS count FROM ${FTS_TABLE_NAME}`).get()?.count ?? 0;
|
|
46882
|
+
if (validMemoryCount !== ftsCount) {
|
|
46883
|
+
this.rebuildFtsIndex();
|
|
46884
|
+
}
|
|
46885
|
+
return true;
|
|
46886
|
+
} catch {
|
|
46887
|
+
this.ftsAvailable = false;
|
|
46888
|
+
return false;
|
|
46889
|
+
}
|
|
46890
|
+
}
|
|
46891
|
+
recreateFtsIndex() {
|
|
46892
|
+
const db = this.requireDb();
|
|
46893
|
+
const recreate = db.transaction(() => {
|
|
46894
|
+
db.run(`DROP TABLE IF EXISTS ${FTS_TABLE_NAME}`);
|
|
46895
|
+
db.run(`CREATE VIRTUAL TABLE ${FTS_TABLE_NAME} USING fts5(
|
|
46896
|
+
${ftsCreateColumnsSql()}
|
|
46897
|
+
)`);
|
|
46898
|
+
});
|
|
46899
|
+
recreate();
|
|
46900
|
+
}
|
|
46901
|
+
rebuildFtsIndex() {
|
|
46902
|
+
const db = this.requireDb();
|
|
46903
|
+
const rebuild = db.transaction(() => {
|
|
46904
|
+
db.run(`DELETE FROM ${FTS_TABLE_NAME}`);
|
|
46905
|
+
for (const row of this.iterateMemoryRows()) {
|
|
46906
|
+
const record3 = this.parseMemoryRow(row);
|
|
46907
|
+
if (record3) {
|
|
46908
|
+
this.writeMemoryFts(record3);
|
|
46909
|
+
}
|
|
46910
|
+
}
|
|
46911
|
+
});
|
|
46912
|
+
rebuild();
|
|
46913
|
+
}
|
|
46914
|
+
countValidMemoryRows() {
|
|
46915
|
+
let count = 0;
|
|
46916
|
+
for (const row of this.iterateMemoryRows()) {
|
|
46917
|
+
if (this.parseMemoryRow(row))
|
|
46918
|
+
count++;
|
|
46919
|
+
}
|
|
46920
|
+
return count;
|
|
46921
|
+
}
|
|
46922
|
+
*iterateMemoryRows() {
|
|
46923
|
+
yield* this.requireDb().query("SELECT id, record_json FROM memory_items").iterate();
|
|
46924
|
+
}
|
|
46925
|
+
parseMemoryRow(row) {
|
|
46926
|
+
try {
|
|
46927
|
+
return validateMemoryRecordRules(JSON.parse(row.record_json), {
|
|
46928
|
+
rejectDurableSecrets: this.config.redaction.rejectDurableSecrets
|
|
46929
|
+
});
|
|
46930
|
+
} catch {
|
|
46931
|
+
return null;
|
|
46932
|
+
}
|
|
46933
|
+
}
|
|
46705
46934
|
loadMemories() {
|
|
46706
46935
|
const rows = this.requireDb().query("SELECT id, record_json FROM memory_items ORDER BY updated_at ASC").all();
|
|
46707
46936
|
const records = [];
|
|
46708
46937
|
let invalidCount = 0;
|
|
46709
46938
|
for (const row of rows) {
|
|
46710
|
-
|
|
46711
|
-
|
|
46712
|
-
|
|
46713
|
-
|
|
46714
|
-
} catch {
|
|
46939
|
+
const record3 = this.parseMemoryRow(row);
|
|
46940
|
+
if (record3) {
|
|
46941
|
+
records.push(record3);
|
|
46942
|
+
} else {
|
|
46715
46943
|
invalidCount++;
|
|
46716
46944
|
}
|
|
46717
46945
|
}
|
|
@@ -46756,6 +46984,29 @@ class SQLiteMemoryProvider {
|
|
|
46756
46984
|
record3.metadata.deleted === true ? 1 : 0,
|
|
46757
46985
|
JSON.stringify(record3)
|
|
46758
46986
|
]);
|
|
46987
|
+
this.writeMemoryFts(record3);
|
|
46988
|
+
}
|
|
46989
|
+
writeMemoryFts(record3) {
|
|
46990
|
+
if (!this.ftsAvailable)
|
|
46991
|
+
return;
|
|
46992
|
+
try {
|
|
46993
|
+
const db = this.requireDb();
|
|
46994
|
+
db.run(`DELETE FROM ${FTS_TABLE_NAME} WHERE id = ?`, [record3.id]);
|
|
46995
|
+
db.run(`INSERT INTO ${FTS_TABLE_NAME} (
|
|
46996
|
+
${FTS_INSERT_COLUMNS.join(", ")}
|
|
46997
|
+
) VALUES (${FTS_INSERT_COLUMNS.map(() => "?").join(", ")})`, [record3.id, ...ftsColumnValues(record3)]);
|
|
46998
|
+
} catch {
|
|
46999
|
+
this.ftsAvailable = false;
|
|
47000
|
+
}
|
|
47001
|
+
}
|
|
47002
|
+
deleteMemoryFts(id) {
|
|
47003
|
+
if (!this.ftsAvailable)
|
|
47004
|
+
return;
|
|
47005
|
+
try {
|
|
47006
|
+
this.requireDb().run(`DELETE FROM ${FTS_TABLE_NAME} WHERE id = ?`, [id]);
|
|
47007
|
+
} catch {
|
|
47008
|
+
this.ftsAvailable = false;
|
|
47009
|
+
}
|
|
46759
47010
|
}
|
|
46760
47011
|
writeProposal(proposal) {
|
|
46761
47012
|
this.requireDb().run(`INSERT OR REPLACE INTO memory_proposals (
|
|
@@ -46956,7 +47207,69 @@ class SQLiteMemoryProvider {
|
|
|
46956
47207
|
function splitSql(sql) {
|
|
46957
47208
|
return sql.split(";").map((statement) => statement.trim()).filter(Boolean);
|
|
46958
47209
|
}
|
|
46959
|
-
|
|
47210
|
+
function buildFtsQuery(request) {
|
|
47211
|
+
const text = request.mode === "injection" && request.task ? `${request.task}
|
|
47212
|
+
${request.query}` : `${request.query}
|
|
47213
|
+
${request.task ?? ""}`;
|
|
47214
|
+
const terms = Array.from(extractFtsTerms(text)).slice(0, 40);
|
|
47215
|
+
if (terms.length === 0)
|
|
47216
|
+
return null;
|
|
47217
|
+
return terms.map((term) => `"${term}"`).join(" OR ");
|
|
47218
|
+
}
|
|
47219
|
+
function extractFtsTerms(text) {
|
|
47220
|
+
const terms = new Set;
|
|
47221
|
+
for (const match of text.toLowerCase().matchAll(/[a-z0-9_]{2,}/g)) {
|
|
47222
|
+
const term = match[0];
|
|
47223
|
+
if (FTS_STOP_WORDS.has(term))
|
|
47224
|
+
continue;
|
|
47225
|
+
if (term.length < 3 && !/^\d+$/.test(term))
|
|
47226
|
+
continue;
|
|
47227
|
+
terms.add(term);
|
|
47228
|
+
}
|
|
47229
|
+
return terms;
|
|
47230
|
+
}
|
|
47231
|
+
function ftsCreateColumnsSql() {
|
|
47232
|
+
return [
|
|
47233
|
+
"id UNINDEXED",
|
|
47234
|
+
...FTS_INDEX_COLUMNS.map((column) => column.name)
|
|
47235
|
+
].join(`,
|
|
47236
|
+
`);
|
|
47237
|
+
}
|
|
47238
|
+
function ftsColumnValues(record3) {
|
|
47239
|
+
return FTS_INDEX_COLUMNS.map((column) => column.value(record3));
|
|
47240
|
+
}
|
|
47241
|
+
function collectMetadataSearchStrings(metadata, keys) {
|
|
47242
|
+
const values = [];
|
|
47243
|
+
for (const key of keys) {
|
|
47244
|
+
const value = metadata[key];
|
|
47245
|
+
if (typeof value === "string") {
|
|
47246
|
+
values.push(value);
|
|
47247
|
+
continue;
|
|
47248
|
+
}
|
|
47249
|
+
if (!Array.isArray(value))
|
|
47250
|
+
continue;
|
|
47251
|
+
for (const item of value) {
|
|
47252
|
+
if (typeof item === "string")
|
|
47253
|
+
values.push(item);
|
|
47254
|
+
}
|
|
47255
|
+
}
|
|
47256
|
+
return values;
|
|
47257
|
+
}
|
|
47258
|
+
function rerankWithFts(items, ftsOrder) {
|
|
47259
|
+
const denominator = Math.max(ftsOrder.size, 1);
|
|
47260
|
+
return items.map((item) => {
|
|
47261
|
+
const order = ftsOrder.get(item.record.id);
|
|
47262
|
+
if (order === undefined)
|
|
47263
|
+
return item;
|
|
47264
|
+
const ftsBoost = (denominator - order) / denominator * 0.08;
|
|
47265
|
+
return {
|
|
47266
|
+
...item,
|
|
47267
|
+
score: item.score + ftsBoost,
|
|
47268
|
+
reason: `${item.reason}, fts_rank=${order + 1}`
|
|
47269
|
+
};
|
|
47270
|
+
}).sort((a, b) => b.score - a.score || a.record.id.localeCompare(b.record.id));
|
|
47271
|
+
}
|
|
47272
|
+
var _DatabaseCtor2 = null, FTS_SCHEMA_MIGRATION_VERSION = 3, FTS_SCHEMA_MIGRATION_NAME = "create_memory_fts5_shadow_index", FTS_TABLE_NAME = "memory_items_fts", FTS_INDEX_COLUMNS, FTS_INSERT_COLUMNS, MIGRATIONS2, FTS_STOP_WORDS;
|
|
46960
47273
|
var init_sqlite_provider = __esm(() => {
|
|
46961
47274
|
init_utils2();
|
|
46962
47275
|
init_config3();
|
|
@@ -46965,6 +47278,45 @@ var init_sqlite_provider = __esm(() => {
|
|
|
46965
47278
|
init_jsonl_migration();
|
|
46966
47279
|
init_schema2();
|
|
46967
47280
|
init_scoring();
|
|
47281
|
+
FTS_INDEX_COLUMNS = [
|
|
47282
|
+
{
|
|
47283
|
+
name: "text",
|
|
47284
|
+
value: (record3) => record3.text
|
|
47285
|
+
},
|
|
47286
|
+
{
|
|
47287
|
+
name: "tags",
|
|
47288
|
+
value: (record3) => record3.tags.join(" ")
|
|
47289
|
+
},
|
|
47290
|
+
{
|
|
47291
|
+
name: "kind",
|
|
47292
|
+
value: (record3) => record3.kind.replace(/_/g, " ")
|
|
47293
|
+
},
|
|
47294
|
+
{
|
|
47295
|
+
name: "source_file_path",
|
|
47296
|
+
value: (record3) => record3.source.filePath ?? ""
|
|
47297
|
+
},
|
|
47298
|
+
{
|
|
47299
|
+
name: "source_ref",
|
|
47300
|
+
value: (record3) => record3.source.ref ?? ""
|
|
47301
|
+
},
|
|
47302
|
+
{
|
|
47303
|
+
name: "metadata_symbols",
|
|
47304
|
+
value: (record3) => collectMetadataSearchStrings(record3.metadata, ["symbol", "symbols"]).join(" ")
|
|
47305
|
+
},
|
|
47306
|
+
{
|
|
47307
|
+
name: "metadata_files",
|
|
47308
|
+
value: (record3) => collectMetadataSearchStrings(record3.metadata, [
|
|
47309
|
+
"file",
|
|
47310
|
+
"filePath",
|
|
47311
|
+
"files",
|
|
47312
|
+
"touchedFiles"
|
|
47313
|
+
]).join(" ")
|
|
47314
|
+
}
|
|
47315
|
+
];
|
|
47316
|
+
FTS_INSERT_COLUMNS = [
|
|
47317
|
+
"id",
|
|
47318
|
+
...FTS_INDEX_COLUMNS.map((column) => column.name)
|
|
47319
|
+
];
|
|
46968
47320
|
MIGRATIONS2 = [
|
|
46969
47321
|
{
|
|
46970
47322
|
version: 1,
|
|
@@ -47014,6 +47366,37 @@ var init_sqlite_provider = __esm(() => {
|
|
|
47014
47366
|
`
|
|
47015
47367
|
}
|
|
47016
47368
|
];
|
|
47369
|
+
FTS_STOP_WORDS = new Set([
|
|
47370
|
+
"a",
|
|
47371
|
+
"an",
|
|
47372
|
+
"and",
|
|
47373
|
+
"are",
|
|
47374
|
+
"as",
|
|
47375
|
+
"at",
|
|
47376
|
+
"be",
|
|
47377
|
+
"by",
|
|
47378
|
+
"for",
|
|
47379
|
+
"from",
|
|
47380
|
+
"goal",
|
|
47381
|
+
"how",
|
|
47382
|
+
"in",
|
|
47383
|
+
"into",
|
|
47384
|
+
"is",
|
|
47385
|
+
"it",
|
|
47386
|
+
"of",
|
|
47387
|
+
"on",
|
|
47388
|
+
"or",
|
|
47389
|
+
"role",
|
|
47390
|
+
"task",
|
|
47391
|
+
"that",
|
|
47392
|
+
"the",
|
|
47393
|
+
"this",
|
|
47394
|
+
"to",
|
|
47395
|
+
"user",
|
|
47396
|
+
"what",
|
|
47397
|
+
"when",
|
|
47398
|
+
"with"
|
|
47399
|
+
]);
|
|
47017
47400
|
});
|
|
47018
47401
|
|
|
47019
47402
|
// src/memory/gateway.ts
|
|
@@ -47064,11 +47447,6 @@ var init_agent_output_schema = __esm(() => {
|
|
|
47064
47447
|
}).passthrough();
|
|
47065
47448
|
});
|
|
47066
47449
|
|
|
47067
|
-
// src/memory/role-profiles.ts
|
|
47068
|
-
var init_role_profiles = __esm(() => {
|
|
47069
|
-
init_schema();
|
|
47070
|
-
});
|
|
47071
|
-
|
|
47072
47450
|
// src/memory/recall-planner.ts
|
|
47073
47451
|
var init_recall_planner = __esm(() => {
|
|
47074
47452
|
init_role_profiles();
|
package/dist/index.js
CHANGED
|
@@ -48,7 +48,7 @@ var package_default;
|
|
|
48
48
|
var init_package = __esm(() => {
|
|
49
49
|
package_default = {
|
|
50
50
|
name: "opencode-swarm",
|
|
51
|
-
version: "7.
|
|
51
|
+
version: "7.37.0",
|
|
52
52
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
53
53
|
main: "dist/index.js",
|
|
54
54
|
types: "dist/index.d.ts",
|
|
@@ -67230,6 +67230,102 @@ var init_curator_decision_helpers = __esm(() => {
|
|
|
67230
67230
|
init_schema2();
|
|
67231
67231
|
});
|
|
67232
67232
|
|
|
67233
|
+
// src/memory/role-profiles.ts
|
|
67234
|
+
function resolveMemoryRecallProfile(agentRole) {
|
|
67235
|
+
const role = normalizeMemoryAgentRole(agentRole);
|
|
67236
|
+
return MEMORY_RECALL_PROFILES[role] ?? MEMORY_RECALL_PROFILES.coder;
|
|
67237
|
+
}
|
|
67238
|
+
function normalizeMemoryAgentRole(agentRole) {
|
|
67239
|
+
const base = stripKnownSwarmPrefix(agentRole ?? "architect");
|
|
67240
|
+
if (base === "reviewer" || base === "test_engineer")
|
|
67241
|
+
return "qa";
|
|
67242
|
+
if (base === "critic" || base === "critic_sounding_board" || base === "critic_drift_verifier" || base === "critic_hallucination_verifier") {
|
|
67243
|
+
return "security";
|
|
67244
|
+
}
|
|
67245
|
+
if (base === "curator_init" || base === "curator_phase")
|
|
67246
|
+
return "curator";
|
|
67247
|
+
if (base === "docs")
|
|
67248
|
+
return "sme";
|
|
67249
|
+
if (base === "architect" || base === "sme" || base === "coder" || base === "security" || base === "curator") {
|
|
67250
|
+
return base;
|
|
67251
|
+
}
|
|
67252
|
+
return "coder";
|
|
67253
|
+
}
|
|
67254
|
+
var MEMORY_RECALL_PROFILES;
|
|
67255
|
+
var init_role_profiles = __esm(() => {
|
|
67256
|
+
init_schema();
|
|
67257
|
+
MEMORY_RECALL_PROFILES = {
|
|
67258
|
+
architect: {
|
|
67259
|
+
kinds: [
|
|
67260
|
+
"project_fact",
|
|
67261
|
+
"architecture_decision",
|
|
67262
|
+
"repo_convention",
|
|
67263
|
+
"failure_pattern",
|
|
67264
|
+
"security_note"
|
|
67265
|
+
],
|
|
67266
|
+
maxItems: 10,
|
|
67267
|
+
tokenBudget: 1600
|
|
67268
|
+
},
|
|
67269
|
+
sme: {
|
|
67270
|
+
kinds: [
|
|
67271
|
+
"api_finding",
|
|
67272
|
+
"code_pattern",
|
|
67273
|
+
"repo_convention",
|
|
67274
|
+
"failure_pattern",
|
|
67275
|
+
"evidence"
|
|
67276
|
+
],
|
|
67277
|
+
maxItems: 8,
|
|
67278
|
+
tokenBudget: 1200
|
|
67279
|
+
},
|
|
67280
|
+
coder: {
|
|
67281
|
+
kinds: [
|
|
67282
|
+
"architecture_decision",
|
|
67283
|
+
"repo_convention",
|
|
67284
|
+
"code_pattern",
|
|
67285
|
+
"test_pattern",
|
|
67286
|
+
"failure_pattern"
|
|
67287
|
+
],
|
|
67288
|
+
maxItems: 8,
|
|
67289
|
+
tokenBudget: 1200
|
|
67290
|
+
},
|
|
67291
|
+
qa: {
|
|
67292
|
+
kinds: [
|
|
67293
|
+
"test_pattern",
|
|
67294
|
+
"failure_pattern",
|
|
67295
|
+
"repo_convention",
|
|
67296
|
+
"security_note"
|
|
67297
|
+
],
|
|
67298
|
+
maxItems: 8,
|
|
67299
|
+
tokenBudget: 1200
|
|
67300
|
+
},
|
|
67301
|
+
security: {
|
|
67302
|
+
kinds: [
|
|
67303
|
+
"security_note",
|
|
67304
|
+
"architecture_decision",
|
|
67305
|
+
"repo_convention",
|
|
67306
|
+
"evidence"
|
|
67307
|
+
],
|
|
67308
|
+
maxItems: 8,
|
|
67309
|
+
tokenBudget: 1200
|
|
67310
|
+
},
|
|
67311
|
+
curator: {
|
|
67312
|
+
kinds: [
|
|
67313
|
+
"project_fact",
|
|
67314
|
+
"architecture_decision",
|
|
67315
|
+
"repo_convention",
|
|
67316
|
+
"api_finding",
|
|
67317
|
+
"code_pattern",
|
|
67318
|
+
"test_pattern",
|
|
67319
|
+
"failure_pattern",
|
|
67320
|
+
"security_note",
|
|
67321
|
+
"evidence"
|
|
67322
|
+
],
|
|
67323
|
+
maxItems: 20,
|
|
67324
|
+
tokenBudget: 3000
|
|
67325
|
+
}
|
|
67326
|
+
};
|
|
67327
|
+
});
|
|
67328
|
+
|
|
67233
67329
|
// src/memory/scoring.ts
|
|
67234
67330
|
function tokenize(text) {
|
|
67235
67331
|
return new Set(text.toLowerCase().replace(/[^\w\s-]/g, " ").split(/\s+/).map((token) => token.trim()).filter(Boolean));
|
|
@@ -67283,13 +67379,16 @@ function kindProfileBoost(kind, request) {
|
|
|
67283
67379
|
return 0.5;
|
|
67284
67380
|
return request.kinds.includes(kind) ? 1 : 0;
|
|
67285
67381
|
}
|
|
67382
|
+
function roleProfileBoost(kind, context) {
|
|
67383
|
+
return context.roleProfileKinds?.has(kind) ? 1 : 0;
|
|
67384
|
+
}
|
|
67286
67385
|
function sameScope(a, b) {
|
|
67287
67386
|
return stableScopeKey(a) === stableScopeKey(b);
|
|
67288
67387
|
}
|
|
67289
67388
|
function scopeAllowed(recordScope, allowedScopes) {
|
|
67290
67389
|
return allowedScopes.some((scope) => sameScope(recordScope, scope));
|
|
67291
67390
|
}
|
|
67292
|
-
function scoreMemoryRecordDetailed(record3, request) {
|
|
67391
|
+
function scoreMemoryRecordDetailed(record3, request, context) {
|
|
67293
67392
|
if (!request.includeExpired && isExpired(record3)) {
|
|
67294
67393
|
return { item: null, skipReason: "filtered" };
|
|
67295
67394
|
}
|
|
@@ -67304,7 +67403,7 @@ function scoreMemoryRecordDetailed(record3, request) {
|
|
|
67304
67403
|
if (request.kinds && !request.kinds.includes(record3.kind)) {
|
|
67305
67404
|
return { item: null, skipReason: "filtered" };
|
|
67306
67405
|
}
|
|
67307
|
-
const queryTokens = request.mode === "injection" &&
|
|
67406
|
+
const queryTokens = request.mode === "injection" && context.taskTokens ? context.taskTokens : context.queryTokens;
|
|
67308
67407
|
const textTokens = tokenize(record3.text);
|
|
67309
67408
|
const tagTokens = tokenize(record3.tags.join(" "));
|
|
67310
67409
|
const fileTokens = tokenize([
|
|
@@ -67317,24 +67416,31 @@ function scoreMemoryRecordDetailed(record3, request) {
|
|
|
67317
67416
|
])
|
|
67318
67417
|
].filter((value) => typeof value === "string").join(" "));
|
|
67319
67418
|
const symbolTokens = tokenize(collectMetadataStrings(record3.metadata, ["symbol", "symbols"]).join(" "));
|
|
67320
|
-
const
|
|
67419
|
+
const kindTokens = tokenize(normalizeKindText(record3.kind));
|
|
67420
|
+
const sourceRefTokens = tokenize(record3.source.ref ?? "");
|
|
67421
|
+
const taskSearchTokens = unionTokens(textTokens, tagTokens, fileTokens, symbolTokens, kindTokens, sourceRefTokens);
|
|
67422
|
+
const taskTermOverlap = context.taskTokens ? overlap(context.taskTokens, taskSearchTokens) : 0;
|
|
67423
|
+
const kindQueryOverlap = overlap(queryTokens, kindTokens);
|
|
67321
67424
|
const textOverlap = overlap(queryTokens, textTokens);
|
|
67322
67425
|
const tagOverlap = overlap(queryTokens, tagTokens);
|
|
67323
67426
|
const fileOverlap = overlap(queryTokens, fileTokens);
|
|
67324
67427
|
const symbolOverlap = overlap(queryTokens, symbolTokens);
|
|
67325
67428
|
const kindMatch = request.kinds?.includes(record3.kind) ?? false;
|
|
67326
67429
|
const scopeMatch = scopeAllowed(record3.scope, request.scopes);
|
|
67430
|
+
const roleBoost = roleProfileBoost(record3.kind, context);
|
|
67327
67431
|
const hasQuerySignal = textOverlap > 0 || tagOverlap > 0 || fileOverlap > 0 || symbolOverlap > 0 || kindQueryOverlap > 0;
|
|
67328
67432
|
if (request.mode === "injection" && request.requireQuerySignal !== false && !hasQuerySignal) {
|
|
67329
67433
|
return { item: null, skipReason: "no_signal" };
|
|
67330
67434
|
}
|
|
67331
|
-
const score = textOverlap * 0.
|
|
67435
|
+
const score = textOverlap * 0.38 + tagOverlap * 0.16 + fileOverlap * 0.12 + symbolOverlap * 0.08 + taskTermOverlap * 0.08 + scopeSpecificityBoost(record3.scope) * 0.12 + kindProfileBoost(record3.kind, request) * 0.06 + roleBoost * 0.05 + record3.confidence * 0.08;
|
|
67332
67436
|
const reasonParts = [
|
|
67333
67437
|
textOverlap > 0 ? `text_overlap=${textOverlap.toFixed(2)}` : null,
|
|
67334
67438
|
tagOverlap > 0 ? `tag_overlap=${tagOverlap.toFixed(2)}` : null,
|
|
67335
67439
|
fileOverlap > 0 ? `file_overlap=${fileOverlap.toFixed(2)}` : null,
|
|
67336
67440
|
symbolOverlap > 0 ? `symbol_overlap=${symbolOverlap.toFixed(2)}` : null,
|
|
67441
|
+
taskTermOverlap > 0 ? `task_terms=${taskTermOverlap.toFixed(2)}` : null,
|
|
67337
67442
|
kindQueryOverlap > 0 ? `kind_query=${kindQueryOverlap.toFixed(2)}` : null,
|
|
67443
|
+
roleBoost > 0 ? "role_profile" : null,
|
|
67338
67444
|
`scope=${record3.scope.type}`,
|
|
67339
67445
|
`confidence=${record3.confidence.toFixed(2)}`
|
|
67340
67446
|
].filter(Boolean);
|
|
@@ -67356,6 +67462,7 @@ function scoreMemoryRecordDetailed(record3, request) {
|
|
|
67356
67462
|
}
|
|
67357
67463
|
function scoreMemoryRecordsWithDiagnostics(records, request) {
|
|
67358
67464
|
const minScore = request.minScore ?? 0;
|
|
67465
|
+
const context = createScoringContext(request);
|
|
67359
67466
|
const diagnostics = {
|
|
67360
67467
|
candidateCount: records.length,
|
|
67361
67468
|
preScoredFilteredCount: 0,
|
|
@@ -67366,7 +67473,7 @@ function scoreMemoryRecordsWithDiagnostics(records, request) {
|
|
|
67366
67473
|
};
|
|
67367
67474
|
const items = [];
|
|
67368
67475
|
for (const record3 of records) {
|
|
67369
|
-
const result = scoreMemoryRecordDetailed(record3, request);
|
|
67476
|
+
const result = scoreMemoryRecordDetailed(record3, request, context);
|
|
67370
67477
|
if (!result.item) {
|
|
67371
67478
|
if (result.skipReason === "filtered")
|
|
67372
67479
|
diagnostics.preScoredFilteredCount++;
|
|
@@ -67385,7 +67492,24 @@ function scoreMemoryRecordsWithDiagnostics(records, request) {
|
|
|
67385
67492
|
diagnostics.returnedCount = items.length;
|
|
67386
67493
|
return { items, diagnostics };
|
|
67387
67494
|
}
|
|
67495
|
+
function createScoringContext(request) {
|
|
67496
|
+
const taskTokens = request.task ? tokenize(request.task) : undefined;
|
|
67497
|
+
return {
|
|
67498
|
+
taskTokens,
|
|
67499
|
+
queryTokens: tokenize(request.query),
|
|
67500
|
+
roleProfileKinds: request.agentRole ? new Set(resolveMemoryRecallProfile(request.agentRole).kinds) : undefined
|
|
67501
|
+
};
|
|
67502
|
+
}
|
|
67503
|
+
function unionTokens(...sets) {
|
|
67504
|
+
const union3 = new Set;
|
|
67505
|
+
for (const set3 of sets) {
|
|
67506
|
+
for (const token of set3)
|
|
67507
|
+
union3.add(token);
|
|
67508
|
+
}
|
|
67509
|
+
return union3;
|
|
67510
|
+
}
|
|
67388
67511
|
var init_scoring = __esm(() => {
|
|
67512
|
+
init_role_profiles();
|
|
67389
67513
|
init_schema2();
|
|
67390
67514
|
});
|
|
67391
67515
|
|
|
@@ -68034,6 +68158,7 @@ class SQLiteMemoryProvider {
|
|
|
68034
68158
|
config;
|
|
68035
68159
|
initialized = false;
|
|
68036
68160
|
db = null;
|
|
68161
|
+
ftsAvailable = false;
|
|
68037
68162
|
memories = new Map;
|
|
68038
68163
|
proposals = new Map;
|
|
68039
68164
|
lastAutomaticJsonlMigration = null;
|
|
@@ -68081,6 +68206,7 @@ class SQLiteMemoryProvider {
|
|
|
68081
68206
|
this.db.run(`PRAGMA busy_timeout = ${busyTimeoutMs};`);
|
|
68082
68207
|
this.db.run("PRAGMA foreign_keys = ON;");
|
|
68083
68208
|
this.runMigrations();
|
|
68209
|
+
this.ftsAvailable = this.initializeFtsIndex();
|
|
68084
68210
|
this.lastAutomaticJsonlMigration = null;
|
|
68085
68211
|
await this.migrateLegacyJsonlIfNeeded();
|
|
68086
68212
|
const memoryLoad = this.loadMemories();
|
|
@@ -68122,6 +68248,7 @@ class SQLiteMemoryProvider {
|
|
|
68122
68248
|
if (this.config.hardDelete) {
|
|
68123
68249
|
this.memories.delete(id);
|
|
68124
68250
|
this.requireDb().run("DELETE FROM memory_items WHERE id = ?", [id]);
|
|
68251
|
+
this.deleteMemoryFts(id);
|
|
68125
68252
|
} else {
|
|
68126
68253
|
const tombstone = {
|
|
68127
68254
|
...existing,
|
|
@@ -68138,17 +68265,19 @@ class SQLiteMemoryProvider {
|
|
|
68138
68265
|
}
|
|
68139
68266
|
async recallWithDiagnostics(request) {
|
|
68140
68267
|
await this.initialize();
|
|
68141
|
-
const
|
|
68268
|
+
const scopedRecords = await this.list({
|
|
68142
68269
|
scopes: request.scopes,
|
|
68143
68270
|
kinds: request.kinds,
|
|
68144
68271
|
includeExpired: request.includeExpired
|
|
68145
68272
|
});
|
|
68146
|
-
const
|
|
68273
|
+
const candidates = this.selectRecallCandidates(request, scopedRecords);
|
|
68274
|
+
const result = scoreMemoryRecordsWithDiagnostics(candidates.records, request);
|
|
68275
|
+
const reranked = candidates.ftsOrder ? rerankWithFts(result.items, candidates.ftsOrder) : result.items;
|
|
68147
68276
|
return {
|
|
68148
|
-
items:
|
|
68277
|
+
items: reranked.slice(0, request.maxItems),
|
|
68149
68278
|
diagnostics: {
|
|
68150
68279
|
...result.diagnostics,
|
|
68151
|
-
returnedCount: Math.min(
|
|
68280
|
+
returnedCount: Math.min(reranked.length, request.maxItems)
|
|
68152
68281
|
}
|
|
68153
68282
|
};
|
|
68154
68283
|
}
|
|
@@ -68238,6 +68367,7 @@ class SQLiteMemoryProvider {
|
|
|
68238
68367
|
return;
|
|
68239
68368
|
this.db.close();
|
|
68240
68369
|
this.db = null;
|
|
68370
|
+
this.ftsAvailable = false;
|
|
68241
68371
|
this.initialized = false;
|
|
68242
68372
|
this.lastAutomaticJsonlMigration = null;
|
|
68243
68373
|
}
|
|
@@ -68267,6 +68397,38 @@ class SQLiteMemoryProvider {
|
|
|
68267
68397
|
markMigration(version4, name2) {
|
|
68268
68398
|
this.requireDb().run("INSERT OR IGNORE INTO schema_migrations (version, name) VALUES (?, ?)", [version4, name2]);
|
|
68269
68399
|
}
|
|
68400
|
+
selectRecallCandidates(request, scopedRecords) {
|
|
68401
|
+
const ftsQuery = buildFtsQuery(request);
|
|
68402
|
+
if (!this.ftsAvailable || !ftsQuery) {
|
|
68403
|
+
return { records: scopedRecords, usedFts: false };
|
|
68404
|
+
}
|
|
68405
|
+
const scopedIds = new Set(scopedRecords.map((record3) => record3.id));
|
|
68406
|
+
if (scopedIds.size === 0) {
|
|
68407
|
+
return { records: [], usedFts: true, ftsOrder: new Map };
|
|
68408
|
+
}
|
|
68409
|
+
try {
|
|
68410
|
+
const rows = this.requireDb().query(`SELECT id, bm25(${FTS_TABLE_NAME}) AS rank
|
|
68411
|
+
FROM ${FTS_TABLE_NAME}
|
|
68412
|
+
WHERE ${FTS_TABLE_NAME} MATCH ?
|
|
68413
|
+
AND id IN (SELECT value FROM json_each(?))
|
|
68414
|
+
ORDER BY rank ASC
|
|
68415
|
+
LIMIT ?`).all(ftsQuery, JSON.stringify(Array.from(scopedIds)), Math.max(100, request.maxItems * 20));
|
|
68416
|
+
const ftsOrder = new Map;
|
|
68417
|
+
for (const row of rows) {
|
|
68418
|
+
if (!scopedIds.has(row.id))
|
|
68419
|
+
continue;
|
|
68420
|
+
ftsOrder.set(row.id, ftsOrder.size);
|
|
68421
|
+
}
|
|
68422
|
+
if (ftsOrder.size === 0 && (request.mode ?? "manual") === "manual") {
|
|
68423
|
+
return { records: scopedRecords, usedFts: false };
|
|
68424
|
+
}
|
|
68425
|
+
const records = scopedRecords.filter((record3) => ftsOrder.has(record3.id));
|
|
68426
|
+
return { records, usedFts: true, ftsOrder };
|
|
68427
|
+
} catch {
|
|
68428
|
+
this.ftsAvailable = false;
|
|
68429
|
+
return { records: scopedRecords, usedFts: false };
|
|
68430
|
+
}
|
|
68431
|
+
}
|
|
68270
68432
|
runMigrations() {
|
|
68271
68433
|
const db = this.requireDb();
|
|
68272
68434
|
db.run(`CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
@@ -68292,16 +68454,82 @@ class SQLiteMemoryProvider {
|
|
|
68292
68454
|
apply();
|
|
68293
68455
|
}
|
|
68294
68456
|
}
|
|
68457
|
+
initializeFtsIndex() {
|
|
68458
|
+
const db = this.requireDb();
|
|
68459
|
+
try {
|
|
68460
|
+
if (!this.hasMigration(FTS_SCHEMA_MIGRATION_NAME)) {
|
|
68461
|
+
this.recreateFtsIndex();
|
|
68462
|
+
this.markMigration(FTS_SCHEMA_MIGRATION_VERSION, FTS_SCHEMA_MIGRATION_NAME);
|
|
68463
|
+
this.insertEvent("migration", String(FTS_SCHEMA_MIGRATION_VERSION), FTS_SCHEMA_MIGRATION_NAME);
|
|
68464
|
+
} else {
|
|
68465
|
+
db.run(`CREATE VIRTUAL TABLE IF NOT EXISTS ${FTS_TABLE_NAME} USING fts5(
|
|
68466
|
+
${ftsCreateColumnsSql()}
|
|
68467
|
+
)`);
|
|
68468
|
+
}
|
|
68469
|
+
this.ftsAvailable = true;
|
|
68470
|
+
const validMemoryCount = this.countValidMemoryRows();
|
|
68471
|
+
const ftsCount = db.query(`SELECT COUNT(*) AS count FROM ${FTS_TABLE_NAME}`).get()?.count ?? 0;
|
|
68472
|
+
if (validMemoryCount !== ftsCount) {
|
|
68473
|
+
this.rebuildFtsIndex();
|
|
68474
|
+
}
|
|
68475
|
+
return true;
|
|
68476
|
+
} catch {
|
|
68477
|
+
this.ftsAvailable = false;
|
|
68478
|
+
return false;
|
|
68479
|
+
}
|
|
68480
|
+
}
|
|
68481
|
+
recreateFtsIndex() {
|
|
68482
|
+
const db = this.requireDb();
|
|
68483
|
+
const recreate = db.transaction(() => {
|
|
68484
|
+
db.run(`DROP TABLE IF EXISTS ${FTS_TABLE_NAME}`);
|
|
68485
|
+
db.run(`CREATE VIRTUAL TABLE ${FTS_TABLE_NAME} USING fts5(
|
|
68486
|
+
${ftsCreateColumnsSql()}
|
|
68487
|
+
)`);
|
|
68488
|
+
});
|
|
68489
|
+
recreate();
|
|
68490
|
+
}
|
|
68491
|
+
rebuildFtsIndex() {
|
|
68492
|
+
const db = this.requireDb();
|
|
68493
|
+
const rebuild = db.transaction(() => {
|
|
68494
|
+
db.run(`DELETE FROM ${FTS_TABLE_NAME}`);
|
|
68495
|
+
for (const row of this.iterateMemoryRows()) {
|
|
68496
|
+
const record3 = this.parseMemoryRow(row);
|
|
68497
|
+
if (record3) {
|
|
68498
|
+
this.writeMemoryFts(record3);
|
|
68499
|
+
}
|
|
68500
|
+
}
|
|
68501
|
+
});
|
|
68502
|
+
rebuild();
|
|
68503
|
+
}
|
|
68504
|
+
countValidMemoryRows() {
|
|
68505
|
+
let count = 0;
|
|
68506
|
+
for (const row of this.iterateMemoryRows()) {
|
|
68507
|
+
if (this.parseMemoryRow(row))
|
|
68508
|
+
count++;
|
|
68509
|
+
}
|
|
68510
|
+
return count;
|
|
68511
|
+
}
|
|
68512
|
+
*iterateMemoryRows() {
|
|
68513
|
+
yield* this.requireDb().query("SELECT id, record_json FROM memory_items").iterate();
|
|
68514
|
+
}
|
|
68515
|
+
parseMemoryRow(row) {
|
|
68516
|
+
try {
|
|
68517
|
+
return validateMemoryRecordRules(JSON.parse(row.record_json), {
|
|
68518
|
+
rejectDurableSecrets: this.config.redaction.rejectDurableSecrets
|
|
68519
|
+
});
|
|
68520
|
+
} catch {
|
|
68521
|
+
return null;
|
|
68522
|
+
}
|
|
68523
|
+
}
|
|
68295
68524
|
loadMemories() {
|
|
68296
68525
|
const rows = this.requireDb().query("SELECT id, record_json FROM memory_items ORDER BY updated_at ASC").all();
|
|
68297
68526
|
const records = [];
|
|
68298
68527
|
let invalidCount = 0;
|
|
68299
68528
|
for (const row of rows) {
|
|
68300
|
-
|
|
68301
|
-
|
|
68302
|
-
|
|
68303
|
-
|
|
68304
|
-
} catch {
|
|
68529
|
+
const record3 = this.parseMemoryRow(row);
|
|
68530
|
+
if (record3) {
|
|
68531
|
+
records.push(record3);
|
|
68532
|
+
} else {
|
|
68305
68533
|
invalidCount++;
|
|
68306
68534
|
}
|
|
68307
68535
|
}
|
|
@@ -68346,6 +68574,29 @@ class SQLiteMemoryProvider {
|
|
|
68346
68574
|
record3.metadata.deleted === true ? 1 : 0,
|
|
68347
68575
|
JSON.stringify(record3)
|
|
68348
68576
|
]);
|
|
68577
|
+
this.writeMemoryFts(record3);
|
|
68578
|
+
}
|
|
68579
|
+
writeMemoryFts(record3) {
|
|
68580
|
+
if (!this.ftsAvailable)
|
|
68581
|
+
return;
|
|
68582
|
+
try {
|
|
68583
|
+
const db = this.requireDb();
|
|
68584
|
+
db.run(`DELETE FROM ${FTS_TABLE_NAME} WHERE id = ?`, [record3.id]);
|
|
68585
|
+
db.run(`INSERT INTO ${FTS_TABLE_NAME} (
|
|
68586
|
+
${FTS_INSERT_COLUMNS.join(", ")}
|
|
68587
|
+
) VALUES (${FTS_INSERT_COLUMNS.map(() => "?").join(", ")})`, [record3.id, ...ftsColumnValues(record3)]);
|
|
68588
|
+
} catch {
|
|
68589
|
+
this.ftsAvailable = false;
|
|
68590
|
+
}
|
|
68591
|
+
}
|
|
68592
|
+
deleteMemoryFts(id) {
|
|
68593
|
+
if (!this.ftsAvailable)
|
|
68594
|
+
return;
|
|
68595
|
+
try {
|
|
68596
|
+
this.requireDb().run(`DELETE FROM ${FTS_TABLE_NAME} WHERE id = ?`, [id]);
|
|
68597
|
+
} catch {
|
|
68598
|
+
this.ftsAvailable = false;
|
|
68599
|
+
}
|
|
68349
68600
|
}
|
|
68350
68601
|
writeProposal(proposal) {
|
|
68351
68602
|
this.requireDb().run(`INSERT OR REPLACE INTO memory_proposals (
|
|
@@ -68546,7 +68797,69 @@ class SQLiteMemoryProvider {
|
|
|
68546
68797
|
function splitSql(sql) {
|
|
68547
68798
|
return sql.split(";").map((statement) => statement.trim()).filter(Boolean);
|
|
68548
68799
|
}
|
|
68549
|
-
|
|
68800
|
+
function buildFtsQuery(request) {
|
|
68801
|
+
const text = request.mode === "injection" && request.task ? `${request.task}
|
|
68802
|
+
${request.query}` : `${request.query}
|
|
68803
|
+
${request.task ?? ""}`;
|
|
68804
|
+
const terms = Array.from(extractFtsTerms(text)).slice(0, 40);
|
|
68805
|
+
if (terms.length === 0)
|
|
68806
|
+
return null;
|
|
68807
|
+
return terms.map((term) => `"${term}"`).join(" OR ");
|
|
68808
|
+
}
|
|
68809
|
+
function extractFtsTerms(text) {
|
|
68810
|
+
const terms = new Set;
|
|
68811
|
+
for (const match of text.toLowerCase().matchAll(/[a-z0-9_]{2,}/g)) {
|
|
68812
|
+
const term = match[0];
|
|
68813
|
+
if (FTS_STOP_WORDS.has(term))
|
|
68814
|
+
continue;
|
|
68815
|
+
if (term.length < 3 && !/^\d+$/.test(term))
|
|
68816
|
+
continue;
|
|
68817
|
+
terms.add(term);
|
|
68818
|
+
}
|
|
68819
|
+
return terms;
|
|
68820
|
+
}
|
|
68821
|
+
function ftsCreateColumnsSql() {
|
|
68822
|
+
return [
|
|
68823
|
+
"id UNINDEXED",
|
|
68824
|
+
...FTS_INDEX_COLUMNS.map((column) => column.name)
|
|
68825
|
+
].join(`,
|
|
68826
|
+
`);
|
|
68827
|
+
}
|
|
68828
|
+
function ftsColumnValues(record3) {
|
|
68829
|
+
return FTS_INDEX_COLUMNS.map((column) => column.value(record3));
|
|
68830
|
+
}
|
|
68831
|
+
function collectMetadataSearchStrings(metadata2, keys) {
|
|
68832
|
+
const values = [];
|
|
68833
|
+
for (const key of keys) {
|
|
68834
|
+
const value = metadata2[key];
|
|
68835
|
+
if (typeof value === "string") {
|
|
68836
|
+
values.push(value);
|
|
68837
|
+
continue;
|
|
68838
|
+
}
|
|
68839
|
+
if (!Array.isArray(value))
|
|
68840
|
+
continue;
|
|
68841
|
+
for (const item of value) {
|
|
68842
|
+
if (typeof item === "string")
|
|
68843
|
+
values.push(item);
|
|
68844
|
+
}
|
|
68845
|
+
}
|
|
68846
|
+
return values;
|
|
68847
|
+
}
|
|
68848
|
+
function rerankWithFts(items, ftsOrder) {
|
|
68849
|
+
const denominator = Math.max(ftsOrder.size, 1);
|
|
68850
|
+
return items.map((item) => {
|
|
68851
|
+
const order = ftsOrder.get(item.record.id);
|
|
68852
|
+
if (order === undefined)
|
|
68853
|
+
return item;
|
|
68854
|
+
const ftsBoost = (denominator - order) / denominator * 0.08;
|
|
68855
|
+
return {
|
|
68856
|
+
...item,
|
|
68857
|
+
score: item.score + ftsBoost,
|
|
68858
|
+
reason: `${item.reason}, fts_rank=${order + 1}`
|
|
68859
|
+
};
|
|
68860
|
+
}).sort((a, b) => b.score - a.score || a.record.id.localeCompare(b.record.id));
|
|
68861
|
+
}
|
|
68862
|
+
var _DatabaseCtor2 = null, FTS_SCHEMA_MIGRATION_VERSION = 3, FTS_SCHEMA_MIGRATION_NAME = "create_memory_fts5_shadow_index", FTS_TABLE_NAME = "memory_items_fts", FTS_INDEX_COLUMNS, FTS_INSERT_COLUMNS, MIGRATIONS2, FTS_STOP_WORDS;
|
|
68550
68863
|
var init_sqlite_provider = __esm(() => {
|
|
68551
68864
|
init_utils2();
|
|
68552
68865
|
init_config3();
|
|
@@ -68555,6 +68868,45 @@ var init_sqlite_provider = __esm(() => {
|
|
|
68555
68868
|
init_jsonl_migration();
|
|
68556
68869
|
init_schema2();
|
|
68557
68870
|
init_scoring();
|
|
68871
|
+
FTS_INDEX_COLUMNS = [
|
|
68872
|
+
{
|
|
68873
|
+
name: "text",
|
|
68874
|
+
value: (record3) => record3.text
|
|
68875
|
+
},
|
|
68876
|
+
{
|
|
68877
|
+
name: "tags",
|
|
68878
|
+
value: (record3) => record3.tags.join(" ")
|
|
68879
|
+
},
|
|
68880
|
+
{
|
|
68881
|
+
name: "kind",
|
|
68882
|
+
value: (record3) => record3.kind.replace(/_/g, " ")
|
|
68883
|
+
},
|
|
68884
|
+
{
|
|
68885
|
+
name: "source_file_path",
|
|
68886
|
+
value: (record3) => record3.source.filePath ?? ""
|
|
68887
|
+
},
|
|
68888
|
+
{
|
|
68889
|
+
name: "source_ref",
|
|
68890
|
+
value: (record3) => record3.source.ref ?? ""
|
|
68891
|
+
},
|
|
68892
|
+
{
|
|
68893
|
+
name: "metadata_symbols",
|
|
68894
|
+
value: (record3) => collectMetadataSearchStrings(record3.metadata, ["symbol", "symbols"]).join(" ")
|
|
68895
|
+
},
|
|
68896
|
+
{
|
|
68897
|
+
name: "metadata_files",
|
|
68898
|
+
value: (record3) => collectMetadataSearchStrings(record3.metadata, [
|
|
68899
|
+
"file",
|
|
68900
|
+
"filePath",
|
|
68901
|
+
"files",
|
|
68902
|
+
"touchedFiles"
|
|
68903
|
+
]).join(" ")
|
|
68904
|
+
}
|
|
68905
|
+
];
|
|
68906
|
+
FTS_INSERT_COLUMNS = [
|
|
68907
|
+
"id",
|
|
68908
|
+
...FTS_INDEX_COLUMNS.map((column) => column.name)
|
|
68909
|
+
];
|
|
68558
68910
|
MIGRATIONS2 = [
|
|
68559
68911
|
{
|
|
68560
68912
|
version: 1,
|
|
@@ -68604,6 +68956,37 @@ var init_sqlite_provider = __esm(() => {
|
|
|
68604
68956
|
`
|
|
68605
68957
|
}
|
|
68606
68958
|
];
|
|
68959
|
+
FTS_STOP_WORDS = new Set([
|
|
68960
|
+
"a",
|
|
68961
|
+
"an",
|
|
68962
|
+
"and",
|
|
68963
|
+
"are",
|
|
68964
|
+
"as",
|
|
68965
|
+
"at",
|
|
68966
|
+
"be",
|
|
68967
|
+
"by",
|
|
68968
|
+
"for",
|
|
68969
|
+
"from",
|
|
68970
|
+
"goal",
|
|
68971
|
+
"how",
|
|
68972
|
+
"in",
|
|
68973
|
+
"into",
|
|
68974
|
+
"is",
|
|
68975
|
+
"it",
|
|
68976
|
+
"of",
|
|
68977
|
+
"on",
|
|
68978
|
+
"or",
|
|
68979
|
+
"role",
|
|
68980
|
+
"task",
|
|
68981
|
+
"that",
|
|
68982
|
+
"the",
|
|
68983
|
+
"this",
|
|
68984
|
+
"to",
|
|
68985
|
+
"user",
|
|
68986
|
+
"what",
|
|
68987
|
+
"when",
|
|
68988
|
+
"with"
|
|
68989
|
+
]);
|
|
68607
68990
|
});
|
|
68608
68991
|
|
|
68609
68992
|
// src/memory/gateway.ts
|
|
@@ -69119,102 +69502,6 @@ var init_agent_output_schema = __esm(() => {
|
|
|
69119
69502
|
}).passthrough();
|
|
69120
69503
|
});
|
|
69121
69504
|
|
|
69122
|
-
// src/memory/role-profiles.ts
|
|
69123
|
-
function resolveMemoryRecallProfile(agentRole) {
|
|
69124
|
-
const role = normalizeMemoryAgentRole(agentRole);
|
|
69125
|
-
return MEMORY_RECALL_PROFILES[role] ?? MEMORY_RECALL_PROFILES.coder;
|
|
69126
|
-
}
|
|
69127
|
-
function normalizeMemoryAgentRole(agentRole) {
|
|
69128
|
-
const base = stripKnownSwarmPrefix(agentRole ?? "architect");
|
|
69129
|
-
if (base === "reviewer" || base === "test_engineer")
|
|
69130
|
-
return "qa";
|
|
69131
|
-
if (base === "critic" || base === "critic_sounding_board" || base === "critic_drift_verifier" || base === "critic_hallucination_verifier") {
|
|
69132
|
-
return "security";
|
|
69133
|
-
}
|
|
69134
|
-
if (base === "curator_init" || base === "curator_phase")
|
|
69135
|
-
return "curator";
|
|
69136
|
-
if (base === "docs")
|
|
69137
|
-
return "sme";
|
|
69138
|
-
if (base === "architect" || base === "sme" || base === "coder" || base === "security" || base === "curator") {
|
|
69139
|
-
return base;
|
|
69140
|
-
}
|
|
69141
|
-
return "coder";
|
|
69142
|
-
}
|
|
69143
|
-
var MEMORY_RECALL_PROFILES;
|
|
69144
|
-
var init_role_profiles = __esm(() => {
|
|
69145
|
-
init_schema();
|
|
69146
|
-
MEMORY_RECALL_PROFILES = {
|
|
69147
|
-
architect: {
|
|
69148
|
-
kinds: [
|
|
69149
|
-
"project_fact",
|
|
69150
|
-
"architecture_decision",
|
|
69151
|
-
"repo_convention",
|
|
69152
|
-
"failure_pattern",
|
|
69153
|
-
"security_note"
|
|
69154
|
-
],
|
|
69155
|
-
maxItems: 10,
|
|
69156
|
-
tokenBudget: 1600
|
|
69157
|
-
},
|
|
69158
|
-
sme: {
|
|
69159
|
-
kinds: [
|
|
69160
|
-
"api_finding",
|
|
69161
|
-
"code_pattern",
|
|
69162
|
-
"repo_convention",
|
|
69163
|
-
"failure_pattern",
|
|
69164
|
-
"evidence"
|
|
69165
|
-
],
|
|
69166
|
-
maxItems: 8,
|
|
69167
|
-
tokenBudget: 1200
|
|
69168
|
-
},
|
|
69169
|
-
coder: {
|
|
69170
|
-
kinds: [
|
|
69171
|
-
"architecture_decision",
|
|
69172
|
-
"repo_convention",
|
|
69173
|
-
"code_pattern",
|
|
69174
|
-
"test_pattern",
|
|
69175
|
-
"failure_pattern"
|
|
69176
|
-
],
|
|
69177
|
-
maxItems: 8,
|
|
69178
|
-
tokenBudget: 1200
|
|
69179
|
-
},
|
|
69180
|
-
qa: {
|
|
69181
|
-
kinds: [
|
|
69182
|
-
"test_pattern",
|
|
69183
|
-
"failure_pattern",
|
|
69184
|
-
"repo_convention",
|
|
69185
|
-
"security_note"
|
|
69186
|
-
],
|
|
69187
|
-
maxItems: 8,
|
|
69188
|
-
tokenBudget: 1200
|
|
69189
|
-
},
|
|
69190
|
-
security: {
|
|
69191
|
-
kinds: [
|
|
69192
|
-
"security_note",
|
|
69193
|
-
"architecture_decision",
|
|
69194
|
-
"repo_convention",
|
|
69195
|
-
"evidence"
|
|
69196
|
-
],
|
|
69197
|
-
maxItems: 8,
|
|
69198
|
-
tokenBudget: 1200
|
|
69199
|
-
},
|
|
69200
|
-
curator: {
|
|
69201
|
-
kinds: [
|
|
69202
|
-
"project_fact",
|
|
69203
|
-
"architecture_decision",
|
|
69204
|
-
"repo_convention",
|
|
69205
|
-
"api_finding",
|
|
69206
|
-
"code_pattern",
|
|
69207
|
-
"test_pattern",
|
|
69208
|
-
"failure_pattern",
|
|
69209
|
-
"security_note",
|
|
69210
|
-
"evidence"
|
|
69211
|
-
],
|
|
69212
|
-
maxItems: 20,
|
|
69213
|
-
tokenBudget: 3000
|
|
69214
|
-
}
|
|
69215
|
-
};
|
|
69216
|
-
});
|
|
69217
|
-
|
|
69218
69505
|
// src/memory/recall-planner.ts
|
|
69219
69506
|
function buildMemoryRecallPlan(input, options = {}) {
|
|
69220
69507
|
const profile = options.profile ?? resolveMemoryRecallProfile(input.agentRole);
|
|
@@ -15,6 +15,7 @@ export declare class SQLiteMemoryProvider implements MemoryProvider, MemoryPropo
|
|
|
15
15
|
private readonly config;
|
|
16
16
|
private initialized;
|
|
17
17
|
private db;
|
|
18
|
+
private ftsAvailable;
|
|
18
19
|
private memories;
|
|
19
20
|
private proposals;
|
|
20
21
|
private lastAutomaticJsonlMigration;
|
|
@@ -48,10 +49,19 @@ export declare class SQLiteMemoryProvider implements MemoryProvider, MemoryPropo
|
|
|
48
49
|
}>;
|
|
49
50
|
hasMigration(name: string): boolean;
|
|
50
51
|
markMigration(version: number, name: string): void;
|
|
52
|
+
private selectRecallCandidates;
|
|
51
53
|
private runMigrations;
|
|
54
|
+
private initializeFtsIndex;
|
|
55
|
+
private recreateFtsIndex;
|
|
56
|
+
private rebuildFtsIndex;
|
|
57
|
+
private countValidMemoryRows;
|
|
58
|
+
private iterateMemoryRows;
|
|
59
|
+
private parseMemoryRow;
|
|
52
60
|
private loadMemories;
|
|
53
61
|
private loadProposals;
|
|
54
62
|
private writeMemory;
|
|
63
|
+
private writeMemoryFts;
|
|
64
|
+
private deleteMemoryFts;
|
|
55
65
|
private writeProposal;
|
|
56
66
|
private applyDecisionToStorage;
|
|
57
67
|
private readPendingProposal;
|
|
@@ -63,3 +73,12 @@ export declare class SQLiteMemoryProvider implements MemoryProvider, MemoryPropo
|
|
|
63
73
|
private insertEvent;
|
|
64
74
|
private requireDb;
|
|
65
75
|
}
|
|
76
|
+
declare function buildFtsQuery(request: RecallRequest): string | null;
|
|
77
|
+
declare function extractFtsTerms(text: string): Set<string>;
|
|
78
|
+
export declare const _test_exports: {
|
|
79
|
+
buildFtsQuery: typeof buildFtsQuery;
|
|
80
|
+
extractFtsTerms: typeof extractFtsTerms;
|
|
81
|
+
FTS_SCHEMA_MIGRATION_NAME: string;
|
|
82
|
+
FTS_SCHEMA_MIGRATION_VERSION: number;
|
|
83
|
+
};
|
|
84
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.37.0",
|
|
4
4
|
"description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|