@oyasmi/pipiclaw 0.5.0 → 0.5.2
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/agent/channel-runner.d.ts +46 -0
- package/dist/agent/channel-runner.d.ts.map +1 -0
- package/dist/agent/channel-runner.js +434 -0
- package/dist/agent/channel-runner.js.map +1 -0
- package/dist/agent/index.d.ts +4 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +3 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/progress-formatter.d.ts +5 -0
- package/dist/agent/progress-formatter.d.ts.map +1 -0
- package/dist/agent/progress-formatter.js +53 -0
- package/dist/agent/progress-formatter.js.map +1 -0
- package/dist/agent/run-queue.d.ts +8 -0
- package/dist/agent/run-queue.d.ts.map +1 -0
- package/dist/agent/run-queue.js +27 -0
- package/dist/agent/run-queue.js.map +1 -0
- package/dist/agent/runner-factory.d.ts +4 -0
- package/dist/agent/runner-factory.d.ts.map +1 -0
- package/dist/agent/runner-factory.js +11 -0
- package/dist/agent/runner-factory.js.map +1 -0
- package/dist/agent/session-events.d.ts +15 -0
- package/dist/agent/session-events.d.ts.map +1 -0
- package/dist/agent/session-events.js +216 -0
- package/dist/agent/session-events.js.map +1 -0
- package/dist/agent/type-guards.d.ts +23 -0
- package/dist/agent/type-guards.d.ts.map +1 -0
- package/dist/agent/type-guards.js +107 -0
- package/dist/agent/type-guards.js.map +1 -0
- package/dist/agent/types.d.ts +161 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +23 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/agent.d.ts +2 -15
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +1 -781
- package/dist/agent.js.map +1 -1
- package/dist/context.d.ts +58 -14
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +50 -7
- package/dist/context.js.map +1 -1
- package/dist/index.d.ts +12 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -12
- package/dist/index.js.map +1 -1
- package/dist/main.js +5 -404
- package/dist/main.js.map +1 -1
- package/dist/memory/bootstrap.d.ts +7 -0
- package/dist/memory/bootstrap.d.ts.map +1 -0
- package/dist/memory/bootstrap.js +47 -0
- package/dist/memory/bootstrap.js.map +1 -0
- package/dist/{memory-candidates.d.ts → memory/candidates.d.ts} +2 -1
- package/dist/memory/candidates.d.ts.map +1 -0
- package/dist/{memory-candidates.js → memory/candidates.js} +34 -21
- package/dist/memory/candidates.js.map +1 -0
- package/dist/memory/chinese-words.d.ts +2 -0
- package/dist/memory/chinese-words.d.ts.map +1 -0
- package/dist/memory/chinese-words.js +210 -0
- package/dist/memory/chinese-words.js.map +1 -0
- package/dist/{memory-consolidation.d.ts → memory/consolidation.d.ts} +1 -1
- package/dist/memory/consolidation.d.ts.map +1 -0
- package/dist/{memory-consolidation.js → memory/consolidation.js} +27 -35
- package/dist/memory/consolidation.js.map +1 -0
- package/dist/{memory-files.d.ts → memory/files.d.ts} +1 -6
- package/dist/memory/files.d.ts.map +1 -0
- package/dist/{memory-files.js → memory/files.js} +12 -36
- package/dist/memory/files.js.map +1 -0
- package/dist/{memory-lifecycle.d.ts → memory/lifecycle.d.ts} +24 -6
- package/dist/memory/lifecycle.d.ts.map +1 -0
- package/dist/memory/lifecycle.js +247 -0
- package/dist/memory/lifecycle.js.map +1 -0
- package/dist/{memory-recall.d.ts → memory/recall.d.ts} +2 -2
- package/dist/memory/recall.d.ts.map +1 -0
- package/dist/memory/recall.js +435 -0
- package/dist/memory/recall.js.map +1 -0
- package/dist/{session-memory.d.ts → memory/session.d.ts} +2 -1
- package/dist/memory/session.d.ts.map +1 -0
- package/dist/{session-memory.js → memory/session.js} +32 -62
- package/dist/memory/session.js.map +1 -0
- package/dist/runtime/bootstrap.d.ts +48 -0
- package/dist/runtime/bootstrap.d.ts.map +1 -0
- package/dist/runtime/bootstrap.js +451 -0
- package/dist/runtime/bootstrap.js.map +1 -0
- package/dist/runtime/delivery.d.ts.map +1 -0
- package/dist/{delivery.js → runtime/delivery.js} +1 -1
- package/dist/runtime/delivery.js.map +1 -0
- package/dist/{dingtalk.d.ts → runtime/dingtalk.d.ts} +10 -0
- package/dist/runtime/dingtalk.d.ts.map +1 -0
- package/dist/{dingtalk.js → runtime/dingtalk.js} +87 -27
- package/dist/runtime/dingtalk.js.map +1 -0
- package/dist/runtime/events.d.ts.map +1 -0
- package/dist/{events.js → runtime/events.js} +1 -1
- package/dist/runtime/events.js.map +1 -0
- package/dist/{store.d.ts → runtime/store.d.ts} +5 -0
- package/dist/runtime/store.d.ts.map +1 -0
- package/dist/{store.js → runtime/store.js} +60 -19
- package/dist/runtime/store.js.map +1 -0
- package/dist/shared/markdown-sections.d.ts +7 -0
- package/dist/shared/markdown-sections.d.ts.map +1 -0
- package/dist/{markdown-sections.js → shared/markdown-sections.js} +10 -3
- package/dist/shared/markdown-sections.js.map +1 -0
- package/dist/shared/text-utils.d.ts +10 -0
- package/dist/shared/text-utils.d.ts.map +1 -0
- package/dist/shared/text-utils.js +37 -0
- package/dist/shared/text-utils.js.map +1 -0
- package/dist/shared/type-guards.d.ts +6 -0
- package/dist/shared/type-guards.d.ts.map +1 -0
- package/dist/shared/type-guards.js +13 -0
- package/dist/shared/type-guards.js.map +1 -0
- package/dist/shared/types.d.ts +15 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +2 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/sidecar-worker.d.ts.map +1 -1
- package/dist/sidecar-worker.js +1 -7
- package/dist/sidecar-worker.js.map +1 -1
- package/dist/{sub-agents.d.ts → subagents/discovery.d.ts} +1 -1
- package/dist/subagents/discovery.d.ts.map +1 -0
- package/dist/{sub-agents.js → subagents/discovery.js} +3 -3
- package/dist/subagents/discovery.js.map +1 -0
- package/dist/{tools/subagent.d.ts → subagents/tool.d.ts} +3 -16
- package/dist/{tools/subagent.d.ts.map → subagents/tool.d.ts.map} +1 -1
- package/dist/{tools/subagent.js → subagents/tool.js} +17 -38
- package/dist/subagents/tool.js.map +1 -0
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +1 -1
- package/dist/tools/index.js.map +1 -1
- package/docs/memory-audit.md +330 -0
- package/docs/memory-optimization-round2.md +319 -0
- package/package.json +1 -1
- package/dist/delivery.d.ts.map +0 -1
- package/dist/delivery.js.map +0 -1
- package/dist/dingtalk.d.ts.map +0 -1
- package/dist/dingtalk.js.map +0 -1
- package/dist/events.d.ts.map +0 -1
- package/dist/events.js.map +0 -1
- package/dist/markdown-sections.d.ts +0 -6
- package/dist/markdown-sections.d.ts.map +0 -1
- package/dist/markdown-sections.js.map +0 -1
- package/dist/memory-candidates.d.ts.map +0 -1
- package/dist/memory-candidates.js.map +0 -1
- package/dist/memory-consolidation.d.ts.map +0 -1
- package/dist/memory-consolidation.js.map +0 -1
- package/dist/memory-files.d.ts.map +0 -1
- package/dist/memory-files.js.map +0 -1
- package/dist/memory-lifecycle.d.ts.map +0 -1
- package/dist/memory-lifecycle.js +0 -150
- package/dist/memory-lifecycle.js.map +0 -1
- package/dist/memory-recall.d.ts.map +0 -1
- package/dist/memory-recall.js +0 -218
- package/dist/memory-recall.js.map +0 -1
- package/dist/session-memory-files.d.ts +0 -2
- package/dist/session-memory-files.d.ts.map +0 -1
- package/dist/session-memory-files.js +0 -2
- package/dist/session-memory-files.js.map +0 -1
- package/dist/session-memory.d.ts.map +0 -1
- package/dist/session-memory.js.map +0 -1
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js.map +0 -1
- package/dist/sub-agents.d.ts.map +0 -1
- package/dist/sub-agents.js.map +0 -1
- package/dist/tools/subagent.js.map +0 -1
- package/docs/proj-review.md +0 -188
- package/docs/test-supplementation-plan.md +0 -553
- /package/dist/{delivery.d.ts → runtime/delivery.d.ts} +0 -0
- /package/dist/{events.d.ts → runtime/events.d.ts} +0 -0
- /package/docs/{memory-rfc.md → specs/001-implement-memory/memory-rfc.md} +0 -0
- /package/docs/{subagent → specs/002-subagent}/pi-subagent-analyse.txt +0 -0
- /package/docs/{subagent → specs/002-subagent}/pi-subagent-design.txt +0 -0
- /package/docs/{subagent → specs/002-subagent}/pi-subagent-phase1-plan.txt +0 -0
- /package/docs/{improve-memory → specs/003-improve-memory}/design.md +0 -0
- /package/docs/{improve-memory → specs/003-improve-memory}/interfaces-and-tests.md +0 -0
- /package/docs/{improve-memory → specs/003-improve-memory}/spec.md +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/memory/files.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from \"fs\";\nimport { mkdir, readFile, rename, writeFile } from \"fs/promises\";\nimport { dirname, join } from \"path\";\n\nconst DEFAULT_CHANNEL_MEMORY = `# Channel Memory\n\nThis file stores durable channel-specific memory.\n\n- It is not preloaded into session context.\n- Read it on demand when prior decisions, preferences, or long-running work matter.\n- The runtime may append updates here during consolidation.\n\n## Durable Facts\n\n<!-- Stable facts, preferences, and ongoing commitments can accumulate here. -->\n`;\n\nconst DEFAULT_CHANNEL_HISTORY = `# Channel History\n\nThis file stores summarized older channel history.\n\n- It is not preloaded into session context.\n- Read it on demand when older context matters.\n- The runtime may append and fold history blocks here during consolidation.\n`;\n\nconst DEFAULT_CHANNEL_SESSION = `# Session Title\n\n<!-- A short title for the current active work in this channel. -->\n\n# Current State\n\n<!-- What is actively being worked on right now. -->\n\n# User Intent\n\n<!-- What the user is currently trying to achieve. -->\n\n# Active Files\n\n<!-- Important files or directories currently in focus. -->\n\n# Decisions\n\n<!-- Recent decisions that matter to the current work. -->\n\n# Constraints\n\n<!-- Current constraints, assumptions, or important guardrails. -->\n\n# Errors & Corrections\n\n<!-- Recent failures, corrections, and things to avoid repeating. -->\n\n# Next Steps\n\n<!-- Likely next actions if work resumes later. -->\n\n# Worklog\n\n<!-- Very terse notes about recent progress. -->\n`;\n\nexport interface MemoryUpdateBlock {\n\ttimestamp: string;\n\tentries: string[];\n}\n\nexport interface HistoryBlock {\n\ttimestamp: string;\n\tcontent: string;\n}\n\nfunction normalizeContent(content: string): string {\n\treturn content.trim().length > 0 ? `${content.trim()}\\n` : \"\";\n}\n\nasync function writeAtomically(path: string, content: string): Promise<void> {\n\tawait mkdir(dirname(path), { recursive: true });\n\tconst tempPath = `${path}.tmp`;\n\tawait writeFile(tempPath, content, \"utf-8\");\n\tawait rename(tempPath, path);\n}\n\nfunction ensureTrailingNewlines(content: string): string {\n\treturn content.trimEnd().length > 0 ? `${content.trimEnd()}\\n\\n` : \"\";\n}\n\nexport function getChannelMemoryPath(channelDir: string): string {\n\treturn join(channelDir, \"MEMORY.md\");\n}\n\nexport function getChannelHistoryPath(channelDir: string): string {\n\treturn join(channelDir, \"HISTORY.md\");\n}\n\nexport function getChannelSessionPath(channelDir: string): string {\n\treturn join(channelDir, \"SESSION.md\");\n}\n\nexport async function ensureChannelMemoryFiles(channelDir: string): Promise<void> {\n\tensureChannelMemoryFilesSync(channelDir);\n}\n\nexport function ensureChannelMemoryFilesSync(channelDir: string): void {\n\tconst memoryPath = getChannelMemoryPath(channelDir);\n\tconst historyPath = getChannelHistoryPath(channelDir);\n\tconst sessionPath = getChannelSessionPath(channelDir);\n\n\tmkdirSync(channelDir, { recursive: true });\n\n\tif (!existsSync(memoryPath)) {\n\t\twriteFileSync(memoryPath, DEFAULT_CHANNEL_MEMORY, \"utf-8\");\n\t}\n\tif (!existsSync(historyPath)) {\n\t\twriteFileSync(historyPath, DEFAULT_CHANNEL_HISTORY, \"utf-8\");\n\t}\n\tif (!existsSync(sessionPath)) {\n\t\twriteFileSync(sessionPath, DEFAULT_CHANNEL_SESSION, \"utf-8\");\n\t}\n}\n\nasync function readTextFile(path: string): Promise<string> {\n\ttry {\n\t\treturn await readFile(path, \"utf-8\");\n\t} catch (error: unknown) {\n\t\tif (isNodeError(error) && error.code === \"ENOENT\") {\n\t\t\treturn \"\";\n\t\t}\n\t\tthrow error;\n\t}\n}\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n\treturn error instanceof Error && \"code\" in error;\n}\n\nexport async function readChannelMemory(channelDir: string): Promise<string> {\n\treturn readTextFile(getChannelMemoryPath(channelDir));\n}\n\nexport async function readChannelHistory(channelDir: string): Promise<string> {\n\treturn readTextFile(getChannelHistoryPath(channelDir));\n}\n\nexport async function readChannelSession(channelDir: string): Promise<string> {\n\treturn readTextFile(getChannelSessionPath(channelDir));\n}\n\nexport async function rewriteChannelMemory(channelDir: string, content: string): Promise<void> {\n\tawait ensureChannelMemoryFiles(channelDir);\n\tconst nextContent = normalizeContent(content) || DEFAULT_CHANNEL_MEMORY;\n\tawait writeAtomically(getChannelMemoryPath(channelDir), nextContent);\n}\n\nexport async function rewriteChannelHistory(channelDir: string, content: string): Promise<void> {\n\tawait ensureChannelMemoryFiles(channelDir);\n\tconst nextContent = normalizeContent(content) || DEFAULT_CHANNEL_HISTORY;\n\tawait writeAtomically(getChannelHistoryPath(channelDir), nextContent);\n}\n\nexport async function rewriteChannelSession(channelDir: string, content: string): Promise<void> {\n\tawait ensureChannelMemoryFiles(channelDir);\n\tconst nextContent = normalizeContent(content) || DEFAULT_CHANNEL_SESSION;\n\tawait writeAtomically(getChannelSessionPath(channelDir), nextContent);\n}\n\nexport async function appendChannelMemoryUpdate(channelDir: string, block: MemoryUpdateBlock): Promise<void> {\n\tif (block.entries.length === 0) {\n\t\treturn;\n\t}\n\n\tawait ensureChannelMemoryFiles(channelDir);\n\tconst path = getChannelMemoryPath(channelDir);\n\tconst existing = await readTextFile(path);\n\tconst renderedBlock = [`## Update ${block.timestamp}`, ...block.entries.map((entry) => `- ${entry.trim()}`)].join(\n\t\t\"\\n\",\n\t);\n\tawait writeAtomically(path, `${ensureTrailingNewlines(existing)}${renderedBlock}\\n`);\n}\n\nexport async function appendChannelHistoryBlock(channelDir: string, block: HistoryBlock): Promise<void> {\n\tconst trimmedContent = block.content.trim();\n\tif (!trimmedContent) {\n\t\treturn;\n\t}\n\n\tawait ensureChannelMemoryFiles(channelDir);\n\tconst path = getChannelHistoryPath(channelDir);\n\tconst existing = await readTextFile(path);\n\tconst renderedBlock = [`## ${block.timestamp}`, trimmedContent].join(\"\\n\\n\");\n\tawait writeAtomically(path, `${ensureTrailingNewlines(existing)}${renderedBlock}\\n`);\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
|
2
2
|
import type { Api, Model } from "@mariozechner/pi-ai";
|
|
3
3
|
import type { ExtensionFactory, SessionEntry } from "@mariozechner/pi-coding-agent";
|
|
4
|
-
import type { PipiclawSessionMemorySettings } from "
|
|
5
|
-
export type ConsolidationReason = "compaction" | "new-session";
|
|
4
|
+
import type { PipiclawSessionMemorySettings } from "../context.js";
|
|
5
|
+
export type ConsolidationReason = "compaction" | "new-session" | "idle";
|
|
6
6
|
export interface MemoryLifecycleOptions {
|
|
7
7
|
channelId: string;
|
|
8
8
|
channelDir: string;
|
|
@@ -15,17 +15,35 @@ export interface MemoryLifecycleOptions {
|
|
|
15
15
|
export declare class MemoryLifecycle {
|
|
16
16
|
private options;
|
|
17
17
|
private backgroundQueue;
|
|
18
|
+
private sessionRefreshQueue;
|
|
18
19
|
private turnsSinceSessionUpdate;
|
|
19
20
|
private toolCallsSinceSessionUpdate;
|
|
20
|
-
private
|
|
21
|
+
private thresholdFailureBackoffTurnsRemaining;
|
|
22
|
+
private thresholdRefreshQueued;
|
|
23
|
+
private sessionRefreshRunning;
|
|
24
|
+
private durableDirty;
|
|
25
|
+
private durableRevision;
|
|
26
|
+
private lastAssistantTurnRevision;
|
|
27
|
+
private lastDurableConsolidationRevision;
|
|
28
|
+
private idleConsolidationTimer;
|
|
29
|
+
private idleConsolidationQueued;
|
|
21
30
|
constructor(options: MemoryLifecycleOptions);
|
|
22
31
|
private buildRunOptions;
|
|
23
32
|
createExtensionFactory(): ExtensionFactory;
|
|
33
|
+
noteUserTurnStarted(): void;
|
|
24
34
|
noteToolCall(): void;
|
|
25
35
|
noteCompletedAssistantTurn(): void;
|
|
36
|
+
private clearIdleConsolidationTimer;
|
|
37
|
+
private shouldForceRefreshFor;
|
|
26
38
|
private refreshSessionMemory;
|
|
27
|
-
private
|
|
28
|
-
private
|
|
39
|
+
private runSessionRefreshSerial;
|
|
40
|
+
private requestThresholdSessionRefresh;
|
|
41
|
+
private enqueueBackgroundJob;
|
|
42
|
+
private hasPendingAssistantSnapshot;
|
|
43
|
+
private markDurableConsolidationCheckpoint;
|
|
44
|
+
private logConsolidationResult;
|
|
45
|
+
private scheduleIdleConsolidation;
|
|
46
|
+
private runPreflightConsolidation;
|
|
29
47
|
private handleSessionBeforeCompact;
|
|
30
48
|
private handleSessionCompact;
|
|
31
49
|
private handleSessionBeforeSwitch;
|
|
@@ -33,4 +51,4 @@ export declare class MemoryLifecycle {
|
|
|
33
51
|
private enqueueBackgroundMaintenance;
|
|
34
52
|
private logBackgroundResult;
|
|
35
53
|
}
|
|
36
|
-
//# sourceMappingURL=
|
|
54
|
+
//# sourceMappingURL=lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/memory/lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EACX,gBAAgB,EAIhB,YAAY,EAEZ,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,eAAe,CAAC;AAanE,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,aAAa,GAAG,MAAM,CAAC;AAExE,MAAM,WAAW,sBAAsB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,YAAY,EAAE,CAAC;IAClC,iBAAiB,EAAE,MAAM,YAAY,EAAE,CAAC;IACxC,QAAQ,EAAE,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACtD,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;CAC9D;AAOD,qBAAa,eAAe;IAef,OAAO,CAAC,OAAO;IAd3B,OAAO,CAAC,eAAe,CAAoC;IAC3D,OAAO,CAAC,mBAAmB,CAAoC;IAC/D,OAAO,CAAC,uBAAuB,CAAK;IACpC,OAAO,CAAC,2BAA2B,CAAK;IACxC,OAAO,CAAC,qCAAqC,CAAK;IAClD,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,qBAAqB,CAAS;IACtC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,yBAAyB,CAAK;IACtC,OAAO,CAAC,gCAAgC,CAAK;IAC7C,OAAO,CAAC,sBAAsB,CAA8C;IAC5E,OAAO,CAAC,uBAAuB,CAAS;gBAEpB,OAAO,EAAE,sBAAsB;IAEnD,OAAO,CAAC,eAAe;IAUvB,sBAAsB,IAAI,gBAAgB;IAiB1C,mBAAmB,IAAI,IAAI;IAI3B,YAAY,IAAI,IAAI;IAOpB,0BAA0B,IAAI,IAAI;IAyBlC,OAAO,CAAC,2BAA2B;IAQnC,OAAO,CAAC,qBAAqB;YAUf,oBAAoB;IAiClC,OAAO,CAAC,uBAAuB;IAU/B,OAAO,CAAC,8BAA8B;IAWtC,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,2BAA2B;IAInC,OAAO,CAAC,kCAAkC;IAK1C,OAAO,CAAC,sBAAsB;IAW9B,OAAO,CAAC,yBAAyB;YAoCnB,yBAAyB;YA6BzB,0BAA0B;IAIxC,OAAO,CAAC,oBAAoB;YAId,yBAAyB;IAQvC,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,mBAAmB;CAW3B"}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import * as log from "../log.js";
|
|
2
|
+
import { runBackgroundMaintenance, runInlineConsolidation, } from "./consolidation.js";
|
|
3
|
+
import { updateChannelSessionMemory } from "./session.js";
|
|
4
|
+
const IDLE_CONSOLIDATION_DELAY_MS = 60_000;
|
|
5
|
+
export class MemoryLifecycle {
|
|
6
|
+
constructor(options) {
|
|
7
|
+
this.options = options;
|
|
8
|
+
this.backgroundQueue = Promise.resolve();
|
|
9
|
+
this.sessionRefreshQueue = Promise.resolve();
|
|
10
|
+
this.turnsSinceSessionUpdate = 0;
|
|
11
|
+
this.toolCallsSinceSessionUpdate = 0;
|
|
12
|
+
this.thresholdFailureBackoffTurnsRemaining = 0;
|
|
13
|
+
this.thresholdRefreshQueued = false;
|
|
14
|
+
this.sessionRefreshRunning = false;
|
|
15
|
+
this.durableDirty = false;
|
|
16
|
+
this.durableRevision = 0;
|
|
17
|
+
this.lastAssistantTurnRevision = 0;
|
|
18
|
+
this.lastDurableConsolidationRevision = 0;
|
|
19
|
+
this.idleConsolidationTimer = null;
|
|
20
|
+
this.idleConsolidationQueued = false;
|
|
21
|
+
}
|
|
22
|
+
buildRunOptions(messages, sessionEntries) {
|
|
23
|
+
return {
|
|
24
|
+
channelDir: this.options.channelDir,
|
|
25
|
+
model: this.options.getModel(),
|
|
26
|
+
resolveApiKey: this.options.resolveApiKey,
|
|
27
|
+
messages: messages ?? this.options.getMessages(),
|
|
28
|
+
sessionEntries: sessionEntries ?? this.options.getSessionEntries(),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
createExtensionFactory() {
|
|
32
|
+
return (pi) => {
|
|
33
|
+
pi.on("session_before_compact", async (event) => {
|
|
34
|
+
await this.handleSessionBeforeCompact(event);
|
|
35
|
+
});
|
|
36
|
+
pi.on("session_compact", async (event) => {
|
|
37
|
+
this.handleSessionCompact(event);
|
|
38
|
+
});
|
|
39
|
+
pi.on("session_before_switch", async (event) => {
|
|
40
|
+
await this.handleSessionBeforeSwitch(event);
|
|
41
|
+
});
|
|
42
|
+
pi.on("session_switch", async (event) => {
|
|
43
|
+
this.handleSessionSwitch(event);
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
noteUserTurnStarted() {
|
|
48
|
+
this.clearIdleConsolidationTimer();
|
|
49
|
+
}
|
|
50
|
+
noteToolCall() {
|
|
51
|
+
this.durableDirty = true;
|
|
52
|
+
this.durableRevision++;
|
|
53
|
+
this.toolCallsSinceSessionUpdate++;
|
|
54
|
+
this.clearIdleConsolidationTimer();
|
|
55
|
+
}
|
|
56
|
+
noteCompletedAssistantTurn() {
|
|
57
|
+
this.durableDirty = true;
|
|
58
|
+
this.durableRevision++;
|
|
59
|
+
this.lastAssistantTurnRevision = this.durableRevision;
|
|
60
|
+
const settings = this.options.getSessionMemorySettings();
|
|
61
|
+
if (settings.enabled) {
|
|
62
|
+
this.turnsSinceSessionUpdate++;
|
|
63
|
+
let canTriggerThresholdRefresh = true;
|
|
64
|
+
if (this.thresholdFailureBackoffTurnsRemaining > 0) {
|
|
65
|
+
this.thresholdFailureBackoffTurnsRemaining--;
|
|
66
|
+
canTriggerThresholdRefresh = this.thresholdFailureBackoffTurnsRemaining === 0;
|
|
67
|
+
}
|
|
68
|
+
if (canTriggerThresholdRefresh &&
|
|
69
|
+
(this.turnsSinceSessionUpdate >= settings.minTurnsBetweenUpdate ||
|
|
70
|
+
this.toolCallsSinceSessionUpdate >= settings.minToolCallsBetweenUpdate)) {
|
|
71
|
+
this.requestThresholdSessionRefresh();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
this.scheduleIdleConsolidation();
|
|
75
|
+
}
|
|
76
|
+
clearIdleConsolidationTimer() {
|
|
77
|
+
if (!this.idleConsolidationTimer) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
clearTimeout(this.idleConsolidationTimer);
|
|
81
|
+
this.idleConsolidationTimer = null;
|
|
82
|
+
}
|
|
83
|
+
shouldForceRefreshFor(reason, settings) {
|
|
84
|
+
if (!settings.enabled) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
return reason === "compaction" ? settings.forceRefreshBeforeCompact : settings.forceRefreshBeforeNewSession;
|
|
88
|
+
}
|
|
89
|
+
async refreshSessionMemory(request) {
|
|
90
|
+
const settings = this.options.getSessionMemorySettings();
|
|
91
|
+
if (!settings.enabled) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
const { reason } = request;
|
|
95
|
+
this.sessionRefreshRunning = true;
|
|
96
|
+
try {
|
|
97
|
+
await updateChannelSessionMemory({
|
|
98
|
+
channelDir: this.options.channelDir,
|
|
99
|
+
messages: request.messages ?? this.options.getMessages(),
|
|
100
|
+
model: this.options.getModel(),
|
|
101
|
+
resolveApiKey: this.options.resolveApiKey,
|
|
102
|
+
timeoutMs: settings.timeoutMs,
|
|
103
|
+
});
|
|
104
|
+
this.turnsSinceSessionUpdate = 0;
|
|
105
|
+
this.toolCallsSinceSessionUpdate = 0;
|
|
106
|
+
this.thresholdFailureBackoffTurnsRemaining = 0;
|
|
107
|
+
log.logInfo(`[${this.options.channelId}] Session memory updated (${reason})`);
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
112
|
+
if (reason === "threshold") {
|
|
113
|
+
this.thresholdFailureBackoffTurnsRemaining = Math.max(0, settings.failureBackoffTurns);
|
|
114
|
+
}
|
|
115
|
+
log.logWarning(`[${this.options.channelId}] Session memory update failed (${reason})`, message);
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
this.sessionRefreshRunning = false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
runSessionRefreshSerial(request) {
|
|
123
|
+
const run = async () => this.refreshSessionMemory(request);
|
|
124
|
+
const resultPromise = this.sessionRefreshQueue.then(run, run);
|
|
125
|
+
this.sessionRefreshQueue = resultPromise.then(() => undefined, () => undefined);
|
|
126
|
+
return resultPromise;
|
|
127
|
+
}
|
|
128
|
+
requestThresholdSessionRefresh() {
|
|
129
|
+
if (this.thresholdRefreshQueued || this.sessionRefreshRunning) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
this.thresholdRefreshQueued = true;
|
|
133
|
+
void this.runSessionRefreshSerial({ reason: "threshold" }).finally(() => {
|
|
134
|
+
this.thresholdRefreshQueued = false;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
enqueueBackgroundJob(job, failureMessage) {
|
|
138
|
+
this.backgroundQueue = this.backgroundQueue.then(job).catch((error) => {
|
|
139
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
140
|
+
log.logWarning(failureMessage, message);
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
hasPendingAssistantSnapshot() {
|
|
144
|
+
return this.durableDirty && this.lastAssistantTurnRevision > this.lastDurableConsolidationRevision;
|
|
145
|
+
}
|
|
146
|
+
markDurableConsolidationCheckpoint(revision) {
|
|
147
|
+
this.lastDurableConsolidationRevision = Math.max(this.lastDurableConsolidationRevision, revision);
|
|
148
|
+
this.durableDirty = this.durableRevision > this.lastDurableConsolidationRevision;
|
|
149
|
+
}
|
|
150
|
+
logConsolidationResult(reason, result) {
|
|
151
|
+
if (result.skipped) {
|
|
152
|
+
log.logInfo(`[${this.options.channelId}] Memory consolidation skipped (${reason}): no meaningful snapshot`);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
log.logInfo(`[${this.options.channelId}] Memory consolidation finished (${reason}): memory entries=${result.appendedMemoryEntries}, history=${result.appendedHistoryBlock ? "yes" : "no"}`);
|
|
156
|
+
}
|
|
157
|
+
scheduleIdleConsolidation() {
|
|
158
|
+
this.clearIdleConsolidationTimer();
|
|
159
|
+
if (!this.hasPendingAssistantSnapshot() || this.idleConsolidationQueued) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
this.idleConsolidationTimer = setTimeout(() => {
|
|
163
|
+
this.idleConsolidationTimer = null;
|
|
164
|
+
if (!this.hasPendingAssistantSnapshot() || this.idleConsolidationQueued) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
this.idleConsolidationQueued = true;
|
|
168
|
+
const messageSnapshot = [...this.options.getMessages()];
|
|
169
|
+
const sessionEntrySnapshot = [...this.options.getSessionEntries()];
|
|
170
|
+
const revisionSnapshot = this.durableRevision;
|
|
171
|
+
this.enqueueBackgroundJob(async () => {
|
|
172
|
+
try {
|
|
173
|
+
log.logInfo(`[${this.options.channelId}] Memory consolidation starting (idle)`);
|
|
174
|
+
const result = await runInlineConsolidation(this.buildRunOptions(messageSnapshot, sessionEntrySnapshot));
|
|
175
|
+
this.markDurableConsolidationCheckpoint(revisionSnapshot);
|
|
176
|
+
this.logConsolidationResult("idle", result);
|
|
177
|
+
const maintenance = await runBackgroundMaintenance(this.buildRunOptions(messageSnapshot, sessionEntrySnapshot));
|
|
178
|
+
this.logBackgroundResult(maintenance);
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
this.idleConsolidationQueued = false;
|
|
182
|
+
if (this.durableDirty) {
|
|
183
|
+
this.scheduleIdleConsolidation();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}, `[${this.options.channelId}] Memory consolidation failed (idle)`);
|
|
187
|
+
}, IDLE_CONSOLIDATION_DELAY_MS);
|
|
188
|
+
}
|
|
189
|
+
async runPreflightConsolidation(reason, messages, sessionEntries) {
|
|
190
|
+
this.clearIdleConsolidationTimer();
|
|
191
|
+
const messageSnapshot = [...(messages ?? this.options.getMessages())];
|
|
192
|
+
const sessionEntrySnapshot = sessionEntries ? [...sessionEntries] : [...this.options.getSessionEntries()];
|
|
193
|
+
const revisionSnapshot = this.durableRevision;
|
|
194
|
+
const settings = this.options.getSessionMemorySettings();
|
|
195
|
+
if (this.shouldForceRefreshFor(reason, settings)) {
|
|
196
|
+
await this.runSessionRefreshSerial({
|
|
197
|
+
reason,
|
|
198
|
+
messages: messageSnapshot,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
try {
|
|
202
|
+
log.logInfo(`[${this.options.channelId}] Memory consolidation starting (${reason})`);
|
|
203
|
+
const result = await runInlineConsolidation(this.buildRunOptions(messageSnapshot, sessionEntrySnapshot));
|
|
204
|
+
this.markDurableConsolidationCheckpoint(revisionSnapshot);
|
|
205
|
+
this.logConsolidationResult(reason, result);
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
209
|
+
log.logWarning(`[${this.options.channelId}] Memory consolidation failed (${reason})`, message);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
async handleSessionBeforeCompact(event) {
|
|
213
|
+
await this.runPreflightConsolidation("compaction", event.preparation.messagesToSummarize);
|
|
214
|
+
}
|
|
215
|
+
handleSessionCompact(_event) {
|
|
216
|
+
this.enqueueBackgroundMaintenance();
|
|
217
|
+
}
|
|
218
|
+
async handleSessionBeforeSwitch(event) {
|
|
219
|
+
if (event.reason !== "new") {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
await this.runPreflightConsolidation("new-session");
|
|
223
|
+
}
|
|
224
|
+
handleSessionSwitch(event) {
|
|
225
|
+
if (event.reason !== "new") {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
this.enqueueBackgroundMaintenance();
|
|
229
|
+
}
|
|
230
|
+
enqueueBackgroundMaintenance() {
|
|
231
|
+
this.enqueueBackgroundJob(async () => {
|
|
232
|
+
const result = await runBackgroundMaintenance(this.buildRunOptions([], []));
|
|
233
|
+
this.logBackgroundResult(result);
|
|
234
|
+
}, `[${this.options.channelId}] Background memory maintenance failed`);
|
|
235
|
+
}
|
|
236
|
+
logBackgroundResult(result) {
|
|
237
|
+
if (!result.cleanedMemory && !result.foldedHistory) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const details = [
|
|
241
|
+
`memory cleanup=${result.cleanedMemory ? "yes" : "no"}`,
|
|
242
|
+
`history fold=${result.foldedHistory ? "yes" : "no"}`,
|
|
243
|
+
].join(", ");
|
|
244
|
+
log.logInfo(`[${this.options.channelId}] Background memory maintenance complete: ${details}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/memory/lifecycle.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@mariozechner/pi-agent-core\";\nimport type { Api, Model } from \"@mariozechner/pi-ai\";\nimport type {\n\tExtensionFactory,\n\tSessionBeforeCompactEvent,\n\tSessionBeforeSwitchEvent,\n\tSessionCompactEvent,\n\tSessionEntry,\n\tSessionSwitchEvent,\n} from \"@mariozechner/pi-coding-agent\";\nimport type { PipiclawSessionMemorySettings } from \"../context.js\";\nimport * as log from \"../log.js\";\nimport {\n\ttype BackgroundMaintenanceResult,\n\ttype ConsolidationRunOptions,\n\ttype InlineConsolidationResult,\n\trunBackgroundMaintenance,\n\trunInlineConsolidation,\n} from \"./consolidation.js\";\nimport { updateChannelSessionMemory } from \"./session.js\";\n\nconst IDLE_CONSOLIDATION_DELAY_MS = 60_000;\n\nexport type ConsolidationReason = \"compaction\" | \"new-session\" | \"idle\";\n\nexport interface MemoryLifecycleOptions {\n\tchannelId: string;\n\tchannelDir: string;\n\tgetMessages: () => AgentMessage[];\n\tgetSessionEntries: () => SessionEntry[];\n\tgetModel: () => Model<Api>;\n\tresolveApiKey: (model: Model<Api>) => Promise<string>;\n\tgetSessionMemorySettings: () => PipiclawSessionMemorySettings;\n}\n\ninterface SessionMemoryRefreshRequest {\n\treason: \"threshold\" | Exclude<ConsolidationReason, \"idle\">;\n\tmessages?: AgentMessage[];\n}\n\nexport class MemoryLifecycle {\n\tprivate backgroundQueue: Promise<void> = Promise.resolve();\n\tprivate sessionRefreshQueue: Promise<void> = Promise.resolve();\n\tprivate turnsSinceSessionUpdate = 0;\n\tprivate toolCallsSinceSessionUpdate = 0;\n\tprivate thresholdFailureBackoffTurnsRemaining = 0;\n\tprivate thresholdRefreshQueued = false;\n\tprivate sessionRefreshRunning = false;\n\tprivate durableDirty = false;\n\tprivate durableRevision = 0;\n\tprivate lastAssistantTurnRevision = 0;\n\tprivate lastDurableConsolidationRevision = 0;\n\tprivate idleConsolidationTimer: ReturnType<typeof setTimeout> | null = null;\n\tprivate idleConsolidationQueued = false;\n\n\tconstructor(private options: MemoryLifecycleOptions) {}\n\n\tprivate buildRunOptions(messages?: AgentMessage[], sessionEntries?: SessionEntry[]): ConsolidationRunOptions {\n\t\treturn {\n\t\t\tchannelDir: this.options.channelDir,\n\t\t\tmodel: this.options.getModel(),\n\t\t\tresolveApiKey: this.options.resolveApiKey,\n\t\t\tmessages: messages ?? this.options.getMessages(),\n\t\t\tsessionEntries: sessionEntries ?? this.options.getSessionEntries(),\n\t\t};\n\t}\n\n\tcreateExtensionFactory(): ExtensionFactory {\n\t\treturn (pi) => {\n\t\t\tpi.on(\"session_before_compact\", async (event: SessionBeforeCompactEvent) => {\n\t\t\t\tawait this.handleSessionBeforeCompact(event);\n\t\t\t});\n\t\t\tpi.on(\"session_compact\", async (event: SessionCompactEvent) => {\n\t\t\t\tthis.handleSessionCompact(event);\n\t\t\t});\n\t\t\tpi.on(\"session_before_switch\", async (event: SessionBeforeSwitchEvent) => {\n\t\t\t\tawait this.handleSessionBeforeSwitch(event);\n\t\t\t});\n\t\t\tpi.on(\"session_switch\", async (event: SessionSwitchEvent) => {\n\t\t\t\tthis.handleSessionSwitch(event);\n\t\t\t});\n\t\t};\n\t}\n\n\tnoteUserTurnStarted(): void {\n\t\tthis.clearIdleConsolidationTimer();\n\t}\n\n\tnoteToolCall(): void {\n\t\tthis.durableDirty = true;\n\t\tthis.durableRevision++;\n\t\tthis.toolCallsSinceSessionUpdate++;\n\t\tthis.clearIdleConsolidationTimer();\n\t}\n\n\tnoteCompletedAssistantTurn(): void {\n\t\tthis.durableDirty = true;\n\t\tthis.durableRevision++;\n\t\tthis.lastAssistantTurnRevision = this.durableRevision;\n\n\t\tconst settings = this.options.getSessionMemorySettings();\n\t\tif (settings.enabled) {\n\t\t\tthis.turnsSinceSessionUpdate++;\n\t\t\tlet canTriggerThresholdRefresh = true;\n\t\t\tif (this.thresholdFailureBackoffTurnsRemaining > 0) {\n\t\t\t\tthis.thresholdFailureBackoffTurnsRemaining--;\n\t\t\t\tcanTriggerThresholdRefresh = this.thresholdFailureBackoffTurnsRemaining === 0;\n\t\t\t}\n\t\t\tif (\n\t\t\t\tcanTriggerThresholdRefresh &&\n\t\t\t\t(this.turnsSinceSessionUpdate >= settings.minTurnsBetweenUpdate ||\n\t\t\t\t\tthis.toolCallsSinceSessionUpdate >= settings.minToolCallsBetweenUpdate)\n\t\t\t) {\n\t\t\t\tthis.requestThresholdSessionRefresh();\n\t\t\t}\n\t\t}\n\n\t\tthis.scheduleIdleConsolidation();\n\t}\n\n\tprivate clearIdleConsolidationTimer(): void {\n\t\tif (!this.idleConsolidationTimer) {\n\t\t\treturn;\n\t\t}\n\t\tclearTimeout(this.idleConsolidationTimer);\n\t\tthis.idleConsolidationTimer = null;\n\t}\n\n\tprivate shouldForceRefreshFor(\n\t\treason: Exclude<ConsolidationReason, \"idle\">,\n\t\tsettings: PipiclawSessionMemorySettings,\n\t): boolean {\n\t\tif (!settings.enabled) {\n\t\t\treturn false;\n\t\t}\n\t\treturn reason === \"compaction\" ? settings.forceRefreshBeforeCompact : settings.forceRefreshBeforeNewSession;\n\t}\n\n\tprivate async refreshSessionMemory(request: SessionMemoryRefreshRequest): Promise<boolean> {\n\t\tconst settings = this.options.getSessionMemorySettings();\n\t\tif (!settings.enabled) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst { reason } = request;\n\t\tthis.sessionRefreshRunning = true;\n\t\ttry {\n\t\t\tawait updateChannelSessionMemory({\n\t\t\t\tchannelDir: this.options.channelDir,\n\t\t\t\tmessages: request.messages ?? this.options.getMessages(),\n\t\t\t\tmodel: this.options.getModel(),\n\t\t\t\tresolveApiKey: this.options.resolveApiKey,\n\t\t\t\ttimeoutMs: settings.timeoutMs,\n\t\t\t});\n\t\t\tthis.turnsSinceSessionUpdate = 0;\n\t\t\tthis.toolCallsSinceSessionUpdate = 0;\n\t\t\tthis.thresholdFailureBackoffTurnsRemaining = 0;\n\t\t\tlog.logInfo(`[${this.options.channelId}] Session memory updated (${reason})`);\n\t\t\treturn true;\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tif (reason === \"threshold\") {\n\t\t\t\tthis.thresholdFailureBackoffTurnsRemaining = Math.max(0, settings.failureBackoffTurns);\n\t\t\t}\n\t\t\tlog.logWarning(`[${this.options.channelId}] Session memory update failed (${reason})`, message);\n\t\t\treturn false;\n\t\t} finally {\n\t\t\tthis.sessionRefreshRunning = false;\n\t\t}\n\t}\n\n\tprivate runSessionRefreshSerial(request: SessionMemoryRefreshRequest): Promise<boolean> {\n\t\tconst run = async (): Promise<boolean> => this.refreshSessionMemory(request);\n\t\tconst resultPromise = this.sessionRefreshQueue.then(run, run);\n\t\tthis.sessionRefreshQueue = resultPromise.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\treturn resultPromise;\n\t}\n\n\tprivate requestThresholdSessionRefresh(): void {\n\t\tif (this.thresholdRefreshQueued || this.sessionRefreshRunning) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.thresholdRefreshQueued = true;\n\t\tvoid this.runSessionRefreshSerial({ reason: \"threshold\" }).finally(() => {\n\t\t\tthis.thresholdRefreshQueued = false;\n\t\t});\n\t}\n\n\tprivate enqueueBackgroundJob(job: () => Promise<void>, failureMessage: string): void {\n\t\tthis.backgroundQueue = this.backgroundQueue.then(job).catch((error: unknown) => {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tlog.logWarning(failureMessage, message);\n\t\t});\n\t}\n\n\tprivate hasPendingAssistantSnapshot(): boolean {\n\t\treturn this.durableDirty && this.lastAssistantTurnRevision > this.lastDurableConsolidationRevision;\n\t}\n\n\tprivate markDurableConsolidationCheckpoint(revision: number): void {\n\t\tthis.lastDurableConsolidationRevision = Math.max(this.lastDurableConsolidationRevision, revision);\n\t\tthis.durableDirty = this.durableRevision > this.lastDurableConsolidationRevision;\n\t}\n\n\tprivate logConsolidationResult(reason: ConsolidationReason, result: InlineConsolidationResult): void {\n\t\tif (result.skipped) {\n\t\t\tlog.logInfo(`[${this.options.channelId}] Memory consolidation skipped (${reason}): no meaningful snapshot`);\n\t\t\treturn;\n\t\t}\n\n\t\tlog.logInfo(\n\t\t\t`[${this.options.channelId}] Memory consolidation finished (${reason}): memory entries=${result.appendedMemoryEntries}, history=${result.appendedHistoryBlock ? \"yes\" : \"no\"}`,\n\t\t);\n\t}\n\n\tprivate scheduleIdleConsolidation(): void {\n\t\tthis.clearIdleConsolidationTimer();\n\t\tif (!this.hasPendingAssistantSnapshot() || this.idleConsolidationQueued) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.idleConsolidationTimer = setTimeout(() => {\n\t\t\tthis.idleConsolidationTimer = null;\n\t\t\tif (!this.hasPendingAssistantSnapshot() || this.idleConsolidationQueued) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.idleConsolidationQueued = true;\n\t\t\tconst messageSnapshot = [...this.options.getMessages()];\n\t\t\tconst sessionEntrySnapshot = [...this.options.getSessionEntries()];\n\t\t\tconst revisionSnapshot = this.durableRevision;\n\t\t\tthis.enqueueBackgroundJob(async () => {\n\t\t\t\ttry {\n\t\t\t\t\tlog.logInfo(`[${this.options.channelId}] Memory consolidation starting (idle)`);\n\t\t\t\t\tconst result = await runInlineConsolidation(this.buildRunOptions(messageSnapshot, sessionEntrySnapshot));\n\t\t\t\t\tthis.markDurableConsolidationCheckpoint(revisionSnapshot);\n\t\t\t\t\tthis.logConsolidationResult(\"idle\", result);\n\t\t\t\t\tconst maintenance = await runBackgroundMaintenance(\n\t\t\t\t\t\tthis.buildRunOptions(messageSnapshot, sessionEntrySnapshot),\n\t\t\t\t\t);\n\t\t\t\t\tthis.logBackgroundResult(maintenance);\n\t\t\t\t} finally {\n\t\t\t\t\tthis.idleConsolidationQueued = false;\n\t\t\t\t\tif (this.durableDirty) {\n\t\t\t\t\t\tthis.scheduleIdleConsolidation();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, `[${this.options.channelId}] Memory consolidation failed (idle)`);\n\t\t}, IDLE_CONSOLIDATION_DELAY_MS);\n\t}\n\n\tprivate async runPreflightConsolidation(\n\t\treason: Exclude<ConsolidationReason, \"idle\">,\n\t\tmessages?: AgentMessage[],\n\t\tsessionEntries?: SessionEntry[],\n\t): Promise<void> {\n\t\tthis.clearIdleConsolidationTimer();\n\t\tconst messageSnapshot = [...(messages ?? this.options.getMessages())];\n\t\tconst sessionEntrySnapshot = sessionEntries ? [...sessionEntries] : [...this.options.getSessionEntries()];\n\t\tconst revisionSnapshot = this.durableRevision;\n\t\tconst settings = this.options.getSessionMemorySettings();\n\n\t\tif (this.shouldForceRefreshFor(reason, settings)) {\n\t\t\tawait this.runSessionRefreshSerial({\n\t\t\t\treason,\n\t\t\t\tmessages: messageSnapshot,\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tlog.logInfo(`[${this.options.channelId}] Memory consolidation starting (${reason})`);\n\t\t\tconst result = await runInlineConsolidation(this.buildRunOptions(messageSnapshot, sessionEntrySnapshot));\n\t\t\tthis.markDurableConsolidationCheckpoint(revisionSnapshot);\n\t\t\tthis.logConsolidationResult(reason, result);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tlog.logWarning(`[${this.options.channelId}] Memory consolidation failed (${reason})`, message);\n\t\t}\n\t}\n\n\tprivate async handleSessionBeforeCompact(event: SessionBeforeCompactEvent): Promise<void> {\n\t\tawait this.runPreflightConsolidation(\"compaction\", event.preparation.messagesToSummarize);\n\t}\n\n\tprivate handleSessionCompact(_event: SessionCompactEvent): void {\n\t\tthis.enqueueBackgroundMaintenance();\n\t}\n\n\tprivate async handleSessionBeforeSwitch(event: SessionBeforeSwitchEvent): Promise<void> {\n\t\tif (event.reason !== \"new\") {\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.runPreflightConsolidation(\"new-session\");\n\t}\n\n\tprivate handleSessionSwitch(event: SessionSwitchEvent): void {\n\t\tif (event.reason !== \"new\") {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.enqueueBackgroundMaintenance();\n\t}\n\n\tprivate enqueueBackgroundMaintenance(): void {\n\t\tthis.enqueueBackgroundJob(async () => {\n\t\t\tconst result = await runBackgroundMaintenance(this.buildRunOptions([], []));\n\t\t\tthis.logBackgroundResult(result);\n\t\t}, `[${this.options.channelId}] Background memory maintenance failed`);\n\t}\n\n\tprivate logBackgroundResult(result: BackgroundMaintenanceResult): void {\n\t\tif (!result.cleanedMemory && !result.foldedHistory) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst details = [\n\t\t\t`memory cleanup=${result.cleanedMemory ? \"yes\" : \"no\"}`,\n\t\t\t`history fold=${result.foldedHistory ? \"yes\" : \"no\"}`,\n\t\t].join(\", \");\n\t\tlog.logInfo(`[${this.options.channelId}] Background memory maintenance complete: ${details}`);\n\t}\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Api, Model } from "@mariozechner/pi-ai";
|
|
2
|
-
import { type MemoryCandidate, type MemoryCandidateCache } from "./
|
|
2
|
+
import { type MemoryCandidate, type MemoryCandidateCache } from "./candidates.js";
|
|
3
3
|
export interface RecallRequest {
|
|
4
4
|
query: string;
|
|
5
5
|
workspaceDir: string;
|
|
@@ -26,4 +26,4 @@ export interface RecallResult {
|
|
|
26
26
|
renderedText: string;
|
|
27
27
|
}
|
|
28
28
|
export declare function recallRelevantMemory(request: RecallRequest): Promise<RecallResult>;
|
|
29
|
-
//# sourceMappingURL=
|
|
29
|
+
//# sourceMappingURL=recall.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recall.d.ts","sourceRoot":"","sources":["../../src/memory/recall.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAItD,OAAO,EAAyB,KAAK,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAGzG,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC7C,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACtD,cAAc,CAAC,EAAE,oBAAoB,CAAC;CACtC;AAED,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACrB;AA0cD,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CA8CxF"}
|