open-research 0.1.10 → 0.1.12
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.js +271 -91
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -811,7 +811,7 @@ function formatDateTime(value) {
|
|
|
811
811
|
}
|
|
812
812
|
|
|
813
813
|
// src/lib/cli/version.ts
|
|
814
|
-
var PACKAGE_VERSION = "0.1.
|
|
814
|
+
var PACKAGE_VERSION = "0.1.12";
|
|
815
815
|
function getPackageVersion() {
|
|
816
816
|
return PACKAGE_VERSION;
|
|
817
817
|
}
|
|
@@ -4761,131 +4761,283 @@ async function manualCompact(messages, model, provider, usage, customInstruction
|
|
|
4761
4761
|
// src/lib/memory/store.ts
|
|
4762
4762
|
import fs14 from "fs/promises";
|
|
4763
4763
|
import path13 from "path";
|
|
4764
|
-
function
|
|
4764
|
+
function getGlobalMemoryFile(options) {
|
|
4765
4765
|
return path13.join(getOpenResearchRoot(options), "memory.json");
|
|
4766
4766
|
}
|
|
4767
|
-
|
|
4768
|
-
|
|
4767
|
+
function getProjectMemoryFile(workspaceDir) {
|
|
4768
|
+
return path13.join(workspaceDir, ".open-research", "memory.json");
|
|
4769
|
+
}
|
|
4770
|
+
async function loadMemoryFile(filePath) {
|
|
4769
4771
|
try {
|
|
4770
|
-
const raw = await fs14.readFile(
|
|
4772
|
+
const raw = await fs14.readFile(filePath, "utf8");
|
|
4771
4773
|
const store = JSON.parse(raw);
|
|
4772
4774
|
return store.memories ?? [];
|
|
4773
4775
|
} catch {
|
|
4774
4776
|
return [];
|
|
4775
4777
|
}
|
|
4776
4778
|
}
|
|
4777
|
-
async function
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
await fs14.writeFile(file, JSON.stringify(store, null, 2), "utf8");
|
|
4779
|
+
async function saveMemoryFile(filePath, memories) {
|
|
4780
|
+
await fs14.mkdir(path13.dirname(filePath), { recursive: true });
|
|
4781
|
+
const store = { version: 2, memories };
|
|
4782
|
+
await fs14.writeFile(filePath, JSON.stringify(store, null, 2), "utf8");
|
|
4782
4783
|
}
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4784
|
+
async function loadGlobalMemories(options) {
|
|
4785
|
+
const mems = await loadMemoryFile(getGlobalMemoryFile(options));
|
|
4786
|
+
return mems.map((m) => ({ ...m, scope: "global" }));
|
|
4787
|
+
}
|
|
4788
|
+
async function loadProjectMemories(workspaceDir) {
|
|
4789
|
+
const mems = await loadMemoryFile(getProjectMemoryFile(workspaceDir));
|
|
4790
|
+
return mems.map((m) => ({ ...m, scope: "project" }));
|
|
4791
|
+
}
|
|
4792
|
+
async function loadAllMemories(options) {
|
|
4793
|
+
const global = await loadGlobalMemories(options);
|
|
4794
|
+
const project = options?.workspaceDir ? await loadProjectMemories(options.workspaceDir) : [];
|
|
4795
|
+
return [...global, ...project];
|
|
4796
|
+
}
|
|
4797
|
+
var MAX_MEMORIES_PER_STORE = 100;
|
|
4798
|
+
function findDuplicate(memories, content) {
|
|
4799
|
+
const b = content.toLowerCase().replace(/\s+/g, " ");
|
|
4800
|
+
const wordsB = new Set(b.split(" ").filter((w) => w.length > 2));
|
|
4801
|
+
return memories.find((m) => {
|
|
4787
4802
|
const a = m.content.toLowerCase().replace(/\s+/g, " ");
|
|
4788
|
-
const
|
|
4789
|
-
const wordsA = new Set(a.split(" "));
|
|
4790
|
-
const wordsB = new Set(b.split(" "));
|
|
4803
|
+
const wordsA = new Set(a.split(" ").filter((w) => w.length > 2));
|
|
4791
4804
|
const intersection = [...wordsA].filter((w) => wordsB.has(w));
|
|
4792
|
-
|
|
4793
|
-
return similarity > 0.7;
|
|
4805
|
+
return intersection.length / Math.max(wordsA.size, wordsB.size) > 0.7;
|
|
4794
4806
|
});
|
|
4807
|
+
}
|
|
4808
|
+
function evictIfNeeded(memories) {
|
|
4809
|
+
if (memories.length <= MAX_MEMORIES_PER_STORE) return;
|
|
4810
|
+
memories.sort((a, b) => {
|
|
4811
|
+
const aScore = new Date(a.lastRelevantAt).getTime() + a.relevanceCount * 864e5;
|
|
4812
|
+
const bScore = new Date(b.lastRelevantAt).getTime() + b.relevanceCount * 864e5;
|
|
4813
|
+
return bScore - aScore;
|
|
4814
|
+
});
|
|
4815
|
+
memories.length = MAX_MEMORIES_PER_STORE;
|
|
4816
|
+
}
|
|
4817
|
+
async function addMemory(memory, options) {
|
|
4818
|
+
const scope = memory.scope ?? (memory.category === "project" || memory.category === "context" ? "project" : "global");
|
|
4819
|
+
const filePath = scope === "project" && options?.workspaceDir ? getProjectMemoryFile(options.workspaceDir) : getGlobalMemoryFile(options);
|
|
4820
|
+
const memories = await loadMemoryFile(filePath);
|
|
4821
|
+
const existing = findDuplicate(memories, memory.content);
|
|
4795
4822
|
if (existing) {
|
|
4796
4823
|
existing.lastRelevantAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4797
4824
|
existing.relevanceCount++;
|
|
4798
4825
|
if (memory.content.length > existing.content.length) {
|
|
4799
4826
|
existing.content = memory.content;
|
|
4800
4827
|
}
|
|
4801
|
-
await
|
|
4802
|
-
return existing;
|
|
4828
|
+
await saveMemoryFile(filePath, memories);
|
|
4829
|
+
return { ...existing, scope };
|
|
4803
4830
|
}
|
|
4804
4831
|
const newMemory = {
|
|
4805
4832
|
id: crypto.randomUUID(),
|
|
4806
4833
|
content: memory.content,
|
|
4807
4834
|
category: memory.category,
|
|
4835
|
+
scope,
|
|
4808
4836
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4809
4837
|
lastRelevantAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4810
4838
|
relevanceCount: 1
|
|
4811
4839
|
};
|
|
4812
4840
|
memories.push(newMemory);
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
const aScore = new Date(a.lastRelevantAt).getTime() + a.relevanceCount * 864e5;
|
|
4816
|
-
const bScore = new Date(b.lastRelevantAt).getTime() + b.relevanceCount * 864e5;
|
|
4817
|
-
return bScore - aScore;
|
|
4818
|
-
});
|
|
4819
|
-
memories.length = MAX_MEMORIES;
|
|
4820
|
-
}
|
|
4821
|
-
await saveMemories(memories, options);
|
|
4841
|
+
evictIfNeeded(memories);
|
|
4842
|
+
await saveMemoryFile(filePath, memories);
|
|
4822
4843
|
return newMemory;
|
|
4823
4844
|
}
|
|
4824
4845
|
async function deleteMemory(id, options) {
|
|
4825
|
-
const
|
|
4826
|
-
const
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4846
|
+
const globalFile = getGlobalMemoryFile(options);
|
|
4847
|
+
const global = await loadMemoryFile(globalFile);
|
|
4848
|
+
const gIdx = global.findIndex((m) => m.id === id);
|
|
4849
|
+
if (gIdx !== -1) {
|
|
4850
|
+
global.splice(gIdx, 1);
|
|
4851
|
+
await saveMemoryFile(globalFile, global);
|
|
4852
|
+
return true;
|
|
4853
|
+
}
|
|
4854
|
+
if (options?.workspaceDir) {
|
|
4855
|
+
const projectFile = getProjectMemoryFile(options.workspaceDir);
|
|
4856
|
+
const project = await loadMemoryFile(projectFile);
|
|
4857
|
+
const pIdx = project.findIndex((m) => m.id === id);
|
|
4858
|
+
if (pIdx !== -1) {
|
|
4859
|
+
project.splice(pIdx, 1);
|
|
4860
|
+
await saveMemoryFile(projectFile, project);
|
|
4861
|
+
return true;
|
|
4862
|
+
}
|
|
4863
|
+
}
|
|
4864
|
+
return false;
|
|
4831
4865
|
}
|
|
4832
4866
|
async function clearMemories(options) {
|
|
4833
|
-
|
|
4867
|
+
if (!options?.scope || options.scope === "global") {
|
|
4868
|
+
await saveMemoryFile(getGlobalMemoryFile(options), []);
|
|
4869
|
+
}
|
|
4870
|
+
if (options?.workspaceDir && (!options?.scope || options.scope === "project")) {
|
|
4871
|
+
await saveMemoryFile(getProjectMemoryFile(options.workspaceDir), []);
|
|
4872
|
+
}
|
|
4873
|
+
}
|
|
4874
|
+
var STOP_WORDS = /* @__PURE__ */ new Set([
|
|
4875
|
+
"the",
|
|
4876
|
+
"a",
|
|
4877
|
+
"an",
|
|
4878
|
+
"is",
|
|
4879
|
+
"are",
|
|
4880
|
+
"was",
|
|
4881
|
+
"were",
|
|
4882
|
+
"be",
|
|
4883
|
+
"been",
|
|
4884
|
+
"being",
|
|
4885
|
+
"have",
|
|
4886
|
+
"has",
|
|
4887
|
+
"had",
|
|
4888
|
+
"do",
|
|
4889
|
+
"does",
|
|
4890
|
+
"did",
|
|
4891
|
+
"will",
|
|
4892
|
+
"would",
|
|
4893
|
+
"could",
|
|
4894
|
+
"should",
|
|
4895
|
+
"may",
|
|
4896
|
+
"might",
|
|
4897
|
+
"can",
|
|
4898
|
+
"shall",
|
|
4899
|
+
"to",
|
|
4900
|
+
"of",
|
|
4901
|
+
"in",
|
|
4902
|
+
"for",
|
|
4903
|
+
"on",
|
|
4904
|
+
"with",
|
|
4905
|
+
"at",
|
|
4906
|
+
"by",
|
|
4907
|
+
"from",
|
|
4908
|
+
"as",
|
|
4909
|
+
"into",
|
|
4910
|
+
"through",
|
|
4911
|
+
"about",
|
|
4912
|
+
"and",
|
|
4913
|
+
"but",
|
|
4914
|
+
"or",
|
|
4915
|
+
"not",
|
|
4916
|
+
"no",
|
|
4917
|
+
"if",
|
|
4918
|
+
"then",
|
|
4919
|
+
"than",
|
|
4920
|
+
"so",
|
|
4921
|
+
"that",
|
|
4922
|
+
"this",
|
|
4923
|
+
"it",
|
|
4924
|
+
"its",
|
|
4925
|
+
"i",
|
|
4926
|
+
"me",
|
|
4927
|
+
"my",
|
|
4928
|
+
"we",
|
|
4929
|
+
"our",
|
|
4930
|
+
"you",
|
|
4931
|
+
"your",
|
|
4932
|
+
"what",
|
|
4933
|
+
"which",
|
|
4934
|
+
"who",
|
|
4935
|
+
"how",
|
|
4936
|
+
"when",
|
|
4937
|
+
"where",
|
|
4938
|
+
"why"
|
|
4939
|
+
]);
|
|
4940
|
+
function tokenize(text) {
|
|
4941
|
+
return text.toLowerCase().replace(/[^a-z0-9\s-]/g, " ").split(/\s+/).filter((w) => w.length > 2 && !STOP_WORDS.has(w));
|
|
4942
|
+
}
|
|
4943
|
+
function scoreRelevance(memory, queryTokens) {
|
|
4944
|
+
const memTokens = tokenize(memory.content);
|
|
4945
|
+
if (memTokens.length === 0) return 0;
|
|
4946
|
+
let matches = 0;
|
|
4947
|
+
for (const token of memTokens) {
|
|
4948
|
+
if (queryTokens.has(token)) matches++;
|
|
4949
|
+
}
|
|
4950
|
+
const overlapScore = matches / memTokens.length;
|
|
4951
|
+
const categoryBoost = memory.category === "user" ? 0.3 : memory.category === "preference" ? 0.2 : memory.category === "methodology" ? 0.15 : 0;
|
|
4952
|
+
const ageMs = Date.now() - new Date(memory.lastRelevantAt).getTime();
|
|
4953
|
+
const ageDays = ageMs / 864e5;
|
|
4954
|
+
const recencyBoost = Math.max(0, 0.1 - ageDays * 1e-3);
|
|
4955
|
+
const freqBoost = Math.min(0.1, memory.relevanceCount * 0.02);
|
|
4956
|
+
return overlapScore + categoryBoost + recencyBoost + freqBoost;
|
|
4957
|
+
}
|
|
4958
|
+
var MIN_RELEVANCE_SCORE = 0.15;
|
|
4959
|
+
var MAX_INJECTED_MEMORIES = 15;
|
|
4960
|
+
var ALWAYS_INCLUDE_CATEGORIES = ["user", "preference"];
|
|
4961
|
+
function selectRelevantMemories(allMemories, userQuery) {
|
|
4962
|
+
if (allMemories.length === 0) return [];
|
|
4963
|
+
const queryTokens = new Set(tokenize(userQuery));
|
|
4964
|
+
const alwaysInclude = allMemories.filter(
|
|
4965
|
+
(m) => ALWAYS_INCLUDE_CATEGORIES.includes(m.category)
|
|
4966
|
+
);
|
|
4967
|
+
const candidates = allMemories.filter((m) => !ALWAYS_INCLUDE_CATEGORIES.includes(m.category)).map((m) => ({ memory: m, score: scoreRelevance(m, queryTokens) })).filter((c) => c.score >= MIN_RELEVANCE_SCORE).sort((a, b) => b.score - a.score);
|
|
4968
|
+
const selected = [
|
|
4969
|
+
...alwaysInclude.slice(0, 5),
|
|
4970
|
+
// Max 5 identity memories
|
|
4971
|
+
...candidates.slice(0, MAX_INJECTED_MEMORIES - Math.min(alwaysInclude.length, 5)).map((c) => c.memory)
|
|
4972
|
+
];
|
|
4973
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4974
|
+
for (const m of selected) {
|
|
4975
|
+
m.lastRelevantAt = now;
|
|
4976
|
+
}
|
|
4977
|
+
return selected;
|
|
4834
4978
|
}
|
|
4835
4979
|
function formatMemoriesForPrompt(memories) {
|
|
4836
4980
|
if (memories.length === 0) return "";
|
|
4837
|
-
const
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
context: "Context"
|
|
4848
|
-
};
|
|
4849
|
-
for (const [cat, mems] of Object.entries(grouped)) {
|
|
4850
|
-
sections.push(`**${categoryLabels[cat] ?? cat}:**`);
|
|
4851
|
-
for (const m of mems) {
|
|
4852
|
-
sections.push(`- ${m.content}`);
|
|
4853
|
-
}
|
|
4981
|
+
const global = memories.filter((m) => m.scope === "global");
|
|
4982
|
+
const project = memories.filter((m) => m.scope === "project");
|
|
4983
|
+
const sections = ["## Relevant Context"];
|
|
4984
|
+
if (global.length > 0) {
|
|
4985
|
+
sections.push("**About you:**");
|
|
4986
|
+
for (const m of global) sections.push(`- ${m.content}`);
|
|
4987
|
+
}
|
|
4988
|
+
if (project.length > 0) {
|
|
4989
|
+
sections.push("**This project:**");
|
|
4990
|
+
for (const m of project) sections.push(`- ${m.content}`);
|
|
4854
4991
|
}
|
|
4855
4992
|
return sections.join("\n");
|
|
4856
4993
|
}
|
|
4857
4994
|
|
|
4858
4995
|
// src/lib/memory/extractor.ts
|
|
4859
|
-
var EXTRACTION_PROMPT = `You are a memory
|
|
4996
|
+
var EXTRACTION_PROMPT = `You are a memory management system. You decide what to remember about the user across sessions.
|
|
4860
4997
|
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
- How they prefer to work (preferred tools, languages, writing style, methodologies)
|
|
4865
|
-
- Methodological preferences (statistical approaches, theoretical frameworks, citation style)
|
|
4866
|
-
- Important context (collaborators, advisors, publication targets, funding constraints)
|
|
4998
|
+
You will receive:
|
|
4999
|
+
1. The current conversation exchange
|
|
5000
|
+
2. ALL existing memories (both global and project-level)
|
|
4867
5001
|
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
- Do NOT
|
|
4872
|
-
-
|
|
4873
|
-
-
|
|
4874
|
-
- Maximum 3
|
|
4875
|
-
|
|
4876
|
-
|
|
5002
|
+
Your job: decide if any NEW memories should be created OR if any existing memories need updating.
|
|
5003
|
+
|
|
5004
|
+
CRITICAL RULES:
|
|
5005
|
+
- Do NOT create a memory if an existing memory already covers the same fact
|
|
5006
|
+
- If a fact has CHANGED (e.g., user switched from Python to R), output an UPDATE to the existing memory instead of creating a new one
|
|
5007
|
+
- Only create memories for facts useful in FUTURE sessions, not task-specific details
|
|
5008
|
+
- Maximum 3 actions per exchange
|
|
5009
|
+
- If nothing meaningful to remember, return an empty array
|
|
5010
|
+
|
|
5011
|
+
Categories:
|
|
5012
|
+
- "user" \u2014 identity, role, field, institution (\u2192 stored globally)
|
|
5013
|
+
- "preference" \u2014 tools, style, methodology preferences (\u2192 stored globally)
|
|
5014
|
+
- "project" \u2014 current research topics, findings, hypotheses (\u2192 stored per-project)
|
|
5015
|
+
- "methodology" \u2014 statistical approaches, frameworks (\u2192 stored globally)
|
|
5016
|
+
- "context" \u2014 deadlines, collaborators, constraints (\u2192 stored per-project)
|
|
5017
|
+
|
|
5018
|
+
Existing memories:
|
|
4877
5019
|
{EXISTING_MEMORIES}
|
|
4878
5020
|
|
|
4879
|
-
Respond with a JSON array
|
|
5021
|
+
Respond with a JSON array. Each item has:
|
|
5022
|
+
- "action": "create" or "update"
|
|
5023
|
+
- "content": the memory text (for create: new content; for update: the updated content)
|
|
5024
|
+
- "category": one of the categories above
|
|
5025
|
+
- "updateId": (only for "update") the ID of the existing memory to update
|
|
4880
5026
|
|
|
4881
|
-
|
|
4882
|
-
|
|
5027
|
+
If nothing to do, respond with [].
|
|
5028
|
+
|
|
5029
|
+
Example:
|
|
5030
|
+
[{"action": "create", "content": "PhD student in neuroscience at MIT", "category": "user"}]
|
|
5031
|
+
[{"action": "update", "updateId": "abc123", "content": "Now using R instead of Python for analysis", "category": "preference"}]`;
|
|
4883
5032
|
async function extractMemories(input2) {
|
|
4884
|
-
const existing = await
|
|
5033
|
+
const existing = await loadAllMemories({
|
|
5034
|
+
homeDir: input2.homeDir,
|
|
5035
|
+
workspaceDir: input2.workspaceDir
|
|
5036
|
+
});
|
|
4885
5037
|
if (input2.userMessage.startsWith("/") || input2.userMessage.length < 20) {
|
|
4886
5038
|
return [];
|
|
4887
5039
|
}
|
|
4888
|
-
const existingList = existing.length > 0 ? existing.map((m) => `- [${m.category}] ${m.content}`).join("\n") : "(none)";
|
|
5040
|
+
const existingList = existing.length > 0 ? existing.map((m) => `- [${m.scope}/${m.category}] (id: ${m.id.slice(0, 8)}) ${m.content}`).join("\n") : "(none)";
|
|
4889
5041
|
const prompt2 = EXTRACTION_PROMPT.replace("{EXISTING_MEMORIES}", existingList);
|
|
4890
5042
|
const conversationSnippet = [
|
|
4891
5043
|
`User: ${input2.userMessage.slice(0, 2e3)}`,
|
|
@@ -4907,10 +5059,12 @@ async function extractMemories(input2) {
|
|
|
4907
5059
|
if (!Array.isArray(parsed)) return [];
|
|
4908
5060
|
const valid = [];
|
|
4909
5061
|
for (const item of parsed) {
|
|
4910
|
-
if (typeof item.content === "string" && item.content.length > 5 && ["user", "preference", "project", "methodology", "context"].includes(item.category)) {
|
|
5062
|
+
if (typeof item.content === "string" && item.content.length > 5 && ["user", "preference", "project", "methodology", "context"].includes(item.category) && ["create", "update"].includes(item.action)) {
|
|
4911
5063
|
valid.push({
|
|
5064
|
+
action: item.action,
|
|
4912
5065
|
content: item.content,
|
|
4913
|
-
category: item.category
|
|
5066
|
+
category: item.category,
|
|
5067
|
+
updateId: typeof item.updateId === "string" ? item.updateId : void 0
|
|
4914
5068
|
});
|
|
4915
5069
|
}
|
|
4916
5070
|
}
|
|
@@ -4920,13 +5074,35 @@ async function extractMemories(input2) {
|
|
|
4920
5074
|
}
|
|
4921
5075
|
}
|
|
4922
5076
|
async function extractAndStoreMemories(input2) {
|
|
4923
|
-
const
|
|
4924
|
-
const
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
5077
|
+
const actions = await extractMemories(input2);
|
|
5078
|
+
const results = [];
|
|
5079
|
+
const existing = await loadAllMemories({
|
|
5080
|
+
homeDir: input2.homeDir,
|
|
5081
|
+
workspaceDir: input2.workspaceDir
|
|
5082
|
+
});
|
|
5083
|
+
for (const action of actions) {
|
|
5084
|
+
if (action.action === "update" && action.updateId) {
|
|
5085
|
+
const target = existing.find((m) => m.id.startsWith(action.updateId));
|
|
5086
|
+
if (target) {
|
|
5087
|
+
target.content = action.content;
|
|
5088
|
+
target.lastRelevantAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5089
|
+
target.relevanceCount++;
|
|
5090
|
+
const saved = await addMemory(
|
|
5091
|
+
{ content: action.content, category: action.category, scope: target.scope },
|
|
5092
|
+
{ homeDir: input2.homeDir, workspaceDir: input2.workspaceDir }
|
|
5093
|
+
);
|
|
5094
|
+
results.push(saved);
|
|
5095
|
+
}
|
|
5096
|
+
} else {
|
|
5097
|
+
const scope = action.category === "project" || action.category === "context" ? "project" : "global";
|
|
5098
|
+
const saved = await addMemory(
|
|
5099
|
+
{ content: action.content, category: action.category, scope },
|
|
5100
|
+
{ homeDir: input2.homeDir, workspaceDir: input2.workspaceDir }
|
|
5101
|
+
);
|
|
5102
|
+
results.push(saved);
|
|
5103
|
+
}
|
|
4928
5104
|
}
|
|
4929
|
-
return
|
|
5105
|
+
return results;
|
|
4930
5106
|
}
|
|
4931
5107
|
|
|
4932
5108
|
// src/lib/workspace/agents-md.ts
|
|
@@ -5083,16 +5259,19 @@ async function runAgentTurn(input2) {
|
|
|
5083
5259
|
const systemPrompt = isPlanning ? buildPlanningSystemPrompt(input2.workspace, activeSkills) : buildSystemPrompt(input2.workspace, activeSkills);
|
|
5084
5260
|
const model = input2.model ?? "gpt-5.4";
|
|
5085
5261
|
const usage = input2.sessionUsage ?? createSessionUsage();
|
|
5086
|
-
const
|
|
5087
|
-
|
|
5262
|
+
const allMemories = await loadAllMemories({
|
|
5263
|
+
homeDir: input2.homeDir,
|
|
5264
|
+
workspaceDir: input2.workspace.workspaceDir
|
|
5265
|
+
});
|
|
5266
|
+
const relevantMemories = selectRelevantMemories(allMemories, input2.message);
|
|
5267
|
+
const memoryBlock = formatMemoriesForPrompt(relevantMemories);
|
|
5088
5268
|
const agentsMd = input2.workspace.workspaceDir ? await readAgentsMd(input2.workspace.workspaceDir).catch(() => "") : "";
|
|
5089
|
-
const
|
|
5269
|
+
const fullSystemPrompt = [
|
|
5090
5270
|
systemPrompt,
|
|
5091
|
-
memoryBlock
|
|
5271
|
+
memoryBlock || null,
|
|
5092
5272
|
agentsMd ? `## Project Context (from AGENTS.md)
|
|
5093
5273
|
${agentsMd}` : null
|
|
5094
5274
|
].filter(Boolean).join("\n\n");
|
|
5095
|
-
const fullSystemPrompt = contextBlocks;
|
|
5096
5275
|
let messages = [
|
|
5097
5276
|
{ role: "system", content: fullSystemPrompt },
|
|
5098
5277
|
...input2.history,
|
|
@@ -5152,7 +5331,8 @@ ${agentsMd}` : null
|
|
|
5152
5331
|
agentResponse: fullText,
|
|
5153
5332
|
provider: input2.provider,
|
|
5154
5333
|
model: "gpt-5.4-mini",
|
|
5155
|
-
homeDir: input2.homeDir
|
|
5334
|
+
homeDir: input2.homeDir,
|
|
5335
|
+
workspaceDir: input2.workspace.workspaceDir
|
|
5156
5336
|
}).then((stored) => {
|
|
5157
5337
|
if (stored.length > 0) {
|
|
5158
5338
|
input2.onMemoryExtracted?.(stored.map((m) => m.content));
|
|
@@ -7006,7 +7186,7 @@ ${msg.text}
|
|
|
7006
7186
|
addSystemMessage(` Workspace: ${workspacePath ? workspacePath : "none"}`);
|
|
7007
7187
|
addSystemMessage(` Files: ${workspaceFiles.length}`);
|
|
7008
7188
|
addSystemMessage(` Skills: ${skills2.length} loaded`);
|
|
7009
|
-
const mems = await
|
|
7189
|
+
const mems = await loadAllMemories({ homeDir });
|
|
7010
7190
|
addSystemMessage(` Memories: ${mems.length} stored`);
|
|
7011
7191
|
addSystemMessage(` Node: ${process.version}`);
|
|
7012
7192
|
const toolChecks = ["python3 --version", "pdflatex --version", "git --version"];
|
|
@@ -7057,7 +7237,7 @@ ${msg.text}
|
|
|
7057
7237
|
addSystemMessage(deleted ? `Deleted memory ${memId.slice(0, 8)}...` : "Memory not found.");
|
|
7058
7238
|
break;
|
|
7059
7239
|
}
|
|
7060
|
-
const mems = await
|
|
7240
|
+
const mems = await loadAllMemories({ homeDir });
|
|
7061
7241
|
if (mems.length === 0) {
|
|
7062
7242
|
addSystemMessage("No memories stored yet. I'll learn about you as we talk.");
|
|
7063
7243
|
} else {
|
package/package.json
CHANGED