opencode-codex-memory 0.1.6 → 0.1.7
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/src/llm.d.ts +1 -0
- package/dist/src/llm.js +39 -2
- package/dist/src/phase2.js +23 -3
- package/dist/src/templates/consolidation.md +629 -197
- package/dist/src/templates/read_path.md +68 -37
- package/dist/src/templates/stage_one_system.md +311 -75
- package/dist/src/workspace.d.ts +12 -0
- package/dist/src/workspace.js +30 -0
- package/package.json +1 -1
package/dist/src/llm.d.ts
CHANGED
|
@@ -15,5 +15,6 @@ export declare function extractViaSubagent(sessionId: string, transcript: string
|
|
|
15
15
|
export declare function consolidateViaSubagent(memoryRoot: string, diffFileName: string, model?: string): Promise<void>;
|
|
16
16
|
export declare function cleanupOldSubSessions(maxAgeMinutes?: number): Promise<void>;
|
|
17
17
|
export declare function fillTemplate(tmpl: string, vars: Record<string, string>): string;
|
|
18
|
+
export declare function buildConsolidationPrompt(memoryRoot: string, diffFileName: string): string;
|
|
18
19
|
/** Parses the stage-1 JSON output. Returns null for the all-empty no-op response. */
|
|
19
20
|
export declare function parseExtraction(raw: string): ExtractionResult | null;
|
package/dist/src/llm.js
CHANGED
|
@@ -209,10 +209,46 @@ function buildExtractionInput(sessionId, cwd, transcript) {
|
|
|
209
209
|
transcript,
|
|
210
210
|
});
|
|
211
211
|
}
|
|
212
|
-
|
|
212
|
+
// codex lib.rs prompt_blocks: rendered into consolidation.md's
|
|
213
|
+
// {{ memory_extensions_* }} placeholders when <memory_root>/extensions exists
|
|
214
|
+
// (prompts.rs build_consolidation_prompt), empty strings otherwise.
|
|
215
|
+
const EXTENSIONS_FOLDER_STRUCTURE = `
|
|
216
|
+
Memory extensions (under {{ memory_extensions_root }}/):
|
|
217
|
+
|
|
218
|
+
- <extension_name>/instructions.md
|
|
219
|
+
- Source-specific guidance for interpreting additional memory signals. If an
|
|
220
|
+
extension folder exists, you must read its instructions.md to determine how to use this memory
|
|
221
|
+
source.
|
|
222
|
+
|
|
223
|
+
If the user has any memory extensions, you MUST read the instructions for each extension to
|
|
224
|
+
determine how to use the memory source. If the workspace diff shows deleted extension resource files,
|
|
225
|
+
remove stale memories derived only from those resources. If it has no extension folders, continue
|
|
226
|
+
with the standard memory inputs only.
|
|
227
|
+
`;
|
|
228
|
+
const EXTENSIONS_PRIMARY_INPUTS = `
|
|
229
|
+
Optional source-specific inputs:
|
|
230
|
+
Under \`{{ memory_extensions_root }}/\`:
|
|
231
|
+
|
|
232
|
+
- \`<extension_name>/instructions.md\`
|
|
233
|
+
- If extension folders exist, read each instructions.md first and follow it when interpreting
|
|
234
|
+
that extension's memory source.
|
|
235
|
+
|
|
236
|
+
If the workspace diff shows deleted memory extension resources, use that extension-specific deletion
|
|
237
|
+
signal to remove stale memories derived only from those resources.
|
|
238
|
+
`;
|
|
239
|
+
export function buildConsolidationPrompt(memoryRoot, diffFileName) {
|
|
240
|
+
const extensionsRoot = path.join(memoryRoot, "extensions");
|
|
241
|
+
let extensionsExist = false;
|
|
242
|
+
try {
|
|
243
|
+
extensionsExist = fs.statSync(extensionsRoot).isDirectory();
|
|
244
|
+
}
|
|
245
|
+
catch { }
|
|
246
|
+
const blockVars = { memory_extensions_root: extensionsRoot };
|
|
213
247
|
return fillTemplate(readTemplate("consolidation.md"), {
|
|
214
248
|
memory_root: memoryRoot,
|
|
215
249
|
phase2_workspace_diff_file: diffFileName,
|
|
250
|
+
memory_extensions_folder_structure: extensionsExist ? fillTemplate(EXTENSIONS_FOLDER_STRUCTURE, blockVars) : "",
|
|
251
|
+
memory_extensions_primary_inputs: extensionsExist ? fillTemplate(EXTENSIONS_PRIMARY_INPUTS, blockVars) : "",
|
|
216
252
|
});
|
|
217
253
|
}
|
|
218
254
|
function readTemplate(name) {
|
|
@@ -231,7 +267,8 @@ export function parseExtraction(raw) {
|
|
|
231
267
|
if (typeof obj.raw_memory !== "string" || typeof obj.rollout_summary !== "string") {
|
|
232
268
|
throw new Error("extraction response missing required fields");
|
|
233
269
|
}
|
|
234
|
-
|
|
270
|
+
// codex phase1: either field empty → SucceededNoOutput (not a partial upsert).
|
|
271
|
+
if (!obj.raw_memory.trim() || !obj.rollout_summary.trim()) {
|
|
235
272
|
return null;
|
|
236
273
|
}
|
|
237
274
|
// Guard against the model echoing the format skeleton from the system prompt.
|
package/dist/src/phase2.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ensureLayout, rebuildRawMemories, writeRolloutSummaries, pruneExtensionResources, writeWorkspaceDiff } from "./workspace.js";
|
|
1
|
+
import { ensureLayout, rebuildRawMemories, writeRolloutSummaries, pruneExtensionResources, writeWorkspaceDiff, validateConsolidationArtifacts, } from "./workspace.js";
|
|
2
2
|
import { ensureBaseline, captureWorkspaceDiff, resetBaseline, DIFF_ARTIFACT } from "./git-baseline.js";
|
|
3
3
|
import { consolidateViaSubagent } from "./llm.js";
|
|
4
4
|
import { invalidateCache } from "./source.js";
|
|
@@ -37,9 +37,16 @@ export async function runPhase2(store, opts = DEFAULT_PHASE2_OPTIONS) {
|
|
|
37
37
|
writeRolloutSummaries(outputs);
|
|
38
38
|
pruneExtensionResources(opts.extensionRetentionDays);
|
|
39
39
|
const diff = await captureWorkspaceDiff();
|
|
40
|
+
// codex: early succeed only when there are no changes AND artifacts are
|
|
41
|
+
// already valid. Invalid/empty summary (e.g. ensureLayout's empty file)
|
|
42
|
+
// falls through so the consolidator can INIT/repair.
|
|
40
43
|
if (diff.changes.length === 0) {
|
|
41
|
-
|
|
42
|
-
|
|
44
|
+
const valid = validateConsolidationArtifacts();
|
|
45
|
+
if (valid.ok) {
|
|
46
|
+
store.markPhase2Succeeded(claim.ownershipToken, outputs);
|
|
47
|
+
return { status: "no_workspace_changes" };
|
|
48
|
+
}
|
|
49
|
+
console.warn("[opencode-codex-memory] no workspace changes but artifacts invalid; running consolidator:", valid.reason);
|
|
43
50
|
}
|
|
44
51
|
writeWorkspaceDiff(diff);
|
|
45
52
|
let heartbeatLost = false;
|
|
@@ -48,8 +55,10 @@ export async function runPhase2(store, opts = DEFAULT_PHASE2_OPTIONS) {
|
|
|
48
55
|
heartbeatLost = true;
|
|
49
56
|
}
|
|
50
57
|
}, 90_000);
|
|
58
|
+
let agentCompleted = false;
|
|
51
59
|
try {
|
|
52
60
|
await consolidateViaSubagent(memoryRoot(), DIFF_ARTIFACT, opts.consolidationModel);
|
|
61
|
+
agentCompleted = true;
|
|
53
62
|
}
|
|
54
63
|
finally {
|
|
55
64
|
clearInterval(heartbeat);
|
|
@@ -64,6 +73,17 @@ export async function runPhase2(store, opts = DEFAULT_PHASE2_OPTIONS) {
|
|
|
64
73
|
store.markPhase2Failed(claim.ownershipToken, "ownership lost");
|
|
65
74
|
return { status: "heartbeat_lost" };
|
|
66
75
|
}
|
|
76
|
+
if (!agentCompleted) {
|
|
77
|
+
store.markPhase2Failed(claim.ownershipToken, "failed_agent");
|
|
78
|
+
return { status: "failed_agent" };
|
|
79
|
+
}
|
|
80
|
+
// codex failed_invalid_artifacts: do not reset baseline on bad output so
|
|
81
|
+
// the next run still sees a diff / can re-INIT.
|
|
82
|
+
const artifacts = validateConsolidationArtifacts();
|
|
83
|
+
if (!artifacts.ok) {
|
|
84
|
+
store.markPhase2Failed(claim.ownershipToken, `failed_invalid_artifacts: ${artifacts.reason}`);
|
|
85
|
+
return { status: "failed_invalid_artifacts" };
|
|
86
|
+
}
|
|
67
87
|
if (!await resetBaseline()) {
|
|
68
88
|
store.markPhase2Failed(claim.ownershipToken, "baseline reset failed");
|
|
69
89
|
return { status: "baseline_reset_failed" };
|